Invalidation Pattern

Jesse Freeman asked for advice:

I’m not a stupid person but prop injection is retarded. I need both vars set before calling apply -> http://twitpic.com/1dz5d9 #Advice

This comes up quite a bit in Mockingbird since hot-swapping dependencies while a game is running is our major differentiator. In practice, it’s often not necessary, but it definitely always make your code more complicated, more fragile and (inevitably) buggier.

If your class has (or ever could have) more than two hot-swappable dependencies, you need a proper invalidation model in order to scale to the dependencies. You can also potentially have a faster object by deferring, and thus aggregating, validations.

Here’s a quick example class I just wrote-up because code speaks louder than words. To keep things conversational, I typed it up in a text editor and haven’t actually tried to compile and run it, which probably means there are typos and stupid mistakes. But the point (and pattern) should hold.

If USE_DEFERRED_VALIDATION is true, validation will not occur immediately when a property changes. Instead, a flag will be set and on the next frame validation will happen. This allows you to set multiple dependencies during one frame and they’ll all be applied at once the next frame.

The classic game engine loop basically embodies this invalidation model with update() (which invalidates) and draw() (which validates).

Tags:

  • jacksondunstan

    This is a really interesting idea! Having a Shape ticker for a bunch of objects sounds pretty painful to me, so perhaps the validation trigger mechanism could be factored out of the class. I could see a lot of classes doing the validation on-demand (an explicit draw() call, as you point out). This would probably be only a minor change to your class, too.

    Lastly, why did you make USE_DEFERRED_VALIDATION protected rather than public? It seems like the user of the object knows how they are going to use it and might like to customize on a per-object basis.

    Thanks for the interesting pattern!

  • troygilbert

    Totally didn't intend this as a base class, hence why i called it a
    pattern. In my code that follows this pattern I already have a global
    tick built-in, and deferred validation is assumed, like a UIComponent.

    Making a base class is tricky because most validation scenarios
    already have more necessary base classes where this pattern should
    just be incorporated.

  • flashartofwar

    This is what I have done before in my components but the situation I am running into revolves around Behavior decorators which don't have A) a visual display or B) access to stage.invalidate (which is a better invalidation method btw). Plus I would not want to run an enterframe loop on several behaviors at once since they would quickly bog down the code. Here is a little more insight into the issue I am having and how it relates to Reflex (the framework I am working in): http://groups.google.com/group/reflex-platform/browse_thread/thread/4ad6f25eb2cdd439

  • flashartofwar

    Oh just realized I jumped to soon on submitting my comment. I get the shape enterframe trick btw for classes that don't have access to enterframe but they still don't have reference to the stage which like I mentioned is a better approach in Flash Player 10+. Also, I am not a big fan of individual instances managing their own enterframe loops. Generally I try to have a master enterframe loop, similar to games, and run through the classes that need to be updated or re-rendered individually as a more top down approach.

  • http://twitter.com/plestik Dario Gieselaar

    I've implemented a similar system for my view components. The basic setup (i'm bad at naming classes)

    - have an UpdateManager listen to Event.ENTER_FRAME, or preferably, Event.RENDER. I haven't tested Event.RENDER properly.
    - every ViewComponent has an UpdatePackage. After the ViewComponent is added to the display list, it sets the order in which it's functions (UpdateFunction) are called, e.g.:

    this.setFunctionPriority(this.getProperties,1);
    this.setFunctionPriority(this.rearrange, 2);
    this.setFunctionPriority(this.draw, 3);

    - when properties are set, mark function to be called at the next opportunity, e.g.:

    public function set width ( value:Number ):void { _width = value; this.updateOnExit(this.rearrange); this.updateOnExit(this.draw); }

    - when updateOnExit is called, the UpdatePackage registers itself with the UpdateManager
    - at Event.ENTER_FRAME (or Event.RENDER), all UpdatePackages are sorted by priority (making sure the viewComponents are updated 'bottom-up').

    Solves a lot of my problems.

  • troygilbert

    Like I said in the above comment, this was intended as just a demo of an invalidation pattern, not as an actual base class or production code. As I explained, in my API I have a central update mechanism not using either ENTER_FRAME or INVALIDATE events, and certainly wouldn't recommend a per-instance-shape, though it's useful in a pinch or one-off class that needs deferred validation.

  • http://www.xtyler.com/ Tyler Wright

    This is a common problem – setting width and height separately but wanting one redraw on the resize.

    The opensource project Reflex exposes a nice utility called RenderEvent which allows you to set up invalidation phases and handles the validation cycle in a very organized manner. It runs phases by priority, validates from the top of the display-list to the bottom (in parent-child depth) or vice versa, and runs on any screen redraw appropriately: enterFrame, render and stage.resize, which ever comes first.

    An invalidation solution can be simple to set up if you work in a bubble, but as soon as your system has any complexity it's invaluable to have a well-structured validation cycle. RenderEvent is able to handle the complexity of Reflex and is a smaller more customizable solution than Flex4's new layout invalidation.

  • jacksondunstan

    I once again weep for the lack of multiple inheritance. :(

    Thanks for clarifying.

  • troygilbert

    Totally didn't intend this as a base class, hence why i called it a pattern. In my code that follows this pattern I already have a global tick built-in, and deferred validation is assumed, like a UIComponent.

    Making a base class is tricky because most validation scenarios already have more necessary base classes where this pattern should just be incorporated.

  • flashartofwar

    This is what I have done before in my components but the situation I am running into revolves around Behavior decorators which don't have A) a visual display or B) access to stage.invalidate (which is a better invalidation method btw). Plus I would not want to run an enterframe loop on several behaviors at once since they would quickly bog down the code. Here is a little more insight into the issue I am having and how it relates to Reflex (the framework I am working in): http://groups.google.com/group/reflex-platform/browse_thread/thread/4ad6f25eb2cdd439

  • flashartofwar

    Oh just realized I jumped to soon on submitting my comment. I get the shape enterframe trick btw for classes that don't have access to enterframe but they still don't have reference to the stage which like I mentioned is a better approach in Flash Player 10+. Also, I am not a big fan of individual instances managing their own enterframe loops. Generally I try to have a master enterframe loop, similar to games, and run through the classes that need to be updated or re-rendered individually as a more top down approach.

  • http://twitter.com/plestik Dario Gieselaar

    I've implemented a similar system for my view components. The basic setup (i'm bad at naming classes)

    - have an UpdateManager listen to Event.ENTER_FRAME, or preferably, Event.RENDER. I haven't tested Event.RENDER properly.
    - every ViewComponent has an UpdatePackage. After the ViewComponent is added to the display list, it sets the order in which it's functions (UpdateFunction) are called, e.g.:

    this.setFunctionPriority(this.getProperties,1);
    this.setFunctionPriority(this.rearrange, 2);
    this.setFunctionPriority(this.draw, 3);

    - when properties are set, mark function to be called at the next opportunity, e.g.:

    public function set width ( value:Number ):void { _width = value; this.updateOnExit(this.rearrange); this.updateOnExit(this.draw); }

    - when updateOnExit is called, the UpdatePackage registers itself with the UpdateManager
    - at Event.ENTER_FRAME (or Event.RENDER), all UpdatePackages are sorted by priority (making sure the viewComponents are updated 'bottom-up').

    Solves a lot of my problems.

  • troygilbert

    Like I said in the above comment, this was intended as just a demo of an invalidation pattern, not as an actual base class or production code. As I explained, in my API I have a central update mechanism not using either ENTER_FRAME or INVALIDATE events, and certainly wouldn't recommend a per-instance-shape, though it's useful in a pinch or one-off class that needs deferred validation.

  • http://www.xtyler.com/ Tyler Wright

    This is a common problem – setting width and height separately but wanting one redraw on the resize.

    The opensource project Reflex exposes a nice utility called RenderEvent which allows you to set up invalidation phases and handles the validation cycle in a very organized manner. It runs phases by priority, validates from the top of the display-list to the bottom (in parent-child depth) or vice versa, and runs on any screen redraw appropriately: enterFrame, render and stage.resize, which ever comes first.

    An invalidation solution can be simple to set up if you work in a bubble, but as soon as your system has any complexity it's invaluable to have a well-structured validation cycle. RenderEvent is able to handle the complexity of Reflex and is a smaller more customizable solution than Flex4's new layout invalidation.

  • jacksondunstan

    I once again weep for the lack of multiple inheritance. :(

    Thanks for clarifying.