4

In a code base I am "starting from" there are a handful of interfaces with many default methods. They look something like this:

public interface HasXY {
   double getX();
   double getY();
   default double method1(double x, double y)  {...}
   default double method1(HasXY other)  {...}
   default double method2(double x, double y)  {...}
   default double method2(HasXY other)  {...}
   default double method3(double x, double y)  {...}
   default double method3(HasXY other)  {...}
   default double method4(double value)  {...}
   default double method5(double value)  {...}
}

At this time I have the option to refactor this code into an interface and a class. The outcome of this refactor will look somewhat like this:

public interface HasXY {
    XYPosition getXY();
}

public class XYPosition {
   double method1(double x, double y)  {...}
   double method1(XYPosition other)  {...}
   double method2(double x, double y)  {...}
   double method2(XYPosition other)  {...}
   double method3(XYPosition other)  {...}
   double method4(double value)  {...}
   double method5(double value)  {...}
}

I should note that the "source" code-base has several such interfaces and many classes implement a handful of these interfaces (leading to object that have many many methods). I am also at a unique moment in time where doing this refactor will be as easy as it ever will.

What are your thoughts on such a refactor? Is it a slam dunk "should do"? Do you think its a waste of time? Is it actually harmful because lose the succinct-ness of calling "myObject.methodFromOneOfSeveralDifferentInterfaces()"

  • 1
    What are your use cases for these classes? How do you define a "successful" design? Please read: Are Design Review questions on-topic? – user22815 Sep 13 '16 at 17:06
  • @Snowman -- This question is "general" because it is about the "correctness" of widespread use of default methods in interface. This question focuses on the case where classes are likely to implement multiple interfaces that each provide 20+ default methods. In this case, is your code "succinct" because you can "call anything" or confusing because SRP is slipping a bit. (i.e. is composition by default methods good?) – Ivan Sep 13 '16 at 17:34
5

The intention of the refactor is good. It takes verbosity out of implementors and bundle XYPosition-related methods to its own class, similar to what we do with parameter objets to avoid functions with a lot of paremeters. You are complying with the Interface Segregation Principle that states that clients should not know about methods they don't need or use.

But an interface (an abstraction) should not depend on a concretion (a non-abstract class). Both abstraction and concretions should depend on abstractions. This is called the Dependency Inversion Principle. Things that change less often (interfaces) should not depend on things that change more often (implementations) but the other way around. So my suggestion is that you make XYPosition an interface, then move the implementation to a concrete XYPosition class (choose another name).

  • 1
    I agree that the question's proposed design helps to keep interfaces focused. But arguing that “an interface should not depend on a non-abstract class” is not useful for value-like, immutable classes where polymorphic behaviour is entirely unnecessary. Unnecessary interfaces make the design more fragile and violate KISS and YAGNI. Of course there's a balance to be found between simplicity and future-proofing, but I feel your second paragraph may encourage over-engineering. – amon Sep 14 '16 at 11:31
  • @amon What is a value-like interfaces and how do you know whether or not implementors will use polymorphism in their apps? – Tulains Córdova Sep 14 '16 at 11:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.