Review of Objects on Rails
This is my review of the book Objects on Rails.
- This book shows us another way to build a web application based on Rails: Write domain objects first, then use AR as an implementation detail. And use patterns like dependency injection (DI) and Data-Context-Interaction (DCI) to keep everything thin.
- I think treating AR as an implementation detail is a great way to build
Rails application.
- Even "Fat model, thin controller" can lead to really fat model classes. We need to keep everything thin and follow SRP.
- If we don't do this, then the model will violate SRP. Since it's both responsible for data persistence and business logic. So let AR handle the data persistence and let model object handle your business logic.
- Another way to do this is to use composition. For every business model, build a class for it and it don't inheritant from AR. If it needs to persistent some data, build another AR class and composite it into the business model object. It's more complicated than this solution but it makes the responsibility separation more clear.
- And there's another article about what framework can influence the software
complexity: Complexity and Strategy
- Rails can help us to build the software faster at the beginning of the project.
- But once the project becomes into a huge application, Rails will slow us
down.
- As it says in Complexity and Strategy: Framework can take us to a higher point at the beginning, but it won't change the complexity curve (the relation between functionality and cost). So the cost will become higher as the app grows.
As it says in this book:
The dark side of having sensible framework conventions is that after a while, those conventions turn into assumptions
- Designing application in the way this book describes can let us understand our domain problems better. And it won't use Rails until it's necessary. So we'll start at a lower point in the complexity curve and can move faster later.
- For the Exhibit pattern, I agree with the idea to extract logic from view.
- But I just feel the Exhibit pattern in this book is too much. It's like another framework just for view layer.
- If another new dev joins the team, he/she needs to learn this whole new view framework to get into work.
- And we can't get that many benifits from this framework.
- In my current understanding, A facade between view and controller is good enough. A controller builds a facade which contains all the information the view needs. A view reference this facade object by access method.
- Decoration vs Extension
- For the DCI part (extend Taggable on an instance object), I'm against it
at first. I think this is where we need to follow Prefer composition over
inheritance principle.
- Decorator (or something similar using composition) can easily do the same thing as the Taggable module did in this book.
For the reasons to not use decorator in this book, I think it's not enough to convince me to use DCI. But I can understand the reason behind this: since AR is an implementation detail, and
#save
method is private, a decorator cannot access#save
method.- Why use mixin instead of decorator?
- we need the tight integration that only a module can give us.
- For instance, intercepting
#save
within the object
- Why use mixin instead of decorator?
- But after I read Appendix C: Decoration vs. Dynamic Module Extension, I
get the idea of extension here.
- Decoration can fall apart when an undecorated method needs to call a decorated method (it can't, it can only call the undecorated version)
- How to choose between Decoration and Extension
- Decoration
- For applications where you want to adorn an object with some extra functionality, or modify how it presents itself, a decorator is probably the best bet. Decorators are great for creating Presenters, where we just want to change an object’s “face” in a specific context.
- Extension
- On the other hand, when building up a composite object at runtime object out of individual “aspects” or “facets”, module extension may make more sense. Judicious use of module extension can lead to a kind of “emergent behavior” which is hard to replicate with decoration or delegation.
- For the DCI part (extend Taggable on an instance object), I'm against it
at first. I think this is where we need to follow Prefer composition over
inheritance principle.
- Conclusion
- There's more than one way to do it
- Your project is not a Rails project; it is a software project, which uses Rails to satisfy the need of projecting your business objects onto the web.
- Rails is not the framework; it is a part of your overall project architecture.
- So don't be afraid to build up your project's architecture.
- There is very little new under the sun; whatever the problem you are facing, chances are Kent Beck already solved it in Smalltalk.
- There's more than one way to do it