The missing Ruby on Rails architecture

🧵let me explain the 10 rules here
1. App layer vs domain layer

Assume that controllers and service objects are app layer (a bit simplification here, but bear with me).

Service objects can never call each other. They are the application facade.
2. App layer modularisation is based on what "apps" you have

Usually you have some public facing app, admin panel, mobile API, some integrations.

Those are good candidates for "modules" at the app layer. Don't confuse it with domain layer.
3. App layer has different modularisation than domain layer

This is the biggest trap I've seen in Rails apps.
Trying to have one dominant modularisation, glueing app layer and domain layer.
4. Have a clear domain interface

I like to use commands as the domain interface. Simple data structures, smallest possible - which reflect the intent of what needs to be changes in a specific domain module
5. Domain modules are your business departments

If you know #domaindrivendesign you know what I mean. Those are bounded contexts.

It's actually more common than not, that many projects have almost the same domain modules. We all have prices in our apps, invoices, inventory etc
6. Denormalize your view data with read models

In Rails apps this is the biggest win usually.

But it's also the hardest one to convince people to.

But this is where you gain most in terms of performance.

Also, this allows clear testable view modules.
7. Domain modules output is events

Events are simple data structures.
This is what has happened.
8. Processes coordinate domains

Domains alone can't do much. They are too specific.

Processes are the thing that coordinates them.

Processes are like business checklists.
When A, B, C happens do X.

Where A,B,C are events and X is a command.
9. This architecture allows for real unit testing

This is where Rails apps struggle.
There is no modularisation.

So devs treat each class as a unit.
Which is wrong.

This architecture puts clear rules on the modules.

App layer turns params into commands.
Domain modules turn commands into events.
Processes turn events into commands.
Read modeles turn events into data.
10. Audit log

If every change is captured as an event, then we have an audit log for free.

Debugging with such audit logs is much easier.
11. Event Sourcing (optional)

Instead of persisting your objects with their last state, we can build our objects from events.

#eventsourcing does take some time to master, though.
Thanks for reading, follow me on @andrzejkrzywda
If you want to see a codebase following those rules, go here…

• • •

Missing some Tweet in this thread? You can try to force a refresh

Keep Current with Andrzej Krzywda

Andrzej Krzywda Profile picture

Stay in touch and get notified when new unrolls are available from this author!

Read all threads

This Thread may be Removed Anytime!


Twitter may remove this content at anytime! Save it as PDF for later use!

Try unrolling a thread yourself!

how to unroll video
  1. Follow @ThreadReaderApp to mention us!

  2. From a Twitter thread mention us with a keyword "unroll"
@threadreaderapp unroll

Practice here first or read more on our help page!

More from @andrzejkrzywda

Sep 20, 2020
Let's fight this monster

/thread Image
First rule: test coverage, no changes can be made if you're not secured
ideally with mutation testing showing us alive mutants Image
We're killing this mutant with new tests Image
Read 21 tweets
Aug 23, 2020
my definition is that nocode/lowcode can be used by non-programmers
Rails allows that, non-programmers can scaffold an app, make some tweaks and deploy to users, all alone, without writing much code
Read 4 tweets
Mar 10, 2020
I hate to make marketing based on the virus situation, but people keep asking me about async/remote work tips and most of the questions are answered in our (@arkency) "Async Remote" ebook. Image
Additionally, there are our "remote", free blogposts here - Image
Also, some aspects of async/remote work were covered in my vlogs on YT, like this one:
Read 5 tweets
Nov 13, 2019
threads in slack are NOT async-friendly
1. someone writes a channel message (M)
2. I read it, interesting, but not much to add from me, yet
3. I go to focus on my task, turn off slack
4. other people add new messages to that channel, less related
5. the original message M is now one screen/scroll behind
6. someone comments on M by replying in a thread
7. they forget to check the "send to channel" (because it's not on by default and it's easy to forget)
8. original author replies to thread (again not to channel)
9. they keep exchanging interesting points
Read 6 tweets
Nov 2, 2019
Ruby AOP experiments with #prepend

Using prepend + super we can simulate the AOP's before advice Image
now the same, but with refine Image
now with TracePoint

title needed to be made public getter to make it easier Image
Read 4 tweets
Oct 29, 2019
My favourite time - books around and researching new/old architectural ideas

Have you signed up to my tomorrow’s Rails Architect webinar already?

There will be:

microservices aka distributed objects

and more

with practical examples Image
Read 4 tweets

Did Thread Reader help you today?

Support us! We are indie developers!

This site is made by just two indie developers on a laptop doing marketing, support and development! Read more about the story.

Become a Premium Member ($3/month or $30/year) and get exclusive features!

Become Premium

Don't want to be a Premium member but still want to support us?

Make a small donation by buying us coffee ($5) or help with server cost ($10)

Donate via Paypal

Or Donate anonymously using crypto!


0xfe58350B80634f60Fa6Dc149a72b4DFbc17D341E copy


3ATGMxNzCUFzxpMCHL5sWSt4DVtS8UqXpi copy

Thank you for your support!

Follow Us on Twitter!