Popularity Cycle of Graphical Tools
We have observed an interesting cycle. Programmers write programs that grow bigger and more complex until their own authors cannot debug or modify them safely. Graphical tools become popular to manage the complexity, but then a new programming language or new programming paradigm is invented, programmers return to the more compact textual programming, and a new cycle begins.
In "The Inevitable Cycle: Graphical Tools and Programming Paradigms" (IEEE Computer, August 2007; www.codefarms.com/OOPSLA07/workshop/cycles.doc), we describe three historical cycles:
- Flow charts were used to manage spaghetti logic in the code but were eliminated by structured programming.
- Diagrams of table indices helped to manage Fortran programs but were eliminated by the introduction of C structures and pointers.
- Pointer diagrams representing C data structures were eliminated by the introduction of class libraries.
Software complexity is a serious problem and the prevalent use of graphical tools including UML fits this observation. If this popularity cycle really exists, it implies that the arrival of a new programming technique is imminent and a new paradigm will eliminate or reduce the use of UML class diagrams. The new paradigm would have to include the major improvements that UML gave us:
- Instead of programming with collections, UML uses more general associations.
- Associations and classes are both treated as first-class entities.
There is more to UML than just the UML class diagrams though, and the new paradigm would also have to cover those other areas to provide the same utility as all of UML.
A Matter of Control
Most associations need an iterator class, and these iterators can be implemented in the same style as collection iterators. However, when implementing associations, reusable or not, the question is where to keep the methods, which operate on the association.
The commonly used practice today is to add individual methods to classes where the implementation of the method is easiest or seems natural:
void SourceXtoX:: add(Terminal *t,Net *n); void LinkXtoX::remove(); // USING THE METHODS Block *b; Terminal *t; Net *n; b->blockNets.add(t,n); t->blockNets.remove();
This may look elegant, but it adds to the problem of having parts of the associations scattered throughout the classes and no guidance on where to find them.
The second possibility is to select one class, preferably the "main" or "most important" class of the association, and keep all the methods in it. In the case of ManyToMany, there isn't any clear difference between the Source and Target, which mirror each other. Let's choose the Source:
void SourceXtoX:: add(Terminal *t,Net *n); void SourceXtoX:: remove(Target *t); // USING THE METHODS Block *b; Terminal *t; Net *n; b->blockNets.add(t,n); b->blockNets.remove(t);
This interface is similar to the interface we use for collections today.
Alternatively, for each association, we introduce a new class just to keep the association methods (Listing Three, available online; see "Resource Center," page 5). This association control class (ACC) is a completely different concept from the UML association class (UAC) commonly used today. ACC provides the interface for the association, while UAC represents the data or state associated with the association.
Note the paradigm shift. The user interface commonly used today:
reads "for Block b and the collection termByBlock on it, add a link that connects it (meaning b) through t to n," with emphasis on b.
The new centralized control has a different order of parameters:
reads "for association blockNets, add a link from b through t to n," with emphasis on the association.