Two measures of an effective design decomposition are coupling and cohesion.
The five types of coupling are described below in order from high (bad)
to low (good):
Content coupling: Sometimes called "pathological coupling" cause it is so tweaked. One module refers to the inside of another module (in any way). E.g. changing data inside another module, or making an unconditional branch into another module. Fortunately, modern languages have made the latter nearly impossible, and if you always make your instance data private, then you defeat the former as well.
Common (global) coupling: Several modules refer to a global data area. See below.
"Global variables = death"
This is about the worst design you would ever imagine. It usually results from a functional design approach where the designer became lazy when it came to data design. All the data just got thrown in a big stew pot, and functional modules dip into whatever they want.
Problems with common coupling:
Control coupling: one module passes a piece of information
(a "flag") that is intended to control the internal logic of another module.
Should be avoided, as it means the calling module must know how the logic
of the called module is organized. This usually is a symptom of deeper
design flaws (e.g., improper decomposition).
E.g. Call ProcessTransaction( WhatToDoFlag)
Stamp coupling: one modules passes another a composite piece
of data. This is okay as long as you really use all the data, but
not good if you use only one field out of a large data structure.
E.g., Call MakeMove (ChessBoard, Move) Return NewChessBoard is
okay.
Call CalculateRentalFee(CustomerRecord) Return RentalFee is not, as
CustomerRecord has many fields not used by the module.
Data coupling: Two modules communicate by parameters, each parameter
is an elementary piece of data. This is normal and usually harmless. However,
beware of excessively long parameter lists, and "tramp" data that hitches
a ride through various modules without being used.
E.g. Call CalculateMortgagePayment (Term, InterestRate, AmountBorrowed)
Return RepaymentRate
Type of cohesion | Quality of module |
coincidental | ghastly |
logical | horrible |
temporal | poor |
procedural | OK |
communicational | OK |
sequential | OK |
functional | good |
Coincidental Cohesion: the module performs a set of tasks that
have little or no relation to each other.
Example:
It usually results from improper decomposition, or taking a previously monolithic code and arbitrarily shoveling it into modules.What's wrong with it?
Very hard to understand and maintain.
Makes modules unnecessarily complex, leading to errors during development and unreliable systems.
Logical Cohesion: the module performs multiple tasks that
are related logically or conceptually, or the activities are of the same
general kind.
Example
AddorUpdateStudent: the name indicates the module is doing more than a single task.Example
Why do programmers do this?
It seems to save code, since some tasks will share certain parts of the code. Why should there be a separate routine for each device?What's wrong with it?
Changes in requirements for one task affect code used by all tasks.
The code is often very convoluted, using flags to control logic.
Temporal Cohesion: The module performs a set of tasks that
occur at the same time, but otherwise have nothing in common.
Example: The classic example is an initialization module that carries
out several unrelated functions, such as Open Files, Reset Totals, Print
Headings.
Why do programmers do this?
Everyone does; initialization modules are obvious.What's wrong with it?
If you later need to Print Headings for a new page, you can't do it without Open Files too.
The module is difficult to reuse.
Procedural Cohesion: The module performs a set of tasks that
are different and possibly unrelated except that control flows from one
to the next. Similar to temporal, except that order of processing
matters. The tasks are related by order of execution rather than
by any single problem-related function.
Example
FOR index IN 1 TO 100finds the total of two tables that are unrelated in the original problem.
Add FirstTable(index) to Total1
Add SecondTable(index) to Total2
END FOR
Why do programmers do this?
They are trying to save code. In the above example, they write only one loop instead of two.What's wrong with it?
Difficult to maintain. What happens if SecondTable changes to 120 items?Communicational Cohesion: the module performs a set of tasks that use the same data.
Why do programmers do this?
Once you've got the data, it's tempting to just get everything you need from it all at once.What's wrong with it?
It can lead to maintenance problem, say, if someone wants to find the customer name but not the balance.Sequential Cohesion: the module performs a set of tasks where the results of one task serve as the input to the next. A sequentially cohesive module is like an assembly line.
Sequential code is easy to follow as it has a linear flow to it.What's wrong with it?
Usually nothing. It can lead to maintenance problems, say, if someone wants to format a record they got somewhere else. It's not as reusable as a functional module because the tasks are probably not generally useful to have bundled together.
Functional Cohesion: all the elements of the module contribute
to completing a single problem-related task.It contains all the code and
only the code sufficient to do a specific operation. There are a small
number of parameters, and thus low coupling. The module can be developed
in parallel with other modules.
Examples:
Because they hate rewriting an entire system when there are minor requirements changes.What's wrong with it?
Nothing! This is the smart way to design your modules.