Ruby on Rails/iOS/Elixir programmer. Head of IT @ BrandnewIO. Blogger. YouTuber. Podcaster.

Aug 29, 2017

Facade design pattern in Ruby on Rails

Facade design pattern in Ruby on Rails

According to GoF and their great book “Design Patterns: Elements of Reusable Object-Oriented Software”, Facade design pattern:

„Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.”

and it’s a part of an object structural design patterns.

The problem

Ruby on Rails is built upon MVC paradigm. That mean’s that there is a view responsible for presentation of data, a model responsible for manipulating data and business logic and a controller responsible for wiring up everything.

Unfortunately what we can see in average Rails project is that controllers are very weak and a lot is happening to prepare data for the views. Although you can use services to perform some operations or even presenters to “restructure” your data/model to be more digestible by a view, it’s still sometimes not enough and you have quite fat controller like that one:

… a lot of initializations of data and helping objects in controller.

And here comes…

The solution

We can use use Facade design pattern to remove that responsibility of preparing data for the view and create unified face visible to outside world, also to hide the components underneath.

As you can see:1. I’ve moved all of the data preparations to UsersFacade2. There is some caching happening in case the view wants to ask for the same data3. There is some refactoring included and dependency injection mechanism with VipUsersPresenter

That allow us to simply the controller:

and use it in the view that way:

Final thoughts

Facade pattern can be very helpful for simplifying the controllers, especially if you have rather big project that is still growing. It can also improve testing by encapsulating some data preparation.

But is has also few drawbacks. Introducing facades in your project means new abstraction layer. Your facades should not be too big. I mean, your goal shouldn’t be to use only one facade by moving every initialisation from the controller to a new class. Facade that is too big is not reusable and you will end up with a facade that is tailored only for a specific controller.

Would be good if your facade could obey law of Demeter. That means that a facade is a unified face to the outside world. So instead of @facade.user.posts you should rather try to implement @facade.user_posts. This is rather a general guideline and is not always the best solution.