How can I check arguments in a method from an interface without breaking the DRY principle

128 views Asked by At

I have the following code:

public interface Person {
    /***
     *@Throws Exception x must be greater than 0 ****/
    setAge(int x);
}
public class Man implements Person {
    setAge(int x) {
        if(x <= 0) thrown new Exception("x <= ");
    }
}

I broke the DRY principle because I repeat the check in every single implementation and the documentation repeats it too. What's the best way to check the arguments in this situation?

3

There are 3 answers

0
Makoto On BEST ANSWER

Given that it's an interface, and interfaces in Java 7 and lower can't contain any implementation, then you've got a design decision to make. Do you require the rigidity of the interface, or can you do with an abstract class?

If you can go with an abstract class for this method, then I'd recommend doing so, as it will make implementing (and retrieving) the value you care about a bit simpler.

public abstract class Person {
    protected int age;

    public void setAge(int age) {
        if(0 > age) {
            throw new IllegalArgumentException("Age must be greater than 0");
        }
        this.age = age;
    }
}

With the above implementation, you don't have to implement the method in child classes, and you won't run the risk of repeating yourself.

1
johnathenwhiter94 On

In Java 8 you can use a default method,

interface Person {

    default void setAge(int age) {
        if (age < 0) {
            throw new IllegalArgumentException();
        }
        // ...
    }

}

When Person is implemented the default method is not required to be overridden, it acts as a non-abstract method within an abstract class, that may be something you need to consider before continuing your design.

1
candied_orange On

"Checking arguments" is known as validation. There are many methods of performing validation. Staying DRY while doing so is not easy but it is possible. It's difficult because most designs center around the idea of things going well and validation is about when they go wrong. Often that puts you in the position where validation is a cross cutting concern. That is, your design doesn't center around validation, it's just another chore you have to perform.

One way to achieve validation (and stay DRY) without having to redo your design is to use Aspect Oriented Programming. It is most useful if you are in a situation that can be described with rules like: "Every time any setAge() method is called we need to ensure it's positive". If that rule needs to be on many disparate classes that don't live in any structure that would allow you to unify them (say, by having an Age class) then you might want to look into AOP.