Commanding objects toward immutability

Following the rules for East-oriented Code helps me organize behavior in my code but it can lead to other benefits as well. As a result of following the rules, I find that my code is better prepared for restrictions like that which immutable objects introduce.

I recently went looking for samples of how people are using instance_eval and instance_exec and ended up with a great example from FactoryGirl thanks to Joshua Clayton. As I was searching, I came upon some code which happened to use instance_eval. Although it was a simple use case for that method it lent itself as a much better example of commands, immutability, and East-oriented code.

Here's the details...

If we want to use nested blocks to create a tree structure, we might create some pseudo-code like this to illustrate our desired code:

Node.new('root') do
  node('branch') do
    node('leaf')
    node('leaf2')
    node('leaf3')
  end
end

The representation of this set of objects should look something like this:

"['root', ['branch', ['leaf', 'leaf2', 'leaf3']]]"

This shows that the created tree is a pair of a named node and an array of named children (who can also have children).

Imperative approach

A simple solution is to initialize a Node and, using an imperative approach, to change its state; that is to say that we alter its collection of children.

class Node
      def initialize(name, &block)
        @name = name
        @children = []

        instance_eval(&block) if block
      end    

      attr_reader :children, :name

      def node(name, &block)
        children << Node.new(name, &block)
      end
    end

When each node is created, its collection of children is set to an empty array. With each call to the node method, a new Node object is created and shoveled into the collection of children.

If we refactor our sample to inline the methods and show us exactly what's going on, it would look something like this:

Node.new('root') do
  self.children << Node.new('branch') do
    self.children << Node.new('leaf')
    self.children << Node.new('leaf2')
    self.children << Node.new('leaf3')
  end
end

We can more clearly see what's happening inside of the node method with this change to our code.

Eastward flow

As I worked with this problem I wondered: what would happen if I started following the 4 rules of East-oriented code?

If our node method returns self, how does that affect our code?

class Node
      # initialize omitted...

      def node(name, &block)
        children << Node.new(name, &block)
        self
      end
    end

Fortunately, because our code relies on an imperative approach by changing the state of the children, the code still works.

If we want, we can shrink the space we use by chaining commands together:

t = Node.new("root") do
      node("branch") do
        node("subbranch") do
          node("leaf").node("leaf2").node("leaf3")
        end
      end
    end

I think that's actually a little more difficult to read, so we can go back to the regular style:

node("leaf")
    node("leaf2")
    node("leaf3")

When seeing techniques like returning self to encourage an East-oriented approach, it's easy to fixate on the chaining. But it's commands that we want to introduce, not chaining. The chaining is incidental here.

If you do chain your method calls together, it at least appears more clearly that each subsequent method is operating on the return value of the last one.

If we want to be clear that we're operating on the last return value, we can maintain the readability of the multiline option by writing it like this:

node("leaf").
    node("leaf2").
    node("leaf3")

Each line chains the next by adding the dot character. We don't have a specific need to do this, but it's good to know how it works.

Not much has changed after introducing our East-oriented approach. We're still updating that collection of children.

Introducing immutability

What will we see if we introduce immutable objects to our solution?

Immutable objects might just help us make our code more predictable. An object which never changes, of course, stays the same. This allows you to better handle the behavior of the system and, without changing any objects, makes a multithreaded approach much less likely to introduce headaches.

The simplest way to add immutability is to freeze objects as they are initialized:

class Node
      def initialize(name, &block)
        @name = name.freeze
        @children = [].freeze

        instance_eval(&block) if block
      end

      attr_reader :children, :name

      def node(name, &block)
        children << Node.new(name, &block).freeze
        self
      end
    end

This, of course, breaks everything. Our code relies upon the fact that the children array may be mutated. Instead of doing the mutation, we'll see this:

RuntimeError: can't modify frozen Array

Now what?

If we can't alter the collection, we're left at creating an entirely new one.

One thing we could do is change the constructor to accept a collection of children when the Node is initialized. Instead of altering the children, we'd use a constructor like this Node.new(name, chlidren). Here's what that looks like:

class Node
      def initialize(name, children=[], &block)
        @name = name.freeze
        @children = children.freeze

        instance_eval(&block) if block
      end
      # ... omitted code

    end

That still doesn't allow us to change anything until we also change the way our node method works (since it is responsible for handling changes to the children).

If the node method created a new Node instead of altering the children, that would get us what we want. Let's break it down.

First, when the node method is called, it needs to create the node to be added to the collection of children:

def node(name, &block)
      new_child = Node.new(name, &block)
      # ... ?
      self
    end

Since we're trying to avoid mutating the state of this object, we don't want to just shove the new node into the collection of children (and we can't because we used freeze on it).

So let's create an entirely new node, with an entirely new collection of children. In order to do that, we need to ensure that for every existing child object, we creat a corresponding new node.

For each command to the object with node, we'll get the representation of what the children should be. So let's build a method to do that:

def next_children
      children.map{|child| Node.new(child.name, child.next_children) }.freeze
    end

When we changed our initializer, that allowed us to set the list of children. Our new next_children method relies on that feature and a recursive call to itself to build the collection of children for that new node with Node.new(child.name, child.next_children).

Looking back at our node method we'll need to break the rules of East-oriented Code. Since we have immutable objects, we'll return a new node instead of self.

def node(name, &block)
      new_child = Node.new(name, &block)
      Node.new(self.name, next_children + [new_child])
    end

But there's still a problem left. Because we need our initialized object to execute a block and the contstructor new might actually need to return a different object than the one originally created. The call to node inside the block changes the return value from the instance that new creates, to the instance that node creates.

Controlling the constructor

To better handle our immutable objects and the return values from the methods we created, we can alter the way the new method works on our Node class.

Instead of handling a block in the initialize method, we can move it to new.

Here's the new new method:

def self.new(*args, &block)
      instance = super.freeze
      if block
        instance.instance_eval(&block)
      else
        instance
      end
    end

The first step is to call super to get an instance the way Ruby normally creates them (as defined in the super class of Node). Then we freeze it.

If we haven't provided a block to the new method, we'll want to return the instance we just created. If we have provided a block, we'll need to evaluate that block in the context of the instance we just created and return it's result.

This means that the block can use the node method and whatever is returned by it.

We need to alter the new method this way because we're not always just returning the instance it creates. Since our objects are frozen, we can't allow the block to alter their states.

The way new usually works is like this:

def self.new(*args, &block)
      instance = allocate
      instance.send(:initialize, *args, &block)
      return instance
    end

You can see the reason that Ruby has you call new on a class but in practice you write your initialize method. This structure ensures that no matter the result of your initialize method, new will always return an instance of the class you've used.

We're bending the rules to allow us to evaluate the given block and return its result, instead of the instance typically created by new.

After that, we can remove the block evaluation from initialize:

def initialize(name, children=[])
      @name = name.freeze
      @children = children.freeze
    end

While the method signature (the list of accepted arguments) has changed for initialize, it's still the same for new: a list of arugments and a block.

Believe it or not, there's still one more problem to solve.

Operating on values

We looked at how returning self allows you to chain your method calls. Although we've broken that rule and are instead returning a new Node object, it's important to consider that chaining.

Our initial code still doesn't work quite right and it's all because we need to think about operating on the return values of our commands and not relying on an imperitive approach to building and changing objects.

First, here's what our Node class looks like:

class Node
      def self.new(*args, &block)
        instance = super.freeze
        if block
          instance.instance_eval(&block)
        else
          instance
        end
      end

      def initialize(name, children=[])
        @name = name.freeze
        @children = children.freeze
      end

      attr_reader :children, :name

      def node(name, &block)
        new_child = self.class.new(name, &block)
        self.class.new(self.name, next_children + [new_child])
      end

      def next_children
        children.map{|child| self.class.new(child.name, child.next_children) }.freeze
      end

      def inspect
        return %{"#{name}"} if children.empty?
        %{"#{name}", #{children}}
      end
    end

We didn't discuss it, but there's an inspect method to return either the name of the node if it has no children, or the name and a list of children if it has some.

Here's what the code to create the tree looks like:

Node.new('root') do
      node('branch') do
        node('leaf')
        node('leaf2')
        node('leaf3')
      end
    end

If we assign the result of that to a variable and inspect it we'll get a surprising result.

t = Node.new('root') do
          node('branch') do
            node('leaf')
            node('leaf2')
            node('leaf3')
          end
        end
    puts [t].inspect

The output will only be

["root", ["branch", ["leaf3"]]]

So what happened to the other leaf and leaf2 objects? Why aren't they there?

Remember that each node call returns a new node. With every node a new result is returned. The node('leaf') returns an object, but node('leaf2') is not a message sent to the object returned by the first. It is a message sent to the node('branch') result.

Each of those calls is returned and forgotten. Here it is annotated:

t = Node.new('root') do
          node('branch') do
            node('leaf') # returned and forgotten
            node('leaf2') # returned and forgotten
            node('leaf3') # returned and used as the final result
          end
        end
    puts [t].inspect
    #=> ["root", ["branch", ["leaf3"]]]

The answer to this problem is to command each object to do the next thing. We can achieve this by chaining the methods. The result of one method is the object which will receive the next command.

t = Node.new('root') do
          node('branch') do
            node('leaf'). # dot (.) charater added to chain
            node('leaf2'). # executed on the result of the last node
            node('leaf3') # executed on the result of the last node
          end
        end
    puts [t].inspect
    #=> ["root", ["branch", ["leaf", "leaf2", "leaf3"]]]

An alternative way to look at this is to store the result of each command:

t = Node.new('root') do
          node('branch') do
            branch = node('leaf')
            next_branch = branch.node('leaf2')
            final_branch = next_branch.node('leaf3')
          end
        end
    puts [t].inspect
    #=> ["root", ["branch", ["leaf", "leaf2", "leaf3"]]]

Following the rules so you know when to break them

What was interesting about this to me was that my code was prepared for the immutable objects when I prepared it to operate on the same one. By structuring my code to return self and send the next message to the result of the last, I was able to change the implementation from an imperative style to a functional style.

Cohesive behaviors with data clumps

A good example of how we use context and locality to understand and manage concepts in our code is using a data clump.

A data clump is a collection of two or more bits of information that are consistently used together. You’ll find that your data loses its meaning when you remove items from the clump.

Date ranges are simple examples of how a data clump puts necessary information into context.
An example of this is to find out if a question was asked between today and one month ago. If our Question class implements a query method for this:

class Question
      def asked_within?(start_date, end_date)
        (start_date..end_date).cover?(self.asked_date)
      end
    end

Then we can pass in our desired dates to get the answer:

# using ActiveSupport
    start_date = 1.month.ago
    end_date = Time.now
    question.asked_within?(start_date, end_date)

Discovering whether a question is within this time frame always requires both a start and end date. This is an indication that we can only understand the feature and indeed only implement it when we have this data clump. To better encapsulate the behavior of these values, we can create a class to manage initializing objects that represent them.

DateRange = Struct.new(:start_date, :end_date)
    last_month = DateRange.new(1.month.ago, Time.now)
    question.asked_within?(last_month)

We can then change our Question class to instead take a date range object for the asked_within? method, but the question’s responsibilities have grown a bit here. A question doesn’t have anything to do with comparing dates, so we can move the control of that information into the data clump that represents them.

DateRange = Struct.new(:start_date, :end_date) do
      def contains?(date)
        (start_date..end_date).cover?(date)
      end
    end
Now, instead of the question managing its date comparison, the date range can do the work.
last_month.contains?(question.date_asked)

By analyzing the individual parts of this date comparison we have to juggle a bit more in our heads. Considering a range as an complete object rather than a collection of parts is simpler and we tend not to think of every individual day within a month when doing a mental comparison. A date range is a small system of interacting parts that we better understand as a broader context.

This example shows us the value not only of separating responsibilities, but of bringing objects together. We get more value by putting details into context than we would have if they remained separate.

Things to note

Struct.new returns a class instance. Inheriting from the result of a new Struct creates an anonymous class in the ancestors of your created class:

[DateRange, #, Struct, ...]

Instead of class DateRange < Struct.new; end use DateRange = Struct.new and avoid an anonymous class in the ancestors:>

[DateRange, Struct, ...]

Additionaly, be careful with large ranges. If our code used include? instead of cover?, Ruby would initialize a Time object for every time between the beginning and end. As your range grows, the memory needed to calculate the answer will grow too.

Avoid excessive memory and use cover? instead. It will check that your beginning date is less than or equal to the given date, and that the given date is less than or equal to the end date.

This article is an excerpt from my book Clean Ruby

Locality and Cohesion

"The primary feature for easy maintenance is locality: Locality is that characteristic of source code that enables a programmer to understand that source by looking at only a small portion of it." -- Richard Gabriel

This advice is from Patterns of Software by Richard Gabriel.

Keeping cohesive parts of our system together can help us understand it. By managing locality we can keep cohesive parts together.

It’s easy to see coupling in our code. When one object can't do it's job without another, we experience frustration in the face of change. We often think about dependencies in our code, but cohesion is the relatedness of the behaviors and plays an import part in how we organize the ideas to support our domain.

def process_payment(amount)
      gateway.authorize_and_charge(amount) do
        deliver_cart
      end
      logger.info "handling payment: #{amount}"
      logger.info "cart delivered: #{id}"
    end

The exact purpose of this completely-made-up code isn't that important. But we can look at parts of this procedure and extract them into a related method:

def process_payment(amount)
      gateway.authorize_and_charge(amount) do
        deliver_cart
      end
      log_purchase(amount)
    end

    def log_purchase(amount)
      logger.info "handling payment: #{amount}"
      logger.info "cart delivered: #{id}"
    end

As Gabriel points out in his book, we can compress a procedure into a simple phrase like log_purchase but this compression carries a cost. In order to understand the behavior of this log_purchase phrase, we need to understand the context around it.

Indeed, we might look at this and realize that there's a problem with the way we managed the locality of the procedure. Instead of easily understanding a single method, we might look at process_payment and realize there's a bit more to it than we first expect.

We're forced to understand the log_purchase and the context which previously surrounded it's procedure. A second look at this extraction might lead us to reconsider and to go back to inline the method. Let's keep this code with a tighter locality:

def process_payment(amount)
      gateway.authorize_and_charge(amount) do
        deliver_cart
      end
      logger.info "handling payment: #{amount}"
      logger.info "cart delivered: #{id}"
    end

While extracting the log_purchase method was easy, given the original code, it added a bit too much for us to understand and it doesn't feel quite right. Handling the locality of this code helps us to better understand it and to make better decisions about how to improve the main process_payment method.

Consider this: How much must you pack into your head before you can begin evaluating a part of your code?

While breaking procedures up into small methods can be a useful way to make easy to understand (and easy to test) parts, we may do so to the detriment of understanding.

This is something to consider if you are building a DSL to compress ideas in your code or if you're trying to create objects to manage your business logic. I'll be writing more about the value of controlling the locality of behavior in your system, but I'd love to hear how you manage locality. What do you do to ensure that related bits stay together?

The difference between instance_eval and instance_exec

There's an important difference between instance_eval and instance_exec. And there's a great lesson about how to use them well in FactoryGirl

But first, before you go rushing off to build your fantastic DSL, let's look at what instance_eval is and does.

The simplest of examples can be taken straight from the Ruby docs:

class KlassWithSecret
      def initialize
        @secret = 99
      end
    end
    k = KlassWithSecret.new
    k.instance_eval { @secret } #=> 99

The current value for self inside the provided block will be the object on which you call instance_eval. So in this case the k object is the current context for the block; @secret is a variable stored inside k and instance_eval opens up access to that object and all of it's internal variables.

The interface that FactoryGirl provides is simple and straightforward. Here's an example from it's "Getting Started" documentation:

FactoryGirl.define do
      factory :user do
        first_name "Kristoff"
        last_name  "Bjorgman"
        admin false
      end
    end

Here, FactoryGirl uses instance_eval to execute the blocks of code passed to factory.

Let's take a look at some representative code from how FactoryGirl makes this work:

def factory(name, &block)
      factory = Factory.new(name)
      factory.instance_eval(&block) if block_given?
      # ... more code
    end

That's not actually the code from FactoryGirl, but it represents roughly what happens. When the method factory is called a new Factory is created and then the block is executed in the context of that object. In other words where you see first_name it's as if you had that factory instance before it and instead had factory.first_name. By using instance_eval, the users of FactoryGirl don't need to specify the factory object, it's implicitly applied to it.

_Ok, that's all well and good, but what about instance_exec?_

I'm glad you asked.

The instance_eval method can only evaluate a block (or a string) but that's it. Need to pass arguments into the block? You'll be frozen in your tracks.

But instance_exec on the other hand, will evaluate a provide block and allow you to pass arguments to it. Let's take a look...

FactoryGirl allows you to handle callbacks to perform some action, for example, after the object is created.

FactoryGirl.define do
      factory :user do
        first_name "Kristoff"
        last_name "Bjorgman"
        admin false

        after(:create) do |user, evaluator|
          create_list(:post, evaluator.posts_count, user: user)
        end
      end
    end

In this sample, the after(:create) is run after the object is created, but the block accepts two arguments: user and evaluator. The user argument is the user that was created. The evaluator is an object which stores all the values created by the factory.

Let's take a look at how this is implemented:

def run(instance, evaluator)
      case block.arity
      when 1, -1 then syntax_runner.instance_exec(instance, &block)
      when 2 then syntax_runner.instance_exec(instance, evaluator, &block)
      else        syntax_runner.instance_exec(&block)
      end
    end

FactoryGirl will create a callback object named by the argument given to the after method. The callback is created with a name, :create in this case, and with a block of code.

The block that we used in our example had two arguments.

The run method decides how to execute the code from the block.

The callback object stores the provided block and Ruby allows us to check the arity of the block, or in other words, it allows us to check the number of arguments.

When looking at a case statement, it's a good idea to check the else clause first. This gives you an idea of what will happen if there's no match for whatever code exists in the when parts.

There we see syntax_runner.instance_exec(&block) and this could easily be changed to use instance_eval instead. Ruby will evaluate, or execute, the block in the context of the syntax_runner object.

If the block's arity is greater than zero, FactoryGirl needs to provide the objects to the block so that our code works the way we expect.

The second part of the case checks if the block arity is equal to 2.

when 2 then syntax_runner.instance_exec(instance, evaluator, &block)

If it is, the syntax_runner receives the instance (or in our case user) and the evaluator.

If, however, the arity is 1 or -1 then the block will only receive the instance object.

So what is that -1 value? Let's look at the ways we could create a callback:

# Two arguments and arity of 2
    after(:create) do |user, evaluator|
      create_list(:post, evaluator.posts_count, user: user)
    end
    # One argument and arity of 1
    after(:create) do |user|
      create_group(:people, user: user)
    end
    # Zero arguments and arity of 0
    after(:create) do
      puts "Yay!"
    end
    # Any arguments and arity of -1
    after(:create) do |*args|
      puts "The user is #{args.first}"
    end

Ruby doesn't know how many args you'll give it with *args so it throws up it's hands and tells you that it's some strange number: -1.

This is the power of understanding how and when to use instance_exec; users of the DSL will expect it to make sense, and it will.

But wait! There's more!

What if you want to specify the same value for multiple attributes?

FactoryGirl.define do
      factory :user do
        first_name "Kristoff"
        last_name  "Bjorgman"

        password "12345"
        password_confirmation "12345"
      end
    end

In the above example, both the password and password_confirmation are set to the same value. This could be bad. What if you change the password for one, but forget to change the other? If they are inherently tied in their implementation, then that could lead to some unexpected behavior when they are not the same.

I would, and probably you would too, prefer to tell FactoryGirl to just use the value I'd already configured.

Fortunately FactoryGirl allows us to use a great trick in Ruby using the to_proc method. Here's what it looks like in use:

FactoryGirl.define do
      factory :user do
        first_name "Kristoff"
        last_name  "Bjorgman"

        password "12345"
        password_confirmation &:password
      end
    end

The important part is the &:password value provided to password_confirmation. Ruby will see the & character and treat the following as a block by calling to_proc on it. To implement this feature, FactoryGirl defines to_proc on attributes and there will use instance_exec to provide the symbol password to the block:

def to_proc
      block = @block

      -> {
        value = case block.arity
                when 1, -1 then instance_exec(self, &block)
                else instance_exec(&block)
                end
        raise SequenceAbuseError if FactoryGirl::Sequence === value
        value
      }
    end

What about lambdas and procs?

Some commenters in Reddit raised an important question about how these methods behave when given lambdas and procs.

If you provide a lambda which accepts no arguments as the block, instance_eval will raise an error:

object = Object.new
    argless = ->{ puts "foo" }
    object.instance_eval(&argless) #=> ArgumentError: wrong number of arguments (1 for 0)

This error occurs because Ruby will yield the current object to the provided block as self. So you can fix it by providing a lambda which accepts an argument:

args = ->(obj){ puts "foo" }
    object.instance_eval(&args) #=> "foo"

This changes a bit if you use instance_exec:

object.instance_exec(&argless) #=> "foo"
    object.instance_exec(&args) #=> ArgumentError: wrong number of arguments (0 for 1)
    object.instance_exec("some argument", &args) #=> "foo"

Because a proc is less restrictive with argument requirements, it will allow either approach to work without error:

p_argless = proc{ puts "foo" }
    object.instance_eval(&p_argless) #=> "foo"

    p_args = proc{|obj| puts "foo" }
    object.instance_eval(&p_args) #=> "foo"

    object.instance_exec(&p_args) #=> "foo"
    object.instance_exec(&p_argless) #=> "foo"

Now you know, instance_exec and instance_eval are similar in the way they behave, but you'll reach for instance_exec if you need to pass variables around.

##Announcing Ruby Metaprogramming Masterclass

I'm offering a new online class where I'll be teaching you how to master metaprogramming in Ruby on April 30th (the day after my birthday!)

I'm keeping the spaces limited to 25 so attendees will be able to talk and ask questions but already over a quarter of the seats are gone. So grab a seat now, before they're all gone.

The 4 Rules of East-oriented Code: Rule 4

Often the rules we create are defined by their exceptions.

It is difficult to create a program which continually passes objects and never returns data. Often the first rule of "Always return self" is met with immediate rejection because it's easy to see the difficulty you'd encounter if that rule is continually followed for every object.

In my presentation for RubyConf, I showed how we break the rules to allow value objects to handle data for a template. I previously wrote about the approach I used in the presentation to push data into a value object.

class Address
      def display(template)
        if protect_privacy?
          template.display_address(private_version)
        else
          template.display_address(public_version)
        end
        self
      end
    end

In the sample above, an Address instance commands a template to display_address with different versions of data: private_version or public_version. This makes a flexible interface that allows Address to create any number of different versions if necessary. Perhaps the requirements will demand a semi_public_version in the future; our design of the template need not change.

This is a great way to break the rules. Value objects allow us to parameterize a collection of data in a single object. The alternative to this approach would be to use setter methods on the template object:

class Address
      def display(template)
        unless protect_privacy?
          template.street = street
          template.apartment = apartment
          template.postal_code = postal_code
        end
        template.city = city
        template.province = province
        template.display_address
        self
      end
    end

We can plainly see that although the code follows the rules by commanding the template object, there's also quite a lot happening in this display method on Address. If the requirements change we might feel encouraged to complicate the unless block or "refactor" it into a case statement. While that might solve our problem, the resulting code could lead to some difficult to read and understand implementation details.

By breaking the rules with a value object we can better encapsulate the ideas in a private address object or public or any other type we desire.

But we're not just breaking the rules inside the Address methods; the template breaks the rules too. Rule 2 says that objects may query themselves and subsequently means they should not query other objects. But by choosing to break the rules we make a design decision at a specific location to make things better.

No matter what rules you follow, you decide not only to follow them, but decide to break them as well. To make your program easy to understand and to create reasonable expectations, you can lean on creating barriers. Preventing yourself from doing one thing frees you to do another.

Embrace constraints.

How do you add constraints to your programs? What are you better able to do by adding restrictions?

The 4 Rules of East-oriented Code: Rule 3

When I set out to create my presentation for RubyConf, I wanted to provide the audience with something they could easily try. By doing that, one could walk away and put themselves in a position to think about their code differently. While, James Ladd, the creator of East-oriented Code made some basic rules, I decide to take them and frame it in the specific context of Ruby:

  1. Always return self
  2. Objects may query themselves
  3. Factories are exempt
  4. Break the rules sparingly

After writing about Rule 1 and Rule 2 I'm very eager to get to Rule 3. It's an easy way to break the intent of this style without breaking the rules.

Factories are Exempt

They must be. If you returned self from Object.new you'd just get Object back, not an instance of an object. So factories are exempt from returning self.

The best way to get around any of these rules is to just make something into a factory. But here lies the danger. It's important to first think about what these objects are doing. For what are they responsible?

We could create a class to sweep our messy code under the rug.

user = User.new
    signup = UserSignupProcess.new
    signup.create_with(user)

The code above, we could say, is East-oriented. The factories create instances, and the signup object is told to create_with and given the user object.

Beyond this (inside create_with), it could easily be an enormous mess. While we can and probably should use different programming techniques for different situations, taking a load of if statements and sweeping it into a class could still be problematic.

Now, the sample code above is completely made up to show how you can take part of your program and say "this part is East-oriented, but over here I used this other technique. I call it If-oriented."

Examining your domain and creating a program to support it requires that you carefully evaluate what objects should exist, what their responsibilities are, and what you will name them.

East-orientation is all about designating responsibilities.

This leads us to breaking the rules...

We'll be getting to that later. There's likely very good reasons to break any particular programming rule, but it probably depends on the context.

I wrote Clean Ruby and the chapter on East-oriented Code before I set up the 4 rules for my presentation, but the same lessons are there. I'll be adding more to it, particularly as discussion and ideas around DCI evolve, but I'm putting effort toward wrapping up the Ruby DSL Handbook. It will soon be complete and the $12 price will go up to $24, so pick it up now if you're interested.

Ruby DSL Handbook is about how to create a DSL without headaches from metaprogramming and I just released an update with a chapter about creating a DSL without metaprogramming at all. Much like this discussion today, it's all about managing responsibilities.

The 4 Rules of East-oriented Code: Rule 2

In a previous article I wrote about the first rule of East-oriented Code.

Here again are the rules I set forth in my presentation at RubyConf:

  1. Always return self
  2. Objects may query themselves
  3. Factories are exempt
  4. Break the rules sparingly

The second rule, that "Objects may query themselves", allows the design of objects to work with their own attributes.

When we design our systems of interacting objects we can use the Tell, Don't Ask approach to limit the decisions in the code to objects which are responsible for the data used to make them.

The Tell, Don't Ask article begins by quoting Alec Sharp:

Procedural code gets information then makes decisions. Object-oriented code tells objects to do things.

In order for objects to do things, they may need to ask questions about their own data. Though the first rule of East-oriented Code says that you should return self, internal private methods don't need to follow this rule. We can and might need to create query methods to allow the object to make decisions.

It's easy to begin designing an object by specifying what it's attributes are:

class Person
      attr_reader :name, :nickname, :gender
    end

When we do that, we also implicitly allow other objects to use these attributes and make decisions:

if person.nickname =~ /^DJ/
      person.setup_playlist_preferences('house')
    else
      person.setup_playlist_preferences('classical')
    end

In the sample code above we're using a method setup_playlist_preferences which accepts a single argument. The decision about what value to set is made outside of the person object. As additional options are added to the system, this if may have elsif clauses added to it or it may turn into a case statement. With public attributes, those changes can appear in multiple places in your system, which can lead to headaches when the structures of your objects change.

Alternatively, we could command the object to do what we want:

person.setup_playlist_preferences

Any decision about what to do to setup preferences can be made inside the setup_playlist_preferences method.

Here's a summary from the C2 wiki

Very very short summary: It is okay to use accessors to get the state of an object, as long as you don't use the result to make decisions outside the object. Any decisions based entirely upon the state of one object should be made 'inside' the object itself.

One way to prevent decisions about an object from being made outside that object is to limit the public information:

class Person
      private
      attr_reader :name, :nickname, :gender
    end

If you like this, check out the new book I'm writing: Ruby DSL Handbook which is currently half-off the final price. It's designed to be a guide to help you make decisions about how to build your own DSL and compressions of concepts.

The 4 Rules of East-oriented Code: Rule 1

4 simple rules are pretty easy to remember, but a bit harder to understand and apply.

A key concept of East-oriented Code is to enforce the use of commands by returning the object receiving a message.

Here's a simple example of what that looks like:

def do_something
      # logic for doing something omitted...
      self
    end

It's incredibly simple to follow.

Here are the rules I set forth in my presentation at RubyConf:

  1. Always return self
  2. Objects may query themselves
  3. Factories are exempt
  4. Break the rules sparingly

The first three are hard rules. The fourth, obviously, is more lenient. We'll get to some guidance on breaking the rules in the future but for now let's look at applying this to your code.

Rule 1: Always return self

Although this rule is simple at first, it inevitably leads to the queston of getter methods.

What if your objects had no getters? What if an object's name attribute simply was inaccessible to an external object?

You can make your data private by either marking your attr_accessors as private:

attr_accessor :name
    private :name

Or you can use the private method to mark all of the following defined methods to be private:

private
    attr_accessor :name

How you choose to do it will depend upon your code, but this would help you remove any getter methods.

Now this leaves you with a conundrum. How do you use the information?

If you have a need for that name, what can you do?

The only answer is to create a command which will apply the data to the thing you need.

def apply_name_to(form)
      form.name = name
      self
    end

The restricitions we put in our code are often self-imposed.

We can make whatever we want, so what's to stop us from putting Rails model data manipulation in it's view template? Nothing concrete stops us from doing so.

The same goes for getter methods like name. If it is publicly accessible by external objects, then we can create whatever if and case statements we want. We can put logic wherever we want.

If we create our own restrictions, we can guide ourselves and other programmers to the direction we intend for our application's structure.

Creating restrictions

I've written about the Forwardable library in the past not only because of it's usefulness, but because we can copy the same pattern to create our own DSL.

Forwardable provides methods which create getter methods for related objects. But what if we created our own DSL for commands to related objects? What if we could pass the messages on, but allow the related object to handle the values?

Here's what that could look like:

class Person
      command :send_email => :emailer
    end
    person = Person.find(1) # get some record
    person.emailer = Emailer.get # get some object to handle the emailing
    person.send_email

That's a lot of pseudo-code but the parts we care about are sending the command to a related object. Commands return the receiving object, queries will return a value.

Here's what that code would look like without our (yet unimplemented) command DSL.

class Person
      def send_email
        emailer.send_email
        self
      end
    end

Any code which uses a Person will have to rely on the command to do its own thing. This prevents a programmer from leaking logic out of the person.

What should happen when the email is sent? With the structure above, this code, can't make decisions:

if person.send_email
      # do one thing
    else
      # this will never work now
    end

If you find that you often write code like the if statement above, you might wonder "where does that logic go now?" Now, you'll be forced to write this code:

person.send_email

And this means that your send_email now has the job of handling what to do:

class Person
      def send_email
        emailer.send_email
        # do some other things...
        self
      end
    end

That might provide you with better cohesion; the related behaviors remain together.

Getting back to that command DSL we used above...

This was the final point of my presentation at RubyConf: you can build guidlines like this for yourself.

I created a gem called direction to handle enforcing this East-oriented approach. I'll write more about that later, but it shows that I can create signals to other developers on my team. I can take a simple concept like a command and simplify my code to show other developers what's happening:

class Person
      command :send_email => :emailer
    end

Building a DSL can aid in communication. The language and terminology we use can compress ideas into easily digestible parts.

If you like this, check out my new book: Ruby DSL Handbook designed to be a guide to help you build your own compressions of concepts.

Ruby Forwardable deep dive

The Forwardable library is one of my favorite tools from Ruby's standard library both for simplifying my own code and learning how to make simple libraries.

I find that the best way to understand how code works is to first understand why it exists and how you use it. In a previous article I wrote about the value of using Forwardable. It takes code like this:

def street
      address.street
    end

    def city
      address.city
    end

    def state
      address.state
    end

And makes it as short as this:

delegate [:street, :city, :state] => :address

Shrinking our code without losing behavior is a great feature which Forwardable provides. So how does it work?

Modules and their context

Forwardable is a module, which can be used to add behavior to an object. Most of the of modules I see tend to be used like this:

class Person
      include SuperSpecial
    end

But Forwardable is different and is designed to be used with the extend method.

require 'forwardable'
    class Person
      extend Forwardable
    end

Using extend includes the module into the singleton_class of the current object. There's a bit more to it than that, but here's a simple model to keep in mind: use include in your class to add instance methods; use extend in your class to add class methods.

Now that we have that out of the way, to use Forwardable, use extend.

Defining forwarding rules

My most often used feature of Forwardable is the one you saw above: delegate. It accepts a hash where the keys can be symbol or string method names, or an array of symbols and strings. The values provided are accessors for the object to which you'll be forwarding the method names.

class Person
      extend Forwardable

      delegate [:message_to_forward, :another_method_name] => :object_to_receive_message,
                :single_method => :other_object
    end

Other shortcuts

Forwardable provides a few methods, and most commonly you'll see their shortened versions: delegate, def_delegator, and def_delegators. These are actually alias methods of the originals.

alias delegate instance_delegate
    alias def_delegators def_instance_delegators
    alias def_delegator def_instance_delegator

The delegate method we reviewed above is a bit of a shortcut for similar behavior that other methods provide in Forwardable.

The def_delegators method accepts multiple arguments but it's sometimes hard for me to remember that one argument in particular is important. The first argument is the reference to the related object, the next arguments are used to create methods to forward.

class SpecialCollection
      extend Forwardable

      def_delegators :@collection, :clear, :first, :push, :shift, :size
      # The above is equivalent to:
      delegate [:clear, :first, :push, :shift, :size] => :@collection
    end

As you can see, with delegate there's a visual separation between the accessor and the list of methods.

There's more of a difference between delegate and def_delegators too.

def instance_delegate(hash) # aliased as delegate
      hash.each{ |methods, accessor|
        methods = [methods] unless methods.respond_to?(:each)
        methods.each{ |method|
          def_instance_delegator(accessor, method)
        }
      }
    end

Here the code loops through the hash argument changing the keys into arrays of methods if they aren't already arrays, and then calls the def_instance_delegator method for each item in the array. Here's what def_instance_delegators looks like. Note that this is the plural version:

def def_instance_delegators(accessor, *methods) # aliased as def_delegators
      methods.delete("__send__")
      methods.delete("__id__")
      for method in methods
        def_instance_delegator(accessor, method)
      end
    end

This method speficially restricts the use of __send__ and __id__ in forwarded messages. These methods are particularly important in communicating with the forwarding object and determining its identity. If you only used delegate and (for some strange reason) you specify either of __send__ or __id__ then those methods will pass right through. That might do exactly what you want or it might introduce some buggy behavior. This is mostly easy to avoid since you'll likely specify all the methods you need.

The different behavior is important to know, however, if you want to do a blanket forward for all methods from another class of objects:

class SpecialCollection
      extend Forwardable

      def_delegators :@collection, *Array.instance_methods
      # The above is equivalent to:
      delegate [*Array.instance_methods] => :@collection
    end

If you do that, you'll likely see warnings from Ruby like this:

warning: redefining `__send__' may cause serious problems

Don't say Ruby didn't warn you!

But def_delegators is a plural version of def_delegator which provides more options than the two we've been reviewing.

class SpecialCollection
      extend Forwardable

      def_delegator :@collection, :clear, :remove
      def_delegator :@collection, :first
    end

The method def_delegator accepts only three arguments. The first is the accessor for the related object (which will receive the forwarded message) and the second is the name of the message to be sent to the related object. The third argument is the name of the method to be created on the current class and is optional; if you don't specify it then the second argument will be used.

Here's what the above def_delegator configurations would look like if you wrote out the feature yourself:

class SpecialCollection
      extend Forwardable

      # def_delegator :@collection, :clear, :remove
      def remove
        @collection.clear
      end

      # def_delegator :@collection, :first
      def first
        @collection.first
      end
    end

You can see how the optional third argument is used as the name of the method on your class (e.g. remove instead of clear).

How the methods are created

We looked at how Forwardable adds class methods to your class. Let's look at the most important one:

def def_instance_delegator(accessor, method, ali = method)
      line_no = __LINE__; str = %{
        def #{ali}(*args, &block)
          begin
            #{accessor}.__send__(:#{method}, *args, &block)
          rescue Exception
            $@.delete_if{|s| Forwardable::FILE_REGEXP =~ s} unless Forwardable::debug
            ::Kernel::raise
          end
        end
      }
      # If it's not a class or module, it's an instance
      begin
        module_eval(str, __FILE__, line_no)
      rescue
        instance_eval(str, __FILE__, line_no)
      end
    end

It looks like a lot, and it is, but let's strip it down to it's simplest form rather than review everything at once. Here's a simpler version:

def def_instance_delegator(accessor, method, ali = method)
      str = %{
        def #{ali}(*args, &block)
          #{accessor}.__send__(:#{method}, *args, &block)
        end
      }
      module_eval(str, __FILE__, __LINE__)
    end

Remembering, of course, that def_instance_delegator is aliased as def_delegator we can see that a string is created which represents what the method definition will be and saved to the str variable. Then then that variable is passed into module_eval.

It's good to know that module_eval is the same as class_eval because I know I often see class_eval but rarely see the other. Regardless, class_eval is merely an alias for module_eval.

The string for the generated method is used by module_eval to create the actual instance method. It evaluates the string and turns it into Ruby code.

Taking this command def_delegator :@collection, :clear, :remove here's what string will be generated:

%{
      def remove(*args, &block)
        @collection.__send__(:clear, *args, &block)
      end
    }

Now it's a bit clearer what's going to be created.

If you're not familiar with __send__, know that it's also aliased as send. If you need to use the send method to match your domain language, you can use it and rely on __send__ for the original behavior. Here, the Forwardable code is cautiously avoiding any clashes with your domain language just in case you do use "send" as a behavior for some object in your system.

Maybe you're scratching your head about what either of those methods are at all. What the heck is send anyway!?

The simplest way to describe it is to show it. This @collection.__send__(:clear, *args, &block) is equivalent to:

@collection.clear(*args, &block)

All Ruby objects accept messages via the __send__ method. It just so happens that you can use the dot notation to send messages too. For any method in your object, you could pass it's name as a string or symbol to __send__ and it would work the same.

It's important to note that using __send__ or send will run private methods as well. If the clear method on @collection is marked as private, the use of __send__ will circumvent that.

The methods defined by Forwardable will accept any arguments as specified by *args. And each method may optionally accept a block as referred to in &block.

It's likely that the acceptance of any arguments and block will not affect your use of the forwarding method, but it's good to know. If you send more arguments than the receiving method accepts, your forwarding method will happily pass them along and your receiving method will raise an ArgumentError.

Managing errors

Forwardable maintains a regular expression that it uses to strip out references to itself in error messages.

FILE_REGEXP = %r"#{Regexp.quote(__FILE__)}"

This creates a regular expression where the current file path as specified by __FILE__ is escaped for characters which might interfere with a regular expression.

That seems a bit useless by itself, but remembering the original implementation of def_instance_delegator we'll see how it's used:

str = %{
      def #{ali}(*args, &block)
        begin
          #{accessor}.__send__(:#{method}, *args, &block)
        rescue Exception
          $@.delete_if{|s| Forwardable::FILE_REGEXP =~ s} unless Forwardable::debug
          ::Kernel::raise
        end
      end
    }

This code recues any exceptions from the forwarded message and removes references to the Forwardable file.

The $@ or "dollar-at" global variable in Ruby refers to the backtrace for the last exception raised. A backtrace is an array of filenames plus their relevant line numbers and other reference information. Forwardable defines these forwarding methods to remove any lines which mention Forwardable itself. When your receive an error, you'll want the error to point to your code, and not the code from the library which generated it.

Looking at this implementation we can also see a reference to Forwardable::debug which when set to a truthy value will not remove the Forwardable lines from the backtrace. Just use Forwardable.debug = true if you run into trouble and want to see the full errors. I've never needed that myself, but at least it's there.

The next thing to do, of course, is to re-raise the cleaned up backtrace. Again Forwardable will be careful to avoid any overrides you may have defined for a method named raise and explicitly uses ::Kernel::raise.

The double colon preceding Kernel tells the Ruby interpreter to search from the top-level namespace for Kernel. That means that if, for some crazy reason, you've defined a Kernel underneath some other module name (such as MyApp::Kernel) then Forwardable will use the standard behavior for raise as defined in Ruby's Kernel and not yours. That makes for predictable behavior.

Applying the generated methods

After creating the strings for the forwarding methods, Forwardable will attempt to use module_eval to define the methods.

# If it's not a class or module, it's an instance
    begin
      module_eval(str, __FILE__, line_no)
    rescue
      instance_eval(str, __FILE__, line_no)
    end

If the use of module_eval raises an error, then it will fallback to instance_eval.

I've yet to find a place where I've needed this instance eval feature, but it's good to know about. What this means is that not only can you extend a class or module with Forwardable, but you can extend an individual object with it too.

object = Object.new
    object.extend(Forwardable)
    object.def_delegator ...

This code works, depending of course on what you put in your def_delegator call.

Forwarding at the class or module level

All these shortcuts for defining methods are great, but they only work for instances of objects.

Fortunately forwardable.rb also provides SingleForwardable, specifically designed for use with modules (classes are modules too).

class Person
      extend Forwardable
      extend SingleForwardable
    end

In the above sample you can see that Person is extended with both Forwardable and SingleForwardable. This means that this class can use shortcuts for forwarding methods for both instances and the class itself.

The reason this library defines those longform methods like def_instance_delegator instead of just def_delegator is for a scenario like this. If you wanted to use def_delegator and those methods were not aliased, you'd need to choose only one part of this library.

class Person
      extend Forwardable
      extend SingleForwardable

      single_delegate [:store_exception] => :ExceptionTracker
      instance_delegate [:street, :city, :state] => :address
    end

As you can probably guess from the above code, the names of each library's methods matter.

alias delegate single_delegate
    alias def_delegators def_single_delegators
    alias def_delegator def_single_delegator

If you use both Forwardable and SingleForwardable, you'll want to avoid the shortened versions like delegate and be more specific by using instance_delegate for Forwardable, or single_delegate for SingleForwardable.

If you liked this article, please join my mailing list at http://clean-ruby.com or pick up the book today!

Avoiding clever mistakes when displaying data with missing values

In a previous article I showed a snippet of code I’ve used for displaying address information. There were some tricks to getting it right that are valuable to know when you have to handle missing data.

Here’s the problem, and how to solve it.

Let’s setup some simple data to use:

street = "123 Main St."
    city = "Arlington"
    province = "VA"
    postal_code = "222222"

The original implementation of displaying an address looked like this:

"".tap do |string|
      string << street unless street.nil?
      string << city unless city.nil?
      string << province unless province.nil?
      string << postal_code unless postal_code.nil?
    end

While that code will skip missing data if there is any, it will just mash all the bits together creating this:

"123 Main St.ArlingtonVA22222"

That’s not particularly helpful for displaying a readable address. I’m looking for it to display like this:

"123 Main St.
    Arlington, VA 22222"

Here’s what I tried next:

[street, [city, [province, postal_code].join(' ')].join(', ')].join("\n")

Thinking I was very clever, I ran the code with complete data and it worked quite well.

When I ran it with incomplete data I found that it didn’t work the way I expected. For example, if the city value was nil, I got this:

"123 Main St.
    , VA 22222"

That leading comma is just visual noise, so we need to remove that. Realizing that I had nil values in my arrays, I knew I could reach for the compact method to strip them out. After compacting the array, the join wouldn’t have nil values to address; they’d be gone.

[street, [city, [province, postal_code].compact.join(' ')].compact.join(', ')].compact.join("\n")

This worked perfectly, to remove the leading comma:

"123 Main St.
    VA 22222"

Just to be sure I got it right, I began checking other data. Next, with the city set to “Arlington” and this time with the province and postal_code set to nil I saw this:

"123 Main St.
    Arlington, "

Ugh! Now I had a trailing comma. Why wasn’t this working!? Using compact should remove the nil values.

The problem was that I had an empty array for the province and postal_code. That meant that with both values removed from the array using compact, this was happening:

[].join(' ') #=> ""

And because that empty array returned a value of an empty string, I was joining the city value with an empty string. In this case, compact was doing nothing for me.

[city, [province, postal_code].compact.join(' ')].compact.join(', ')
    # is the same as:

    [city, ""].compact.join(', ')]
    # which yields:

    "Arlington, "

So there it was. Finally I found my problem that what I thought was nil, wasn’t.

I decided to change the values to nil if they were empty strings:

province_and_postal_code = [province, postal_code].compact.join(' ')
    province_and_postal_code = nil if province_and_postal_code.empty?

    city_province_postal_code = [city, province_and_postal_code].compact.join(', ')
    city_province_postal_code = nil if city_province_postal_code.empty?

    [street, city_province_postal_code].compact.join("\n")

Finally, I got the output I needed:

"123 Main St.
    Arlington"

    "123 Main St.
    VA 22222"

    "123 Main St.
    Arlington, VA 22222"

My clever one-liner gave me unexpected behavior. While it was nice and short, it was also wrong. Eventually I ended up with code which is not just correct, but much more readable too. You might have your own preferences for how to handle these nil values. What would you do differently?

Enforcing encapsulation with East-oriented Code

Often our programs become complicated inadventently. We don't intend to put things it the wrong place, it just seems to happen.

Most of the time it happens to me when I allow my objects to leak information and eventually their responsibilities.

In recent articles I showed code that handled displaying address details and how to separate the responsibility for formatting from the responsibility for data. But there's still a problem which would allow me or someone else to unintentionally leak responsibility from these objects.

It's a good idea to be guarded against how much you reveal from an object; you never know how someone might use it in the future.

In our Template code, we provide a number of values about the object: province, postal_code, city, street, apartment, province_and_postal_code, city_province_postal_code, address_lines, and display_address. With each attribute provided, we introduce the ability to other objects to query the information and make decsions based upon the answer.

It's far too easy to write these types of queries:

if template.province == "..."
if template.city == "..." && template.postal_code == "..."
if template.city_province_postal_code.include?("...")

But what would our code look like if we couldn't do this? What if there were no questions to ask?

What if the only accessible information from our template was the display_address used to show the formatted data?

require 'forwardable'
class Template
  extend Forwardable

  def display_address
    address_lines.join("\n")
  end

  def with_address(address)
    @address = address
  end

  private
  delegate [:province, :postal_code, :city, :street, :apartment] => :@address

  def province_and_postal_code
    # ...
  end

  def city_province_postal_code
    # ...
  end

  def address_lines
    [street, apartment, city_province_postal_code].compact
  end
end

By moving most of our methods under the private keyword, our Template interface has shrunk significantly. Now all we'll have to handle and all other objects will need to know about is the display_address and with_address methods.

East vs. West

The changes we made make a significant restriction on the questions that we can ask about an object. This is where the idea of East-orientation comes in.

If we imagine a compass applied to our source code we'd see that any query, any if, will send the information flowing westward.

# <---- information travels West
if template.city == "..."

The if handles the execution of the algorithm. But by removing methods from the public interface which provide attributes like above, we better encapsulate the data in the target object. Our template here could not answer a question about its city attribute.

Instead, the code which uses the template would be forced to command the template to perform a particular action. The body of the if could instead become a method on the template object.

# ----> information travels East
template.perform_action

The template can make it's own decisions about what to do when told to perform some action.

Enforce encapsulation with return values

An easy way to ensure that our code encourages commands, discourages queries, and enforces encapsulation is to control the return values of our methods.

The best thing to return is not necessarily the result of the method, but the object performing the method. It's as simple as adding self to the end of the method block.

Here's what that might look like:

class Template
  def with_address(address)
    @address = address
    self
  end
end

By adding self there, each time we set the address value object using with_address we are given the object itself back, instead of the value that we passed to it.

# Without appending "self"
template.with_address(address) #=> address

# After appending "self"
template.with_address(address) #=> template

This becomes a powerful change to the way we interact with the template object. It enforces the encapsulation of data of the template and it forces us to think more about sending messages to our objects and allowing them to implement the solution.

When we return the object itself, we can only continue operation on that object.

The added benefit is that our code will become more concise. We will prevent unintentional dependencies between objects. And we can chain our commands together; it's all the same object:

template.with_address(address).display_address

See the flow at a glance

By using a visual compass to guide us through our code, it's easy to step back and see exactly where we leave our objects leaking information and responsibility.

Each time we query an object, each time we set a variable, we should now see the westward flow of information.

By simply returning self from our methods, we will force the hand of every developer to think with East-orientation in mind. By only working with the same object we will get back to using objects in the way that tends to be the most useful: for handling messages and implementing the required algorithm.

One last issue is that of the display_address method. Currently it returns the string representation of the address and not the template itself.

We can change that. What you do depends on how you're using a template. Perhaps our base Template will output details to STDOUT, or perhaps to a text file. Here's how we'd take care of that:

class Template
      def display_address
        STDOUT.puts address_lines.join("\n")
        # or perhaps File.write ...
        self
      end
    end

Try this with your code. Return "self" and see how it changes your thinking. Scan for westward flow of information and see how you can push responsibilities into the appropriate objects by heading East.

From now until the end of the year, you can get Clean Ruby for only $42 (the original pre-release price) by using this link. It'll only be valid this year (2014) and will go up automatically in January 2015. Merry Christmas!

Preferring value objects or setters and arguments

The problem with programming can be that there are so many ways to solve a problem. For each solution there are arguments for it and arguments against it.

In recent articles I've written about moving responsibilities into a template object and out of the objects which use them for display.

When the template code first began, its use was extremely simple:

class Address
      def display(template)
        template.display_address(self)
      end
    end

By making changes to the template to allow for shared behavior among different types of templates, the way in which our Address class used it became a bit more complex:

class Address
      def display(template)
        unless protect_privacy?
          template.street = street
          template.apartment = apartment
          template.postal_code = postal_code
        end
        template.city = city
        template.province = province
        template.display_address
      end
    end

Originally the Address class knew of two features of the template, that it had a display_address method, and that the method took a single argument intended to be the address.

After some rework, the template became easier to manage and it became easier to make alternative formats, but the changes burdened the user of the object with the need for more knowledge. The Address objects now also need to know that there are setters for street=, apartment=, postal_code=, city=, and province=. It also needs to be implicitly aware that the template could render incomplete data; we know we aren't required to set nil values for certain attributes.

Getting back to simple

We made good changes for the template, but I want that simple interface back. I want my address to act as a value object instead of needing to keep track of passing so many arguments.

While I want to go back to this:

class Address
      def display(template)
        template.display_address(self)
      end
    end

I need a way to handle the case where we have sensitive data. What about that protect_privacy? method?

Here's what we could do:

class Address
      def display(template)
        if protect_privacy?
          template.display_address(private_version)
        else
          template.display_address(self)
        end
      end

      def private_version
        self.class.new_with_attributes(city: city, province: province)
      end
    end

With this change, the Address can still make a decision about displaying private data and it merely sends that version along to the template. I'm leaving the implementation of new_with_attributes up to imagination, but we'll assume it will set the attributes we've provided on a new instance and return that.

Our template, when last we saw it, looked like this:

class Template
      attr_accessor :province, :postal_code, :city, :street, :apartment

      def province_and_postal_code
        # ... return the combined value or nil
      end

      def city_province_postal_code
        # ... return the combined value or nil
      end

      def address_lines
        [street, apartment, city_province_postal_code].compact
      end

      def display_address
        address_lines.join("\n")
      end
    end

We've been shifting the method signature of display_address from originally accepting an argument, to then not accepting one, to now requiring one. That's generally a bad thing to change since it causes a cascade of changes for any code that uses the particular method. I'd rather not switch back now, so what I can do is provide a way for the template to get the data it needs.

I'm happy to know how to use Forwardable because I can still keep my template code short and sweet. Here's what we can do. First, lets change hte way we interact with the template:

class Address
      def display(template)
        if protect_privacy?
          template.with_address(private_version)
        else
          template.with_address(self)
        end
        template.display_address
      end
    end

Next, we can alter the template by creating the with_address method:

class Template
      def with_address(address)
        @address = address
      end
    end

Then, we can alter the line where we use attr_accessor to instead query for information from the address and use it as our value object:

require 'forwardable'
    class Template
      extend Forwardable
      delegate [:province, :postal_code, :city, :street, :apartment] => :@address  
    end

As long as we provide an object which has all of those required features, our Templates will work just fine.

Here's the final result for our Template:

require 'forwardable'
    class Template
      extend Forwardable
      delegate [:province, :postal_code, :city, :street, :apartment] => :@address

      def with_address(address)
        @address = address
      end

      def province_and_postal_code
        value = [province, postal_code].compact.join(' ')
        if value.empty?
          nil
        else
          value
        end
      end

      def city_province_postal_code
        value = [city, province_and_postal_code].compact.join(', ')
        if value.empty?
          nil
        else
          value
        end
      end

      def address_lines
        [street, apartment, city_province_postal_code].compact
      end

      def display_address
        address_lines.join("\n")
      end
    end

With this change, the Template is still responsibile for only the proper display of data and will handle missing data appropriately. Our Address is responsible for the data itself; it will make decisions about what the data is, and whether or not it should be displayed with a given template.

Managing change using a common interface

In a previous article I showed a way to move display code into a template object to manage missing data. Here's what the basic template code looked like:

class Template
      def display_address(address)
        province_and_postal_code = [address.province, address.postal_code].compact.join(' ')
        province_and_postal_code = nil if province_and_postal_code.empty?

        city_province_postal_code = [address.city, province_and_postal_code].compact.join(', ')
        city_province_postal_code = nil if city_province_postal_code.empty?

        [address.street, city_province_postal_code].compact.join("\n")
      end
    end

That's relatively short and easy to read code for displaying the data for an address object.

But the display_address method contains the entire algorithm for displaying the data and stripping away any missing values. When we needed to add a new format type we created an HtmlTemplate and it contained duplicated code for the display_address. That reeks of a future bug where we might need a change to the algorithm and only remember to change one template type.

If we add new attributes to our address, we'd need to change every template so it could handle the new data. Inheritance is an easy solution for managing the way multiple types can handle the change.

And because we specifically allow for data to be missing, we can treat our template object like a partially applied function. Here's what our main template will have...

We'll need methods to set the values to be used for the display data, methods to handle the removal of missing values from the data to be processed, and finally the display method.

To set the data values, we can use attr_accessor:

class Template
      attr_accessor :province, :postal_code, :city, :street

      def province_and_postal_code
        value = [province, postal_code].compact.join(' ')
        if value.empty?
          nil
        else
          value
        end
      end

      def city_province_postal_code
        value = [city, province_and_postal_code].compact.join(', ')
        if value.empty?
          nil
        else
          value
        end
      end

      def address_lines
        [street, city_province_postal_code].compact
      end

      def display_address
        address_lines.join("\n")
      end
    end

With that change, our additional template types can inherit from our beginning Template class and change the behavior relevant to the needs of its format:

class HtmlTemplate < Template 
      def display_address
        address_lines.join("
") end end

Eventually we'll find that the addresses we need to handle might require a secondary bit of information like an apartment number.

class Template
      # Additional attribute
      attr_accessor :apartment

      # Updated collection of information
      def address_lines
        [street, apartment, city_province_postal_code].compact
      end
    end

The way our Address objects interact with these templates would change, of course, but could allow the Address to make decisions about what may be revealed to the outside world:

class Address
      def display(template)
        unless protect_privacy?
          template.street = street
          template.apartment = apartment
          template.postal_code = postal_code
        end
        template.city = city
        template.province = province
        template.display_address
      end
    end

By creating a standard set of template methods, we can treat our objects containing data separately from the objects which display them. What else could we do now that we've made this distiction? For example, what might a template for an IO stream look like?

Forwarding messages with Tell, Don't Ask

My avid use of Forwardable helps me simplify my code to raise up the important parts. When things still end up too complicated, I can reach for null objects to ease my commands into place.

class Person
      def initialize(address)
        @address = address
      end
      def address
        @address || DefaultAddress.new
      end
    end

As we've seen in this code, any Person object will always have an address, but what I do with that Person or address is what can cause some problems in the future.

Displaying an address can sometimes be a complicated matter.

Asking for too much

In the case of displaying the address for a particular person, we might want certain formatting depending upon the available details.

If we only have a person's city, or just city and state, we'd probably only show that. An easy way is to just check for those attributes on the address:

class Person
      def display_address
        "".tap do |string|
          string << address.street unless address.street.nil?
          string << address.city unless address.city.nil?
          string << address.province unless address.province.nil?
          string << address.postal_code unless address.postal_code.nil?
        end
      end
    end

This is easy, but introduces a problem if the display of the address ever changes. With the above code, we are asking for a lot of information from the address. It would be more flexible to move this into the address itself.

class Person
      def display_address
        address.display
      end
    end

    class Address
      def display
        "".tap do |string|
          string << street unless street.nil?
          string << city unless city.nil?
          string << province unless province.nil?
          string << postal_code unless postal_code.nil?
        end
      end
    end

This simplifies the knowledge we store in the Person class for interacting with an address. Now all we need is to know is that the address has a display method.

As an added benefit, it's far shorter and easier to read.

Being prepared for changes

What happens when we need to output a person's address in both an HTML page and a text-only email? In one case we'll need a simple line break, and in another we'll need HTML formatting such as a <br /> element.

Here's an example:

123 Main Street
Arlington, VA 22222

An updated version of our code which would skip missing data and create our desired output would look like this:

class Address
      def display
        province_and_postal_code = [province, postal_code].compact.join(' ')
        province_and_postal_code = nil if province_and_postal_code.empty?

        city_province_postal_code = [city, province_and_postal_code].compact.join(', ')
        city_province_postal_code = nil if city_province_postal_code.empty?

        [street, city_province_postal_code].compact.join("\n")
      end
    end

With simple text a newline is all we need, but in HTML we'll need to provide a break:

123 Main Street
Arlington, VA 22222

We could add features to our Address class to handle changes like this:

class Address
     def display(line_break)
       # same code as above here ...

       [street, city_province_postal_code].compact.join(line_break)
     end
   end

That seems like a simple change, but in order to use it the Person would need to know what type of line break to provide to the address. This would push the decision for how to display the address far away from the address itself.

Instead, we could keep the information for formatting inside an object whose responsibility is specifically for formatting the information. If we require a new type of format, we would then only need to create an object for that format.

For example, our standard template could handle the data with a newline character.

class Template
      def display_address(address)
        province_and_postal_code = [address.province, address.postal_code].compact.join(' ')
        province_and_postal_code = nil if province_and_postal_code.empty?

        city_province_postal_code = [address.city, province_and_postal_code].compact.join(', ')
        city_province_postal_code = nil if city_province_postal_code.empty?

        [address.street, city_province_postal_code].compact.join("\n")
      end
    end

Then our HTML template could handle the data with proper line breaks for it's format:

class HtmlTemplate
      def display_address(address)
        # same code as above here ...

        [address.street, city_province_postal_code].compact.join("
") end end

We should move the duplicated code to a common location so that each template could share it, but this will do for now.

So how might our Person and Address objects use these templates?

All we'll need to do is change our display_address and display methods to accept a template for the formatting.

class Person
      def display_address(template)
        address.display(template)
      end
    end

    class Address
      def display(template)
        template.display_address(self)
      end
    end

If we add new formats, neither or Person nor our Address class will need to change. There's still more we can do to guard against changes but I'll write more about that next time.

Clean Ruby 1.0 is released!

I'm excited to be able to call Clean Ruby "final".

The compliments to that work have been great. Here's just a few comments I've received for Clean Ruby:

"The current version of Clean Ruby is a great start on a critical topic. Learning how to keep code clear and understandable is useful for any kind of project. I've already applied a couple of ideas from the book to keep a project from mumbling in the shadows."
—David Richards

"I have not come across such a revelatory approach to things since first learning OOP."
—Mike Pence

"Clean Ruby from Jim Gay will change the way you design your Rails apps"
—Hector Sansores

As time goes on, I'll be updating the book with changes to Ruby and new ideas, but it's at a point where you can get some great techniques. Self-publishing this book has been wonderful for handling updates; I'm able to make changes and get them in the hands of my customers as soon as I can. I'm not limited by a publishing house setting my schedule.

My free newsletter has helped me engage with developers from all over the world. I'll be continuing writing there and releasing more useful tools like Casting and Surrounded. I'm eager to try screencasts and more books.

Grab a copy of Clean Ruby and help me celebrate by using the code TAKE10 for $10 off!

Avoiding errors when forwarding to missing objects

The "final" update for Clean Ruby will be released soon. More on that below, but first here are some thoughts on what to do when you've got a missing object.

The Ruby standard library Forwardable is really useful for raising up valuable information and hiding unimportant details.

A single line of code can configure the relationship between two objects and the data they share.

delegate [:street, :city, :state] => :address

I'm often asked: what happens if that address is nil?

In this case, you'll see an error about an undefined method on nil:

NoMethodError: undefined method `street' for nil:NilClass

You might want that, or you might not. It depends on how you want to structure your program.

When using the Forwardable library, the street method above will raise an error if address is missing.

But, it might make the most sense for your application that if there is no address, then there is obviously no street. So a method that handles this will make more sense:

def street
      if address
        address.street
      end
    end

With this requirement, Forwardable seems useless. I don't have a way to configure Forwardable to just skip the nil object and the forwarded message. ActiveSupport (and Rails) adds its own answer to this problem.

delegate :street, :to => :address, :allow_nil => true

By specifying allow_nil the call to street will silently continue returning nothing if the address is nil. This type of approach to managing nil objects is valuable when it's what you want (of course), and can be a life-saver when you're dealing with a large and/or unfamiliar codebase that's throwing up errors where you don't expect them.

A problem with this approach, however, is that the absence of a an object might be an indication that you're missing some vaulable setup steps. Perhaps a missing address is a problem and removing the error hides the problem. You can take your error as encouragement to use a null object, an object which will stand-in for your missing address.

class Person
      def initialize(address)
        @address = address
      end
      def address
        @address || DefaultAddress.new
      end
    end

You likely have a different way to initialize your objects, but with something like the above code we can use a DefaultAddress which can answer for your missing address.

class DefaultAddress
      def street
        "123 Home Base"
      end
    end

By following this design you can easily change your program from displaying nothing, as you do in the case of allow_nil, to displaying a default value. But what's great about this structure is that you can change the default behavior without any change to your Person class.

Before reaching for an option like allow_nil, consider an alternative object instead. How do you handle nil objects in your code?

Lastly, Clean Ruby is out and you can get it now! I'll be keeping the book up to date with relevant changes to Ruby or with any good techniques for Object-oriented programming so "final" true, barring any updates that come along.

Shorter, simpler code with Forwardable

I often find that visual distractions slow me down. Reading simple code with familiar concepts feels cumbersome when I have to sort through repetition to find the meaning.

Take a glance at this code to see what I mean:

class Person
      def street
        address.street
      end

      def city
        address.city
      end

      def state
        address.state
      end
    end

Although the code is short, you have to think a bit before you realize that all of these methods do basically the same thing.

Ruby has a built-in way to bring the information out of this code: Forwardable.

I touched on using Forwardable in a previous article but we'll look closer at what's happening and why you want to use it.

The code above merely forwards the given method to another object. In this case if you try to get address details from a "Person", it will automatically pass it along to the related "address" object.

Given that the procedure is so simple and common in the code, I'd much rather have a way to read that information faster.

require 'forwardable'
    class Person
      extend Forwardable

      delegate [:street, :city, :state] => :address
    end

With this code, the concept of forwarding a message to a collaborating object is so clear that it reads like configuration.

Good configuration is fast and easy to understand.

Forwardable works essentially the same way that the longform code above does. You can provide a list of methods which should be sent to a particular object. Here's what a simplified version of what Forwardable looks like:

module Forwardable
      def delegate(hash)
        hash.each{ |methods, accessor|
          methods.each{ |method|
            instance_eval %{
              def #{method}(*args, &block)
                #{accessor}.__send__(:#{method}, *args, &block)
              end
            }
          }
        }
      end
    end

The "delegate" method accepts a hash where the keys are the method names to forward and the values are the object names to receive the forwarded messages.

For each item in the hash, it will loop through each method name and define a method using instance_eval and the generated string. Those methods send the message along to the object you specified.

The Forwardable code looks complicated, but it's merely 2 loops over a hash and an array, then the instance_eval. The ultimate result is the equivalent of the original code above. With some simple iteration and dynamically defining methods, Forwardable helps us strip away the unimportant parts and raises the valuable information to the top:

delegate [:street, :city, :state] => :address

This shows us what methods will be sent to which object without any additional code to sort through. What could be simpler or easier to scan and understand?

The tools that are right under your nose

I recently had a fantastic experience giving a presentation at RubyConf called The Secrets of the Standard Library. The slides are available and once the video is up I'll send along a link to that.

There are no secrets in the Standard Library

There are no secrets, of course, because the code is right there for you to read but many developers don't realize that powerful tools like SimpleDelegator and Forwardable are built into Ruby. There's no gem to find and install, just require the file you need and you've got it. It's as easy as:

require 'delegate'
class MyWrapper < SimpleDelegator; end

require 'forwardable'
class MyClass
  extend Forwardable
end

My goal in the RubyConf presentation was to show that these tools are available and to describe how they work. Using the tools is one thing, but understanding them is another.

In previous posts we've been looking at ways to use SimpleDelegator to handle presentation behaviors and there's been a bit of Forwardable too. Once you've got a clear understanding of them, you can be more creative with their use and build your own tools to make your code more habitable.

I find that implementing my own library can be a great exercise in understanding an existing one. It was fun to write two short lines in an attempt to create SimpleDelegator and Forwardable in what would fit in less than 140 characters:

# My SimpleDelegator
class D;def initialize(o);@o=o;end;
def method_missing(m, *r, &b);@o.send(m,*r,&b);end;end
# My Forwardable
module Fwd;def fwd(a,m,n=m);self.class_eval
"def #{n}(*r,&b);#{a}.__send__(:#{m},*r,&b);end";end;end

Expanding those out with more descriptive names reveals a bit more about what they do:

# My SimpleDelegator
class Delegator
  def initialize(object)
    @object = object
  end
  def method_missing(method, *args, &block)
    @object.send(method, *args, &block)
  end
end
# My Forwardable
module Forward
  def forward(to, method_name, alternative=method_name)
    self.class_eval "
     def #{alternative}(*args, &block)
       #{to}.__send__(:#{method_name},*args, &block)
     end
    "
  end
end

In both my simple implementation and the actual implementation one uses method_missing at run time and the other defines methods at compile time.

Knowing this, and seeing how they work, can help you make decisions about when to use one over the other. Defined methods are faster than method_missing but they require a more rigid structure.

When do you use SimpleDelegator and when do you use Forwardable?

I generally follow these simple rules for choosing which library to select:

  1. Use SimpleDelegator when you either don't know or don't care which messages may be sent to your object. This excepts (of course) the methods you define in your wrapper.
  2. Use Forwardable when you know the messages to forward ahead of time.

Both libraries follow the same pattern that a message to one object will be sent along unaffected to the relevant object. But there are times when building your own gives you a better understanding and more control over when errors occurr.

Building your own SimpleDelegator can be tricky. There's quite a lot of work done for you already to help ensure that your wrapper acts like the wrapped object so do read the code and get familiar with the trade-offs when writing your own.

Errors instead of method_missing

Sometimes you may want more control or restriction on the behavior of objects.

You can build a wrapper with Forwardable, for example, by swapping out the object of concern and instead of everything passing through method_missing, you'll get a NoMethodError.

Here's a short example:

class Person
  attr_accessor :name, :color, :number, :email
end
require 'forwardable'
class Wrapper
  extend Forwardable
  delegate [:name, :color, :number] => :person

  attr_accessor :person
end
wrapper = Wrapper.new
wrapper.person = person1
wrapper.name #=> person1 name value
wrapper.person = person2
wrapper.name #=> person2 name value
wrapper.email #=> NoMethodError

A wrapper like this allows us to specify only the methods we want to pass-through and any others that person may have will raise an error.

How have you used these libraries? How do you decide what to use?

What have you built to do similar things?

Last but not least, I recently wrote about undestanding delegation on my blog and how it helped me create the casting gem.

If you enjoyed this post, sign-up for my newsletter below and get more.

Delegation is Everything and Inheritance Does Not Exist

Sharing behavior among and between objects requires a balanced decision. Will other objects use this behavior? Which ones? Why? Should I make a new class to handle what I need?

Determining answers led me to dive into exactly what delegation is and inevitably led to more research to get a better understanding of inheritance.

Prefer delegation over inheritance goes the standard advice.

It seems that many developers think about inheritance in terms of classes. Classes define everything about your objects so it must be the only way to handle inheritance. We tend to think about delegation in terms of instances of classes as well.

This mental model mostly works well. But then there's always someone who points out a seemingly contradictory phrase...

Delegation is Inheritance

Lynn Andrea Stein argued that Delegation is Inheritance in her 1987 OOPSLA paper of the same name. It's a fantastic read and an important paper in describing the behavior of Object-oriented systems and what the costs and benefits are to different inheritance schemes.

But this title seems to go against a simple mental model of what inheritance and delegation are.

Classes and Prototypes

First and foremost, object-oriented programs tend to have either class-based or prototype-based inheritance.

Sometimes you'll see comments around the web like this

a problem that Javascript is having is people wanting to force OOP on the language, when fundamentally it’s a prototype-based language

It's certainly a good thing to understand the way a language was designed, but there is no dichotomy between OOP and prototypes.

Prototypes are an object-oriented paradigm.

Classes are a paradigm which groups objects by type. Classes generate instances whose abilities are defined by their class. This is a rigid approach to sharing behavior and is the one provided in Ruby.

Prototypes on the other hand share behavior among individual objects. An object's prototype defines behaviors that may be used on the object itself.

Perhaps a problem that people see in JS development is instead forcing a class-based paradigm on their programs. Perhaps not. I'm not venturing into that debate but recognize that prototypes are OO.

Inheritance Through Delegation

Many (most?) OO programmers are familiar with class-based inheritance systems.

You create a new instance of Thing and that thing instance has all of the abilities defined in its class. This concept is easy to grasp.

Prototype-based inheritance, however, seems much more complex. In order to understand the behavior of one object you also need to understand the behavior provided by its prototype which is just another object. A prototype doesn't necessarily act as an umbrella of classification like classes.

It's harder to think in generalizations outside of a class system. The type of an object is a simple mental model but with prototypes, the possibilities are myriad.

But getting back to the point of this section, class-based inheritance uses delegation to share behavior. A message sent to the instance thing is delegated to the class Thing. All of the behaviors are defined in the class, but self is bound to the object that received the message. The behavior is evaluated in the context of the object. That is: self refers to the instance, not the class (where the behavior is defined).

class Thing
  def hello
    self.inspect
  end
end

thing = Thing.new
thing.hello # <-- delegation to its class which defines the behavior

In a case where two objects exist in a prototype-based system, the same rules apply. The keyword self is bound to the object that received the message and any delegated behavior is defined in another object.

Ruby delegates through classes and as a result caches its methods based upon the classes of objects. This class-based approach means that adding new behavior to an object leads to the cache being cleared because as an instance of a particular class the object's behavior changes and needs to be reflected in the method lookup (defined by its class). Charlie Somerville has a great rundown of things that clear Ruby's method cache.

Our class-colored lenses skew our understanding of delegation.

Inheritance Does Not Exist

This brings me around to why reading Stein's argument about delegation being inheritance is important. Most (or maybe just many) programmers seem to misunderstand what delegation is.

Stein's paper made the argument that delegation is inheritance. Her paper is based upon the definition of delegation citing Henry Lieberman's 1986 paper.

Lynn Stein was recently very helpful to me and suggested that the original understanding of delegation may have come from "Delegation in Message Passing Proceedings of First International Conference on Distributed Systems Huntsville, AL. October 1979". Alas, I can't find that paper online but it is related to the application of the Actor pattern by Carl Hewitt, Beppe Attardi, and Henry Lieberman.

Stein's work was built against the understanding that delegation has a specific meaning. When methods are delegated, they are bound to the object that received the message. The self or this keywords (depending on the language) refer to the original object that received the message.

Many commenters on my delegation article (and on other forums) claimed that the "delegation" term has changed meaning over the years. Lieberman, critics say, may have coined the term but he doesn't own the meaning.

Some have argued that delegation no longer means what Lieberman, Stein, and other OO pioneers meant. If this is true and delegation means 2 objects forwarding messages, and if delegation is inheritance, then effectively every object sending a message is inheritance. Either that or inheritance does not exist.

Why Care?

I've been working around the limitations of implementing DCI in Ruby and the behavior of objects is a central concern.

In DCI our bare data objects gain behavior inside a context relevant to some business goal. Typically this is either explained through the use of extend to add a module to an object's inheritance lookup:

thing.extend(SomeModule)
thing.method_from_module

The problem in Ruby is that the object's inheritance tree remains the same for the life of the object.

# Before
thing.singleton_class.ancestors #=> [Thing, Object, Kernel, BasicObject]
thing.extend(SomeModule)
# After
thing.singleton_class.ancestors #=> [SomeModule, Thing, Object, Kernel, BasicObject]

The thing object is forever tied to it's new set of ancestors. This may affect your program if you expect your object to lose behavior after executing some procedure inside a DCI context.

There are projects which hack Ruby to add unextend or other like methods, but they are additions to Ruby typically only in one interpreter (like MRI).

What Can Ruby Do?

A new feature of Ruby 2.0 is exciting in the abilities we'll have to build libraries that aid in delegation.

Methods defined in modules may now be bound to objects regardless of their class ancestry.

SomeModule.instance_method(:method_from_module).bind(thing).call

That code is a mouthful, but it shows (in Ruby 2.0) that we can add behavior to objects without extending them.

If we want to implement a delegation technique we could hide all this inside a method.

def delegate(method_name, mod)
  mod.instance_method(method_name).bind(self).call
end

This is an approach I built into casting, a gem that helps add behavior to objects, preserves the binding of self inside shared methods and leaves the object in it's original state.

It's easy to use, but it takes a different view of what delegation is compared to how most Ruby developers seem to think. The delegated method here will preserve the self reference to the thing object and behavior is added without extending the object.

class Thing
  include Casting::Client
end

thing.delegate('some_method', SomeModule)

It's a work in progress and has given me a great reason to explore what Ruby can and can't do.

The Best of Both Worlds

Stein's paper suggested that a hybrid system of both class-based and prototype-based inheritance would provide both rigidity and flexibility when needed.

As I've worked with my code more and researched more for Clean Ruby I've had the desire for a hybrid system. Stein's words ring true:

In order to take full advantage of the potential of such a system, objects must be treated simply as objects, rather than as classes or instances.

Indeed, DCI requires a system where an object gains and loses behavior based upon the context. The behaviors are localized to the context and a hybrid system like the one Stein described would benefit from the advancement of DCI.

This is a challenge to implement in Ruby but I'll be working more on casting in the future.

For now, it's useful to consider the contextual behavior of our objects and think less about the classes that define them and more about the message passing among them.

Focus on the behavior of your system first, use delegation and worry about classes later.

How abstractions encourage good thinking

Many times, as developers, we grow our code in ways we don't intend. We live with quick decisions a little too long and end up with a problem where, well, we don't see the problem. With too much of this, our code becomes our unkempt bedroom or messy desk.

Working against your brain

A few years ago I saw an excellent presentation at Rocky Mountain Ruby by Michael Feathers about a phenomenon he called "code blindness." In that keynote he raised the point that despite the fact developers may know how to, or know why our code should be structured differently, we become used to seeing things the way they are and no longer recognize real or potential problems. We become blind to it.

This type of behavior is a result of how our brains react to visual clutter. As we add more information, more objects, and more variablity to the environment we're creating, our brains will dampen the signals from each part and hide their influences on our attention.

The dampening of each stimulus is a way we cope with too much information. The NIH released a news advisory in 1998 which explained how our brains can counterbalance the dampening effect with focused attention. So what exactly does this mean and how does it apply to programming?

Read the NIH advisory here.

Our programming languages are merely ways of representing concepts. Our brains translate characters to representations of things, to describe iteration, to define decisions and outcomes, and more. The more variation and number of concepts we require our brains to translate, the harder it becomes to maintain focused understanding of any individual concept.

This, of course, leads to the development of ideas such as separation of concerns, the single responsibility principle, and others in which we aim to remove visual clutter form our code and reduce the cognitive load on our brains required to translate stimuli into ideas.

By dampening the effect of stimuli, our brains are able to better focus on the immediate task. The studies at the NIH revealed that by placing effort to focus on a particular aspect of our environments we are able to counteract the dampening feature of our brains. This makes quite a bit of sense: pay attention to something and you're more likely to notice it. But as the NIH points out that while we may only partially cancel-out the effects of nearby stimuli, the amount of the attention required increased in tandem with the amount of visual clutter.

Living with complexity and clutter in our code is often a way we decide to get work done faster now and come up with a better solution later. Unfortunately it is also a decision to create an environment where we'll have to work harder in the future to focus on the right thing.

Working with your brain

The more we have in our environments demanding attention, the more our brains will dampen our attention to them.

Abstractions, such as the presenters we've reviewed in previous articles, are a way we can remove visual clutter and unnecessary stimuli. Separating our programs into layers of responsibility is a way of working with our brains to ensure they'll only need to place just enough effort required to maintain focus and understanding of a particular concept.

The act of building these layers in our programs is how we make decisions to work with our brains' ability to manage focus and prevent the dampening effect from slowing down our work.

This introduces to our program our idea of habitable code. What we consider to be a place where our brains will function well will be expressed in our program code. Often, the place I find the most trouble is with view templates. As a result I work to treat these as much as possible like configuration where logic and number of distinct objects are kept to a minimum.

Transformations of data are often a place where confusing details can cause us to filter out valuable concepts from our minds. View templates which contain multiple objects, transformations of data, control structures such as if/else/unless blocks or iteration are a source of clutter.

Visual clutter can appear all over or merely in a single line.

link_to timeslot.in_time_zone(@timezone).strftime("%l:%M%p"), 
      new_profile_appointments_calendar_event_path(@calendar.profile, @calendar, 
      :event_slot_id => event_id, :timezone_name => @timezone.name), 
      :class => "open", rel: 'nofollow'

When we write code we create the environment in which our brains must function and react. Often, we end up creating these cognitive barriers in our view templates like this. Fortunately, we're able to simplify them with techniques like pushing complexity into a presenter layer.

If you review the code sample above, you'll need to spend quite a bit of time, far more than you should, just to understand what will be output.

It's important to make decisions to remove the parts unimportant to us. The abstractions which we create can remove as much information as we decide. Leaving parts for our brains to compose can be a feature:

link_to time_display, new_event_path, class: "open", rel: "nofollow"

Or creating a small footprint to handle a concept at a higher level allows us to remove visual clutter and removes the need to compose parts.

presenter.new_event_link(class: "open", rel: "nofollow")

These sample bits of code show no implementation, but the great thing about programming is that we get to choose. The choices we make might work with our brains or might work against them. We can push away noisy details like which timezone to use for formatting and how how to

Our divide and conquer approach with abstraction layers helps us to filter out noise from signal. Of course, with too much abstraction we may become mired in the noise created by divided ideas but we get to decide and experience what fits best.

Work with your brain and consider what ideas belong in which places. Write the code you wish to have.

Get a FREE sample chapter

Get a sample chapter of Clean Ruby and you'll be added to my periodic newsletter of helpful Ruby tips.