Where is the database?

I have just watched an interesting conversation between Martin Fowler and Badri Janakiraman about #hexagonalrails, and in particular about the role of databases. The central question in the discussion is whether the database should be considered outside or inside the domain. While watching, I realised I had had similar thoughts in 2005!

In recent years I have considered databases to be always outside the domain. I can definitely see the attraction of an “always present” domain model, but I think it is conflating different points of view, and misunderstanding the point of Hexagonal Architecture. I was wrong in 2005 :)

The comments on the video are very interesting, particularly those by Alistair Cockburn. Specifically he makes two key points:

  1. [There is no] debate of whether the persistence is in or out in HA, it is out. So you should say you chose not to use that piece of HA, not that you used it but brought the db inside.
  2. the purpose of HA is the configurable link t0 db

By forcing ourselves to keep to database outside of the domain we respect the hexagonal symmetry , and this is the only way to guarantee complete separation of concerns. The choice of Active Record or Data Mapper then becomes a decision about how to implement the “configurable database” port/adapter.

Query actions in Rails controllers

Recently some of my controller actions have taken on a definite new shape. Particularly when the action is a read-only query of the app’s state. Such actions tend to make up the bulk of my apps, and they can be simple because they are unlikely to “fail” in any predictable way. Here’s an example from my wiki app:

This has a couple of significant plus points: First, no instance variables, so both the controller action and the view are more readable and easier to refactor. Second, no instance variables! So there’s a clear, documented, named interface between the controller and the view. And third, this is so transparently readable that I never bother to test it.

The wiki used in the above action is a repository, built in a memoizing helper method that most of the controllers use:

In this case the correct kind of repository is created for the current user, and all of the other code in this request sits on top of that. So the controller action, helped by the memoized repository builder, effectively constructs an entire hexagonal architecture for each request, and the domain logic is thus blissfully unaware of its context.

Here’s a slightly bigger example. This is for a page that shows a variety of informative graphs about the wiki; and because I may want to re-organise my admin pages in the future, each graph’s data is built independently of the others:

That’s the most complex query controller action I have, and I maintain that it’s so simple I don’t need to test it. Would you?

A testing strategy

The blog post Cucumber and Full Stack Testing by @tooky sparked a very interesting Twitter conversation, during the course of which I realised I had fairly clear views on what tests to write for a web application. Assuming an intention to create (or at least work towards creating) a hexagonal architecture, here are the tests I would ideally aim to have at some point:

  • A couple of end-to-end tests that hit the UI and the database, to prove that we have at least one configuration in which those parts join up. These only need to be run rarely, say on CI and maybe after each deployment.
  • An integration test for each adapter, proving that the adapter meets its contract with the domain objects AND that it works correctly with whatever external service it is adapting. This applies to the views-and-controllers pairings too, with the service objects in the middle hexagon stubbed or mocked as appropriate. These will each need to run when the adapters or the external services change, which should be infrequent once initial development of an adapter has settled out.
  • Unit tests for each object in the middle hexagon, in which commands issued to other objects are mocked (see @sandimetz‘s testing rules, for which I have no public link). And for every mocked interaction, a contract test proving that the mocked object really would respond as per the mocked interaction (see @jbrains‘s Integrated tests are a scam articles). These will be extremely fast, and will be run every few seconds during the TDD cycle.

I’ve never yet reached this goal, but that’s what I’m striving for when I create tests. It seems perfectly adequate to me, given sufficient discipline around the creation of the contract tests. Have I missed anything? Would it give you confidence in your app?

Hexagonal rails: Rake tasks are adapters

If I’m thinking about my Rails app in terms of a hexagonal architecture, I find it also pays to consider every rake task to be an Adapter. Thus:

Picture: @rosieemackenzie

The true picture is a little more complicated than that, but the principal ideas are there. The rake task acts as a mediator, allowing me to send messages to (ie. call methods on) my application’s objects.

In general, we want our Adapters to be as thin as possible (and no thinner). That’s because the Adapter code inherently depends on some framework, and that fact will usually make its tests difficult and/or slow. We still need those tests, but we want to have as few paths through the Adapter as possible, and thus fewer tests of the Adapter, so that the total test complexity and test run-time are minimized.

As an example, suppose I have a rake task that validates the posts and comments on my blog:

I want to maximize the unit tested percentage of the code executed during the task, so I move the code out of the rake task and into a new domain object. That new object “is” the task, and usually my rake tasks can then slim down to a single line of code.

Stripping all of the code out of the rake task and moving it into a domain object is analogous to the approach currently being explored by @mattwynne and @tooky in their Rails controller refactorings. In my own code I call these task objects “use case objects”. Currently I keep them in a UseCases namespace within app/models, although I’m open to exploring alternative conventions. One of the nice side-effects of this is that I sometimes discover synergies between the work done by rake tasks and that done by controllers. By pulling Use Case objects out of both kinds of adapter I’m creating a convention for some of the code that turns out to be cleaner, more (quickly) testable, and which names things better.

Please let me know if you try this — or indeed if you’re already doing it.

Hexagonal rails: Hiding the finders

This is a brief follow-up to the Hexagonal Rails sessions I did last week at the Scottish Ruby Conference with Matt and Steve. We tried to cram a 3-day course into 45 minutes, with inevitable consequences. So by way of an apology, here’s another brief foray into some of the same territory…

Today I’ve been exploring ways of improving the unit tests in one of my Rails apps. Let’s pretend it’s a blog app, and I have to add a feature to publish posts. I’ve pulled some code out of a controller to make a UseCase object:

(Here ui is a controller, and makes decisions about routing and rendering in response to the events sent by the use case object.)

I’m really sick and tired of looking at code like this. It seems that most of the classes in any Rails app know that finders return nil when they can’t find something, and so they all have to cope with that case. I want to get rid of that if, or at least hide it away in a single place so that it doesn’t contaminate the rest of the app. I want the test to be a bit simpler and more readable too. And I want the option to have richer finders, maybe coping with fuzzy edge cases and still finding the desired database record. In short, I want to wrap the finder in an Adapter.

So I experimented with a couple of alternatives to the above. First, a variant on Smalltalk’s ifTrue:ifFalse message argument style:

I don’t like this because it’s near impossible to isolate and test the interactions. For example, Blog.should_receive(:lookup_post).with( … what?

Another approach might be something like this:

Indeed Rails itself uses this style in its controllers, and so does the inherited_resources gem. But it suffers from the same testing problems as my previous attempt. So I finally settled on this:

This version uses an explicit listener object, which I can thus instantiate and test independently of the calling context. (In real code I might make it an inner class too.) And I’ve already found a couple more uses for the lookup_post method, removing dependencies and ifs along the way.

I find this approach highly readable and testable, nicely separating different responsibilities and allowing me to give them names. But that doesn’t mean I’ll stop exploring. Have you tried other approaches? How did they work out?

Update

Luke points out that I forgot to include the option I actually use the most, the Self Shunt:

This is the same as the listener option above, but the UseCase object passes itself as the listener, thus saving a class and in my opinion) improving readability a little. Can’t think why I forgot it, cos it’s the best and neatest of them all. Anyroadup, thanks Luke!

Conditionals on the edge

As you know, I have a thing about conditional code. Most conditionals are duplicates, and the only “genuine” conditionals are at the system boundaries, where they test external state and input information. But I discovered recently that, even at the edges, not every conditional is necessary…

Here’s (a drastically simplified version of) some code I wrote a while back. (It’s from a Rails app, but the message in this post applies to any technology and any kind of system input.)

class Users::RegistrationsController < Devise::RegistrationsController
  def create
    user = create_new_user_account
    if params[:invitation_token]
      sign_in_as(user)
      redirect_to Invitation.find(params[:invitation_token]).shared_content
    else
      redirect_to new_user_session_path
    end
  end
end

This route handles incoming user registrations, and it has a conditional branch to cater for the case in which the new user was invited, via email, by an existing user. If the new user arrived by clicking a link in an email we do one set of things; whereas we do a different set of things if the user got here via the ‘Register now’ button on the home page. Perfectly reasonable, I thought. Sure, it’s conditional code; but it’s sitting on the system boundary and therefore it’s fine, yes? No.

This conditional check represents duplication. Somewhere else in my application already knew, at some time in the recent past, which route should be taken through this method when it was finally invoked. When the app sent that email invitation, it was in a sense delegating to the recipient the task of supplying user account details. The conditional branch that handles the invitation is a callback from across a technology boundary, and the inviting code already knew to expect it.

The duplication also has a nasty side-effect: high complexity. This method is an order of magnitude harder to understand and to test(-drive) because of the conditional construct. (And you’re reading a version from which I’ve elided all manner of error handling.) Oh, and by forcing two routes into the same method I also made it violate the Single Responsibility Principle.

Happily the duplication is really easy to remove. The code that sends the email invitation knows which path it wants the registration code to take, so I just need to create a new input route for “invitation acceptance” and change the email invitation to link to it. As a result I’ll have two controller methods, each with simpler logic than their predecessor:

class Users::RegistrationsController < Devise::RegistrationsController
  def create
    user = create_new_user_account
    redirect_to new_user_session_path
  end
end

 

class InvitationAcceptancesController < Devise::RegistrationsController
  def create
    user = create_new_user_account
    sign_in_as(user)
    redirect_to Invitation.find(params[:invitation_token]).shared_content
    end
  end
end

So I have now removed the duplication, and the controller code is simpler as a result. These controller methods are also much easier to test(-drive) than the earlier code. And as a final bonus, I can design the user interface to this route with more knowledge, maybe adding some details of the invitation so that the incoming potential user feels a little more at home. In short, now that each code path has its own method (and class) I can pay it more attention, and it will flourish as a result.

Now, having refactored this code, I take away a few points for the future:

  • Where appropriate and possible, model system outputs as delegations into a space that your code can’t reach or control; and model the resulting future input as a response.
  • Where a system input is due to the system having earlier delegated a responsibility across its boundary, make sure the return route is differentiated from all others.
  • Differentiated incoming routes have code that is easier to read and simpler to test.
  • When an input route has a single use, the user experience can be tailored and enriched.
  • Not every conditional at the system boundary tests external state.