DEV Community

Cover image for Cohesion and Coupling in Javascript
mahdi
mahdi

Posted on

Cohesion and Coupling in Javascript

Summary

Cohesion and coupling are two fundamental principles in Object-Oriented (OO) design that play a crucial role in creating robust and maintainable software systems.

Cohesion refers to the degree to which the elements within a module or class are related to each other and focused on a single task or responsibility. High cohesion suggests that the elements within a module work closely together to achieve a common purpose, resulting in more readable, understandable, and maintainable code. On the other hand, low cohesion indicates that the elements within a module may be unrelated or loosely connected, leading to code that is harder to comprehend and modify.

Coupling, on the other hand, refers to the degree of interdependence between modules or classes. Low coupling implies that modules or classes are loosely connected and can be modified independently without affecting each other, promoting modularity, reusability, and maintainability. High coupling suggests strong interdependencies between modules or classes, making it difficult to modify one component without impacting others, leading to a fragile and less adaptable system.

In OO design, achieving high cohesion and low coupling is essential for building scalable, maintainable, and extensible software systems. Designing classes and modules that are cohesive and loosely coupled promotes code that is easier to understand, test, and maintain, facilitating the evolution of software over time. By adhering to these principles, developers can create more robust, flexible, and resilient applications that meet the evolving needs of users and stakeholders.

Better Understanding:

Coupling

Coupling is a fundamental concept in object-oriented design that refers to the degree of interdependence between software modules or classes. It measures how closely connected or intertwined two or more routines or modules are within a system. Coupling reflects the strength of relationships between modules and the extent to which changes in one module can affect other modules .Coupling is usually contrasted with cohesion. Low coupling often correlates with high cohesion, and vice versa. Low coupling is often thought to be a sign of a well-structured computer system and a good design, and when combined with high cohesion, supports the general goals of high readability and maintainability.

Summary:

Coupling is the degree of interdependence between software modules; a measure of how closely connected two routines or modules are; the strength of the relationships between modules.

  1. Low Coupling: Low coupling implies minimal interactions between different components. This desirable characteristic in OOP promotes modularity and independence. Achieved by limiting the knowledge each class or module has of others and ensuring communication occurs through well-defined interfaces, low coupling facilitates easier maintenance, testing, and reuse of code.

  2. High Coupling: High coupling denotes strong dependencies between components. When one component relies heavily on the internal details of another, changes in one component can cascade, affecting others and rendering the system fragile and difficult to maintain. High coupling often results in code that is challenging to understand, modify, and test.

Types of Coupling:

Procedural Programming:

  1. Content Coupling (High):

    • Definition: Content coupling occurs when one module directly accesses or modifies the internal data or implementation details of another module.
    • Characteristics:
      • Tightest form of coupling.
      • Modules are highly dependent on each other's internal structure.
      • Any change in one module's implementation may require corresponding changes in another module.
    • Example: Module A directly accesses variables or functions defined in Module B without using any interfaces.
  2. Common Coupling:

    • Definition: Common coupling happens when multiple modules share the same global data.
    • Characteristics:
      • Changes to the global data affect all modules that use it.
      • Increases the risk of unintended side effects and makes debugging and maintenance difficult.
    • Example: Multiple modules accessing and modifying a global variable.
  3. External Coupling:

    • Definition: External coupling occurs when modules depend on an external interface, such as a file format, database schema, or communication protocol.
    • Characteristics:
      • Modules are coupled through external dependencies.
      • Changes in the external interface may require modifications to multiple modules.
    • Example: Modules that read and write data to a shared file format.
  4. Control Coupling:

    • Definition: Control coupling happens when one module controls the behavior of another module by passing it control information, such as flags or status variables.
    • Characteristics:
      • Tight coupling based on control flow.
      • One module dictates the behavior of another.
    • Example: Module A invokes Module B and passes a flag to indicate a specific behavior.
  5. Stamp Coupling (Data-structured Coupling):

    • Definition: Stamp coupling occurs when modules share a complex data structure, but not all elements of the structure are used by each module.
    • Characteristics:
      • Modules are coupled through a shared data structure.
      • Each module may use different parts of the structure.
    • Example: Module A passes a record to Module B, but Module B only uses certain fields of the record.
  6. Data Coupling:

    • Definition: Data coupling happens when modules communicate by passing data, typically through parameters.
    • Characteristics:
      • Loose coupling based on passing data.
      • Modules are aware of each other's data, but not their internal details.
    • Example: Module A calls Module B and passes parameters as arguments.

Object-Oriented Programming:

  1. Subclass Coupling:

    • Definition: Subclass coupling occurs when a subclass is dependent on the implementation details of its superclass.
    • Characteristics:
      • Tight coupling between a subclass and its superclass.
      • Subclass inherits properties and behaviors from the superclass.
    • Example: Subclass B extends superclass A and relies on the implementation of A's methods.
  2. Temporal Coupling:

    • Definition: Temporal coupling happens when the control flow between modules is based on timing or synchronization.
    • Characteristics:
      • Modules are temporally dependent on each other.
      • Execution timing affects the interaction between modules.
    • Example: Module A must be called before Module B due to timing constraints.
  3. Dynamic Coupling:

    • Definition: Dynamic coupling occurs when modules are coupled at runtime, often through dynamic method invocation or late binding.
    • Characteristics:
      • Runtime behavior determines the interaction between modules.
      • Flexibility in method invocation at runtime.
    • Example: Using interfaces or abstract classes for dynamic polymorphism.
  4. Semantic Coupling:

    • Definition: Semantic coupling occurs when modules are coupled based on their meaning or purpose, rather than their implementation.
    • Characteristics:
      • Modules are coupled based on their logical relationship.
      • Changes in one module may impact another due to their semantic connection.
    • Example: Modules handling similar business logic or domain concepts are semantically coupled.
  5. Logical Coupling:

    • Definition: Logical coupling happens when modules are not directly connected by code, but they share a common logical concept or task.
    • Characteristics:
      • Modules are loosely coupled but related conceptually.
      • Changes in one module may indirectly affect another due to their logical relationship.
    • Example: Modules related to user authentication and authorization are logically coupled even if they do not directly interact in code.

Disadvantages of tight coupling

  1. Ripple Effect of Changes:

    • Tight coupling means modules are highly dependent on each other's implementation details.
    • When one module is modified, it often necessitates changes in other tightly coupled modules.
    • This ripple effect can propagate throughout the system, making maintenance more challenging and error-prone.
  2. Increased Effort and Time for Assembly:

    • Building or assembling modules into the system becomes more complex and time-consuming.
    • Dependencies between tightly coupled modules must be carefully managed, increasing the effort required for integration.
    • Changes in one module may require modifications in several others, prolonging the development process.
  3. Difficulty in Reusability and Testing:

    • Tightly coupled modules are less reusable because they are closely tied to specific contexts or environments.
    • Reusing a tightly coupled module may require including its dependent modules as well, leading to unnecessary complexity.
    • Testing individual modules in isolation becomes difficult due to their tight interdependency.
    • Unit testing and integration testing become more challenging, as changes in one module can affect the behavior of other modules, leading to intricate testing scenarios.
  4. Reduced Flexibility and Scalability:

    • Tight coupling limits the flexibility of the system to accommodate changes or adapt to new requirements.
    • It becomes harder to extend or modify the system without affecting existing functionality.
    • Scalability may be hindered because tightly coupled systems often struggle to accommodate growth or changes in workload.
  5. Difficulty in Understanding and Maintenance:

    • Tightly coupled systems tend to be more complex and harder to understand.
    • Developers may find it challenging to comprehend the interactions between tightly coupled modules, leading to confusion and errors.
    • Maintenance becomes more arduous as changes in one part of the system can have unforeseen consequences elsewhere.

Conclusion:

Coupling is a critical concept in software engineering that describes the level of dependency between modules or components within a system. It plays a significant role in determining the modularity, flexibility, and maintainability of software systems. Understanding the different types of coupling and their implications is essential for designing robust and scalable software architectures.

Advantages and Disadvantages of Coupling:

Aspect Advantages Disadvantages
Flexibility - Loose coupling allows for easier adaptation to changes and new requirements. - Tight coupling restricts flexibility and makes it harder to modify or extend the system.
Modularity - Loose coupling promotes modular design, facilitating independent development and testing of modules. - Tight coupling can lead to monolithic systems where modules are highly interdependent, reducing modularity.
Reusability - Loose coupling enhances code reusability, as independent modules can be reused in different contexts. - Tight coupling reduces reusability, as tightly coupled modules are closely tied to specific contexts and dependencies.
Maintenance - Loose coupling simplifies maintenance, as changes in one module are less likely to impact other modules. - Tight coupling increases maintenance effort, as changes in one module may require modifications in multiple other modules (ripple effect).
Integration - Loose coupling eases module integration, allowing for more straightforward assembly of components. - Tight coupling complicates integration, as dependencies between modules must be carefully managed and resolved.
Testing - Loose coupling facilitates unit testing and integration testing of modules in isolation. - Tight coupling makes testing more challenging, as modules are tightly interdependent and changes in one module may affect the behavior of others.
Scalability - Loose coupling improves system scalability, as individual modules can be scaled independently. - Tight coupling hampers scalability, as changes or growth in one part of the system may require modifications across multiple tightly coupled modules.

Cohesion

Cohesion in computer programming refers to the degree to which the elements within a module are related or belong together. It is a fundamental concept in software design that influences various aspects of software quality, such as maintainability, reusability, and understandability.

In computer programming, cohesion refers to the degree to which the elements inside a module belong together.In one sense, it is a measure of the strength of relationship between the methods and data of a class and some unifying purpose or concept served by that class.
Cohesion is an ordinal type of measurement and is usually described as “high cohesion” or “low cohesion”. Modules with high cohesion tend to be preferable, because high cohesion is associated with several desirable traits of software including robustness, reliability, reusability, and understandability. In contrast, low cohesion is associated with undesirable traits such as being difficult to maintain, test, reuse, or even understand.
NOTE:

Cohesion is often contrasted with coupling. High cohesion often correlates with loose coupling, and vice versa.

Summary:
In computer programming, cohesion refers to the degree to which the elements inside a module belong together. In one sense, it is a measure of the strength of relationship between the methods and data of a class and some unifying purpose or concept served by that class.

High cohesion

When methods within a class share commonalities and serve similar purposes, the class is said to exhibit high cohesion. This concept plays a crucial role in enhancing code readability, reusability, and maintainability while keeping complexity manageable.

Cohesion is Increased if:

  1. Common Functionalities: When the functionalities embedded in a class, accessible through its methods, have significant commonalities or serve a unified purpose, cohesion is increased. This ensures that the class encapsulates a coherent set of operations.

  2. Small Number of Related Activities: High cohesion is achieved when methods within a class carry out a limited number of closely related activities. By avoiding broad or unrelated sets of data, the class maintains focus and clarity in its responsibilities.

  3. Grouping of Related Methods: Related methods should be logically grouped together within the class structure or in the same source file. This facilitates comprehensibility and makes it easier for developers to locate and understand the functionalities provided by the class.

Advantages of High Cohesion:

  1. Reduced Module Complexity: Highly cohesive modules are simpler, containing fewer operations. This reduction in complexity makes the codebase easier to understand and maintain.

  2. Increased System Maintainability: High cohesion minimizes the impact of changes in the domain or requirements. Modifications to one module often require fewer changes in other modules, thus enhancing system maintainability.

  3. Enhanced Module Reusability: With cohesive sets of operations provided by highly cohesive modules, application developers can easily identify and utilize components, increasing code reuse and promoting modular design practices.

Example :

// Example of a highly cohesive class for managing user authentication

class AuthManager {
  constructor() {
    // Initialize authentication-related variables
    this.loggedInUser = null;
    this.isAuthenticated = false;
  }

  // Method to handle user login
  login(username, password) {
    // Authenticate user logic here
    // Assume it sets this.loggedInUser and this.isAuthenticated upon successful login
  }

  // Method to handle user logout
  logout() {
    // Clear authentication-related variables
    this.loggedInUser = null;
    this.isAuthenticated = false;
  }

  // Method to check if user is logged in
  isLoggedIn() {
    return this.isAuthenticated;
  }

  // Method to retrieve current logged-in user
  getCurrentUser() {
    return this.loggedInUser;
  }

  // Method to reset user password
  resetPassword(username, newPassword) {
    // Reset password logic here
  }
}

// Usage of AuthManager class
const authManager = new AuthManager();

// Example usage
authManager.login("john_doe", "password123");
console.log(authManager.isLoggedIn()); // Output: true
console.log(authManager.getCurrentUser()); // Output: { username: 'john_doe', ... }

authManager.logout();
console.log(authManager.isLoggedIn()); // Output: false
console.log(authManager.getCurrentUser()); // Output: null
Enter fullscreen mode Exit fullscreen mode

In this example:

  • The AuthManager class encapsulates authentication-related functionalities.
  • Methods within the class (login, logout, isLoggedIn, getCurrentUser, resetPassword) are closely related to user authentication and management.
  • Each method serves a specific aspect of authentication, such as login, logout, checking if a user is logged in, retrieving the current user, and resetting passwords.
  • The class exhibits high cohesion because all methods are focused on a common purpose of user authentication and management.
  • Related methods are grouped within the same class, promoting code organization and readability.

Low cohesion

Low cohesion in programming occurs when the elements within a module lack a strong, unified purpose or have loosely related functionalities. This can lead to code that is difficult to understand, maintain, and reuse. Below are the characteristics and disadvantages of low cohesion:

Characteristics of Low Cohesion:

  1. Diverse Functionalities: Low cohesion is observed when the functionalities embedded in a class or module are diverse and unrelated. Methods within the class may serve different purposes, leading to confusion about the module's responsibility.

  2. Large Number of Unrelated Activities: Modules with low cohesion tend to contain methods that perform a large number of unrelated activities. This results in a lack of clarity and focus, making it challenging to understand the module's purpose.

  3. Scattered Related Methods: Related methods may be scattered across different classes or modules rather than being logically grouped together. This fragmentation hampers code organization and makes it difficult for developers to locate and understand the functionalities provided by the module.

Disadvantages of Low Cohesion:

  1. Increased Module Complexity: Low cohesion results in modules that are more complex, containing a wide range of unrelated functionalities. This complexity makes it harder to understand, maintain, and modify the codebase.

  2. Decreased System Maintainability: Changes in one part of the codebase may have unintended consequences in other parts due to the lack of cohesion. This increases the risk of introducing bugs and errors during maintenance and evolution of the system.

  3. Reduced Module Reusability: Modules with low cohesion are less likely to be reusable in other parts of the system or in different projects. The lack of a cohesive purpose makes it challenging for developers to identify and extract reusable components from the module.

Example of Low Cohesion:

// Example of a class with low cohesion

class UtilityFunctions {
  constructor() {
    // Initialize utility functions
  }

  // Method to calculate area of a rectangle
  calculateRectangleArea(length, width) {
    return length * width;
  }

  // Method to convert a string to uppercase
  convertToUppercase(str) {
    return str.toUpperCase();
  }

  // Method to generate a random number
  generateRandomNumber(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
  }

  // Method to validate email format
  validateEmail(email) {
    return /\S+@\S+\.\S+/.test(email);
  }
}

// Usage of UtilityFunctions class
const utils = new UtilityFunctions();

// Example usage
console.log(utils.calculateRectangleArea(5, 10)); // Output: 50
console.log(utils.convertToUppercase("hello")); // Output: HELLO
console.log(utils.generateRandomNumber(1, 100)); // Output: Random number between 1 and 100
console.log(utils.validateEmail("example@example.com")); // Output: true
Enter fullscreen mode Exit fullscreen mode

In this example:

  • The UtilityFunctions class contains a collection of methods that perform unrelated tasks such as calculating rectangle area, converting strings to uppercase, generating random numbers, and validating email addresses.
  • These methods do not have a strong, cohesive purpose; they are arbitrary utility functions bundled together within the same class.
  • The class exhibits low cohesion because its methods lack a common theme or purpose, leading to a codebase that is harder to understand and maintain.
  • Related methods should ideally be grouped together in separate classes or modules to improve cohesion and maintainability.

Types of Cohesion:

1. Coincidental Cohesion (worst):

Coincidental cohesion refers to a situation where elements within a module are grouped together arbitrarily, without any logical relationship or common purpose. Methods or functions in such modules typically perform unrelated tasks, and the module lacks a cohesive design. Coincidental cohesion is considered the worst type of cohesion because it leads to code that is difficult to understand, maintain, and reuse.

2. Logical Cohesion:

Logical cohesion occurs when the elements within a module are grouped together based on some logical criteria or category. Although the elements may not share a strong, inherent relationship, they are grouped together because they are logically related to each other in some way. While better than coincidental cohesion, logical cohesion still results in modules that may be somewhat disjointed and harder to maintain.

3. Temporal Cohesion:

Temporal cohesion involves grouping elements within a module based on the timing of their execution. Methods or functions that need to be executed together or during the same period are grouped together within the module. While temporal cohesion ensures that related tasks are executed at the same time, it may lead to modules that are more difficult to understand and maintain, especially if the tasks are not logically related.

4. Procedural Cohesion:

Procedural cohesion occurs when elements within a module are grouped together because they contribute to a single, well-defined procedure or process. Methods or functions within the module work together to achieve a specific task or objective, making the module more focused and cohesive. Procedural cohesion is common in procedural programming paradigms.

5. Communicational/Informational Cohesion:

Communicational or informational cohesion involves grouping elements within a module based on the data they operate on or share. Methods or functions within the module work with the same set of data or exchange information, indicating a strong relationship between them. While communicational cohesion promotes data encapsulation and reusability, it may also lead to modules that are tightly coupled.

6. Sequential Cohesion:

Sequential cohesion occurs when elements within a module are arranged in a sequence, where the output of one element serves as the input to the next. Methods or functions within the module are executed in a specific order, typically to achieve a step-by-step process or algorithm. While sequential cohesion ensures a clear flow of execution, it may also result in modules that are harder to modify or reuse.

7. Functional Cohesion (best):

Functional cohesion is the most desirable type of cohesion, where elements within a module are grouped together because they contribute to a single, well-defined function or task. Methods or functions within the module work together to accomplish a specific objective, sharing common data and operations. Functional cohesion leads to modules that are focused, reusable, and easy to understand and maintain.

8. Perfect Cohesion (Atomic):

Perfect cohesion refers to a theoretical ideal where a module consists of only one element, such as a single function or method. While perfect cohesion ensures that the module has a single, well-defined purpose, it is often impractical for complex tasks, as they cannot be expressed by a single, simple element. Perfect cohesion needs to be balanced with considerations of unit complexity and coupling in practice.

total resulting :

Cohesion Type Description Characteristics Advantages
Coincidental Cohesion Elements grouped arbitrarily without logical relationship or common purpose. Unrelated tasks, difficult to understand, maintain, and reuse. None
Logical Cohesion Elements grouped based on logical criteria or category, though not inherently related. Somewhat disjointed, logical relationship between elements. Provides some organization, but may still be challenging to maintain.
Temporal Cohesion Elements grouped based on timing of execution, needing to be executed together. Tasks executed at the same time, potential difficulty if tasks are not logically related. Ensures related tasks are executed together, but may sacrifice clarity.
Procedural Cohesion Elements grouped to contribute to a single, well-defined procedure or process. Focused on a specific task or objective. Promotes clarity and focus within the module.
Communicational Cohesion Elements grouped based on the data they operate on or share, indicating a strong relationship. Work with the same set of data, may lead to tightly coupled modules. Encourages data encapsulation and reusability, but may increase coupling.
Sequential Cohesion Elements arranged in sequence, with the output of one serving as the input to the next. Executed in a specific order, may be harder to modify or reuse. Ensures clear flow of execution, but may limit flexibility.
Functional Cohesion Elements grouped to contribute to a single, well-defined function or task. Work together to accomplish a specific objective, leads to focused, reusable modules. Promotes clarity, reusability, and maintainability.
Perfect Cohesion Module consists of only one element, such as a single function or method. Ideal case, but often impractical for complex tasks. Provides a clear, well-defined purpose for the module, but may not be feasible in practice.

High Cohesion Vs Low Cohesion:

Aspect High Cohesion Low Cohesion
Definition Degree to which elements in a module are related and serve a unified purpose Degree to which elements in a module lack a strong, unified purpose or have loosely related functionalities
Characteristics - Methods share commonalities and serve similar purposes
- Small number of related activities
- Grouping of related methods
- Diverse functionalities
- Large number of unrelated activities
- Scattered related methods
Advantages - Reduced module complexity
- Increased system maintainability
- Enhanced module reusability
- Clear flow of execution
- Potentially easy to understand individual elements
Disadvantages - May result in increased module complexity
- May lead to reduced system maintainability
- Can make debugging and modification challenging
- Can lead to modules that are harder to understand, maintain, and modify
- Increased risk of introducing bugs due to lack of clarity
Example - AuthManager class managing user authentication
- Methods closely related to authentication and management
- UtilityFunctions class with unrelated methods like calculating area, converting strings, generating random numbers, and validating email addresses
Types of Cohesion - Functional Cohesion: Ideal scenario where methods contribute to a single, well-defined function or task - Coincidental Cohesion: Arbitrary grouping without logical relationship
- Logical Cohesion: Grouping based on logical criteria, but not strong relationship
- Temporal Cohesion: Grouping based on timing of execution
- Procedural Cohesion: Grouping based on contributing to a single procedure
- Communicational/Informational Cohesion: Grouping based on data operations or sharing
- Sequential Cohesion: Elements arranged in sequence
- Functional Cohesion: Grouping based on contributing to a single function or task
- Perfect Cohesion: Theoretical ideal of a module consisting of only one element

Coupling Vs Cohesion

Aspect Cohesion Coupling
Definition Degree to which elements in a module are related and serve a unified purpose. Degree of interdependence between software modules or classes.
High Cohesion Methods share commonalities, serve similar purposes, and have a small number of related activities. Low interdependencies, modules encapsulate well-defined functionalities, promoting modularity and maintainability.
Low Cohesion Elements lack a strong, unified purpose, leading to diverse functionalities and scattered related methods. High interdependencies, changes in one module affect others, making the system less flexible and harder to maintain.
Types - Functional Cohesion: Ideal scenario where methods contribute to a single, well-defined function or task.
- Coincidental Cohesion: Arbitrary grouping without logical relationship.
- Logical Cohesion: Grouping based on logical criteria, but not a strong relationship.
- Temporal Cohesion: Grouping based on timing of execution.
- Procedural Cohesion: Grouping based on contributing to a single procedure.
- Communicational/Informational Cohesion: Grouping based on data operations or sharing.
- Sequential Cohesion: Elements arranged in sequence.
- Perfect Cohesion: Theoretical ideal of a module consisting of only one element.
- Tight Coupling: High interdependencies, direct and strong connections between modules or classes.
- Loose Coupling: Flexible, independent interactions through well-defined interfaces, promoting modularity and maintainability.
Advantages - Reduced complexity
- Increased maintainability
- Enhanced reusability
- Modularity
- Reusability
- Maintainability
Disadvantages - Increased complexity
- Reduced maintainability
- Challenges in understanding and modification
- Reduced efficiency
- Reduced scalability
- Increased difficulty in testing and maintenance
Impact Influences various aspects of software quality, such as maintainability, reusability, and understandability. Determines the flexibility, scalability, and maintainability of the software system.

Conclusion

In conclusion, cohesion and coupling are two fundamental principles in software design that play a crucial role in creating robust and maintainable systems.

Cohesion refers to the degree to which elements within a module are related and serve a unified purpose. High cohesion leads to modules that are focused, understandable, and easier to maintain, while low cohesion results in scattered functionality and increased complexity.

Coupling, on the other hand, measures the interdependence between modules or classes. Low coupling promotes modularity, reusability, and maintainability by reducing dependencies between components, while tight coupling leads to fragile systems that are harder to modify and maintain.

By achieving high cohesion and low coupling, developers can design software systems that are easier to understand, test, and evolve over time. These principles contribute to the creation of scalable, flexible, and resilient applications that meet the evolving needs of users and stakeholders.

Get in Touch:

If you have questions, feedback, or suggestions about the content of this article, or if you think there is an inaccuracy that needs to be addressed, please contact me. Your comments are valuable and help improve the quality and accuracy of the information provided.

You can contact me on twitter. to discuss any concerns or insights you may have. I am always open to constructive discussions and welcome the opportunity to work together to improve content for the benefit of all readers.

Thank you for your interest and participation!

Top comments (0)