- personal software technology blog

The Problem: You have a page on a  website whose messaging becomes highly conditional on customer state.  Many messaging and page module nuances are controlled by many aspects of your system state.  For shorthand, let us say this is a "legislation" page (due to the obscure rules and levels of conditionality that is usually embodied by legistative text).

The Natural solution: Most of the time, a legislation page, once written lives on forever.  So the natural basic solution that comes up is to not solve it - add more conditional logic to the page view template, and/or to add more information to the model object(s) backing the page.  This leads to a complex and bloated view for the page.  No one will read your piece of legislation, and no-one will want to amend it.  Amendments may even creep in as included-views.  The idea of amendments leads to the next solution.  But this solution is fine, as long as you do not have to scale.

The Divide-It-and-Hide-it Solution: Break the pages into "components" or "blocks" or "modules" and use a separate include for each module.  Often this leads to development of a model object for each component, or it makes the page conceptually more difficult to visualize as a user-interface-engineer, especially for things like box models, padding and margin sizes  and stretch constraints. To obtain control of the whole, on would need to amalgamate all the legislative text together to maintain a cohesive picture.  Looking and trying to maintain your hidden-included view templates is not feasible; they will only ever be viewed as standalone documents, and bugs about how they break the larger page are just waiting to happen.

Double-Interpreter Solution: Break the pages into "blocks".  Each block has a name.  Build a domain-specific interpreter for your system state: given the state, page and block name, this interpreter retrieves and interprets different snippets of text.  As we are evaluating the outer view template, these blocks have their contents retrieved and interpreted by another text template engine (Velocity, StringTemplate, Freemarker) and expanded into the block's contents.  This way, you are building an domain-specific interpreter within your outer view-tempalte interpreter - hence "double-interpreter" solution.   By using a second interpreter, you achieve these things:

You can then use such a dynamic system to fill in more blocks over time, and make this system participate in smarter page construction schemes (early sending of JS and CSS, smart 'blocks' with SLAs to backend content providers with static fallbacks etc.).  But that's the subject of a different post.