Did you know that you can navigate the posts by swiping left and right?
This post is written in response to Keep your privates close of Thoughtbot
At the beginning I must admit that previously I have never thought, that we could use private keyword in THIS way. First time I met this approach in my new outsourced project with code written by former devs. When I opened random file, I saw ugliness written in following style:
I hope, you’ve got the idea. When I asked why do we need to follow this convention,
I’ve got answer that this solves problem of vertical distance between public and
private methods related to each other. It was surprise for me, because usually I put
FIXME comment in large files.
During discussion my team mate sent me a link to the mentioned blog post from Thoughtbot. After reading it I must agree with author at one point.
First programs ever written had mostly one file. Developers were helping themselves by separating code with comments. Later file inclusion has been introduced enabling developers to split code into several files. Then came functions, namespaces, classes and modules. Everything what makes the code more readable and beautiful.
It is not only about look&feel. The code, we write, should be maintainable.
Someone said once that you should always keep in mind that developer coming after you is psychopath, who knows, where do you live. It might be just you, after few months. Making code maintainable reduces overall costs of the project. It’s okay to not care about that when prototyping, but is not when you write a real project, especially an for external client.
The need of grouping methods together exposes something to us. Usually we group them by some concern, which corresponds to a part of object’s responsibilities. This mean that object, when realizing those responsibilities, plays a role in our system. Yea, I know, you may think now, that I am next guy selling DCI or some other pattern. DCI is in fact quite nice solution, but I really don’t care how do you split your code.
When your class is getting bigger, you can easily extract concerns into separate module. Your main file becomes a list of contents. First step of refactoring of example above would be following:
For me it is much better. Please note that this approach is in early stage and few things should be discussed, like:
ActiveSupport::Concernand extract relations to modules?
load_missing_constantambiguous behaviour? It happens when you name your nested models like classes or modules being visible in global scope, consider
Ticket. Rails somehow fallbacks to
User::Ticket. I bypass this by writing
require_relative 'user/ticket' and include User::Ticket. I know, it is not perfect but good enough for now.
Often we get to the point, when a model in our projects grows too big. We did tend always to follow Skinny controller, fat model principle, but models have got extremely big - I saw files with 300 LoC, who bids more? Of course, we can live with that. We can also live without dishwashers and RSS (both are big time savers to me).
After separating your concerns, you may discover that persistence is also a concern. This will change the way you think about domain models drastically. I haven’t get to this point or/and I am not brave enough yet to experiment with PORO models in projects for clients, but for sure I will give it a try in my next side-project. However this is topic for next post ;-).
Some of you may think, why bother? Ruby is beautiful. Most of use came here from Java, PHP and other languages. Ruby let us express our thoughts easier than many of them. Let’s don’t break this with ugly spaghetti code. Don’t go back.