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

  • Viewing all posts tagged "Robotlegs"

  • Robotlegs. What I’m falling in love with.

    Background

    I just thought I’d comment on my latest endeavor at Visfleet. I’ve been a little worried about my cobbled together framework for our Flex codebase. It was designed and added too from the day we started with Flex 2 and hasn’t had a proper review since. It works, and we have workable code, but I find that the developers here have the same trouble using it over and over again. So I identified my biggest ongoing concerns:

    Hard to Test Code

    Sure some unit tests could be attached, but I use registries and locators for dependency injection. There are some really nice DI frameworks around now, it’s time to use one.

    Sloppy Inversion of Control

    IOC is sloppy due to many levels of inheritance. I use inversion of control by means of placeholder virtual methods, which after one level of inheritance still leaves us with a “call super” anti-pattern. Or with the need to add more virtual methods. I’d rather just not depend on inheritcance so often.

    Namespace polution

    There’s no convention in my current framework that makes enough sense when it comes to naming and positioning classes. I see Rails apps that do this so well and I get envious. Can haz conventions?

    Service and Model mixed

    Just don’t know what I was thinking. In the days of the mostly read only API (iVistra’s focus on visualization) I could get away with a “ListLoader” class that maintained a canonical representation of server side data using a limited CRUD command set and RESTful view of the data. RESTful is a great place to start with any service, but I think you’re a fool if you try to ‘Resourcify’ everything. It’s definitely not pragmattic, and it’s often not practical either.

    [robotlegs]

    This is robotlegs. Currently the documentation is a little confused about what Robotlegs is (or I find it confiusing). But here’s what I’ve gleaned from Shaun Smith (inventor) and Joel Hooks (major contributor):

    [robotlegs] the DI automation framework

    Robotlegs is a framework for the automation of Dependency Injection. It should be possible to plug any DI framework into it. At the moment, SwiftSuspenders is the only one successfully and completely “adapted”.

    To quote Shaun:

    Robotlegs aims (and does not succeed 100%.. yet) to be a set of tools for automating DI and nothing more. It’s not a DI framework itself.

    It provides:

    • A CommandMap - for instantiating, injecting and executing Commands triggered by an EventDispatcher.
    • A MediatorMap - for instantiating, injecting and registering Mediators as view components arrive on stage in a given context
    • A ViewMap - for injecting directly into view components as they arrive on stage in a given context

    SwiftSuspenders

    SwiftSuspenders is a simple and fast DI framework. It uses very little metadata but I find it very effective. Just try it, even if you don’t use RL, it’s so simple and effective.

    [robotlegs] MVCS

    Let’s call this RL-MVCS for the purpose of this discussion.

    This is a reference implementation MVC framework written using Robotlegs. This is where most of the confusion arises.

    When you look at Robotlegs demos, it’s usually RL-MVCS. When you look at Robotlegs discussions, it’s often about RL-MVCS. When you read the best practices documentation, it is entirely about RL-MVCS.

    That said. I really like this implementation. The only thing I’d like to see made simpler is the idea of “sub contexts”, which I use for separating components and for separating modules, where a module is a largely separate “application domain”.

    What [robotlegs] Addresses.

    Returning to my concerns for my current framework, SwiftSuspenders adresses my sloppy IOC and DI issues directly. [robotlegs] the DI framework is even better though because:

    • I get the ability to switch to a different DI framework (although I might have to write the adapter).
    • I get an easily introduced mechanism for adding DI to my existing MVC implementation.
    • I get documentation, open discussion and an open convention.

    The conventions would help me improve my namespace pollution issues, but I’d still need to do a lot of work and document it myself. Ditto for the service/model coupling I have.

    So this is why I love RL-MVCS, I get all of the RL-DI improvements plus:

    • An MVC implementation that has examples, open convention, and open discussion.
    • A thoroughly well thought through best practice guide.
    • A framework based entirely on OO best practices. It’s actually quite hard to cut corners with RL-MVCS.
    • Conventions that pry my classes apart until they are testable.
    • Conventions that let me readily reduce my long inheritance chains through DI.
    • Nice examples of working projects with tests in place (but not compiled into the final product, Yay!)

    Also, I’ve edified myself on RL-MVCS by picking one system component of our application and only implementing it there. So right now, I have my own application mostly untouched, with just one little corner of it’s world implemented in RL to prove its value. It’s no mean feat for a MVC style framework to be able to work so readily inside another.

  • Mediating ItemRenderers

    ListBase, what it is and is not.

    The ListBase classes are containers. In their simplest form, they mimic a typical OS list. In this capacity they work fairly well, and I see very little reason to mediate ItemRenderers. But they can be used for things far outside the scope of a typical list. This other use, I will refer to as the “Optimised Continuum Container”. Cool name eh? :)

    Continuum Containers.

    A “Continuum Container” is any container that presents a collection (the continuum) along an axis (1). VBox and HBox are prime examples. When the continuum get’s long, we need a scrolling mechanism to present the continuum to the user (2).

    When the continuum gets very long, we need to ‘Optimise’ the container such that it only instantiates enough children to represent what’s on screen (3). That’s what the ListBase classes do.

    A UX decision

    We decided that we wanted to present a list of items to the user in such a way that common goals (actions upon the items) were easy to find and use. Lets say its an employee list. Here’s a typical implementation of a list, with actions associated:

    Maybe not too typical, this obviously has some design challenges. Common actions for a list item should be readily locatable. One way of doing this is shown above, you keep the actions still (motionless, in one obvious place), and you select the item upon which to act.

    When your list window gets large, as ours often do, the travel time with the mouse to the action items becomes frustrating and can cause disorientation. So what we do is (and you’ve seen this many times before) is to group the actions with the list item:

    Not a typical ListItem

    So suddenly we don’t have typical list items. Each list item has more than one “concern” now:

    • Present the name
    • Present the state of “in/out”
    • Accept input to change “in/out” state
    • Accept input to launch the editor
    • Accept input to edit the item
    • Accept input to launch an email window

    It get’s even more complicated when there are modelled conditions that lie outside the VO, for example, if the user does not have permission to send emails from the application, we don’t want to show the email button.

    I personally believe that these concerns should be seperate. When I first saw an example of a view-mediator tuple for a single button, I thought “What horrendous overkill”. Now I’ve been Robotlegging it for a while, I can’t imagine a life less granular, and I always try to get my view/mediator “concern count” near to 1.

    If you don’t agree with that last paragraph, then you won’t need to mediate ItemRenderers.

    The view for my list item in that example includes several child views (and mediators) for each button. This is so clean and simple to refactor, and to read, that I would not have it any other way (pragmatically speaking).

    Mediating ItemRenderers

    ItemRenderers and ItemEditors lead a fragile existence and are not straight-forward to mediate. This does not mean you can’t mediate them, it means you must know your enemy.

    ItemRenderers are re-used.

    So when an item goes off the list, it’s renderer does not get destroyed, instead the ‘data’ property is set to a new item and the renderer is moved into place on the list.

    This means that you can’t simply rely on instantiation and the event bus to observe when you need to mediate your view. You need to also watch the data property. That’s not so hard now is it?

    Typically when you mediate, you establish state on instantiation (if necessary) and modify state as changes come off the event bus (and binding). This means that you establish an accurate reflection of state by knowing the previous “reflection of state” was correct

    That’s what makes ItemRenderers a little harder, you need to reset state more often, and there are more gotchas.

    For example, when we save an edit on a list item, we tell the Renderer (not the editor) to switch to a busy “spinny circle” state. If the item goes off screen, the Renderer get’s reused for something else, and we must reset it’s state such that it doesn’t look busy. If the item comes back on screen while still saving to the server (hello New Zealand ping times), then we need to reset it’s state to busy.

    I’ll try to write a follow up article on best practices for resetting ItemRenderer state.

    ItemEditors stand in for renderers.

    When an item is editable and the user begins an edit, the ItemRenderer is hidden, and a new ItemEditor is instantiated. This means that whatever mediation you use for the renderer, may well need to be duplicated for the editor. I keep these concerns seperate and look for common code via common refactoring methods (extract*).

    Stick with the basics.

    Despite all this, we do have a simple set of rules we always follow, no matter the renderer. I’ll spell them out here, and in my next article I’ll show some working code.

    • Use the VO dependency provided by the list (.data property)
    • OnItemEditBegin and OnItemEditEnd are handled at the parent (list) mediator.
    • When an edit begins (OnItemEditBegin), our list mediator asks the model for an editable VO and provides that to the list in place of the original VO.
    • When an edit ends (OnItemEditEnd) the list mediator issues a command to save the modified VO. This keeps us canonical with the server/services.
  • 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 :)

  • Robotlegs Plugin for IntelliJ

    So I started a little plugin a few days ago. I’m writing it for IntelliJ and it’s designed to make your life a little simpler, letting you navigate between classes with known ‘Up’ and ‘Down’ relationships in Robotlegs MVCS. Eg, The view is “Up” from the mediator and the service is “Down” from a command.

    IntelliJ is really cool.

    Apart from finding great little timesavers all the time, this is my first exposure to the underlying code of IntelliJ. It looks a little ‘patternitis’ but everything makes sense, and even the closed source ‘JavaScript’ plugin was easy enough to take advantage of with just headers.

    It’s also my first time into Java, and the experience has been made sweet because:

    1. IntelliJ is a great IDE and makes light work of what would be chore-like coding
    2. IntelliJ is written with IntelliJ, and all the Best Practices and quality coding behaviours that IntelliJ promotes, are included in the “OpenAPI”

    I mean the Javadocs are ancient and out of date, and some things are clearly legacy, and yet me, a n00b Java programmer had no trouble cobbling together the first part of the Robotlegs plugin.

    The Plugin, where’s that then?

    Here: http://plugins.intellij.net/plugin/?idea&id=4685 which means it’s also available in your IDE.

    You may need the EAP version of IntelliJ as that is what I coded against.

    It only does one thing right now. If you are in a mediator, then Ctrl-Alt-PageUp will take you to the linked in view. There is a roadmap here and all the source is here

    All the design is in place and a lot of the ‘discovery’ is done. So things should fall into place. Let me know if you have any trouble with it.

  • Ascending the Ivory Tower is good for everyone.

    I attended the Flash And The City conference last week. It was an amazing experience and I met some of my personal Heroes. People who make the effort to popularise good software, good design, good tools, and good practices.

    Sometimes I don’t see eye to eye with them, but I still respect anyone who puts themselves out there to be criticised so willingly :)

    Funnily, a term started re-appearing that I haven’t had applied to my opinions (or the opinions of those I hold in highest regard) in a long while:

    Ivory Tower

    Ivory Tower connotes a place that’s unattainable. It’s being used regularly in the pejorative when discussing best practices for business, development teams and coding standards.

    Now when I started using Object Oriented concepts like message passing, way back in the day, with Flash 4 and Flash 5, the same Ivory-Tower term was often bandied about by hackers and traditional linear programmers. It was often purported that things like Message Passing, Encapsulation and Polymorphism were too hard to understand and ill-suited to the day to day Flash developers’ work.

    In 2000 I presented at the Sydney FlashKit Conference in an attempt to promote Flash as an RIA platform, all we needed was better coding practices. It was an uphill battle, I was asking people to climb an “Ivory Tower”. I was by no means a purist. I still don’t think I’m a purist.

    So I will mix the Ivory Tower metaphor with the climb Mt Everest Metaphor somewhat from here. I think there is a surmountable slope to lofty standards of Agile and Best Practices.

    Purists

    A purist is someone who attains the summit and pretends they’ve never had to do a day of climbing in their life. A purist wonders, condescendingly, how you could possibly do things any other way. A purist doesn’t care for outside pressures. This kind of elitism can only be found in people who aren’t pressured into making pragmatic choices.

    Pragmatism

    Pragmatism does not mean “embrace the status-quo”. It means when achieving your goals, you recognise the path to attain them and the alternatives, especially the alternatives that bring everyone else to the summit. You will chose alternatives that let you reach important waypoints during your ascent.

    Pragmatism can be applied to your singular ascent, your current team’s ascent, and everyone else’s ascent.

    Our experiences

    2 Years ago we set out to become an Agile development team that:

    • Had continuous integration
    • Automated, repeatable deploys
    • Encapsulated documentation (Knowledge stored in the same place it needed to be applied)
    • Automated Test and Behaviour driven development
    • Automated Integration testing
    • Clean consistent code
    • Software with a great user experience
    • Frequent delivery of improvements.

    That was out lofty peak. We’re still not there, however I would say that we are in sight of our first peak. We got this far not by being purists, but by being pragmatists. Once we are upon the summit, we’ll look for something taller I am sure :)

    Micro-architectures

    Micro-architectures and small prescriptions are a fantastic tool for the worthy climber.

    These are both lightweight prescriptions (easy to follow) that have massive impact:

    • Robotlegs gives you the Single Responsibility Concept, Code by Contract, Testable code etc.
    • Kanban gives you focused work-in-process, release-often, faster feedback etc.

    I consider them both important tools for this ascent, others are Hudson CI, FlexUnit, Cucumber and many many more.

    In closing

    So my only argument with some of my heroes who proclaim “Ivory Tower” is:

    “It’s not healthy to denigrate these attainable best practices”.

    With the greatest respect, I ask that we speak instead in the following terms.

    Find valid, workable stops along the way, and good reasons, not excuses, for stopping short of the summit

    It has a more positive air to it, and it doesn’t devalue the amazing, and often freely given, efforts of the Mountain Climbing Specialists whom I think deserve slightly more respect.

    Hmmm… and those of us who like to think of ourselves as Mountain Climbing Specialists could work harder to be humble. Not to make a stink so often just because someone cut a corner we wouldn’t have.

  • Mediating ItemRenderers, Again.

    I’ve posted about this before.

    I still have no shame about mediating ItemRenderers and to my happy suprise, Flex 4 makes it simpler with the spark.ItemRenderer and its dataChange event.

    Here’s my base prescription in sample form:

    Now you and I both know it can be a lot simpler to achieve the same, namely:

    Why mediate, it’s so simple? Well the reason is simple too. Things never stay simple. My prescription is a easy template for me to follow, its already second nature for me to do it that way.

    The moment I need to mix selection state (or multiple models) into a single renderer, my mediator is there waiting. This includes ensuring that no matter what data source is generating the itemRenderer, I have a templated method for locating the correct model (hence the comment in my mediator above).

  • Builder pattern is so easy in Robotlegs

    The Builder Pattern is a breeze in Robotlegs

    public class ConcreteWidgetBuilder implements IWidgetBuilder {
    
      [Inject]
      public var injector:IInjector;
    
      public function buildPart(parameterised:IThing):IWidget {
        var widget:IWidget = injector.getInstance(IWidget);
        widget.param = parameterised;
    
        return widget;
      }
    
    }
    

    Parameterized builder

    If you want to control what gets instanced based on a parameter:

    public class ConcreteWidgetBuilder implements IWidgetBuilder {
    
      [Inject]
      public var injector:IInjector;
    
      public function buildPart(parameterised:IThing):IWidget {
        var interface:Class;
    
        switch(parameterised.style) {
          case ThingConst.COOL:
            interface = ICoolWidget;
            break;
          case ThingConst.HOT:
            interface = IHotWidget;
            break;
          default:
            interface = IDefaultWidget;
        }
    
        var widget:IWidget = injector.getInstance(interface);
        widget.param = parameterised;
    
        return widget;
      }
    
    }
    

    Bit freakin’ sexy if you ask me.

  • Robotlegs Bootstrap Actor

    I’m sharing the following Bootstrap Actor class, which simplifies bootstrap sequencing in Robotlegs.

    I figure it has some value because Stray, who has a fairly similar programming ethos to me, see’s some merit in it.

    Usage first.

    Trigger the bootstrap in your context

    override public function startup():void {
        commandMap.mapEvent(ContextEvent.STARTUP_COMPLETE, BootstrapCommand, ContextEvent);
        super.startup();
    }
    

    Which calls the BootstrapCommand

    import org.robotlegs.mvcs.Command;
    
    public class BootstrapCommand extends Command {
    
        override public function execute():void {
            injector.mapSingleton(ConfigurationSequence);
            injector.getInstance(ConfigurationSequence).step();
        }
    
    }
    

    Then implement the sequence

    public class ConfigurationSequence extends AbstractSequencer {
    
        override protected function configure():void {
            addStep(ConfigureWorkersModelCommand);
            addStep(ConfigureScalesModelCommand);
    
            ... yadda yadda ... 
    
            addStep(ConfigureJobDraggingModel);
        }
    
    }
    

    What happens is that the line in the bootstrap

    injector.getInstance(ConfigurationSequence).step();
    

    instances the Sequencer and tells it to run the next step, which in this case, is the first one.

    Each command added with ‘addStep’ is added as a command mapping which responds to a SequenceStepEvent with a named type. This is not conventional behavior for an event, but it works really well in this context.

    Finally, a sequenced command looks a bit like this:

    public class ConfigureScheduleHeaderViewCommand extends Command {
    
        [Inject]
        public var event:SequenceStepEvent;
    
        override public function execute():void {
            mediatorMap.mapView(TimelineView, TimelineMediator);
            ... yadda yadda ...
    
            event.step();
        }
    }
    

    The event.step causes the next item to be run.

    Source Code

    The sequencer gets the addStep() and configure() methods from AbstractSequencer.as.

    You also need the SequenceStepEvent.as class

    Options

    Bootstrap command and context

    You could merge BootstrapCommand into the context. I prefer to overdo SRP than underdo it.

    Automatically step

    Instead of specifying event.step() in each sequence command, you could modify AbstractSequencer#executeNextStep like this:

    private function executeNextStep():void {
        var classFQN:String = steps.shift();
        var event:SequenceStepEvent = new SequenceStepEvent(classFQN, this);
    
        dispatch(event);
    
        step();
    }
    
  • 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

  • Why Boiler is better than Robotlegs. Pt. 1

    Haha! That’s gunna turn some heads.. I hope.

    Herein I set out to explain why I’m building Boiler. Other than the obvious fun of writing a framework, I have some very specific reasons.

    I could be wrong of course, Robotlegs is so good (and it’s well past the alpha stage, unlike Boiler) that it’s a tough call. However, why would I bother if I wasn’t trying to improve on something awesome?

    Doubling intent

    Imagine this is a mediator I just wrote:

    package views {
        public class WidgetMediator {
    
        [Inject]
        public var notifier:IEventDispatcher;
    
            private var view:Widget;
    
            public function register(view:Widget):void {
                this.view = view;
    
                view.addEventListener(MouseEvent.Click, handleClick);
            }
    
            public function deregister():void {
                view.removeEventListener(MouseEvent.Click, handleClick);
            }
    
            protected function handleClick(event:MouseEvent):void {
                notifier.dispatchEvent(event);
            }
        }
    }
    

    I consider this class to have all the markings of a mediator. It’s name ends in mediator, that should be enough… But there’s more. It’s in the views folder where a lot of folk stash their mediators. It expects to be registered against a view:

    register(view:Widget)
    

    Despite not inheriting from a Mediator Interface, it’s a mediator. In the land of Ruby, they call it ‘duck-typing’. It looks like a duck, quacks like a duck, it’s a duck.

    So in Boiler, we use conventions to invert control. When you start using Steam, you follow convention to describe the intent for a class. Steam, by the way, is the reference desktop framework for Boiler, like MVCS is for Robotlegs.

    The above mediator needs only be ‘Mapped’ using SwiftSuspenders and Steam will configure injections and view mappings ‘because it looks like a mediator’.

    In Boiler:

    lifetime.mapClass(WidgetMediator,WidgetMediator); // A little note on the first param later.
    

    In Robotlegs:

    mediatorMap.mapMediator(WidgetMediator);
    

    It’s a tiny difference, really, except now we don’t have to inherit from anything to look like something. Later I’ll show that we also don’t let ourselves get caught by inheriting from sugar classes.

    The first thing that Boiler gives you, is no more polymorphic dependencies that only serve to duplicate intent.

    When you want to extend the framework behavior, remove behavior, or use certain behavior in only some modules, the benefits of avoiding framework polymorphism become clear. Later on, I’ll demonstrate this with examples that extend or modify the framework.

    About that first parameter

    Why does SwiftSuspenders require an interface separate from the class to instance? This example is a mediator, all of it’s dependencies are injected. It’s never injected into another class. Where it’s built is where it’s stored, in a generic, testable class… So I can’t see a problem with lifetime.mapClass(widgetMediator);