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:
By induction, here is what happens:
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):
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.