Coupling and Cohesion


In software engineering we've been taught that coupling should be low and cohesion high. But there is a lot more depth and detail in these two seemingly simple measures of software quality. There are a lot of very informative sources about them around the net. This is a gleaning of some ideas and examples that hopefully makes sense.

Coupling

Definition: The degree to which each program module relies on each one of the other modules.

Layers of coupling
Layers of coupling. (source wikipedia, license cc by-sa 3.0)
Layers of coupling (from high to low)
  • Content: One component uses contents of another 
  • Common:  Share global data
  • External:  Share imposed data format, protocol or device interface
  • Control: Components control the flow of another, by passing it information on what to do
  • Stamp: Share a composite data structure and use only a part of it
  • Data: Share data through, for example, parameters
  • Message
  • Uncoupled

Content Coupling
  • Component directly modifies another’s data
  • e.g. Part of program handles lookup for customer. When customer not found, component adds customer by directly modifying the contents of the data structure containing customer data.
  • Improvement: When customer not found, component calls the AddCustomer() method that is responsible for maintaining customer data.
Common Coupling
  • Two or more modules have read and write access to the same global data
  • Usually a poor design choice because:
    • Lack of clear responsibility for the data
    • Reduces readability
    • Difficult to determine all the components that affect a data element (reduces maintainability)
    • Difficult to reuse components
    • Reduces ability to control data accesses
  • It’s ok if just one module is writing the global data and all other modules have read-only access to it.
  • e.g. Process control component maintains current data about state of operation. Gets data from multiple sources. Supplies data to multiple sinks.
  • Improvement: Data manager component is responsible for data in data store. Processes send data to and request data from data manager.
Control Coupling
  • One module tells another what to do with a control flag.
  • Bad when component must be aware of internal structure and logic of another module (can't be reused)
  • Good if parameters allow factoring and reuse of functionality
  • Acceptable: Module p calls module q and q passes back flag that says it cannot complete the task, then q is passing data
  • Not Acceptable: Module p calls module q and q passes back flag that says it cannot complete the task and, as a result, writes a specific message.
Stamp Coupling:
  • Two modules are stamp coupled if they communicate via a passed data structure that contains more information than necessary for them to perform their functions.
  • Requires second component to know how to manipulate the data structure (e.g., needs to know about implementation)
  • May be necessary due to efficiency factors: this is a choice made by insightful designer, not lazy programmer. 
  • e.g.  Customer Billing System. The print routine of the customer billing accepts a customer data structure as an argument, parses it, and prints the name, address, and billing information.
  • Improvement: The print routine takes the customer name, address, and billing information as an argument.
Data Coupling
  • Modules communicate by passing simple arguments or data structure in which all elements are used
  • Good, if it can be achieved. 
  • Easy to write contracts for this and modify component independently. 

Cohesion

Definition: The degree to which all elements of a component are directed towards a single task and all elements directed towards that task are contained in a single component.
 
Layers of cohesion (from low to high)
  • Coincidental: Arbitrary grouping of elements
  • Logical: Elements are logically categorized to do the same thing
  • Temporal:  Elements of a component are related by execution timing
  • Procedural:  Elements of a component are related only to ensure a particular order of execution
  • Communicational: Parts of a module are grouped because they operate on the same data
  • Sequential:  Output data from one element serves as input data to the next
  • Functional: Parts of a module are grouped because they all contribute to a single well-defined task

Coincidental Cohesion:
  • A module has coincidental cohesion if its elements have no meaningful relationship to one another.
  • Elements needed to achieve some functionality are scattered throughout the system.
  • Worst form. It's bad m'kay?
  • "However, one interesting property of coincidental cohesion is that even though the code in question should not be stuck together, it tends to remain in that state because programmers are too afraid to touch it." [source]
  • e.g. Utilities
Logical Cohesion: [link]
  • A logically cohesive module is one whose elements perform similar activities and in which the activities to be executed are chosen from outside the module (= from the client).
  • e.g.  A component reads inputs from tape, disk, and network. All the code for these functions are in the same component. Operations are related, but the functions are significantly different.
  • Improvement: A device component has a read operation that is overridden by sub-class components. The tape sub-class reads from tape. The disk sub-class reads from disk. The network sub-class reads from the network. 
Temporal Cohesion:
  • A temporally cohesive module is one whose elements are functions that are related in time.
  • Difficult to change because you may have to look at numerous components when a change in a data structure is made.
  • Component unlikely to be reusable.
  • A module called "On_Really_Bad_Failure" that is invoked when a Really_Bad_Failure happens. The module performs several tasks that are not functionally similar or logically related, but all tasks need to happen at the moment when the failure occurs.
  • Improvement: Put the components of the code on where they functionally belong and use a routine to invoke each component on failure.
Procedural Cohesion: [link]
  • A procedurally cohesive module is one whose elements are involved in different activities, but the activities are sequential. 
  • Procedural cohesion is essentially temporal cohesion with the added restriction that all the parts of the module correspond to a related action sequence in the program
  • Actions are still weakly connected and unlikely to be reusable
  • Related to bad control coupling?
  • e.g. Same module reads customer entry from db & sends email if he's overdue.
  • Improvement: Let db module handle reading and mailer module send the email.
Communicational Cohesion: [link]
  • Communicational cohesion occurs when a module performs operations related to a sequence of steps performed in the program (see procedural cohesion) AND all the actions performed by the module are performed on the same data
  • Communicational cohesion is an improvement on procedural cohesion because all the operations are performed on the same data
  • Communicational cohesion isn't common in object-oriented systems since object-oriented designs tend to stress polymorphism.
  • e.g. Stack module: push(), pop(), empty() etc.
  • e.g. Book module: obtain author, title, or price of book from bibliographic record
Sequentially Cohesion:
  • A sequentially cohesive module is one whose functions are relaed such that output data from one function serves as input data to the next function like an assembly line.
  • Occurs naturally in functional programming languages.
  • e.g. Retrieve customer, retrieve customer order, and generate invoice
Functional Cohesion: 
  • A functionally cohesive module is one in which all of the elements contribute to a single, well-defined task. Object-oriented languages tend to support this level of cohesion better than earlier languages do.
  • Reusability:  Modules such as read_file, or draw_graph are more likely to be applicable to another project than one called initialize_data.
  • Fault isolation: If the data is not being read from the file correctly, there is a good chance the error lies in the read_file module/function
  • e.g.  Calculate Net Pay module: calculate taxable deductions, calculate tax, calculate social security deduction

Rule of "one sentence module description" [source]

One way to determine the level of module cohesion is to write a concise sentence that describes the module's functionality. You can usually tell from the sentence structure the level of cohesion. 
  • "Calculate Invoice Total" => Functional
  • "Perform an activity depending on the menu option" => Logical (switch)
  • "Compute minimum, maximum, and average rainfall" => Communicational
  • "Edit all input data" => Procedural
  • "Retrieve and (then) validate employee information" => Sequential
  • "Process various functions depending on the value of the parameters passed" => Coincidental
  • "Validate Customer Details" => Functional
  • "Perform end of day activities" => Temporal
 

    Sources: [1][2][3][4][5][6][7]
    Stathis Fotiadis 21 June 2014

    blog comments powered by Disqus