Hóng các thánh rồ FP code lại và SO SÁNH CỤ THỂ CHỔ NÀO FP LẠI ƯU VIỆT HƠN OOP cho đề bài trên.
fp - immutable cơ bản là tốt, nhưng performance sẽ ko đc ngon, phải làm bạn với memoize để tăng performance.Không liên quan lắm, tôi chưa code FP bao giờ, nhưng ko phủ nhận tư duy immutable rất hay, đang cố gắng áp dụng tư duy đó cho 1 phần nhỏ dự án của tôi. Nhưng cho hỏi anh em FP làm việc với các external resource như socket hay file ổn không nhỉ, performance, async các kiểu ấy?
bài này code chỉ 10 phút nhưng câu này có mà cãi nhau tới năm sau chưa xong Tư duy của FP nó khác OOP, nên ko thể so đc cái nào ưu việt hơn.
fp - immutable cơ bản là tốt, nhưng performance sẽ ko đc ngon, phải làm bạn với memoize để tăng performance.
Thím hường kiếm đâu đc cái hình chất quáĐó là thím nghĩ như này:
View attachment 229295
Nhưng các anh rồ FP lại nghĩ như này cơ:
View attachment 229296
Vừa tìm hiểu hóa ra C# cũng code FP được, đỡ phải làm quen ngôn ngữ mới. Có điều chuyển sang FP đúng tốn bộ nhớ, test thấy sơ sơ Memory x3 so với OOP, 1 phần có thể là do thói quen dùng variable thoải mái cho là chẳng tốn bao nhiêu nhưng giờ mọi thứ đã là immutable. Để lúc nào có thời gian tập code lại mọi thứ = FP xem thế nào, hy vọng cuối tuần. Ước gì mình trẻ lại 10 tuổi khi chưa có gia đình, thèm code quá mà con thì vẫn còn ốm.
Ưu việt hơn nó noi hết trong định nghĩa cả 2 rồi , tôi nói rồi code để show cách viết cách reuse thôi , lì vlĐề bài:
Tạo hệ thống hiển thị thông tin cho nhiều loại khách hàng. Hiện tại có 2 loại: Customer (Name, Age), VipCustomer(Name, Age, VipPoints) thỏa các yêu cầu sau:
OOP Implementation
- Giả sử phần core hiển thị thông tin Customer là vô cùng phức tạp, ví dụ có tương tác phần cứng, thiết bị đặc biệt. Việc cập nhật, deploy lại sẽ dẫn tới dừng hoạt động kinh doanh. Tóm lại phần này hạn chế, trong đề bài này xem như fixed không được thay đổi. Hoạt động phức tạp đó là in ra các dấu "##############".
- Hệ thống này cho phép bên thứ 3 custom cách hiển thị cho từng loại khách hàng thêm vào cái "hoạt động phức tạp" ở mục 1. Cụ thể là sau khi in thông tin sẽ in "$$$$$$$$$$$" đối với loại Customer, in "@@@@@@@" với loại VipCustomer.
- Các loại khách hàng có thể phát sinh không giới hạn theo thời gian. Cụ thể sau khi deploy rồi thì có phát sinh InternalCustomer(Name, Age, Deparment) cũng cần được hiển thị thông tin như trong phần core và phần custom là in "&&&&&&&&&&&&"
Module 1: CustomerVisualizer.dll: đây là phần core sẽ không được thay đổi, có cho phép bên thứ 3 custom cách hiển thị bằng cách public interface IPrintable với method CustomPrint()
C#:using System; namespace CustomerVisualizer { public interface IPrintable { void CustomPrint(); } public class CustomerVisualizer { public void Print(IPrintable printable) { Console.WriteLine("\n#######################################################"); printable.CustomPrint(); } } }
Module 2: CustomerInfoManager.dll: module này chứa thông tin các loại khách hàng và quy định phần hiển thị custom. Module này được cập nhật khi có thêm loại khách hàng mới:
C#:using CustomerVisualizer; using System; using System.Collections.Generic; namespace CustomerInfoManager { /// <summary> /// Base class implement IPrintable để giao tiếp với CustomerVisualizer /// </summary> public class Customer : IPrintable { public string Name { get; set; } public int Age { get; set; } /// <summary> /// Custom print được sử dụng trong CustomerVisualizer /// </summary> public void CustomPrint() { // Process basic info Console.WriteLine($"{nameof(this.Name)} = {this.Name}"); Console.WriteLine($"{nameof(this.Age)} = {this.Age}"); // Process other info this.PrintOtherInfo(); } protected virtual void PrintOtherInfo() { Console.WriteLine("$$$$$$$$$$$$$$$$$$$$$$$"); } } public class VipCustomer : Customer { public int VipPoints { get; set; } protected override void PrintOtherInfo() { Console.WriteLine($"{nameof(this.VipPoints)} = {this.VipPoints}"); Console.WriteLine("@@@@@@@@@@@@@@@@@@@@@@@"); } } public class InternalCustomer : Customer { public string Department { get; set; } protected override void PrintOtherInfo() { Console.WriteLine($"{nameof(this.Department)} = {this.Department}"); Console.WriteLine("&&&&&&&&&&&&&&&&&&&&&&&"); } } public class CustomerRepo { /// <summary> /// Giả lập lấy data để test /// </summary> public static IList<Customer> GetCustomers() { IList<Customer> customers = new List<Customer> { new Customer { Name = "John Smith", Age = 20 }, new VipCustomer { Name = "Tim Batte", Age = 30, VipPoints = 100 }, new InternalCustomer { Name = "Jenny Lars", Age = 40, Department = "IT" } }; return customers; } } }
Program: CustomerManagement.exe: cái này là entry point, chứa hàm main để chạy thoy:
C#:using CustomerInfoManager; using System.Collections.Generic; namespace CustomerManagement { class Program { static void Main(string[] args) { IList<CustomerInfoManager.Customer> customers = CustomerRepo.GetCustomers(); CustomerVisualizer.CustomerVisualizer visualizer = new CustomerVisualizer.CustomerVisualizer(); foreach (CustomerInfoManager.Customer customer in customers) { visualizer.Print(customer); } } } }
Tự nhận xét:
Dùng OOP có interface nên có thể public IPrintable.CustomPrint() cho bất kỳ ai muốn custom khi sử dụng CustomerVisualizer.dll. Đây là khả năng mở rộng.
Customer.CustomPrint() in basic info là Name, Age của tất cả các loại khách hàng. Cho dù có 10 loại thì cũng không phải lặp lại 10 lần và đặc biệt là cũng không cần phải gọi lại 10 chổ (do tính kế thừa).
Chương trình có 3 modules, mổi khi thêm loại khách hàng chỉ 1 CustomerInfoManager.dll là phải deploy lại:
CustomerVisualizer.dll - (fixed)
CustomerInfoManager.dll - (updated)
CustomerManagement.exe - (fixed)
Polymorphism hiện rõ cùng là in thông tin nhưng cách custom khác nhau tùy vào loại customer:
Hóng các thánh rồ FP code lại và SO SÁNH CỤ THỂ CHỔ NÀO FP LẠI ƯU VIỆT HƠN OOP cho đề bài trên.
cái cục dll đó nó chỉ xài dc cho project nhà anh thôi, quăng cái dll đó vào project nào chạy cũng dc nhu các package trong fp đi mới có cái mà so sánh ,
Tôi thấy ông thiếu kiến thức quá, thiếu kiến thức thì đừng tranh luận. DLL -> dynamic link library ngay cái tên của nó đã nói lên nhiều điều rồi.Ưu việt hơn nó noi hết trong định nghĩa cả 2 rồi , tôi nói rồi code để show cách viết cách reuse thôi , lì vl
Thất bại điển hình nhất là thằng angular , oop tù quá thay đổi éo nổi viết lại cả cái framework từ đầu :]] , angular cũ éo merge lên bản mới dc làm con dân dỗi chuyển hết qua nền tảng khác , kế thừa, đa hình , bao đóng mạnh mẽ là thế đấy,
còn interface là khái niệm chung của lập trình rồi đừng lôi nó như đặc sản của oop vậy , cái cục dll đó nó chỉ xài dc cho project nhà anh thôi, quăng cái dll đó vào project nào chạy cũng dc nhu các package trong fp đi mới có cái mà so sánh ,
Câu này sai. Nói câu này ra thì tôi biết trình anh cỡ nào rồi.
À trước khi bật lại thì anh tìm hiểu kỹ rồi hay reply nhé.
Nhiều khi tranh luận để biết có cái sai thôi , thế anh giải thích xem dll sinh ra để làm gì , để các anh tự hàoTôi thấy ông thiếu kiến thức quá, thiếu kiến thức thì đừng tranh luận. DLL -> dynamic link library ngay cái tên của nó đã nói lên nhiều điều rồi.
ừ thì nó liên quan gì đâu. Nhiều cái nó đơn giản quá, google phát là ra mà thanh niên trên không thèm google luônĐã gọi là file DLL thì còn bàn cái gì OOP với chả FP trời
tôi hiểu sai dòng nào chỉ hộ để cảm ơn cái
cái cục dll đó nó chỉ xài dc cho project nhà anh thôi.
pub trait Visualization {
fn special_print(&self) {
println!("##############")
}
fn customized_print(&self) -> ();
fn print(&self) -> () {
self.special_print();
self.customized_print();
}
}
}
use crate::visualizer::Visualization;
#[derive(Debug)]
pub struct BasicInfo {
pub name: String,
pub age: u8,
}
impl BasicInfo {
fn print_info(&self) {
println!("Name = {}", self.name);
println!("Age = {}", self.age);
}
}
#[derive(Debug)]
pub struct BasicCustomer {
pub info: BasicInfo,
}
impl Visualization for BasicCustomer {
fn customized_print(&self) -> () {
self.info.print_info();
println!("$$$$$$$");
}
}
#[derive(Debug)]
pub struct VipCustomer {
pub info: BasicInfo,
pub vip_point: u8,
}
impl Visualization for VipCustomer {
fn customized_print(&self) -> () {
self.info.print_info();
println!("@@@@@@@");
}
}
#[derive(Debug)]
pub struct InternalCustomer {
pub info: BasicInfo,
pub department: String,
}
impl Visualization for InternalCustomer {
fn customized_print(&self) -> () {
self.info.print_info();
println!("&&&&&&&");
}
}
pub fn get_list_customer() -> Vec<Box<dyn Visualization>> {
let basic = BasicCustomer {
info: BasicInfo {
name: "John Smith".into(),
age: 20,
},
};
let vip = VipCustomer {
info: BasicInfo {
name: "Tim Batte".into(),
age: 30,
},
vip_point: 100,
};
let internal = InternalCustomer {
info: BasicInfo {
name: "Jenny Lars".into(),
age: 40,
},
department: "IT".into(),
};
vec![Box::new(basic), Box::new(vip), Box::new(internal)]
}
mod customer;
mod visualizer;
fn main() {
let list = customer::get_list_customer();
list.into_iter().for_each(|c| c.print())
}
##############
Name = John Smith
Age = 20
$$$$$$$
##############
Name = Tim Batte
Age = 30
@@@@@@@
##############
Name = Jenny Lars
Age = 40
&&&&&&&
self.customized_print();
có tính là functional ko bác :vcustomer.printOtherInfo
cũng được nhưng mình ... ko thích làm, làm demo cho mọi người coi thôi. Ai tò mò muốn biết fp thế nào thì cứ lập thread hỏi, mình biết gì thì hỗ trợ náy chứ cũng ko máu hơn thua, vì làm cho tới nơi thì mất công mà mình lại lười.Nay rảnh đc xíu code Rust trước cho bà con xem và bình phẩm trước, chỗ tôi hiện chỉ có 3G nên chưa tải GHC về đc, Haskell hẹn một hôm ko xa.
1. visualizer.rs
Code:pub trait Visualization { fn special_print(&self) { println!("##############") } }
2. customer.rs
Code:use crate::visualizer::Visualization; use core::fmt::Debug; pub trait Printable where Self: Visualization + Debug, { fn customized_print(&self) -> (); fn print(&self) -> () { self.special_print(); println!("{:?}", self); self.customized_print(); } } #[derive(Debug)] pub struct BasicInfo { pub name: String, pub age: u8, } #[derive(Debug)] pub struct BasicCustomer { pub info: BasicInfo, } impl Visualization for BasicCustomer {} impl Printable for BasicCustomer { fn customized_print(&self) -> () { println!("$$$$$$$"); } } #[derive(Debug)] pub struct VipCustomer { pub info: BasicInfo, pub vip_point: u8, } impl Visualization for VipCustomer {} impl Printable for VipCustomer { fn customized_print(&self) -> () { println!("@@@@@@@"); } } #[derive(Debug)] pub struct InternalCustomer { pub info: BasicInfo, pub department: String, } impl Visualization for InternalCustomer {} impl Printable for InternalCustomer { fn customized_print(&self) -> () { println!("&&&&&&&"); } } pub fn get_list_customer() -> Vec<Box<dyn Printable>> { let basic = BasicCustomer { info: BasicInfo { name: "John Smith".into(), age: 20, }, }; let vip = VipCustomer { info: BasicInfo { name: "Tim Batte".into(), age: 30, }, vip_point: 100, }; let internal = InternalCustomer { info: BasicInfo { name: "Jenny Lars".into(), age: 40, }, department: "IT".into(), }; vec![Box::new(basic), Box::new(vip), Box::new(internal)] }
3. main.rs
Code:mod customer; mod visualizer; fn main() { let list = customer::get_list_customer(); list.into_iter().for_each(|c| c.print()) }
Nhận xét: Cần dek gì Inheritance bạn toi ơi. Bài này interface + generic là quá đủ.
Đầy đủ output, structure chuẩn như lời hứa, còn lại đẹp xấu hay ngon hơn thì mời bà con bình. Output đây cho ai ko quen đọc code imperative.
Code:############## BasicCustomer { info: BasicInfo { name: "John Smith", age: 20 } } $$$$$$$ ############## VipCustomer { info: BasicInfo { name: "Tim Batte", age: 30 }, vip_point: 100 } @@@@@@@ ############## InternalCustomer { info: BasicInfo { name: "Jenny Lars", age: 40 }, department: "IT" } &&&&&&&