Do you really need a List?

One of the most important aspects of each interface: It should be small and single responsible. Let's look at the List interface which is used in almost all Java based projects. Here are some main List methods.

int size();
boolean add(E e);
boolean remove(E e);
E get(int index)

Pretty clear and understandable, other programming languages have the same contract for lists.

However , the main idea of this post is.

Do you really need all those methods?

Let's look at an example from one of my pet projects J-Riddler

Class PrimaryKeys implements List interface and delegate all List methods calls to the global variable primaryKeys and here is an example how this class is used in test.

final List<String> users = new PrimaryKeys("users", TestDbInstance.datasource);
Assert.assertThat(users.size(), CoreMatchers.is(1));
Assert.assertThat(users.get(0), CoreMatchers.equalTo("id"));

So what is the problem ? Well there many of them, first of all what if user will call add method and add new primary key to the list or what if user delete primary key(user means user of this class).

In order to prevent it java has some utility methods which wrap List instance into immutable List Collections.unmodifiableList(list);. Now when user tries to modify this list it throws an exception. However it is still a list. Now users of this class have to remember that this list is immutable and doesn't support the majority of it's methods. Does it follow the Interface segregation principle? The answer in no , it doesn't. All classes that use PrimaryKeys will depend on methods they don't use. Could we make it better by using interface without modification methods ? Well partly. Java doesn't provide such interface. The closest one is Iterator , but it has remove method which is not supported by default. Here is the list of Iterator methods.

boolean hasNext();
E next();
default void remove() {throw new UnsupportedOperationException("remove");}

Few words before we start. There are a lot of java methods which accept Iterable instead of Iterator, so it would be better to implement Iterable interface which has a method that creates Iterator instance.

public final class PrimaryKeys implements Iterable<String> {
    public Iterator<String> iterator() {
        return this.primaryKeys.iterator();
     }

Now PrimaryKeys class allows user to access data without modifying the actual list of primary key names, but what if we want to access element by index as in the test above ? Well in this case it's up to the user to convert Iterable into something else such as Array.

Iterable it = new PrimaryKeys("users", TestDbInstance.datasource)
Assert.assertThat(new String[](it)[0],CoreMatchers.is("id"))

Unfortunately, you can't create array using the syntax above( Maybe java will support custom constructors for array in the near future ,will see).

List is just a beginning

List is just an example. I face Interface segregation principle violation everyday when I work with backend services especially those which are Spring Based.

Let's say you have UserDao(or Repository if you use SpringData) interface with 10 methods which behave as a layer between service and Database. You inject this Dao into UserService class and you use only 3 methods out of 10.

Usually , as a result , this UserDao is injected into a lot of other classes but none of them use all methods.

Now lets say you need to operate with orders related to the User , in this case you inject OrderDao into UserService and use only 2 methods out of let's say 5. Does UserService follow single responsibility principle now ? I don't think so. UserService has two Dao instances but use both of them partly.

Conclusion

List is just an example how to spoil you architecture. Try to make your interfaces as small as possible. If users of your interface use only half of methods then probably you should redesign your interface and split it into smaller parts