Book now

Hexagonal Rails

Interview on QCon: BDD, Cucumber and Hexagonal Architectures

I was interviewed recently by QCon’s Peter Bell about various subjects dear to my heart: BDD, Cucumber, Relish and hexagonal architectures.

Click here to watch the video

Agile / Lean Software Development
BDD
Hexagonal Rails
Relish

Comments (0)

Permalink

Triangulating from GOOS – Great books on Object Oriented Design

A few weeks ago I asked on GOOS the mailing list about some other books that teach the same style of design.

I’ve just put together a big order for the juiciest looking ones. Here they are:

  • Concurrency: State Models and Java Programs by Jeff Magee
  • Object Design: Roles, Responsibilities and Collaborations by Rebecca Wirfs-Brock
  • Object Thinking by David West
  • Object-oriented Design Heuristics by Arthur J. Riel
  • Object-Oriented Programming by Peter Coad

Would you add any to this list?

Agile / Lean Software Development
Hexagonal Rails

Comments (7)

Permalink

Matt vs NYC

New York is one of my favourite cities in the world. I’m extremely fortunate to be able to spend a whole week there next week. I’ll be mostly hanging out at QCon:

I’m also going to run a couple of sessions at General Assembly on Thursday evening. If you can’t afford the time or ticket price for QCon, this might be a good option to come along and hear some of my ideas:

  • At 6pm on Thursday I’ll be doing an intro-level talk on BDD. It’s aimed at business people, development managers etc who want to get an idea of the benefits of specification by example and a wider BDD process. Sign up here.
  • at 8pm on Thursday I’ll be doing my ‘BDD as if you meant it’ demonstration, using the example from the middle section of The Cucumber Book. If you’re already using Cucumber, this should give you some fresh perspective and insights about how to use it most effectively. Sign up here.

Finally, I’m honoured to be spending Saturday on the bill with some amazing people at the Gotham Ruby Conference. I’m going to be speaking about hexagonal rails. I’m excited and nervous about this talk, as I feel like I’m still discovering so much about this topic all the time.

As well as all this geekery, I’d love to get some proper culture while I’m in town. Are there any locals who would like to show me around?

Agile / Lean Software Development
BDD
Hexagonal Rails
Ruby Programming

Comments (1)

Permalink

Hexagonal Rails: Objects, Values and Hexagons

This is the second post in a series about my experience of applying a GOOS-style hexagonal architecture to a Ruby on Rails application. In the first post, I talked about why the idiomatic, connected, style of Rails architecture might have advantages in the short term, but that I want a more modular architecture to make it habitable for the long term.

In this post, I’ll explain a couple of the fundamental concepts that will be used in the rest of the series, which should give you some new ideas to think about as you’re working on your own Rails applications. We’ll talk about the tell, don’t ask style of object communication, and about the difference between objects and values. Let’s start by explaining what that funny term hexagonal architecture actually means.

So what is a hexagonal architecture?

The fundamental idea behind this style of architecture is to isolate the core domain of your program—the bit that defines its unique and interesting behaviour—from the technical infrastructure that enables it to talk to the outside world. Technical infrastructure means things like databases, file systems, user interfaces, web services and message queues.

We can visualise it as two hexagons, one inside the other, as in the diagram below. The inner hexagon contains our core business logic. It doesn’t know or care anything about the details of how it will communicate with the outside world, but it exposes ports where we can plug in adapters that fulfil that role. The adapters sit in the outer hexagon, and translate between our core domain and the technology-specific domain of a particular piece of infrastructure.

Hexagonal Architecture Sketch

That’s it, nothing fancy. The word hexagon isn’t actually really very important but I like to think it as a metaphor for the modular, pluggable nature of this architecture. It’s catchier than ports and adapters, too.

Keeping this separation between the inner and outer hexagons, between the core behaviour and infrastructure details of our program, gives us a few advantages:

  1. Our code is easier to understand. When we’re working in the inner hexagon, all the language and concepts we see are related to our core domain, without the distraction of the technical realities of connecting it to the real world. When we’re working in the outer hexagon, we can concentrate on the job of mapping core domain events and data onto the domain of the technical infrastructure that we’re writing an adapter for, without the distraction of business logic.

  2. We can easily replace pieces of infrastructure, such as swapping out a relational database for a key-value store, or using an in-memory database for fast acceptance testing, without modifying the core domain at all.

  3. Our tests can run fast. The code in the core domain does not depend on Rails or any other large external libraries, so its tests are lightning quick. Once we start to recognise core domain logic and push it inside the inner hexagon, more and more of our tests are running against plain old Ruby objects that are quick to instantiate. We have separate tests for our adapters that ensure they integrate with their respective technology, but we don’t need to run them as often as we used to. We only need to run those slow tests when the adapter needs to change, and because our business logic has moved into the core domain, that’s not very often.

There are apparent costs too. As I’ve moved the Relish codebase towards a more hexagonal style, I’ve noticed that there’s more code appearing. However, each piece of code is simpler to understand, and the pieces are much less coupled together, giving me flexibility for the future.

For me, probably the biggest factor in achieving this flexibility has been finally understanding an object-oriented design axiom I’ve been hearing for a long time: that objects should communicate by telling each other things, rather than asking each other questions.

Tell, don’t ask

Your Rails application most likely has a problem with procedural code. When I talk about a procedural style of programming, I am talking about this kind of thing:

class PublishersController < ApplicationController
  def create
    @publisher = Publisher.new(params[:publisher])
    @publisher.creator_user = current_user
 
    if @publisher.save
      current_user.add_membership(@publisher)
      redirect_to publisher_collaborators_path(@publisher),
        :notice => 'Publisher created successfully. You can now add collaborators.'
    else
      render :index
    end
  end
end

This is a fairly typical Rails controller action method. We can read this code and quite easily understand what is going to happen when it runs. This is the advantage of a procedural style – it reads like a story. The problem with this style really hits us when we want to change the behaviour.

Imagine we want to add an activity feed to our application, so that as a side-effect of successfully creating a new publisher, we want to post a message to the user’s activity feed. The way things stand, we’d probably be inclined to squeeze another line into the top branch of that if statement:

...
if @publisher.save
  current_user.add_membership(@publisher)
  current_user.feed_entries.create! content: "Created a new publisher #{publisher.name}."
  redirect_to publisher_collaborators_path(@publisher),
    :notice => 'Publisher created successfully. You can now add collaborators.'
else
...

Over time, as more and more behaviour is added to the application, this is only heading in the direction of chaos and ugliness. A more object-oriented design would allow us to plug in the extra activity feed behaviour without modifying this code at all, and it’s the tell-don’t-ask principle that will guide us into producing that kind of code.

We don’t have space for an example here, but we’ll see plenty of them as the series unfolds.

Your domain is in the protocols

Let’s examine that controller action again, looking in detail at the messages passing between the different objects in the scenario where the publisher is saved successfully. All in all, there are six different actors in this little scene: the Controller, the Publisher class, the new Publisher instance, the current User instance, the user’s Feed Entries collection, and Rails itself. Let’s imagine this method as a conversation between them:

Controller: Dear Publisher class, please may I have a new instance using these parameters? [Query]

Publisher Class: Certainly, here you are. [Query Response]

Controller: Publisher instance, this User instance is your creator_user! [Command]

Controller: Publisher instance, attempt to persist yourself! [Command]

Controller: Hey Publisher instance, did the attempt to persist yourself succeed? [Query]

Publisher instance: Thanks for asking! Yes, it went perfectly. [Query response]

Controller: User instance, grant yourself membership of this publisher instance! [Command]

Controller: User instance, can I see your feed entries collection please? [Query]

User instance: Oh alright then, here it is. [Query response]

Controller: Feed entries collection, create and persist a new entry with these parameters! [Command]

Controller: Rails, redirect to the following path, and show this message to the user! [Command]

In total, there are eleven different messages passing between the six different objects in play as this method runs. Of these, five messages are commands, and the other six are queries or their responses. We’re not even counting the potential for the call to feed_entries.create! to raise exceptions – we’ll talk about that some other time.

A revelation for me as I re-read GOOS recently was this: Your domain model is not in the classes you create in your source code, but in the messages that the objects pass to one another when they communicate at runtime.

In other words, the structure of these conversations—the protocols—is what’s most interesting about your application. The simpler you can keep these protocols, the easier your code will be to change in the future. Code that involves queries is inevitably more complex, because the code asking the question needs to then act upon the answer. Using a tell, don’t ask style encourages us to push that action off into other objects. Smaller, more re-usable objects.

So is there ever a valid case for using queries? There is, and that’s when the object is a value.

Objects and values

The authors of the GOOS book distinguish between just two different categories of class in an object-oriented program: objects, and values. As Rails programmers, we can find these two categories confusing because many of the objects we’re used to dealing with, particularly ActiveRecord::Base subclasses, fit into both categories. Nevertheless, I’ve found these two labels extremely useful in helping me think about how I structure my own core domain code.

Objects are the things that get work done. They may carry state, but they don’t expose it. They receive messages from collaborating objects, and make decisions about what messages to send to their collaborators.

Values carry state. They’re immutable: once created, they can’t be changed. Values have query methods that either return component parts of their state, or the results of calculations on that state.

So I’ve explained that a hexagonal architecture involves separating the code that allows your application to talk to the outside world, from the code that is the application itself. I’ve talked about how, when designing that code, it’s important to think about the protocols between the objects, and I’ve talked about the difference between objects and values.

I realise that these first two posts have been fairly abstract and theoretical, but I really felt I needed to put down some terminology before we could continue with the story. In the next post we’ll get much more practical and look at a pattern for applying tell-don’t-ask in my Rails controllers which I’m calling passive controller.

Hexagonal Rails

Comments (6)

Permalink

Hexagonal Rails – Introduction

A few months ago, development of http://relishapp.com reached what is a familiar but rather unpleasant plateau for me. Up until that point, it had been developed using conventional Ruby on Rails idioms, with controllers that talk directly to ActiveRecord class methods to make queries, then set instance variables to pass the results of those queries to view templates for rendering. It’s all very procedural, and very tightly coupled.

This post is an introduction to a forthcoming series which will explain how I’ve been tackling this.

Let me start by saying that the coupling in my Rails application is not necessarily a bad thing. In fact, to get the product off the ground and give RSpec’s amazing living documentation a place to call home, we needed to be able to put Relish together very quickly. This is where Rails absolutely dazzles: the early stages of a project are so easy that adding features is a delight.

Unfortunately, the very forces that make adding features to a new Rails application so easy are the same ones that start to hold you back as the number of features grows. That conventional Rails style is what Kent Beck has called a connected design style, Quoting from that article:

In a connected system, elements are highly available to each other (via global state, for example). Adding the first feature to a connected system is cheap. All the resources you need are available. However, the cost of all those connections is that subsequent features are very likely to interact with previous features, driving up the cost of development over time.
The alternative to a connected design style is what Kent calls a modular design style. He contrasts these using this chart:

Cost of Features in Connected and Modular Designs (from http://www.threeriversinstitute.org/)

For the first few features, a connected design style is cheaper than a modular design style. In fact, using what might be referred to by software design snobs as ‘poor design’ could give you a competitive advantage in the early stages of your product’s development. The trick is to recognise when it’s time to switch styles.

So, while I love Rails for what it is, I also recognise its weaknesses. To make the Relish codebase habitable in the long term, I need to move beyond its connected design style and establish a more modular design. But how? It’s a question that many different people are asking at the moment, and I’ve been diving deep into what they are saying. Here’s a sample:

For my part, I re-read the outstanding Growing Object-Oriented Software Guided by Tests (GOOS) by Steve Freeman and Nat Price. In that book, Steve and Nat advocate a ports-and-adapters or hexagonal architecture, which keeps your core application logic separate from any technical details needed to connect the application to the real world; technical details like databases, or web user interfaces.

I think it’s easier to use an architecture like this in Java or C#, where packages and interfaces make it easy to see and enforce separation between chunks of the application, than in Ruby where it’s harder to make clear boundaries around areas of the system. But that doesn’t mean it isn’t possible. For the past couple of months I have been experimenting with refactorings in the Relish codebase to move it towards a more hexagonal architectural style. The overall goal is to make the Relish codebase habitable, which for me breaks down into:

1. Fast tests

I never add features without tests, and I want those tests to run fast. The goal of the hexagonal architecture is to have the most interesting (and frequently changing) logic implemented in plain old Ruby objects that have no dependency on any other libraries so they are easy to understand, and can be quickly spun up in a test.

2. Modularity and encapsulation

Ruby is an object-oriented language with great support for functional programming, and I want to make the most of that to keep Relish’s code easy to change.

3. Clean and well-organised

I want a structure that communicates what each part of the system is doing, and makes it easy for new team members to jump in and start hacking on the code.

I’ll start the series by explaining a couple of key concepts from Steve and Nat’s GOOS book, and about hexagonal architectures in general. Then we’ll get down to some practical work refactoring a typical Rails controller. Stay tuned!

Agile / Lean Software Development
Hexagonal Rails
Relish
Ruby Programming

Comments (6)

Permalink