Seems to me that FamilySplit is an additional complexity in the "engine" to make up for a bad design in the subclassing structure of the program being implemented. Am I missing something? It would seem that a refactoring of the class hierarchy could always provide exactly the same storage structure in practice ... and that it would likely lead to a better object design. If I'm understanding the idea, I'd leave it out as an incentive for the program-builders to do the job they should be doing. --RonJeffries
The FamilySplit pattern describes a way to design the instance data after the class hierarchy is designed. by refactoring do you mean splitting one class into two classes with an aggregate relationship? In effect this is what this pattern is doing - and it is a common implementation pattern. However it is not desirable to do this 'refactoring' during the design stage as it makes the resultant design much harder to maintain and understand.
This implies that those things that you implement have a different structure to those identified in design/analysis. Does this make for increased maintenance problems? What about somebody that is new to the project, he picks up the design document and then looks through the code and can not match that with what they have read! -- ScottWalsh
I believe this is a philosophical issue.
Should the OO design be created with the knowledge of the implementation method? Or Not?I take the philosophy that the design should not be overly concerned about the implementation. The design is more maintainable if it is not coupled with a particular implementation method. Ideally, we can take the same design and implement in C (using ObjectBasedProgramming) or C++ (using OOP). Granted we do have a problem reading an OO design and trying to map it onto an OBP implementation. I believe the problem can be solved simply by writing good comments in the code. -- StephenCheng
I'm beginning to think we may have different aims here. Stephen's concept of ObjectBaseProgramming? does not coincide with mine.
In our implementation, we are doing ObjectOrientedProgramming. We're just using C to achieve it. In places we have virtual functions, pure virtual functions, constuctors, and so on. With a little bit of a briefing (say half a day), a C++ literate programmer would have little difficulty in recognising the C++ idioms within our code.
We actually did our full design without heed to implementation language or platform. If a particular problem needed advanced OO features, or a "complex" static class structure, that's what was designed in.
When we came to implementation, we applied a general set of "rules of thumb" for implementing OOP in C. Occasionally, we may have actually thrown away much of a class hierarchy - for example by only implementing the bottom most layer.
But the original class diagrams still relate closely to both the code, and the data structures we use.
Stephen, you seem to be trying to define an entire approach geared specifically towards producing a highly optimised implementation. Your pattern language may be closer to an in-house coding standard.
-- KeithDerrick
The FamilySplit pattern has some benefits when it comes to buffer management. As there will be many instances that require the primary instance data structure, the buffer management for the primary instance data structure can be optimized to reduce waste. The secondary data structures (especially those used less frequently) can be managed with higher waste without lowering the overall efficiency too much.
I personally don't like this pattern too much. I always go for the FamilyFusion pattern whereever possible.
-- StephenCheng
After further looking around in this thread of ideas, What has not come out to me are the following:
In what kind of application might this whole thing need to be done? Not that it isn't fun ... I'm just wondering what environment would really need to do this.
The examples are in C, unless I miss my guess. That would make sense, since C is pretty ubiquitous. However, relating to FamilySplit and FamilyFusion, the concern of multiple structs makes me wonder the following:
Instead of merging/splitting the structs, why not just have each "method" implementation cast the struct to what it thinks it should be? (Or are you winding up with the "same" instance variable at different offsets in the different structs? I'll have to go back and look at that...)
The pattern for what you describe currently has the methods called with a void* argument, which is then cast internally to the correct type. We have not got to that discussion yet, but the more sensible approach is for the method to accept a pointer of the correct type in the first place, and it is the point at which the function is called where the casting take place. This also makes for more informative code, i.e. does it really make sense that I am casting this type so that this function will accept it -- ScottWalsh
Instead of making the storage management function deal with the different structs, why not abstract it one level further down, to sized arrays of bytes, and do all the allocation at that level, casting to the struct as needed?