Skip to content

Archive

Category: Software Design

Recently I experimented with various ways of configuring data programmatically.

Okay, I’ll say loud what some will be thinking when reading this. Why not use an XML file?

Well… no. Not unless you need to store this data, share it… load it over a network… (then, yes). In many other cases, using hard, compile safe code to assign values and configure objects, has advantages.

  • XML data without a validator (including build system integration) is no better than interpreted code.
  • Without a template (and a convenient editor driving the ‘form filling process’) XML data is tedious to write and tedious to maintain.
  • Hard-wired configs break at compile time. Data loaded from XML files or CSV rarely breaks before runtime.
  • There’s no point in writing data formats and validators for data that changes often – for example when a codebase / paradigm is relatively ‘fresh’.

So I’ll go with hard-wiring and try to figure a decent pattern for it. I’ll use macros if I have to, and avoid them if I can. I was, then, looking for a patterned way of configuring my data, and I came up with this:

  1. Have a class Foo, need to configure instances of Foo.
  2. Created an interface IFooSetup, specifying getter methods for configuration data: getA(), getB(), getC()… etc… etc…
  3. Created a class FooDefaultSetup <IFooSetup> providing a default configuration.
  4. Created multiple subclasses of FooDefaultSetupBlueFooSetup, YellowFooSetup, GreenFooSetup etc etc…

Not just I won’t do it again (at least, not in ObjC). I will also refactor my code.

Why is this approach troublesome – why did I come up with this idea in the first place?

Setup interface/protocol

IFooSetup is a protocol dedicated to helping programmers configure instances of Foo. Sometimes it can work. One advantage of using an interface is that (inside an IDE) it works much like a form (a piece of paper with blanks that one needs to write into). The compiler helps the programmer ensure (often, in realtime) that all required config parameters are set.

So good so far (and I don’t care whether anybody’s bothered writing a class just to configure another object).

Maybe it is a pattern, then. A fortiori, however, it does take a couple of useful language features for this to actually work.

Default config class

Sooner or later, the idea of creating a class named FooDefaultSetup will arise. Why, because several objects shared common parameters. It is logical.

Unfortunately, although some languages allow abstract classes, ObjC does not. As a result, once we go with FooDefaultSetup, we have to implement all the methods declared by IFooSetup, including getters for which FooDefaultSetup can supply no meaningful default – and as a result we have just short-circuited the usability of IFooSetup – it no longer works ‘more or less like a form’ – to determine what methods we’d like to override, we have to check the source code for IFooSetup.

Breakable code.

No real mess will start until we change the signature of a method in IFooSetup. At this point, it would be neat if the compiler could help us make sure that the many, many implementers of IFooSetup (BlueFooSetup, YellowFooSetup, … ) are updated accordingly, alas…

  • Some languages (quizzically, the defunct Javascript 4) will have you tag every method intended to override a method up the inheritance chain. This means that you can’t accidentally override methods. It also means that you get an error when the method no longer overrides another method. Not so in ObjC
  • Other languages won’t let you implement a method that hasn’t been declared. Not so in ObjC.

What happens, then?

FooDefaultSetup is somewhat maintainable since it must implement all methods in IFooSetup.

Sadly, none of the subclasses of FooDefaultSetup are maintainable. Forgetting to update/correct the method signature for any of these subclasses is now the easiest thing in the world, resulting in code never being called. Not just any code, but sound, simple, honestly good looking trivial code that mainly consists in getters.

A little down the line we’ll be looking at bugs and wondering why an object doesn’t behave as expected, the trivial reason being: configuration code is out of date, and the compiler knows nothing about it.

K.I.S.S

So, yea… never again. Instead of configuring objects in this way, I’ll sooner do the following and be better for it:

  • Keep it simple, stupid. Configure an object by calling accessors on this object.
  • If you need a ‘checklist’ of what needs to be configured… consider copy-pasting the config block from another, similar object. Or write a checklist. Or write a validator.
  • At least when an accessor’s signature changes, the compiler will warn against all and every deprecated use of the modified method.

This is quick tutorial showing how to get started with F* in Objective-C. F* is a proposed meta-pattern for application development (see here for related documents)

You can check out the sample project from SVN:

http://xp-dev.com/svn/harmony-framework/trunk/f-star/iOS/tutorial/FStarExample/

Setting up your project

  1. Open XCode.
  2. Go to File > New Project
  3. Select ‘Empty Application’.
  4. In Product Name, I input FStarExample.
  5. I put my projects under my experiments/ folder. XCode will create a folder for our project.

Arranging the sample project

I like to have ‘headroom’ in my projects. The initial project structure looks like this:

  • FStarExample (project node)
    • FStarExample (source location)
    • FStarExampleTests (for unit testing)
    • Frameworks (libraries required by the iOS SDK)
    • Products (build output)

I regroup all items, so that it looks like this:

  • FStarExample (project node)
    • source (custom group)
    • tests (previously, ‘FStarExampleTests’)
    • [implied]
      • FStarExample-Prefix.pch (digged up from ‘Supporting Files’ I just like to keep this one ‘visible’)
      • FStarExample (still the app delegate)
      • Products
      • Frameworks

Keep in mind that XCode groups are just a convenient way to… group files. For better and for worse, grouping is irrelevant to the underlying file structure.

Setting up an F* instance

Under source I create the following structure:

  • source
    • [m]
    • Facade.h
    • Dispatcher.h
    • Feature.h

The Facade will be used to instantiate all the features we use in our application. The Dispatcher provides the basis for gluing features together. Feature is the base class for all application features.

Note: XCode doesn’t encourage physical groupings (putting source files in separate folders – it is needless to say possible but doesn’t flow smoothly) so I’ll be content with XCode groups.

Creating a feature

To create a feature named foo, follow the steps:

  1. create a group named foo
  2. create a subclass of Feature, Foo inside group foo.
  3. foo overrides setup in Feature.
  4. import the feature class from Facade and add an entry to initFeatures.

The sample project illustrates the above steps.

Event handling

The dispatcher mediates communication between features via events. In the provided example:

  • Foo registers with the dispatcher to receive an event x. registration happens within the setup method. (While setup is running, nothing warrants that all features are already initialized so while it’s okay to register for events, it is not okay to dispatch.
  • After all features are setup, the start method is called on each feature, at which point Bar dispatches the event.
If you test the sample project (hold run button in top left until options appear), you can check the output in the log window.

Implementation notes

About event handling and the dispatcher
In my sample project, the dispatcher is not very scalable – as we go on and define more and more notifications, it will quickly become bloated. I will probably update the sample project a bit later to show how this can be fixed.
In practice this needs to be done with some care – when using F* defining new notifications is common enough that a templated approach quickly becomes desirable.
About the facade
In the facade each feature is bound to the applications in two ways:
  • We need to import the feature class
  • The feature class needs to be instantiated and added to the feature list.
Classes can be instantiated dynamically, which practically allows turning a feature off without having to change any code. Needless to say this comes at the cost of compile time safety.
The facade should be connected with FStarExampleAppDelegate. As the last call in application:didFinishLaunchingWithOptions: I instantiate the facade. A real application would need to provide access to UI resources (here, the window provided by the app delegate).

In Practice

When I use F*, I tend two follow a 3 step cycle.

1. induction

During the ‘inductive phase’, I try to focus exclusively on the problem I am solving. If I feel my feature requires external input (or a signal), I design notifications without worrying about the source of such notifications.

This approach becomes important over time because it allows solving the problem at hand without  burdening ourselves with the growing ‘mass of code’ that the project generates. For me this inductive phase is similar to ‘starting a new project’. Surely most programmers have noticed that they feel dynamic and fresh at the beginning of a new project?

2. testing

During the testing phase, notifications can be used to write acceptance tests – test the feature in isolation.

3. integration

During the integration phase, I make sure that the notifications the feature relies on are actually satisfied.

Our code is rarely as neat as we’d like it to be. And sometimes we’d like to make it do something, and we’re not sure how. Depending on… …a lot of things, there are two ways around the problem:

  1. Go with the code. Work out the problem bottom up and wire up everything as best as we can.
  2. Bend (and break) the code. Work out the problem top down, lay out a neat solution and (re)wire up everything else according to how we think is best.

The main argument for going with the code is that it won’t break anything. Honest, it’s true. I’ve seen it done with extreme care and it works. But… It doesn’t make it easier to make the next change, and the next change, and the next change.

Working top down will break the code, and should be done with care too. Sometimes breaking and repairing code is better than just going along with it. But just because the code hasn’t been written to solve the particular, new problem we’re looking at needn’t mean it’s bad code.

A Story

It was an ordinary day. A colleague had been working for a couple of months on a client side bridging component. We wanted the same functionality on the server side and I just thought it would be neat to share the code. So I suggested we do just that and he told me the component couldn’t be extracted from the client. I said it could, and he asked: how?

Separation is rarely down to our software’s effective logic. For practical purposes, anything can be separated from anything else. So I just said:

“Use the Sword of Faith”

A couple of days later, the bridging component was all neatly… modularized. The code was cleaner and more readable (not my opinion – I didn’t even look). Unsurprisingly (and however unfortunate) the guy in charge of our server refused to use this code, and moved on to write their own. Whatever project this related to was postponed, and we moved on…

The Evangelist

For all the medieval hype surrounding it, the sword of faith is a well named design tool. Ideally it should be as sharp as a Katana, and operated with surgical precision (that and lightning fast coding skill, right?). Why a sword, then. Well there are other tools you might consider working with when extending and fixing up your code:

  • The mace. You can maim and mangle large sections of your code in the name of a good cause, leaving behind you many bugs for others (or more likely, yourself) to fix later.
  • Biological weapons. You can add a couple of lines of code here and there to get your new feature to work. This code won’t make sense in context and will likely contribute the overall sense of rot and decay emanating from your codebase.
  • The Hydrogen bomb. You can delete whole classes, even packages. At this point extending our software isn’t a problem. The problem is we’ll have to write the code all over again.

In contrast, there are several techniques founding our belief into the sword of faith – namely, that code can be improved locally and that local improvements over time can significantly reduce our overall sense of helplessness looking at (what looks less like) the ambient mess.

  1. Define a ‘good solution’ for the problem at hand. Inasmuch as possible, the solution should hold good considered in isolation.
  2. Retrofit the ideal solution onto existing code, pass (existing code fits the solution) or break (existing code must be modified)
  3. Rewrite/Refactor as little and as much code as necessary.
  4. Be comprehensive, not exhaustive. If you’re unsure whether something needs/to be changed or fixed, you (or a compiler, or a unit test, or a tester…) will find out later. Trying to be exhaustive may result in changing too much code, getting a migraine, breaking more code and losing hair.

In similar situations, many programmers will either offer to ‘entirely refactor (meaning, rewrite) the code’ or ‘just make it work’ (aka muddle through). These attitudes underly dubious beliefs, explicit and implicit.

  • The explicit belief that Order and Chaos cannot coexist, (let alone interact) within our codebase.
  • The implicit (and somewhat Luciferian) belief that this time we’ll get everything right.

Don’t buy into this s**t. Use the sword.

The Brothel

Back to my code, here is what I wanted to do today. I am rewriting the ‘go back to main menu’ feature in Antistar. Yes, I could muddle through, but I won’t. Here goes.

1. Destroying the game session is (almost) all we (should need) to do.

I have a class named GameSession. This class is instantiated by a command (GameStart) and is meant to contain the game session (everything that goes on while playing) as opposed to the game container (the menus and other bits and pieces that frame the gaming experience).

So I’m guessing deallocating the game session object is a good step towards going home.

While many objects reference the session, most (all) of these are back-references from aggregates. Say we just called [session release], would [session dealloc] be called? Sadly no. It took a couple of calls to release to get dealloc to kick in. Not being the local reference counting expert, I use a little trick to get me out of trouble in these situations. We can set a breakpoint in an object’s [ retain] method, overriding it as thus:

-(id)retain{

return [super retain]; // set a breakpoint here

}

I find it convenient, although it is crude. I don’t keep this code after I find what I’m looking for.

2. Everything must go

It isn’t enough that dealloc be called onto the game session object. We want the whole hierarchy of objects owned by the session to ‘collapse’. I don’t have a clean implementation of [GameSession dealloc], so I’m guessing now is a good time.

The idea is simple. All objects owned by the game session should get deallocated, unless proven otherwise — recursively.

So I spent about three hours writing miscellaneous implementations of [dealloc] (I’ll explain later why I don’t do this upfront). Amusingly, after I finished I found the code crashing exactly as it had three hours before:

  1. The display link dispatches to my EAGLView
  2. My overlay view ‘ticks’
  3. Talkback display attempts using a zombie instance of the… …game session.

So why is my EAGLView not being destroyed?

  1. Retained as a child of the main window.
  2. Retained by display link using EAGLView’s startAnimation method.
  3. Retained (and most likely, released again later) by a couple of system level thingies.

Let’s ignore (3) for now. So practically this says we should remove the 3D view from the main window and unregister the display link callback. While it may seem obvious, it is altogether pleasant and reassuring to find about it this way, right?

There we go:

  • EAGLView provides a (void)stopAnimation method (this is code provided by the big guns).
  • We have removeFromSuperView, or whatever it’s called.

After adding this code to my MainMenuAction, I had a slightly more worrying occurrence as an auto-release pool attempted to deallocate the view a second time. This reminded me a couple of useful points:

  • When using NSZombieEnabled, we can find out the type of the zombie being accessed by checking the console, if anywhere.
  • self.myRetainedProperty = foo; will retain myRetainedProperty. myRetainedProperty = foo will not.

After fixing this up, I could observe the following behavior when pressing the menu button:

  • The screen goes blank
  • The overlay view (ui controls) is still visible. Not much of a surprise. For better (and especially for worse), I use a UI view from a nib file for my controls. As it is, this view exists independently from the game session. It isn’t clean, but it isn’t really useful to ever get rid of it either. Notwithstanding I can press the menu button over again, causing an exception and demonstrating that, if we’re keeping a view after the game session has been discarded, we need to do some cleanup.
  • The game menu isn’t showing. Not a surprise either. The game menu shouldn’t be part of the view hierarchy while we’re playing, so I guess we’ll have to put it back.

3. The final touch?

I made a trivial interface, GameSessionListener:

@protocol GameSessionListener <NSObject>

-(void)gameSessionEnded;

@end

This lets me pass an instance of the game container to the game session, so after the game is over the container can put up the menu again.

While this works, starting and exiting over and over causes bugs on the game menu. It looks like the view hierarchy interacts in unpredictable ways, as eventually the menu screen goes blank.

But hey, that’s what the sword is for, right? :)

Needless to say I went back to my code a few minutes later. UIViews don’t just go blank, do they? and that view had to interact with something. So I looked up whatever views (not many) are somehow shared between the game container and the game session. Then I found the view root  (a kind of custom thing, not the absolute view hierarchy root) was being over-released.

What have we gained?

In the previous version of Antistar, the game exit/re-entry process is fairly robust. Meanwhile, it involves a lot of cookery for no special reason other than me shying away from just saying ‘let’s tear down everything’. In theory, tearing everything down should be easy. In practice, if it’s not then we probably have an unsolved problem that’s not good being left unsolved.

The ‘cookery’ occasioned hard to fix bugs. Not tearing everything down means having dirty objects lingering, leading to functional bugs. I haven’t run the new code through instruments and I’m bound to find leaks. Good point here. Leaks, unlike functional bugs, can be detected automatically.

Not tearing everything down also defeats one of the useful applications of a so called game container. Running not just one, but several games under the same hat.

So I started with a clear goal and solved the problem as I intended. I wanted to clear the game session by deallocating it, and this is what it does. What I did not intend to get over and done with today (yesterday, rather) is memory management. Yes, I feel I have a head start on this, but that wasn’t quite the issue here and I’ll look into it another time.

Epilogue

  1. I didn’t go around analyzing this and that, eventually deciding that I should rewrite the whole whatchamacallit (don’t use the hydrogen bomb)
  2. I haven’t hacked up a quick patch (no biological weapons)
  3. I added code that’s useful, concise and clear and contributes functionality to my app (use the sword)
  4. I haven’t fixed or otherwise ‘improved’ anything that didn’t need fixing (don’t use the mace)
  5. I spent about 7 hours on this f***ing thing (have faith).

Hairlock - dev pic

Let’s face it, Good Old Fashioned AI was practically (if unintentionally) invented for making games. Why? Because it works well with clean, clearcut data sets. So instead of lamenting that the lab methods only work with ‘block-worlds’, take notice and realize game worlds are all ‘block-worlds’. Or shall we?

I should be elated I suppose. I wouldn’t be considering implementing a general purpose solver unless I actually had a use in mind, and I if I do, then I’m in for fun and the weather, since I get to do the kind of programming I like best – as if coding a game wasn’t hard work, hard fun enough.

A conversation

Hyde: Your objects and functions. All of this lacks structure.

Jekyll: It’s because I want to address a few more practical problems before normalizing the structure.

Hyde: Well, I think it’s time. Actually, aren’t you getting tired of reusing the same recipes over and over?

Jekyll: We’ve been through this before. Sometimes applying the same recipe over and over is better than attempting to normalize everything, only to realize that we weren’t applying quite the same recipe over and over.

Hyde: Just a simple heuristic solver would breeze over the tedious steps you take in programming your game logic. Plus you could subtly vary the solver’s behavior to emulate agents with various degrees of intelligence and contrasting personas.

Jekyll: Specifically what can a problem solver do, other than add more mess to the ambient mess?

Hyde: Come to reason. Our problem solver will solve our problems.

Jekyll: Can I trust you?

Hyde: No, but you have to.

Jekyll: How about performance. Won’t this ruin performance?

Hyde: Probably not. Once you’ve objectified search steps, you’ll find it easy to stagger processing. Besides the solver load is independent from  the rendering/animation load.

Jekyll: Back to the original point, why take excuse of the lack of structure to suggest introducing a problem solver?

Hyde: Elementary. Solvers don’t look at individual steps. Good solvers heuristically chain steps without consideration for what each individual step does. Ergo, programming-wise writing a solver will force your game code into normalized structures.

Jekyll: Sounds Ominous.

A Piece of Cake

Chocolate isn’t enough. The world is not enough. I’ve been wondering all week why my girlfriend has been babbling about how she’d been thinking of ordering a cake, and how it would be great to have a cake done to spec. Even asking me if I’d like mint chocolate. I don’t really think mint and chocolate are such great pals.

Either way. Enjoy the cake – or the picture at least. See you in the app store.

Here’s an idea that may work for some of us. I’ll try this next week if, and only if, I run into annoyances:

Let’s take an example:

  1. We have a Model class. The model class is just a placeholder for data.
  2. We have a Request class. The request class is just querying a server for data.
  3. We have a controller that (a) fires the Request and receives its response and (2) passes the result to the model.

Does the controller need to effect this operation? Think not. Maybe the controller shouldn’t control this.

The business logic argument

The described operation is exposing too much of the model in the wrong way. The controller should care about how the model updates only insofar as the view may need to render something about it.

If we need the view to let the user know that a request has been sent, what we’re really asking for is the model to fire an event to let us know, and the controller to handle this event.

The clarity argument.

Controllers easily get intricate. If we can move something from the controller to the view or the model, we should.

I like to have struct like classes that not define any operations. This isn’t incompatible. More often than not, model operations can be neatly defined using commands. Otherwise, we can fall back on a model/data split, where the model is a kind of ‘data controller’ viz. the model holds no state, only business flow, and the data holds no function, just data.

The integration argument

If the controller is manipulating view and model states too finely, service integration is reduced. Instead of having qualified, usable views and models, we have particulate, D.I.Y views and models that turn out, more often than not, to provide the kind of flexibility attracting bugs and reducing maintainability.

A particular, enlightening scenario is when the model or view expose sufficient state that they could not avoid being put into an inconsistent state by a careless controller. Hey, we got a nice little rule here:

If a view or model’s interface allows putting such view or model in an inconsistent state, there is too much logic in the controller.

An organic, yet ideal controller

An ideal controller should…

  1. Hold no state
  2. Receive events from the view and model
  3. Issue high level commands mapping the model to the view, and vice versa.
  4. Be thin.
  5. Look boring and redundant.

Why (5)? well, that’s good, and that’s why we often wonder what the controller is for. Here’s an example:

  1. Play button is pressed and fires an event
  2. Controller handles the event and invokes the model’s play method.

That’s boring, yet performs an awfully simple function: decouple the view from the model. Because it is boring and simple, it also makes a fair allowance for ‘becoming more complicated later on’ without anticipating over much anything at all. This isn’t planning what features we’ll need in six months, it’s just a kind of placeholder for future intricacies.

On the other hand, here’s a counter-example

  1. Play button is pressed and fires an event
  2. Controller handles the event
  3. Controller creates a download stream.
  4. Controller receives a callback to indicate the stream is connected (and sets a ‘control state’ flag)
  5. Controller  changes the color of the play button.

The good news

Interaction can easily get complex. Models and views can also get complex. Let the controller be thin and stateless. If our controllers are more concerned with the semantics of interaction, and less with rendering and model updates, they are better controllers.

The bad news is, it’s easy to push too much logic in a controller. The good news is, it’s easy to take it out.

I wrote a little, here and there, about the so called F* meta-pattern. I created F* to close a bag of worms. However… …F* is merely a minority report. A kind of footnote to MVC.

In the grand scheme of corporate front end development, MVC stands out for super-structure. To begin with, it doesn’t take a genius architect to work out labour separation. We named Max, Vincent and Connie. How many Frogs would it take to maintain an F* app?

Incidentally, the bag of worm re-opened when I tried to explain the command pattern to a new recruit, and got a poor old MVC natural on my doorstep the next day.

What would you do? Rewrite the whole thing? I didn’t. I tried fixing it up. Now’s a time for rambling and recriminating.

Post-scriptum

OK then. This post is about MVC the way people do it ‘their own way’. Without using frameworks, and without using the command pattern. This post doesn’t contain answers. It’s just listing lazily a lot of scary/worrying/time consuming issues.

Command patterns and frameworks have one thing in common. They’re a little heavy. Heavy can mean a lack of concision and elegance. It can also imply conceptual overhead. Heavy can also cover an element of cultural difference. Either way…

…heavy isn’t for everybody. I didn’t write heavy code when I was 17. I did write some cool stuff though, including stuff I would only half-guttedly replicate today. So this post is raising an issue: can we still just write a little bit of code, and get away with it?

Finally, before you read away, be assured this isn’t a spoiler. If you want to do your own MVC stuff without a command pattern and without a framework, it won’t protect you against unpleasant surprises.

May refactoring be with you.

It all started with a view, a model and a controller…

Back when I started ‘doing MVC’…

  1. Write a *Model* class containing a few bites (no bits, no bytes) of data.
  2. Write a *View* class batching a couple of widgets.
  3. Write a *Controller*. The controller instantiates and refers the *View* and the *Model*.
  4. Let the controller listen to events from the view and the model.
  5. In response to view/model events, let the controller update the view and modify the model.

Really doing it

If you really are doing MVC the wild way  (or maybe just writing a moderately sizable app) then you’ll need to go a little further:

  • Writing components. For lack of a better word, I refer to ‘mini-apps’ – bunches of MVC classes that work together to realize a feature in a larger app – as ‘components’. Components needn’t be hard to write, and in theory the ‘scaling up’ question needn’t interact with whatever well-formed approach to MVC we’re using (why? because either way the secret is to keep components decoupled. A ‘keep the bags of crap small enough’ idea that I’ve been pushing forward in my posts about F*).
  • Writing ‘models’. I hope you’re not trying to get your way around TableModel, ListModel and other API induced models, and how they should fit in our MVC collection. Because I am, and I wish to be enlightened.
  • Keeping it small and simple. We don’t want our apps to grow any bigger or more complex than they ought to be. Or do we? Unfortunately trying to keep front ends manageably small is a good way to make them unbearably intricate. At the other end of the scale, fixing the same bugs in countless apps ‘prototyped one another’ resurrects Taylorism.

Before things go wrong

Before things get really nasty, here are the tell-tal signs that might finally help us understand what to do with our MVC naturals.

Getting confused and arguing over it

When I started with my 3D engine, I considered that 3D assets were view. Unfortunately, 3D geometry affects game logic. Sometimes also, 3D assets are adequately used to hold data that (I think) ought belong to the model. Some guys quickly judge this kind of situation and get over it. Your colleagues from the front end get into heated discussions about what goes in the M or V or C. You think it’s a waste of time and you’re perfectly right. If there’s no hard business/real world constraint driving towards a correct answer, it’s like naming a baby can get. Oh my.

What is the controller?

I felt immensely relieved when I heard a colleague say this for the first time. Here’s why. Because every so often, the view is specifically written for the model. Most of us understand why you would want to change/write a different view for the same model. Many of us acknowledge that views are disposable app-fodder. Views are ad-hoc. In short, the view root can listen to widget events and effect model changes directly. So why do we need a controller?

Why we cannot write clean components.

Because the UI is bullshit, or the UI is bullshit.

If you give the UI work to a UI designer, they’ll think about usability. They’ll make a UI that has weird shortcuts. The component hierarchy won’t match the model’s functional hierarchy. In short, the UI won’t map your model closely. If it’s a good UI, it will even get literally (legitimately) intricate. Meaning that the hierarchy will be unclear enough that you won’t be able to ‘just take a component and drop it into another app’. Business apps should be more tractable. That’s because…

Usability is irrational bullshit. Unfortunately business apps also are bullshit. They are boring, slow to use and un-fun. That’s why people are paid to use them.

What are view states?

We’re writing an app allowing people to choose shirts. Shirts come in different colors. The UI designer suggests that the ‘add’ buttons in the shopping cart should match the shirt colors. What’s going on?

This is just a silly (and actually, redemptory – the ‘color state’ is blissfully captured by the natural data model) version of the model-view/view-model dilemma. View has states that aren’t perceived to partake the model. However such states can be linked to the model, and more often than not, these states also persist in real apps (as in, real-world apps persist their UI states). Here are three perspectives on the situation:

  1. If it’s a variable, it’s a state. State belongs to the model. My first tech lead frustrated me a little by implying this is obvious. Is it obviously right to conflate the data, or (as he suggested) whatever is the data model (4th tier alarm!) with cosmetic stuff like font size, colors and alignments?
  2. Add view.model, view.controller, view.view to your view package. Call a cat a cat. While this may seem logical, it needn’t take us very far. If we’re not serious about our view, that’s OK. Otherwise we’re reducing separability in unpredictable ways. Most apps do MVC just to keep things neat and clean. If separability has business strings attached, there will be a price.
  3. Don’t confuse data and model. More specifically, don’t confuse the view model and the data model. That’s a weird avatar of (1) and I don’t want to be sure what to make of it.

Is my controller holding state?

Yes. That’s a prime rule for a well formed MVC instance (an app written using MVC). The controller should hold no state. I would be so very delighted to announce that controllers cannot declare fields. Err, I’m afraid we started off declaring a view and a model field under our Control class. I’m sure you don’t think we are doomed yet.

But it’s not over. Now we’re ready to add ‘control states’. We’re also ready to write state machines. Yuk, see below.

I know you know. Call a rabbit a rabbit. These are states which belong to the control layer. Let’s add a control.model package. Unleash the Geek Inside.

Hyper-hacktivity

MVC naturals are incredibly hackable. That’s one of the things that got me writing tonight. I’ve been hacking an MVC instance mercilessly for 10 hours nigh. It’s very neat, because I spent three days this week trying to ‘rehabilitate’ the same app. Now I feel ready to start over. It’s good to be able to sort things out and release on time. But if I save one day every time I waste three, how good can it get?

Thinking about it, here’s one reason why MVC naturals are so hackable: statemessness.

  • Your GUI library is object oriented. It’s full of weeny controls that duplicate model state.
  • Your model is the primary state-holder. Surely the model knows (nearly) everything.
  • Your controller wouldn’t be so easy to write if you didn’t buffer a little state here and there.

Hackable. No matter where we’re writing code inside an MVC application, no state is ever far from us. Maybe not quite the right state, yet, in a first (and durably misleading) approximation, just about right.

Don’t hide behind your framework

MVC frameworks do that. If you look into their implementations, you’ll find that rules get broken. Basic rules. I see three solutions:

  1. Rules are for n00bs. The powerful magic behind singletons, static, event broadcasters and (while you’re at it) the C pre-processor is trickery that everyday coders should be interfaced with / insulated from, not exposed to.
  2. MVC frameworks are bad.
  3. The rules are bad.

Unit-testable or clear and concise?

I’ve been trying to put some of my latest MVC natural under unit test. Since I’ve been trying, and trying often leads me to explicit stuff I’d rather, for the sake of clarity, didn’t show up, I feel that natural MVC is biased against unit tests.

Inter-act

STOP.

By now, if you’re still reading you should probably go for a coffee break. Trust me. After all this article is just food for thought, not very thoughts.

Nice to see you back. Now that I’ve dusted around a little of the dust in the dust-bag, let’s muse a while into the muddle-dy swamp.

How things go wrong…

The shortest path is never the best path

Here are a few examples:

  1. It’s faster to emulate a button click than to separate action from reaction. The play button starts playback. The play menu item also starts playback. I want exactly the same thing to happen when I press the play menu item and when I press the play button. Sooo… I hack something up to pretend the play button was pressed when I hit the play menu item.
  2. It’s nearly always faster to pre-empt view updates. The controller knows what the view wants to do. The controller knows what the model will be like after we change it. In fact, the controller needn’t read the model, because the view reflects the model state faithfully enough… especially when we get started off and our view/model mapping is simple. I remember decomposing roundabout VCMCV routes using powerfully soporific sequence diagrams for the sake of principled colleagues. I also remember breaking my own rules and trying to explain what kind of risk is involved using whatever shortcuts.
    Now that I think about it…. (gasp) we don’t even need to update the model every time. That is, until auto-save stores a half-baked image of our data.
    Back to the original point: do we need a controller, or a model? Do we even need classes? Why not just use punchcards?
  3. Re-writing it is faster than just using it. MVC naturals tend to generate hierarchies. These hierarchies, more often than not, connect on an ad-hoc basis. Lay it out in UML:

    “it is 7:50 pm and you want to go home. You are ‘here’. The function you need is 10 clicks away on the class diagram and 3 steps are blocked because the hierarchy doesn’t back-wire. Re-write? Use a singleton? Introduce dependencies over 10 unrelated classes? Expose your lack of style and insight (russian doll message passing)?”

My button back-fired

Here’s a list widget. The user selects an item. A view event fires. The model updates.

Here’s a list. The list selection gets remotely updated. A model event fires. The list widget gets updated. A view event fires. The model gets updated. A model event fires…

Why is this happening all the time?

The inheritance delusion

It’s a text-book truth that inheritance isn’t an implementation level commodity. That’s probably why inheritance is hailed as a technique improving reusability and concision.

I took a controller this week; abstracted a base class off it. That simplified my coding four more, similar controllers. How are they similar? Well, they kind of work the same as the first one.

Truth is, I did it to save time and clarity. I’ve also seen what happens when we keep at it. Controller code isn’t especially concise. App controllers are meaningless idiosyncratic beasties anyway. Not your rationally bound mammal to mouse to cow inheritance anyway. If an app controller is a meaningless idiosyncratic beastie, what would an abstract app controller be? Or its grand-grandson?

Before you know it you’re abusing the decorator pattern. Classes implement functions for no reason, and nobody can understand a derived class until they’ve mastered five ancestors up the chain.

MVC naturals make it easy to use inheritance in this way. Or is it just inheritance that’s easier than delegation?

Your controllers are cursed down to the 13th generation. Amen.

The state machine delusion

Controller states are non committal. Unlike data-grave entries. Unlike serializable model data. Unlike view states, which at least, get rendered. Add a little flag here. Add an enum there. It doesn’t matter if two controller state-holders describe overlapping state. It can only hurt a little.

Here we are. It’s ‘kind of like a state machine’ just less complex and more complicated at the same time. However, all we need to keep ahead of it is a really good debugger. Well, I’d rather go and sink my own boat.

Until next time

It’s nothing like I’m done. I’m expecting staffing this experiment. As I stated at the beginning, there are many reasons not to go heavyweight. So I still need to find a way to get us sitting atop Pandora’s box. If there’s a way little bits of code mightn’t spiral out of control, looking for it is helping out, not brandishing glossy patterns no teenage coder would bother with.

Once again I’m about to do the wrong thing – forgo my assumption that stumbling steps are enlightening and not writing this post. I’ve just completed writing a unit test for a foo():Void haXe function with no flow control to its name. More about this another time.

Bear in mind, this article isn’t about what is or isn’t worth testing. My first step into TFD consists in having a fair go at writing tests before I write the code, without breaking my usual design flow – correcting my design flow is OK, if that’s what it amounts to. Correcting, yes – breaking, no.

Can we test the main() method? Do we want to?

I’m taking over a colleague’s work, now I’m sniffing the Main class and thinking hell, what shall I do with it. Test? Well yea, I should test it first. Since there are not unit tests for this project yet, I might as well consider it to be legacy code.

My colleague did something that I tend not to do – they just use Main.main() to instantiate a singleton. I guess it should really be a singleton but the point is, they escaped the static logic behind main. So I’ll follow in their steps and instead of testing main(), I should probably test whatever gets instantiated by main.

Unfortunately, as a good initializer does, mine mostly invokes other initializers. Essentially a constructor is a static function. So yea I could pass an array of  classes and instantiate them by reflection, but I don’t want to do that. Too much trouble.

I had the neat idea to just call the constructor to make sure it works, but that’s not a unit test – that’s actually testing the whole f*** thing. Too integrated.

Why I don’t feel like testing main() and constructors anyway?

I’d like to test how my code changes the software system I’m building. Although I’ll come back to this later and discuss, a function that doesn’t return value isn’t making local changes, so from this point of view there’s nothing to test inside the unit.

So what shall I do?

Flowing with TFD?

Here’s my problem with test first development right now. I need a method that flows. If it flows slowly, fine, but right now my flow is frozen. Let’s get flowing and try this…

  • I’ll always write a test for each function. That’s easier than  asking everytime whether to write a test.
  • If I can’t test the function, at least, I’ll document the test function with my design intention for the non-test function – that’s because I need somewhere to write my design intention. Then I’ll past this doc in the function’s code body so I can use it to write the actual code (that’s because my STM is very limited)

I’d like to still call these functions to make sure they don’t fail. That wouldn’t be a unit test, however. Oh my…

Working notes

No time for a conclusion today – just a few ideas

  • In absolute, I’d really like to write my tests first. This is why I’d prefer to write an ‘untestedConstructor’ function rather than no function at all in the test class. untestedConstructor() may seem horribly pedant, but I like it. This way you know I haven’t tested this by looking at the tests. Also, I can move design comments to the test class – if the tests are gonna stand for documentation, I think that’s alright.
  • So far, I only note I find it difficult to test root initializers. The type dependencies involved make it appear so difficult as to be counter productive. However, even with a statically typed language such as C++, doing this is likely not impossible (just map another .c file to the same .h file?).
  • One view about testing is that only state transitions matter. ‘unit’ testing consists in testing a class. Applying this, we could say that a method that causes no local change needn’t be tested.
  • Surely, a controller doesn’t manipulate it’s own state. A controller should hold no state. Does it mean a controller shouldn’t be tested? Oh my, controllers are were the case logic of a program resides… Maybe a productive idea – how about if we extract the case logic, so that the case decision can be returned from a function as a value. My counter-intuitive bet is that such functions should then be private – unfortunately, I heard over and over that a good unit test focuses on the public interface of a class. More contradiction. Or maybe we should just distinguish ‘do’ classes from ‘case’ classes; then we’ll have a good reason to make ‘case logic’ methods public.
  • Another view about testing might be that it is the behaviour of a class we are trying to test. Even if a class doesn’t manipulate its own state, we still want to assert whether the changes it makes to the outside world are as intended. TDD programmers that use mock objects liberally seem to be on this side.

Enough musings for today.

A few months ago, I put quite a bit of work into understanding an MVC framework called PureMVC and getting a team up to speed using it.

I didn’t like the PureMVC thing too much because it’s so heavy. In this post I described a strategy for doing MVC with your own, home baked MVC pattern instance.

Do you bake MVC? Here’s a way to get your three layer cake from the designer’s pencil to the forge.

Ideal means this stuff is paperwork. I haven’t really tried it – but frankly speaking it’s mostly a simplification of what goes on in PureMVC, with a little bit of salt. Bon Appetit

An ideal MVC instance

In this model, the software is structured around three broad categories instantiated as packages.

  • View classes. View classes use some GUI API such as flash, java swing, OpenGL or the like. View classes also hold view specific data(1). When the user performs an action, such as clicking a button, the view handles this action by firing an event (see below).
  • Model classes. Model classes hold your application data.
  • Controller commands. A controller command is a command that changes the way the application reacts to events from the model and view, rather than changing the view and model directly. Typically, a controller command does nothing except register callbacks causing such or such event to trigger such or such command. Additionally…
    • Model actions are commands that change the model in some way. These commands operate only on the model. When the model has changed in some way, and we want to update the UI, the model needs to fire an event
    • The UI is controlled by UI update commands – commands that change the UI in some way. These commands operate only on the UI.

More about events

In the above model, note that neither view or model ever handles an event directly. This is not to avoid type dependencies, but to avoid conceptual dependencies:

  • Maybe an animation just finished in the view. If the model handles this event, the model is doing something based on the fact that an animation is complete. Even though the actual view type is hidden from the model, the model now requires making a big assumption about the view to operate.
  • Maybe the model changed in such or such way. It may be that this causes just one change in the view, but it maybe that the view needs to update in many ways, or it may be that we are using a general purpose view component that is used in combination with concurrent models.

Also note that a view or model doesn’t directly instantiate commands. This is consistent with the fact that the view shouldn’t know about the model (and vice versa). There are many cases in which it may be convenient and safe to allow the view to know about the model; however, this is a simplification of the ideal instance described here, so to stick to the general rule, the view should generate a SEND_MAIL event, even though it is obvious that this event maps to the SendMail command.

Lightweight versus heavyweight events

When writing your application, you will often need to send quite a bit of data along with an event – for example if a view needs to update a table, you need to send whatever needs to be updated along with your event, not just a message.

In this case, you have two choices:

  1. Use untyped event data. This is in some ways unsafe (more parsing/relying on implicit data formats), but it saves the trouble of defining additional structs or classes to store event data.
  2. Use typed event data. It is commendable to include event definition in a subpackage, e.g model.event, view.event

More about the event dispatcher

To make the above work, you need a kind of event dispatcher that can broadcast events to receivers. All your view/model classes should be able to access the dispatcher so that they can trigger events. Your control commands should be able to access the dispatcher so they can register callbacks.

It may be a good idea to expose the dispatcher to the view/model and the controller commands using a different interface. We don’t want view classes and model classes to modify our event to command bindings accidentally

ViewManager and ModelManager

When a command is instantiated, it needs to get hold of the data that it wants to manipulate. A simple way to allow this is to define singleton ViewManager and ModelManager. So for example the ViewManager contains all the views, and ModelManager is the root of the model’s data hierarchy.

How does the application start?

You may have noticed that it’s the job of command to specify bindings from events to commands. This leads to one of those chicken and egg problems – which one started it all? an event or a command. This doesn’t really matter, but here are two solutions anyway:

  1. Use a Main command. Then your framework needs some kind of bootstrap class that you call start() on.
  2. Invoke a command to bootstrap your application.

How to use the above while enforcing feature driven separation

It may be a good idea to combine your MVC pattern with some degree of feature driven separation (I wrote a lot about the F* Meta-Pattern and feature driven separation somewhere else). Here’s how a simple, non adventurous way to do it:

  • Break down your controller package into subpackages – one package per feature.
  • Use a controller command to register all the callbacks and commands related to each given feature. This is the ‘feature root’
  • Bundle additional commands required to realize your feature in the same sub-package as the feature root.

There are pros and contras to the above approach, compared to a typical F* instance:

  • PRO 1: In many existing workflows, we use WYSIWYG UI builders to generate our views. The original F* pattern typically requires moving back UI building into the code, because you need to be able to add widgets as part of feature code – in F*, your ‘send mail’ feature will require you to add the send mail button to a toolbar – that’s the price to pay if you want the UI to be correct once you have the removed the mail feature.
    This is further reflected in the way UI designers work. In cool applications, the UI is typically very integrated. Removing a function often means redesign in this case.
  • PRO 2: In many applications, most features rely on a core data model – i.e most of the data is used by several features. F* fragments your data model across features and leaves the generation of the core model as a refactoring exercise. There are many cases in which designing the data model as a self contained entity, adding stuff to it over time, maybe more efficient.
  • CON: F* allows you to delete a feature by deleting all related classes. With the above strategy, deleting the feature deletes only application functionality, not widgets and model data related to such functionality.

How far can we go into the writing of an application without losing momentum?

As an application becomes richer, it typically becomes more complex. There are two aspects to this:

  • Logical complexity increases as a result of new functionality binding to existing functionality.
  • Physical complexity increases as a result of increased application size.

The result of increasing complexity is that developers find it increasingly challenging to add new features to an application. This complexity manifests itself in two ways:

  1. Your workspace is increasingly cluttered with irrelevant entities – entities that do not contribute to the feature you are developing
  2. Your code is increasingly dependant on existing elements of functionality.

Very large applications are typically broken down into modules. Modules reduce logical complexity by providing narrowing interfaces; physical complexity is reduced by keeping all the code for a given module separate from the code for other modules.

Feature architectures enforce micro-modularity:

  • Each feature typically maps a single value increment or story.
  • Features are abstracted from each other using channeled notifications.

Why design feature architectures?

Feature architectures are derived from story driven development. In agile, story driven development, developers collaborate towards the development of a given story cutting across the layers of a selected framework. Agile ensures that developers deliver value faster; in suitable contexts (assuming that value can be delivered incrementally), this maximises profitability while reducing the risk to produce large amounts of unused functionality.

Feature architectures take advantage of the separation between source spaces and runtime spaces to allow developing well formed (layered) runtime architectures while limiting linearly growing physical and logical complexity. This allows developers to focus on delivering atomic value increments without incurring mounting familiarization costs and splitting development across framework layers. Also, this may allow fairly large developer teams to collaborate without facing large communication costs.

In a nutshell, feature architectures and micro-modularity target value driven separation. In contrast, existing separation strategies and meta-patterns provide abstract roles that can be re-instantiated in a variety of contexts (the MVC meta-pattern is an example). This affords industry endorsement for high level design solutions. Beyond, classic separation models emphasize a component drive approach. While this means that component cores can be developed in parallel, this may result in glossing over communication interfaces between components.

Layered, component oriented architectures emphasize potential and structural integrity and are more suitable for long term investments and library development. Feature architectures emphasize value increments and may be ideal for writing application front ends:

  • Reusable data and view components are already available
  • Applications are feature rich, yet do not involve much complex code.
  • Value increments typically involve cutting across layered architectures.

Working using a feature architecture

Feature architectures require developers to package features separately. Each feature is developed as an integrated micro-module – if you are writing an application, a feature will probably bundle view, model and controller functionality.

  1. Each developer or pair are responsible for designing and implementing a feature derived from a user story.
  2. The core functionality involved in developing a feature is developed independently from other features.
  3. The source code related to a given feature is bundled within a separate package.
  4. Developers integrate their feature by implementing handlers for channeled notifications.
  5. Developers expose required resources by providing external notifications.
  6. All source code for a given feature may be removed without causing the application to break at compile time.

Mmh… this may not be the best introduction to feature architectures I could write. I’ll try to improve on that and will also provide an application template very soon.

In agile development, the emphasis is on delivering business value incrementally. While this explicits features within software cycle management, it may also reduce the developers’ visibility over software architecture; this may part in explain why agile methods rely heavily on refactoring.

In contrast, classic development approaches emphasize planning and upfront design. While this may promote architectural integrity, it has been largely demonstrated that  this reduces both customer satisfaction and software profitability, typically resulting in a large amount of unused functionality.
When debugging and processing change requests, development teams naturally adopt a feature oriented approach; this is because bugs and change requests are normally raised by end users.

Overall, software features, whether implicit or explicit to the development cycle as agile stories or bugs, remain largely implicit to code-bases because the high level structure of software applications follows a technical orientation – a paramount example in front end development being the unavoidable Model View Controller meta-pattern. Features typically cut across layered architectures. For agile programmers and maintenance teams, completing stories, fixing bugs and resolving change requests requires juggling between application layers. For traditional teams, reduced visibility over application features will result in a higher number of bugs and decreased customer satisfaction.

I define Feature Programming as a set of methods designed to reduce the cost of software development by revealing features within source code. This is mainly achieved in two ways:

  • Feature Annotations using domain semantics allow software architects to retain a layered architecture while increasing feature visibility.
  • Feature Architectures emphasize feature separation over layering when deciding the high level structure of an application.

Both approaches are expected to reduce costs in front end development. While feature annotations provides non invasive, lightweight techniques for teams that want to reduce liabilities in the software cycle, Feature architectures may be very suitable for decentralized and open source application projects and further afford the creation of reusable value increments.

In this article, I cover feature annotations; later I will cover feature architectures in another article and will also demonstrate a small framework guiding the development of feature centric front ends while affording elements of layering using a suitable interpretation of the MVC meta-pattern – stay posted!

Feature Annotations

Annotating features simply requires a fairly disciplined approach to tracing code. Feature annotations can be applied either during development or retrospectively, as a scaffolding technique used to reduce the cost of maintaining legacy code.

Feature annotations requires the following:

  1. One or several feature classes define static functions expressing application features. Such feature traces must be easy to spot and suitable for automated discovery (in Java or ActionScript, you may use $ as a prefix).
  2. Each function in a feature class encapsulates a trace statement. Traces may be logged, output to a console or even displayed in an application specific debug window.
  3. Semantics for feature functions are typically provided either as story names or itemized requirements.
  4. All code that relates to a specific feature must be annotated using trace function invocations (‘trace annotations’). Within an agile process, a developer writing a story will tag their code, and otherwise contributing code, using trace annotations (for each class involved in the developed story, at least one function or constructor should be annotated).
  5. It is important that feature traces can be filtered easily either at runtime or at compile time (commenting out unwanted traces may be sufficient in simple cases).

Feature annotations constitute a non invasive technique. Adding feature annotations cannot break existing code and doesn’t require re-thinking your approach to software architecture. Developers working on agile stories need not be concerned with selecting trace annotations as the same annotation semantics are used over and over during story development.

In spite of this simplicity, feature modeling provides several benefits that will help in drastically increasing a development team’s reactivity to change requests while increasing software maintainability:

  1. If you are doing code reviews, feature annotations reveal and delimit the code related to a given feature and afford validating the code from the point of effectiveness. Classical code reviews validate structural integrity, glossing over functionality scattered across application layers.
  2. New starters observe feature traces at runtime and isolate features in the source; this complements a developer’s understanding of packaging and structure; developers also appreciate the software’s actual uses by reviewing feature classes. This results in decreased learning curves and reinforced consistency across the code-base given multiplied reuse opportunities.
  3. Maintenance teams benefit orderly, channeled traces mapping business logic using domain language. Observing channeled traces and isolating defective features can save hours spent learning control flow and discovering all scattered elements potentially involved in a defect.
  4. Liabilities associated with reuse are reduced given that concurrent, co-located traces provide tell-tale signs of reuse. A developer targeting a given code fragment will be able to determine which elements of functionality are affected, thereby correctly assessing the risk involved in modifying shared resources and identifying functionality that may require regression testing.