Tom Kadwill

Domain Driven Design, Key Points. Part 1

This post outlines the key points of Domain-Driven Design by Eric Evans.

1. Continuous Learning & Knowledge Crunching
Regulary converse with domain experts to develop a language, based on the model. Seek to continously improve the model.

2. Ubiquitous Language
Developers should pursue a ubiquitous language; one that helps developers and domain experts talk about the same model. A change in the language represents a change in the model.

3. Unifying your model with your code
Any representation of the model (documentation, UML or diagrams) should tie in directly to your code. You should see the same model concepts in your code that you see on a diagram.

4. Isolating to domain
Separate the domain logic from non-business specific code (UI, Database, Currency ect).

5. Coding the model
Associations between objects is a key component of good domain design:

5.1. Impose a direction
5.2. Add a qualifier (eg. rather than saying a country has had many presidents, we can say that a country has one present at any one time. This reduces the association to a one-to-one)
5.3. Eliminate non-essential associations

Entities are unique objects that are defined by more than just their attributes (a person or a car).

When modeling entity objects, strip the objects down to its defining characteristics. Any attributes that are not essential should be moved into other objects associated with the core entity.

Value objects have no identity and are interchangeable with other value objects. Value objects are transient, they can be destroyed or created without thought. Value objects are immutable.

Value objects should be used to simplify entities. For example, an address can be removed from a Customer class, into an address value object.

Services Some concepts do not belong as objects, they may be more suited to services. A service should be stateless.

Modules Modules should have low coupling in the sense that they can be understood independently. Give modules a name that becomes part of the ubiquitous language.

6. Domain Object Life Cycle
An Aggregate is a cluster of associated objects that we treat as a unit (eg, a car). Aggregates have one root which is allowed to communicate with external objects.

A Factory should be used when creation of an object or aggregate becomes complex. Assembly corresponds to a milestone in the domain (eg. open a bank account). When designing the interface:
6.1. You must pass in everything required to create a complete product
6.2. A factory will be coupled to its arguments. Picking lots of parts out of objects to use as arguments can create a rats nest.

A Repository represents all objects of a certain type; it acts like a collection except it allows for more elaborate queriying capabilities.

7. Constantly Re-factor
Constantly re-factor towards a deeper insight, small changes can add up and lead to large changes in the model.

8. Making implicit concepts implicit
When domain experts use words that are not in the design, that is a lead. Scrutinize awkwardness in your domain model and study contraditions. Use predicate value objects for specifications.

Before Type Cast

Recently I came across Rails’ attribute_before_type_cast method. This is great for manipulating objects as string where you wouldn’t have a chance to do so otherwise. For example, I once had a situation where I was using a Money gem and I wanted to remove the currency symbol in a few cases. The gem did not have any functionality for this.

If I had known about attribute_before_type_cast I could have simply manipulated the value as a string:

1
2
3
def as_dollar
  price_before_type_cast.gsub("£", "$")
end

Rails Serialization

Here is a quick example of Serialization in Rails 4. For this example I’ll be adding perferences to a user. Preferences are a common use case for serialization because we can store the perferences against each user, as text. We can then de-serialize and parse the perferences, in a nicely structured way.

Rails provides the serialize method but in this case it is more convenient to use store. store is a wrapper for serialize designed for storing hashes.

First, lets add a migration.

1
2
3
4
5
class AddOptionsToUsers < ActiveRecord::Migration
  def change
    add_column :users, :preferences, :text
  end
end

Lets also add store to the User model.

1
2
3
class User < ActiveRecord::Base
  store :preferences
end

After setting up perferences as a serialized attribute we can save a hash to it.

1
$ user.preferences = {admin: true}

We can access the new preferences option via:

1
2
$ user.preferences[:admin]
  => true

But There is an easier way, which is to use accessors.

1
2
3
class User < ActiveRecord::Base
  store :preferences, accessors: [:admin]
end

Now Rails will provide an admin method for saving to preferences[:admin]:

1
$ user.admin = true

Finally, we can also add accessors using store_accessor:

1
2
3
4
class User < ActiveRecord::Base
  store :preferences, accessors: [:admin]
  store_accessor :preferences, :manager
end

This also tells Rails to add a setter method, just like before:

1
$ user.manager = true

Using store_accessor also gives us a nice getter method:

1
2
$ user.manager
  => true

Rails Callback Inheritance and Types

Rails controllers can inherit callbacks from parent controllers. Most controllers will inherit from ApplicationController so this is a good place to put callbacks that you want to share across all of your controllers.

Remember that callbacks from the base class are run first and thus it is possible to ‘skip’ the callback of the subclass altogether. In the example below the base class implements a method to redirect the user to google.com. I have also implemented a HomeController which implements a callback that adds a debug message to the log.

1
2
3
4
5
6
7
8
9
class ApplicationController < ActionController::Base
  before_action :redirect_to_user

  private

  def redirect_to_user
    redirect_to 'http://www.google.com'
  end
end
1
2
3
4
5
6
7
8
9
class HomeController < ApplicationController
  after_action :call_logger

  private

  def call_logger
    logger.debug 'HomeController log'
  end
end

When the user visits a page served by the HomeController Rails will first run the call back in the ApplicationController redirecting the user to google.com. As a result, the call_logger callback in the HomeController is never run.

Action Callback types

There are three types of callbacks. The first are method callbacks, like the example above. The second are callback classes which allow programmers to reuse callback code.

1
2
3
4
5
6
7
8
9
class AddDebug
  def self.before(controller)
    controller.logger.debug "AddDebug class"
  end
end

class ApplicationController < ActionController::Base
  before_action AddDebug
end

The third are inline methods/blocks.

1
2
3
4
5
class ApplicationController < ActionController::Base
  before_action do
    logger.debug 'before_action blog log'
  end
end

Route Constraints

Rails route constraints are useful if you want to only allow a specific segment key (eg, only integers). The route below uses a regex expression to filter by the id segment; if the id is an integer then it will route to the show action, otherwise it will fall through to the index action.

1
2
  get 'questions/:id' => 'questions#show', constraints: { id: /\d+/ }
  get 'questions/:id' => 'questions#index'

You also have access to the request object, which you can use if you need more control. The example below routes to the show action only if the id is lower than 100.

1
2
  get 'questions/:id' => 'questions#show', constraints: proc {|request| request.params[:id].to_i < 100 }
  get 'questions/:id' => 'questions#index'

Rails routes can of course be re-written using scopes and the rule is no different when using constraints. Our first example could be re-written as:

1
2
3
4
  scope controller: :questions, path: :questions do
    get ':id' => :show, constraints: { id: /\d+/ }
    get ':id' => :index
  end

You can also nest specific routes inside a constraints block, within your scope. This allows constraints to be added to certain routes only:

1
2
3
4
5
6
  scope controller: :questions, path: :questions do
    constraints id: /\d+/ do
      get ':id' => :show
    end
    get ':id' => :index
  end

Finally, Rails allows you to reuse constraints in a modular way. Simply create an object that has a matches? method and pass it into the constraints method:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class IdConstraint
  def self.matches?(request)
    request.params[:id] =~ /\d+/
  end
end

Rails.application.routes.draw do
  scope controller: :questions, path: :questions do
    constraints IdConstraint do
      get ':id' => :show
    end
    get ':id' => :index
  end
end

REST

REST stands for Representational State Transfer (ReST), the idea is to use HTTP calls between machines rather than complex mechanisms like CORBA, RPC or SOAP. In a sense the web itself can be viewed as having REST-based architecture as it is based on HTTP.

RESTful applications use HTTP requests for all four CRUD operations:

  • reading data, querying the DB (Read)
  • posting data, create and/or update (Create, Update)
  • deleting data (Delete)

About REST

  • Platform independent (Unix, Mac or Windows)
  • Language-independent (JavaScript can talk to Ruby, for example)
  • Standards-based (runs on top of HTTP)
  • No built in security or encryption

Simplicity

A typical request using SOAP would look something like the one below, all of which has to be sent via HTTP POST.

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding">
 <soap:body pb="http://www.acme.com/phonebook">
  <pb:GetUserDetails>
   <pb:UserID>12345</pb:UserID>
  </pb:GetUserDetails>
 </soap:Body>
</soap:Envelope>

With REST the request might look something like:

1
http://www.acme.com/phonebook/UserDetails/12345

No request body is required and the url is sent to the server using a simpler HTTP GET. Aside from the obvious simplicity, another advantage is that when using REST all you need is a network connection and you can even test the API directly in the browser.

More complex REST requests

The previous example was a simple one, with a single parameter. REST can also handle multiple parameters via HTTP GET:

1
http://www.acme.com/phonebook/UserDetails?firstName=John&lastName=Doe

If you want to pass longer parameters then you would typically use HTTP POST.

GET vs POST

GET requests should be used for read-only queries that do not change the state of the server’s data. POST requests should be used for creating, updating and deleting.

REST response

Unlike SOAP, REST is not bound to XML. Possible formats include CSV and JSON. HTML should only be used when the service is documented to return a human-readable document.

REST design guidelines

  1. Don’t point to physical files – Use http://www.acme.com/inventory/product/003 not http://www.acme.com/inventory/product003.xml
  2. Queries should not return an overload of data, if required, use pagination.
  3. GET access requests should never change state.

References

This post is a simplified version of Dr. M. Elkstein’s REST series.

Ruby Blocks

As a Ruby programmer I frequently use blocks. Most programmers first touch blocks during their first ruby tutorial when they learn to iterate over an array. This is a common use for blocks but they are far more powerful.

What is a block?

A block is similar to a callback, it is a chunk of code that you wish to execute a little later. Blocks can take 1 of the following forms:

1
thing.each {|thing| thing + 1 }

or

1
2
3
thing.each do |thing|
   thing + 1
end

What does a block do?

The idea is that you pass a block (chunk of code) into a method. That method then decides what to do with the block.

Procs

Blocks are essentially annoymous, you can pass them into methods but you cannot assign them to variables to reference. in order to that you need to use the proc keyword. A proc lets you turn a block into an object, allowing you to reference it. Once you have created a proc you can use the call method to execute the block.

1
2
hello_world = proc { puts 'hello world!' }
hello_world.call # prints "hello world!\n"

Procs can also take parameters.

1
2
hello_world = proc {|name| puts 'hello #{name}' }
hello_world.call('Tom') # prints "hello Tom\n"

Blocks and method parameters

Every method, whatever its parameter list, can optionally be passed a block as a parameter. This is know as the default block and you can access it, within the method, using the keyword yeild.

1
2
3
4
5
6
def two_times(title)
   puts title
   yeild
   yeild
end
two_times('hello') { puts 'world' }

We can also rewrite this method to use procs.

1
2
3
4
5
6
7
def two_times(title, action)
   puts title
   action.call
   action.call
end
action = proc { puts 'world' }
two_times('hello', action)

The cool thing here is that, using the default block, we can write methods that act almost like Ruby keywords. For example, in Ruby we have each.do.... After defining the method above, we can call two_times.do... which looks just like a build in Ruby method.

Note that default blocks can also accept parameters just like any other block.

1
2
3
4
5
def two_times
   yeild 0
   yeild 1
end
count {|i| puts 'position #{number}' }

Methods that work with or without a block

It is possible to write methods that work both with and without having a block passed to them. You can do this using the line yeild if block_given?.

Block to a proc

Ruby makes it possible for a method to turn a block that it recieves into a proc using the & symbol.

1
2
3
4
5
def two_times(&p)
   p.call
   p.call
end
count { puts 'position #{number}' }

Proc to a block

This also works in reverse so you can turn a proc into a default block.

1
2
stuff = proc {|thing| thing + 1}
something.each(&stuff)

Lambdas

Almost idential to procs with two differences:

  1. Procs do not care how many arguments are passed to it. Lambdas will throw an error if it is passed the wrong number of arguments.
  2. When using return within a proc it returns from the method. If used within a Lambda is it returned from the block.

Rails Sessions Hash

This post looks at Rails sessions, specifically the Rails session hash and how to use it in an application.

A session is used to persist data for longer than a typical browser request. For example, most modern web applications will store your user session so that once you have logged in you don’t need to re-enter your user information each time you visit the site.

The first thing to know is that rails provides a sessions hash.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def login
  if user = session[:user]
    login_user user
  else
    render 'new'
  end
end

...

def sign_in
  user = User.find(params[:id])
  session[:user] = user
  login_user user
end

Using the sessions hash you can write a controller action similar to the login action above. The first time the login method is called the user is redirected to the new user form. The new user form will post to sign_in which will find the user and assign it to the sessions hash, before logging the user in. The next time login is triggered it will get the user from the sessions hash and login the user in straight away.

Typically the sessions will persist until the user closes their browser. If we inspect the page we can see how Rails implements a session on the clients browser. Rails creates a cookie which is set to expire with the session – hence when the user closes their browser, the session ends and the cookie disappears. After setting a user to the session hash (line 13) you will see that the size of the cookie increases, indicating that the user’s data has indeed been saved to the session.

In a real world application we often want to persist data even after the user closes their browser. Michael Hartl’s book Learn Rails by Example walks you through storing sessions in the database. I recommend that you check it out to learn more about using sessions in production code.

Rails 4 Forms with Virtual Attributes

There are times when you want to post an attribute along with the rest of your form parameters which is not a field in the database. With Rails, you can achieve this by creating a virtual attribute. This post explains how to create virtual attributes for a form, using Rails 4.

First, imagine that we have a User model with a name and email field. The form might look something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
<%= form_for @user do |f| %>
<ol>
  <li>
    <%= f.label :name, 'Full Name' %>
    <%= f.text_field :name %>
  </li>
  <li>
    <%= f.label :email, 'Email' %>
    <%= f.password_field :email %>
  </li>
  <%= f.submit %>
</ol>
<% end %>

Now imagine that we want to add a nickname field but we don’t want to set nickname in the database. The first thing we need to do is to add the field to the form:

1
2
3
4
<li>
  <%= f.label :nick_name, 'Nick Name' %>
  <%= f.text_field :nick_name %>
</li>

Next we need to create the virtual attribute in the User model. We can do that using attr_accessor. This method creates getter and setter methods for the new attribute allowing us to set the value after submitting the form. Your model with look something like this:

1
2
3
class User < ActiveRecord::Base
  attr_accessor :nick_name
end

Finally, we need to set up the controller to receive the params and create a new User record.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
  def create
    @user = User.new(user_params)
    if @user.save
      render "index"
    else
      render "new"
    end
  end

  private

  def user_params
    params.require(:user).permit(:name, :email, :nick_name)
  end

Rails 4 uses strong parameters, meaning developers cannot mass assign attributes by default. Rails 4 also prefers that you specify allowed attributes in the controllers rather than the model, as it was previously.

In the example above I create a method user_params which allows me to specify which params the User model will permit. To create a new user I simply call User.new and pass in user_params.

Atom Packages

Github recently released Atom, a new ‘hackable’ text editor. I’ve switched to using Atom full time to experience the good and the bad.

Prior to the switch I was using Vim; the transition from a modal text editor to a shortcut based text editor has been interesting. There are some features that I like but there are some features of Vim that I really miss. To fill the gap, I have been busy writing a few packages.

  1. atom-rails – I wrote this package to bring the best features of tpope’s vim-rails to Atom. The plugin allows for jumping between associated models, controllers and views. I want to expand the plugin to include more advanced features like rails generate shortcuts and jumping to partial files.

  2. find-letter – This plugin attempts to mimic Vim’s t and f commands where you can jump to the next occurance of a character. I’m not sure how useful this will be in a non-modal text editor but it will be fun to see.

I hope people find these plugins useful and I would love to hear your feedback.