Which of the following type of coupling is possible when two or more modules acquire the common global data variable?

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

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

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.

Copyright © 2015 IDG Communications, Inc.

Modular programming (according to Wikipedia) is a software design technique that emphasizes separating the functionality of a program into independent, interchangeable modules, such that each contains everything necessary to execute only one aspect of the desired functionality. This means that if you are not writing the new Star Wars Movie script, and if you are developing software, you do not write the whole software script in one file like the Iliad. By dividing the whole concept into smaller parts, modules, you deal with them separately and construct the communication of these modules with each other while creating the whole.

Modularization of a Software

The main purpose of modularization is to make the software project simpler and more manageable and scalable. Let’s modulate the benefits:

Your code will be easier to read. Code blocks will become smaller and narrower, therefore it will be easier to understand what they do in a narrow sense, and what is their role in the bigger picture.

You will test your code easily. The function volumes will be smaller, it will be easier to write and manage the tests. Since you deal with the small parts in the whole closely, a much more detailed test will be implemented in total.

In fact, since we also categorize the responsibilities in modularization, you will be able to easily access a code snippet or function that you are looking for.

Reusability. You will not need to write the same code again and again. Just take the one you have already written, and use it somewhere else.

If a function is problematic, then you will just fix that specific function. You do not need to visit all parts of the software which are using this function.

It will be very easier to refactor your code. Besides, it will be easier to work together with team members. Each person can work on a different module, etc.

Coupling and cohesion are two higher-level terms that we should consider when constructing the inter-module and intra-module structure in a software design. They give information about how easily your code can be changed or extended.

Coupling

Coupling is the degree of interdependence between software modules. It specifies how much information one class has about another class. If information is transferred from one class to another directly, we can say that coupling is tight here, however, if there is an interface between them, then we can say that it is loosely coupled. We should make our structure as loosely as possible.

Having high coupling is problematic because changing something in one part of your program means you need to change things in multiple places. Of course, there will be some portion of coupling in your code because various parts of your program need to work together, but the more coupling you introduce, the more complicated things will be.

Coupling. Change one part, what will happen to others? Co-exchange problem.

Here are the different types of couplings from worst to best:

Content coupling: Cases where classes are dependent on each other’s internal structures & their implementations, happen because of wrong abstractions. It creates the problem of updating / changing together. A change in one causes a change in the other one. As the program grows, this problem becomes inextricable.

In the example below, if we change KeyReader class, we have to change related Console behaviors since they are linked to each other.

Content coupling

Common coupling: Dependencies on global data and variables. If you change the global variable, everything related will be affected.

External coupling: If the component or system they use in common along the structures imposes format, interface, data structure, etc, this will cause external coupling.

Control coupling: A dependency in which structures control each other’s flows by passing flags. It is a special case of data coupling.

Data-structured coupling: It is the dependency that structures create by passing complex data structures to each other. What is sent is a data structure, not an object.

Data coupling: It is the dependency that structures create by passing primitive data to each other, for example, integers. It is a simpler version of data-structured coupling. Passing too many parameters to a method is a common symptom of this coupling.

Message coupling: Best case. It is a form of coupling that does not require any knowledge other than the interface of an object. The coupling must be over the interfaces of the methods, methods that the classes offer to each other.

Objects with message coupling provide services to each other, data remains only as material in the provision of this service. There is no direct access to the data. That is, it is not an exchange of data, it is an exchange of services.

No coupling: There is no coupling. Completely different units.

There are other coupling types in OOP:

Inheritance coupling: is-a coupling.

Abstract coupling: coupling to abstract classes. Can be both is-a and has-a coupling (polymorphism).

Cohesion

Cohesion is the extent to which two or more parts of a system are related and how they work together to create something more valuable than the individual parts. “The whole is greater than the sum of the parts.”. We definitely want more cohesive structures.

A strong cohesive structure has a clear responsibility, it is being focused on a single task. Single responsibility in Solid principles is actually about how cohesive we are, and how high or low the level of cohesion is. Each part of the design addresses a separate concern, a set of information that affects the code of a computer program. If all the structures and functions of a class are for the same common purpose, the cohesion of that class is high.

Cohesion is a common purpose.

Strong cohesion makes your code easier to understand (lower complexity) and maintain. And also, increases the reusability.

Now let’s examine some types of cohesion from worse to best. We will use abstract classes in Python scripts to demonstrate.

Coincidental cohesion: No conceptual relationship between elements. It is accidental and the worst form of cohesion. This one is very common in utility classes. For example, in the class below, there are unrelated methods together.

An abstract class that has coincidental cohesion

Logical cohesion: They are classes that are brought together by thinking that they are about the same concept, even though they are different in reality. Better than coincidental, there is at least a low level of semantic relation. All the methods in the below class are related to reading, but there is no semantic unity between them. Which object reads both the article and the database?

An abstract class that has logical cohesion

Temporal cohesion: The elements are related by their timing involved. In a module connected with temporal cohesion, all the tasks must be executed in the same period. For example, there may be a situation where a method trying to perform a calculation catches the exception thrown when it fails to perform the calculation for some reason, logs the situation, generates the necessary warnings, and continue to calculate in other ways.

An abstract class that has temporal cohesion

Procedural cohesion: It is the functional separation of works related to a subject from top to bottom and bringing them all together in a class.

Procedural cohesion

Communicational / Informational cohesion: It brings together structures that work on the same data. It is seen in cases where data processing comes to the fore.

Sequential cohesion: They are classes that combine functions that work in form of pipes, where the output of one feeds the other at the class level.

Sequential cohesion

Functional cohesion: Ideal case. Every essential element for a single computation is contained in the component. A functional cohesion performs the task and functions. They are structures that are single, well-defined, and put together for as little as possible a task or responsibility.

As the details increase in the software development process, the classes in other types of cohesion tend to be larger and larger. In functional cohesion, it is tried to protect the focus by dividing, for example, when new add-on methods arrive, classes are divided by grouping again. Because as the detail increases, the definition of the job or responsibility changes, and each job is divided into different and smaller jobs.

In the example below, the Phone class is both connecting and sending data. We split this class into two to make it more cohesive. DataHandler handles data transfer and PhoneConnection is responsible for connections.

Functional cohesion

Conclusion

We want low coupling and high cohesion at the end of the day. For the components that do the jobs to be highly cohesive and low-coupling, the structures must be subdivided appropriately into atomic works. These atomic works will be not able to break down into smaller sub-parts. They should have only one task and each must do one exact task successfully. They should have a lower relationship with each other.

Structures with high-level methods responsible for coordination that manage the output of multiple atomic works and translate them into a process are also required. This coordination is also a coupling and should be minimal. This is how we create work hierarchies.

Further Reading

More content at PlainEnglish.io. Sign up for our free weekly newsletter. Follow us on Twitter and LinkedIn. Join our community Discord.