Coupling and Cohesion là gì

Khả năng đóng gói dữ liệu [Data encapsulation], kế thừa [Inheritance] và đa hình [Polymorphism] là nền tảng của lập trình hướng đối tượng, nhưng đơn thuần vận dụng cả ba khái niệm trên không ngẫu nhiên mang lại một thiết kế chương trình tốt. Một chương trình thiết kế theo hướng đối tượng đòi hỏi chia nhỏ bài toán thành các phần, sao cho chúng vừa có đặc tính cố kết [giao tiếp giữa các phần]  lại vừa có khả năng tách biệt riêng rẽ để thay đổi, kiểm tra mà không ảnh hưổng đến thành phần khác. Điều này rất quan trọng trong sự phát triển, tiến hóa của một sản phẩm phần mềm.

Coupling và Cohesion là hai khái niệm trong OOP đặc trưng cho vấn đề này. Coupling : là sự phụ thuộc mô tả mức độ mà theo đó một phương thức [method] hay một kiểu [type] phụ thuộc vào phương thức khác hoặc kiểu khác để thực hiện hành vi của nó. Lớp A được gọi là phụ thuộc ở mức độ cao vào lớp B nếu một sự thay đổi trong lớp B là có khả năng gây ra một thay đổi trong hành vi của lớp A. Coupling còn được hiểu là sự phụ thuộc – dependence.

Các kiểu Coupling được chia làm 2 nhóm : Loosely Coupling và Tightly Coupling. Một chương trình có thiết kế tốt phải đảm bảo được đặc tính Loosely Coupling.

Independent/No Coupling : Nếu 2 lớp hoặc phương thức không chia sẻ bất kỳ dữ liệu nào thì chúng là độc lập [independent]. Việc lớp này sử dụng lớp kia một cách đơn giản không có nghĩa là 2 lớp phụ thuộc vào nhau. Ví dụ

class A { public void Foo[] { B b = new B[]; b.Bar[]; } } class B { public void Bar[] { //Thay doi o day khong anh huong toi hanh vi cua A } }

Data Coupling : Khi lớp A truyền một giá trị cần thiết cho B, thì A và B được gọi là ràng buộc về dữ liệu [data-coupled].  Đây là kiểu Coupling phổ biến thường được áp dụng. Ví dụ

class C { public void Foo[] { string mes = "Hello OOP"; D d = new D[]; d.Bar[mes]; } } class D { public void Bar[string mes] { Console.WriteLine[mes]; } }

Stamp Coupling : A truyền cho B kiểu tham chiếu hoặc toàn bộ cấu trúc dữ liệu thay vì chỉ truyền cho B trường dữ liệu cần thiết, do vậy nếu bất kỳ trường hay phương thức nào trong A thay đổi có thể ảnh hưởng tới xử lý của B, hoặc B có thể thay đổi A.

class G { public void Foo[] { K k = new K[]; k.Bar[this]; } int field1; public int Field1 { get { return field1; } set { field1 = value; } } int field2; public int Field2 { get { return field2; } set { field2 = value; } } } class K { public void Bar[G myG] { //Co the anh huong len myG.Field1 va myG.Field2 } }

Nhận xét : Stamp Coupling khiến chương trình trở lên rối và tạo ra nhiều bug tiềm ẩn, nên tránh truyền toàn bộ cấu trúc hoặc kiểu cho phương thức nếu phương thức đó chỉ sử dụng một phần của cấu trúc.

Tramp Coupling : Các tham số được truyền không đổi qua nhiều phương thức khác nhau cho đến khi chính thức được sử dụng

class TransactionService { void CalculateOrder[string custname] { FetchListProduct[custname]; } void FetchListProduct[string custname] { FetchAccountInfo[custname]; } void FetchAccountInfo[string custname] { //Su dung custname o day } }

Nhận xét : Có thể loại bỏ Tramp Coupling bằng cách đặt custname là một trường trong lớp TransactionService, việc truyền một tham số cho phương thức luôn ngụ ý rằng phương thức đó sử dụng tham số này, do vậy lập trình viên phải tránh viết các phương thức có các tham số đầu vào không có mục đích.

Control Coupling : Nếu logic của lớp B được điều khiển bởi một tham số cho bởi lớp A, thì 2 lớp A và B được gọi là control-coupled. Ở đây điều kiện tiên quyết là A chỉ định logic của B, B không có quyền tự quyết định.

class AirConditioner { const int NORMAL_TEMP = 20; public void ChangeTemperature[] { int temp = RoomThermometer.RoomTemp; if[temp < NORMAL_TEMP] { IncreaseTemp[]; } else { DecreaseTemp[]; } } private void DecreaseTemp[] { //throw new NotImplementedException[]; } private void IncreaseTemp[] { //throw new NotImplementedException[]; } } class RoomThermometer { static int roomTemp; public static int RoomTemp { get { return GetRoomTemp[]; } set { roomTemp = value; } } public static int GetRoomTemp[] { Random rand = new Random[]; roomTemp = rand.Next[0, 50]; return roomTemp; } }

Nhận xét:  đây là kiểu Coupling được sử dụng phổ biến trong lập trình.

External Coupling : Nếu 2 lớp A và B tương tác thông qua một non-native object [file, CSDL], thì 2 lớp đó được gọi là external coupled. Yếu điểm ở đây là khó theo dõi các trạng thái giao tiếp, debug gặp khó khăn.

Common Coupling : Nếu 2 lớp A và B là phụ thuộc vào cùng một dữ liệu tĩnh [static data], thì 2 lớp đó được gọi là common coupled.

Content Coupling : Nếu 2 lớp A và B thay đổi trực tiếp trạng thái nội tại của lớp kia, dẫn tới thay đổi hành vi của nó thì được gọi là content coupling

Low coupling và high cohesion là 2 thuộc tính đi cùng với nhau như là mục tiêu cần đạt được trong thiết kế, trong bài viết này, cùng tìm hiểu xem chúng là gì, làm sao để đạt được và tránh các lỗi liên quan đến coupling và cohesion khi thiết kế phần mềm.

Bạn đang xem: Cohesion là gì

COUPLING

Low couplingloose coupling hay high coupling và tight coupling, ắt hẳn ai trong chúng ta khi học về các nguyên lý lập trình căn bản đều biết về khái niệm coupling này. Coupling đề cập đến vấn đề phụ thuộc lẫn nhau giữa các component. Low coupling, loose coupling có nghĩa là các component ít phụ thuộc vào nhau, sự thay đổi trong component này ít khi, hoặc không ảnh hưởng đến component kia. Ngược lại, high coupling và tight coupling cho thấy các component phụ thuộc nhiều vào nhau, khi thay đổi 1 component thì các component kia đều bị ảnh hưởng và có khả năng phải thay đổi theo. Tất nhiên, low coupling là mục tiêu chúng ta cần hướng đến để đảm bảo cho hệ thống ít bị ảnh hưởng khi có thay đổi và do đó, tăng tốc độ thực hiện công việc và bảo trì.


Nếu chúng ta nhìn vào hình trên, nó cho chúng ta thấy một mối liên hệ giữa hai class được gọi là tight coupling. Class1 ở trên tạo ra các đối tượng của Class2 trực tiếp, và thậm chí là đi đến các biến thành viên và truy cập vào. Điều này làm cho nó rất phụ thuộc vào Class2. Điều gì sẽ xảy ra nếu chúng ta quyết định rằng chúng ta muốn thêm tham số thêm vào trong constructor của Class2 và đặt mặc định là private? Sau đó, chúng ta phải thay đổi mọi cách sử dụng Class2 ở mọi nơi. Không đẹp lắm, heh? Có thể là một cơn đau đầu rất lớn và là một trong những vấn đề đầu tiên trong thiết kế.

Dưới đây là ví dụ bằng code:

public class ClassA { private boolean attributeA; public int methodA[] { if[attributeA] { return new ClassB[].attributeB; } return -1; } public String getValue[] { return new ClassB[].getValue[]; }}public class ClassB { public int attributeB; public String getValue[] { return "Heh?!?"; }}

MỘT SỐ GIẢI PHÁP

DEPENDENCY INVERSION

Ví dụ trong Java, ta sẽ thêm một interface. Đó là cách Class1 sẽ chỉ phụ thuộc vào interface đó, chứ không phải là implementation thực tế của Class2, do đó giảm thiểu sự phụ thuộc trực tiếp giữa 2 class với nhau.

Xem thêm: Phó Giáo Sư Tiếng Anh Là Gì, Phó Giáo Sư Tiến Sĩ Tên Tiếng Anh Là Gì

LAW OF DEMETER [DON’T TALK TO STRANGERS!]

Lợi điểm của Law of Demeter là nó giúp hệ thống của chúng ta đứng vững trước những thay đổi bằng cách giảm coupling hay còn gọi là cách design loose coupling, mọi sự thay đổi sẽ là nhỏ nhất nếu có thể.

COHESION

Còn high cohesion [trái ngược với nó là low cohesion] là gì? Khi nói đến cohesion chúng ta nghĩ đến nhiệm vụ của từng module. Nhiệm vụ của từng module càng rõ ràng và tách biệt thì cohesion càng cao [high cohesion], và đó là mục tiêu cần đạt tới khi thiết kế. Giải thích bằng code có lẽ sẽ không rõ ràng, hãy xem xét câu dưới đây:

Tại kỳ họp Quốc hội thứ năm, khi thảo luận về quản lý chất lượng vệ sinh an toàn thực phẩm có vị đại biểu Quốc hội đã ví việc có tới 5 bộ chịu trách nhiệm chính như vậy cũng giống như “nhiều sãi không ai đóng cửa chùa”.Bởi thế, làm rõ trách nhiệm của từng cơ quan quản lý Nhà nước về an toàn thực phẩm là một yêu cầu được nhấn mạnh khi xây dựng Dự Luật An toàn thực phẩm.

Nếu xem Dự Luật An toàn thực phẩm là một feature thì rõ ràng nó đã không đạt được tính high cohesion trong thiết kế vì nó phải dàn trải và phụ thuộc vào rất nhiều module [5 bộ, phòng ban] khác nhau. Do đó, khi cần chỉnh sửa bổ sung dự luật sẽ rất khó khăn vì phải sửa 1 lúc 5 module, mà bạn thấy đó, điều đó rõ ràng là rất khó. Nếu quy trách nhiệm xây dựng bộ luật này cho một bộ ban duy nhất thì sẽ giảm tính phức tạp và do đó, tăng tính cohesion. High cohesion thường đạt được nếu ta tuân thủ theo nguyên tắc đơn nhiệm [Single responsibility principle], mỗi module, khi đó chỉ đảm nhiệm một nhiệm vụ duy nhất, không hơn không kém, và không có chuyện 2 module cùng làm một nhiệm vụ, một tính năng.

Xem thêm: Đuôi Svg Là Gì ? Tại Sao Nên Dùng Svg? File Svg Là Gì

Đến đây chắc ai cũng hiểu được rồi đúng không? Ít nhất là về mặt lý thuyết, hãy xem xét bảng sau trước khi mình đi vào các dẫn giải tiếp theo.

Video liên quan

Chủ Đề