Mirror Model Contagion

Overcoming MirrorModel requires modeling the model, rather than modeling the problem instance.

Modeling the model means that one must then use data to construct the application. Thus the overall application becomes a pair: a process that can construct and maintain the application, and the configuration data used by that process. The data typically goes into a database (for robust management) or a pile of XML files (for the PowerOfPlainText - users may edit these). It really doesn't matter where the data is stored unless one wants other cool features irrelevant to this page (like the ability to monitor these for updates and push updates back to them, live, while the application is running...).

This separation has many flexibility advantages. It readily overcomes problems of fragility and rigidity associated with 'pure' OOP approaches.

In this context, I describe a problem I'll call MirrorModelContagion.

MirrorModelContagion is when you need some sort of app-specific feature in an app-specific form. E.g. a particular operation upon opening or clicking a button in form_X. And, instead of making this app-specific feature available to the configuration file, you "hook it together" inside the application language by use of a special constructor-procedure or specialized 'form_X_model' class. This might occur as follows:

At this point, you've established precedence of what to do: you hook application-specific things together inside the application. So, now you need a button to open form_X. Let's say this button is form_S. Here's what you do: Nice pattern we have going, isn't it? But then the problem gets bigger. If form_X had some other buttons... stuff that could have been described by simple scripts, perhaps, even those need to be defined in application! Now the form_X_constructor needs to create some other buttons, describe them (stylistic options and all), build the FunctorObjects, and attach them together. Same goes for form_S.

By induction, here is what happens:

This isn't just a slippery slope. It's a cliff. And it's a real one.

It also happens to be core to Microsoft's "old" model for building applications (before WindowsPresentationFoundation) and it is so well known that programmers often follow this approach without even wondering whether there are better, more flexible, less painful design options. Or perhaps they think of WebApplications as the only other option. Either way, they're stuck in that pitiful mental rut where it seems like things are the way they are because that's how it must be.

It's actually really easy to avoid the problem. Just one small change in the pattern (and you have choices, including):

The latter is considerably more flexible with only a slight increase in initial implementation complexity. And, in addition to scripted events on input, it may naturally be extended to AbstractConstructors for other features, such as video-windows, clocks, fonts, data-sources and subscriptions for PublishSubscribeModel (perhaps DataDistributionService), OpenGl vs. DirectXlibrary rendering, GUI Engine selection, etc. With some care, you'll be darn well set for building some sweet, high-performance, runtime-reconfigurable, persistent, sharable applications. This is the marginally-OOP-mixed-DataflowProgramming design I've been using very successfully in my work, and that's with only having bits and pieces of it implemented. The PluginArchitecture is nice... it allows users to add features, and keeps the application tiny since it only loads what it needs.

Anyhow, upon choosing this alternative solution, you can simply access the desired feature from the 'soft layer' configuration data. You're back to describing models-of-models. The system is flexible again. It's also much less painful to create, since there is much less redundant effort essentially describing 'initial data' in a language designed for describing application components, and it is easy to tweak data then see a change (albeit perhaps after restarting if you don't have end-to-end DataflowProgramming).

MirrorModelContagion is a real problem with a simple fix. It's one of those things professional OOPers tend to learn by reinvention after a decade or so (depending on experience) then forget to tell the younger crowds. Hell, it probably has a different name - I'm one of those idiots that learned it by reinvention, so I'm just making a name up. Or perhaps it's one of those things that just 'click' at some point that tutorials don't help with, like recursion and monads.


MirrorModelContagion is pretty simple to resolve if you are starting with the PolicyInjection/PluginArchitecture/AbstractConstructor approach. But there is another point to consider: if the application is instead starting with the MirrorModel application, and you want to refactor it to be more data-driven, the application will generally require a significant overhaul. You can simplify it a bit by turning some of the forms into 'primitives' (i.e. a "form_X" primitive available to the AbstractConstructor). But significant overhaul is still necessary wherever the forms or form-constructors used to directly reference one another.


This topic would be greatly helped with example code, case studies, etc.

What would you show? The end result? just look at any old Microsoft application where every menu, form, button-command, etc. is hard-coded. That was already mentioned, and hardly needs code here. Would you show each step? Well, that might work, but you'd need to start with a data-driven application that constructs the app against a model-of-model framework (e.g. example code in PolicyInjection), and show how it devolves from there into the MirrorModel if 'app-specific features' are unavailable to the data-driven construction. I cannot imagine that being done in a reasonable amount of space.

If you have a good idea how to use example code to demonstrate MirrorModelContagion, and you have TimeToMakeItShort, then feel free to contribute.


EditText of this page (last edited March 10, 2010) or FindPage with title or text search