SDSU CS 696: Advanced OO
Spring Semester, 1997
Doc 2 Coupling

To Lecture Notes Index
San Diego State University -- This page last updated Feb 4, 1997
----------

Contents of Doc 2 Coupling

References -- on slide # 1
Coupling -- on slide # 3
...Data Coupling -- on slide # 5
...Control Coupling -- on slide # 12
...Global Data Coupling -- on slide # 16
...Internal Data Coupling -- on slide # 17
...Lexical Content Coupling -- on slide # 18
Object Coupling -- on slide # 19
...Interface Coupling -- on slide # 20
......Object Abstraction Decoupling -- on slide # 21
......Selector Decoupling -- on slide # 23
......Primitive Methods -- on slide # 24
......Constructors -- on slide # 26
......Iterator -- on slide # 29
...Inside Internal Object Coupling -- on slide # 32
...Outside Internal Coupling from Underneath -- on slide # 34
...Outside Internal Coupling from the Side -- on slide # 35


Doc 2 Coupling Slide # 1

References


Object Coupling and Object Cohesion, chapter 7 of Essays on Object-Oriented Software Engineering, Vol 1, Berard, Prentice-Hall, 1993,
Doc 2 Coupling Slide # 2
Quality of Objects
Not all objects are created Equal!

Metrics for quality

Coupling

Strength of interaction between objects in system


Cohesion

Degree to which the tasks performed by a single module are functionally related


Doc 2 Coupling Slide # 3

Coupling

Decomposable system

One or more of the components of a system have no interactions or other interrelationships with any of the other components at the same level of abstraction within the system



A nearly decomposable system

Every component of the system has a direct or indirect interaction or other interrelationship with every other component at the same level of abstraction within the same system



Design Goal

The interaction or other interrelationship between any two components at the same level of abstraction within the system be as weak as possible


Doc 2 Coupling Slide # 4
Coupling


Measure of the interdependence among modules

"Unnecessary object coupling needlessly decreases the reusability of the coupled objects"

"Unnecessary object coupling also increases the chances of system corruption when changes are made to one or more of the coupled objects"


Types of Modular Coupling
In order of desirability

Data Coupling (weakest ­ most desirable)

Control Coupling

Global Data Coupling

Internal Data Coupling (strongest ­ least desirable)

Content Coupling (Unrated)


Doc 2 Coupling Slide # 5
Modular Coupling

Data Coupling



Output from one module is the input to another

Using parameter lists to pass items between routines


Common Object Occurrence:

Object A passes object X to object B

Object X and B are coupled

A change to X's interface may require a change to B

Example

class Receiver
     {
     public void message( MyType X )
          {
          // code goes here
          X.doSomethingForMe( Object data );
          // more code
          }
     }

Doc 2 Coupling Slide # 6
Modular Coupling
Data Coupling

Major Problem

Object A passes object X to object B

X is a compound object

Object B must extract component object Y out of X

B, X, internal representation of X, and Y are coupled


Example: Sorting student records, by ID, by Name

class StudentRecord
     {
     String name;
     Long ID;
     
     public String getName()
          { return name; }

     // etc.
     }

SortedList cs696 = new SortedList();
StudentRecord newStudent;
//etc.
cs696.add ( newStudent );

Doc 2 Coupling Slide # 7
Solution 1
Bad News

class SortedList
     {
     Object[] sortedElements = new Object[ properSize ];

     public void add( StudentRecord X )
          {
          // coded not shown
          Long IDa = X.getID();
          Long IDb = sortedElements[ K ].getID();
          if ( IDa < IDb )
               // do something
          else
               // do something else
          }
     }


Doc 2 Coupling Slide # 8
Solution 2
Send message to object to compare self

class SortedList
     {
     Object[] sortedElements = new Object[ properSize ];

     public void add( StudentRecord X )
          {
          // coded not shown
          if ( X.lessthan( sortedElements[ K ] ) )
               // do something
          else
               // do something else
          }
     }



Doc 2 Coupling Slide # 9
Solution 3 Interfaces or "required operations"

Interface Comparable
     {
     public boolean lessThan( Object compareMe ); 
     public boolean greaterThan( Object compareMe ); 
     public boolean equal( Object compareMe ); 
     }

class StudentRecord implements Comparable
     {
     public boolean lessThan( Object compareMe )
          {
          // compare student record to object compareMe
          }
     }

class SortedList
     {
     Object[] sortedElements = new Object[ properSize ];

     public void add( Comparable X )
          {
          // coded not shown
          if ( X.lessthan( sortedElements[ K ] )
               // do something
          else
               // do something else
          }
     }


Doc 2 Coupling Slide # 10
Solution
4 Function Pointers
Code is neither C/C++ nor Java
typedef int (*compareFun ) ( StudentRecord, StudentRecord ); class SortedList { StudentRecord[] sortedElements = new StudentRecord[ properSize ]; int (*compare ) ( StudentRecord, StudentRecord ); public setCompare( compairFun newCompare ) { compare = newCompare; } public void add( StudentRecord X ) { // coded not shown if ( compare( X, sortedElements[ K ] ) ) // code not shown } }

int compareID( StudentRecord a, StudentRecord b )
     { // code not shown }

int compareName( StudentRecord a, StudentRecord b )
     { // code not shown }
SortedList myList = new SortedList();
myList.setCompair( compareID );

Doc 2 Coupling Slide # 11
Solution 5 Function Pointers using generic types


typedef int (*compairFun ) ( <type>, <type> );


Doc 2 Coupling Slide # 12
Modular Coupling

Control Coupling


Passing control flags between modules so that one module controls the sequencing of the processing steps in another module

Common Object Occurrences:

€ A sends a message to B

B uses a parameter of the message to decide what to do

class Lamp {
     public static final ON = 0;

     public void setLamp( int setting ) {
          if ( setting == ON )
               //turn light on
          else if ( setting == 1 )
               // turn light off
          else if ( setting == 2 )
               // blink
     }
}
Lamp reading = new Lamp();
reading.setLamp( Lamp.ON );
reading.setLamp)( 2 );



Doc 2 Coupling Slide # 13
Cure:
Decompose the operation into multiple primitive operations



class Lamp {

     public void on() {//turn light on }
     public void off() {//turn light off }
     public void blink() {//blink }
}


Lamp reading = new Lamp();
reading.on();
reading.blink();


Doc 2 Coupling Slide # 14
Control Coupling

Common Object Occurrences:

€ A sends a message to B

B returns control information to A

Example: Returning error codes

Cure:
Use exceptions

class Test {
     public int printFile( File toPrint ) {
          if ( toPrint is corrupted )
               return CORRUPTFLAG;
          blah blah blah
     }
}


Test when = new Test();
int result =  when.printFile( popQuiz );
if ( result == CORRUPTFLAG )
     blah
else if ( result == -243 )

Doc 2 Coupling Slide # 15
Using Exceptions
class Test 
{
     public int printFile( File toPrint ) throws PrintExeception
     {
          if ( toPrint is corrupted )
               throws new PrintExeception();
          blah blah blah
     }
}

try
{

     Test when = new Test();
     when.printFile( popQuiz );
}
catch ( PrintException printError )
{
do something
}



Doc 2 Coupling Slide # 16
Modular Coupling

Global Data Coupling


Two or more modules share the same global data structures

Common Object Occurrence:

A method in one object makes a specific reference to a specific external object

A method in one object makes a specific reference to a specific external object, and to one or more specific methods in the interface to that external object

A component of an object-oriented system has a public interface which consists of items whose values remain constant throughout execution, and whose underlying structures/implementations are hidden

A component of an object-oriented system has a public interface which consists of items whose values remain constant throughout execution, and whose underlying structures/implementations are not hidden

A component of an object-oriented system has a public interface which consists of items whose values do not remain constant throughout execution, and whose underlying structures/implementations are hidden

A component of an object-oriented system has a public interface which consists of items whose values do not remain constant throughout execution, and whose underlying structures/implementations are not hidden


Doc 2 Coupling Slide # 17

Internal Data Coupling


One module directly modifies local data of another module

Common Object Occurrence:

C++ Friends


Doc 2 Coupling Slide # 18
Modular Coupling

Lexical Content Coupling



Some or all of the contents of one module are included in the contents of another


Common Object Occurrence:

C/C++ header files



Decrease coupling by:

Restrict what goes in header file

C++ header files should contain only class interface specifications


Doc 2 Coupling Slide # 19

Object Coupling

Object Coupling diagram

Coupling measures the strength of the physical relationships among the items that comprise an object

Cohesion measures the logical relationship among the items that comprise an object

Interface coupling is the coupling between an object and all objects external to it. Interface coupling is the most desirable form of object coupling. Internal coupling is coupling among the items that make up an object.


Doc 2 Coupling Slide # 20
Object Coupling

Interface Coupling


Interface coupling occurs when one object refers to another specific object, and the original object makes direct references to one or more items in the specific object's public interface

Includes module coupling already covered

Weakest form of object coupling, but has wide variation

Sub-topics

Object abstraction decoupling
Selector decoupling
Constructor decoupling
Iterator decoupling


Doc 2 Coupling Slide # 21

Object Abstraction Decoupling


Assumptions that one object makes about a category of other objects are isolated

Example: List items

C++ Example
class LinkedListCell
     {
     int cellItem;
     LinkedListCell* next;

     // code can now use fact that cellItem is an int
     if ( cellItem == 5 ) print( "We Win" );
     }

template <class type>
class LinkedListCell#2
     {
     type cellItem;
     LinkedListCell* next;

     // code does not know the type, it is just a cell item,
     // it becomes an abstraction
     }


Doc 2 Coupling Slide # 22
Java Example

class LinkedListCellA
     {
     int cellItem;          
     LinkedListCell* next;

     if ( cellItem == 5 ) print( "We Win" );
     }

class LinkedListCellB
     {
     Object cellItem;          
     LinkedListCell* next;

     if ( cellItem.equals( "hi" ) ) print( "We Win" );
     }

interface ListItem
     {
     public operation1();
public operation2();
     }

class LinkedListCellC
     {
     ListItem cellItem;          
     LinkedListCell* next;

     if ( cellItem.operation1() ) print( "We Win" );
     }

Doc 2 Coupling Slide # 23

Selector Decoupling


Example
: Counter object

class Counter
     {

     int count = 0;

     public void increment()      {  count++; }
     public void reset()      { count = 0; }
     public void display()      {
          code to display the counter
     }

Display of Counter
Display of Counter

"display" couples the counter object to an output object

The counter class is nearly useless do to this coupling

Better Counter Class
class Counter
     {
     int count = 0;

     public void increment()      {  count++; }
     public void reset()      { count = 0; }
     public String toString()      {return String.valueOf( count );}
     }
Doc 2 Coupling Slide # 24

Primitive Methods
A primitive method is any method that cannot be implemented simply, efficiently, and reliably without knowledge of the underlying implementation of the object

Primitive methods are:

functionally cohesive, they perform a single specific function

small, seldom exceed five "lines of code"

A composite method is any method constructed from two or more primitive methods ­ sometimes from different objects

Types of Primitive Operations

Selectors (get operations)

Constructors (not the same as class constructors)

Iterators


Doc 2 Coupling Slide # 25
Selectors

Selectors
are encapsulated operations which return state information about their encapsulated object and do not alter the state of their encapsulated object

Replacing

     public void display()      {
          code to display the counter
     }

with

public String toString()      {return String.valueOf( count );}

is an example of Selector decoupling.

By replacing a composite method (display) with a primitive method the Counter class is decoupled from the display device

This makes the Counter class far more useful

It also moves the responsibility of displaying the counter else where


Doc 2 Coupling Slide # 26

Constructors


Operations that construct a new, or altered version of an object

class Calendar
     {

     public void getMonth( from where, or what)
          {
          }
     }

class Calendar
     {

     public static Calendar fromString( String date )
          {
          }
     }

Doc 2 Coupling Slide # 27
Primitive Objects

Primitive objects are objects that are both:


Primitive objects don't count in coupling with other objects

"
An object that refers to itself and to primitive objects is considered for all intents and purposes, totally decoupled from other object"


Doc 2 Coupling Slide # 28
Composite Object

Object conceptually composed of two or more objects



Heterogeneous Composite Object

Object conceptually composed from objects which are not all conceptually the same

class Date
     {
     int year;
     int month;
     int day;
     }

Homogeneous Composite Object

Object conceptually composed from objects which are not all conceptually the same

list of names - each item is a member of the same general category of object
Doc 2 Coupling Slide # 29

Iterator

Allows the user to visit all the nodes in a homogeneous composite object and to perform some user-supplied operation at each node

     List grades = new List();

     // add some grades 

     while ( grades.nextpointer != null )
          {
          grades = grades.nextpointer^;
          print( grades.examName )
          }

or

     for ( int k = 0; k < grades.length(); k++ )
          print( grades.getExamNameAt( k ) );


Doc 2 Coupling Slide # 30
Passive Iterator

class List
     {
     Object[] listElements = new Object[ size ];

     public void do( Function userOperation )
          {
          for ( int k = 0; k < listElements.length(); k++ )
               userOperation( listElements[ k ] );
          }
     }

In Main


     List grades = new List();

     aFunction = ( item ){ print( item ) };

     grades.do ( aFunction );


Doc 2 Coupling Slide # 31
Active Iterator

List grades = new List();

Enumeration gradeList = grades.elements();

while ( gradeList.hasMoreElements() )
     {
     listItem = gradeList.nextElement();
     print ( listItem );
     }

Java Enumerations

public interface Enumeration {
    /**
     * Returns true if the enumeration contains more elements; false
     * if its empty.
     */
    boolean hasMoreElements();

    /**
     * Returns the next element of the enumeration. Calls to this
     * method will enumerate successive elements.
     */
    Object nextElement();

Doc 2 Coupling Slide # 32

Inside Internal Object Coupling

Coupling between state and operations of an object


The big issue: Accessing state

Changing the structure of the state of an object requires changing all operations that access the state including operations in subclasses

Solution: Access state via access operations

C++ implementation
Provide private functions to access and change each data member

Simple Cases:

One function to access the value of the date member

One function to change the value of the data member

Only these two functions can access the data member


Doc 2 Coupling Slide # 33
Accessing State
C++ Example


class Counter
{
public:
     void increment(void);

private:
     int  value;
     
     void  setValue(int newValue);

     int  getValue(void);
};

void Counter::increment(void)    //Increase counter by one
{
     setValue(getValue() + 1);
};

void Counter::setValue(int newValue)
{
     value = newValue;
};

int Counter::getValue
{
     return value;
};

Doc 2 Coupling Slide # 34

Outside Internal Coupling from Underneath


Coupling between a class and subclass involving private state and private operations


Major Issues:

€ Access to inherited state

Direct access to inherited state

See inside internal object coupling

Access via operations

Inherited operations may not be sufficient set of operations to access state for subclass


€ Unwanted Inheritance

Parent class may have operations and state not needed by subclass

Unwanted inheritance makes the subclass unnecessarily complex. This reduces understandability and reliability.


Doc 2 Coupling Slide # 35

Outside Internal Coupling from the Side


Class A accesses the private state or private operations of class B

Class A and B are not related via inheritance


Main causes:

Using nonobject-oriented languages

Special language "features"

C++ friends


Donald Knuth

"First create a solution using sound software engineering techniques, then if needed, introduce small violations of good software engineering principles for efficiency's sake."


Doc 2 Coupling Slide # 36
Type and Inheritance

Type is a set of values and a set of operations that act on those values

integer, float, string, boolean

Classes define structures

methods
internal state information
exportable constants
etc.

Smalltalk has classes but no type

C++ tightly couples the type hierarchy with the class hierarchy

That is a user defined type A can be a subtype of B if and only if A is a subclass of B
----------