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: * you create a FunctorObject for your app-specific on-click action * now, you need to assign this action to a button in form_X, so you create a form_X_constructor that creates the button, creates the FunctorObject, and attaches them together. 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: * You create a FunctorObject for your app-specific form_S button that will call the form_X constructor. * Now, you need to assign this action to a button in form_S, so you create a form_S_constructor that will create the button, create the FunctorObject, and attach them together. 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 FunctorObject''''''s, and attach them together. Same goes for form_S. By induction, here is what happens: * The entire application from form_X back to the 'root' form become a MirrorModel of the requirements. * Then, induction the other direction, the entire application from the root back to the leaves become a MirrorModel of the requirements. * The required support for external data is now eliminated entirely. * The total amount of application embedded into the 'hard layer' is very high, which (according to most) is painful to implement correctly and easy to mess up in bad ways. * The application is now rigid, inflexible, and nearly petrified as far as the user is concerned. 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 WebApplication''''''s 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): * enable access to the app-specific form_X feature from a common scripting language used to describe input-events and other features. E.g. if your allow JavaScript injection to describe user-events, then add a global function to the JavaScript that will call back and execute the necessary behavior to implement the application. (This is, essentially, the approach taken by DOM to add such features as XmlHttpRequest to JavaScript.) * alternatively, provide an AbstractConstructor for FunctorObject''''''s in general such that one can support an arbitrary number of scripting languages (ScriptingLanguageAgnosticSystem). Maybe use PluginArchitecture+AbstractFactory to add make the application extensible (so users can add entirely unanticipated functions to the application). Perhaps use PolicyInjection to select between competing implementations. This approach has a higher initial complexity to implement the frameworks, but also reduces the need to create new applications in the future (just use a new plugin for app-specific operations + new data configuration, and voila - new application). 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 AbstractConstructor''''''s 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.