Author: Avdi Grimm
Pub Date: 2013
Size: 10 Mb
32 Patterns for Joyful Coding
For many programmers, discovering Ruby is a revelation. They are overjoyed by how elegantly and succinctly they can state problems in the language. But then the real world creeps in, and that joy gradually wanes as the code becomes cluttered with distracting edge case scenarios, error handling, and checks for nil.
Confident Ruby is a guide to recapturing the joy of writing Ruby by employing small patterns and stylistic choices to make each method tell a coherent story. Over the course of 32 patterns, you’ll learn how to isolate uncertainty at the borders of your code; how to avoid repetitive conditionals; and how to liberate your code from the chore of nil-checking. You’ll discover the four parts of a method, and how to use those parts to construct a narrative. Following along with real-world refactoring sessions, you’ll learn how to apply these lessons to legacy code.
Whether you are a novice or an experienced Ruby hacker, this book will help you become a more confident and joyful programmer.
In the introduction, I made the assertion that methods have four parts:
- Collecting input
- Performing work
- Delivering output
- Handling failures
I went on to claim that in order to tell a good story, a method should contain these parts in the order listed above.
Given those statements, you may be wondering why I’ve started out with a chapter on “performing work”, even though that’s part #2 in my list.
Here’s the thing. Chances are, when you started reading this book, you had the reasonable idea thatallof a method was about “performing work”. If some code isn’t getting any work done, it shouldn’t be in the method at all, right?
So before we start to talk about collecting input, delivering results, and handling failure, I want to first change the way you think about theworkof a method. I want to give you a framework for thinking about a method’s responsibilities that focuses on theintentof a method, rather than on the method’s environment.
Unlike the chapters that follow, this chapter does not consist of a list of patterns. The structure of the “work” portion of your code is determined based on what tasks your methods are responsible for doing—and only you can say what those responsibilities are. Instead, in this chapter I want to share a way of thinking through a method’s design which will help you isolate the “core” of the method’s logic from the incidental complexities of being a part of a larger system.
It all starts with the idea ofsending messages.
Sending a strong message
The foundation of an object oriented system is themessage.
— Sandi Metz, Practical Object-Oriented Design in Ruby
As we write a method, we are a little like a captain of a naval vessel, pacing the bridge and issuing orders. A captain with a well-trained crew doesn’t waste time checking her subordinates’ insignia to see if they are qualified to execute an order; asking them if they understood the command, or giving them detailed instructions about how to do their job. She barks out an order and walks on, confident that it will be carried out. This trust frees her up to focus on the big picture of executing her mission.
Writing maintainable code is all about focusing our mental energy on one task at a time, and equally importantly, on onelevel of abstractionat a time. The ship’s captain doesn’t think about oil pressure and driveshaft RPMs when she says “all ahead full!”. In order to be equally clear-headed commanders of our code, we need to be able to trust that the objects we send messages to will respond to, and understand, those messages.
Up until now we’ve been looking at what I think of assimple, ordirectinputs: inputs which are used for their own value. But the use ofTime.nowis anindirectinput. First, we refer to theTimeclass. Then we send it the#nowmessage. The value we’re interested in comes from the return value of.now, which is one step removed from theTimeconstant. Any time we send a message to an object other thanselfin order to use its return value, we’re using indirect inputs.
The more levels of indirection that appear in a single method, the more closely that method is tied to the structure of the code around it. And the more likely it is to break, if that structure changes. You may have seen this observation referred to as theLaw of Demeter [page 0].
Input can also come from the surrounding system. Here’s a method that prettyprints the current time. The format can be influenced externally to the program, using a system environment variable calledTIME_FORMAT.