Design Patterns in Ruby / Edition 1

Hardcover (Print)
Buy New
Buy New from BN.com
$39.41
Used and New from Other Sellers
Used and New from Other Sellers
from $15.94
Usually ships in 1-2 business days
(Save 72%)
Other sellers (Hardcover)
  • All (17) from $15.94   
  • New (11) from $37.08   
  • Used (6) from $15.94   

Overview

Praise for Design Patterns in Ruby

" Design Patterns in Ruby documents smart ways to resolve many problems that Ruby developers commonly encounter. Russ Olsen has done a great job of selecting classic patterns and augmenting these with newer patterns that have special relevance for Ruby. He clearly explains each idea, making a wealth of experience available to Ruby developers for their own daily work."

—Steve Metsker, Managing Consultant with Dominion Digital, Inc.

"This book provides a great demonstration of the key 'Gang of Four' design patterns without resorting to overly technical explanations. Written in a precise, yet almost informal style, this book covers enough ground that even those without prior exposure to design patterns will soon feel confident applying them using Ruby. Olsen has done a great job to make a book about a classically 'dry' subject into such an engaging and even occasionally humorous read."

—Peter Cooper

"This book renewed my interest in understanding patterns after a decade of good intentions. Russ picked the most useful patterns for Ruby and introduced them in a straightforward and logical manner, going beyond the GoF's patterns. This book has improved my use of Ruby, and encouraged me to blow off the dust covering the GoF book."

—Mike Stok

" Design Patterns in Ruby is a great way for programmers from statically typed objectoriented languages to learn how design patterns appear in a more dynamic, flexible language like Ruby."

—Rob Sanheim, Ruby Ninja, Relevance

Most design pattern books are based on C++ and Java. But Ruby is different—and the language's unique qualities make design patterns easier to implement and use. In this book, Russ Olsen demonstrates how to combine Ruby's power and elegance with patterns, and write more sophisticated, effective software with far fewer lines of code.

After reviewing the history, concepts, and goals of design patterns, Olsen offers a quick tour of the Ruby language—enough to allow any experienced software developer to immediately utilize patterns with Ruby. The book especially calls attention to Ruby features that simplify the use of patterns, including dynamic typing, code closures, and "mixins" for easier code reuse.

Fourteen of the classic "Gang of Four" patterns are considered from the Ruby point of view, explaining what problems each pattern solves, discussing whether traditional implementations make sense in the Ruby environment, and introducing Ruby-specific improvements. You'll discover opportunities to implement patterns in just one or two lines of code, instead of the endlessly repeated boilerplate that conventional languages often require.

Design Patterns in Ruby also identifies innovative new patterns that have emerged from the Ruby community. These include ways to create custom objects with metaprogramming, as well as the ambitious Rails-based "Convention Over Configuration" pattern, designed to help integrate entire applications and frameworks.

Engaging, practical, and accessible, Design Patterns in Ruby will help you build better software while making your Ruby programming experience more rewarding.

Read More Show Less

Product Details

  • ISBN-13: 9780321490452
  • Publisher: Addison-Wesley
  • Publication date: 12/24/2007
  • Series: Addison-Wesley Professional Ruby Series
  • Edition description: New Edition
  • Edition number: 1
  • Pages: 352
  • Sales rank: 705,806
  • Product dimensions: 7.30 (w) x 9.55 (h) x 0.95 (d)

Meet the Author

Russ Olsen has been building software for more than twenty-five years. He has led projects through several generations of programming technologies, from FORTRAN to C to C++ to Java, and now Ruby. He has been using and teaching Ruby since 2002. Olsen writes the popular technology blog Technology As If People Mattered (http://www.russolsen.com).

Read More Show Less

Read an Excerpt

A former colleague of mine used to say that thick books about design patterns were evidence of an inadequate programming language. What he meant was that, since design patterns are the common idioms of code, a good programming language should make them very easy to implement. An ideal language would so thoroughly integrate the patterns that they would almost disappear from sight.

To take an extreme example, in the late 80's I worked on a project that produced object oriented code in C. Yes, C, not C++. We pulled this off by having each "object" (actually a C structure) point off to a table of function pointers. We operated on our "objects" by chasing the pointer to the table and calling functions out of the table, thereby simulating a method call on an object. It was awkward and messy, but it worked. Had we thought of it, we might have called this technique the "object oriented" pattern. Of course with the advent of C++ and then Java, our object oriented pattern disappeared, absorbed so thoroughly into the language that it vanished from sight. Today, we don't usually think of object orientation as a pattern—it is too easy.

But many things are still not easy enough. The justly famous Gang of Four book, (Design Patterns: Elements of Reusable Object-Oriented Software by Gamma, Helm, Johnson, and Vlissides) is required reading for every software engineer today. But actually implementing many of the patterns described in Design Patterns with the languages in widespread use today, Java and C++ and perhaps C#, looks and feels a lot like my 1980s vintage handcrafted object system. Too painful. Too verbose. Too prone to bugs.

The Ruby programming language takes us a stepcloser to my old friend's ideal, a language that makes implementing patterns easy, so easy that sometimes they fade into the background. Building patterns in Ruby is easier for a number of reasons:

  • Ruby is dynamically typed. By dispensing with static typing, Ruby dramatically reduces the code overhead of building most programs, including those that implement patterns.
  • Ruby has code closures. Ruby allows us to pass around chunks of code and associated scope without having to laboriously construct entire classes and objects that do nothing else.
  • Ruby classes are real objects. Since a class in Ruby is just another object, we can do any of the usual runtime things to a Ruby class that we can do to any object. At runtime we can create totally new classes. We can also modify existing classes by adding or deleting methods. We can even clone a class and change the copy, leaving the original alone.
  • Ruby has an elegant system of code reuse. In addition to garden variety inheritance, Ruby provides also allows us to define mixins, which are a simple but flexible way to write code that can be shared among several classes.

All of this makes code in Ruby compressible: In Ruby, like Java and C++, you can implement very sophisticated ideas, but with Ruby it is possible to hide the details of your implementations much more effectively. As you will see on the pages that follow, many of the design patterns that require many lines of endlessly repeated boiler plate code in traditional static languages require only one or two lines in Ruby. You can make a class into a singleton with a simple include Singleton. You can delegate as easily as you can inherit. Since Ruby enables you to say more interesting things in each line of code, you end up with less code.

This is not just a question of keyboard laziness, it is an application of the DRY (Don't Repeat Yourself) principal. I don't think anyone today would mourn the passing of my old object oriented pattern in C—it worked for me, but it made me work for it, too. In the same way, the traditional implementations of many design patterns work, but they make you work too. Ruby is a real step forward to be able to do that work only once and compress it out of the bulk of our code. In short, Ruby allows us to concentrate on the real problems that we are trying to solve instead of the plumbing. I hope that this book will help you see how.Who Is This Book For?

Simply put, this book is for developers who want to know how to build significant software in Ruby. I assume that you are familiar with object oriented programming, but you don't really need any knowledge of design patterns —you can pick that up as you go through the book.

You also don't need a lot of Ruby knowledge to read this book profitably: you can find a quick introduction to the language in Chapter 2 and I do try to explain any Ruby specific language issues as we go.How Is This Book Organized?

This book is divided into three parts. First there are a couple of introductory chapters, starting with the briefest outline of the history and background of the whole Design Patterns movement and ending with a quick tour of the Ruby language, at the "just enough to be dangerous" level.

The second section, which takes up the bulk of these pages, looks at a number of the original Gang of Four patterns from a Ruby point of view. What problem is this pattern trying to solve? What does the traditional implementation of the pattern, the implementation given by the Gang of Four look like in Ruby? Does the traditional implementation make sense in Ruby? Does Ruby provide us with any alternatives that will make solving the problem easier?

The final section of this book looks at a three patterns that have emerged from the Ruby.A Word of Warning

I cannot sign my name to a book about design patterns without repeating the mantra that I have been muttering for many years now: design patterns are little spring loaded solutions to common programming problems. Ideally, when the appropriate kind of problem comes along, you should trigger the design pattern and the problem is solved. It is that first part, the bit about waiting for the appropriate problem to come along, that some engineers have trouble with. You cannot say that you are correctly applying a design pattern unless you are confronting the problem that the pattern is supposed to solve.

The reckless use of every design pattern on the menu to solve nonexistent problems has given design patterns a bad name in some circles. I would contend that Ruby makes it easier to write an adapter that uses a factory method to get a proxy to the builder which creates the command which coordinates the operation of adding two plus two. Ruby will make that easier, but even in Ruby it will not make any sense.

Nor can you look at program construction as a simple process of piecing together some existing design patterns in new combinations. Any interesting program is going to have unique sections, bits of code that fit that specific problem perfectly and no other. Design patterns are meant to help you recognize and solve the common problems that arise over and over when you are building software. The advantage of design patterns is that they let you rapidly get past the problems that someone has already solved, so that you can get on to the hard stuff, the code that is unique to your situation. Design patterns are not the universal elixir, the magic potion that will fix all of your design problems. They are simply one technique, albeit a very useful technique, that you can use to build programs.

Read More Show Less

Table of Contents

Foreword xvii

Preface xix

Acknowledgments xxv

About the Author xxvii

PART I: Patterns and Ruby 1

Chapter 1: Building Better Programs with Patterns 3

The Gang of Four 4

Patterns for Patterns 4

Separate Out the Things That Change from Those That Stay the Same 5

Program to an Interface, Not an Implementation 5

Prefer Composition over Inheritance 7

Delegate, Delegate, Delegate 12

You Ain't Gonna Need It 13

Fourteen Out of Twenty-Three 15

Patterns in Ruby? 17

Chapter 2: Getting Started with Ruby 19

Interactive Ruby 20

Saying Hello World 20

Variables 23

Fixnums and Bignums 24

Floats 26

There Are No Primitives Here 26

But Sometimes There Is No Object 27

Truth, Lies, and nil 28

Decisions, Decisions 30

Loops 32

More about Strings 34

Symbols 37

Arrays 38

Hashes 40

Regular Expressions 40

A Class of Your Own 41

Getting at the Instance Variables 43

An Object Asks: Who Am I? 46

Inheritance, Subclasses, and Superclasses 46

Argument Options 47

Modules 49

Exceptions 52

Threads 53

Managing Separate Source Files 54

Wrapping Up 55

PART II: Patterns in Ruby 57

Chapter 3: Varying the Algorithm with the Template Method 59

Keeping Up with What Life Throws at You 60

Separate the Things That Stay the Same 61

Discovering the Template Method Pattern 65

Hook Methods 66

But Where Are All the Declarations? 68

Types, Safety, and Flexibility 69

Unit Tests Are Not Optional 71

Using and Abusing the Template Method Pattern 73

Templates in the Wild 74

Wrapping Up 75

Chapter 4: Replacing the Algorithm with the Strategy 77

Delegate, Delegate, and Delegate Again 78

Sharing Data between the Context and the Strategy 80

Duck Typing Yet Again 82

Procs and Blocks 84

Quick-and-Dirty Strategies 88

Using and Abusing the Strategy Pattern 90

The Strategy Pattern in the Wild 90

Wrapping Up 92

Chapter 5: Keeping Up with the Times with the Observer 95

Staying Informed 95

A Better Way to Stay Informed 97

Factoring Out the Observable Support 100

Code Blocks as Observers 104

Variations on the Observer Pattern 105

Using and Abusing the Observer Pattern 106

Observers in the Wild 108

Wrapping Up 109

Chapter 6: Assembling the Whole from the Parts with the Composite 111

The Whole and the Parts 112

Creating Composites 114

Sprucing Up the Composite with Operators 118

An Array as a Composite? 119

An Inconvenient Difference 120

Pointers This Way and That 120

Using and Abusing the Composite Pattern 122

Composites in the Wild 123

Wrapping Up 125

Chapter 7: Reaching into a Collection with the Iterator 127

External Iterators 127

Internal Iterators 130

Internal Iterators versus External Iterators 131

The Inimitable Enumerable 133

Using and Abusing the Iterator Pattern 134

Iterators in the Wild 136

Wrapping Up 140

Chapter 8: Getting Things Done with Commands 143

An Explosion of Subclasses 144

An Easier Way 145

Code Blocks as Commands 147

Commands That Record 148

Being Undone by a Command 151

Queuing Up Commands 154

Using and Abusing the Command Pattern 154

The Command Pattern in the Wild 155

ActiveRecord Migrations 155

Madeleine 156

Wrapping Up 160

Chapter 9: Filling in the Gaps with the Adapter 163

Software Adapters 164

The Near Misses 167

An Adaptive Alternative? 168

Modifying a Single Instance 170

Adapt or Modify? 172

Using and Abusing the Adapter Pattern 173

Adapters in the Wild 173

Wrapping Up 174

Chapter 10: Getting in Front of Your Object with a Proxy 175

Proxies to the Rescue 176

The Protection Proxy 178

Remote Proxies 179

Virtual Proxies Make You Lazy 180

Eliminating That Proxy Drudgery 182

Message Passing and Methods 183

The method_missing Method 184

Sending Messages 185

Proxies without the Tears 185

Using and Abusing Proxies 189

Proxies in the Wild 190

Wrapping Up 192

Chapter 11: Improving Your Objects with a Decorator 193

Decorators: The Cure for Ugly Code 193

Formal Decoration 200

Easing the Delegation Blues 200

Dynamic Alternatives to the Decorator Pattern 201

Wrapping Methods 202

Decorating with Modules 202

Using and Abusing the Decorator Pattern 204

Decorators in the Wild 205

Wrapping Up 206

Chapter 12: Making Sure There Is Only One with the Singleton 207

One Object, Global Access 207

Class Variables and Methods 208

Class Variables 208

Class Methods 209

A First Try at a Ruby Singleton 211

Managing the Single Instance 212

Making Sure There Is Only One 213

The Singleton Module 214

Lazy and Eager Singletons 214

Alternatives to the Classic Singleton 215

Global Variables as Singletons 215

Classes as Singletons 216

Modules as Singletons 218

A Safety Harness or a Straitjacket? 219

Using and Abusing the Singleton Pattern 220

They Are Really Just Global Variables, Right? 220

Just How Many of These Singletons Do You Have? 221

Singletons on a Need-to-Know Basis 221

Curing the Testing Blues 223

Singletons in the Wild 224

Wrapping Up 225

Chapter 13: Picking the Right Class with a Factory 227

A Different Kind of Duck Typing 228

The Template Method Strikes Again 231

Parameterized Factory Methods 233

Classes Are Just Objects, Too 236

Bad News: Your Program Hits the Big Time 237

Bundles of Object Creation 239

Classes Are Just Objects (Again) 241

Leveraging the Name 242

Using and Abusing the Factory Patterns 244

Factory Patterns in the Wild 244

Wrapping Up 246

Chapter 14: Easier Object Construction with the Builder 249

Building Computers 250

Polymorphic Builders 253

Builders Can Ensure Sane Objects 256

Reusable Builders 257

Better Builders with Magic Methods 258

Using and Abusing the Builder Pattern 259

Builders in the Wild 259

Wrapping Up 260

Chapter 15: Assembling Your System with the Interpreter 263

The Right Language for the Job 264

Building an Interpreter 264

A File-Finding Interpreter 267

Finding All the Files 267

Finding Files by Name 268

Big Files and Writable Files 269

More Complex Searches with Not, And, and Or 270

Creating the AST 272

A Simple Parser 272

A Parser-less Interpreter? 274

Let XML or YAML Do the Parsing? 276

Racc for More Complex Parsers 277

Let Ruby Do the Parsing? 277

Using and Abusing the Interpreter Pattern 277

Interpreters in the Wild 278

Wrapping Up 279

PART III: Patterns for Ruby 281

Chapter 16: Opening Up Your System with Domain-Specific Languages 283

The Domain of Specific Languages 283

A File Backup DSL 284

It's a Data File--No, It's a Program! 285

Building PackRat 287

Pulling Our DSL Together 288

Taking Stock of PackRat 289

Improving PackRat 290

Using and Abusing Internal DSLs 293

Internal DSLs in the Wild 294

Wrapping Up 295

Chapter 17: Creating Custom Objects with Meta-programming 297

Custom-Tailored Objects, Method by Method 298

Custom Objects, Module by Module 300

Conjuring Up Brand-New Methods 301

An Object's Gaze Turns Inward 306

Using and Abusing Meta-programming 306

Meta-programming in the Wild 308

Wrapping Up 311

Chapter 18: Convention Over Configuration 313

A Good User Interface--for Developers 315

Anticipate Needs 315

Let Them Say It Once 316

Provide a Template 316

A Message Gateway 317

Picking an Adapter 319

Loading the Classes 320

Adding Some Security 323

Getting the User Started 325

Taking Stock of the Message Gateway 326

Using and Abusing the Convention Over Configuration Pattern 327

Convention Over Configuration in the Wild 328

Wrapping Up 328

Chapter 19: Conclusion 331

Appendix A: Getting Hold of Ruby 333

Appendix B: Digging Deeper 335

Index 339

Read More Show Less

Preface

A former colleague of mine used to say that thick books about design patterns were evidence of an inadequate programming language. What he meant was that, since design patterns are the common idioms of code, a good programming language should make them very easy to implement. An ideal language would so thoroughly integrate the patterns that they would almost disappear from sight.

To take an extreme example, in the late 80's I worked on a project that produced object oriented code in C. Yes, C, not C++. We pulled this off by having each "object" (actually a C structure) point off to a table of function pointers. We operated on our "objects" by chasing the pointer to the table and calling functions out of the table, thereby simulating a method call on an object. It was awkward and messy, but it worked. Had we thought of it, we might have called this technique the "object oriented" pattern. Of course with the advent of C++ and then Java, our object oriented pattern disappeared, absorbed so thoroughly into the language that it vanished from sight. Today, we don't usually think of object orientation as a pattern—it is too easy.

But many things are still not easy enough. The justly famous Gang of Four book, (Design Patterns: Elements of Reusable Object-Oriented Software by Gamma, Helm, Johnson, and Vlissides) is required reading for every software engineer today. But actually implementing many of the patterns described in Design Patterns with the languages in widespread use today, Java and C++ and perhaps C#, looks and feels a lot like my 1980s vintage handcrafted object system. Too painful. Too verbose. Too prone to bugs.

The Ruby programming language takes us a step closer to my old friend's ideal, a language that makes implementing patterns easy, so easy that sometimes they fade into the background. Building patterns in Ruby is easier for a number of reasons:

  • Ruby is dynamically typed. By dispensing with static typing, Ruby dramatically reduces the code overhead of building most programs, including those that implement patterns.
  • Ruby has code closures. Ruby allows us to pass around chunks of code and associated scope without having to laboriously construct entire classes and objects that do nothing else.
  • Ruby classes are real objects. Since a class in Ruby is just another object, we can do any of the usual runtime things to a Ruby class that we can do to any object. At runtime we can create totally new classes. We can also modify existing classes by adding or deleting methods. We can even clone a class and change the copy, leaving the original alone.
  • Ruby has an elegant system of code reuse. In addition to garden variety inheritance, Ruby provides also allows us to define mixins, which are a simple but flexible way to write code that can be shared among several classes.

All of this makes code in Ruby compressible: In Ruby, like Java and C++, you can implement very sophisticated ideas, but with Ruby it is possible to hide the details of your implementations much more effectively. As you will see on the pages that follow, many of the design patterns that require many lines of endlessly repeated boiler plate code in traditional static languages require only one or two lines in Ruby. You can make a class into a singleton with a simple include Singleton. You can delegate as easily as you can inherit. Since Ruby enables you to say more interesting things in each line of code, you end up with less code.

This is not just a question of keyboard laziness, it is an application of the DRY (Don't Repeat Yourself) principal. I don't think anyone today would mourn the passing of my old object oriented pattern in C—it worked for me, but it made me work for it, too. In the same way, the traditional implementations of many design patterns work, but they make you work too. Ruby is a real step forward to be able to do that work only once and compress it out of the bulk of our code. In short, Ruby allows us to concentrate on the real problems that we are trying to solve instead of the plumbing. I hope that this book will help you see how.

Who Is This Book For?

Simply put, this book is for developers who want to know how to build significant software in Ruby. I assume that you are familiar with object oriented programming, but you don't really need any knowledge of design patterns —you can pick that up as you go through the book.

You also don't need a lot of Ruby knowledge to read this book profitably: you can find a quick introduction to the language in Chapter 2 and I do try to explain any Ruby specific language issues as we go.

How Is This Book Organized?

This book is divided into three parts. First there are a couple of introductory chapters, starting with the briefest outline of the history and background of the whole Design Patterns movement and ending with a quick tour of the Ruby language, at the "just enough to be dangerous" level.

The second section, which takes up the bulk of these pages, looks at a number of the original Gang of Four patterns from a Ruby point of view. What problem is this pattern trying to solve? What does the traditional implementation of the pattern, the implementation given by the Gang of Four look like in Ruby? Does the traditional implementation make sense in Ruby? Does Ruby provide us with any alternatives that will make solving the problem easier?

The final section of this book looks at a three patterns that have emerged from the Ruby.

A Word of Warning

I cannot sign my name to a book about design patterns without repeating the mantra that I have been muttering for many years now: design patterns are little spring loaded solutions to common programming problems. Ideally, when the appropriate kind of problem comes along, you should trigger the design pattern and the problem is solved. It is that first part, the bit about waiting for the appropriate problem to come along, that some engineers have trouble with. You cannot say that you are correctly applying a design pattern unless you are confronting the problem that the pattern is supposed to solve.

The reckless use of every design pattern on the menu to solve nonexistent problems has given design patterns a bad name in some circles. I would contend that Ruby makes it easier to write an adapter that uses a factory method to get a proxy to the builder which creates the command which coordinates the operation of adding two plus two. Ruby will make that easier, but even in Ruby it will not make any sense.

Nor can you look at program construction as a simple process of piecing together some existing design patterns in new combinations. Any interesting program is going to have unique sections, bits of code that fit that specific problem perfectly and no other. Design patterns are meant to help you recognize and solve the common problems that arise over and over when you are building software. The advantage of design patterns is that they let you rapidly get past the problems that someone has already solved, so that you can get on to the hard stuff, the code that is unique to your situation. Design patterns are not the universal elixir, the magic potion that will fix all of your design problems. They are simply one technique, albeit a very useful technique, that you can use to build programs.

Read More Show Less

Customer Reviews

Be the first to write a review
( 0 )
Rating Distribution

5 Star

(0)

4 Star

(0)

3 Star

(0)

2 Star

(0)

1 Star

(0)

Your Rating:

Your Name: Create a Pen Name or

Barnes & Noble.com Review Rules

Our reader reviews allow you to share your comments on titles you liked, or didn't, with others. By submitting an online review, you are representing to Barnes & Noble.com that all information contained in your review is original and accurate in all respects, and that the submission of such content by you and the posting of such content by Barnes & Noble.com does not and will not violate the rights of any third party. Please follow the rules below to help ensure that your review can be posted.

Reviews by Our Customers Under the Age of 13

We highly value and respect everyone's opinion concerning the titles we offer. However, we cannot allow persons under the age of 13 to have accounts at BN.com or to post customer reviews. Please see our Terms of Use for more details.

What to exclude from your review:

Please do not write about reviews, commentary, or information posted on the product page. If you see any errors in the information on the product page, please send us an email.

Reviews should not contain any of the following:

  • - HTML tags, profanity, obscenities, vulgarities, or comments that defame anyone
  • - Time-sensitive information such as tour dates, signings, lectures, etc.
  • - Single-word reviews. Other people will read your review to discover why you liked or didn't like the title. Be descriptive.
  • - Comments focusing on the author or that may ruin the ending for others
  • - Phone numbers, addresses, URLs
  • - Pricing and availability information or alternative ordering information
  • - Advertisements or commercial solicitation

Reminder:

  • - By submitting a review, you grant to Barnes & Noble.com and its sublicensees the royalty-free, perpetual, irrevocable right and license to use the review in accordance with the Barnes & Noble.com Terms of Use.
  • - Barnes & Noble.com reserves the right not to post any review -- particularly those that do not follow the terms and conditions of these Rules. Barnes & Noble.com also reserves the right to remove any review at any time without notice.
  • - See Terms of Use for other conditions and disclaimers.
Search for Products You'd Like to Recommend

Recommend other products that relate to your review. Just search for them below and share!

Create a Pen Name

Your Pen Name is your unique identity on BN.com. It will appear on the reviews you write and other website activities. Your Pen Name cannot be edited, changed or deleted once submitted.

 
Your Pen Name can be any combination of alphanumeric characters (plus - and _), and must be at least two characters long.

Continue Anonymously

    If you find inappropriate content, please report it to Barnes & Noble
    Why is this product inappropriate?
    Comments (optional)