Interface Segregation Principle | SOLID as a Rock
Tags: cpp, programming, tutorial, codenewbie
Published: 2020-05-26 12:46:04

<!-- wp:paragraph -->
<p><strong>I</strong>nterface <strong>S</strong>egregation <strong>P</strong>rinciple in C++ is the fourth &amp; by far the simplest design principle of a series SOLID as a Rock design principles. The SOLID design principles focus on developing software that is easy to maintainable, reusable &amp; extendable. In this article, we will see a code violating ISP, a solution to the same code, guideline &amp; benefits of ISP.</p>
<!-- /wp:paragraph -->


> /!\\\: This article has been originally published on my [blog](http://www.vishalchovatiya.com/interface-segregation-principle-in-cpp-solid-as-a-rock/). If you are interested in receiving my latest articles, [please sign up to my newsletter](http://eepurl.com/gDNybv).

By the way, If you haven't gone through my previous articles on design principles, then below is the quick links:

1.  [**S**RP -- Single Responsibility Principle](http://www.vishalchovatiya.com/single-responsibility-principle-in-cpp-solid-as-a-rock/)
2.  [**O**CP -- Open/Closed Principle](http://www.vishalchovatiya.com/open-closed-principle-in-cpp-solid-as-a-rock/)
3.  [**L**SP -- Liskov Substitution Principle](http://www.vishalchovatiya.com/liskovs-substitution-principle-in-cpp-solid-as-a-rock/)
4.  [**I**SP -- Interface Segregation Principle](http://www.vishalchovatiya.com/interface-segregation-principle-in-cpp-solid-as-a-rock/)
5.  [**D**IP -- Dependency Inversion Principle](http://www.vishalchovatiya.com/dependency-inversion-principle-in-cpp-solid-as-a-rock/)

The code snippets you see throughout this series of articles are simplified not sophisticated. So you often see me not using keywords like `override`, `final`, `public`(while inheritance) just to make code compact & consumable(most of the time) in single standard screen size. I also prefer `struct` instead of `class` just to save line by not writing "`public:`" sometimes and also miss [virtual destructor](http://www.vishalchovatiya.com/part-3-all-about-virtual-keyword-in-c-how-virtual-destructor-works/), constructor, [copy constructor](http://www.vishalchovatiya.com/all-about-copy-constructor-in-cpp-with-example/), prefix `std::`, deleting dynamic memory, intentionally. I also consider myself a pragmatic person who wants to convey an idea in the simplest way possible rather than the standard way or using Jargons.

***Note:***

-   If you stumbled here directly, then I would suggest you go through [What is design pattern?](http://www.vishalchovatiya.com/what-is-design-pattern/) first, even if it is trivial. I believe it will encourage you to explore more on this topic.
-   All of this code you encounter in this series of articles are compiled using C++20(though I have used [Modern C++](http://www.vishalchovatiya.com/21-new-features-of-modern-cpp-to-use-in-your-project/) features up to C++17 in most cases). So if you don't have access to the latest compiler you can use <https://wandbox.org/> which has preinstalled boost library as well.

<!-- wp:heading -->
<h2>Intent</h2>
<!-- /wp:heading -->

> Clients should not be forced to depend on interfaces that they do not use.

<!-- wp:list -->
<ul><li>Interface Segregation Principle is very much related to the Single Responsibility Principle. What it really means is that you should always design your abstractions in such a way that the clients that are using the exposed methods do not have to get the whole pie instead. That imposing the clients with the burden of implementing methods that they don’t actually need.</li></ul>
<!-- /wp:list -->

<!-- wp:heading -->
<h2>Violating the Interface Segregation Principle</h2>
<!-- /wp:heading -->

```c++
struct Document;

struct IMachine {
    virtual void print(Document &doc) = 0;
    virtual void fax(Document &doc) = 0;
    virtual void scan(Document &doc) = 0;
};

struct MultiFunctionPrinter : IMachine {      // OK
    void print(Document &doc) override { }
    void fax(Document &doc) override { }
    void scan(Document &doc) override { }
};

struct Scanner : IMachine {                   // Not OK
    void print(Document &doc) override { /* Blank */ }
    void fax(Document &doc) override { /* Blank */ }
    void scan(Document &doc) override {  
        // Do scanning ...
    }
};
```

<!-- wp:list -->
<ul><li>As you can see, as far as <code>MultiFunctionPrinter</code> was concerned it's ok to implement <code>print()</code>, <code>fax()</code> &amp; <code>scan()</code> methods enforced by <code>IMachine</code> interface.</li><li>But what if you only need a <code>Scanner</code> or <code>Printer</code>, some dev still inherits <code>IMachine</code> &amp; leave unnecessary methods blank or throw <code>NotImplemented</code> exception, either way, you are doing it wrong.</li></ul>
<!-- /wp:list -->

<!-- wp:heading -->
<h2>Interface Segregation Principle Example</h2>
<!-- /wp:heading -->

```c++
/* -------------------------------- Interfaces ----------------------------- */
struct IPrinter {
    virtual void print(Document &doc) = 0;
};

struct IScanner {
    virtual void scan(Document &doc) = 0;
};
/* ------------------------------------------------------------------------ */

struct Printer : IPrinter {
    void print(Document &doc) override;
};

struct Scanner : IScanner {
    void scan(Document &doc) override;
};

struct IMachine : IPrinter, IScanner { };

struct Machine : IMachine {
    IPrinter&   m_printer;
    IScanner&   m_scanner;

    Machine(IPrinter &p, IScanner &s) : printer{p}, scanner{s} { }

    void print(Document &doc) override { printer.print(doc); }
    void scan(Document &doc) override { scanner.scan(doc); }
};
```

<!-- wp:list -->
<ul><li>This gives the flexibility for the clients to combine the abstractions as they may see fit and to provide implementations without unnecessary cargo.&nbsp; </li><li>As explained in the <a href="http://www.vishalchovatiya.com/single-responsibility-principle-in-cpp-solid-as-a-rock/" target="_blank" rel="noreferrer noopener"><span style="color:#170cec" class="color">Single Responsibility Principle</span></a>. You should avoid classes &amp; interfaces with multiple responsibilities. Because they change often and make your software hard to maintain. You should try to <strong><em>split up the interface into multiple interfaces based on role</em></strong>.</li></ul>
<!-- /wp:list -->

<!-- wp:heading -->
<h2>Benefits</h2>
<!-- /wp:heading -->

<!-- wp:heading {"level":3} -->
<h3>=&gt; Faster Compilation</h3>
<!-- /wp:heading -->

<!-- wp:list -->
<ul><li>If you have violated ISP i.e. stuffed methods together in the interface, and when method signature changes, you need to recompile all the derived classes. This is an important aspect for some compiled languages like <a href="http://www.vishalchovatiya.com/21-new-features-of-modern-cpp-to-use-in-your-project/" target="_blank" rel="noreferrer noopener" aria-label="C++ (opens in a new tab)"><span style="color:#0010a3" class="color">C++</span></a> which is well known for <a rel="noreferrer noopener" aria-label="slow compilation (opens in a new tab)" href="https://stackoverflow.com/questions/318398/why-does-c-compilation-take-so-long" target="_blank"><span style="color:#0d00a3" class="color">slow compilation</span></a>. While another way around is self explainable.</li></ul>
<!-- /wp:list -->

<!-- wp:heading {"level":3} -->
<h3>=&gt; Reusability</h3>
<!-- /wp:heading -->

<!-- wp:list -->
<ul><li><a rel="noreferrer noopener" aria-label="Martin (opens in a new tab)" href="https://en.wikipedia.org/wiki/Robert_C._Martin" target="_blank"><span style="color:#0002a3" class="color">Martin</span></a> also mentions that <strong><em>"fat interfaces" — interfaces with additional useless methods</em></strong> — lead to inadvertent coupling between classes. Thus, an experienced dev knows coupling is the bane of reusability.  </li></ul>
<!-- /wp:list -->

<!-- wp:heading {"level":3} -->
<h3>=&gt; Maintainability</h3>
<!-- /wp:heading -->

<!-- wp:list -->
<ul><li>The much more universal ISP benefit is that by avoiding unneeded dependencies, the system becomes<ul><li>easier to understand;</li><li>lighter to test;</li><li>quicker to change.</li></ul></li><li>Similarly, to the reader of your code, it would be harder to get an idea of what your class does from the class declaration line. So, if dev sees only the one god-interface that may have inherited other interfaces it will likely not be obvious. Compare</li></ul>
<!-- /wp:list -->

<!-- wp:enlighter/codeblock {"language":"cpp"} -->
<pre class="EnlighterJSRAW" data-enlighter-language="cpp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">MyMachine : IMachine</pre>
<!-- /wp:enlighter/codeblock -->

<!-- wp:paragraph -->
<p>to</p>
<!-- /wp:paragraph -->

<!-- wp:enlighter/codeblock {"language":"cpp"} -->
<pre class="EnlighterJSRAW" data-enlighter-language="cpp" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">MyMachine : IPrinter, IScanner, IFaxer</pre>
<!-- /wp:enlighter/codeblock -->

<!-- wp:list -->
<ul><li> The latter tells you a lot, the former makes you guess at best. </li></ul>
<!-- /wp:list -->

<!-- wp:heading -->
<h2>Yardstick to Craft Interface Segregation Principle Friendly Software</h2>
<!-- /wp:heading -->

<!-- wp:list -->
<ul><li>This principle comes naturally when you start decomposing your problem space by identifying major roles that take part in your domain. Hence, it's never a mechanical action. </li><li>Following a single question to your self may help you to rectify your design:</li></ul>
<!-- /wp:list -->

> Do I need all the methods on this interface I'm using?

<!-- wp:heading -->
<h2>Closing Notes</h2>
<!-- /wp:heading -->

<!-- wp:paragraph -->
<p>Even though big interfaces are a potential problem, the ISP isn't about the size of interfaces. Rather, it's about whether classes use the methods of the interfaces on which they depend. So ISP is poor guidance when designing software, but an excellent indicator of whether it’s healthy or not. </p>
<!-- /wp:paragraph -->



[Have Any Suggestions, Query or Wants to Say `Hi`? Take the Pressure Off, You Are Just a Click Away.](http://www.vishalchovatiya.com/contact-2/)🖱️