I just read an
excerpt from
@avdi's new alpha
Confident Ruby ebook and it prompted some thoughts:
In the article, he talks about dealing with an
account_balance
where you iterate over
the transactions of the account and sum up their
amount
s to arrive at a final balance.
A special case arrives when he points out you're dealing with a
transaction.type
whose value is
"pending"
. You clearly don't want to include this in the
account_balance
because when the transaction processor introduces a new
transaction of
"authorized"
for the same purchase, your overall balance will be incorrect.
A
lot of the code I see (and used to write) looks like Avdi's example:
def account_balance
cached_transactions.reduce(starting_balance) do |balance, transaction|
if transaction.type == "pending"
balance
else
balance + transaction.amount
end
end
end
It cannot be stressed enough how important the advice is to go from code like that to introducing a new object. In my experience, many cases are solved by simply introducing an
OpenStruct.new(attributes: "you need", to: "support")
, but Avdi advocates going further than that, and introducing a new object entirely.
I'm a fan of that, but typically I'll wait until
YAGNI is satisfied, like when I need a method call with parameters.
Doing that is a huge win. As Avdi points out, it
solves the immediate problem of a special type of transaction, without duplicating logic for
that special case all throughout the codebase
But for me, the second benefit he mentions is the biggest, and I hope he'll revisit its importance over and over again:
But not only that, it is exemplary: it sets a good example for code that follows. When, inevitably, another special case transaction type turns up, whoever is tasked with dealing with it will see this class and be guided towards representing the new case as a distinct type of object.
It's something I mentioned in my
How to avoid becoming a formerly-employed Rails developer standing in line at the OOP Kitchen presentation, and I'll continue to stress its importance: "it's always easier to go with the flow, even when the flow is taking you through the sewers." So if you can introduce a little example of how to avoid the sewers, do it.
Anyway, I bought the book (which is literally just an introduction right now) based on the strength of that article and
Avdi's commitment in his blog post. The
article I linked to on Practicing Ruby is not yet in the book, but I hope it makes its way in.
I really enjoy the style of what I've read so far as a narrative, and if the article is any indication, this will be better than
Objects on Rails (which I loved). One bit of feedback though: I'd like to see a "Key Takeaway" at the end of every section, so it can double as a quick reference book when I need to remind myself of its lessons.
Hey! Why don't you make your life easier and subscribe to the full post
or short blurb RSS feed? I'm so confident you'll love my smelly pasta plate
wisdom that I'm offering a no-strings-attached, lifetime money back guarantee!
Leave a comment
There are no comments for this entry yet.
Leave a comment