Coupling and cohesion are two often misunderstood terms in software engineering. These are terms that are used to indicate the qualitative analysis of the modularity in a system, and they help us to identify and measure the design complexity of object oriented systems.
However, a good knowledge of both is necessary to build systems that are scalable, manageable and can be extended over time. In this post, I'll discuss both of these; I'll present code examples in my future posts on this topic.
How do cohesion and coupling differ? How are concepts cohesion and coupling related to good or poor software designs? Before we explore cohesion and coupling and how they impact software designs, let's understand what each of these concepts is and their types.
Coupling may be defined as the degree of interdependence that exists between software modules and how closely they are connected to each other. In essence, coupling indicates the strength of interconnectedness between software modules. When this coupling is high, we may assume that the software modules are interdependent, i.e., they cannot function without the other. There are several dimensions of coupling:
- Content coupling -- this is a type of coupling in which a particular module can access or modify the content of any other module. In essence, when a component passes parameters to control the activity of some other component, there is a control coupling amongst the two components.
- Common coupling -- this is a type of coupling in which you have multiple modules having access to a shared global data
- Stamp coupling -- this is a type of coupling in which data structure is used to pass information from one component in the system to another
- Control coupling -- this is a type of coupling in which one module can change the flow of execution of another module
- Data coupling -- in this type of coupling, two modules interact by exchanging or passing data as a parameter
Cohesion denotes the level of intra-dependency amongst the elements of a software module. In other words, Cohesion is a measure of the degree to which the responsibilities of a single module or a component form a meaningful unit. Cohesion is of the following types:
- Co-incidental cohesion -- this is an unplanned random cohesion that might be a result of breaking a module into smaller modules.
- Logical cohesion -- this is a type of cohesion in which multiple logically related functions or data elements are placed in the same component
- Temporal cohesion -- this is a type of cohesion in which elements of a module are grouped in a manner in which they are processed at the same point of time. An example could be a component that is used to initialize a set of objects.
- Procedural cohesion -- this is a type of cohesion in which the functions in a component are grouped in a way to enable them to be executed sequentially and make them procedurally cohesive
- Communicational cohesion -- in this type of cohesion the elements of a module are logically grouped together in a way that they execute sequentially and they work on the same data
- Sequential cohesion -- in this type of cohesion the elements of a module are grouped in such a manner that the output of one of them becomes the input of the next -- they all execute sequentially. In essence, if the output of one part of a component is the input of another, we say that the component has sequential cohesion.
- Functional cohesion -- this is the best and the most preferred type of cohesion in which the degree of cohesion is the highest. In this type of cohesion, the elements of a module are functionally grouped into a logical unit and they work together as a logical unit -- this also promotes flexibility and reusability.
The best practices
Tight coupling increases the maintenance cost as it is difficult and changes to one component would affect all other components that are connected to it. So, code refactoring becomes difficult as you would need to refactor all other components in the connected-chain so that the functionality doesn't break. This process is cumbersome and takes a lot of tedious effort and time.
You should design classes that contain the less number of instance variables, i.e., your class design is "good" if it contains a small number of instance variables. Ideally, each of the methods in your class should manipulate one or more of these instance variables. Theoretically, a class is maximally cohesive if each of the instance variables of the class is used or manipulated by each of the methods of that class. When cohesion in class is high the methods and the data members of the class are co-dependent and work together as a single logical unit. However, in reality it isn't possible to design such classes or I would rather say, it is not advisable to design classes that are maximally cohesive.