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 considered to be
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:
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");
}
Example of Common Coupling :
Use and 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;
}
}
Example of Control Coupling :
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");
}
}
Example of Stamp Coupling :
Stamp Coupling occurs when too much information is passed to a function.
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;
}
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.
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;
}