Advent Calendar #20 - The interface segregation principle

Alexander PanovAlexander Panov
2 min read

It states

1) that classes should not depend on interfaces, that they can't implement

2) that you should only depend on the data that you need in a specific place.

Today's post is about the second less obvious meaning. Let's look at the following code.

class Post {
  id: string;
  title: string;
  subTitle: string;
  description: string;
}

function postTitleToUppercase(post: Post) {
  return post.title.toUpperCase();
}

In order to make a string uppercase we need to provide a whole post object, while we are only using the title (string) of a post.

We should rather only expect the things that we are working with.

function postTitleToUppercase(postTitle: string) {
  return postTitle.toUppercase();
}

To be fair, this example is quite simplistic. It is, for the sake of easy understanding and to focus on the important paths.

Real-world example

Looking at the repository pattern, we can apply this principle too.

interface PostRepository {
  getAll();
  get(id: string);
  create(post: Post);
  update(id: string, post: Post);
  delete(id: string);
}

A page, that just renders the page by its ID (may be retrieved from the query parameters) should not depend on the write operation of the post repository.

That's why we should separate the PostRepository into two smaller repositories. The ReadPostRepository and the WritePostRepository.

interface ReadPostRepository {
  getAll();
  get(id: string);
}

// and
interface WritePostRepository {
  create(post: Post);
  update(id: string, post: Post);
  delete(id: string);
}

To simplify the usage for first-time users of our module, we create a general post repository.

interface PostRepository extends ReadPostRepository, WritePostRepository {}

Usage

class PostPage {
  public post: Post;
  constructor(_postRepository: ReadPostRepository) {
    this.post = _postRepository.get("0");
  }
}

Why?

For example, if we want to test certain code, we want to know exactly what a component depends on. It would be a huge hassle to always have a greater dependency than what is being used.

Did you like the post?

Subscribe to the newsletter to not miss a post.

0
Subscribe to my newsletter

Read articles from Alexander Panov directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Alexander Panov
Alexander Panov

Software developer and CEO at RoyalZSoftware. I build web applications for startups with Ruby on Rails, Angular and React.