---
title: 'Building Reusable Object-Oriented Systems: Modules'
teaser: Solving the combinatorial explosion problem with multiple inheritance.
tags: web,ruby,good code
author: Joël Quenneville
published_on: 2016-11-01
---

> If you can't fix it with duct tape, you haven't used enough

~ American folk saying

In a [previous post], we looked at building an API adapter for fetching
directors from a service called `movie-facts.com`. It comes in two flavors,
read from HTTP and read from cache. The shared logic between the two of these is
extracted to a base class.

[previous post]: reusable-oo-inheritance

## Paginated requests

After a few weeks in production, you get a bug report. The directors page only
displays 10 directors even though the `movie-facts.com` API contains many more.
You try to duplicate the problem locally and quickly realize that the
`movie-facts.com` API is paginated, 10 per page. Unfortunately, they seem to
hard code that 10 results per page. You'll need to make multiple requests and
combine the results together.

In the previous example, following the principle

> Separate things that change from those that stay the same

led us to using inheritance in a way that allowed us to easily extend and change
the system in the future.

However, we now have two independent ways for logic to vary. There are (2 ways
to fetch data) X (2 ways of de-paginating data) = 4 combinations. These are:

1. `DepaginatedHttpClient < ClientBase`
1. `PaginatedHttpClient < ClientBase`
1. `DepaginatedCacheClient < ClientBase`
1. `PaginatedCacheClient < ClientBase`

Our inheritance hierarchy now looks like:

![Combinatorial explosion](https://images.thoughtbot.com/reusable-oo-modules/2er47sFmR5a9cxZBlf4B_combinatorial-explosion.png)

The logic is duplicated and reused in many places.

We could try to get clever and add another layer of inheritance to remove some
of the duplication:

1. `HttpClient < ClientBase`
1. `DepaginatedHttpClient < HttpClient`
1. `CacheClient < ClientBase`
1. `DepaginatedCacheClient < CacheClient`

![Sort of fix combinatorial-explosion](https://images.thoughtbot.com/reusable-oo-modules/MtTSGjhT9CcnwdXZEHhb_sort-of-fix-combinatorial-explosion.png)

There is still duplication of the de-pagination logic and this solution won't
scale once we add more fetching classes or a third independent thing that can
change. We are going to need something more powerful than simple inheritance.

## Modules

Ruby implements multiple inheritance via modules (often referred to as
"mixins"). We can define a module with our de-pagination logic:

```ruby
module Depaginatable
  def fetch_depaginated_data
    # make multiple calls to `fetch_data`
    # combine results together
  end
end
```

Now the child classes look like:

```ruby
module MovieFacts
  class HttpClient < ClientBase
    include Depaginatable

    private

    def fetch_data
      # make HTTP request
      # cache response
    end
  end
end
```

and

```ruby
module MovieFacts
  class CacheClient < ClientBase
    include Depaginatable

    private

    def fetch_data
      # read data from cache
    end
  end
end
```

![Multiple inheritance](https://images.thoughtbot.com/reusable-oo-modules/aDtiBqtSRFOfDMlAGlHm_multiple-inheritance.png)

We've now eliminated all duplication and can now extend our system without too
much effort. Success!

Rails uses this approach heavily, taking advantage of modules and concerns (a
specialized type of module provided by Rails) to add multiple inheritance
throughout the its source.

## Limitations of multiple inheritance

Multiple inheritance solved our combinatorial explosion problem. Mostly. Note
that the method in our module is `fetch_depaginated_data` and now `fetch_data`.
We needed to be able to make both normal and de-paginated requests.

Code that uses one of our clients needs to know about the difference and make a
decision about which one it wants to use.

We can't fully leverage polymorphism and create an object that responds to
`fetch_data`, and would return the correct (raw/de-paginated) from (http/cache).

Like simple inheritance, multiple inheritance suffers from **encapsulation**
issues. Although we've used some clever tricks to prevent _duplicating code_,
we've still _duplicated logic_ across our clients.

We are using a single object to do all the things. An `HttpClient` instance
knows how to fetch data, de-paginate it, and convert it into `Director`
instances. Because a sub-class _is all of its ancestors combined_, an
`HttpClient` instance looks more like this:

![`HttpClient` is all of its ancestors combined](https://images.thoughtbot.com/reusable-oo-modules/KWqYqikSCSMi4fzO6c53_http-client-is-all-ancestors-combined.png)

There are no clearly defined responsibilities. Each ancestor has access to the
private methods and instance state of the combined object. Since there are no
boundaries, it's easy to refactor the implementation of a function in an
ancestor in a way that doesn't change its behavior and yet still break one of
the descendent classes.

In the next article, we address these concerns by looking at [composition] as an
alternate implementation approach.

[composition]: reusable-oo-composition

## Further Reading

This article is part 2 of 4 in a series on building reusable object-oriented
software.

1. [Simple Inheritance](reusable-oo-inheritance)
1. [Mixins/Multiple Inheritance (this article)](reusable-oo-modules)
1. [Composition](reusable-oo-composition)
1. [Composition vs Inheritance](reusable-oo-composition-vs-inheritance)
