Information Technology Dark Side

Struggles of a Self-Taught Coder

Information Technology Dark Side header image 2

Re-imagining TroopTrack in a Use-Case-Centric Architecture

May 16th, 2012 · 1 Comment

Please read this first if you are a TroopTrack user
My blog is read, not only by coders like me, but also by a pretty decent number of TroopTrack users. I just put them through a fairly horrible major release, after which I swore I would never do an X.0 release again, so I need to start this post with an assurance. Please don’t interpret this post as a sign of things to come regarding TroopTrack. This is merely a hypothetical discussion to help me understand a concept being advocated by a fellow programmer whom I respect but whose ideas have troubled and frustrated me for the last year or so. There will NEVER be another major TroopTrack release. All changes will be incremental as previously promised.

Throwing the gauntlet down with Uncle Bob
This post is a follow on to an earlier post which was a response to a post by Uncle Bob Martin, author of Clean Code and other noteworthy books about software development. There were some tweets involved as well, but to make things easier and get you caught up if you haven’t been following along, just read these posts first:

Perhaps I Got It More than I Knew
About a year ago I embarked on a major re-design of TroopTrack. One of the changes I made was to group functionality in the five major uses cases of my software. This grouping is evident in the UI:

And in the code:

I show here the controllers folder, but if you looked in the views folder you would see something very similar – I’ve namespaced my application based on the major use cases of my system. Like FitNesse, there is plenty of cruft in there and, since it’s a rails app, things are pretty much glued to HTTP.

This may seem like a relatively small change, but it has had a dramatic improvement on TroopTrack overall. For one thing, TroopTrack’s “first glance” grade improves significantly. It’s a lot easier to see what TroopTrack does than pre-namespacing, when everything was just lumped in one sloppy bucket. For another thing, this improves separation of concerns at a higher level and lets me think about the same bits of data differently in different contexts.

Let’s Be Honest Here
Namespacing TroopTrack this way is nice, but let’s not call it a use-case-centric architecture. It’s not. It’s simply more use-case centric than it was. Whoop-dee-doo.

One of the frustrations I encountered in TroopTrack 3.0 was that I couldn’t namespace models. The “user” I deal with in Communicate is rather different than the “user” I deal with in Manage. Perhaps it would be more accurate to say that I wish they were different, in spite of the fact that underneath it all is a database structure that they share. You see, in Communicate I really only care about a few things related to the user:

  • Their name (not the parts of it)
  • Their email address
  • Mailing lists they belong to
  • Their privileges related to editing web sites, uploading documents, sending messages, and sharing links

In Manage, I have a much larger set of stuff I am interested in:

  • First name
  • Middle name
  • Last name
  • Household they belong to
  • Birthday
  • When they joined scouts
  • What scouting unit they belong to
  • Their avatar image
  • Medical information about them
  • All their privileges
  • Their access level
  • etc.

It bothered me that I couldn’t namespace my models the same way I namespaced my views and controllers. Why can’t I have a different set of validations, accessible attributes, methods, etc for a different high level use case?

Note: this is a rhetorical question. In rails, you can in fact accomplish at least some of these things by adding logic to your validations and adding :as => namespace to your accessible attributes. But it’s not what I would call clean and, since all this stuff would wind up being in the same model file as every other namespace it would murkify intent in significant ways.

What I’d Like to Have
At some point in the future, I’d like to bust open my source code and see something like this:

I’m not 100% sure what the controllers here would look like. It might be nice to un-marry them from HTTP, but the pragmatic part of me is not totally sold on that. I might just call them HTTP controllers or something, just so there is semantic congruence between what they are called and what they are.

I like the convention for naming views in a way that shows their action, format, and the language used to implement them, like so:

  • show.html.haml
  • show.pdf.haml
  • show.json.erb
  • etc

It would be important to be able to disconnect the views and controllers from HTTP if needed, so that I could continue to use them with other protocols. The pragmatist in me says “leave that step until you need it, just leave room for it for now”, and I agree with him at the mo. It would also be important to put some thought into keeping the views from being too married to models, but I think this might have more to do with the models than the views.

Neither of these things are a HUGE departure from things we’ve seen before. In fact, you could probably take different parts of Rails and bend them to your will to support an approach like this.

The problem is, you could go this far and still end up with an architecture that is fundamentally data-centric. In order to be truly use-case centric, you need to have models that reflect the use case as much as your views and controllers do.

The Models are the Big Deal
For the most part, models tend to be 1:1 matches to the way the data is stored. A model’s class usually represents a table and an instance is a row. The model you build just adds behavior on top of that data. This is convenient, especially in a framework like rails where active record adds some magic for all sorts of stuff, but the 1:1 mating of a model to a table is limiting.

Ultimately, it might be valuable to break both this 1:1 mapping and the tight database coupling to allow for a model to be “storable” in multiple ways. I can think of cool uses for this including an often-requested feature that TroopTrack currently doesn’t have – the ability for a scouting group to get/restore a csv or sql or json backup of all their data (TroopTrack is a multi-tenant application).

That’s all well and good, but I think there is a simpler advancement that is needed that is also more important. I mentioned it earlier in my example about how I care about different aspects of users depending on whether I am in the manage use case or the communicate use case. I think it boils down to something simple.

Models need to be a reflection of the use case rather than a reflection of the columns on a table plus a generalized set of behaviors.

At this point I can hear Bob Martin cackling ruthlessly. It’s what he’s been saying all along. Sometimes, you just gotta see some code to believe it.

If you enjoyed this post, make sure you subscribe to my RSS feed!
Stumble it!

Tags: Uncategorized

1 response so far ↓

  • 1 Andrew L. Robinson III // May 16, 2012 at 10:42 am

    The context aware model concept feels like an approach that a co-architect and I came up with…we called it bundles.

    Bundles would essentially be a context aware model that wasn’t tied to a data repository, but was more of a representation of a grouping of actions, or better yet, I think you hit the nail on the head when you talk about grouping these by namespace. The job of the bundle was to represent the model in such a way that it was easy to use within the context that we would use them.

    But, this added a layer that doesn’t really exist in the traditional Rails app(this architecture was built on .Net, but wasn’t using .Net MVC or .Net Webforms), and a layer that is very data-centric…sometimes referred to as a services layer.

    So after reading this conversation, and reflecting back on the framework I used to build BbyBk.com, I think I was trying to be use case centric with the layers that were closer to the UI…but I fell back into very data-centric in the layers that dealt with persistence.

    Not sure what to make of this self-reflection other than, I love what you guys are striving for, and being aware of when we are being too data-centric is a good exercise to have in your “build this product” arsenal

Leave a Comment