Should the separation between the API and the implementation be complete?

The separation between API design and implementation is often recommended in large software implementations. But somewhere they must be reconnected (i.e., the implementation must be reconnected to the API).

The following example shows the construction of the API and the call to its implementation through the INSTANCE object:

import java.util.List; public abstract class Separation { public static final Separation INSTANCE = new SeparationImpl(); // Defining a special list public static interface MySpecialList<T> extends List<T> { void specialAdd(T item); } // Creation of a special list public abstract <T> MySpecialList<T> newSpecialList(Class<T> c); // Merging of a special list public abstract <T> MySpecialList<? extends T> specialMerge( MySpecialList<? super T> a, MySpecialList<? super T> b); // Implementation of separation public static class SeparationImpl extends Separation { @Override public <T> MySpecialList<T> newSpecialList(Class<T> c) { return ...; } @Override public <T> MySpecialList<? extends T> specialMerge( MySpecialList<? super T> a, MySpecialList<? super T> b) { return ...; } } } 

Some argue that the API should not reference implementation code. Even if we separate the API code from the implementation through separate files, we often have to import the implementation code (at least the class name) into the API.

There are methods to avoid such links using a string representation of the full name. The class is loaded by this line, and then an instance is created. This makes the code more complex.

My question is: is there any use for a full branch or isolation of the API code from the implementation code? Or is it just a purist's attempt to achieve excellence with little practical benefits?

+6
source share
4 answers

I always understood that it was necessary to separate the interface from the implementation, to mean that you are not confusing how your implementation is with anything. So in the above example, mixing api and implementation would mean revealing in the api what was specific to how SeparationImpl implemented your api.

As an example, consider how iteration is performed in different classes of a collection. There are more specific ways to retrieve elements in certain collections (for example, by position in ArrayList), but they do not appear in Collection because they are specific to the implementation of a specific ArrayList.

I also saw projects with huge catalogs of interfaces, each of which has a single specific implementation, and each of them mechanically reproduces each method in its specific implementation, which seems like a completely meaningless "mock" abstraction, since it actually does not provide a logical abstraction.

+6
source

One method that is often used in OSGi is to have the API in a separate module for implementation. The API must compile itself, avoiding the implementation reference directly.

+3
source

The answers of Peter and Steve are enough, but I would like to add more - if you ever had a single implementation of an interface or an abstract class, then it makes no sense to have an interface or an abstract class, since the purpose of abstraction defeats it.
In your case, I really didn’t understand why you implemented Separation as an abstract class, and SeparationImpl itself can be an API class or if you have different implementations of Separation can be inetrface and if you have common functionality then you can have another abstract class implementing your interface and then SeparationImpl inheriting from this abstract class. sample pattern hierarchy will look like

 interface Separation --> AbstractSeparation --> SeparationImpl 

like the standard collection library

 interface List --> AbstractList --> ArrayList 
+2
source

In addition to good models from other authors, I would mention testing goals:

For object layouts, it is very simple when they have interfaces located above the classes.

+1
source

Source: https://habr.com/ru/post/888775/


All Articles