SOLID Object-Oriented Design (Sandi Metz)

May 31, 2009 Pivotal Labs

Sandi Metz, a Dukie visiting from NC, will be talking about SOLID principles of software development:

  • Single Responsibility
  • Open Closed
  • Liskov Substitution
  • Interface Segregation
  • Dependency Inversion

All of Sandi’s code is available here.

Change

Fact: your application is going to change. How will your application handle that change?

Robert Martin says your app can behave a couple of different ways:

  • Rigid: Making a change somewhere will break something somewhere else.
  • Fragile: You can’t predict where that break will be.
  • Immobile: It’s hard to change your code.
  • Viscous: It’s easier to do the wrong thing than to fix things.

In the beginning, though, your app was perfect. “Dependencies are killing you!”

Design might save you.

The Design Stamina Hypothesis says that, after a certain point, you’ll have done better if you had designed first.

“Skip design, if you want your app to fail.”

To avoid dependencies, your design should be:

  • Loosely coupled
  • Highly cohesive
  • Easily composable
  • Context independent

Ignorable Rules

SOLID principles we can ignore in ruby:

  • Interface Segregation

    Really only a problem for statically-typed, compiled languages. Because we’re in Ruby, we don’t have this problem! Win!

    “Dynamic languages obey this rule in the most extreme way possible: duck typing.”

  • Liskov Substitution

    When you design, don’t break the contract of the superclass in the subclass.

Testing Interlude

Sandi draws her examples of applicatoin change from the source code at: http://skmetz.home.mindspring.com/img28.html.

Lesson #1: Resistance is a Resource.

  • Don’t be attached to your first idea
  • Embrace the friction
  • Fix the problem

If testing seems hard, examine your design. Tests depend upon the design of the code. “TDD will punish you if you don’t understand design.”

During refactoring, ask yourself:

  1. Is it DRY?
  2. Does it have one responsibility?
  3. Does everything in it change at the same time?
  4. Does it depend on things that change less often than it does?

The answers should all be ‘yes’.

Important Rules

Sandi references her code to demonstrate when and how to mock and use dependency injection to achieve Single Responsibility, in which a class both downloads and acts upon the downloaded data.

She urges developers to do the simplest possible refactoring when extracting responsibilities from a class.

“Refactor, not because you know the abstraction, but because you want to find it.”

Sandi uses a very interesting example of building a Config class which behaves differently in different Rails environments. The first version had a lot of smell, and with a combination of hash parameters, YAML file, and metaprogamming, she demonstrates how to be open for extension, but closed for modification.

Sandi explains that paying attention to your classes’ dependencies is important. If a relatively static class is dependent on a class that changes more often, that’s a smell! Use dependency injection to avoid Dependency Inversion.

Summary

“TDD, BDD and DRY are all good, but they are not enough.”

“Design because you expect your app to succeed, and the future to come.”

Sandi recommends reading:

About the Author

Biography

Previous
TrustTheVote: Open Source Digital Voting
TrustTheVote: Open Source Digital Voting

This talk will present the TrustTheVote project and the "I count!" movement. It will cover the technology r...

Next
Playing With Fire: Running Uploaded Ruby Code in a Sandbox
Playing With Fire: Running Uploaded Ruby Code in a Sandbox

In this session, David Stevenson explores how to run untrusted code inside a ruby application using a sandb...