September 11, 2017
Engines can be thought of as miniature applications that provide functionality to their host applications. A Rails application is actually just a "supercharged" engine, with the Rails::Application class inheriting a lot of its behavior from Rails::Engine.
My hypothesis is as follows: Engine-based architecture isn’t great for real world app and in most cases you won’t need to use it.
The following 3 considerations show the pitfalls of Engine-based architecture and will help you decide if it’s the right fit for the given use case.
We should first highlight a key difference between Rails components and front-end components: front-end components are created to be reused in the current application, whereas Rails components are created to be reused in the next Rails projects.
In any application, components should adhere to the following principles: They should be:
explicitly dependent on each other
and together, they should create a non-cyclic dependency graph
If you have followed these principles and used Engines as components, your architecture may look something like this:
If you have a project without any documentation, or the documentation is fluid, it would be frustrating to follow these principles. You would need to move some parts of your code into other Engines, or consider deleting one Engine and creating another for daily tasks.
By attempting to do this, you’ll waste a lot of time making changes in your architecture and trying to create an app where each component has its own logic.
So, if you want to use Engine-based architecture, you should have clear specification at the beginning. Most projects change as they progress: for instance when clients request alterations, or ideas are improved upon. Because of these frequent changes, you will not be able to create a finalised version of the documentation at the start of the project.
You may think that it’s easier for developers to understand a single Engine rather than trying to understand the entire app. So the ramp-up time is shorter.
It would be wrong to presume that development will be a quicker process. The use of Engines does not have many pitfalls, but the pitfalls it does have are serious:
You will need to write your own generator for the Engine if the default one creates redundant code. Each time you generate a new Engine, you will need to remove that useless code (most likely you will need to write your own generator).
When using gems, you run the risk that they will be problematic when used with Engines; they may have issues under the hood. You would either need to debug them, or wait until the issue is fixed by the gem’s maintainer.
If a new developer is brought on and they are not familiar with the Engines, it will take some time for them to understand the basic principles. With the addition of this on-boarding process, the code review time will further increase.
Therefore, using Engines can be much more time-consuming than one might assume.
Initially, it would appear that using components is a departure from a standard monolithic Rails app. One might think that Rails-Engines are a great opportunity to create a more flexible and understandable architecture, but this is simply not true.
For example, I once assumed that I could put a user’s business logic into a UsersEngine, move orders to an OrdersEngine and have other Engines for each logical part of the application. The result was as mess as if I had written a Rails app without any components.
Take a look at Engine-based architecture:
Engine-Based architecture is simply multiple MVC patterns. It won’t provide you any additional abstract layers. Compare Engine-based architecture with Trailblazer architecture:
Essentially, Engine-based architecture has no benefits over standard Rails architecture regarding abstract layers. There is only one reason to use it — in order to not duplicate your code down the line.
We think out loud on our blog. We share our views on coding, remote work and post regular insights into the freshest tech industry news.
+44 (0) 20 31 37 63 39
©2018 DVELP. All Rights Reserved.