Here's a nice summary (we only use a small subset of full UML).
Since we only model static structure, and no behavior, our convention is to hide the operations compartment of all classes in diagrams. This helps conserve screen space for complex diagrams. Also, try to keep superclasses above their subclasses. Example:
If a diagram gets too complicated, refactor it into a number of simpler views of different aspects of the model. A sign you need to refactor is when you have line crossings and it's not possible to avoid them because the diagram graph is non-planar.
- Be sure to give every association a unique name. If you forget to do this, you may get difficult-to-decipher errors during createCatalog. Association names are mapped directly into Java class names (without any prefix).
- Likewise, give both ends of every association a name. An end name is used to generate an accessor method, so it should be unique within the class on the other end of the association (and all of that class's superclasses and subclasses).
- Use only MOF primitive types for attributes. If you accidentally use a Java type (some of the names are the same as MOF types), you may get difficult-to-decipher errors during createCatalog. (In ArgoUML, the primitive MOF types are the ones with Initcap names AND green disks next to them; some of the Java types also have green disks, but you don't want those.)
- Watch out for trailing spaces or tabs on object names; they will pass createCatalog successfully, but will cause mysterious failures later during XMI import.
- The version of Netbeans MDR in use in Farrago contains a bug which causes invalid class definitions to be generated when there are too many primitive long or double attributes. In practice, if an attribute's type is Long or Double and its multiplicity is 1, the metamodel's interfaces will use a long or double primitive. When 5 or more of these attributes exist in a class (including super class attributes), catalog creation will intermittently fail. For 6 or more, it will always fail. The simplest short term workarounds are to use another type (e.g. Integer or Float) or to set multiplicity to 0..1. In the longer term, we'll resurrect a buildable copy of the MDR source and can fix its code generation. See FRG-295.
- Don't bother specifying initial values for attributes, since that metamodel feature is not known to JMI.
The rules below are important for persistent catalog entries which will be queried via SQL views. For convenience, they can be safely ignored for transient metadata such as Fennel commands and plans:
- Don't define many-to-many associations. Instead, define intersection classes.
- Don't use classes as attribute types. Instead, define a composition association.
- Don't define multi-valued attributes. Instead, define a composition association.
- Create a new class, e.g. AggregationType.
- Give it a "stereotype" of <<enumeration>> (ArgoUML shows the available stereotypes down in one of the tabs at the bottom pane).
- For each symbol such as SUM, COUNT, etc, repeat steps 4-6 below.
- Create a new attribute in AggregationType with the corresponding name, all uppercase (e.g. SUM)
- Give the attribute the same type as the class (AggregationType). This is a little unintuitive, but correct, and matches the pre-1.5 typesafe enumeration pattern everyone used before 1.5.
- Mark the attribute as frozen and static (corresponds to static and final in Java, same as in the typesafe enum pattern).
- Once you're done defining the enum, you can use it as the type for an attribute in a normal class such as Measure. Here you have to violate the rule above about not using classes for attribute types; it's OK in this context. The multiplicity can be either 0..1 (allowing null) or 1..1 (one of the enumerated values is always required to be set; there is no default).
Additive Changes Only
As described in FarragoCatalogUpgrade, it is important when changing the model to think about upgrades for existing catalogs in the wild. To be safe, only make additive changes for non-transient portions of the model. Here's what this means:
- Don't rename attributes, change their types, or delete them
- Don't rename packages, classes, associations, or ends; and don't delete them or move them to different parent packages
- Don't reattach associations to different end classes
- Don't add new associations between existing classes (unless you make both ends optional).
- Don't add or remove superclasses from existing classes. (But you can add new classes as subclasses of existing classes.)
- When adding a new association between an existing class and a new class, be sure the new class end is optional (multiplicity 0..1 or 0..*).
- For new attributes of primitive type (e.g. Integer) it is not necessary to make them optional; they will be set to 0 (or false for Boolean) by upgrade. However, new attributes of String or enum type must be declared as optional (multiplicity 0..1).
Which UML editor to use? We're using the open-source project ArgoUML. Download the latest version before editing the model. Version 0.26.2 is known to work, but do not use version 0.28.1. (It writes a UML file that is not well-formed XML, and gives the error 'The prefix "argouml" for element "argouml:pathitem" is not bound.' during the convertExtModel xslt processing.) See ArgoUmlAssociationPlacement for details on how to get around an incompatibility between MDR and the association placement rules imposed by ArgoUML.
Generating C++ model classes
To update C++ code to match catalog changes in the Fennel sub-package, see FarragoFennelModelUpdate.