Practical Object-Oriented Design in Ruby: An Agile Primer (Addison-Wesley Professional Ruby Series)
Format: PDF / Kindle (mobi) / ePub
The Complete Guide to Writing More Maintainable, Manageable, Pleasing, and Powerful Ruby Applications
Ruby’s widely admired ease of use has a downside: Too many Ruby and Rails applications have been created without concern for their long-term maintenance or evolution. The Web is awash in Ruby code that is now virtually impossible to change or extend. This text helps you solve that problem by using powerful real-world object-oriented design techniques, which it thoroughly explains using simple and practical Ruby examples.
Sandi Metz has distilled a lifetime of conversations and presentations about object-oriented design into a set of Ruby-focused practices for crafting manageable, extensible, and pleasing code. She shows you how to build new applications that can survive success and repair existing applications that have become impossible to change. Each technique is illustrated with extended examples, all downloadable from the companion Web site, poodr.info.
The first title to focus squarely on object-oriented Ruby application design, Practical Object-Oriented Design in Ruby will guide you to superior outcomes, whatever your previous Ruby experience. Novice Ruby programmers will find specific rules to live by; intermediate Ruby programmers will find valuable principles they can flexibly interpret and apply; and advanced Ruby programmers will find a common language they can use to lead development and guide their colleagues.
This guide will help you
Understand how object-oriented programming can help you craft Ruby code that is easier to maintain and upgrade
Decide what belongs in a single Ruby class
Avoid entangling objects that should be kept separate
Define flexible interfaces among objects
Reduce programming overhead costs with duck typing
Successfully apply inheritance
Build objects via composition
Design cost-effective tests
Solve common problems associated with poorly designed Ruby code
direct Mechanic, Trip must change if Mechanic adds new procedures to the bike preparation process. For example, if Mechanic implements a method to check the bike repair kit as part of Trip preparation, Trip must change to invoke this new method. Figure 4.6 depicts an alternative where Trip asks Mechanic to prepare each Bicycle, leaving the implementation details to Mechanic. Figure 4.6. A Trip asks a Mechanic to prepare each Bicycle. In Figure 4.6: • The public interface for Trip includes
the method bicycles. • The public interface for Mechanic includes method prepare_bicycle. • Trip expects to be holding onto an object that can respond to prepare_bicycle. Trip has now relinquished a great deal of responsibility to Mechanic. Trip knows that it wants each of its bicycles to be prepared, and it trusts the Mechanic to accomplish this task. Because the responsibility for knowing how has been ceded to Mechanic, Trip will always get the correct behavior regardless of future
motion and then stand back proudly and watch it run forever. No matter how wobbly, the plates of code would rotate on and on, teetering round and round but never quite falling. As long as nothing changed. Unfortunately, something will change. It always does. The customers didn’t know what they wanted, they didn’t say what they meant. You didn’t understand their needs, you’ve learned how to do something better. Even applications that are perfect in every way are not stable. The application was a
object receives a message and merely forwards it to another. Delegation creates dependencies; the receiving object must recognize the message and know where to send it. Composition often involves delegation but the term means something more. A composed object is made up of parts with which it expects to interact via well-defined interfaces. Composition describes a has-a relationship. Meals have appetizers, universities have departments, bicycles have parts. Meals, universities, and bicycles are
that matter) that Wheel is playing the Diameterizable role. The role is virtual, it’s all in your head. Nothing about the code guides future maintainers to think of Wheel as a Diameterizable. However, despite the invisibility of the role and this coupling to Wheel, structuring the test in this way has one very real advantage, as the next section shows. Injecting Dependencies Using Classes When the code in your test uses the same collaborating objects as the code in your application, your