CSC/ECE 517 Fall 2007/wiki2 7 as: Difference between revisions
mNo edit summary |
|||
(28 intermediate revisions by the same user not shown) | |||
Line 54: | Line 54: | ||
== Types of coupling == | == Types of coupling == | ||
=== | === Stamp Coupling === | ||
==== Definition of Stamp Coupling ==== | |||
Stamp coupling occurs between modules when data are passed by parameters using a data structure containing fields which may or may not be used. | |||
*As a rule of thumb, never pass a data structure containing many fields to a module that only needs a few. | |||
*Normally we dont make a distinction between the passing of parameters in an unstructured format (as described under data coupling) and the passing of parameters in a data structure (stamp coupling). The distinction between data and stamp coupling is not relevant in object-oriented systems. | |||
*;Strengths of Stamp Coupling | |||
**It is a loose form of coupling. | |||
**It simplifies interfaces between modules. | |||
*;Weaknesses of Stamp Coupling | |||
**It forces the creation of artificial data structures (i.e., bundling of unrelated data elements together in a structure). Data structures are appropriate as long as the data bundled together is meaningful and related. | |||
==== Example ==== | |||
In this example, we are passing an entire RECTANGLE to each of the functions, even though the function really doesn't need to see or modify all of the members. Written this way, the function must know the names of the members and is also allowed to change any of the members. Each of these functions really should have been written to take primitive types, not the entire RECTANGLE. | |||
<pre> | |||
typedef struct rectangle | |||
{ | |||
int length; | |||
int width; | |||
int area; | |||
int perimeter; | |||
int color; | |||
double diagonal; | |||
char symbol; | |||
} RECTANGLE; | |||
RECTANGLE CalcArea (RECTANGLE r); | |||
RECTANGLE CalcPerimeter (RECTANGLE r); | |||
RECTANGLE CalcDiagonal (RECTANGLE r); | |||
int main() | |||
{ | |||
RECTANGLE rect1; | |||
rect1.length = 7; | |||
rect1.width = 6; | |||
rect1.color = RED; | |||
rect1.symbol = '#'; | |||
rect1 = CalcArea (rect1); | |||
rect1 = CalcPerimeter (rect1); | |||
rect1 = CalcDiagonal (rect1); | |||
printf("For width: %d and length %d\n", | |||
rect1.width, rect1.length); | |||
printf("The area, perimeter and diagonal are\n"); | |||
printf("%d %d %f\n", rect1.area, rect1.perimeter, | |||
rect1.diagonal); | |||
return 0; | |||
} | |||
RECTANGLE CalcArea (RECTANGLE r) | |||
{ | |||
r.area = r.width * r.length; | |||
return r; | |||
} | |||
RECTANGLE CalcPerimeter (RECTANGLE r) | |||
{ | |||
r.perimeter = 2 * r.width + 2 * r.length; | |||
return r; | |||
} | |||
RECTANGLE CalcDiagonal (RECTANGLE r) | |||
{ | |||
r.diagonal = sqrt (r.width * r.width | |||
+ r.length * r.length); | |||
return r; | |||
} | |||
</pre> | |||
=== Data Coupling === | |||
==== Definition of Data Coupling ==== | ==== Definition of Data Coupling ==== | ||
Line 67: | Line 149: | ||
**A module can be difficult to maintain if many data elements are passed. Too many parameters can also indicate that a module has been poorly partitioned. | **A module can be difficult to maintain if many data elements are passed. Too many parameters can also indicate that a module has been poorly partitioned. | ||
=== | ==== Example ==== | ||
==== | This example shows a better way to write the previous program. Here we will be passing and returning only primitive data types. They are all that is really needed by the functions and now the functions are more general, too. | ||
<pre> | |||
typedef struct rectangle | |||
{ | |||
int length; | |||
int width; | |||
int area; | |||
int perimeter; | |||
int color; | |||
double diagonal; | |||
char symbol; | |||
} RECTANGLE; | |||
int CalcArea (int width, int length); | |||
int CalcPerimeter (int width, int length); | |||
double CalcDiagonal (int width, int length); | |||
int main() | |||
{ | |||
RECTANGLE rect1; | |||
rect1.length = 7; | |||
rect1.width = 6; | |||
rect1.color = RED; | |||
rect1.symbol = '#'; | |||
rect1.area = CalcArea(rect1.width, rect1.length); | |||
rect1.perimeter = CalcPerimeter(rect1.width, rect1.length); | |||
rect1.diagonal = CalcDiagonal(rect1.width, rect1.length); | |||
printf("For width: %d and length %d\n", | |||
rect1.width, rect1.length); | |||
printf("The area, perimeter and diagonal are\n"); | |||
printf("%d %d %f\n", rect1.area, rect1.perimeter, | |||
rect1.diagonal); | |||
return 0; | |||
} | |||
int CalcArea (int width, int length) | |||
{ | |||
int area; | |||
area = width * length; | |||
return area; | |||
} | |||
int CalcPerimeter (int width, int length) | |||
{ | |||
int perimeter; | |||
perimeter = 2 * width + 2 * length; | |||
return perimeter; | |||
} | |||
double CalcDiagonal (int width, int length) | |||
{ | |||
double diagonal; | |||
diagonal = sqrt (width * width | |||
+ length * length); | |||
return diagonal; | |||
} | |||
</pre> | |||
=== | === Control Coupling === | ||
==== Definition of Control Coupling ==== | ==== Definition of Control Coupling ==== | ||
Line 96: | Line 238: | ||
**Control flags passed up the hierarchy cause a subordinate module to influence the flow of control in the parent module (i.e., the subordinate module has an affect on a module it does not control). | **Control flags passed up the hierarchy cause a subordinate module to influence the flow of control in the parent module (i.e., the subordinate module has an affect on a module it does not control). | ||
==== Example ==== | |||
Use of a flag to determine what the function will do. | |||
A flag called <I>done</I> is passed into the function. If the game is over, the flag done will be TRUE and the board will be printed differently than if the game is not done. A single function shouldn't have a dual purpose. We should have written two different functions, one to print the board during the game and a different one to show the player where the ships were if he lost. | |||
<pre> | |||
void PrintBoard (char board[ROWS][COLS], int rows, int cols, int done) { | |||
int i, j; | |||
printf(" 0 1 2 3 4 5 6 7 8 9\n"); | |||
printf(" -----------------------------------------\n"); | |||
for(i = 0; i < rows; i++) { | |||
printf("%d ", i); | |||
for(j = 0; j < cols; j++) { | |||
if(done) { | |||
printf("| %c ", board[i][j]); | |||
} else { | |||
if(board[i][j] == ' ' || board[i][j] == 'O' || board[i][j] == 'X') { | |||
printf("| %c ", board[i][j]); | |||
} else { | |||
printf("| "); | |||
} | |||
} | |||
} | |||
printf("|\n"); | |||
printf(" -----------------------------------------\n"); | |||
} | |||
} | |||
</pre> | |||
=== | === Common Coupling === | ||
==== Definition of Common Coupling ==== | ==== Definition of Common Coupling ==== | ||
Line 113: | Line 283: | ||
**It is more difficult to track the modules that access global data when a piece of global data is changed (e.g., a field size is changed). | **It is more difficult to track the modules that access global data when a piece of global data is changed (e.g., a field size is changed). | ||
==== Example ==== | |||
This example illustrates the modification of a global variable. | |||
<pre> | |||
int Function1 (int a) { | |||
if (a > 0) { | |||
myGlobalVar++; | |||
a = 0; | |||
} | |||
return a; | |||
} | |||
void Function2 (void) { | |||
if(myGlobalVar > 0) { | |||
myGlobalVar = 42; | |||
} else { | |||
myGlobalVar = -1; | |||
} | |||
} | |||
</pre> | |||
=== | === Content Coupling === | ||
==== Definition of Content Coupling ==== | ==== Definition of Content Coupling ==== | ||
Line 127: | Line 318: | ||
*Content coupling is the worst level of coupling. Content coupling should never be used when designing modules. | *Content coupling is the worst level of coupling. Content coupling should never be used when designing modules. | ||
< | ==== Example ==== | ||
This example is simple and self explanatory, one function moves the control to another function using a label. (very very bad programming) | |||
<pre> | |||
int Func1 (int a) { | int Func1 (int a) { | ||
printf ("In Func1\n"); | printf ("In Func1\n"); | ||
a += 2; goto F2A; | a += 2; | ||
goto F2A; | |||
return a; | return a; | ||
} void Func2 (void) { | } | ||
void Func2 (void) { | |||
printf("In Func2\n"); | printf("In Func2\n"); | ||
F2A: | F2A: | ||
printf("At Func2A\n"); | printf("At Func2A\n"); | ||
} | } | ||
</ | </pre> | ||
== Determining Coupling Type == | == Determining Coupling Type == | ||
Line 150: | Line 347: | ||
Object coupling is categorized into interface coupling and internal coupling. Interface coupling describes the coupling between an object and objects external to it through a public interface. Internal coupling describes how behaviors within an object interface with each other. | Object coupling is categorized into interface coupling and internal coupling. Interface coupling describes the coupling between an object and objects external to it through a public interface. Internal coupling describes how behaviors within an object interface with each other. | ||
== Types of cohesion == | |||
Cohesion is a qualitative measure meaning that the source code text to be measured is examined using a [[rubric (academic)|rubric]] to determine a cohesion classification. The types of cohesion, in order of the worst to the best type, are as follows: | |||
=== Coincidental cohesion === | |||
==== Definition ==== | |||
This is worst form of cohesion. Coincidental cohesion is when parts of a module are grouped arbitrarily (at random); the parts have no significant relationship (e.g. a module of frequently used mathematical functions). | |||
Common Occurrence: | |||
*Object does not represent any single object-oriented concept | |||
*Collection of commonly used source code as a class inherited via multiple inheritance | |||
==== Example ==== | |||
<pre> | |||
class Something | |||
{ | |||
public static int findPattern( String text, String pattern) | |||
{ // blah} | |||
public static int average( Vector numbers ) | |||
{ // blah} | |||
public static OutputStream openFile( String fileName ) | |||
{ // blah} | |||
} | |||
</pre> | |||
=== Logical cohesion === | |||
==== Definition ==== | |||
Logical cohesion is when parts of a module are grouped because they logically are categorised to do the same thing, even if they are different by nature (e.g. grouping all I/O handling routines). | |||
i.e. Module performs a set of related functions, one of which is selected via function parameter when calling the module | |||
Similar to control coupling | |||
Cure: | |||
Isolate each function into separate operations | |||
==== Example ==== | |||
<pre> | |||
public void sample( int flag ) | |||
{ | |||
switch ( flag ) | |||
{ | |||
case ON: | |||
// bunch of on stuff | |||
break; | |||
case OFF: | |||
// bunch of off stuff | |||
break; | |||
case CLOSE: | |||
// bunch of close stuff | |||
break; | |||
case COLOR: | |||
// bunch of color stuff | |||
break; | |||
} | |||
} | |||
</pre> | |||
=== Temporal cohesion === | |||
==== Definition ==== | |||
Temporal cohesion is when parts of a module are grouped by when they are processed - the parts are processed at a particular time in program execution (e.g. a function which is called after catching an exception which closes open files, creates an error log, and notifies the user). | |||
Elements are grouped into a module because they are all processed within the same limited time period | |||
Common example: | |||
*Constructors/Initialization modules that provide default values for objects | |||
*Destructor/"End of Job" modules that clean up | |||
==== Example ==== | |||
<pre> | |||
procedure initializeData() | |||
{ | |||
font = "times"; | |||
windowSize = "200,400"; | |||
foo.name = "Not Set"; | |||
foo.size = 12; | |||
foo.location = "/usr/local/lib/java"; | |||
} | |||
/* | |||
* A way to do this properly in OOPS is as follows | |||
* Make sure that each object has a constructor and destructor | |||
* | |||
*/ | |||
class foo | |||
{ | |||
public foo() | |||
{ | |||
foo.name = "Not Set"; | |||
foo.size = 12; | |||
foo.location = "/usr/local/lib/java"; | |||
} | |||
} | |||
</pre> | |||
=== Procedural cohesion === | |||
==== Definition ==== | |||
Procedural cohesion is when parts of a module are grouped because they always follow a certain sequence of execution (e.g. a function which checks file permissions and then opens the file). | |||
Associates processing elements on the basis of their procedural or algorithmic relationships | |||
*Procedural modules are application specific | |||
*In context the module seems reasonable, however removed from the context these modules seem strange and very hard to understand | |||
*Can not understand module without understanding the program and the conditions existing when module is called | |||
*This kind of cohesion makes module hard to modify, understand | |||
*This can lead to code duplication. | |||
*Cure: | |||
**Redesign the system, if a module is unnecessary, remove it from objects | |||
==== Example ==== | |||
The following two examples have procedural cohesion, but has code duplication. | |||
<pre> | |||
void printdata () { | |||
//code to fetch data | |||
.... | |||
//code to modify data | |||
.... | |||
//code to print data | |||
.... | |||
} | |||
</pre> | |||
This function appropriately returns data. | |||
<pre> | |||
retType returnData () { | |||
//code to fetch data | |||
.... | |||
//code to modify data | |||
.... | |||
//return data | |||
} | |||
</pre> | |||
=== Communicational cohesion === | |||
==== Definition ==== | |||
Communicational cohesion is when parts of a module are grouped because they operate on the same data (e.g. a module which operates on the same record of information). | |||
*Operations of a module all operate upon the same input data set and/or produce the same output data | |||
*Cure: | |||
**Isolate each element into separate modules | |||
*However good news is that, it rarely occurs in object-oriented systems due to polymorphism | |||
==== Examples ==== | |||
Examples include functions like validation procedures, fetching data from database, displaying information etc.. | |||
=== Sequential cohesion === | |||
==== Definition ==== | |||
Sequential cohesion is when parts of a module are grouped because the output from one part is the input to another part like an assembly line (e.g. a function which reads data from a file and processes the data). | |||
*Sequential association the type in which the output data from one processing element serve as input data for the next processing element | |||
*A module that performs multiple sequential functions where the sequential relationship among all of the functions is implied by the problems or application statement and where there is a data relationship among all of the functions | |||
*Cure: | |||
**Decompose into smaller modules | |||
==== Examples ==== | |||
Examples of activities in a sequentially cohesive module are: | |||
*retrieve customer, retrieve customer order, and generate invoice | |||
*get and edit input data | |||
=== Functional cohesion === | |||
==== Definition ==== | |||
This is the best form of cohesion. Functional cohesion is when parts of a module are grouped because they all contribute to a single well-defined task of the module (e.g. calculating the sine of an angle). | |||
*If the operations of a module can be collectively described as a single specific function in a coherent way, the module has functional cohesion | |||
*In an object-oriented system: | |||
**Each operation in public interface of an object should be functional cohesive | |||
**Each object should represent a single cohesive concept | |||
==== Example ==== | |||
The following are some examples. | |||
*Drag Drop – an event triggered when a dragged object is dropped on a window | |||
*Sum Elements in Array | |||
*Convert Kilometers to Miles | |||
*Read Customer Record | |||
*Calculate Net Pay | |||
*Assign Account Number | |||
== Metrics == | |||
Coupling in Software Engineering <ref name=Pressman>Pressman, Roger S. Ph.D (1982). Software Engineering - A Practitioner's Approach - Fourth Edition. ISBN 0-07-052182-4</ref> describes a version of metrics associated with this concept. | |||
For data and control flow coupling: | |||
d<sub>i</sub> = number of input data parameters | |||
c<sub>i</sub> = number of input control parameters | |||
d<sub>o</sub> = number of output data parameters | |||
c<sub>o</sub> = number of output control parameters | |||
For global coupling: | |||
g<sub>d</sub> = number of global variables used as data | |||
g<sub>c</sub> = number of global variables used as control | |||
For environmental coupling: | |||
<pre> | |||
w = number of modules called (fan-out) | |||
r = number of modules calling the module under consideration (fan-in) | |||
</pre> | |||
Coupling (C) = 1 - 1/(d<sub>i</sub> + 2·c<sub>i</sub> + d<sub>o</sub> + 2·c<sub>o</sub> + g<sub>d</sub> + 2·g<sub>c</sub> + w + r) | |||
"1 - ..." makes the value larger the more coupled the module is. This number ranges from approximately 0.66 (low coupling) to 1.0 (highly coupled). | |||
For example, if a module has only a single input and output data parameter | |||
<pre> | |||
C = 1 - 1/(1+0+1+0+0+0+1+0) = 1 - 1/3 = 0.67 | |||
</pre> | |||
If a module has 5 input and output data parameters, an equal number of control parameters, and accesses 10 items of global data, with a fan-in of 3 and a fan-out of 4, | |||
<pre> | |||
C = 1 - 1/(5 + 2·5 + 5 + 2·5 + 10 + 0 + 3 + 4) = 0.98 | |||
</pre> | |||
For Cohesion: | |||
Data Complexity | |||
D(i) = V(i) / f(i) + 1 | |||
where | |||
*D(i) = data complexity of module i | |||
*V(i) = I/O variables in module i | |||
f(i) = fanout of module i | |||
== Conclusion == | |||
In simple layman words, Coupling is a relationship between conceptswhile Cohesion, on the other hand is a metric reserved for a single concept (or a group of related concepts treated as a whole.) Cohesion is not really about relatedness. Cohesion is also not about completeness. <br> | |||
Cohesion is more about integrity. i.e. Evaluating cohesion is about evaluating the 'Dogness' of the Dog model. or well something like that. | |||
== References == | |||
[1] http://www.ugolandini.net/AccoppiamentoCoesioneE.html. <br> | |||
[2] http://www.cs.unc.edu/~stotts/COMP145/modules.html. <br> | |||
[3] http://javaboutique.internet.com/tutorials/coupcoh/ <br> | |||
[4] http://www.eli.sdsu.edu/courses/spring01/cs635/notes/module/module.html <br> | |||
[5] http://www.informit.com/articles/article.aspx?p=30496&rl=1 <br> | |||
== Further Reading == | |||
[1] http://www.informit.com/articles/article.aspx?p=30496&rl=1 <br> | |||
[2] http://www.kellen.net/Coupling%20and%20Cohesion.htm <br> | |||
[3] http://class.ee.iastate.edu/berleant/home/Courses/SoftwareEngineering/CprE486fall2004/designModularity.htm <br> | |||
[4] http://forums.objectsbydesign.com/showthread.php?threadid=264 <br> | |||
[5] http://forum.java.sun.com/thread.jspa?threadID=5225243&messageID=9916000 <br> | |||
[6] http://corfield.org/blog/index.cfm/do/blog.entry/entry/Coupling_amp_Cohesion__Self_amp_Other <br> | |||
[7] http://www.compoundtheory.com/?action=displayPost&ID=63 <br> | |||
[8] http://www-static.cc.gatech.edu/classes/cs2390_97_summer/lectures/rdd/slide7.html <br> | |||
[9] http://codebetter.com/blogs/jeremy.miller/pages/129542.aspx <br> | |||
[10] http://ieeexplore.ieee.org/Xplore/login.jsp?url=/iel5/9462/30025/01374314.pdf?arnumber=1374314 <br> |
Latest revision as of 02:28, 25 October 2007
Topic
Cohesion and coupling Cohesion and coupling are concepts that are reasonably easy to understand, but nonetheless, it is challenging to find good examples that are succinct. Browse the hundreds of Web pages that attempt to explain these concepts, picking your favorite examples. Many of these pages mention related concepts; list some of them and explain how they relate to cohesion and coupling. Be sure to mention the metrics that can be used to measure how well a program conforms to the principles of high cohesion and low coupling.
Definition
Coupling
Coupling is simply defined as the degree of interdependence between modules or its like a measure of the strength of interconnection of modules or objects.
- The more the connections between one module and the rest, the harder to understand that module, the harder to re-use that module in another situation, the harder it is to isolate failures caused by faults in the module.
- The lower the coupling the “better”.
Cohesion
Cohesion can be described as the extent to which its individual components are needed to perform the same task i.e. how tightly bound or related [a module’s] internal elements are to one another.
- The less tightly bound the internal elements, the more disparate the parts to the module, the harder it is to understand.
- The higher the cohesion the “better”.
- Note
- Low coupling is usually results in high degree of cohesion.
- Some Small Definitions
Module a lexically contiguous sequence of program statements bounded by boundary elements, having an aggregate identifier.
Relationship A relationship exists between one module and another if that module cannot function correctly without the presence of the other.
Low Coupling and High Cohesion with different methods
Assuming the state of an object is the snapshot of its attributes in the time, all methods can belong to one of these three categories:
- Utility: doesn't use or modify object state for ex: Integer.toString(int), Math.cos(double)
- State View: use object state for ex: TextField.getText(), Object.toString()
- State Change: modify object state for ex: Vector.addElement(..), Hashtable.clear()
An utility method can reach the lowest possible coupling:
- takes only input parameters, and only if it needs them to make the output
- returns a value (primitive or handle), or alters objects passed a parameters, and it produces all its output data (it doesn't call other methods)
A State/View method with lowest possible coupling does:
- takes input parameters and uses attributes or methods (class or instance ones) belonging to its class (i.e. in every way but not from class members of others classes, constants excluded)
- returns a value, alters parameters or throws an exception
A State/Change method with lowest possible coupling does:
- takes input parameters and uses attributes or methods (class or instance ones) belonging to its class (i.e. in every way but not from class members of others classes, constants excluded)
- returns a value, alters parameters or throws an exception , or through attributes and methods (class or instance ones) belonging to its class (i.e. in every way but not with class members of others classes)
To get high cohesion, the following are some simple thumb rules
- The method must do only a single conceptual task. Ex: Instance methods, Constructors, wrappers, getter/setter methods.
- A method must not assume the type/values of its parameters and arguments.
Types of coupling
Stamp Coupling
Definition of Stamp Coupling
Stamp coupling occurs between modules when data are passed by parameters using a data structure containing fields which may or may not be used.
- As a rule of thumb, never pass a data structure containing many fields to a module that only needs a few.
- Normally we dont make a distinction between the passing of parameters in an unstructured format (as described under data coupling) and the passing of parameters in a data structure (stamp coupling). The distinction between data and stamp coupling is not relevant in object-oriented systems.
- Strengths of Stamp Coupling
- It is a loose form of coupling.
- It simplifies interfaces between modules.
- Weaknesses of Stamp Coupling
- It forces the creation of artificial data structures (i.e., bundling of unrelated data elements together in a structure). Data structures are appropriate as long as the data bundled together is meaningful and related.
Example
In this example, we are passing an entire RECTANGLE to each of the functions, even though the function really doesn't need to see or modify all of the members. Written this way, the function must know the names of the members and is also allowed to change any of the members. Each of these functions really should have been written to take primitive types, not the entire RECTANGLE.
typedef struct rectangle { int length; int width; int area; int perimeter; int color; double diagonal; char symbol; } RECTANGLE; RECTANGLE CalcArea (RECTANGLE r); RECTANGLE CalcPerimeter (RECTANGLE r); RECTANGLE CalcDiagonal (RECTANGLE r); int main() { RECTANGLE rect1; rect1.length = 7; rect1.width = 6; rect1.color = RED; rect1.symbol = '#'; rect1 = CalcArea (rect1); rect1 = CalcPerimeter (rect1); rect1 = CalcDiagonal (rect1); printf("For width: %d and length %d\n", rect1.width, rect1.length); printf("The area, perimeter and diagonal are\n"); printf("%d %d %f\n", rect1.area, rect1.perimeter, rect1.diagonal); return 0; } RECTANGLE CalcArea (RECTANGLE r) { r.area = r.width * r.length; return r; } RECTANGLE CalcPerimeter (RECTANGLE r) { r.perimeter = 2 * r.width + 2 * r.length; return r; } RECTANGLE CalcDiagonal (RECTANGLE r) { r.diagonal = sqrt (r.width * r.width + r.length * r.length); return r; }
Data Coupling
Definition of Data Coupling
Data coupling occurs between two modules when data are passed by parameters using a simple argument list and every item in the list is used.
- Use data coupling when the argument list is small. As a rule of thumb, limit the argument list to three items.
- Strengths of Data Coupling
- A module sees only the data elements it requires.
- It is the best form of coupling.
- Weakness of Data Coupling
- A module can be difficult to maintain if many data elements are passed. Too many parameters can also indicate that a module has been poorly partitioned.
Example
This example shows a better way to write the previous program. Here we will be passing and returning only primitive data types. They are all that is really needed by the functions and now the functions are more general, too.
typedef struct rectangle { int length; int width; int area; int perimeter; int color; double diagonal; char symbol; } RECTANGLE; int CalcArea (int width, int length); int CalcPerimeter (int width, int length); double CalcDiagonal (int width, int length); int main() { RECTANGLE rect1; rect1.length = 7; rect1.width = 6; rect1.color = RED; rect1.symbol = '#'; rect1.area = CalcArea(rect1.width, rect1.length); rect1.perimeter = CalcPerimeter(rect1.width, rect1.length); rect1.diagonal = CalcDiagonal(rect1.width, rect1.length); printf("For width: %d and length %d\n", rect1.width, rect1.length); printf("The area, perimeter and diagonal are\n"); printf("%d %d %f\n", rect1.area, rect1.perimeter, rect1.diagonal); return 0; } int CalcArea (int width, int length) { int area; area = width * length; return area; } int CalcPerimeter (int width, int length) { int perimeter; perimeter = 2 * width + 2 * length; return perimeter; } double CalcDiagonal (int width, int length) { double diagonal; diagonal = sqrt (width * width + length * length); return diagonal; }
Control Coupling
Definition of Control Coupling
Control coupling occurs between modules when data are passed that influence the internal logic of a module (e.g., flags and switches).
- As a rule of thumb, use descriptive flags (i.e., a flag that describes a situation or condition, such as end-of-file). Do not use control flags.
- Object-Oriented Considerations
- In object-oriented systems, control coupling occurs when an object receives a message from another object and the receiving object responds to the message differently based on control information contained in the message. Another type of control coupling is evident when a method returns control information to an object in responding to a message.
- An example of object-oriented control coupling is a method that returns an error code with a value of zero when no errors are encountered handling a message.
- It only a moderate form of coupling and doesnt affect the quality of the program that much.
- Weaknesses of Control Coupling
- Control flags passed down the hierarchy require the calling program to know about the internals of the called program (i.e., the called program is not a black box).
- Control flags passed up the hierarchy cause a subordinate module to influence the flow of control in the parent module (i.e., the subordinate module has an affect on a module it does not control).
Example
Use of a flag to determine what the function will do.
A flag called done is passed into the function. If the game is over, the flag done will be TRUE and the board will be printed differently than if the game is not done. A single function shouldn't have a dual purpose. We should have written two different functions, one to print the board during the game and a different one to show the player where the ships were if he lost.
void PrintBoard (char board[ROWS][COLS], int rows, int cols, int done) { int i, j; printf(" 0 1 2 3 4 5 6 7 8 9\n"); printf(" -----------------------------------------\n"); for(i = 0; i < rows; i++) { printf("%d ", i); for(j = 0; j < cols; j++) { if(done) { printf("| %c ", board[i][j]); } else { if(board[i][j] == ' ' || board[i][j] == 'O' || board[i][j] == 'X') { printf("| %c ", board[i][j]); } else { printf("| "); } } } printf("|\n"); printf(" -----------------------------------------\n"); } }
Common Coupling
Definition of Common Coupling
Common coupling occurs when modules communicate using global data areas (i.e., universal common data areas). For example, C allows the developer to declare a data element as external, enabling it to be accessed by all modules.
- Common coupling is also known as global coupling.
- Object-Oriented Considerations
- In object-oriented systems, common coupling occurs when an object references a specific external object and has knowledge of the structure and implementation details of the external object. Generally one should avoid the use of data in the public interface of an object. However, it is sometimes necessary for objects to include items other than methods in their public interfaces. In these instances, the general guideline is to use constants rather than variables.
- Weaknesses of Common Coupling
- Modules are very tightly coupled. A fault in one module using global data may show up in another module because global data may be updated by any module at any time.
- Modules referencing global data are tied to specific data names, unlike modules that reference data through parameters. This greatly limits the module's re-usability.
- It may take considerable time for a maintenance programmer to determine what module updated the global data. The more global data used, the more difficult the job becomes to determine how modules obtain their data.
- It is more difficult to track the modules that access global data when a piece of global data is changed (e.g., a field size is changed).
Example
This example illustrates the modification of a global variable.
int Function1 (int a) { if (a > 0) { myGlobalVar++; a = 0; } return a; } void Function2 (void) { if(myGlobalVar > 0) { myGlobalVar = 42; } else { myGlobalVar = -1; } }
Content Coupling
Definition of Content Coupling
Two modules are content coupled if one directly references contents of the other. This can occur when you directly modify an instance variable of a instantiated class without using getter-setter methods. (like using public variables in a class/global variables without appropriate precautions). This should be avoided since any modification of data should be easy to find and easy to understand.
- Generally, only assembler language allows content coupling. Most procedural and object-oriented programming languages make it difficult to implement content coupling.
- Content coupling is also known as pathological coupling.
- Avoid Content Coupling
- Content coupling is the worst level of coupling. Content coupling should never be used when designing modules.
Example
This example is simple and self explanatory, one function moves the control to another function using a label. (very very bad programming)
int Func1 (int a) { printf ("In Func1\n"); a += 2; goto F2A; return a; } void Func2 (void) { printf("In Func2\n"); F2A: printf("At Func2A\n"); }
Determining Coupling Type
When two modules are coupled in more than one way, the coupling type is determined by the worst coupling type. For example, if two modules are data and control coupled, they are described as being control coupled.
Object Coupling
Object-oriented applications are comprised of systems of interacting objects. Objects must be coupled for these interactions to occur. In object-oriented applications, coupling can take place between the object and all objects external to it or coupling can occur among the items (i.e., methods, state, component objects) that comprise an individual object.
Object coupling is categorized into interface coupling and internal coupling. Interface coupling describes the coupling between an object and objects external to it through a public interface. Internal coupling describes how behaviors within an object interface with each other.
Types of cohesion
Cohesion is a qualitative measure meaning that the source code text to be measured is examined using a rubric to determine a cohesion classification. The types of cohesion, in order of the worst to the best type, are as follows:
Coincidental cohesion
Definition
This is worst form of cohesion. Coincidental cohesion is when parts of a module are grouped arbitrarily (at random); the parts have no significant relationship (e.g. a module of frequently used mathematical functions).
Common Occurrence:
- Object does not represent any single object-oriented concept
- Collection of commonly used source code as a class inherited via multiple inheritance
Example
class Something { public static int findPattern( String text, String pattern) { // blah} public static int average( Vector numbers ) { // blah} public static OutputStream openFile( String fileName ) { // blah} }
Logical cohesion
Definition
Logical cohesion is when parts of a module are grouped because they logically are categorised to do the same thing, even if they are different by nature (e.g. grouping all I/O handling routines). i.e. Module performs a set of related functions, one of which is selected via function parameter when calling the module
Similar to control coupling
Cure: Isolate each function into separate operations
Example
public void sample( int flag ) { switch ( flag ) { case ON: // bunch of on stuff break; case OFF: // bunch of off stuff break; case CLOSE: // bunch of close stuff break; case COLOR: // bunch of color stuff break; } }
Temporal cohesion
Definition
Temporal cohesion is when parts of a module are grouped by when they are processed - the parts are processed at a particular time in program execution (e.g. a function which is called after catching an exception which closes open files, creates an error log, and notifies the user).
Elements are grouped into a module because they are all processed within the same limited time period
Common example:
- Constructors/Initialization modules that provide default values for objects
- Destructor/"End of Job" modules that clean up
Example
procedure initializeData() { font = "times"; windowSize = "200,400"; foo.name = "Not Set"; foo.size = 12; foo.location = "/usr/local/lib/java"; } /* * A way to do this properly in OOPS is as follows * Make sure that each object has a constructor and destructor * */ class foo { public foo() { foo.name = "Not Set"; foo.size = 12; foo.location = "/usr/local/lib/java"; } }
Procedural cohesion
Definition
Procedural cohesion is when parts of a module are grouped because they always follow a certain sequence of execution (e.g. a function which checks file permissions and then opens the file).
Associates processing elements on the basis of their procedural or algorithmic relationships
- Procedural modules are application specific
- In context the module seems reasonable, however removed from the context these modules seem strange and very hard to understand
- Can not understand module without understanding the program and the conditions existing when module is called
- This kind of cohesion makes module hard to modify, understand
- This can lead to code duplication.
- Cure:
- Redesign the system, if a module is unnecessary, remove it from objects
Example
The following two examples have procedural cohesion, but has code duplication.
void printdata () { //code to fetch data .... //code to modify data .... //code to print data .... }
This function appropriately returns data.
retType returnData () { //code to fetch data .... //code to modify data .... //return data }
Communicational cohesion
Definition
Communicational cohesion is when parts of a module are grouped because they operate on the same data (e.g. a module which operates on the same record of information).
- Operations of a module all operate upon the same input data set and/or produce the same output data
- Cure:
- Isolate each element into separate modules
- However good news is that, it rarely occurs in object-oriented systems due to polymorphism
Examples
Examples include functions like validation procedures, fetching data from database, displaying information etc..
Sequential cohesion
Definition
Sequential cohesion is when parts of a module are grouped because the output from one part is the input to another part like an assembly line (e.g. a function which reads data from a file and processes the data).
- Sequential association the type in which the output data from one processing element serve as input data for the next processing element
- A module that performs multiple sequential functions where the sequential relationship among all of the functions is implied by the problems or application statement and where there is a data relationship among all of the functions
- Cure:
- Decompose into smaller modules
Examples
Examples of activities in a sequentially cohesive module are:
- retrieve customer, retrieve customer order, and generate invoice
- get and edit input data
Functional cohesion
Definition
This is the best form of cohesion. Functional cohesion is when parts of a module are grouped because they all contribute to a single well-defined task of the module (e.g. calculating the sine of an angle).
- If the operations of a module can be collectively described as a single specific function in a coherent way, the module has functional cohesion
- In an object-oriented system:
- Each operation in public interface of an object should be functional cohesive
- Each object should represent a single cohesive concept
Example
The following are some examples.
- Drag Drop – an event triggered when a dragged object is dropped on a window
- Sum Elements in Array
- Convert Kilometers to Miles
- Read Customer Record
- Calculate Net Pay
- Assign Account Number
Metrics
Coupling in Software Engineering <ref name=Pressman>Pressman, Roger S. Ph.D (1982). Software Engineering - A Practitioner's Approach - Fourth Edition. ISBN 0-07-052182-4</ref> describes a version of metrics associated with this concept.
For data and control flow coupling:
di = number of input data parameters ci = number of input control parameters do = number of output data parameters co = number of output control parameters
For global coupling:
gd = number of global variables used as data gc = number of global variables used as control
For environmental coupling:
w = number of modules called (fan-out) r = number of modules calling the module under consideration (fan-in)
Coupling (C) = 1 - 1/(di + 2·ci + do + 2·co + gd + 2·gc + w + r)
"1 - ..." makes the value larger the more coupled the module is. This number ranges from approximately 0.66 (low coupling) to 1.0 (highly coupled).
For example, if a module has only a single input and output data parameter
C = 1 - 1/(1+0+1+0+0+0+1+0) = 1 - 1/3 = 0.67
If a module has 5 input and output data parameters, an equal number of control parameters, and accesses 10 items of global data, with a fan-in of 3 and a fan-out of 4,
C = 1 - 1/(5 + 2·5 + 5 + 2·5 + 10 + 0 + 3 + 4) = 0.98
For Cohesion:
Data Complexity D(i) = V(i) / f(i) + 1
where
- D(i) = data complexity of module i
- V(i) = I/O variables in module i
f(i) = fanout of module i
Conclusion
In simple layman words, Coupling is a relationship between conceptswhile Cohesion, on the other hand is a metric reserved for a single concept (or a group of related concepts treated as a whole.) Cohesion is not really about relatedness. Cohesion is also not about completeness.
Cohesion is more about integrity. i.e. Evaluating cohesion is about evaluating the 'Dogness' of the Dog model. or well something like that.
References
[1] http://www.ugolandini.net/AccoppiamentoCoesioneE.html.
[2] http://www.cs.unc.edu/~stotts/COMP145/modules.html.
[3] http://javaboutique.internet.com/tutorials/coupcoh/
[4] http://www.eli.sdsu.edu/courses/spring01/cs635/notes/module/module.html
[5] http://www.informit.com/articles/article.aspx?p=30496&rl=1
Further Reading
[1] http://www.informit.com/articles/article.aspx?p=30496&rl=1
[2] http://www.kellen.net/Coupling%20and%20Cohesion.htm
[3] http://class.ee.iastate.edu/berleant/home/Courses/SoftwareEngineering/CprE486fall2004/designModularity.htm
[4] http://forums.objectsbydesign.com/showthread.php?threadid=264
[5] http://forum.java.sun.com/thread.jspa?threadID=5225243&messageID=9916000
[6] http://corfield.org/blog/index.cfm/do/blog.entry/entry/Coupling_amp_Cohesion__Self_amp_Other
[7] http://www.compoundtheory.com/?action=displayPost&ID=63
[8] http://www-static.cc.gatech.edu/classes/cs2390_97_summer/lectures/rdd/slide7.html
[9] http://codebetter.com/blogs/jeremy.miller/pages/129542.aspx
[10] http://ieeexplore.ieee.org/Xplore/login.jsp?url=/iel5/9462/30025/01374314.pdf?arnumber=1374314