2

We recently had a discussion about defining methods for developers convenience in interfaces. Given the following minimal example:

public interface aInterface{

    public void setUri(Uri uri);
    public void setUri(String uri);

}

public class aClass implements aInterface{
  @Override
  public void setUri(Uri uri){
      //do something with uri
  }

  @Override
  public void setUri(String uri){
      set Uri(new Uri(uri));
  }

}

Implementation pathway 1: One of us suggest to prospectively define both methods, to save developers from writing boiler plate code if they want to use implementations of the interface. This would be done prospectively, not knowing which of both methods is finally often used. The method with the String-type-parameter is explicitly intended for developers convenience.

Implementation pathway 2: Another person stated that only setUri(Uri uri) should be created, because you oblige implementors of the interface to implement both methods which leads to higher efforts for users of the interface (testing etc.) and this leads to a better type-safety.

I see the following aspects:

  • corresponding to the YAGNI-principle, only one of both methods should be created - the one which fits better to the intended feature
  • implementing only the setUri(Uri)-method perhaps lead to more boiler plate code if often only a string is available. In particular if the construction of the Uri-Type is more complex. In the end, this violates the DRY-principle, because the construction of the Uri-Type is repeated at the different usages of the method.

Which code-convention can be applied to this problem setting? What are the implications that result for each of both implementation pathways?

martin
  • 2,957
  • 3
  • 25
  • 46

1 Answers1

1

In my opinion, declaring overrides of methods in interface just for "what if someone needs it", both violates YAGNI and Interface segregation.

And I also support composition over inheritance. Interfaces are contracts of classes which means "this class has that capabilities", defining optional methods and pushing classes to implements it is not effective at all.

There are different solutions depends on overall design structure.

I can suggest you some different approaches as below:

  • Abstract class: providing some common methods on abstract class
  • Encapsulation: to hide underlying data type by wrapping it an object
  • UriFactory (factory pattern): to create uri from given type of data
  • UriGenerationStrategy (strategy pattern): to inject generation of uri strategy into our class

All above can be useful or meaningless at all depending on your current project structure and design.

Emre Savcı
  • 3,034
  • 2
  • 16
  • 25