The diagram to the left represents a very simple quote. Each quote contains multiple lines of business, lines of business contain products. Easy enough. If the quote header is in a state which renders it read-only, however, none of its children should be editable either.
Faced with the challenge of making this work yesterday, I am ashamed to say I almost gave up. This object model is easy to understand and manipulate, but when mapping to a database the object model begins to crumble. This was exacerbated by some very early design decisions in our back-end library. Our design revolved heavily around run-time modifications. If a vested party asked for a new field on a screen, we wanted the ability to add the field at run-time. We used business objects to implement business rules. These objects represent tables and inherit from a single source. At runtime we can change the BO for a selected table using reflection.
This approach uses the tenets of object oriented programming in working with and representing tables of information. It does not allow for modeling of objects as represented in the figure above. Everything was peachy until I got stuck between large releases. The release version of the configuration file would continue to get out of sync with the development version. I switched the model a bit, and now runtime changes can be saved...but they must be compiled into the main executable. I lost my ability for runtime modification, but I still didn't have to design 80+ individual screens at design time. I can drag fields around at runtime and save my changes.
Back to my problem from yesterday. In order to determine the state of a quote header at the product level, I would have to find two queries in the configuration file, execute them, and then use the results to determine if the quote was editable. What a pain. Worse, if someone unwittingly changed the configuration, this subtle piece of code would stop working. I almost threw my hands up in desperation. Perhaps I would make it impossible to drill into a quote that was read-only.
Then I started to realize some things. I'm the coder, not the library of functions. Runtime design is high maintenance for the reasons I just mentioned-there are very few compile time sanity checks. Why not use application resources to associate business functions with stored procedure names and descriptions, and then create a stored procedure executor? Then I could have the compile time checking I need, and the flexibility I crave! I did it, it works, and it works well. More importantly though...I realized that version three of our library needs to be designed around a real object mode, not a "sort of" object model. The very reason I didn't like my own library is the very reason I don't like other libraries: lack of flexibility. Finally, in order to make my new vision work...I'm going to need to change my coding habits. I've been breaking the rule of designing to interfaces instead of classes. Now I've got a bunch of display classes that only work with SetTableBO instead of something more flexible like iSetBindable.