The Artima Developer Community
Sponsored Link

What's a Method to Do?
How to Maximize Cohesion While Avoiding Explosion
by Bill Venners
First Published in JavaWorld, April 1998

<<  Page 4 of 9  >>

Advertisement

High cohesion
A better design for the CoffeeCup class is to divide remove() into two more methods, neither of which accept control data as input or have parameters that are used only part of the time. Here remove() has been divided into releaseOneSip() and spillEntireContents():

// In Source Packet in file cohesion/ex3/CoffeeCup.java
class CoffeeCup {

    private int innerCoffee;

    public void add(int amount) {
        innerCoffee += amount;
    }

    public int releaseOneSip(int sipSize) {
        int sip = sipSize;
        if (innerCoffee < sipSize) {
            sip = innerCoffee;
        }
        innerCoffee -= sip;
        return sip;
    }

    public int spillEntireContents() {
        int all = innerCoffee;
        innerCoffee = 0;
        return all;
    }
}

As you can see, the process of removing input data used for control yields more methods, each with a more focused functionality. Instead of indicating your wishes to one comprehensive method by passing down a command as a parameter, you call a different method. For example, instead of saying:

// In Source Packet in file cohesion/ex1/Example1.java
class Example1 {

    public static void main(String[] args) {

        CoffeeCup cup = new CoffeeCup();
        // ignore bogus return value of modify() in ADD case
        cup.modify(CoffeeCup.ADD, 355);
        int mlCoffee = cup.modify(CoffeeCup.RELEASE_SIP, 25);
        // 2nd parameter is unused in SPILL case
        mlCoffee += cup.modify(CoffeeCup.SPILL, 0);

        System.out.println("Ml of coffee: " + mlCoffee);
    }
}

You say:

// In Source Packet in file cohesion/ex3/Example3.java
class Example3 {

    public static void main(String[] args) {

        CoffeeCup cup = new CoffeeCup();
        cup.add(355);
        int mlCoffee = cup.releaseOneSip(25);
        mlCoffee += cup.spillEntireContents();

        System.out.println("Ml of coffee: " + mlCoffee);
    }
}

As described earlier, this approach to method design yields code that is easier to understand because each method is responsible for performing one conceptual function, and the method's name can describe that one function. Such code is also easier to understand because the data passed in and out are always used and valid. In this example, add(int), int releaseOneSip(int), and spillEntireContents() are easier to understand at first glance than the int modify(int, int) from the low cohesion example.

In addition, this approach to method design yields code that is more flexible, because it is easier to change one functionality without affecting the others. For example, if you wanted to make some adjustments to the spilling behavior of the coffee cup class with modify(), you would have to edit the body of modify(). Because the code for spilling is intermingled in modify() with the code for sipping and adding, you might inadvertently introduce a bug in the adding behavior when you enhance the spilling behavior. In the CoffeeCup class with separate methods for adding, spilling, and sipping, your chances are better that you can enhance the spilling behavior without disturbing the adding and sipping behaviors.

<<  Page 4 of 9  >>


Sponsored Links



Google
  Web Artima.com   
Copyright © 1996-2017 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use - Advertise with Us