PACKAGE DIAGRAMS
 

pre-requisite knowledge:

 

http://homepage.eircom.net/~iandowney/dep040208.htm

 

and

 

1. broken line headed by open arrow: on class diagrams (& package diagrams) to mean dependency.
2. solid line headed by an enclosed white arrow:
on class diagrams (& package diagrams) to mean generalisation/sub-typing.

3. stereotypes: customised extensions to UML indicated by << some text >>. 

4. abstract: uninstantiable, i.e. there can be no instances of the thing (class of package) that's abstract.

 

Contents of this chapter:
 

0. The Idea of packages

1. Using Package Diagrams to track Dependencies

2. Dependency Shielding

3. Visibility

4. Superpackages

5. Global Packages

6. Where to put the package name?

7. Generalisation

8. Run-time Binding

9. The five-tier software model

11. An example of layered architecture taken from the field of Operating Systems.  
12. Package diagrams used to package use cases.  
 

Review Questions

 

0. The Idea of packages

 

Packages are a grouping mechanism used in systems design, that summarises what's going on at a lower level without necessarily showing the details.  They are most commonly used to represent groups of classes. 

 

1. Using Package Diagrams to track Dependencies

 

A package diagram shows packages of classes and the dependencies among them.  Dependencies among packages exist because of dependencies that exist among classes in different packages.  In other words dependencies among packages summarises dependencies among classes.  

 

A dependency exists between two elements if changes to the definition of one element may cause changes to the other.  With classes dependencies exist for various reasons: 

 

 

Only changes to a class’s interface should affect any other class.  It's the class's public features that can participate in the definition of its interface; private features can't.

 

The art of large scale design involves minimising dependencies.  Packages do not offer answers about how to reduce dependencies in your system but they do help you to see what the dependencies are and you can work to reduce dependencies only when you can see them. 

 

In the following figure:

 

 

 

we have domain classes that model the business, grouped into two packages:  Orders and Customers.  Both packages are part of an overall domain package.  The Order Capture application has dependencies with both domain packages.  The Order Capture UI has dependencies with the Order Capture application and the AWT.  (The AWT, incidentally stands for Abstract Windowing Toolkit and is a library of classes in Java that provides features, which together with the Swing package, provides the infrastructure for the user interface.)

 

A dependency between two packages exists if any dependency exists between any two classes in the package.  For example, if any class in the Mailing List package is dependent on any class in the Customers package, a dependency exists between their corresponding packages. 

 

2. Dependency Shielding

 

Look at the above diagram again.  If a class in the Orders package changes, this does not indicate that the Order Capture UI package needs to be changed.  It merely indicates that the Order Capture application package needs to be looked at to see if it changes.  Only if the Order Capture application package’s interface is altered does the Order Capture UI potentially need to change.  In this case, the Order Capture application is shielding the Order Capture UI from changes to Orders. 

 

If you have a chain of dependencies, then you know where to stop looking for consequential changes:

 

For example suppose:

 

M depends on L which depends on K which depends on J which depends on I which depends on H which depends on G which depends on F which depends on E which depends on D which depends on C which depends on B which depends on A

 

Let's now suppose that F changes.  G has to be looked at to see if it changes and only if it does, does H need to be looked at to see if it changes, and only if H changes do we have to even bother looking at I to see if it changes.  We might have to go right down the line as far as L or even M, if we're unlucky, but on the other hand we can stop looking down the line just as soon as we find one that doesn't change.  Now as far as E, D, C, B and A are concerned, we don't have to worry about them at all.  Nothing can happen to them as a consequence of a change to F.

 

Exercise: Illustrate the above example with a set of diagrams based on this one below; you'll add to box to the diagram to the right of B's box, and an arrow too, and so on, down to M.

 

 

3. Visibility

 

Classes within packages can be public, private or protected.  So, the Orders package is dependent on the public methods of the public classes in the Customers package.  If you alter a private method in the Customers package, none of the classes in the Orders package needs to change. 

 

A useful technique is to reduce the interface of the package by exporting (i.e. allowing access coming from outside of the package) only a small subset of the operations associated with the package’s public classes.  You can do this by designating all classes as localised to the package they're in so that they are known only to other classes in the same package, and by adding extra classes for the public behaviour.  These extra classes, called facades then delegate  to their shyer companions in the package. 

 

For more information on visibility in Java, whatever about other languages, please see:

http://en.wikibooks.org/wiki/Java_Programming/Access_Modifiers

 

4. Superpackages

 

The following diagram:

 

is a more complex package diagram that contains additional constructs that will be discussed below. 

 

There are eleven packages in this diagram.  There is also a Domain superpackage that contains the Orders and the Customers packages. 

 

In this case, we’ve shown that whereas the Order Capture application has a dependency to the entire Domain package, the Mailing List application is dependent only on the Customers package.  

 

Note that we could have left the domain package empty on the diagram, not letting anyone know what's in it.  Then in another diagram, we could show what the domain package contains.  If we had done this, then we'd have shown both the dependency arrows terminating with their arrow heads at the boundary of the domain package.  It's only because of the simplicity, in this case, of what's in the domain package that we nest, diagrammatically, its internal package structure within it.  Otherwise we'd have put it on a separate diagram.

 

What does it mean to draw a dependency to a package that contains subpackages?  In general, it means that the dependency summarises a lower-level dependency.  That is, there is some dependency to some element within the higher-level package, but you may need a more detailed diagram to see the details. 

 

5. Global Packages

 

The diagram above shows the Common package marked as <<global>>.  This means that many packages in the system have a dependency to Common.  Obviously, you should use this construct sparingly, but common classes, such as Range (see medical case study) or Money, or such like, may be used everywhere. 

 

6. Where to put the package name?

 

You can put the package name in the tab of the package symbol, or, if the main part of the package symbol itself is empty on the diagram, you can put it there.  Most of the packages above have their names in the main body of the package symbol.  Only the package called Common and the superpackage called Domain have the package name in the tab.  That's because something is shown as being contained within these packages. 

 

7. Generalisation

 

You can use generalisation within packages.  This means that the specific package must conform to the interface of the general package.  Therefore, in accordance with the diagram above, the Database Broker (i.e. the interface) can use either the Oracle Interface or the Sybase Interface.  When generalisation is used like this the general package may be marked as {abstract} to show that it merely defines an interface that is implemented by a more specific package. 

 

Generalisation implies a dependency from the subtype to the supertype.  You don’t need to show the extra dependency; the generalisation itself is enough.

 

8. Run-time Binding

 

The generalisation  referred to in section 7, allows us to put various load and save operations, into the database interface package.  There operations are then implemented by classes within the subtype packages.  At run time, it will be the subtype package that gets called by the domain.  But the domain thinks it is dealing only with the simpler database interface package.  Polymorphism is just as useful for packages as it is with classes. 

 

9. The five-tier software model

 

The five-tier application model.  We can easily carve up this diagram into tiers according to the five-tier model (described elsewhere on this web site - look and see!).  We can see that the top layer is the user interface layer.  Below that is the application layer, then the domain layer, followed by the data mapper and data base layer.  The data mapper package depends on both the domain layer and the database layer thus allowing the domain layer and the database layer to be independent of each other. 

 

To understand the idea of the data mapper layer in relation to the diagram above, imagine a package called Data Mapper between Domain and Data Interface such that dependencies are shown from that package both to Domain and Data Interface.  The dependency of Domain on Database Interface is now removed.  The Domain and Database Interface packages are now independent of each other.  It's the job of the Data Mapper package to reconcile them.  That's data mapper's purpose. 

 

10. Refactoring Existing Systems

 

In an existing system, dependencies can be worked out by looking at the classes.  This is a very useful task for an automated tool to perform.  This is handy if you’re trying to improve the structure of an existing system.  A useful early step is to divide the classes into packages and to analyse the dependencies among the packages.  Then you refactor to reduce dependencies. 

 

11. An example of layered architecture taken from the field of Operating Systems.  

 

A given version of Microsoft Windows can run with any set of PC hardware (subject to certain limitations, of course).  How is this possible?  The BIOS makes it so.   The BIOS is software, that lives in a ROM chip, on the computer's motherboard, and it depends on both the underlying hardware and also on the Windows Operating System, rendering the hardware and the Operating System independent of each other. 

 

12. Package diagrams used to package use cases.  
 

Package diagrams can also be used to package use cases.  Notice the use of the dependency arrow in this diagram.  (Note, too, in passing, a further use of the UML label symbol, used here to provide a title to the diagram in the top left corner.)

 

 

Review Questions

 

1. Why might one class be dependent on another?
2. How many classes in a system should be dependent on other classes?

3. How might one get a catalogue of all the dependencies in an existing system?

4. Can a dependency arrow terminate on the boundary of a superpackage or should it penetrate the boundary to land on the class(es) to which it bears a dependency? Discuss.

5. Do we need to use a broken arrow to show the dependency that a subclass has on a superclass?

6. Of what is <<global>> yet another example?

7. Complete the following "The art of large-scale design ....".
8. What are the UML single character symbols for (a) private, (b) public, (c) protected and (d) package?