MagicDraw UML for Java software engineering

These tutorials demonstrate proven ways to use MagicDraw UML for forward- and reverse engineering of Java software system, and how to organise diagrams of Java systems well.

HOWTO reverse-engineer existing Java source into MagicDraw UML

In these trails you will learn how to create and/or update your MagicDraw UML projects with UML models and diagrams corresponding with existing Java code (we will be using the MagicDraw UML Open API and other mini Java examples). Of course all Java will be reversed into MagicDraw UML models.

However, just reversing Java code into a UML model is only the beginning of the story. A UML model of Java code and automatically generated diagrams of Java classes do not alone achieve much. To improve your understanding of your Java code you must interact graphically and cognitively with the diagrams and models, and only once you begin manual re-organisation and analysis of the generated diagrams, create new "logical" diagrams and views of model elements , and introduce editorial commentary and annotated refactoring, do you reap the full benefits that a graphical view of code can provide.

You will learn here proven ways to organise and annotate reverse-engineered UML models in MagicDraw UML.

Basic Java Desktop Application example

In this simple reverse engineering example the default Java Desktop Application from Netbeans IDE 6.1 will be reverse engineered into MagicDraw UML. All code for the example is automatically provided by Netbeans IDE on creation of a new Java Desktop Application, and when it runs it looks like this:

Create a new Java code engineering set

To commence reverse engineering on existing Java code create first a new code engineering set.

NB: Make sure the Show Code Engineering Set option is active in the model browser

We will create here a Java set, because we will be reversing Java source.
(Later we will also see how to reverse and diagram Java Bytecode models.)

Message: choose option import only

You will be presented with a dialog explaining "import only" mode. Since we are only working here on "passive" reverse engineering, not code generation (forward engineering).  we will accept this option for increased efficiency by checking the option in the next dialog:

Choose code engineering set name and import-only option

You may use any name you like, here I simply use the name of the Application
(you may also choose to org.indicate.the.package.structure).

The Use set to import code only option is chosen because we will only be reverse engineering.

Edit code engineering set to select source

Once the code engineering set is created it will appear under the Code Engineering Sets node, however it is not yet populated.

Select the code engineering set and then choose Edit from its context menu ...

Message: Round Trip Set

Although it describes a Round Trip Set we will only be using the set for reverse engineering.

Set code engineering source directory and add sources

The src directory of the Java project has been chosen.

For Java sources choose Files of type: *.java 

Use Add Recursively to add the source files to the code engineering set.


NB: no matter what Java package a source file is in it will land in a simple list within the code-engineering set,
however on reverse the packages will be correctly identified from the Java header.

 

Reverse entire code engineeering set

Once souce files have been added to a code engineering set they will appear under that set (in a simple list) in the model browser Code engineering sets group. To reverse the entire code engineering set (including resolution of dependencies within the set) choose Reverse from the context menu for the set.


By selecting Reverse from the context menu for a source within a code engineering set it is possible to reverse and individual source file (which can be useful if files are recently added) however I advise against this approach when dealing with complete source bundles and until you gain experience with reverse engineering, as it can result in unresolved dependencies, and the generation of elements in the Default package in the model.


WARNING: reverse engineering changes can't be undone

Heed the warning before proceeding:

Reverse Options: default

At first you will be presented with the default reverse options, as shown.. We wil be fine tuning this options before proceeding:

Reverse options: fine tuning

I recommend that when reverse engineering a Java project for the first time you at least select the automatic class diagram generation, and explore also  the Model Visualizer, within the Visualization group.


WARNING:
Unless you are experienced and familiar with the code I recommend that you DO NOT choose the option to Create class fields as Associations, because it will generate Associations to utility classes like java.lang.String and java.lang.Integer, as well as to trivial classes within your Application.

(Instead I will be showing you how to "create roles" for selected properties using the context menu or by "dragging" a Property out of a Class, which action also offers more cognitive reinforcement, as you witness an associative "connection" being generated before your eyes.)


If the code is unlikely to change, then you may wish to generate additional Analysis dependencies between Classifiers and Packages, however these can be difficult to maintain if code changes frequently, and for your first reverse engineering trials I recommend that you avoid them.

Create diagram for reverse engineering and choosing its name and location

Because I have selected the visualisation option to Create New Class Diagram I am now prompted for a name and location for the diagram. In this case I have chosen to name the diagram after the single Package containing all generated Class elements, and I am also placing it in that package (which can then be hyperlinked to that diagram).

After reverse always check the messages window to find any unresolved dependencies

Before you proceed to examine the generated model elements or diagrams it is a good idea to always check the messages window.

In this case we see that 2 Classes SingleFrameApplication and FrameView that are used by the JavaDesktopApplication have not been found, and model elements from them are created in the Default package, which you might like to think of as an "inbox" for unknown elements.  Checking in the IDE one can find these unresolved classes from appframework-1.0.3.jar, which are:

org.jdesktop.application.SingleFrameApplication
org.jdesktop.application.FrameView

You now have some choices:

  1. ignore the warning and live with the unresolved classes SingleFrameApplication and FrameView polluting your model in the Defaults package
  2. massage the unresolved classes by hand into a manually created UML Package org/jdesktop/application (very error prone)
  3. delete the unresolved classes and repeat the reverse after adding the required JAR to the the classpath (much better, see next pages)

If the appframework-1.0.3.jar had been included in advance in the classpath the problem (deliberately provoked for this tutorial) would not have arisen, so it is a good idea to examine dependencies as much as possible in your IDE before performing reverse on large applications.

Reversed elements: overview in containment browser

Before proceeding to view and edit the generated diagrams I recommend that you examine the elements generatedin the containtment browser.

Here we see at the top the 2 unresolved classes FrameView and SingleFrameApplication in the Default package (which will be deleted and resolved promptly).

Under File View we see a UML Package corresponding the Java package javadesktopapplication,  and some UML Component elements corresponding to the java source files.

The application classes appear as UML Class elements under a package javadesktopapplication with reversed attributes, operations, and parameters.

The matching matching code generation node for each class in the code engineering set (at the bottom) now also contains a child node for each feature.

Some java.awt, java.swing and javax.swing classes have been correctly resolved by name and namespace (although NOT reversed in detail) because the Java jars are already known via the Java ClassPath for the project.

Let's now fix the 2 incorrectly resolved classes ..

Delete unresolved elements in the Default package

Experience shows that it is best to simply delete unresolved elements and then fix the model properly by reversing again after adding the required JARs to the classpath.

HOWTO add a JAR to the Java ClassPath for the project to resolve unknown references

A JAR can be added to the ClassPath for a project using:

Project Options > Java Language Options > (...) Set ClassPath > Add > Choose

Here the appframework-1.0.3.jar for the Swing Application Framework distributed with Netbeans IDE 6.1 is added, so that FrameView and SingleFrameApplication can be resolved.

Note that a number of JVM jars are already known to a default MagicDraw UML project for Java, and that you can also use Get from System to update the list.

Repeating a reverse to fix unresolved references

With the correct JAR now in the project's classpath we can simply repeat the reverse to resolve the unknown elements. Note that because the originally unresolved elements were deleted from the Default package it is easiest to simply reverse the entire project in this case (for larger projects you may wish instead to perform repeat reverses on selected source files).

The default options wil be taken (with no new diagram creation):

Correctly resolved Classes after repeat reverse

Now - because the correct JAR is in the classpath - the required classes from org.jdesktop.application have  been resolved, and Class elements for them have been created (although not reversed in detail).


 Note that the Default package is now empty; if is not empty you SHOULD ALWAYS ask yourself why before proceeding !


So far in this tutorial we have not examined a single UML diagram ! However, we do have a model with good integrity. I recommend that you always take care to examine the model and the Messages Window to ensure correct resolution of references BEFORE proceeding to the diagrams.

Motto: it is much easier to prevent reference errors in the underlying model than to detect them and/or fix them using diagrams !

Understanding and adapting reverse engineered diagrams

Now that all references are known to be correctly resolved we begin to examine the generated class diagram.

The default layout engine has created an acceptable starting point for our analysis of the Java application.

(I have switched the grid off under Options > Project > Symbol Properties styles, I don't recommend showing the grid unless you are doing geometrical/physical engineering.)

One of my style recommendations is to only show the operations and attributes of a given Class in a dedicated "focus" diagram for each Class, whereas one does well in an overview diagram for a package to not show features of elements. In the next pages I'll be fine tuning and adapting this diagram and adding "focus" diagrams for each major Class to improve readability and navigability.

Creating navigable package diagrams and focus diagrams

As a first shot I've used Select All to apply Symbol Properties to all elements to Suppress Attributes and Suppress Operations, following be the Organic Layout. This forms a good starting point to navigate to hyperlinked "focus diagrams" for each Class.

Unfortunately this code is not very "UML-friendly", there are not obvious relationships between the Classes, and because "create Dependencies" was not used the reverse has relied entirely on Java fields, so there is nothing here to "wire up" yet. We'll return to this theme later.

Let's now create some focus class diagrams and hyperlink to them from the featured classes.

Creating a "focus diagram" for each Class in a Package

You can create a diagram by simply selecting a Class symbol and choosing New Diagram > Class Diagram. It will not be automatically hyperinked to the Class Diagram, and it will not be automatically named after the chosen Class, which is done by hand in the next pages ...

Manually name a "focus" class diagram after its Class

To avoid errors I recommend you copy the Class name from the symbol first then paste the name using the clipboard

Starting and hyperlinking a "focus" diagram

Drag the element from the browser onto it's focus diagram so that it appears a symbol in its own focus diagram. Then immediately - BEFORE DOING ANYTHING ELSE  - drag the diagram icon from the browser onto the element's symbol in the diagram to create a default hyperlink from the element to its focus diagram. Super, the element now opens up into its focus diagram !

Always offer a way out of a focus diagram

TIP: place at least one package or overivew diagram's symbol on every focus diagram to offer a way out/up, to avoid a navigation Cul de Sac.

Note however that using diagram symbols from outside the namespace of an element can block modularisation ! In this case we are safe because the package overview diagram is in the same namespace. In general, one should not have to resort often to the browser to navigate across a project.



I have also used Retrieve Documentation into Comments with handles to the Class and an Operation, to show how a "focus diagram" might be used. There is not much of interest to be done with this main class, and it has no attributes, so let's move back to the package overview diagram ...

Navigation from a package overview diagram to focus diagrams (and beyond)

Now that a hyperlinked "focus" diagram has been created for each element in the package one can simply navigate to each focus diagram by clicking on its Class element's symbol to "open it up".

Or one can use the Hyperinks/GoTo button (tiny arrow lower left) on a Class to navigate more widely, to other non-default hyperlinks, or to usages of it in other diagrams, or to elements related to it through Generalization.

Analysing a Class and its nearest neighbours in a "focus" diagram

The JavaDesktopAboutBox Class has a single Java field, shown in the model as a UML attribute Property closeButton: JButton.

Next we will now see how to convert this attribute (a text representation) into a Property end of an Association (a graphical representation).

Convert an attribute into a Property end of an Association by "dragging it out" of its owner's symbol

Simply select an attribute and drag it out of it's owner's symbol boundary to convert it to the Property end of an Association. The result is shown in the next page ..

Attribute converted to Property end of an Association

This provides an associative/relational graphical view of the system, as well as the ability to examine the Property in more detail (to view its owner, operations, etc.)

TIPS for display options of nearest neighbours

DO show the (owner) of nearest neighbour (immediately associated) elements in a "focus" diagram if it is not from the same Namespace as the focus element.

AVOID showing the attributes (Properties) and Operations (Features) or verbose information about a nearest neighbour (associated Class) UNLESS it is very closely bound to the function of the focus Class, or there is an immediate context (such as an annotating comment) for the revealed Feature(s). If you do wish to show a Feature(s) of a nearest neighbour consider using Edit Compartments to display only relevant features.



TIP: Try to "feature" the Features of a Classifer in its own dedicated "focus" diagram; and try not to feature it's Features anywhere else. This will help reduce graphical coupling throughout your software engneering (and it will also help to make you more aware of undesirable software coupling, too).

Graphical coupling when showing features of associated elements in a "focus" class diagram

If you reverse engineer javax.swing.JButton with its symbol's Feature compartments showing this "focus" class diagram for JavaDesktopAboutBox "explodes" graphically ! In general, show only Features of the focus Classifier in its dedicated "focus" diagram (unless features of an associated Class collaborate immediately).

Exploring nearest neighbours with Display Related Elements

A good way to explore the neighbourhood of a Class in it's "focus" diagram is with this context menu:

  Related Elements > Display Related Elements

There are (at least) 2 basic strategies to choose from:

  • Show only those elements that the focus Class depends on (it's suppliers):
    • Does not preempt the usage context
    • One can still navigate to clients via Related Elements > Used By
    • I recommend this approach where possible 
  • Also show those elements that depend on or use the focus Class:
    • Preempts the usage context
    • Can prevent modularisation
    • Diagram needs to be updated if new clients added
    • Tempting, because one can easily navigate to client classes
    • I recommend you avoid showing client Classes on "focus" diagrams where possible:
      • instead use separate architectural level diagrams with an overview of paricular clients and suppliers

In the following we will only explore suppliers for the "focus" class JavaDesktopAboutBox.

The Display Related Elements dialog

I have chosen here to only display related suppliers (cf. Dependency), and to only show related Generalizations.

Also, since I am only investigating "nearest neighbours" in a "focus" class diagram, the Depth is left at 1.

The result shows 1 related Generalization supplier ("parent") JDialog ..

Showing the Generalization supplier in a "focus" class diagram

It is useful to show the immediate Generalization supplier(s) of a given Class in a hyperlinked "focus" class diagram.

(In Java a class can only extend at most 1 Java class, so there is always at most one Generalization supplier in the UML reverse.)

The supplier javax.swing.JDialog was generated for JavaDesktopAboutBox in the diagram above using Display Elements > Display Related Elements. The owner (javax.swing) of JDialog has been shown, and the attributes and operations compartments are open; thet are empty, suggesting that JDialog has not been reverse engineered. If we examine the code we see that JavaDesktopAboutBox relies on methods inherited from JDialog. So we will now reverse JDialog from bytecode and we'll display (only) some of the operations used by JavaDesktopAboutBox using Edit Compartments ..


/*
* JavaDesktopAboutBox.java
*/
package javadesktopapplication;
import org.jdesktop.application.Action;
public class JavaDesktopAboutBox extends javax.swing.JDialog {
public JavaDesktopAboutBox(java.awt.Frame parent) {
super(parent);
initComponents();
getRootPane().setDefaultButton(closeButton);
}
@Action public void closeAboutBox() {
setVisible(false);
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
//
private void initComponents() {
..
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
..
getContentPane().setLayout(layout);
..
pack();
}
// Variables declaration - do not modify                     
private javax.swing.JButton closeButton;
// End of variables declaration                       
} 


 

Reversing from bytecode by reversing from classpath

We now wish to explore those operations of JDialog that are inherited and used by JavaDesktopAboutBox.

Since the JDK jars are already included in the project's Java classpath, we can use the convenient Reverse from Classpath menu ..

Reverse from classpath: options dialog

There is no need in this case to Visualize the result (since we will only examine selected operations in an existing diagram), and once again only attributes, not Associations, will be generated ...

Beware of graphical coupling when reversing classes with many features !

Oops, the focus diagram for JavaDesktopAboutBox has now been polluted with attributes and operations from JDialog !

We can choose (at least) to:

  1. not show any attributes or operations at all for JDialog 
  2. show only those attributes or operations of immediate consequence to JavaDesktopAboutBox

Next we learn how to show only selected features using Edit Compartment ...

Displaying only selected attributes/fields and operations/methods using Edit Compartment

We now choose to display with Edit Compartment > Operations only those operations of JDialog inherited and used by JavaDesktopAboutBox

The Compartment Edit dialog

Often it is easiest to choose to display no operations first, then to choose explicitly which ones are to be shown.

Here I use the << button to remove all operations from the compartment, then I'll choose those of interest ...

Compartment Edit dialog: selected operations

Explicitly select operations to display using the > button.

From inspection of the code of JavaDesktopAboutBox I know that at least those operations from JDialog shown below are relevant ..

Improved focus diagram with only selected operations showing from related class

Now that only those operations from the Generalization supplier JDialog relevant to JavaDesktopAboutBox are showing the "focus" diagram for JavaDesktopAboutBox makes far more sense and is much tidier.

Note carefully the '...' at the bottom of the operations compartment of JDialog, showing that not all operations are displayed !


This technique works well when it is known that new attributes/operations are unlikely to arise in future, which is the case here with very stable JDialog.

Exploring beyond the nearest neighbour in a "focus" diagram

It turns out that JavaDesktopAboutBox uses operations from higher up than its immediate Generalization supplier JDialog. Let us now explore a bit wider, more than 1 relationship away from the "focus" element JavaDesktopAboutBox.

While it is possible in MagicDraw UML to Display Related Elements to infinite depth, I advise against it in most cases; one is far more likely to create manageable diagrams and to learn more by moving 1 step at a time out from an element of interest .. 

Show crucial interfaces in a "focus" diagram for a class

We see that javax.swing.JDialog is in fact also a java.awt.Dialog, and that it realizes (implements) a number of interfaces.

Now we are beginning to get a feel for JavaDesktopAboutBox as a "machine" !


TIP: A "focus" diagram without any interfaces might indicate a lack of "design by contract" or "service orientation". One should explore out from a "focus" Class until its major direct or indirect interfaces (and direct and indirect Generalization suppliers) are revealed.

Let's now reverse java.awt.Dialog and display (only) some of those operations used by JavaDesktopAboutBox ...

The natural extent of a "focus" class diagram

Here I've gone up as far as java.awt.Component, paying of course the price for reverse engineering quite a lot of features not really relevant to the focus element JavaDesktopAboutBox, which features do take up space in the underlying model, even if they are not shown in the diagram. In this case it is necessary to get at the interfaces of java.awt.Component, and to methods like pack() in java.awt.Window, which is used by JavaDesktopAboutBox.

Does on really need to show that java.awt.Container has a LightWeightDispatcher and a LayoutManager, or that it has a list of components ? Probably not, these are not immediately relevant to the focus element JavaDesktopAboutBox, and they belong - if anywhere - in a dedicated focus diagram for java.awt.Container. A balance must be found between keeping the "focus" on a particular element, and displaying enough features and related elements to reveal the "machine" nature of the "focus" class.

Notice how I've placed the Interfaces left and the implementation details right, which is just one way of emphasising design-by-contract, service orientation, and the "machine" nature of well-designed software systems.

Managing physical, logical, and graphical groupings of software model elements

Let us now turn our attention to the reverse engineered JavaDesktopView class, which has a number of Properties typed by classes from javax.swing.

It will soon be seen that if one converts these attributes to Property ends of Associations the focus diagram for JavaDesktopView can become unwieldy ..

Some pros and cons of text-like attributes vs. graphical associations

By dragging out most of the attributes typed by a javax.swing Class (and with a little graphical tweaking), I've made a more "associative" focus diagram for the JavaDesktopView Class.

This approach has some benefits:

  • one can reveal rich information about the types of the properties, such as operations and attributes
  • one can navigate easily on the classes that type the properties to other diagrams
  • one can easily comment on the classes that type the properties
  • one easily separate and group properties typed by classes from different packages or frameworks
    (although in this example here all are from the same framework)
  • one can see when a single Class types more than one property

It also however brings with it some problems, which can discourage those used to purely text-based coding:

  • it can be fiddly to diagram (one barely has to do anything todeal with a list of attributes in a single compartment)
  • Not every detail is easily shown in the associative representation, such as the Property.defaultValue of a Property:
    • See busyIcons : Icon"[]"[0..*]= new Icon[15], which has been left as an attribute
  •  if one moves or resizes a Class in one part of the diagram the others have to be moved, which can be time consuming

Next we see just some of the strategies which can help make dealing with associative diagrams easier ...



Visit also: 

 

Using physical packaging to group Class symbols graphically

In the JavaDesktopView example all attributes that were turned into Property ends of Associations were from the same Package (javax.swing) so one can easily group them graphically using a Package. All of the grouped elements can now be moved at once (easier and more robust than using multi-select).

Notice how I've chosen to show the package name with its owner in the tab, and the owner need then not be shown for the owned Classes.

Extreme care must be taken when moving Class symbols into Package symbols in diagrams that the ownership is not changed !
Check the ownerships carefully first lest you corrupt the model !

Depending on the system involved this physical grouping strategy can be quite effective, and it works quite well when only a few packages are involved, however it does not scale well in all systems, and although quite widespread this practice is NOT robust against changes in the design and/or packaging ! The most flexible grouping can be achieved with "parasitic" logical grouping that does not affect the ownership and enables far more flexble diagramming and representation of class collaborations.

Using "wrapper" Components to logically group Classes (without stealing ownership)

Although not standard UML2, the following recipe is extremely powerful, robust, and flexible, and it works particularly well in MagicDraw UML.

The UML2 Component can be "re-appropriated" as a graphical and logical wrapper to group Classes in a diagram without "stealing ownership". All you have to do is put a Component symbol in a diagram (not in the browser, there it does steal ownership), and move Classes symbols in the same diagram into the Component symbol's rectangular boundary.

Note in the example below:

  • The ownership of the classes has been preserved.
  • I have clearly stereotyped each Components re-appropriated in this way as a «logical» «wrapper» !
  • I have used freestyle lower-case names for the wrapper Components to indicate that they are general logical contexts.

Using this recipe one can create any number of logical views of any number of different physically packaged elements according to any desired logical context. It provided "orthogonal" views of a system, and it is simply wonderful. Don't leave home without it !



Visit also these detailed discussions and examples of wrapper Components as popularised by Dr Darren:

Reverse engineering Java variables

In this trail we examine what happens to the different types of Java variables when they are reversed into MagicDraw UML.

You should be familiar with the Java variables terms and definitions from:

http://java.sun.com/docs/books/tutorial/java/nutsandbolts/variables.html

http://java.sun.com/docs/books/tutorial/java/javaOO/variables.html

http://java.sun.com/docs/books/tutorial/java/javaOO/classvars.html

A first reverse engineering of a simple test suite is shown below. A class Main has a number of different types of attributes (Java fields), operations (Java methods), and it depends on a Thing Interface, which it can create directly through the default implementation Thing_, or via a Factory.

As usual, I have chosen to NOT yet create Associations from the attributes (as reversed from the Java fields); let's now join up the system a bit by converting selected UML attributes from Java object references to Property ends of Associations ..

Converting object reference attributes to graphical Property ends of Associations

I've dragged out some atttributes typed by Thing, Thing_, and Factory (except for the static CLASSY_THING which we'll examine later).

It is of course not good practice to have references to specific implementations like the default implementation Thing_, as that approach blocks dependency injection and breaks the golden rule of design-by-contract,  it is much better to only ever obtain a Thing Interface from a Factory, however in this demonstration at least a non-null Thing is provided by default in operation getThing(), which uses an implementation-specific field thing_ to hold a Thing_. (We'll examine the factories later.)

Already the graphical, associative approach is helping to wire the system up nicely, and in fact it even highlights the lack of design-by-contract in some methods. Let's break it down further using package overview diagrams and focus diagrams ..

Creating a "focus" Class diagram with immediate Associations

I have created a "focus" Class Diagram for javavariables.Main, which I've hyperlinked to Main by dragging the diagram icon from the model browser onto the Main Class symbol in this same diagram.

Because Main does not know directly of the strange Package's implementations, they are not shown in this diagram, for that would preempt implementations of Thing and Factory.

There remains however one explicit reference to an default implementation Thing_ (and later we'll discover that there are also references to Thing_ and Factory_ implementations in the methods through local variables, however these are not exposed as Associations, because they don't reverse from Java fields to UML attributes or Property ends of Associations).

Java users new to UML should note carefully how a visibility indicator appears on the Property at the end of each Association to Thing:

  • '+' indicates 'public'
  • '#' indicates 'protected'
  • '-' indicated 'private'

The same indicators appear on the remaining attributes (which we'll examine in detail soon).

Let's see first how the package overview might look .. 

Improved Package Overview diagram

The Package Overview Diagram has been improved:

  • Features of Classifiers are not shown except:
    • the features of the Thing Interface are shown to enable the 3 Associations to it to be drawn easily (a compromise)
  • The packaging of the strange implementations has been shown
  • One can also see 2 additional classes involving arrays and containers we'll examine shortly
  • Some loose grouping of elements concerning factories and elements concerning things have been made

Before resuming our study on lets's look briefly at one strategy for logically grouping and graphically the elements to do with factories and things ..

Logically grouping with UML2 Components as "wrappers"

Here UML2 Components have been re-appropriated through stereotyping as «logical» "wrappers", with the benefit of graphical grouping, without affecting the ownership of the visually contained elements, by moving them in the diagram into the Component wrapper symbols in the diagram.

One could argue that Factory Interface, its default implementation Factory_, and its related exception NullFactoryException should go physically in one Package; the wrapping strategy enables one to suggest this refactoring passively, and even if the physical refactoring takes place, this diagram will still be valid and stable on reverse of the newly packaged system.



Let's return now to the the analysis of Java variables under reverse engineering in MagicDraw UML ..

Java fields and methods as UML attributes and operations

Let us examine now in detail some aspects of the representation of Java fields and methods when reversed to UML in MagicDraw.

I have used "callouts" into UML Note symbols here in combination with Edit Compartment > Element Properties to reveal aspects of the UML representation of features on reverse from Java, as well as using Retrieve Documentation some of the Javadocs into UML Comments.

Java users new to the graphical UML representations should study such examples carefully and experiment frequently with similar tests. Note that:

  • Default values for attributes (Java fields) are are shown by default: +iPublic : int = 2;
  • All static features - both attributes (Java fields) and operations  (Java method) are underlined
  • Additional stereotypes like «JavaElement» and «setter» are applied from the UML Profile for Java «modelLibrary»
    • new users are encouraged to explore this profile to examine correspondence between Java and UML concepts
  • Java annotations appear as "tagged values" of stereotypes: like «JavaElement» {JavaAnnotations = "@Lazy"}
  • The visibility indicators are:
    • '+'  public
    • '#'  protected
    • '-'   private
    • '~'  package

MagicDraw UML also provides a number of sorting options for attributes and operations compartments under Presentation Options.

As a rule of thumb, one does well to leave primitively typed properties as attributes, whereas object reference types of interest to the application are often best converted to Property ends of Associations, except for common reference types like java.lang.String and the java.lang.Number classes. 

What about the static field +CLASSY_THING : Thing, which is initialized by the static method initClassyThing() ? If we convert it to a Property end of an Association we can't easily display the initialisation information. Or can we ? In MagicDraw UML you can have your cake and eat it, too ..

One can show a Property as both an attribute and as a Property end of an Association

Here I have dragged the CLASSY_THING : Thing Property out of the attributes compartment of javavariables.Main to create an Association with it as the Property end. I have then also selected the option [All] under Symbol Properties >  Show Association Ends as Attributes:

Now one can see the Property in both the attributes compartment as a Property end of an Association !

BTW one can also use a "callout" into a Note to get at information not otherwise displayed on an Association end.


Visit also:

Reversing Java arrays, collection classes, and generics

Below I have reversed the following class javavariables.HasArrays with variations on Java arrays:




public class HasArrays {

public int[] iArrayNoInit;

public float[] fArray = new float[5];

public int[] iArrayInited = {0,2,4,6};

public Thing[] thingsEmpty;

public Thing[] thingsFilled = {new Thing_("1"), new Thing_("2")};

String[][] names = {{"Mr.", "Mrs.","Ms."},{"Smith","Jones"}};
}


Note that:

  • The Type Modifier indicator for an array Property shown in the attributes compartment is shown quoted "[]" to distinguish it from the multiplicity indicator: [0..*]
  • Although fArray clearly can't have more than 5 elements after initialisation, it has multiplicity [0..*]
  • MultiplicityElement./upper:UnlimitedNatural[0..1] for fArray is set to -1, which acts as a placeholder for a MultiplicityElement.upperValue:ValueSpecification[0..1] of '*'. Compare with UML2.1.2: 

    17.4.4 UnlimitedNatural (from PrimitiveTypes) .. An instance of UnlimitedNatural is an element in the (infinite) set of naturals (0, 1, 2…). The value of infinity is shown
    using an asterisk (‘*’).

  • A multi-dimensional Java array "[][]"has multiplicity [0..*]

I've chosen to drag out an array Property thingsEmpty typed by object Thing to make it an Association end. Note that the type modifier indicator for an array Property is not shown explicitly at the end of an Association, however it can be accessed through a callout into a Note using Edit Compartment > Element Properties.

Let's now see what happens with Java collection classes ..

Reversing Java collections

The class javavariables.HasCollections has some Java lists, sets, and maps:




public class HasCollections {

 public List list;

 public List<Thing> lThings; 

 public List<List<Thing>> lolThings;

 public List<String> lStrings;

 public Set<Thing> sThings = new HashSet<Thing>();

 public Map<String,Thing> map;
}



Some of the collections use Java5 generics and can only deal in objects compatible with generics parameter.

Let's see first what happens on reverse if we select the option to Resolve collection generics ...

Collections with resolved generics

We see that on reverse a number of collection class types are detected, such as List<String>, List<List<Thing>>, etc. The template binding can be shown with Display Elements > Display Related Elements.

When the collections generics are resolved Associations (such as the one I've made by dragging out Property lThing), are made to the Type of the generic parameter(s), not to the generic collection class.

Let's now compare with reversing with unresolved collections generics ..

Collections with unresolved generics

Here I've deselected the option to Resolve collection generics before reversing. The properties corresponding to Java fields with generic collection types are now typed explictly by those generic collection types, like: lStrings:List<String>. (Compare this with the Property list:List, which is always reversed the same from the non-generic Java field public List list, no matter what reverse option is chosen.)

So which way is best, resolving generics or not resolving them ? That depends a lot on what you wish to achieve ..

To resolve or not to resolve collection generics

When collection generics are not resolved on reverse the explicit details about particular collection interfaces are chosen to type a Java field are revealed in the UML Property,  and in some cases details about specific collections implementations used are also revealed. So in a sense this results in more of a "design" view.

When collection generics are resolved, the explicit details about particular collection interfaces chosen to type a field (as represented by a UML Property) are suppressed, so in this sense it results in more of an analysis view. One can however still get and edit information about the assigned Java "container" class under the Java language properties in the Property specification dialog as shown in the image below.

What really matters is that you choose to either resolve or not resolve collection generics consistently throughout your project.

Template bindings and substitution

The image below shows that our reversed collection type List<String> is in fact only named to indicate a generic, it does not have a template parameter in the model. That information is provided by a TemplateBinding from it to the templated java.util.List<E>.

Unfortunately, one can't callout much of the information about the template binding and substitution process into Notes, however one can view it in the specification dialogs for the TemplateBinding and the targeted, templated Classifier:

 

Using the Analysis options to create «virtual» Dependencies on reverse

Let's see now what happens if we select the Analysis options to create Dependencies between both Classifiers and Packages on reverse.
This process will create «virtual» Dependencies in a dedicated virtual Dependencies Package. 

A reverse will be performed on the entire JavaVariables (Java) example code engineering set, and we'll choose the Visualization option to visualize the reversed model and Launch Model Vizualizer ...

 

Viewing «virtual» Dependencies between Packages using the Package Overview Diagram Wizard

For this example when the Model Vizualiser dialog appears I choose the Package Dependency Diagram Wizard ..

Choose packages for package Dependency Diagram

Make sure that you only select those packages required, and avoid the UML profiles and the top-level package (usually called Data), and don't select packages from the FileView unless really required ..

Resulting Package Overview Diagram with «virtual» Dependencies

On choosing Finish (without fine tuning selected relationships and symbol properties) we have an automatically generated Package Overview Diagram with «virtual» Dependencies, and automatic layout.

Viewing «virtual» dependencies between Packages using Display Paths

Another way to view the virtual Dependencies between Packages is to place the symbol of selected Packages in one diagram then use Display Paths to show the Dependencies. This can give finer control over the diagram, and it offers more opportunity for one to understand and consider the Dependencies step-by-step.

Viewing «virtual» Dependencies between Classifiers using Display Related Elements

One way to view the  «virtual» Dependencies generated by reverse with Analysis is to choose one of the Visualization options on reverse, however even for simply Java applications like the javavariables example the generated diagrams can be very complex and hard to understand.

Another way - providing more control - is to create a dedicated "focus" diagram for a Class then choose:

Display Elements > Display Related Elements

with the result limited to «virtual» Dependencies.

This is shown below for the Main class of the javavariables example (with some tidying up and all other relationship symbols removed). Note that:

  • it shows the Dependency with a faint grey line and sterotyped as «virtual»
  • it includes the number of detected Dependencies: example {n=10} for Thing
  • it shows Dependencies on primitive types
  • it shows Dependencies on stereotypes, too.

Did it also detect the Dependencies from local variables ?

Does the Analysis option to create Dependencies between Classifiers also catch local variables in methods ?

Not every dependency of Main on the other classes in the javavariables example is revealed by just using Associations, because some of the methods of Main use Java local variables:



static public Thing newThingDefault() {
Thing t = new Thing_();
return t;
}



@Lazy
final static protected Factory factory() {
if ( factory_ == null ) {
factory_ = new Factory_(); // by default choose default factory
}
return factory_;
}


Did the Analysis option to create dependencies between Classifiers on reverse catch these as virtual Dependencies (see diagram) ?:

  • it gave only {n=1} for Thing_ (which comes from an explicit private field anyway)
  • it does not find a Dependency on a Factory_ in factory() at all !

So it seems that the Analysis reverse option does not penetrate methods (although the method-based reverse for generating sequence diagrams can).


Exposing Dependencies between Java methods and Classifiers

There are at least the following strategies for dealing with this situation to achieve a graphical UML model communicating this Dependency information:

  1. Create Dependency (or Usage) relationships "by hand" in the UML model from methods to the Classifiers they use (see example below):
    • WARNING: this can be very error prone and is not automatically synced with the code on future reverse.
    • TIP: if you do this I recommend that you clearly stereotype them as «manual» to show they are not automatically reversed.
  2. Code in a UML-friendlier way by avoid local variables wherever possible; expose them explicitly as fields:
    • I am a fan of this approach, as the tiny loss in Java efficiency is more than compensated by the increased readability of graphical, associative UML diagrams that correspond well to the reverse engineered Java.


Visit also:

Reversing the implementation of an operation (Java method)

Let us now analyse the Main.factory() "lazy variable method" in the javavariables example.

Simply select the operation in the model browser then choose Reverse Implementation to open up the Sequence Diagram from Java Source Wizard ...

The Reverse Implementation wizard dialog

We'll just accept here the defaults for the name and location of the generated sequence diagram

Selecting the operation to reverse

We will accept the defaults  provided by choosing to Reverse Implementation from the browser context menu of the operation factory() ..

Selecting the classes to include

We see that the Reverse Implementation has detected that the method factory() uses a Factory_ implementation. Let's accept these settings and see the final reversed sequence diagram by selecting Finish ..

Result of sequence diagram reverse of a Java method

 Below we see the sequence diagram generated by reverse from this simple method:


@Lazy
final static protected Factory factory() {
if ( factory_ == null ) {
factory_ = new Factory_(); // by default choose default factory
}
return factory_;
}


Unlike the Analysis option to create dependencies between Classifiers, the Reverse Implementation procedure is able to detect dependencies within an operation/method.

Sequence diagram reverse of static method Main.main()

As another example, here is the reverse of the javavariables.Main.main() method (adapted slightly), which shows how it first gets a defaultThing(), then a newThingViaFactory() (with the default configured Factory), and then it configures itself with a StrangeFactory_ implementation before again getting a newThingViaFactory(). Note that there are 2 sequence diagram LifeLines representing the two different assignments of Thing implementations to the one local Java variable Thing factoryThing as different times.

On organising physical packages and logical views

One the main reasons to supplement coding in an Integrated Development Environment (IDE)  - in an object-oriented language like Java - with graphical UML engineering is to provide a range of different diagrams as views of the one underlying model from different perspectives.

Most IDEs do quite a good job or presenting the physical organisation of classes in packages in a straightforward fashion (such as tree-table model browsers), and some IDEs can also - to some extent - generate views of dependencies between classes and also plugin architecture.

However, the real benefit of UML-oriented development often only becomes apparent when on starts to create new logical views of the system, using techniques such as dedicated logical diagrams and even logical wrappers. UML also provides for a wide range of analysis elements and requirements modelling mechanisms that can be bound to reverse engineered code, even if the original code was not explicitly developed with these elements in mind, thus value adding graphically and logically.

Let's begin by consider the javavariables.strange Package in an overview diagram that only shows elements from that namespace.

Physical package overview diagrams

The strange Package demonstrates the simplest possible form of Factory. It is used in javavariables.Main thus:



public static void main(String[] args) {

Thing defaultThing = newThingDefault();
defaultThing.out();

Thing factoryThing = newThingViaFactory();
factoryThing.out();
try {
setFactory(new StrangeFactory_());
factoryThing = newThingViaFactory();
factoryThing.out();
} catch (NullFactoryException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
}


When main() calls newThingDefault() it simply chooses directly a default implementation Thing_ of Interface Thing and asks it to output itself.

When main() first calls newThingViaFactory() it in fact also calls factory() which lazily creates a default implementation Factory_ of Interface Factory, which will give it a default Thing_ anyway.

When Main is instead configured with a StrangeFactory_ implementation it will be given a StrangeThing_ implementation instance when it calls newThingViaFactory() next in main() which will output strangely:


Name(<NAME>)
Name(from default Factory implementation)
Factory changed
STRANGE! Name(<NAME>)


Here a Class Diagram is used as a package overview diagram to show the 2 elements of the strange package. This purely physical diagram does little to reveal the collaboration of the 2 elements in the wider picture, the elements are not "connected" with anything via Associations or Generalizations (as reversed) or other relationships.

Let's see how to relate it to some other elements in the system to add some meaning ..

Showing elements related to the elements of a Package

Here I've used Related Elements > Display Related Elements to show the InterfaceRealizations and Generalizations from the elements of Package strange. I've also used Display Elements > Display Paths to show the virtual Dependency of Factory on Thing. This already provides some context for the elements of strange.

Here are some subtle tips about how I've diagrammed:

  • I've chosen to include the strange Package symbol in the diagram, which provides a clear boundary for its elements, and I'm also showing its (owner) so that I don't have to show the owner on its contained elements.
  • I am showing the (owner) of all other supplier elements.
  • There is no need here to show the operations of the Interfaces because they are clear from the overriding strange classes
  • One might be tempted to also  "package" the supplier elements, and this can be useful when they are from a stable library, however in general that strategy does not scale well; if the physical ownership of the supplier elements changes it would corrupt this diagram, a very unwelcome form of graphical coupling !
  • The fact that StrangeThing_ extends Thing_ is in fact only an implementation detail (it could just as easily implement out() directly) so I've placed Class Thing_ "on the other side" from the Interfaces. This trick is a theme you'll notice throughout this eSchool, one wishes to progressively indicate the spirit of service orientation and separation of interface/contract from implementation.

Would it be a good idea to also show here how the Package is used? Would it be nice to include - for example - Main, which uses the strange Package ? The problem with that strategy is that it introduces another form of graphical coupling, and it preempts the usage context of the strange classes. It can also prevent modularisation, which is a good way to test whether your diagramming style has too much coupling. It is often better to use a separate "architectural" diagram that shows the interactions of particular classes in a "class collaboration" ...

Avoiding elements external to a Package in its Package overview diagram and module

In this variation on a overview diagram for Package strange I've included some elements that use the strange elements either directly or indirectly. I've also used Display Elements > Display Paths to show the virtual Dependency of Factory on Thing, and similarly some other selected virtual Dependencies. And I've added a Usage from Main.main() to StrangeFactory_. What a mess ! This will never modularise, let's see why:

Firstly, note that although both Factory and Thing come from outside the strange Package, this package depends on them anyway, so having them in the diagram does no harm.

Including the client Main, however, is a problem, along with its owned Associations with end Properties thing_, uPublic,  and factory_.

Including the virtual Dependencies are also a Problem, because by default they are generated in the Virtual dependencies Package.

And even the annotation stereotype «AVOID» may be a problem unless it is packaged in a profile known to Package strange when modularised.

Let's see what happens when we attempt to create a module naively from this strange Package .. 

Attempt to modularise a Package with graphical coupling

A Package (like javavariables.strange) can be modularised in MagicDraw UML by selecting  Modules > Export Module from its context menu in the model browser:

You will given the opportunity to select additional Packages (which opportunity I'll ignore for now):

On selection you will be asked whether you want to check Dependencies (you should):

When I attempt to modularise the strange Package I immediately get a number of errors and warnings as shown below in the Package Dependencies window. What a mess !

  • External class Main is a problem, along with all of its owned Associations and Dependencies.
  • All of the virtual Dependencies shown in the badly designed diagram strange package with using clients cause errors, too.

There are some other problems not caused by this diagram, such as the relationships to Factory, Thing, and Thing_, however recall that these will need to be referenced from the module's elements anyway, so they can freely be included in any diagrams within or under Package strange.


So if showing clients in a diagram within a Package like this is a bad idea, how can it be done better ? By using an external "architectural" diagram that shows the collaboration of particular classes from a number of other Packages ...


Architectural class collaborations

To explore how we can better diagram the way Factory, Thing, and the strange implementations within the JavaVariables example are used I create first a fresh Java project ThingSystem with its own Package thingsystem and Classes Server, LocalClient, and LocalTest. Because these classes will depend on a number of collaborating elements from different packages, diagrams in ThingSystem are free to refer to elements from those packages without introducing undesirable graphical coupling; ThingSystem is a particular usage context, so its diagrams are permitted to express that.

The Server prempts a gradual move to a more port-based, service-oriented approach by offering services quarantined through the Serve and Manage Interfaces. LocalClient will use Serve, and LocalTest will use Manage to set a specific Factory.

The LocalTest.main() trivially creates a Server, configures it with a StrangeFactory_ implementation, and then "connects" the LocalClient to the Server by passing the client a reference to Serve (later we'll examine how to reverse and model across a network, such as under RMI).

However the reversed ThingSystem does not (without virtual Dependency creation) otherwise easily wire up, and it is not coded in a very UML-friendly way:

  • The reverse did not "see" the Java local variables Server_ server or LocalClient client in LocalTest.main()
  • The creation of a new StrangeFactory_() is also not detected. 

How can we expose more in our UML models automatically on reverse ? Before recoding in a UML-friendlier way, let's first see what happens we reverse the implementation of method LocalTest.main() ..

Reverse of LocalTest.Main() implementation to Sequence Diagram

Using Reverse Implementation one obtains more sense of architectural collaboration of elements in this simplified client-server system (although the choice of a StrangeFactory_) is still a bit buried. How can we code in Java in way that admits more access to this information already at the Class and Association level ?

Coding to expose Dependencies as Java fields with lazy initializers

Here I demonstrate a style of Java coding that supports generation of end Properties of Associations from explicit Java fields, rather than burying Dependencies as Java local variables. It enables one to "wire up" UML models of Java code associatively.

In UMLfriendlierTest there are explicit Java fields for the choices of LocalClient_ and StrangeFactory_, which are created and configured through "lazy" protected operations client() and factory(), which act as lazy variable operations; the fields are never used directly, only ever by calling the lazy ops.

Also, the Interfaces Serve and Manage are only accessed through service accessors  serve() and manage(), which in turn trigger the lazy server() method. I call this approach cascading lazy methods, and it makes for very tidy and systematic coding, because one always knows where a field is initialized (in the lazy op), and it is efficient because resources are only allocated if and when needed. (One can even code with cascading lazy ops for real-time work and create an entire system by calling one lazy op up front.) If no client-side initializationis required these service accessors could also be completely in the Server_ implementation.

From an implementation point of view there is no compelling need to create an explicit Manage manage_ field, as manage() can always just return server(), although it does help to store a Manage interface during initialization. It is there primarily to ensure that the UML model can be easily wired up associatively on reverse.

For comparison, I did not create an explicit Serve serve_ field, so it is not directly wired up from the UMLfriendlierTest. How can one indicate that Dependency without changing the Java code to admit an associative interpretation on reverse ?  One could use virtual Dependencies again (by choosing the option to Create Dependencies between Classifiers on reverse in MagicDraw UML). Alternatively, UML2 specifies a special "ball and socket" notation for Classifier-level Dependency wiring of provided and required Interfaces, which we'll examine briefly next ..

Architectural "ball and socket" Dependency wiring

By drawing a Usage relationship from a Classifer that "requires" a service to an Interface that is "provided" as an InterfaceRealization from another Classifier one can create a Ball-and-Socket notation, which is a concise architectural notation for Classifier level diagrams (not to be confused in MagicDraw UML with the Lollipop-and-Fork notation for ports, available both in Classifier level diagrams and in composite structure diagrams).

In the example below the Interfaces Serve, Manage, and Factory have been "dependency wired" using Ball-and-Socket notation. Each Interface is provided exactly one and required exactly once, demonstrating a complete system.

While the InterfaceRealizations are automatically created on reversing Java (from the Classes that implement a given Interface), there is no facility when reverse engineering in MagicDraw UML to automatically create the Usage relationships (which are subject to architectural interpretation).Thus, if you are relying on reverse-engineering only, I advise you to create UML-friendly explicit Java fields to promote a graphical associative representation of these dependencies as end Properties of Associations to complement the "manual" Usage notation.

Custom forward-engineering suites and MDA system can however generate corresponding Java fields from Ball-and-Socket notation.

Port-based reverse-engineering and Java

It is possible to code Java so that it admits a port-based interpretation under reverse engineering to UML. One recipe is shown in this trail.

In PortServer_ services are only ever offered via associated port implementors - never directly - and services are accessed by service accessors which trigger lazy instantiation of the the port implementors (in this case Manage_ and Serve_). These implementors can be modelled as UML2 Ports. This recipe works particularly well when using Java inner classes as the Port implementors (which I've custom stereotyped with «port»).

From the point of view of clients to the services, the port-based class only ever reveals selected aspects through interfaces. This greatly reduces coupling to implementation, and promotes opportunities for substitutability of components.

The port-based Class PortServer_ shown below is inflexible, as it relies entirely on particular implementations to type its ports. For now the point is just to see how the graphical representation of Ports maps from Java fields, for which it is of little consequence whether the implementors are considered to relay to delegates, or whether they implement provided service Interfaces directly.

However the whole point of adopting port-based software engineering is to exploit the ability of the EncapsulatedClassifier to support highly reusable, substitutable components, by decoupling the specification of provided and required Interfaces from the provision of them via Ports. Later in this tutorial trail we'll see how to represent delegation and assembly Connectors with passed Java references and with resolution of abstract port creators, and how to create a truly replaceable, encapsulated abstract port-based class. The full port-based recipe is subtle, so for now we'll use the simpler PortServer_.

Let's now see how to convert the Properties manage_:Manage_ and serve_:Serve_ to UML Ports ..

Converting an end Property of an Association to an Attribute

If you have reverse-engineered your "port field" as the end Property of an Assocation (or if you've created an Association from an attribute) you have to convert it back to a true attribute before proceeding to convert it to a UML Port. Select the Association in a diagram (be careful to select the middle of the Association line, not the end lest you choose an end Property instead) then choose Convert to Attributes as shown below:

Converting an attribute Property to a Port

When a Property is represented as an attribute (however not as an end Property of an Association) it is possible to convert the Property to a Port (noting that a UML2 Port extends Property and enforces the condition that the AggregationKind is 'composite').  In the port-based server example here I show the interim step with the "port implementor" properties serve_:Server_ and manage_:Manage_ as attributes.

The next step shows how to convert these Properties to UML Ports in the model  ..

The Convert To Port menu item

The Convert To > Port menu item is available on attribute Properties (only).

Viewing Ports in or on a Class in a class diagram

There are two ways to view Ports in a Class lon a class diagram:

  • Deselect the context menu (or symbol properties) option: Presentation Options > Suppress Ports:
    • This shows the typed Ports in a list in a special compartmen (as shown below)
  • Select Related Elements > Display Ports and check the desired ports as offered in the dialog:
    • This displays the ports using "little box" notation on the boundary (see next pages)

Viewing Ports as "little square boxes" on the boundary of a Class in a Class diagram

You can also display Ports on a Class in Class diagram using "little square box notation" (one can in fact resize the box to any rectangular size) by choosing the context menu item Related Elements > Display Ports:

You can then select to display all or only particular ports in a checkbox selection dialog (see image below).


If you choose this representation please DO NOT attempt to connect the ports up externally in class diagram ! Connectors are instance-like (or Link-like) and have nothing to seek in a class diagram, except within the internal structure compartment of a Class. 



The next page shows the result for the port-based server example .. 

Port-based server in Class diagram with boundary

Here is a graphical port-based representation of the port-based server example in Class Diagram.

One can optionally choose to show the Type of the Port, or also to not show the name (often the Type is sufficient to indicate the role of a Port).

Note how the InterfaceRealizations to the provided Interfaces are automatically created.

If they are not present you can use Related Elements > Display Paths.

(If there is more than one InterfaceRealization or Usage to an Interface it is not an error, it is an indication that there is architectural redundancy in the Dependency Wiring.)



TIP: you can drag the "focus" Class Diagram of the Type of a Port onto it's port symbol to make it the default hyperlink target !

Representing Usage of Interfaces

From UML2.1.2 7.3.53 Usage (from Dependencies):

'A usage is a relationship in which one element requires another element (or set of elements) for its full implementation or operation. In the metamodel, a Usage is a Dependency in which the client requires the presence of the supplier.
..

The usage dependency does not specify how the client uses the supplier other than the fact that the supplier is used by the definition or implementation of the client.'

For the purposes of this tutorial a Java client Class will be considered to "use" an Interface if it as some stage it could call an Operation of that Interface

There are a number of ways that a Java client Class can be "provided" with a "required" Interface, including:

  • "injection" of the Interface via a Constructor or Setter (as shown below)
  • obtaining the Interface from a ServiceFactory as needed (where perhaps the ServiceFactory has been in turn injected).

Below I have reverse engineered a simple Java clent UsesServe. It uses Interface Serve to obtain a Thing, and because it is coded in a UML-friendly way it has explicit Java fields (rather than local variables) for Thing and Serve, so that on reverse to UML in MagicDraw UML we get matching Properties. I've also added a Usage to Serve by hand.

So where does the UML Usage come in ? In fact for a wide range of reverse-engineering cases like this it adds little value (other than to leverage the UML2 "Ball-and-Socket" Dependency Wiring notation. 

Let's see however what happens when we reverse engineer a Java client that uses a service "via" a Port ..

Client with usage Port class

Here is the first step in representing a Java client with a "usage Port", one that "requires" an Interface. I've reversed to attribute Properties only. 

Only the inner class Serve$ uses the Serve Interface directly, not the outer Class PortClient, which only ever calls Serve$.getNameOfNewThing().

Let's now see how this can be represented graphically .. 

migration to graphical usage Port representation

As an interim step I've converted the private attribute Property PortClient.serve$:Serve$ to a Port, and the attribute Property Serve$.serve_ to an end Property of an Association. Next the Type Serve$ will be removed from the diagram, leaving only the Port ..

PROBLEM: can't automatically wire-up usage Port to required Interface

The reverse-engineered end Property serve_:Serve of the Association from usage Port class Serve$ to Interface Serve can't be shown on this diagram, because it belongs to the Type of the Port serve$:Serve$, not to the Port itself. We therefore need to manually introduce a Usage, as shown next ..

Usage Port with manually created Usage relationship

Here I've manually created a Usage from a usage Port to its required Interface, to complete the "Ball-and-Socket" architectural Dependency Wiring.

At this stage, given that one has to introduce a manual Usage element, you may well be asking "why bother ?". There are a number of good reasons why you might like to persist with babysitting "Ball-and-Socket" notation in port-based diagrams this way, and why it is worth the fuss of coding usage ports in Java:

  • For smaller systems you can get away with relying on providing and requiring directly from a class, however it does not scale.
  • It is simply impossible to build substitutable EncapsulatedClassifiers (holons) without both providing and requiring ports:
    • We'll see this shortly in examples where more complex systems are built using composite structure diagrams
  • The more you structure your hand-written and reverse-engineered code around port-based engineering, the more you will understand and benefit from forward-engineering from models using the provide/required and Ball-and-Socket idioms 

Unfortunately, it is currently very difficult to interpret plain old Java as port and particular fields as Usages on reverse (however Java annotations could give a reverse engineering system hints). When forward-engineering from UML models it is possible to interpret Ports and Usage as desired and to generate code corresponding to the port-based design intention.

Review of some relationships indicating "usage"

I have applied the same procedure to create a usage Port manage$:Manage$ which requires the Interface Manage, as indicated by a Usage relationship.

The class Administrator uses Interface Manage indirectly - via the requiring Port typed by Manage$ - to set a Factory of some unspecified service provider to be a StrangeFactory_ implementation. In as sense it also "uses" the StrangeFactory_, and this is also indicated with a Usage relationship. One must take care not to confuse these usages of Usage (excuse the UML puns).

I have also shown the reverse-engineered Property manage_:Manage at the end of an Association from the requiring port class Manage$, which is yet another way to indicate usage (however it is NOT a UML Usage relationship).

We'll now see why it is important to indeed use the UML Usage from a requiring Port when building composite structures (leveraging the holon nature of EncapsulatedClassifiers) ...

 

Classifier-level Dependency Wiring of port-based systems

In MagicDraw UML Classifier-level Dependency Wiring is shown in Class Diagrams (or Implementation Diagrams) with "Ball-and-Socket" notation involving an InterfaceRealization and/or Usage relationship to an Interface (not to be confused with the "lollipop and fork" notation listing required and provided interfaces at a Port, which we'll review shortly).

Architectural Dependency Wiring shows which elements may be validly connected (as opposed to what elements are actually connected as shown in an instance-level Composite Structure).  I recommend that you create a Classifier-level Dependency Wiring diagram - as shown below - BEFORE you attempt to create a specific wiring of port-based elements in a Composite Structure Diagram (as shown next).

If you've already created the Usage relationships, and the InterfaceRealizations already exist from reverse engineering, you can simply "Dependency wire" the system by using Related Elements  > Display Ports from classes, Related Elements  > Display Related Elements from Ports to show provided and required Interfaces, and Related Elements  > Display Paths from Interfaces.



Visit also (in the Port-based UML engineering tutorial trail): 

Port-based Composite Structure Diagrams

In the diagram below I've created a usage context for port-based classes PortSystem_, PortClient, and Administrator and I've already used RelatedElements > Display Ports to show the ports on each Property typed by the port-based classes.

One can show what interfaces are provided and/or required by a Port of a Property from the context menu items for a Port as shown. This results in the "lollipop and fork" notation with a comma-separated list of the required or provided interfaces, as shown next .. 

Composite Structure Diagram with provided "lollipops" and required "forks" Interface notation

Unlike in the Classifier-level Dependency Wiring "Ball-and-Socket" notation, the instance-level "lollipop and fork" notation for provided and required interfaces does NOT show an editable Interface symbol (because an Interface is a Classifier).  It is information about the Port of a Property (and indeed if you click on a "lollipop" or "fork" it will open up into a Port spec dialog).

I've also include some Connectors manually, i.e. they aren't generated on reverse engineering the Java code. 

So what do UML connections correspond to in Java ? And how can we interpret them under reverse engineering ?

Next we'll see an interpretation in Java code of connecting these elements up .. 

Assembly connections as Java references to services

One interpretation of "assembly connection" in a Java system is the passing of a reference to a required service Interface.

This is illustrated in the following code, where references to the Manage and Serve Interfaces are obtained from the port-based PortServer_ (via an Interface PortServer) and passed to the port-based classes Administrator and PortClient on construction (in lazy instantiators), which in turn pass those references to their Ports' constructors. This approach combines well with cascading lazy instantiators, so that the entire creation and wiring up of the system is triggered in the top-level system constructor in advance (if desired) or as and when needed.


public class PortBasedComposite {

private PortServer_ server_;

@Lazy
protected PortServer server() {
if (server_==null) {
server_ = new PortServer_();
}
return server_;
}

private PortClient client_;

@Lazy
protected PortClient client() {
if (client_==null) {
client_ = new PortClient(server().serve()); //connect !
client_.printNameOfThing();
}
return client_;
}

private Administrator administrator_;

@Lazy
protected Administrator administrator() {
if (administrator_==null) {
administrator_ = new Administrator(server().manage()); //connect !
}
return administrator_;
}

public PortBasedComposite () {
administrator();
client();
}

public static void main(String[] args) {
new PortBasedComposite();
}
}


There are however some problems with this naive strategy:

  • A UML Interface does not have Ports, so a symbol of a Property typed by Interface PortServer in a composite structure diagram can't show Ports; the server with ports is not well encapsulated.
  • The Ports of the port-based classes seem to be bound to particular implementations of provided and required Interfaces.
  • While the "Connector as reference" approach works ok for simple Ports that provide 1 Interface, it turns out that it does not scale well to complex Ports.

What is needed is a better abstraction of the port-based contract than is possible with a UML Interface, as well as abstract Port implementors that define only what Interfaces are required and provided, without stating where or how they are required and provided, so that they can be flexibly delegated to different internal parts with Ports.  For this purpose a new example and some useful terms and definitions will be introduced ..

ADVANCED TOPIC: The "Portface" recipe for encapsulated port-based Java engineering in UML2

This tutorial trail introduces a recipe for port-based software engineering I have developed and refined over a number of years, and especially while working for the Australian Nuclear Science and Technology Organisations (ANSTO) on scientific instrument modelling in UML and SysML for Java. It is applicable to a wide range of software and systems engineering tasks, including real-time synthesis systems (we'll be building a simple one here, too).

The recipe is subtle, and applying it "by hand" in Java code so that is reverses well to UML2 requires some effort and discipline, however the rewards are compelling, because it leads to truly encapsulated software systems with well-defined port-based contracts and substitutability, which criteria are the bread-and-butter of electronics and mechatronics, yet they have remained an elusive "holy grail" of software engineering, with its infamously highly coupled systems.

It can be used to integrate existing classes that implement interfaces directly into a purely port-based system, by assigning those classes (if needed wrapped) as implementations of services provided by well-defined abstract ports. This provides a powerful, relatively non-invasive technique for refactoring existing systems and migrating them to port-based technology with a UML2-based graphical interpretation.

The recipe (as applied to reverse engineering) is unfortunately compromised by the following two major limitations:

  1. Because the UML2 Interface does not support Ports, one has to use instead an abstract "Portface" Class to represent the port-based contract, which consumes the one direct inheritance path allowed in Java (however it will be seen that in many cases such "vertical" inheritance can be better achieved anyway by "horizontal" aggregation, with services offered by Ports).
    • Note that this is less of a problem when forward engineering from a port-based UML2 model to Java.
  2. MD UML currently does not support provided/required Interface notation on Ports typed by <generic> (templated) Java classes, which is especially restrictive for signal processing applications, where ports can be parametrised by a signal type.

These limitations notwithstanding, the recipe is extremely useful, and studying it will hopefully help you to see your software systems in a new light. as well as providing insight into the UML2 provided/required port notation, and how to use Composite Structure Diagrams, Ports, and Connectors.

The recipe is supported by specific notation suited to port-based engineering in Java and UML2. If you've been reading my tutorials and wondering why I often place an underscore after class names like Serve_, and why I avoid the popular IServe "Eclipse-style" Interface notation, you are about to find out ..

The «portface» Class as abstract contract for a service provided by a Port

This diagram introduces the elements and notation for the simplest possible truly abstracted and encapsulated port-based service under my Java-friendly "Portface" recipe, tuned for MagicDraw UML.

A simple service Serve with an operation doServe() will appear to be provided by an abstract Server "Portface" Class via a Port serve_:Serve_, where Serve_ is an abstract «port» Class. The Server «portface» contract is implemented by the concrete Server_ Class, which creates - in its implementation of the abstract "hook" port creation method myServe_() - a concrete Serve__ implementation of the Serve_ «port» Class (which in turn promises to provide the Serve service Interface).

Easy, obvious, and no sneaky tricks, right ? Let's walk through it carefully to find out why, what, when and whether ..

Serve: is an Interface with no special characteristics. It could be any interface from an existing system. It is not named IServe "Eclipse-style", although it would not be deadly if it were. (We'll see soon that the use of 'I' as a prefix in front of every Interface quickly leads to pollution in the UML models, especially in the provided/required "lollipop/fork" notation, however you are free to use it if you wish.) Typically Serve would have a number of operations, which should be named as verbs like serve(), doServe(), serveFast(), serveSlow(), serveSecure() etc. Note that it is NOT named "Server" (which is rather the thing that owns the port that offers the service), and it is not a noun ! It is named after the "archetypal" verb action of the operations it provides, which ideally represent collectively a certain aspect of the system.

Serve_: is an abstract Class that promises to provide the Serve interface (eventually). It would be tempting to already implement doServe() in a concrete Serve_, however that makes it difficult to sensibly delegate from Ports typed by it, i.e. it would break the rules of substitutable encapsulation that we wish to achieve with port-based software engineering in the first place. Also, as we'll see shortly, implementing directly in a concrete Port does not scale well when dealing with complex ports that provide and/or require more than 1 Interface, so to keep the pattern consistent Serve_ has to be abstract. It will be called the abstract port implementor.

Server: is the abstract «portface» Class that defines the port contract. A clients will interact with a usage of Server via its public Ports, or alternatively via the service accessors (like serve()), that - after the pattern of the recipe - will return a serve_:Serve_ that is known to provide a Serve Interface.We'll explore as we go the difference between a client depending only on a specific Interface service (obtained via a service accessor operation, which is a BehavioralFeature ), and a client depending on a public Port (a StructuralFeature). In any case either the client has to have access to a Feature of the Server, or it has to be passed a reference from another player that "connects" the client to the Port (or possibly only to the Interface provided by the Port).

In the reversed UML model the Java field Serve_ serve_; appears as a Port serve_:Serve_ (noting that Port extends Property). The existence of serve_ is ensured by the abstract "hook" Server.myServe_(), which in the concrete implementation of the Server will typically trigger creation of a compatible port implementation, or will eventually return a delegate that meets the contract for the abstract port class Serve_.

So why - given that the provided Interface Serve can be accessed by public accessors like serve() on the parent Portface anyway - is the Port serve_:Serve_ public ? Doesn't that also break encapsulation ? Not if the Class typing the Port is abstract and if it does not offer any public methods other than those promised through the provided Interfaces. Because serve_:Serve_ is public it can be exported from the boundary of an internal :Server to the boundary of an external higher-order system.

Server_: is a concrete implementation of the abstract «portface» Server. Because this is a simple implementation (it will not delegate to ports of internal part Properties), in its implementation of the port creator myServe_() it will merely return an instance of its local concrete implementation Serve__ (note the double underline) of the abstract port class Serve_, keeping in mind that in general a «portface» Class might provide n services via m ports, so it implementations might have to offer (or fetch from factories) implementations of many Port types.

This case does not however require any Interfaces, it only provides a single Interface. Next we'll see how to handle required Interfaces as well ..

A service required via a Port of a «portface» Class

The abstract Manager «portface»  Class requires a service Help via a port manage_:Manage_, where Manage_ is an abstract «port»  Class that also provides a Manage service. The constructor of Manager invites injection of a Help Interface, which it then passes to the Manage_(help:Help) constructor on creation of its port manage_ via the port creation "hook" myManage(help:Help):Manage_ , which has a parameter for a Help. The abstract Manage_ stores the Help in a protected help_, which can then be accessed in the concrete implementation Manage__ of the abstract port Class Manage_.

As far as clients of a Manager are concerned there is only a service accessor manage():Manage; there is no need for clients to have access to or know about the existence of a Help within the Manager, nor how it is used.

Let's now combine the Server and the Manager to build a more complex system, ensuring that the Manager is given the required Help ..

More on port-based engineering in MagicDraw UML and MD SysML

Visit also these related tutorial trails to find out more about port-based engineering:

Why reverse ? Shouldn't I be forward engineering everything from UML these days ?

There are lots of good reasons why you might still code in Java (or another OO language) and "just" reverse engineer to UML, without full "round trip" engineering, including:

  • You don't yet command UML fully, and want to progressively move towards UML from your familiar programming code
  • You have a large amount of legacy code and you want to progressively migrate to UML-driven model-orientation (the UML models of which might then eventually form an initial input to a fresh "round trip" based development iteration).
  • You have scientific or mathematically oriented code that is not easily or sensibly generated using UML behaviors
  • You have to work with team members who are not UML fluent and will not accept a completely UML-driven approach

I highly recommend the following approach to get the best out of a "manual" reverse-engineering oriented approach (assuming your are not working with IDE Integration):

  • You don't have to spend the whole time looking at the UML; reverse frequently, and then plan your next "Java attack" with the UML diagrams in mind:
    • Consider printing (yes, on paper) your UML diagrams and then planning refactoring and migration with nice big thick wet coloured pens (yes, on paper), in a session away from your computer (over tea or coffee) before resuming Java coding to refactor your system.
    • Consider exporting selected diagrams to a folder as images to freeze a moment in your development:
      • I recommend reviewing frozen diagrams at meetings with colleages either printed or projected, rather than working with the MagicDraw UML application live, especially when managers and/or UML newbies are involved.
  •  be ashamed to spend good periods of time in your good ol' favourite IDE, let yourself get into your Java coding zone !
  • It is a good idea to conclude your work day performing UML reverse of changed code, diagramming,  and refactoring analysis without any Java coding, so that your mind finishes work in the graphical zone, and export selected diagrams to frozen images as a record.
  • It is a good idea to start your work day by reviewing frozen images of the previous days' work, then plan your refactoring in the MagicDraw UML tool (or with pen annotations on printed diagrams) before resuming Java coding.
  • DO use refactoring stereotypes to indicate common problems and to encapsulate repeating coding solutions: «! throw not null»
  • DO use Design Pattern stereotypes to promote architectural refactoring:  «!AbstractFactory», «!DependencyInjection»
  • DO have a graphical UML target diagram with or near you: in your mind's eye, in the MagicDraw UML application, as a frozen exported diagram image, on a whiteboard, or printed with refactoring annotations.
  • DO aim to achieve a cognitive balance between text-based coding and graphical UML modelling (left/right brain synergy)

HOWTO forward-engineer to Java from MagicDraw UML [INCUBATING]


HOWTO manage round-trip engineering from and to Java in MagicDraw UML [INCUBATING]


HOWTO use IDE integrations in MagicDraw [INCUBATING]

Visit also the MagicDraw UML Integrations UserGuide in our MagicDraw UML distribution:

/manual/MagicDraw Integrations UserGuide.pdf

You DO NOT have to use full integration with your IDE to work effectively, consider also just working with frequent reverse of code to UML.

HOWTO use the MagicDraw UML Open API [INCUBATING]

Before starting this tutorial you should study first (or at least have at hand) the MagicDraw OpenAPI UserGuide from your distribution:

/manual/MagicDraw OpenAPI UserGuide.pdf



One the most powerful aspects of MagicDraw UML is the ability to create custom Plugins against the Java Open API. In this tutorial we examine a trivial plugin with a few menus and actions, all with synced UML models from reverse-engineering of Java code of course. You can also inspect reverse engineerings of selected elements from the Open API interface.

 

The Bragg Institute Instrument ModelServer and ModelClient [INCUBATING]

In this tutorial trail you will learn about Java and XML engineering in MagicDraw UML from functioning examples taken from Dr Darren's  Intrument ModelServer system for modelling, control, simulation, and
animation of scientific instruments.

The Instrument ModelServer system and related ModelClients were developed for the
Australian Nuclear Science and Technology Organisation (ANSTO). It is the result of over one decade's development, application, and teaching. It
includes:

COMING VERY SOON !