A package is a grouping of UML elements, which can include diagrams and may include subordinate packages and other kinds of model elements. According to the UML Specification, packages "can be used for organizing elements for any purpose; the criteria to use for grouping elements together into one package are not defined within UML" (Rational Software Corporation 1999). Packages are probably the most important aspect of the UML from a modeling perspective; they play a role in UML modeling that is similar to the role classes play in programming.
Most UML books treat packages lightly. Because of their importance and this lack of attention elsewhere, I'll provide more details on them here than I will for the other UML symbols and artifacts.
Packages can be nested and can reference other packages. They provide the basis for configuration control, storage, and access control. They also provide the basis for naming model elements. They define the namespace for model elements; nested packages create a naming hierarchy. Because packages can't be instantiated, nominally their only formal function (in a system) is to provide this name space.
Each element in a package must be uniquely named. Elements in different packages may have the same name, but they are differentiated by the package name as an additional identifier. This capability becomes significant with components, with reuse, and as systems grows larger. A name collision between components can be resolved by placing them into separate packages and referencing their fully qualified name:
Individual packages own model elements directly; an element can belong only to one package. If the owning package is removed from the model, the owned model elements are removed as well. A package is "the basic unit of development productsomething you can separately create, maintain, deliver, sell, update, assign to a team and generally manage as a unit" (D'Souza and Wills 1998, 285).
Elements contained in the same package can be related, and can be related to elements in a containing package at any level. Elements in contained packages are not visible; "packages do not see inwards," as the UML Specification puts it (Rational Software Corporation 1999). Elements in other packages (contained or separate) can be made available by importing or accessing the package(s) or by generalization.
Packages can import or access the contents of other packages. When one package imports another, it imports all those elements that are visible in the second package. Imported elements become part of the importing package's namespace (that is, they can be referenced without the qualification of a pathname), and may be used in relationships owned by the package. An access relationship keeps the namespaces separate, requiring that the accessing package reference elements in the accessed package use fully qualified names (ones that include the pathname). Packages can also "specialize" other packages in a generalization relationship that parallels inheritance among classes.
Containment and visibility are key characteristics of model elements in packages. Packages encapsulate the model elements they contain and define their visibility as private, protected, or public:
PrivateElements that are not available at all outside the containing package
ProtectedElements that are available only to packages with generalizations to the package owning the elements
PublicElements that are available also to importing and accessing packages (see the following sections)
Package visibility is a variation on the standard approach that the UML provides for the visibility of model elements. Martin Fowler rightly cautions against using the UML's standard version of visibility too glibly because it is a mishmash of compromises that don't necessarily correspond to the way visibility is used in your programming language. For object-oriented development, he suggests relying on the flavor of visibility supported by the language you're using (1997, 99). For component-based development, on the other hand, especially where packages form the basis for working with components (as in D'Souza and Wills' book), UML package visibilities are a critical tool. For components, UML visibility is a significant modeling concern, not just one that has a transitive interest, as a reflection of programming concerns. See Objects, Components and Frameworks with UML: The Catalysis Approach for an example (D' Souza and Wills 1998, 259296).
Although package can be mapped to programming constructs, the UML version is far richer and more nuanced than any of the available programmatic translations. It is the core-modeling concept that distinguishes the UML from previous programming-oriented modeling approaches. Reflecting its importance, the idea of a package has undergone significant shifts during the brief life of the UML, contributing to user confusion.
UML 0.8 did not include packages; instead, category and subsystem provided logical and physical organizing mechanisms. UML 0.9 combined categories and subsystems into an all-purpose construct called package, initially limited to grouping classes. With UML Specification, Version 1.3, packages can be used to group a much broader range of model elements. It seems likely that package, as a modeling construct, will continue to be refined and refactored, especially given its utility in managing the complexity of components.
The downside of all this is that the literature on the UML varies in its treatment of packages, depending on the vintage of the UML Specification being referenced. However, the evolving notion of a package and its evolving usage is probably a key to understanding the changing environment of modeling (and development), and it is a key to the success of the UML in the post-object- oriented world of systems development.
3.2.1 Models: Packages of Views
Models are one type of package explicitly identified in the UML metamodel. Therefore, it is a good example of how to use packages. Conceptually, packages provide a way of organizing models that is analogous to a hierarchic directory structure of folders and files.
With the UML, the process you use (and the toolset) will dictate the structure you use to organize your models. Generally, a single top-level package provides the starting point for a hierarchy of views and models (organized in packages and expressed as diagrams). Rational's Rose CASE tool is organized this way, but its approach is at best a useful convention that reflects the RUP. D'Souza and Wills' book incorporates a more imaginative approach that leverages packaging to the hilt, based on factoring the system in a variety of ways (1998). These can accord with the categories of user, express the different architectural layers in a system, contain the rules that constitute a system's architectural style, hold the patterns that drive the design, and provide the means of organizing work and configuring the work products.
3.2.2 Subsystems: Packages of Behavior and Operations
Subsystems are the other type of package explicitly identified in the UML metamodel. Subsystems decompose systems, whereas models partition the logical abstractions that describe a system. Models should be "nearly independent," whereas each subsystem should be independent and completethere should be a minimum of coupling between the parts of different subsystems.
The notion of subsystems that has been incorporated in the 1.3 version of the UML Specification has an enhanced flavor that hints at a cross between model and class. A subsystem is no longer a collection of modules or classes as it was for Grady Booch in Object-Oriented Analysis and Design with Applications (1994, 221) or Ivar Jacobson in Object-Oriented Software Engineering (1994, 148). Now, a subsystem is a means of representing "a behavioral unit in the physical system" and a collection of model elements. It is fundamentally a way of partitioning the system-to-be-implemented, and so is more physical than logical or conceptual. Although it is a chunking mechanism like a model, at its simplest it is meant to address the organization of executables and production artifacts rather than ideas.
A model can be divided into subsystems; subsystems can include one or more models. Conceptually, the whole physical system is represented at the top level by a single model. This model can then be subdivided as needed to suit the purposes of the modeling exercise. Ordinary subordinate models that are packaged as models are logical conveniences. Subsystems are miniature systems themselves, ones that do not overlap. In the course of development, as the focus of modeling shifts towards construction and the physical architecture becomes stabilized, subsystems provide a way of organizing work products that can be translated into real physical implementations.
A subsystem inherits all the naming, access, and dependency properties of a package. However, like a class and unlike a model, a subsystem provides interfaces and has operations. Its contents can be separated into specification and realization subsets:
SpecificationOperations and/or features, together with such elements as use cases and state machines
RealizationIdentifies those elements that physically implement the specification
Subsystems are one of those areas in the UML that are notably inconsistent and muddy. For example, on page 2-180, the UML Specification declares that a subsystem "may or may not be instantiable." On page 2-181, however, it says that subsystems "cannot be instantiated" while declaring that an instantiable subsystem has some of the semantics of a composite class, whereas one that is not instantiable has the semantics of a package (Rational Software Corporation 1999).
Subsystems are probably going to become much clearer when the next major revision happens. Meanwhile, the importance of subsystems is very much a matter of the process that you're using. The RUP relies on subsystems heavily; for D'Souza and Wills' book, they're mostly a convenient way to package infrastructural services.
3.2.3 Frameworks: Packages of Patterns
A framework can also be expressed by using a package, one "consisting mainly of patterns, where patterns are defined as template collaborations" (Rational Software Corporation 1999, 2-174). The generic package acts as a template with some elements parameterized (that is, acting as placeholders for elements in what amounts to a software pattern) such as the Gang of Four patterns or Martin Fowler's analysis patterns.
Although not high-profile members of the UML (that is, they don't have a specification as a separate ModelElement, such as Model and Subsystem), frameworks are the third legitimate use for packages.
D'Souza and Wills' book uses frameworks as a way of providing a consistent mechanism for organizing and reusing model elements across all stages of development (1998). An implementation model can be composed of code frameworks that reflect the frameworks that emerged in the analysis model and were refined in the design model. Seeing components as collaborations and systems as collaborations between components makes the use of patterns that are instantiated as frameworks an effective alternative to the models-and-subsystems approach of traditional object-oriented design.
In the same way that packages have evolved from groupings of classes, in D'Souza and Wills' book, a framework provides a more refined means of using patterns, especially as a way of enhancing reuse. Although collaboration remains the core of patterns and frameworks in D'Souza and Wills' book, catalysis frameworks go beyond the simplistic understanding of patterns as a collaboration between objects that underlies the way patterns are currently embodied in the UML (1998).