You could have just one class, and put everything in it. Or you could move the attributes of the class out to be classes in their own right, and have links between them. Of course, if you want to store data about the links, you could turn them into classes, with links to each of the places they linked to. And their attributes could be turned into classes... etc. ad nauseum. That is what I call 'unfolding the classes. --AlistairCockburn
Sometimes it is good to unfold the classes a bit. Usually it is not good to unfold them too far. What is the right amount of unfolding to do? Different amounts at different times. When showing the "domain model" to people, it is useful to fold things up some. AssociationClass is an example of unfolding a link, either to store data about the link, or to make associative access or control the number of pointers being used.
I've actually been thinking about something like that. Something more extreme than ExtremeProgramming. Start with an empty class that represents the system and everything else factors out of it, or whatever it is broken into over time. Since so many refactorings have inverses, you could fold everything back up into that class, but it wouldn't be recommended. The controversial part is starting with the system as an object.
It seems that with refactoring, you can get anywhere from anyplace. -- MichaelFeathers
It's not overly extreme at all. Reflect on "Do it in an Inspector", "No, Do it in a Workspace", "No, do it in an Object", on armaties. --RonJeffries
I once saw a domain model designed by data modelers, which had been unfolded to its logical extreme. Anything that could possibly be date-stamped had been unfolded out. Hundreds of itty-bitty classes. The OO programmers who showed up claimed it was not an "OO" model. We used the 'unfolding' notion to show both sides the extremes and the gradient, and let them get started on the discussion of how much unfolding was right for which point of use on this particular project. Since you can get from anywhere to anywhere, you have to have an idea of which direction to go in and when to stop. --Alistair
This leads to the interesting question: how much unfolding is appropriate? You have my criteria on AclassIsNothingButaCyclicDependency, but of course this is far from the only way to do it. XP's "simplest system" criterion is an excellent prescription too, but it's not clear whether a "foldish" or "unfoldish" decomposition is simpler ... or is it? --PeterMerel
Perhaps, Peter, you'd present some examples of two decompositions of some problem (in some standard programming language), and we'll discuss simplicity in that light? It'd be hard work for you, but we might learn something. --rj
As I mentioned on ACINBACD, I apply cycle abstraction, for which there is an example on that page, as well as OnceAndOnlyOnce, for which you have ample examples of course.
Above, I'm asking a question about whether XP, with which you have vastly more expertise than I, regards a more or a less folded decomposition as simpler. Now are you asking for an example of the foldedness quality that Alistair describes in order to illustrate your thoughts about XP? Or are you trying to compare what you do with what I do? If the latter, you have my technique and an example; apply it yourself and see how it works. If the former, I hope and believe you can make a much better job of that than a novice like me. --PeterMerel
Perhaps the construction "Is a more or less folded decomposition simpler?" is not a question, even though it appears to have question format.
Which diagram on ACINBACD is simpler? One diagram has three nodes and three connections, one has four nodes and four connections. In one diagram, the arrows all go in one direction, nicely round and round, in the other, they go both directions, back and forth, willy-nilly. Therefore the first diagram is simpler by any criterion I can think of.
Since you seem to think that the four by four diagram is simpler, or at least better, I conclude that whatever you're talking about isn't in the diagram. It must be in something not yet said.
What is interesting (at least to me) is which way the code is simpler. Somone who has a clue what "foldish" is could, if they chose, produce two examples of actual code, doing the same thing the same way except for foldishness. Then we could talk about which is simpler. We might learn something. OTOH, we might not. My current hypothesis is that ACINBACD and unfolding are ideas in the hatching stage. For sure, I don't understand either one. You're saying what you felt, not what the code was. Show the code, please. --RonJeffries
I don't think the 4x4 diagram is simpler. I think it's more maintainable. I think this because I had a most disagreeable experience back in days before I worried about cycles. I'd built an authoring system for some folk who were spruiking for GUI work back when M$ didn't rule that roost. Yes, I know, it seems like I must be an ancient Greek or Etruscan or something.
So what I found was that (a) building OOish GUIs is both powerful and fun especially the first time you invent patterns for yourself like composite and prototype, and (b) maintaining OOish GUIs is an incredible pain because every time you change one thing you have to change dozens of others, and you have no idea how many or how long it's going to take.
What soured me particularly was that the system slapped itself together extremely rapidly - from conception to delivery in 4 weeks - but that each change I wanted to make happened extremely slowly. Just adding poly-lines, even given a line class, for example, took the better part of a week. And almost all that time was tail-chasing - following refactorings around and around cycles to try to make things simpler.
When I learned the CycleAbstractionPattern (I've since used and taught it many more than the requisite 3 times), I realized that this was what was wrong with what I'd done. Abstracting the cycles was like untangling a mess of twine. Suddenly I could refactor easily, without having to trace changes throughout the system. I could fish instead of wrestling with snarls. A change to a base affected its derived classes, sure, and 2-cycles could communicate changes to each other, but that work was tightly scoped and easy to accomplish.
So the code was easier to change. But another effect rapidly became evident to me. The code was easier to extend. Because the classes implicit in cycles were made explicit, it was a lot easier to add new classes without having to add their corresponding collaborators around the cycle. And it was a lot easier to see where to do extensions - there was always an obvious class to use.
So the code isn't simpler, but it's easier to change and extend - ergo, easier to maintain. This, I suspect, is what I haven't said that you wanted to hear. Let me know.
It's important to stress that this is only one technique, not a panacea. Without OOAO, it leads straight to ravioli. There are certainly other ways of approaching this too, and I'd like to hear about them on this page as well. --PeterMerel
Peter, teach me the pattern. I'm a programmer, not a diagrammer. Your comments are about the code, which you never show. Please show me two programs, differing only by which diagram they reflect. Then maybe I'll get it. Or don't, that's OK too. I don't have to get everything. --r
Peter- Could you make a little ArchitecturePrototype? of the two diagrams, but including code? When you say "Integer uses Person to record themself", I don't understand what you mean. I'm sorry to be so dense. --KentBeck
Or just elaborate CycleAbstractionPattern with more code?
(avoiding the XP thread) Hmm... ClassUnfolding sounds like CodeNormalization (or ClassNormalization?) to me. I've been thinking about this but don't have a coherent story yet. If I had a story, it would go something like this:
You start with a UniversalClass? --- perhaps a facade for the entire application; perhaps the list of all the use cases, or perhaps you've written all the unit tests. Then, you design the internal structure by normalising the UniversalClass?. Take one message/use_case/test/story/facade_method, analyse the existing structure, refactor, repeat. At the end you should get something which is arguably behaviourally equivalent to the UniversalClass? but with a much nicer internal structure. --JamesNoble
Normalization sounds like it is either an endpoint or an optimal point. Of course, DrCodd and Date made 1st, 2nd, 3rd, 4th, 5th normal forms. Guess they could have gone on. Folding does have an end point - one object. But Unfolding can go on indefinitely, truly ad naseum. Every attribute of any object can be unfolded or taken out to become its own object, connected by a link. Eventually you run out of attributes to take out. But every link between two objects can be reified, turned into its own object, with links to both sides. And this you can repeat forever. There is a point when you just stop, because you can't think of anything to store about the new object.
This would have been totally academic, if I hadn't seen a model that had been unfolded to its logical conclusion. Every change to the state of the system was date-stamped, so there was an object creation for every attribute change. So every attribute was taken out, and every link to every attribute reified, and a creation date and obsolescence date associated every one of these attribute or link objects. I can't recall exactly, but I think there were occasions in which they time-stamped the fact that they time-stamped the creation of an attribute object. Certainly you could query the system, "what did I believe on such and such a date?" Amazing, wouldn't you say?
The more general question people have is when to reify an association, or an attribute. That is somewhere in the early stages of the unfolding story. The people I have met who have worked extensively with 3rd or 5th normal forms seem to come up with consistently nice results, but neither they nor I can say how. --AlistairCockburn