The Rails Way is wrong and has led thousands of projects to an unmaintainable state of highly coupled software assets.
In order to keep the growing complexity maintainable, and to maximize reusability, people now start to introduce “micro services”, which are physically separated, completely stand-alone applications that provide a subset of the application’s functionality via a document API.
DHH is absolutely right when criticizing this approach.
Not only does a “micro service” increase the complexity for deploys, because now, you have to roll out 17 applications and not just one, it also makes it almost impossible to test the application under real-life conditions.
The test environment will have countless mocks for “micro service” endpoints and results in half-assed pseudo images of production. The tests you write are better than no tests, but I doubt the pain for setting them up outweighs their integrity.
Now you have a fragmented system with loose coupling and a tremendous maintainance effort.
Micro Services! And Now?
People make it look as if “micro services” are the only alternative to a monolith.
They make it look as if you either have the choice between a huge pile of rubbish with many internal dependencies – your Rails Way monolith. Or your devops engineers – that you had to hire to take care of your system – have to deploy up to 17 applications every time APIs change.
This is absolute bullshit.
A monolith the way DHH leverages it is the excuse for a horrible software architecture without any encapsulation (called The Rails Way). The micro service architecture is the attempt to decouple things by enforcing physical boundaries.
Both are a nightmare.
What About Good Object Design?
Micro services are great if parts of your system are to be written in another language, or if you really need physical extraction for scaling or global reusability.
I have no intention to maintain 17 separated micro services along with my base application, not to speak of the testing apocalypse that is gonna come with that. I haven’t seen a single working, testable micro service system so far. If you have one, please invite me and change my mind.
On the other side, monolithic Rails apps are terrible, quickly become unmaintainable and testing will be a third-class citizen for the sake of “development speed”.
I don’t see what’s so hard about having a proper object design in one, monolithic Rails app?
You can have cleanly composed, separated layers with interfaces that allow reusability and simple testing and debugging.
You Can Have a Nice Service Architecture Within a Monolith.
You can have stand-alone components in your monolith, just not the Rails Way.
We have dispatching, deserialization, validations and forms, transactions and business rules, decoration and rendering, authorization and persistence, just to name a few. How on earth are we supposed to implement all that using three primitive abstraction layers?
The Rails Way is wrong. However, don’t let that mislead you to the conclusion that the only ways out of this are either micro services or, even better, switching to a new fancier language, just to do all the same architectural mistakes, again.
Decouple your logic from the actual framework, ship independent components in gems and introduce interfaces between your layers. This is only possible if you actually have abstractions, which could be service objects, endpoints, view models and higher-level abstractions.
Don’t let the monolith be an excuse for a shitty software architecture.