0

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?

Jerome Dahdah
  • 273
  • 2
  • 14
jgleoj23
  • 262
  • 2
  • 9

3 Answers3

1

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.

Makoto
  • 104,088
  • 27
  • 192
  • 230
0

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.

johnathenwhiter94
  • 124
  • 1
  • 3
  • 11
  • You're right, but this feels wrong to me. Default methods were really intended to support functional interfaces, since you can only have one method that didn't have an implementation in a functional interface. My gut feeling is to go with an abstract class, since it conveys intent clearer (and if that's the only method you have in your interface, there's not much gain to having it be an interface). – Makoto Nov 30 '14 at 20:12
0

"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.

Community
  • 1
  • 1
candied_orange
  • 7,036
  • 2
  • 28
  • 62
  • While I'm sure this was not the point of the question, I feel compelled to point out that storing age is rarely a good idea since it changes over time. Far better to store a birth date and calculate age every time it's read. – candied_orange Nov 30 '14 at 07:25