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.
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…
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.
Let’s create a new folder in Rails project
app/facades and let’s create our facade PORO class:
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 data
3. There is some refactoring included and dependency injection mechanism with
That allow us to simply the controller:
and use it in the view that way:
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.
Want to know first about new articles from that blog?
Subscribe to my newsletter now! — http://eepurl.com/cVPm_v
If you like this article and consider it useful for you, please support it with 👏.