All atomic-powered posts from January 2008:
Presenter First: Get your triads talking
Today I got an email from Sandro Aloisio asking an important question about the connection of one MVP triad to another. When introducing the basics of Presenter First, one usually runs out of breath before getting to the topic of connecting triads using Managers (or Coordinators, whatever you call them), which is a technique that has grown up a little and proven to have some merit. So here’s a little more discussion on that front:
Q: There should be at least one MVP triad per user story, is that correct?
Yes, at least one triad for a user story is a good way to go, especially at the outset of a project. It’s worth pointing this out, as I have seen code written by folks who interpret Model-View-Controller patterns to mean your application should consist of exactly 3 gigantic classes.
One user story usually involves one or more like-minded statements that start with “when the user clicks Save” and “when the user clicks Cancel”. A subsequent user story might augment a feature by saying “when the user clicks Apply, save changes but don’t dismiss the dialog” which might involve going back to the old Presenter for that feature.
And it could happen that a small handful of innocent, related phrases from the same story are technically separated enough to make you want to compose more than one triad to answer the story. There’s nothing in the pattern (or our experience) that says this is a problem. At worst, you’ve added a little extra interface code. At least you’ve introduced that much more domain language into your code.
That second case comes up often when the actual verbiage from the customer covers a lot of ground, such as “I can double-click the user name in the list, change that user’s password, then save.” This implies a collection of smaller stories, such as an interactive user list, a password editor, etc. Decomposing the larger story into several related smaller stories gets you several related MVP triads which will need to interact according to the overall user story.
Q: What if a model from one MVP needs to know the state of a foreign model (in another MVP)?
The model-to-model communication you’re asking about is something we answer with the loosely-named “manager” pattern (naming of these objects varies from project to project, I’ll discuss that below). A Manager is structurally identical to a Presenter: it acts as an observer on two objects, and channels data and intentions from one to the other. The Manager exists only to do these things, and has no public API (same as Presenter) and nobody holds a direct reference to this object.
Managers come into existence when you recognize that a user story describes the interaction between two other story-level application features. You’ve already got a triad for each feature, and you’ve decided that the models from these features need to talk to each other. Responsibility and testability issues pop up quickly if you simply let the models reference one another directly, and even if you try to wire one model up to observe the other. (We’ve found that subscribing for, reacting to and processing input is indeed too much to do cleanly all in one class… Presenters lift a lot of this burden from our backs.)
A Presenter’s basic event-and-data brokering habits have freed you up to write much simplified View and Model code. Objects get to “wish” for things to make their testing easier, like “I wish someone would send this data to me, instead of my having to retrieve it, and knowing when”. if you take two models and put a Presenter-ish object between them (creating a new triad) you get to connect your models without overloading them too much. Additionally, you’ve got a specific place to transcribe the user story that connects these two features in the first place.
If you still feel like your models in this triad are starting to get somewhat heavy in their dual responsibilities, do not hesitate to elaborate on the relationship between the models by introducing more models, and perhaps more Managers to connect them. Don’t be frightened of the additional classes… if a problem has become complex enough to make you ask yourself if you need another class to get the job done, you probably do.
On naming:
In several large projects, we found that we wanted to reserve the word Presenter for that specific type of object that connects Models to Views (or Adapters, but that’s a different topic). Verbal design sessions are easier when the words always mean the same thing. In our seach for terms that mean “Presenter-like object that connects models to models” we’ve used Manager, Conductor and Coordinator. We tend to refer to this aspect of Presenter First as the “coordinator pattern” or “manager pattern.”
When choosing a specific name for a Manager object, try naming it directly for the feature the object will enabled. Eg, you might connect the UserListModel and PasswordEditorModel via the UserPasswordEditorCoordinator.
Presenter First Modeling Tools for Visual Studio
Brooke Hamilton has developed some of his own extensions to Presenter First and a cool-looking visual modeling tool to match. We at Atomic have not put it to use yet (none of us is using Visual Studio 2008) but it sure looks snazzy.
The tool and its source code are hosted on CodePlex: A Modeling Tool for the Presenter First Pattern
Also linked from that page is a bit of explanation regarding Brooke’s take on PF, setting it up for DSL use. I have not made use of this derivation of Presenter First (I tend to use my Presenters as the place where I describe my features—the one part of my application that cannot be auto-generated) but Brooke’s tool and approach have been working well for him, and as he says, “it’s a lot of fun, too.” Give it a read.
We're Hiring this Winter
The Molecule needs more good Atoms. We’re looking for solid generalist developers and especially those with strong working knowledge of web programming.
Atomic Object people are more than technical wizards; they’re also proficient in writing, managing changing requirements, working directly with clients, and satisfying customers. They care about good code, create tools to make tasks easier, are skilled at problem solving, think testing is essential and not optional, and know how to learn the things they don’t know.
If you’re comfortable with anything from web to desktop to systems programming, have a good working knowledge of databases, already know several languages and enjoy learning new ones, and are handy with more than one operating system, then you might just be the kind of proficient generalist we’re looking for.
If you can analyze web applications down to the HTTP protocol, think in terms of interaction design, and roll your eyes when you see HTML listed as a programming language, you might be the kind of web-savvy developer in whom we’re interested. We look for depth in our developers – much more than only a resume dripping with a web-flavored alphabet soup of acronyms.
Poke around our site and this blog to learn about us.
Relating User Interfaces & Security in Software
We’ve been talking quite a bit these days in the office about user interfaces and interaction design. I came across an interesting post on the Architectures of Control | Design with Intent blog by Dan Lockton, a PhD researcher at Brunel University’s School of Engineering & Design.
In his post Interesting Parallels, Dan draws on unique definitions of interaction design and security (namely, that both are related to shaping human behavior) to tie the two together. He quotes a computer security specialist and interaction design expert to draw the parallel:
“Security is about preventing adverse consequences from the intentional and unwarranted actions of others. What this definition basically means is that we want people to behave in a certain way… and security is a way of ensuring that they do so.”
“A simpler way of thinking about Interaction Designers is that they are the shapers of behavior. Interaction Designers… all attempt to understand and shape human behavior. This is the purpose of the profession: to change the way people behave.”
It’s a rare software project that doesn’t require a developer to think about and implement user interfaces or security in some fashion. So it seems immensely useful for a software developer to view himself or herself as a shaper of human behavior, asking questions as a behaviorist to effectively create useful interfaces and secure software.
The Exceptional Presenter
PresentationObject is an implementation of Jay Fields’ Presenter pattern in Rails. It has familiar declarative style syntax and offers encapsulating presentation logic in a testable object.
Without a presenter-like object it’s easy to spread presentation logic and information across the MVC architecture: models end up with unneeded methods, controllers make unneeded decisions and view templates become corroded by unneeded code. Combined it becomes difficult to test and maintain presentation logic in the application.
Here’s an example of a simple presentation-oriented method existing in a model:
1 2 3 4 5 6 7 8 9 10 |
class Group < ActiveRecord::Base belongs_to :parent has_many :subgroups def show_relationships? return true if parent || subgroups.any? false end end |
The show_relationships? method is only used in a view to determine whether or not it should display the relationships information. It doesn’t really belong on the model.
Here’s an example of a controller making presentation decisions:
1 2 3 4 5 6 7 8 9 10 11 |
class GroupsController < ApplicationController def index if current_user.superuser? @groups = Group.find(:all) else @groups = Group.find_active_groups_with_member(current_user) end end end |
The index action introduces an unneeded branch of logic for a controller to have. It is painful to see this branch sprinkled throughout any controller that has to do with supplying @groups to the view because you will have to test the branch separately for each controller action that includes it. A common mistake made is to make this branch a before filter and define the method inside of the ApplicationController. Before filters can be easily misused and that is a topic for its own post so let’s not discuss that here—just know that using a before filter for this example is not the best thing to do.
Here’s an example of code that should not be in the view:
1 2 3 4 5 6 |
<%= Group::GROUPS_TITLE %> <% Group.find(:all).each do |group| %> <% if group.member?(@current_user) %> <%= link_to h(group.name), group_path(group) %> <% end %> <% end %> |
The first thing to stand out is the Group.find(:all) call. It shouldn’t be there. The second thing to spot is the group.member? call. It doesn’t need to be there. Lastly, the usage of the GROUPS_TITLE constant doesn’t belong in the view.
Rather then sprinkling these presentation-oriented decisions and knowledge across the whole MVC architecture the PresentationObject drops in as an intermediary between the view and the model. It is responsible for knowing that the logic it contains will be presentation logic. This makes it the perfect place to put logic that otherwise shows up in the model, controller or view. A strength of the presenter is that it can mimic the model.
Here’s a GroupPresenter moving code out of the model:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
class GroupPresenter < PresentationObject delegate :id, :to_param, :name, :members, :to => :@group def initialize(options) @group = options.delete(:group) end declare :show_relationships? do return true if @group.parent || @group.subgroups.any? false end end # in a controller action that deals with a single group def some_action group = Group.find(params[:id]) @group = GroupPresenter.new group end |
By creating a GroupPresenter we’re able to keep our model responsible and disciplined. It also allows us to make little or no change to the view since the GroupPresenter delegates the necessary methods. Now, moving one method out may or may not be enough motivation for you to create a presenter. That depends on the situation you and your code are in. Unfortunately there’s rarely just one method that doesn’t belong on the model.
Here’s a GroupsPresenter moving code out of the controller:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
class GroupsPresenter < PresentationObject include Enumerable def initialize(options={}) @user = options.delete(:user) end declare :groups do if @user.superuser? Group.find(:all) else Group.find_active_groups_with_member(current_user) end end def each(&blk) groups.each(&blk) end end # in the index controller action def index @groups = GroupsPresenter.new :user => current_user end |
Here the view won’t have to change. You gave it an array of groups before and you are giving it an object which acts exactly the same. The only difference is that your GroupsPresenter will make the right decision on what groups should be iterated over.
Before we look at a cleaned up view template there is more benefit with the PresentationObject and these last two examples.
First, it’s easily testable since all of the work is done in the methods themselves. Here’s a spec example covering the GroupPresenter we extracted from the model:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
describe GroupPresenter, 'delegates' do before do @group = mock('group') @presenter = GroupPresenter.new :group => @group end it_delegates :id, :to_param, :name, :members, :on => :presenter, :to => :group end describe GroupPresenter, 'show_relationships?' do before do @group = mock('Group') @presenter = GroupPresenter.new :group => @group end describe 'when the passed in :group has a parent' do it 'returns true' do @group.should_receive(:parent).and_return(true) @presenter.show_relationships?.should be_true end end describe 'when the passed in :group does not have a parent, but has subgroups' do before do @group.stub!(:parent).and_return(nil) end it 'returns true' do @group.should_receive(:subgroups).and_return([:subgroup]) @presenter.show_relationships?.should be_true end end describe 'when the passed in :group does not have a parent or any subgroups' do before do @group.stub!(:parent).and_return(nil) @group.stub!(:subgroups).and_return([]) end it 'returns false' do @presenter.show_relationships?.should be_false end end end |
The it_delegates spec helper is included at the bottom of this post.
Secondly, the presenter uses lazy evaluation and implements caching. For example the GroupsPresenter declares a :group method which retrieves all groups the user is able to see. This can be called as many times as you want, but it will only execute the first time. Every subsequent call will return a cached result. For example:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
groups = GroupsPresenter.new :user => current_user groups.each { || } # this will call :groups which will make a find call to Group groups.each { || } # this will returned the cached value from the last time :groups was called #likewise for the GroupPresenter group = GroupPresenter.new :group => Group.find(:first) group.show_relationships? # executes our implementing code group.show_relationships? # returns the cached value from the last execution</li> # this works for delegated methods to group = GroupPresenter.new :group => Group.find(:first) group.to_param # executed the delegated call to our group model group.to_param # returns the cached value from the last execution |
So depending on whatever your view ends up actually displaying the minimum number of calls to the database or to complicated methods will be made.
A real-world example of this is implementing a leader board which involves users, scores, games and user play regions. In order to show the leader board a number of computationally heavy algorithms and queries have to execute. These database and CPU intense calculations should happen once. PresentationObject gives you this advantage—for free.
Another advantage that is easy to overlook is where the decision is made that determines which specific query or computation to run. When it’s in a presenter it is isolated in an object which is only concerned with doing the right thing based on what needs to be displayed to the user. This makes it much simpler to comprehend and track down when compared to housing it inside one of the alternatives: the model and the controller.
But back to cleaning up the view template. Here’s what the view template should look like:
1 2 3 4 |
<%= @groups.title %> <% @groups.each do |group| %> <%= link_to h(group.name), group_path(group) %> <% end %> |
We’ve pulled out two important things from the view template: the GROUPS_TITLE constant and the conditional logic checking the current user for group membership.
Here’s the presenter that goes with the new view template:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
class CurrentUserGroupsPresenter < PresentationObject include Enumerable def initialize(options) @user = options.delete(:user) end def each(&blk) groups.each(&blk) end declare :groups do Group.find_active_groups_with_member(@user) end declare :title do Group::GROUPS_TITLE end end # in the index controller action def index @groups = CurrentUserGroupsPresenter.new :user => current_user end |
Pulling out the GROUPS_TITLE constant into a method on our presenter is important because the view template doesn’t need to know what title should be displayed. It just needs a title to display. If we wanted to build a title dynamically there is one single place where we can change that logic without affecting the view or anything else—the presenter.
Pulling out the conditional logic from the view template into our presenter gives us several advantages.
First, the view template is now available to be reused as a partial because it is only displaying the groups it is given. We can make the decision elsewhere on what groups to show and our template will just work.
Second, we’ve removed the urge to add any other conditional statements in that loop. We were just checking for group membership, but maybe we need to see if the user is a superuser. By placing this logic in the presenter we have removed the temptation of just adding more logic to the view template.
Lastly, we have created a single testable object for this presentation logic—our presenter. This greatly simplifies our view tests and the implementation of our views. And it stays consistent with placing this logic in a single object whose responsible for making these presentation-oriented decisions.
An alternative to this approach prior to the refactoring would have been to extract the code into a controller helper. This isn’t the right thing to do in our example. Helpers are too often used to tuck away code that shouldn’t be out in the presentation layer. They appear to add benefit because it’s so simple to move things from a view into a helper, but the long term debt far outweighs this short term gain. Helpers aren’t highly cohesive objects. Their responsibilities tend to be a little bit of everything and this hurts the ability to have simple testable objects that have highly cohesive behavior and responsibility. It also hurts maintainability. And it adds to the temptation that it is ok to put code in a helper that shouldn’t otherwise be there.
The name of this last presenter was CurrentUserGroupsPresenter whereas the earlier examples were GroupPresenter and GroupsPresenter. The goal of a presenter is to reduce the sprinkling of presentation logic throughout the system which in turn reduces complexity. We’ve found that presenters are cheap to create and work with. They usually work best when they focus on a single component in the UI. If we have four different components on the UI which each uniquely display groups on the site there may be four different group presenters, each one focusing on a specific UI component.
This differs from Jay Field’s presenter concept in that it focuses on encapsulating presentation logic rather then just encapsulating actions that operate on a model from the controller. This isn’t to say that these two ideas can’t be combined successfully or that one is better then the other. We have found that encapsulating presentation logic in a presenter is a great win overall and we haven’t had the need to push other responsibilities such as model creation and updates onto the presenter itself. This usually ends up in a manager-like object.
Installing PresentationObject
The current release is a 0.1.0 release:1 2 3 4 5 |
# installing the latest presentation_object (points to 0.1.0) script/plugin install svn://rubyforge.org/var/svn/atomicobjectrb/tags/presentation_object # installing the 0.1.0 release specifically script/plugin install svn://rubyforge.org/var/svn/atomicobjectrb/tags/presentation_object-0.1.0 |
it_delegates
An RSpec helper:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
module Spec::Example::ExampleGroupMethods def it_delegates(*args) options = args.extract_options! methods = args src = options[:on] to = options[:to] raise "Missing an object to call the method on, pass in :on" unless src raise "Missing an object to ensure the method delegated to, pass in :to" unless to method_options = options.reject{|k,v| [:on, :to].include?(k)} methods.each {|m| method_options[m] = m} method_options.each do |source_method, to_method| it "delegates ##{source_method} to @#{to}.#{to_method}" do obj = instance_variable_get "@#{to}" _src = instance_variable_get "@#{src}" return_val = stub("return val") obj.should_receive(to_method).and_return(return_val) _src.send!(source_method).should == return_val end end end end |