Anda di halaman 1dari 15

Coupling & Cohesion

Sue Evans Press space bar for next slide

Components
A component, at least for sake of this discussion, is a routine or module. In Python a component might be an object / class.
Routines and Modules

A routine is a generic program unit - a function, procedure, or main program.

The quality of routines in a program have a tremendous impact on the reliability of that program.

A module is a collection of objects that are logically related. These may include constants, data types, variables, and program units. (routines)
Modularity and Abstraction

Characteristic of all design methods. Components have clearly defined inputs and outputs, and clearly stated purpose.

Easy to examine each component separately. Organized in a hierarchy so the system can be investigated one level at a time.

Components at one level refine those in the level above. The more abstract top levels hide the details of lower level functional or data components

Information Hiding

Components hide internal details and processing from one another. Each hides a specific design decision. Allows us to isolate complex parts of problem, where "decisions" need to be made.

Possible to use different design methods within different components.

When a hidden design decision changes, only that component must be changed.

The rest of the design remains intact.

Good Design
Characteristics of Good Design

High-quality design leads to quality products 1. Ease of understanding 2. Ease of implementation 3. Ease of testing 4. Ease of modification 5. Correct translation from requirements
Component Independence

Abstraction and Information Hiding allow us to examine ways that components are related. Strive to make components as independent as possible

Easier to understand if not tied to others Easier to modify if independent Easier to isolate and fix problems

Component Coupling

Component coupling is the degree to which components are dependent on one another.

Highly coupled - great deal of dependence between components Loosely coupled - some dependence but interconnections are weak Uncoupled - no interconnections at all
How components are coupled

References from one component to another, such as invocation Amount of data passed from one component to another Amount of control one component has over another Degree of complexity of interface, e.g., one entry point vs. mutual entry points
The Goal is to Minimize Coupling

Enables us to change portion of system while disrupting rest of system as little as possible.

Very low coupling might allow pull-out, plug-in replacement of only one component.

Loose coupling may require changing or replacing a few components. High coupling may require widespread perturbations in system. Low coupling reduces the number of components needing revision.

Types of Coupling

Content: One component directly modifies data or control flow of another

Common: Organizing data into a common store Control: Control flags passed as parameters between components Stamp: Data structures passed Data: Only primitive data passed where Content, Common and Control Coupling are High Coupling. Stamp Coupling is Loose Coupling and Data Coupling is, of course, Low Coupling. The degree of coupling decreases as we go down the list.
Example of Content Coupling:

Python is such a strongly structured language, that it doesn't have goto or it's associated label, so content coupling isn't possible in this language. So the following code doesn't run, but you will get the idea of what content coupling is from it.
def Func1(a): print "In Func1" a += 2 goto F2A return a

def Func2(): print "In Func2" F2A: print "At Func2A"

Example of Common Coupling :

Use and Modification of a Global Variable


globalVar = 0 def Function1(a): if a > 0: globalVar += 1 a = 0 return a

def Function2(): if globalVar > 0: globalVar = 42 else: globalVar = -1

Example of Control Coupling :

Uses a flag to determine what the function will do. This example is from a game of "Naval Battle", where the craft are indicated on the board by a letter in their name. When the user makes a

guess that is a miss, an 'O' is placed on the board in that position. When the user has a hit, the character of the boat is changed from its original letter to an 'X'. When the last original letter for a craft has been hit, a message is printed indicating which craft was hit. Here's a board in play.
linuxserver1.cs.umbc.edu[138] python naval.py 0 1 2 3 4 5 6 7 8 9 ----------------------------------------0 | O | | | | O | | | O | | | ----------------------------------------1 | | O | | | | | | | X | X | ----------------------------------------2 | | | | | | | | | | | ----------------------------------------3 | | | | | | | | | | | ----------------------------------------4 | | | X | X | O | | | O | | | ----------------------------------------5 | | | | | | | | | | | ----------------------------------------6 | | | | | | | | | | | ----------------------------------------7 | | | | | O | | | | | | ----------------------------------------8 | | | | | | | | | | | ----------------------------------------9 | | | | | | | | | | | ----------------------------------------linuxserver1.cs.umbc.edu[139]

Here's the same game after play is done. After 30 moves, the destroyer, cruiser and battleship were sunk. The aircraft carrier was found and partially destroyed, but the sub was not found. We should show the player where the remaining craft were, as well as the shots taken.
0 1 2 3 4 5 6 7 8 9

----------------------------------------0 | O | | | | O | A | | O | | | ----------------------------------------1 | | O | | | | A | | | X | X | ----------------------------------------2 | | | | O | | A | | | | O | ----------------------------------------3 | | | | | | X | | | | O | ----------------------------------------4 | O | X | X | X | O | X | | O | | O | ----------------------------------------5 | | | | | | | | | | O | ----------------------------------------6 | | O | | | | | | | | O | ----------------------------------------7 | S | | | | O | | X | X | X | X | ----------------------------------------8 | S | O | | | | | | | | | ----------------------------------------9 | S | | O | | | O | | | | O | ----------------------------------------linuxserver1.cs.umbc.edu[140]

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.
def printBoard (board, rows, cols, done): print " print " for i in print for j if 0 1 2 3 4 5 6 7 8 9" -----------------------------------------" range(rows): i, in range(cols): done:

print "| %c" % (board[i][j]), else: if board[i][j] == ' ' or board[i][j] == 'O' or board[i][j] == 'X': print "| %c" % (board[i][j]), else: print "| ", print "|" print " -----------------------------------------"

Example of Stamp Coupling :

Stamp Coupling occurs when too much information is passed to a function. As a rule of thumb, never pass a data structure containing many fields to a module that only needs a few. The distinction between data and stamp coupling is not relevant in object-oriented systems. This example is written in C, which is a procedural language. Here we are passing an entire RECTANGLE structure 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; }

Example of Data Coupling :

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.

#define BLACK 0 #define RED 1 #define BLUE 2 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 rect1.width rect1.color rect1.symbol = = = = 7; 6; RED; '#';

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; }

Cohesion
Cohesion is the degree of interrelatedness of internal parts. All of the elements of a component are directed towards and are essential for the same task, ("A function should do one thing, and only one thing"). We should try to MAXIMIZE Cohesion.
Degrees of Cohesion

Coincidental Cohesion: component's parts unrelated Logical Cohesion: logically related tasks and/or data placed in same component

Temporal Cohesion: performs several tasks in sequence, related only by timing (not ordering)

Procedural Cohesion: tasks grouped together to ensure mandatory ordering

Communicational Cohesion: functions operate on or produce the same data set.

Sequential Cohesion: output from one function is input to next.

Functional Cohesion: every processing element is essential to single function, and all such essential elements are contained within one component where the degree of cohesion increases as we go down the list.
How much cohesion?

Functional cohesion should be achieved where ever possible. Communicational and sequential cohesion represent a satisfactory fallback level. Logical, temporal, and procedural cohesion should be reserved for application specific, non-reusable code. Coincidental cohesion should not be used at all.
Example of Coincidental Cohesion

All of the following in one module: Logic to produce student list Logic to produce class grade report Logic to check e-mail Logic to change Unix password
Example of Logical Cohesion
Display time and date on the screen Prompt user for user-id Look up user-id in USER list If found: Prompt for password Validate password Process course enrollment request Else if not found:

do error processing

Example of Temporal Cohesion

Related only by the time they need to be done, i.e. at the beginning of the program
Initialize two arrays Initialize several variables Seed the random number generator Print a greeting

Example of Functional Cohesion

Each in a separate module: Logic to Display Date Logic to Display Time Logic to prompt user for id Logic to Validate User ID Logic to Process Error Condition Logic to process class enrollment request Logic to ... etc.
* Help Contents Restart slide n/m

Anda mungkin juga menyukai