thảo luận Cuối cùng thì áp dụng 4 tính chất OOP vào code base như thế nào nhỉ?

Dễ sửa đổi, dễ xài lại thôi các thím.

Abstraction: obj nên show ra cái ổn định.

Encapsulation: obj nên hide đi cái bất ổn định.

2 thằng trên liên quan khá mật thiết. Nếu obj mình có cái bất ổn định mà bị show ra (public methods) cho thằng khác xài, tới lúc mình đổi làm nó phải đổi theo.

Polymorphism: tôi chơi chó thì cứ có hành vi chó là tôi chơi, chó tây chó ta chơi tuốt, mà source code của tôi ko phải sửa => tôi dễ dc xài lại.

Xài lại phải để nguyên mà xài chứ sửa source thì nói làm gì (nhiều khi ko có source mà sửa).

Inheritance: cái này các thím nói nhiều rồi, nhưng mục đích cũng là xài lại. Nên cẩn thận vì mức độ coupling rất cao, nhất là với nhưng ngôn ngữ dùng class inheritance.
 
Lên codeleatrn học lại đi ông :)) mấy này cũng khó gì đâu mà chỉ cần code thôi là dùng r :))) chứ chưa nói tới design pattern :))
 
Mấy tính chất thớt nói chung quy nó là để quản lý state. Vì có code thế nào đi nữa thì vấn đề vẫn là state (data) nó hoạt động ra sao khi bị các behavior tác động vào hoặc nó đang được một data nào khác phụ thuộc nó hoặc nó phụ thuộc data khác. Thế nên bộ môn OOP nó luôn liền tay liền chân với Design pattern cũng là vì câu chuyện quản lý state.

View attachment 987045

Ví dụ trong trường hợp này thì cần sử dụng concept Polymorphism. Nghĩa là mỗi lớp kế thừa phải làm chủ state data của chính nó, k để bị tác động bởi lớp cha. Mà để đạt được ý nghĩa này thì dever cứ code lớp cha sao cho chung chung thôi, k có hành vi nào tác động vào data nào cả.

View attachment 987101

Tương tự với Encapsulation cũng là cách để quản lý state vậy. Một lớp k muốn lớp khác chọc vào state của mình thì cứ private lại state (data) của nó thôi.
Mình cũng tư duy kiểu thế này. Sau cùng, tất cả chỉ là dùng behaviour để control states. Suy nghĩ mấy cái định nghĩa làm gì cho mệt đầu.
:bad_smelly:
 
Polymorphism có mục đích để cho object nó quyết định implement function một trong hai context :
  • overloading (Compile-time polymorphism)
  • overriding (Run-time polymorphism)

k rõ a đang nói về cái gì, còn bản chất polymorphism thì như tôi vừa nói.
mình bổ sung là tùy vào định nghĩa của ngôn ngữ đó nữa, chẳng hạn trong java chỉ có overriding là thể hiện tính poly, còn overloading nó nằm ở method signature. Còn nếu general case thì bác này ví dụ chuẩn rồi

via theNEXTvoz for iPhone
 
Viết lại chỉ là vd để thể hiện thím hiểu rõ server ntn thôi.

Quay lại vấn đề unit test, bản chất của nó là gì? Làm thế nào để viết unit test 1 cách đơn giản đỡ tốn cơm nhất? Có nhất định phải xài mock với dependency injection?

Khi tôi xác định sẽ viết unit test thì sẽ cân nhắc thiết kế chương trình sao cho việc viết test là đơn giản nhất, thuần oop sẽ bị loại đầu tiên do một số tính chất khiến việc quản lý state và dependencies trở nên chồng chéo phức tạp. Đi giải bài toán theo đúng bản chất của vấn đề thì mọi thứ sẽ trở nên đơn giản.

Nói ngáo vãi.
Bản chất là class A có unit test, class B có unit test, và nếu B gọi vào A thì mock class A ko có vấn đề gì, vì A nó đã được cover unit test rồi.
Thuần Oop bị loại đầu tiên :LOL::LOL: nghe rất ngáo, giải bài toán bằng cách bỏ ngôn ngữ lập trình Oop luôn thì đúng là dễ vl, chắc thanh niên này code frontend à

Sent from Samsung SM-G996B using vozFApp
 
Em ko hiểu ý bác lắm, nếu chỉ là áp dụng trong project thì:
Trong class biến nào private và phải dùng getter setter thì nó là áp dụng tính bao đóng.
Chỗ nào dùng abstract class và interface thì là tính trừu tượng
Class nào extend từ các class khác thì là tính kế thừa.
Cái đa hình thì nó hơi rắc rối chút, đại khái là nó cast kiểu lớp con về lớp cha. Ví dụ 2 class Car và Bike đều kế thừa class Vehicle. Ví dụ có chức năng cần nhận input là Car hoặc Bike, thay vì phải viết 2 hàm giống hệt nhau:
funcName(Car c){}
funcName(Bike b){}
Thì chỉ cần viết 1 hàm
funcName(Vehicle v) {}

Nếu chỉ hỏi áp dụng trong project thì nó dễ nhận biết và hình dung mà, ko biết có phải ý bác thớt k
 
Encapsulation là tính đóng gói và nó cũng dùng để giấu thông tin. Ví dụ người viết class ko muốn cho người dùng class đó đọc dc các biến bên trong mà phải đọc qua các method getter. Hoặc người viết ko muốn người dùng set linh tinh vào biến của họ. Ví dụ trong class đó có lưu địa chỉ số nhà, đường, thành phố. Người viết muốn đảm bảo lúc nào cũng phải có đủ 3 thông tin đấy thì họ sẽ ngăn chặn ko cho set riêng trực tiếp 3 field như vậy. Thay vào đó họ sẽ viết 1 hàm setter , validate các thông tin truyền vào để đảm bảo dữ liệu vào là chính xác.

Tương tự như getter, tính đóng gói sẽ giúp người dùng sử dụng tiện hơn. Ví dụ từ 3 field số nhà, đường, thành phố , sẽ có 1 hàm getter trả về địa chỉ dạng string. Viết hàm này trong chính class entity đó sẽ giúp người sử dụng ko cần phải implement lại logic đó nữa. Bê cái object đấy đi đâu đều có thể lấy dc địa chỉ theo đúng format. Đóng gói nó là như vậy

Ở level cao hơn class, tính đóng gói này cũng được áp dụng ở mức module hay service trong design

Rảnh viết tiếp 3 cái còn lại
 
:shame: anh thử show ra ví dụ dùng 4 tính chất xem, chứ tôi từng gặp nhiều người hay nói câu này lắm,đặc biệt mấy th sinh viên
Tính đóng gói ở trên rồi. Giờ tính trừu tượng

Như mình có design ở cty. Tính đa hình sẽ dc áp dụng như sau.

Mình muốn stream data ra bên ngoài để các partner có thể dùng dc dữ liệu của mình. Tuy nhiên mỗi response format của mỗi partner yêu cầu lại khác nhau. Thằng thích json, thằng lại thích xml. Giờ phải làm sao, if else tùy partner hay sao. Nếu if else thì nếu thêm thằng partner mới thì phải sửa code if else khá ngu. Vì vậy mình áp dụng đa hình.

Mình có 2 class đều implement interface OutputInterface là XML và json. Trong interface này có 1 hàm genResponse và 2 class này implement method đó.

Mình có 1 service BuildDataService và tạo dữ liệu cần thiết trong đó. Rồi muốn output ra mình chỉ cần for tất cả những class implement cái interface OutputInterface kia và gọi hàm genResponse. Tự động mình gen dc cả 2 loại json và xml.

Sau này muốn sửa logic genresponse mình chỉ vào từng class mình sửa. Muốn thêm loại response nữa thì mình chỉ cần tạo thêm class implement OutputInterface là đủ. Không cần quan tâm, debug xem cái hàm genresponse nó dùng ở đâu. Rất dễ maintain
 
Về tính trừu tượng của OOP thì trong OOP, design chuẩn và tối ưu nhất là giao tiếp qua Interface. các class chỉ implement lại các interface thế thôi.

Ví dụ mình làm 1 cái tính năng mua hàng mình cần có các bước addToCart, Payment, Receive. 3 bước này phải làm theo thứ tự. Vậy nên mình có 1 Interface BuyProductInterface có 3 hàm addToCart, Payment, Receive.

ServiceA sẽ có dạng
BuyProductInterface.addToCart();
Buyproductinterface.Payment();
Buyproductinterface.Receive().

Mình ko quan tâm thằng nào implement thằng Buyproductinterface mà mình chỉ cần dùng nó. Thằng nào implement Buyproductinterface sẽ phải implement đủ 3 hàm kia và nó sẽ dc auto sử dụng theo đúng thứ tự.

Mình chỉ cần thêm sửa xóa mấy class implement mà ko ảnh hưởng đến các logic khác
 
Không thể tin được có người đi làm java .net mà l biết oop ứng dụng ntn lại còn public hết field @@
Ngoài ra cái trừu tượng có khái niệm lâu r mà đặt ra khái niệm để xử lý vấn đề thì là trừ tượng rồi. Ở đâu chả dùng có phải mỗi oop đâu. Làm nó tiện hơn chính là trừu tượng. Biến đổi 1 đồng khái niệm bên dưới thành 1 cái dùng được và đel quan tâm cái bên dưới như a trên bảo là đúng cmnr.
Số k biết ntn trong thớt đông vcl 1 là ng lập trình có exp họ chán k thèm rep 2 là toàn sinh viên

via theNEXTvoz for iPhone
 
Về tính trừu tượng của OOP thì trong OOP, design chuẩn và tối ưu nhất là giao tiếp qua Interface. các class chỉ implement lại các interface thế thôi.

Ví dụ mình làm 1 cái tính năng mua hàng mình cần có các bước addToCart, Payment, Receive. 3 bước này phải làm theo thứ tự. Vậy nên mình có 1 Interface BuyProductInterface có 3 hàm addToCart, Payment, Receive.

ServiceA sẽ có dạng
BuyProductInterface.addToCart();
Buyproductinterface.Payment();
Buyproductinterface.Receive().

Mình ko quan tâm thằng nào implement thằng Buyproductinterface mà mình chỉ cần dùng nó. Thằng nào implement Buyproductinterface sẽ phải implement đủ 3 hàm kia và nó sẽ dc auto sử dụng theo đúng thứ tự.

Mình chỉ cần thêm sửa xóa mấy class implement mà ko ảnh hưởng đến các logic khác
Thx bác :love:. em đang rất cần những ví dụ thực tế như thế này :p .Mấy bác đi làm rồi cho em xin ví dụ thực tế với, chứ học trên trường xong làm bài thi thì được chứ implement vô trong project thấy nó cứ luộm thuộm sao ấy. =((
 
Tính ra thì cái tính trừu tượng là mình hay xài hằng ngày lun. Giống như khi làm với framework thì fw nó đã trừu tượng hoá những thứ phức tạp rồi.
Chỉ cần lên doc gọi đúng các Api mà fw đó show là có thể đáp ứng nhu cầu rồi (ko cần bít api nó chạy như thế nào)
1 vd là với React thì các hook useState, useEffect đã dc trừu tượng hoá rồi. Chỉ cần học cách xài thôi

Sent from Xiaomi 2201117TG using vozFApp
 
Tính đóng gói ở trên rồi. Giờ tính trừu tượng

Như mình có design ở cty. Tính đa hình sẽ dc áp dụng như sau.

Mình muốn stream data ra bên ngoài để các partner có thể dùng dc dữ liệu của mình. Tuy nhiên mỗi response format của mỗi partner yêu cầu lại khác nhau. Thằng thích json, thằng lại thích xml. Giờ phải làm sao, if else tùy partner hay sao. Nếu if else thì nếu thêm thằng partner mới thì phải sửa code if else khá ngu. Vì vậy mình áp dụng đa hình.

Mình có 2 class đều implement interface OutputInterface là XML và json. Trong interface này có 1 hàm genResponse và 2 class này implement method đó.

Mình có 1 service BuildDataService và tạo dữ liệu cần thiết trong đó. Rồi muốn output ra mình chỉ cần for tất cả những class implement cái interface OutputInterface kia và gọi hàm genResponse. Tự động mình gen dc cả 2 loại json và xml.

Sau này muốn sửa logic genresponse mình chỉ vào từng class mình sửa. Muốn thêm loại response nữa thì mình chỉ cần tạo thêm class implement OutputInterface là đủ. Không cần quan tâm, debug xem cái hàm genresponse nó dùng ở đâu. Rất dễ maintain
Bác cho em hỏi nếu mình dùng overriding method để implement trong trường hợp này được không bác? Có gì khác so với xài Interface không bác? Sorry trước nếu em hỏi ngu quá =((
 
Thx bác :love:. em đang rất cần những ví dụ thực tế như thế này :p .Mấy bác đi làm rồi cho em xin ví dụ thực tế với, chứ học trên trường xong làm bài thi thì được chứ implement vô trong project thấy nó cứ luộm thuộm sao ấy. =((
Luôn là luộm thuộm trước, sau đó refactor, vài lần sẽ đẹp. Tùy theo project có cho phép thời gian với code review để refactoring nhiều hay ít, chất lượng phụ thuộc vào đây

Như bên out source code xong vất hết cho QA thì đừng hỏi về chất lượng

Kể cả senior architect bên tôi lúc code draft cho issue cũng luôn nói là ý tưởng thôi, phải nghiên cứu kỹ đi
 
Tính ra thì cái tính trừu tượng là mình hay xài hằng ngày lun. Giống như khi làm với framework thì fw nó đã trừu tượng hoá những thứ phức tạp rồi.
Chỉ cần lên doc gọi đúng các Api mà fw đó show là có thể đáp ứng nhu cầu rồi (ko cần bít api nó chạy như thế nào)
1 vd là với React thì các hook useState, useEffect đã dc trừu tượng hoá rồi. Chỉ cần học cách xài thôi

Sent from Xiaomi 2201117TG using vozFApp
Nếu là vấn đề chỉ dùng mà ko cần biết cách xài thì lại là tính đóng gói chứ không phải trừu tượng.

Kiểu như bật công tắc là đèn sáng mà ko cần biết tại sao thì là đóng gói. Vì dây điện, bảng mạch để đèn sáng đã dc đóng gói vào 1 cục rồi :)
 
Back
Top