What makes a module a
good module?
High cohesion
and low coupling
First, let's discuss
these as general concepts
. . .applicable to software, cars, teams, . . .
Then, examine some
technical details
. . .different kinds of cohesion and coupling . . .
. . .their names . . .and the fact that
. . .some are better than others
![]()
![]()
First, Coupling
What is
coupling?
. . . how much modules
communicate
"Coupling is the degree
of interaction between two modules"
- Schach
Question:
Should coupling be minimized or maximized in a software design?
![]()
![]()
Coupling in Software, Cars,
. . .
Which of these have high
coupling? Low coupling?
Two cooked
strands of spaghetti with no oil
Two cooked
strands of spaghetti, coated with green, aromatic, expensive olive oil
Two loops,
one executing after the other is done
Two loops,
one nested in the other
A car tire
and the metal wheel it is on
A car tire/wheel assembly
and the engine
A car tire
and a road covered with beer bottles
Two methods that operate
on the same array of robots
Two
methods; one calls the other with no arguments
Two
classes with all public member variables and methods
Two
classses with mostly private members
Cereal+milk+bowl --> low coupling
A two-cracker sandwich
with peanut butter
A package of loose
crackers
High coupling means weak
module boundaries
Low coupling means strong
module boundaries
One design criterion:
minimize coupling
![]()
![]()
Cohesion in
Cars, Software, Crackers . . .
Cohesion describes how
well the contents of a module cohere (stick together)
Peanut butter cracker
sandwich has high cohesion
Cheese cracker sandwich
has low cohesion
"Cohesion is the degree
of interaction within a module"
- Schach (bolding added)
Question: should a design
goal be low cohesion or high cohesion?
![]()
![]()
Examples of
Cohesion, High and Low
Which of the following
have high cohesion?
Which have low cohesion?
A car
A sealed
box containing all the parts of a car
A method
with an integer argument N, which
contains error messages and
prints out error #N when N is passed to it
A method
with nested loops
A method
with loops; one runs, then the other runs
A class in
which every method contains
a call to at least one other method in the same class
A class in
which
no method calls any other method in that class
A handful
of uncooked spaghetti
A pot of
cooking spaghetti
A handful of cooked spaghetti in which
the cook did not stir in oil after draining the water
A handful of cooked
spaghetti in which
the cook did stir in oil after draining the water
A peanut butter cracker
sandwich
A cheese
cracker sandwich
Review Q: should one
design for high or low cohesion?
![]()
![]()
Cohesion and Coupling:
Summary and Cliffhanger
High cohesion and low
coupling are good
They support code
reuse
They support
maintenance
They support design
change
A design
criterion:
Maximize
cohesion
(by using good kinds of cohesion)
Another design
criterion:
Minimize
coupling
(by using good kinds of coupling)
![]()
Varieties of Module Coupling
Different kinds, from
worst to best...
Content
coupling (Bad, avoid it!)
Common
coupling (Pretty bad!)
Control
coupling (Not great, not terrible)
Stamp
coupling (Pretty good!)
Data
coupling (Good! Seek it!)
![]()
![]()
Varieties of Module Coupling
- Some Details
Different kinds, from
worst to best...
Worst to best models how to think about your modules:
"Here's a module concept -
How can it be improved?"
So, for each coupling type...
we will see how it can be improved
Content
coupling (Bad! Avoid it!)
One module
refers directly to part of another
Example:
A module changes a statement in another module
Example:
A module refers to data by offset in another module
It's easy to content
couple modules in assembly language
This is one reason why high level languages are better
(e.g. programmers do more with less effort)
Why is
content coupling so bad?
- Maintenance on the called module
may require
maintenance on the calling module too
- Can't reuse calling module without including the called one
"they are
inextricably linked" - Schach
They can hardly be
considered separate modules at all!
Can you do this in
Java?
Can one distinguish between
"read content coupling" and "write content coupling?
Which is better? worse?
Common
coupling (bad, but not quite as bad!)
Both modules
share same data
See Schach
Figure 7.10 (5th ed.)/6.10 (4th)
Problems:
Hard for programmers to see how they interact
Changing one module likely requires changing other(s)
Example:
the trafficLight classes
If color is public - common coupling
If color is private - better
Not very reusable -- module is tied into overall program
Example:
Replacing an automobile engine
Has security problems:
seeing unauthorized data
A malicious module could
see/do destructive things to the data
Let's break it down
into subcategories
1. Global common coupling
- common coupling using global data
2. Non-global common coupling
- local data is accessible from outside
A. Read common coupling
- read-only common coupling
B. Write common coupling
- common coupling with read+write
Which is better, 1 or 2? A or B?
Which does Java prevent (1,2,A,B)?
Control
coupling (not great, but not terrible)
One module
controls decisions made by other module
Example:
see a structure diagram (Schach Figure 13.4/12.4)
Example:
a control flag is passed from one module to another
- Remember the module that takes an integer arg and
prints the corresponding error message?
Example:
cout << hex; in C++
Problem: one
module must know too much about the other
(i.e. its internal logic and structure)
Hard to reuse such
modules
Example:
a module that calls the error printer with a number
Why is the caller not
very reusable?
Why is the called module not very reusable?
Which is more reusable?
Is calling a method in
another object control coupling?
Does Java allow control coupling?
Could this be fixed?
Stamp
coupling (good, but not the best)
Modules pass
data structures but only use parts of them
Problem:
harder to understand what the modules do
...because the unused parts confuse
Problem: easy
for modules to accidentally mess up data
Problem: malicious data
access/modification
Example: passing a
pointer in C
Everything the pointer points to is now accessible!
Does Java allow stamp
coupling?
Could this be fixed?
Would it be good to fix?
Data
coupling (The best! Use it!)
Modules
communicate only data which is used
Considered
the best kind of coupling
Why? Because problems
mentioned earlier are absent
Why? Changes to one are
less likely to affect another
...makes maintenance easier
Design with data
coupling as much as possible!
![]()
![]()
"Cohesion": Peanut Butter
has it and Modules Should
Cohesion: "tendency to
stick together"
Software module: its
parts work together
Error message writing
module has low cohesion
trafficLight class has
high cohesion
(why?)
![]()
![]()
Coincidental cohesion
(Bad!)
Logical
cohesion
Temporal
cohesion
Procedural
cohesion
Communicational
cohesion
Informational
cohesion
Functional cohesion
(Good!)
![]()
Coincidental Cohesion
(bad)
"coincidental"
--
"characterized by"
"...accidental...
occurrence of events..."
- (Webster's, 2nd college edition)
"A module has coincidental
cohesion if
it performs multiple,
completely unrelated actions" (Schach p. 171/175)
Example:
multiply args 2 & 3,
print arg 4,
search for string arg5 in passage arg 6
Pretty stupid module!
Why would
anyone write it?
. . . when strict module
size standards are forced on programmers
. . . then they collect
pieces of "too-long" modules into
new modules with coincidental cohesion
Why is coincidental cohesion
bad?
- low reusability
(why?)
- low maintainability
(why?)
- to fix, break apart module
into smaller modules
![]()
Logical Cohesion (pretty
bad)
Example: A module that
prints error messages
Its integer arg determines
which error to print
In logical cohesion the
module can do various things
The things are all
related
The caller determines
which one is done
(Is this control coupling?)
Another example: see Fig.
7.5/6.5.
One problem: interface is
obscure
(what value of N to pass?)
Another
problem:
"intertwining" of code can occur
Example:
Error message module that also
outputs recommended user action.
Improving recommendation for one error risks
improving it for other errors (good)
making it worse for other errors (bad).
May need to "deintertwine" the code
![]()
![]()
Temporal Cohesion (kind
of bad)
"performs a series of
actions related in time" (section 7.2.3/6.2.3)
Example: an
init()
function
The actions relate to
other modules more than to each other
Another
example?
a deinit()
module
Problem: not
reusable
Problem: maintenance
headaches
Every time you
make a change to another module you have to fix init()
Every time you make a
change to init() you have to fix another module too
Does Java allow temporal
cohesion?
Does Java support efforts
to avoid temporal cohesion?
![]()
![]()
Procedural Cohesion
(middling)
Module does a number of
actions that form a sequence
(must be done in order)
Example:
read in zip code, then
look up postage
Example:
read part_number from database
update
repair_record on maintenance file
Problem:
internal connectivity is better, but still low
Problem: poor
reusability
But better than
temporal cohesion
Solution:
break each action into its own module
Supported by
Java?
![]()
![]()
Communicational Cohesion
(getting better)
Like procedural cohesion,
but on same data
"Procedural cohesion
++"
all steps operate on the same data
Example: Update record, then
update the log file
Example: Read in postage as
float, then convert to cents
Better, but still not
particularly reusable
Solution: break each action
into own module
Is communicational cohesion
supported by Java?
![]()
![]()
Functional Cohesion
(good!)
"Performs exactly one
action or achieves a single goal" (Schach Sec. 7.2.6/6.2.6)
Example: return square
root
Highly reusable: e.g. can
be sold in libraries
Module is relatively easy
to understand
Since you know what it
does
Maintainable because it
makes fault location easier and is more understandable
![]()
![]()
Information Cohesion
(
Does several
things
Each thing has its own
point of entry
Code of each thing is
independent
All things act on the
same data structure
What if each thing is in
its own module?
(Good idea?)
Example: See
Schach Fig. 7.6/ 6.6
What's the
difference compared to logical cohesion?
Note: this is
"essentially... an abstract data type"
(Schach sec. 7.2.7/6.2.7)
Suppose there
are several classes derived from a base class Better to
have one method definition in the base or several identical ones in the
derived classes? Why or why
not?
Good or bad: put
the method in a class closer to the base class than the data it
operates on? Why/why
not?
Is it also essentially
a
There are different
kinds of cohesion in software
(from worst to best kind, again . . .
)
Coincidental
cohesion
Unrelated
statements bundled together in a method
Hard to
understand what it does
Can't be
reused in another program later
Solution:
break it into smaller modules
Logical
cohesion
Does any of
several different related things
Confusing
interface, since some parameters are needed only sometimes
Better than
coincidental cohesion, but not great
Temporal
cohesion
Method does
diverse things, but they happen at the same time
Example: a
typical init( ); call
Problem: Not
very reusable in other programs
Procedural
cohesion
method does
things that have to be done in order
Example: read
in destination zip code, then look up postage
Better, but
still not very reusable
Communicational
cohesion
Like
procedural cohesion, but on same data
Example: Read
in postage as float, then convert to cents
Better, but
still not particularly reusable
Informational
cohesion
Can do
several different things on same data
Example: A
C++ class with various methods
Considered a
good kind of cohesion
Functional
cohesion
Does exactly
one thing or achieves one goal
Example 1:
sort
Example 2:
convert postage amount to number & denomination of stamps
Considered
good. Module is reusable.
![]()
![]()
Cohesion vs. Coupling:
Summary
Cohesion describes the
contents of a module
Coupling describes how
modules interact
(how they are
coupled)
High coupling means weak
module boundaries
Low coupling means strong
module boundaries
Design criterion:
minimize coupling