Agile software development using Kanban & Scrum. We code Flex & Ruby on Rails in Auckland, New Zealand.

  • Viewing all posts tagged "Patterns"

  • Static Controller in Robotlegs

    I’ve been away for a while in the land of the Ruby Object model and Rails. Upon my return to some Flex development, I decided that, although Robotlegs MVC ‘Controllers’ are really nice, they require too much boilerplate. One thing I found in RoR, is that although they use static controller classes with many command methods, most folk follow convention and avoid introducing wads of business logic and tightly coupling their code.

    The good things about RL-MVC Commands

    RL-MVC Commands enforce loose coupling. It’s really hard to end up with complex, tightly coupled controllers when every ‘action’ is a short lived class.

    Commands are dynamic. You can change the existing command set on the fly. I’m not sure where this is useful, I don’t take advantage of it, but that’s not to say that other people do not.

    The tradeoff

    With awesome power comes diminished responsibility. Yeah, that decoupling that Commands give you, removes the need for you to pay as much attention to OO and MVC best practices. Instead, you pay the price by having quite a lot of boilerplate:

    One command class per ‘action’ (read: method)

    I never did mind this tradeoff. Now It’s wearing thin. Our app is big, and there is a lot of boilerplate. After spending some time learning to write Ruby DSL’s it’s really grating to see that a simple and sensible idea reads so badly in code. If I was in Ruby I would have something like:

    # controller_map.rb
    
    map RubbishReminderEvent, PutTheRubbishOutCommand
    
    # put_the_rubbish_out_command.rb
    class PutTheRubbishOutCommand
      def initialize 
        house.nature_strip << house.rubbish_bin
      end
    end
    

    Minimal boilerplate, just intention. Actually, with a decent DSL, you could do away with all of the boilerplate.

    However if you look at Rails, events (http requests) are routed by “concept”. In the de-facto Rails convention a “concept” is a resource, but it does not need to be. The ‘routes’ tell Rails how to map incoming events to controllers.

    In Rails, the controllers are classes, by “concept”, with action methods. This runs the risk of being abused, and it sometimes is. However, people who care do not make a mess of their controllers. So I decided to assume my developers are good people, and make a compromise to remove some boilerplate.

    The boilerplate

    As a reminder, this is the boilerplate I’m talking about

        import ....  // boilerplate
    public class PutTheRubbishOutCommand extends Command { // Boilerplate
    
                // Boilerplate
        [Inject] 
        public var event:TimerEvent;
    
                // Often repeated, not 'DRY' 
        [Inject]
        public var rubbishModel:RubbishModel;
    
                // The only bit of actual 'intent'
        override public function execute():void {
            rubbishModel.putRubbishBinOnNatureStrip;
        }
    
    }
    

    Static Controller

    I propose using a Static Controller. Here, “static” is an antonym of “dynamic”, not the keyword

    This is more like a Rails Controller which groups ‘action methods’ and reduces boilerplate:

    public class RubbishController extends Controller {
    
        [Inject]
        public var rubbishModel:RubbishModel;
    
        public function RubbishController() {
            addMethod(TimerEvent.RUBBISH_NIGHT, putTheRubbishOut);
            addMethod(HomeOwnerEvent.GO_TO_WORK, bringTheRubbishIn);
        }
    
        private function putTheRubbishOut(event:TimerEvent):void {
            rubbishModel.putRubbishBinOnNatureStrip()
        }
    
        private function bringTheRubbishIn(event:HomeOwnerEvent):void {
            if (!rubbishModel.rubishBinIsOnNatureStrip())
                return;
    
            rubbishModel.putRubbishBinRoundBack();
        }
    
    
    }
    

    I think this looks good. At this point I should apologise to Jesse Warden for admonishing him when he suggested to a conference room at FATC that it was o.k. to do this.

    I still think it’s not “o.k.” because if you don’t grasp the value of seperation of concerns, you will make a mockery of this approach to controllers. If you’re starting out with Robotlegs, do not use this approach!

    Addendum

    Extra reading: How I aim to implement the static controller

    The heart of a Static controller is Controller which looks a bit like this:

    public class Controller extends Actor {
    
        public function dispose():void {
            eventMap.unmapListeners();
        }
    
        protected function addMethod(eventType:String, callback:Function, eventClass:Class = null):void {
            eventMap.mapListener(eventDispatcher, eventType, callback, eventClass);
        }
    }
    

    All it does is give you the ‘addMethod’ event and allows ControllerMap to tear it down via ‘dispose’ as the context dies.

    addMethod is a similar to CommandMap#mapCommand, except it doesn’t map a class, it maps a method.

    Also, I need to extend Context to provide/manage ControllerMap.

    ControllerMap collects and disposes of Controllers. It won’t do much more than:

    public function mapController(controllerClass:Class):void {
        injector.mapSingleton(controllerClass);
        controller:IController = injector.getInstance(controllerClass);
        controllers[controllerClass] = controller; // for teardown later
        }
    

    I realise that some people may consider the ‘routing’ and the controller to be different responsibilities. As it stands, I cannot figure out a way of keeping routing seperate, because the Controller#actionMethods have to have a ‘thisObject’ of Controller. It would mean a really dopey looking router method like this:

    addMethod(TimerEvent.RUBBISH_NIGHT, RubbishController, RubbishController.putTheRubbishOut);
    

    Which would get worse when you need to enforce the event type:

    addMethod(TimerEvent.RUBBISH_NIGHT, RubbishController, RubbishController.putTheRubbishOut, TimerEvent);
    

    yick

  • On Robotlegs UI Architectures

    There are now Caveats to all my posts.

    I am considering everything in this post from the point of view of a N-Tier RIA developer’s point of view.

    The Robotlegs MVCS presents a myriad of ways you can work with your tiers, without adding one line of extra framework code or departing from the Best Practices. Then there are the few presentation model mods I’ve seen around, such as Elad Elrom’s.

    I quite like the “Robotlegs is the presentation model” one we use at Visfleet. Below, I give a little bit of backstory and explain why I like it so.

    “MVC”

    I find that the original beauty of MVC is somewhat lost in most breakdowns of MVC-like architectures. I have to wonder if I’m missing something.

    Originally the “View” of MVC was a Component, The original SmallTalk MVC was component oriented. From Fowler’s UI Architecture Article:

    At this point I should stress that there’s not just one view and controller, you have a view-controller pair for each element of the screen, each of the controls and the screen as a whole.

    There are reasons this approach died off and isn’t considered practical. Noteably, when the components are generic (yay re-use) and encapsulate their own modelling. For example, a checkbox has it’s own selection state and transition modelling. All you get as a consumer is a public interface (on the “View” no less) consisting of properties (e.g.: checked), methods and signals (e.g.:VALUE_COMMIT).

    However there is a beauty to the idea of having control/model support for these component views in your MVC-like architecture. This is something I’m a proponent of. Verbs like “select”, “move”, “reorient”, “announce”, “publish”, “change”, “commit”, “save” etc can all become adjectives of state: “Jobs[1] is selected”, “task is running”, “person is facing east”.

    I consider a lot of what most would call ‘view state’ (something kept by view, mediator or presenter) is in fact domain modelling.

    Domain Modelling

    Again from Fowler’s UI Architecture Article:

    The idea behind Separated Presentation is to make a clear division between domain objects that model our perception of the real world, and presentation objects that are the GUI elements we see on the screen. Domain objects should be completely self contained and work without reference to the presentation, they should also be able to support multiple presentations, possibly simultaneously.

    I worry that the domain modelling found in the client-tier of most N-Tier applications (read database backed with a server encapsulating business logic) is often treated as a model of the business logic.

    Certainly there is a good case to model some business logic in the client for speed and responsiveness, networks aren’t terribly fast compared to my computer’s bus. However that “business logic” being modelled is actually a part of the client domain model. It should be considered a utility and not actual Business Domain Modelling.

    Let’s reiterrate that through example.

    The business tier (server) says that:

    • A “Job” may transition state from “started” to “finished” or to “not started”.
    • A “Job” can not transition from “Started” to “Deleted” (you have to finish the job or back out of it before removing it)

    When enforced on the business tier, this is “Business Logic” or “Business Domain Modelling”

    When mimicked in the client tier, this is “Client Domain Modelling”. It is not:

    • Canonincal. So I’m calling it untrusted
    • Business Logic. Let’s not have it in two places.

    Client Domain Models in N-Tier application clients are there to serve the purpose of presenting the business to the user

    What I take away from this is:

    • A “Start” method is a domain model action.
    • selectedItem is domain model state.
    • runningJobs is domain model state.
    • etc…

    To put it another way, I see my whole Robotlegs MVCS stack as one giant ‘Presentation Model’

    Re-tiering feels pointless

    What a lot of people do in their presenters and mediators is have a local state and message bus. This feels awkward to me. Suddenly I’m without a prescription, and frankly it’s really easy for me to write crap again. I can fill my mediator or presenter with awkward code that unsuprisingly is often best served by the MVC pattern.

    I could treat my mediator as the context for another Robotlegs stack, however there is one clear drawback to this: Views, with their own concerns, cannot change containment easily. I explain this with the “Doorbell Model” later.

    One context to rule them all

    Or most of them… There’s lots of good reasons to use subcontexts, but within a context, I want to use a single MVCS 4-Tier.

    I mediate as many components as I can, it gives me some of the elegance that the original MVC had. Each component action is mapped to a command, the command changes state in my modelling in some way, the mediator and view ensure they represent the new state. Again, I’ll outline this in the “Doorbell Model”

    If I want to ‘genericise’ a component, and thus limit other users to it’s view’s public interface (as with most UIComponents), then I still create a robotlegs 4-tier stack and pass in dependencies via the view’s public interface. Then the context for the component uses these values as injection mappings (often named value mappings). I don’t do this very often mind you, a single context doesn’t cause me any real pain. Sub contexts might make for less clutter and I look forward to investigating those further.

    The Doorbell Model

    A simple analogy for why I don’t want any more tiers than the 4 in MVCS.

    First, the views

    • A House is composed of a roof, a floor, and walls.
    • Walls are composed of Mortar, Bricks, Windows, Adornments and Doors
    • Doors have Adornments.
    • Example Adornments are: Lights, Doorknockers, Doorbells, Plaques etc..

    A doorbell, where you might find it.

    I’ve seen Doorbells on Doors, on the Wall beside Doors , and even at the back of a House (for a teenage boy’s mates to ring late in the evening.)

    My original design might call for the Doorbell to be beside the frontDoor, thus contained by the frontWall, in turn contained by the house.

    This frontDoorBell could be mediated by House’ or Door’s mediator. But why? Why not put a mediator on DoorBell. Then when I go to put a DoorBell on the backWall, and move the frontDoorBell to the frontDoor itself, nothing needs to change.

    I almost imagine the DoorBell’s mediator to be a little circuit that hooks it to the wire on the House’ event bus.

    An identifiable doorbell

    Did you notice the arrival of the DoorBell on the backWall. This puppy makes it interesting. The event bus wants to ring two different bells, one for the teenageKidsRoom.bell and one for the hallway.bell. How would we identify the messages coming from these objects? That’s easy, the parent container of the DoorBell can inform it of it’s location (or the doorbell could ask the parent, it’s not an issue we need to care about right now).

    The DoorBell.location property can be used to identify it’s position within views. This is appropriate intimacy and requires nothing but an obvious refactor to introduce it.

    All those classes!

    This approach to architecting my UI means that I have a proliferation of class definitions, and all within the convention of /model /view /controller /events /service. That’s OK. I compartmentalise component of the system by namespaces. Take a look at our namespace-prescription (living document) for Visfleet’s vWork product.

    RFC

    If you think I need to clear up anything or ammend anything or consider something, please comment. I crave peer input :)