Skip to content

Commit b1df069

Browse files
Reduce paragraph gaps by joining sentences
1 parent fbb9082 commit b1df069

1 file changed

Lines changed: 12 additions & 35 deletions

File tree

posts/2026-03-31-rails-apps-have-layers-but-no-modules.md

Lines changed: 12 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ You can have 200 models and zero modules. That's the problem with typical Rails
1515
Order.first.user.invoices.last.line_items
1616
```
1717

18-
Such code is not so uncommon. It crosses **4 business boundaries**. In just 1 line of code. All thanks to associations.
18+
Such code is not so uncommon. It crosses **4 business boundaries**. In just 1 line of code. All thanks to associations.
1919

2020
## The problem with associations
2121

22-
One of the first thing we teach in Rails is associations.
22+
One of the first thing we teach in Rails is associations.
2323

2424
```ruby
2525
class Order < ApplicationRecord
@@ -57,57 +57,34 @@ and this is how we allow the original code:
5757
Order.first.user.invoices.last.line_items
5858
```
5959

60-
This is how we boil the frog. One step at a time. One column at a time. One association at a time.
61-
62-
The result?
63-
A User class with **100 columns** in the database.
60+
This is how we boil the frog. One step at a time. One column at a time. One association at a time. The result? A User class with **100 columns** in the database.
6461

6562
## DRY and god models
6663

67-
There is a misconception about DRY - Don't Repeat Yourself. We have an existing User class. It feels right to just add things there.
68-
69-
**No one was ever fired for adding a new column to the users table.**
70-
71-
It feels like the User class is the right abstraction for DRY. Yet, it always ends as the god model.
64+
There is a misconception about DRY - Don't Repeat Yourself. We have an existing User class. It feels right to just add things there. **No one was ever fired for adding a new column to the users table.** It feels like the User class is the right abstraction for DRY. Yet, it always ends as the god model.
7265

7366
## Service Objects don't help with modularisation
7467

75-
Many Rails teams believe that Service Objects are the solution. They are, but to a different problem.
68+
Many Rails teams believe that Service Objects are the solution. They are, but to a different problem.
7669

7770
Service objects help us when our controllers become too big. They are called from the controllers and they are the ones orchestrating ActiveRecord models. Often they handle transactions too.
7871

79-
What is good about them?
80-
81-
They are creating a boundary between the HTTP layer (controllers) and the domain layer.
82-
They also are a good solution to the transaction boundary.
83-
84-
Service objects are a new layer. We could now call it MVCS. Model View Controller Service. It's not bad. It does help with unit testing - it's easier to unit test a service object than a controller action.
72+
What is good about them? They are creating a boundary between the HTTP layer (controllers) and the domain layer. They also are a good solution to the transaction boundary.
8573

86-
**Service objects do nothing about modularisation.**
74+
Service objects are a new layer. We could now call it MVCS. Model View Controller Service. It's not bad. It does help with unit testing - it's easier to unit test a service object than a controller action.
8775

88-
They don't create new boundaries. They don't help with composing modules.
89-
90-
Service objects are just **another horizontal slice**.
76+
**Service objects do nothing about modularisation.** They don't create new boundaries. They don't help with composing modules. Service objects are just **another horizontal slice**.
9177

9278
## Microservices
9379

94-
It's usually around this phase in the architecture - MVCS - when a decision is made.
95-
96-
We will go microservices.
80+
It's usually around this phase in the architecture - MVCS - when a decision is made. We will go microservices.
9781

9882
Sometimes it comes from the team itself - what can be a stronger boundary than a network? The team hopes it will enforce a better design. Microservices bring the hope of starting fresh — new language, new design, better boundaries. But the boundaries **still aren't modules**.
9983

100-
Are microservices helping with the modularisation?
101-
Nope. They are just yet another horizontal layer. This time we add a layer behind a network call. We no longer have transactions, it's harder to run tests, the build takes longer. All for the benefit for having 3 new Go microservices and adding new layers of serialisation/deserialisation.
102-
103-
**More layers, less performance, but still no modules.**
84+
Are microservices helping with the modularisation? Nope. They are just yet another horizontal layer. This time we add a layer behind a network call. We no longer have transactions, it's harder to run tests, the build takes longer. All for the benefit of having 3 new Go microservices and adding new layers of serialisation/deserialisation. **More layers, less performance, but still no modules.**
10485

10586
## A bitter conclusion
10687

107-
Rails makes it easy to add code. It doesn't make it easy to **isolate it**.
108-
109-
200 models. Five layers. Zero modules. That's the default.
110-
111-
In 1972, Parnas wrote that a module hides a design decision from the rest of the system. Fifty years later, Rails apps hide nothing.
88+
Rails makes it easy to add code. It doesn't make it easy to **isolate it**. 200 models. Five layers. Zero modules. That's the default.
11289

113-
What does your User class hide?
90+
In 1972, Parnas wrote that a module hides a design decision from the rest of the system. Fifty years later, Rails apps hide nothing. What does your User class hide?

0 commit comments

Comments
 (0)