As we make our way through the SOLID Development journey, it’s time we turned to the I in SOLID, which represents the: interface segregation principle.
Interface Segregation Principle Definition
As with several of the other SOLID design concepts, this represents a scary name for an important topic. A dead simple definition of the interface segregation principle is that code should not be forced to depend on methods that it doesn’t use.
If this is a bit fuzzy, don’t worry I’m going to walk through a code example that clears it up.
Believe it or not, this is one of the easier SOLID concepts to understand and work with.
Interface Segregation Principle Code Example
Let’s start by taking a look at a program that manages a blog. (Obviously this program simply prints out some values in each method). If we run the program you’ll see that this code works properly.
Introducing the Moderator
Now what happens if we want to create a moderator class? On a side note: let’s ignore the fact that a Moderator
class should never be connected or inherit from a Blog
class since a moderator isn’t a type of blog. However in preparing for this guide I walked through a number of examples and this case study illustrated the interface segregation principle the best.
Our Moderator
class is very specialized. Moderators should only be able to edit a post. However this poses a problem because if we try to use code like this:
You’ll see that the moderator is able to not only edit posts, but also delete posts.
For practical reasons this is bad. However it is also breaking the interface segregation principle because we’ve intertwined our Blog
class with our Moderator
. And even though Moderator
may not directly depend on all of the Blog
methods, it’s still coupled with them since they can be called from instances of the class.
A Better Way
Thankfully Ruby offers us a better way of giving us the behavior that we need. By leveraging the Forwardable
module we can limit the scope of what our Moderator
class can access.
We’ll start by importing the Forwardable
module in both the file and inside the Moderator
class. Next we’ll update the Moderator
class so it no longer inherits from Blog
. With those components cleaned up we can leverage the Forwardable
module’s def_delegators
method to list what we want the Moderator
class to have access to.
In this case we want the Moderator
to have access to the Blog
class and the edit_post
method inside of Blog
. Notice how this is different than having Moderator
inherit from Blog
? Instead of giving access to the full class definition we’re able to pick and choose what elements Moderator
should be able to work with.
Next we’ll setup an initialize
method that takes a blog
as an argument. This is how we’re letting Ruby know that our Moderator
class needs to be passed the Blog
class as an argument.
Lastly we can instantiate a new Moderator
and pass in a new Blog
as an argument.
The Result
After running this code you’ll see that our moderator can edit posts successfully. However when it tries to delete a post it gets an error since we didn’t give it access to that method.
A Caveat
Before ending this guide I want to make one point of clarification. The walk through I just went through is specific to how you can work with the interface segregation principle in the Ruby language. However, since Ruby is a dynamic language it doesn’t require developers to declare class and method types. The interface segregation principle has a number of other requirements for statically typed languages such as Java or c++. So please keep that in mind if you work with those types of languages.
Ruby does quite a bit of the hard work for us when it comes to Object Oriented Development, however this is still an important concept to understand. And as a bonus you were able to learn about the Forwardable
module!
Summary
I hope that this has been a helpful guide to understanding the SOLID Development topic of interface segregation. In the resources section I’ve included some links to additional sites that discuss the topic if you want to deepen your knowledge.