Command Objects


In any Unix based OS the command line reigns supreme. Commmands are predictable, and return zero for success and non-zero for failures.

Rules

The same principles can be applied to programming with some minor rule alterations.

  • Class name must be in a similar format to VerbNoun (ex. CreateResource).
  • Instance must have an #execute method. It can accept arguments.
  • The only instance method that should be accessed is the #execute method.
  • The return type for #execute must be a Boolean.

Example

A basic command object will look like the following:

class CreateUser
  attr_reader :user

  # @param [Hash] params
  def initialize(params={})
    @user = User.new(params)
  end

  # @return [Boolean]
  def execute
    user.persisted? ? false : user.save
  end
end

Inside of the controller it would be applied like this:

class RegistrationsController < ApplicationController
  # ...

  def create
    command = CreateUser.new(user_params)

    if command.execute
      sign_in(command.user)
      redirect_to welcome_path
    else
      @user = command.user
      render action: 'new'
    end
  end

  # ...
end

These rules are fairly simple to follow. The command object is not supposed to be complex. It is supposed to break other complex tasks down into digestable, easy to maintain, and an easy to test format. If the command starts to become complex, consider extracting code into services or refactoring the command.

if all you have is a hammer, everything looks like a nail - Abraham Maslow

Remember not everything looks like a nail, so apply this design pattern with care and understand why others may opt for this in their application and why it may or may not be a good fit for your application.

Resources

State Machines


A state machine is an interesting design pattern.

The state_machine gem is a great library. It provides a nice structure to declare states and transitions. It also provides nice callback hooks that can be utilized to run specific actions before or after a transition happens.

It has hooks into ActiveRecord and saves the model when the transition from one state to another is successful. The gem also works just fine with plain old ruby objects as well. Here is a simple example of a state machine.

class Ticket < ActiveRecord::Base
  state_machine :state, :initial => :stopped do
    state :stopped
    state :started

    event :start do
      transition :stopped => :started
    end

    event :stop do
      transition :started => :stopped
    end
  end
end

To interact with the state machine, you can do the following:

ticket = Ticket.create(subject: 'New issue with post', content: 'Some text')
ticket.start #=> true
ticket.state #=> 'started'
ticket.start #=> false
ticket.state #=> 'started'
ticket.stop  #=> true
ticket.state #=> 'stopped'

Earlier in Dumb Data Objects I talked very briefly about how to integrate a state machine into a Dumb Data Object. What this gem brings to the table is another way back into “Callback Hell”, and that is something everyone should avoid.

The transition callbacks are there to be used sparingly. If the need arises to apply a callback to the state machine, think about the implications this can have on the object through out its lifetime. Will this callback make interaction easier or will it complicate the model and make it difficult for someone else to pick up?

One callback that is typically rife with code smell is the after_transition callback. This callback will trigger an action after a transition from one state to another has taken place. Why not just execute that method after the event was triggered? It’s very easy to do.

State machines are supposed to be simple. If transitions become complex, then the state machine flow becomes disruptive and difficult to ascertain. The ultimate goal is to move crazy logic out of the model and push that off into service objects and command objects like the following:

class StartTicket
  def initialize(ticket)
    @ticket = ticket
  end

  def execute
    if @ticket.start
      notify = NotifyTicketSubscribers.new(@ticket)
      notify.send_ticket_started_email
      true
    else
      false
    end
  end
end

If I were to mix in the Signals Gem and implement a command pattern, it would look like the following:

class StartTicket
  include Signals::Publisher

  def initialize(ticket)
    @ticket = ticket
  end

  def execute
    if @ticket.start
      broadcast(:start_ticket_successful, @ticket)
    else
      broadcast(:start_ticket_failed, @ticket)
    end
  end
end

Testing StartTicket becomes really easy at this point.

# Use 'rspec', >= '2.14.0.rc1' in order to
# utilize test spies
describe StartTicket do
  describe '#execute' do
    it 'should start the ticket' do
      # Mock
      ticket = double('Ticket', start: true)
      command = StartTicket.new(ticket)
      command.stub(broadcast: true)

      # Excercise
      command.execute

      # Verify
      command.should(
        have_received(:broadcast).
        with(:start_ticket_successful, ticket)
      ).once
      ticket.should have_received(:start).once
    end
  end
end

The after_transition callbacks will be pushed off onto the listeners and before_transition calls will be done before the event is ever triggered in the StartTicket#execute method.

class TicketListener
  include Signals::Subscriber

  listen_for :start_ticket_successful => :send_ticket_started_email
  listen_for :stop_ticket_successful => :send_ticket_stopped_email

  def send_ticket_started_email(ticket)
    # Send out emails
  end

  def send_ticket_stopped_email(ticket)
    # Send out emails
  end
end

Piecing it all together, results in this simple use case.

ticket  = Ticket.find(1)
command = StartTicket.new(ticket)
command.subscribe(TicketListener.new)
command.execute

Yes there is a lot of boiler-plate code, but trust me when I say the benefits greatly out weighs the drawbacks.

For the love that is programming and refactoring, stay away from callbacks!

Resources

Dumb Data Objects


As a Rails application grows and evolves. Fat models often become rampant in the application. ActiveRecord callbacks are used and models start interacting with other models in ways they should not.

memes/activerecord-bad-time.jpg

Enter the idea of “dumb data objects”. It is nothing more than a simple data structure. It holds state and that is it. Only methods that display data or modify the internal state should be on the model.

This is of course very opinionated, but I do believe it has a lot of merit.

# app/models/user.rb
class User < ActiveRecord::Base
  def activate
    active = true
    self.save
  end

  def deactivate
    active = false
    self.save
  end
end
# app/services/create_user.rb
class CreateUser
  attr_reader :user

  def initialize(params={})
    @user = User.new(params)
  end

  def execute
    @user.save ? @user : false
  end
end

Instead of having all the heavy lifting done with the models. The idea is to shift the burden to Service Objects, Query Objects, and form objects.

Remember, Rails is just a large library of Ruby code. You are simply working with Ruby objects. Nothing is forcing us to stuff everything into models. It took me over a year to figure that out when I first started using Rails.

Quick Questions

What can I do to replace my ActiveRecord callbacks?

You wont need to replace them completely. If and only if the callback is modifying internal state alone, then the callback doesn’t necessarily need to be removed. However, if it is creating other objects and or modifying external resources, it should be moved into the service object.

Where can state machines fit into this?

The answer is simple, state machines will reside within the model it is intended for. Remember, my definition of dumb data objects are objects whose methods only modify internal state or transform data residing on that object.

Resources

Services and Pub Sub


The Publish-Subscribe pattern is a great way to make code modular and decoupled from the rest of the architecture. It also has a nice side-effect of making testing easier and classes smaller.

In a pub-sub pattern, publishers don’t know anything about its subscribers and subscribers don’t know anything about who is publishing to it. Subscribers are simply listening for specific messages and handling them accordingly and publishers are simply broadcasting messages.

Subscribers are meant to be reused with other publishers. Though often some subscribers will only be used in one place. The value add with this approach is that the subscriber can be removed at anytime and readded. If one were to implement a feature flipper, dynamically adding subscribers can be a big win.

Let’s take a dive into the Signals gem.

At a basic level a publisher can be considered a service object and any calls to and external service can be a subscriber. Subscribers need a way to listen for specific events and fire off the appropriate actions.

class ActivityListener
  include Signals::Subscriber

  listen_for :failed_login => :log_failed_attempt

  def log_failed_attempt(user)
    # ... some security audit stuff ...
  end
end

The ActivityListener is now isolated away from what other subscribers are doing. This makes testing really simple. A mocked user could be passed in and test spies could be used to ensure that the proper methods were invoked.

Sometimes there are events that will take place that need to have multiple actions taken. For example, when a user creates a subscription the application will probably need to send a confirmation email along with talking to a payment gateway while logging the request to some security tracker. This is a strawman example, but it is something that can happen.

class ActivityListener
  include Signals::Subscriber

  listen_for [:logged_in, :logged_out] => :log_activity

  def log_activity(user)
    # ... something ...
  end
end

Example

This is something similar to how I use Signals in production. This does assume you are using Delayed Jobs, however if you are using a different background job tool, I’m sure the conversion is easy enough.

# app/services/create_user.rb
class CreateUser
  include Signals::Publisher

  def initialize(params={})
    @user = User.new(params)
  end

  def execute
    if @user.save
      broadcast(:create_user_successful, @user)
    else
      broadcast(:create_user_failed, @user)
    end
  end
end
# app/jobs/welcome_email_job.rb
class WelcomeEmailJob
  def initialize(id)
    @id = id
  end

  def perform
    user = User.find(@id)
    EmailListener.new.user_created(user)
  end
end
# app/listeners/email_listener.rb
class EmailListener
  include Signals::Subscriber

  listen_for :create_user_successful => :enqueue_user_created

  def enqueue_user_created(user)
    Delayed::Job.enqueue(WelcomeEmailJob.new(user.id))
  end

  def user_created(user)
    WelcomeMailer.welcome_email(user).deliver
  end
end
# app/controllers/users_controller.rb
class UsersController < ApplicationController
  # ...
  def create
    service = CreateUser.new(user_params)
    service.subscribe(EmailListener.new)
    service.on(:create_user_successful) do |user|
      redirect_to root_url
    end
    service.on(:create_user_failed) do |user|
      @user = user
      render action: 'new'
    end
    service.execute
  end
  # ...
end

Resources

These are some resources I found extremely helpful as I wrote the library to further my understanding of the publish-subscriber pattern.

Task Based Threading


Task based thread execution is a great way to do threading in an application. Taking the same idea that is used in web development can be applied directly to any application that can utilize threads.

When working with a web application, often the application will need to send an email to a customer without slowing down the user’s request. Background jobs are typically used for slow; long running tasks that can be processed later.

These background jobs are normally added to queue and multiple workers are processing them simultaneously. Often I have been guilty of writing baddly threaded Java applications (C is not exempt from this either). I would make a few Runnable tasks that would have an infinite loop and just spawn threads to process the tasks. This was my naive way of thinking.

// SomeBadJob.java
public class SomeBadJob implements Runnable {
    public void run() {
        while(true) {
            // Some loop to crunch numbers
        }
    }
}

In reality, the maximum number of threads running concurrently is based on the number of cores available on the CPU. So if I spawned five threads, one of them will be context switching and that is not free.

Solution

Stop writing individual tasks and break it down to a smaller tasks. Each runnable task should be executed once, and then return. For example:

// MovePlayerTask.java
public class MovePlayerTask implements Runnable {
    private Player player;

    public MovePlayerTask(Player player) {
        this.player = player;
    }

    public void run() {
        player.move(Direction.SOUTH, 1);
    }
}

Testing these runnable tasks becomes very easy and the overall complexity of the runnable job has been reduced significantly.

How this task can be rans is by wrapping Java’s ThreadPoolExecutor into a class called Scheduler and is setup as a singleton. This is because there is no need to have multiple schedulers around.

// Scheduler.java
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * A very thin wrapper around ThreadPoolExecutor
 *
 * @author Matthew A. Johnston
 */
public class Scheduler {
    private static Scheduler instance;

    private ThreadPoolExecutor executor;
    private LinkedBlockingQueue<Runnable> queue;

    public Scheduler() {
        int processors = Runtime.getRuntime().availableProcessors();
        queue = new LinkedBlockingQueue<Runnable>();
        executor = new ThreadPoolExecutor(processors, 10, 10, TimeUnit.SECONDS, queue);
    }

    public void schedule(Runnable runnable) {
        executor.execute(runnable);
    }

    public static void scheduleTask(Runnable runnable) {
        getInstance().schedule(runnable);
    }

    public static Scheduler getInstance() {
        if (instance == null) {
            instance = new Scheduler();
        }
        return instance;
    }
}

To execute the MovePlayerTask all that is necessary is the following:

player = Game.getPlayer();
Scheduler.scheduleTask(new MovePlayerTask(player));

The MovePlayerTask will be executed once and to execute it again, all that is necessary is to re-enqueue the task. I have found that this approach will scale very well as computer hardware progresses. As the number of cores available increases, so will the number of workers.

Limitations

It is possible to fill the Scheduler queue up with jobs faster than it can process. Though I have not run into this issue yet, however the LinkedBlockingQueue that the ThreadPoolExecutor uses will not allow an new task to be scheduled until it is able to do so. If the application is time critical, a time delta should be used in the task’s run() method.

Resources