views:

1342

answers:

1

There is a Checkstyle rule DesignForExtension. It says: if you have a public/protected method which is not abstract nor final nor empty it is not "designed for extension". Read the description for this rule on the Checkstyle page for the rationale.

Imagine this case. I have an abstract class which defines some fields and a validate method for those fields:

public abstract class Plant {
    private String roots;
    private String trunk;

    // setters go here

    protected void validate() {
     if (roots == null) throw new IllegalArgumentException("No roots!");
     if (trunk == null) throw new IllegalArgumentException("No trunk!");
    }

    public abstract void grow();
}

I have also a subclass of Plant:

public class Tree extends Plant {
    private List<String> leaves;

    // setters go here

    @Overrides
    protected void validate() {
     super.validate();
     if (leaves == null) throw new IllegalArgumentException("No leaves!");
    }

    public void grow() {
     validate();
     // grow process
    }
}

Following the Checkstyle rule the Plant.validate() method is not designed for extension. But how do I design for extension in this case?

+7  A: 

The rule is complaining because it is possible for a deriving (extending) class to completely replace the functionality you provided without telling you about it. It's a strong indication that you haven't fully considered how the type might be extended. What it wants you to do instead is something like this:

public abstract class Plant {
    private String roots;
    private String trunk;

    // setters go here

    private void validate() {
        if (roots == null) throw new IllegalArgumentException("No roots!");
        if (trunk == null) throw new IllegalArgumentException("No trunk!");
        validateEx();
    }

    protected void validateEx() { }

    public abstract void grow();
}

Note that now someone can still supply their own validation code, but they can't replace your pre-written code. Depending on how you meant to use the validate method you could also make it public final instead.

Joel Coehoorn
I see the point, but I'm still missing a way to implement the validate() method "good" and "practical" at the same time. If Tree implements a final validateEx() and calls validate(), a class extending Tree (lets say Forest) will not be able to override validateEx().Solution?Implement validateExEx()?
Eduard Wirch
Use a better name, then. Maybe ValidateTreeEx().
Joel Coehoorn
Sure - they can't replace your code.. but how can validate() ever get called ?
markt
Doesn't protected final make more sense here..
markt
Maybe - or even final public. But if you'll notice, validate is called by the grow() function. It's part of an internal operation of the class.
Joel Coehoorn