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.
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.
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:
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.)
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:
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.
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 ...
Although it describes a Round Trip Set we will only be using the set for reverse engineering.
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.
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.
Heed the warning before proceeding:
At first you will be presented with the default reverse options, as shown.. We wil be fine tuning this options before proceeding:
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.
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).
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:
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.
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 ..
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.
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.
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):
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 !
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.
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.
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 ...
To avoid errors I recommend you copy the Class name from the symbol first then paste the name using the clipboard
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 !
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.
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.
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).
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 ..
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.)
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.
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).
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:
In the following we will only explore suppliers for the "focus" class JavaDesktopAboutBox.
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 ..
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
}
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 ..
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 ...
Oops, the focus diagram for JavaDesktopAboutBox has now been polluted with attributes and operations from JDialog !
We can choose (at least) to:
Next we learn how to show only selected features using Edit Compartment ...
We now choose to display with Edit Compartment > Operations only those operations of JDialog inherited and used by JavaDesktopAboutBox
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 ...
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 ..
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.
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 ..
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 ...
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.
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 ..
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:
It also however brings with it some problems, which can discourage those used to purely text-based coding:
Next we see just some of the strategies which can help make dealing with associative diagrams easier ...
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.
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:
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 !
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 ..
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 ..
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:
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 ..
The Package Overview Diagram has been improved:
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 ..
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 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:
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 ..
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:
Below I have reversed the following class javavariables.HasArrays with variations on Java arrays:
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:
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 (‘*’).
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 ..
The class javavariables.HasCollections has some Java lists, sets, and maps:
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;
}
Let's see first what happens on reverse if we select the option to Resolve collection 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 ..
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 ..
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.
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:
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 ...
For this example when the Model Vizualiser dialog appears I choose the Package Dependency Diagram Wizard ..
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 ..
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.
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.
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:
Did it also detect the Dependencies from local variables ?
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) ?:
So it seems that the Analysis reverse option does not penetrate methods (although the method-based reverse for generating sequence diagrams can).
There are at least the following strategies for dealing with this situation to achieve a graphical UML model communicating this Dependency information:
Visit also:
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 ...
We'll just accept here the defaults for the name and location of the generated sequence diagram
We will accept the defaults provided by choosing to Reverse Implementation from the browser context menu of the operation factory() ..
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 ..
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.
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.
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.
The strange Package demonstrates the simplest possible form of Factory. It is used in javavariables.Main thus:
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 ..
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:
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" ...
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 ..
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 !
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 ...
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:
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() ..
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 ?
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 ..
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.
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 ..
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:
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 is available on attribute Properties (only).
There are two ways to view Ports in a Class lon 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.
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.)
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:
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 ..
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 ..
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 ..
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 ..
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:
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.
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) ...
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.
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 ..
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 ..
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:
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 ..
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:
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 ..
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 ..
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 ..
Visit also these related tutorial trails to find out more about port-based engineering:
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:
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):
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.
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
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 !