180 likes | 312 Views
CMSC 202. Design Basics: Coupling. Coupling. The degree to which software modules rely upon one another. If module A is coupled to module B, module A has a dependency on module B. For example, if class A below has an instance variable of class type B (composition), A is coupled to B,
E N D
CMSC 202 Design Basics: Coupling
Coupling • The degree to which software modules rely upon one another. • If module A is coupled to module B, module A has a dependency on module B. • For example, if class A below has an instance variable of class type B (composition), • A is coupled to B, • A depends on B, but • B is not coupled to A and • B does not depend on A. public class A { private B b; ... } Class A Class B
Coupling (con’t) • Coupling strength is based on the • quantity of module coupling points, and • the complexity of the coupling points. A A A B B B C C C D E F D E F D E F Low coupling Higher coupling Very high coupling For each example above, what are the concerns when the module C must be modified or replaced?
The Low Coupling Situation This is a “has a” dependency (i.e. composition) public class A { . . . private B bVar = new B( ); private C cVar = new C( ); // instance variable of type C . . . private void aMethod1( ) { . . . int x = cVar.cMethod1( ); // call to a method in class C . . . } // other methods which may call methods in class C } public class C { . . . private D dVar = new D( ); // instance variable of type D private E eVar = new E( ); // instance variable of type E . . . public int cMethod1( ) { // called from class A F fVar = new F( ); . . . // code that uses fVar } // other methods that are called by methods in class A // other methods that call methods in classes D and E } A B C D E F Low coupling • C must be aware of: • Which of its methods are used by class A • What it needs from classes D, E, and F (instance variables and methods) This is a “uses a” dependency
The Very High Coupling Situation It’s now much more complex to make modifications to class C. A B • C must be aware of: • Which of its methods are used by classes A, B, and D • What it needs from classes B, D, E, and F (instance variables and methods) C D E F
Coupling (con’t) • Want weak (loose) coupling • Cannot have zero coupling, so our goals are to • minimize coupling, • weaken (loosen) coupling, and • most importantly, to control coupling. • Every coupling point is intentional. • Every coupling point has a well-defined interface.
So, What’s a Module? • Any “chunk” of a software system or program • program • function • method • class • cluster of functions • cluster of classes • other … • Coupling must be controlled at every level of a software system or program.
Project 1 Design Program Stub Project1 Class CashRegister Class Test Script (Driver) Code that tests Project1 class functionality and error conditions Driver Stub: All code necessary to emulate the CashRegister class interface Driver: All code necessary to fully exercise the CashRegister class (can be a separate class or CashRegister’s main( )
Sample CashRegister Driver (Partial) • public static void main( ) { • // Testing constructor and toString() • System.out.println("***Testing constructor() and toString()***"); • CashRegister cr1 = new CashRegister(); • System.out.println(cr1.toString()); • System.out.println(); • // Testing unlock() and lock() • System.out.println("***Testing lock() and unlock()***"); • CashRegister cr2 = new CashRegister(); • System.out.println(cr2.toString()); // register is locked • System.out.println(); • cr2.unlock(); • System.out.println(cr2.toString()); // register is now unlocked • System.out.println(); • cr2.lock(); • System.out.println(cr2.toString()); // register is locked again • System.out.println();
Sample CashRegister Driver (Partial, con’t) • // Testing removeMoney() • System.out.println("***Testing removeMoney()***"); • CashRegister cr5 = new CashRegister(); • System.out.println(cr5.toString()); // register is locked • cr5.unlock(); // unlock register • System.out.println(cr5.toString()); // register is unlocked • System.out.println("Success = " + cr5.addMoney(5, 6, 7, 8)); // add money • System.out.println(cr5.toString()); // success • System.out.println("Success = " + cr5.removeMoney(-1, 1, 1, 1)); // negative $ • System.out.println(cr5.toString()); // fail • System.out.println("Success = " + cr5.removeMoney(4, 3, 2, 1)); // good $ • System.out.println(cr5.toString()); // success • System.out.println("Success = " + cr5.removeMoney(10, 1, 1, 1)); // too much $ • System.out.println(cr5.toString()); // fail • cr5.lock(); // lock register • System.out.println("Success = " + cr5.removeMoney(1, 1, 1, 1)); // locked • System.out.println(cr5.toString()); // fail • System.out.println(); • } // end main( )
Sample Project1 Stub (Partial) • package proj1; • publicclass CashRegister { • . . . • publicboolean addMoney(int twenties, int tens, int fives, int ones) { • System.out.println(“addMoney called”); • System.out.println(“twenties = “ + twenties); • System.out.println(“tens = “ + tens); • System.out.println(“tens = “ + tens); • return (true); • } • publicboolean removeMoney(int twenties, int tens, int fives, int ones) { • System.out.println(“removeMoney called”); • System.out.println(“twenties = “ + twenties); • System.out.println(“tens = “ + tens); • System.out.println(“tens = “ + tens); • return (true); • } • // other stub methods • }
A More Complex System Design System Stub Application UI D E A B F C One or more classes One or more classes Driver Stub: all code necessary to emulate the application interface Driver: all code necessary to fully exercise the application
An Example from Later This Semester … Game You write this Application UI Controller Class (e.g. Poker) Model Classes Deck Card We write this Hand other classes? So, in this situation, who writes the application interface?
Example 1: Evaluating Coupling • This code is very strongly coupled to any other internal or external code that calls it. • Yes, there is only one coupling point between the caller and someMethod( ). But it is very strong (complex). • The calling code must be aware of the meaning of all flag values. • someMethod must be careful if it adds flag values, deletes flag values, or changes the meaning of any flag values. A Method public void someMethod(int flag) { . . . if (flag == 1) . . . else if (flag == 2) . . . else if (flag == 3) . . . else . . . . . . } Relative to coupling, what’s a better way to implement this code?
Example 1: A Better Solution • Each of these methods is more cohesive than the method on the previous slide. They each perform one specific task. • Yes, the caller needs to know which method to call. But a change to one of these methods will not affect any of the other methods. • If new functionality is needed by the caller, a new corresponding method is written. The calling code then simply tests for the newly added flag value and calls the new method. • The number of coupling points has increased, but each is weak (loose). Replacement Methods public void someMethod1( ) { // method to call if (flag == 1) } public void someMethod2( ) { // method to call if (flag == 2) } . . . public void someMethodN( ) { // method to call if (flag == “N”) }
Example 2: Evaluating Coupling • Once again, this code is very strongly coupled to any other internal or external code that calls it. • Again, the coupling point between the caller and anotherMethod( ) is very strong (complex). • The calling code must be aware of the meaning of all return values. • anotherMethod( ) must be careful if it adds flag conditions, deletes flag conditions, or changes the meaning of any flag conditions. A Method public int anotherMethod( ) { . . . if (condition1) { . . . return (1); } else if (condition2) { . . . return (2); } else if (condition3) { . . . return (3); } else . . . . . . } Relative to coupling, what’s a better way to implement this code?
Example 2: A Better Solution • This one is not as easy to get around. • It’s common for predefined library functions/methods to return flags that may have many values. • If it’s possible to compute the condition to be tested outside of anotherMethod( ), then break up anotherMethod( ) into separate methods. • If the condition to be tested must be computed inside of anotherMethod( ), you just need to deal carefully with the coupling.
Example 3: Evaluating Coupling Problem: Create a program to track students registered for all sections of a course. Course UI (main) But… more coupling! X Better: X X X course.getStudentGPA(studentId) Section Student Transcipt section.getStudentGPA(studentId) student.getTranscript() transcript.getGPA() Date Suppose we want the GPA for a given student. From the UI class, we could: X X X course.getSection(sectionId).getStudent(studentId).getTranscript().getGPA()