You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: posts/2026-03-31-rails-apps-have-layers-but-no-modules.md
+9-9Lines changed: 9 additions & 9 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,15 +7,15 @@ publish: false
7
7
8
8
# Rails apps have layers but no modules
9
9
10
-
You can have 200 models and zero modules. That's the problem with typical Rails conventions. Rails supports layers - models, views, controllers. But layers are not modules. Within one layer - especially models - usually all is mixed together. There are no boundaries.
10
+
You can have 200 models and zero modules. That's the problem with typical Rails conventions. Rails supports layers - models, views, controllers. **But layers are not modules.** Within one layer - especially models - usually all is mixed together. There are no boundaries.
11
11
12
12
<!-- more -->
13
13
14
14
```ruby
15
15
Order.first.user.invoices.last.line_items
16
16
```
17
17
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.
This is how we boil the frog. One step at a time. One column at a time. One association at a time.
61
61
62
62
The result?
63
-
A User class with 100 columns in the database.
63
+
A User class with **100 columns** in the database.
64
64
65
65
## DRY and god models
66
66
67
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
68
69
-
No one was ever fired for adding a new column to the users table.
69
+
**No one was ever fired for adding a new column to the users table.**
70
70
71
71
It feels like the User class is the right abstraction for DRY. Yet, it always ends as the god model.
72
72
@@ -83,28 +83,28 @@ They also are a good solution to the transaction boundary.
83
83
84
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.
85
85
86
-
Service objects do nothing about modularisation.
86
+
**Service objects do nothing about modularisation.**
87
87
88
88
They don't create new boundaries. They don't help with composing modules.
89
89
90
-
Service objects are just another horizontal slice.
90
+
Service objects are just **another horizontal slice**.
91
91
92
92
## Microservices
93
93
94
94
It's usually around this phase in the architecture - MVCS - when a decision is made.
95
95
96
96
We will go microservices.
97
97
98
-
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.
98
+
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**.
99
99
100
100
Are microservices helping with the modularisation?
101
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
102
103
-
More layers, less performance, but still no modules.
103
+
**More layers, less performance, but still no modules.**
104
104
105
105
## A bitter conclusion
106
106
107
-
Rails makes it easy to add code. It makes it impossible to isolate it.
107
+
Rails makes it easy to add code. It doesn't make it easy to **isolate it**.
108
108
109
109
200 models. Five layers. Zero modules. That's the default.
0 commit comments