Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Concepts for Simpler Design


June 1999: Features: Concepts for Simpler Design

Today’s complex object systems continually benefit from the new features in object-oriented analysis and design tools and methodologies. According to a Gartner Group report in June 1998, object-oriented analysis and design tools are expected to grow 30% to 35% per year through 2000. Although these tools get better with each release, there are still major functionality gaps such as mapping business-model detail to design diagrams.

Currently, all comprehensive architecture models, such as Philippe Kruchten’s 4+1 view architecture model (“The 4+1 View Model Architecture,” IEEE Spectrum, Nov. 1995), include mapping subsystems to object models. But, they do not address how to map these subsystems in an easily repeatable way, especially for large, object-oriented applications. As you’ll see, this is where packages and class categories can help you.

In object modeling, the combined approach of two methods—UML packages described in Pierre-Alain Muller’s Inside UML (Wrox Press, 1997), and generic class categories described in Bertrand Meyer’s Object-Oriented Software Construction (Prentice Hall, 1997)—help simplify the transition of mapping business models to diagrams. Understanding these concepts can also help you find your way around an existing large, class hierarchy by grouping the design activities.

Current architecture models and textbooks of popular methodologies don’t clearly describe how to combine these two methods efficiently. The evolving versions of UML have further confused the terminology and relationship of “categories” and “packages.” The concepts behind categories and packages are not difficult; in fact, they are complementary to current concepts like frameworks, analysis patterns, design patterns, and reusable class libraries. In this article, I’ll highlight different techniques for working with them and show how you can build object models of complex applications systematically with less effort.

Packages—The Concept

In UML, packages represent a “model management area” of an application. They are basically mechanisms to partition a system into subsystems based on the designer’s criteria. This helps you understand and focus on a large application’s architecture without getting into detailed levels of classes and objects. Packages have the benefit of a classic “divide and conquer” strategy in object-oriented software design. Without them, designing and coding for large projects can be messy and risky.

It is important to realize that you only create packages to identify the classes needed in that object-oriented subsystem. Your goal is obviously not to create an architecture that captures processes in an old-fashioned coding style.

What warrants creating a new package? What type of criteria should you use? How do packages interact with each other? These questions ultimately affect your design’s quality and implementation.

Packages cover either the problem global space (external environment) or the solution global space (internal environment). Most designers work on the problem space first and then move to solution space. The criteria you use to create packages depends on the type of “space” you focus on. The packages in the problem space (domain packages) are primarily responsible for simulating the functions of “business processes.” The packages in solution space, on the other hand, support the solution details in these user functions that you can code internally or customize from third-party vendors.

Packages communicate with each other either locally or remotely. Their communication method and where they reside is the focus of application architecture, which is beyond the scope of this article. The use of object brokers is one example of how packages can interact over networks.

Packages can contain other packages and have dependencies. Eventually, a package will contain many classes to implement that subsystem’s logic. A dependency relationship between two packages indicates that at least one class in package A uses the services offered by at least one class in package B. For example, the object model components—a technique Peter Coad suggests for starting an object model in Object Models: Strategies, Patterns and Applications (Yourdon Press, 1997)—includes problem domain, data management, user interface interaction, and system interaction (between domain objects and other systems). Since these categories help you identify the high-level subsystems within a system, they represent different packages. As shown in Figure 1, a problem domain, such as an order management system (with dependencies on data access and communications), can have other subpackages like credit check, address validation, product check, and order entry processes.

Figure 1: A Problem Domain Containing Subpackages

According to Craig Larman’s Applying UML and Patterns (Prentice Hall, 1998), unless multiple teams can work simultaneously on different packages (basically those mentioned in object model components), you should create user interface and domain packages first since a higher uncertainty is associated with those subsystems.

The terms “packages” and “categories” have been revised in newer versions of the UML. Previously, UML 0.8 contained “category” and “subsystem” concepts. However, UML 0.9 replaced categories and subsystems with an all-purpose construct called “package.” And finally, UML 1.0 abandoned categories all together. For modeling object-oriented systems, packages are about subsystems. The class categories, on the other hand, are about the types of classes built for a specific design purpose.

Packages with Class Categories

A class category is the architectural grouping of classes that share a similar design purpose in the application’s object model. To clearly demonstrate the design principles of classes within a subsystem, you need to see an object model based on class categories.

According to Bertrand Meyer, there are three major generic class categories in any application’s object model. These are analysis, design, and implementation classes. The path between packages and class categories is clear. While packages are the source of the logical view of an application, class categories are the source of the logical view of an object model. Figure 2 shows this complementary relationship.

Figure 2: Relationship Between the Logical View of an Application and the Logical View of an Object Model

A brief example might help you see the differences between the three class categories. Consider what’s involved in building a house. First, you must decide the types of space in the house, such as rooms, bathrooms, and a two-car garage. This is similar to identifying analysis classes. Likewise, creating a floor plan to maximize the house’s efficiency is analogous to constructing design classes. And finally, deciding what type of carpet, windows, or doors to use is similar to creating implementation classes. Taking this example further, building the house according to county regulations and federal laws is like including “enterprise- and global-level classes” to your design.

Class Category Characteristics

The classes in an application belong to either an external or an internal system. The external system represents the application’s domain area (such as order processing or accounting), while the internal system focuses on the application’s efficiency, performance, reusability, and maintenance. As shown in Figure 3, some class categories belong to both an external and an internal system. Therefore, class categories are related to their domain coverage.

Figure 3: Relationship of Class Categories to Their Domain Coverage

You can discover class categories using several techniques. This is an important point because it helps you focus on the classes’ architectural purpose in the application. For example, employing use cases would help identify the domain’s analysis classes, not necessarily its design classes. Identifying design classes requires a different approach, which I’ll explain later.

Analysis Classes

You create analysis classes out of the core problem domain to satisfy the processes captured in the corresponding packages. These classes become apparent during the project’s analysis phase when users begin to talk about their environment. They are easier to identify than design classes because they are frequently spoken of and generally understood.

Ivar Jacobson’s entity objects (Object-Oriented Software Engineering, ACM Press, 1992) belong to this class category. The entity objects are those in which the information is usually persistent (held over from a use case). An example of analysis classes in the order entry package may include customer, product, order header, and order detail classes. If multiple packages need to use the same class, you should update the class to satisfy other requirements.

One way to find analysis classes is by concentrating on the most important responsibilities of the system and creating use cases for them. Each instance of the use case would represent a valid business scenario. Therefore, you should be careful to distinguish a use case from a scenario to minimize the number of valid use cases. Prioritizing these use cases will reveal areas that you must focus on to uncover analysis classes. Once you identify candidate analysis classes, you can revise or change them later as necessary. What is a good analysis class in one context, may not be in another context. It depends on the class’s responsibilities in the current domain.

You can use Rebecca Wirfs-Brock’s CRC (class responsibility collaboration) technique (Designing Object-Oriented Software, Prentice Hall, 1990) to record these initial analysis classes and their responsibilities. CRC cards are small index cards with class names that you and your team can examine and refine quickly by passing them around. As the number of classes increases, the cards become cumbersome and you’ll need to switch to a notation like UML. Nevertheless, the cards provide a simple way to start recording the first analysis classes covering important use cases.

While use cases are a way of capturing a business process, analysis classes help build the structures of the business process, also known as analysis patterns (Analysis Patterns by Martin Fowler, Addison-Wesley, 1997). In other words, analysis patterns identify the relationship between the analysis classes in the use cases, and describe parts of the domain. Figure 4 shows an analysis pattern for an order in an order management system in UML notation. It captures a simple order structure in which order headers and lines make up the electronic or non-electronic orders.

Figure 4: Example of an Analysis Pattern in UML Notation

So-called “business frameworks” (as shown in Figure 3) are actually a combination of analysis patterns (for the domain) and some design patterns (for the software implementation of the domain). Since the goal of frameworks is to provide a plan-of-attack that lets you reuse code and design, frameworks include the most commonly used domain objects with basic interactions. Unfortunately, reusable frameworks are still mostly a promise. Since systems by different vendors are usually not built to interface with each other, the interoperability of applications, and therefore, their reusability, is weakened.

Design Classes

You create design classes after you identify the most obvious analysis classes. Their main purpose is to make the system more programmable and easier to reuse with minimal code change. You create design classes that focus less on domain than organizing class structures for maintenance and clarity. The design principles behind the class structures can come from various sources, such as past experience, published works, or training. They are not about programming tricks.

An abstract design class pushes details down a level so that changing details will not necessitate updating most of the code. It hides complexity and enforces high-level policies. An abstract design class can provide the same interface to its subclasses. This helps reduce maintenance when the application is just linked to the interface, rather than fully implemented. It is estimated that abstract design classes make up to 10% to 15% of the application. Although there is a direct correlation between a class’s abstraction and its inflexibility, coding to the abstract interface makes the system more stable.

A “non-abstract” design class can also make maintenance easier; for example, a class that benefits from composition instead of inheritance. That way, any change in the parent’s implementation will not force a change in a subclass and responsibilities will be equally distributed among other classes.

Another example of a design class is Ivar Jacobson’s control objects concept. The processes identified in the packages that must act on multiple entity objects are good candidates for control objects. The control objects are responsible for communication between entity and interface (user or system) objects of the system to isolate interface changes from domain rules.

As I said earlier, it is harder to identify design classes than analysis classes. This is because design classes must rise above existing classes to search for the commonality and identify places where future changes are most likely to occur. This type of information is not readily available from the customer. Most of it is solely the result of an architectural effort that focuses on reusability, maintenance, and clarity.

You use different techniques to identify design classes than you do for analysis classes. With design classes, you focus more internally than externally. This is not to say you completely ignore the external domain entities at this point. It basically means you must be more concerned about issues such as reuse, maintenance, and efficiency of the application. Therefore, you must look for ways to classify your initial classes into generalized entities, such as devices, roles, organizations, forms, reports, locations, processes, and so on. While there is no sure way to find design classes, you should create design classes by anticipating changes. This will reveal the places in the application where, for example, coding to the interface of a base class is better.

While identifying design classes, you could form the basis for a design pattern. Design patterns are reusable design techniques that you can apply to conceptually similar situations in different applications. Luckily, there now appears to be more information about design patterns than reusable business frameworks. Therefore, another way to develop this skill is by studying well-known works on proven design patterns, such as Design Patterns: Elements of Reusable Object-Oriented Software by Erich Gamma, et al. (Addison-Wesley, 1994).

Implementation Classes

The implementation classes are basically the low-level classes needed to support the internal infrastructure of an application. Even though they do not represent any domain entities, implementation classes provide the necessary functions that let domain objects build on them. The functions include sorting or searching algorithms, database access methods, synchronization and threading support, and graphical functions.

Since this support is needed in most applications, implementation classes exist as either class libraries, components, or application frameworks from multiple software vendors. They help domain classes accomplish their tasks efficiently. Implementation classes enjoy the highest reuse among the class categories presented here.

Since they are mostly available from the tool vendors, you usually don’t have to recreate them unless you must for reasons such as specific functionality, portability, or performance. Nevertheless, you must know the strengths and limitations of implementation classes to successfully incorporate them into your designs.

Putting It All Together

Now that you understand packages and class categories, I’ll explain how you can use them together to create an object model. Here are the basic steps to this approach:

Requirements Phase

• Create use case diagrams for the domain.

• Prioritize use cases.

Analysis Phase

Static Model (Class Design):

• Partition domain into packages and subpackages (related use cases).

• Identify analysis classes for each use case in a subpackage.

• Create class diagram.

Design Phase

Dynamic Model (Class Interaction Design):

• Create interaction diagrams.

• Identify design classes in packages and subpackages.

• Revise class diagram.

Functional Model (Class Implementation Design):

• Identify the implementation classes you need for each class to function.

• Refine the implementation classes.

As you can see, compiling and prioritizing use cases takes place in the requirement definition phase. Since these use cases are the starting point of your class design, they should describe the processes at a high level with less detail.

In the analysis phase, you organize use cases based on domain area and identify most of your domain’s analysis classes. To create an object model for large and complex applications, you first break the problem space into multiple domain packages and subpackages. Since a domain package is like a set of related use cases for that subsystem, it’s useful to partition them for design purposes. This is especially helpful in large projects where a large number of use cases exist. Therefore, you can organize use cases in multiple domain subpackages. This is important since you can iteratively build your object model’s first version, one use case at a time after you prioritize them. The details of use cases should still be documented in use case diagrams with actors. You mainly use domain packages to organize them. The goal of this phase is to end up with an initial class diagram. Since this is a rather static view of the system, it will be a part of the static model (sometimes called conceptual model). At the end of the analysis phase, you will form the domain-specific analysis classes (with their basic attributes and associations).

Once you find the initial analysis classes for the domain, you can concentrate on the interactions between the classes in the dynamic model. You can document these interactions in collaboration, state, and sequence diagrams. At this stage, you further assign responsibilities (operations) of the classes. During this effort, the true design classes (abstract or non-abstract) are born, either by refining existing classes or creating new ones. They are identified by factoring out commonality, anticipating future changes, and using design patterns. As I explained previously, these classes are supposed to make your model easily extensible later with less effort. Unfortunately, although creating a dynamic model is one of the most important tasks, it is usually underestimated in the design process.

On the other hand, the functional model section of the design phase starts when you focus on the support for your classes’ and application’s internal needs. At this stage, the implementation classes become more evident. These include lower-level functions such as stacks, search algorithms, distributed communication methods, remote database access, and operating-system or language- specific features.

To summarize, you can partition your system and objects by using packages and class categories. Multiple packages (such as problem domain, data management, user interface interaction, and system interaction) separate application logic from presentation and technical details. Organizing the problem domain by the related use cases makes managing the domain easier. Further, each type of class category fits into different modeling efforts (static, dynamic, and functional). As your design progresses, you can easily identify the type of classes expected from each model.

Avoiding Analysis Paralysis

Using packages and class categories during the design process is a very effective and practical approach for managing an application’s objects. Packages and class categories have complementary strengths and allow an iterative process for the design of an object model, thus helping you avoid analysis paralysis. Each approach addresses a necessary and unique type of effort. While organizing a system in packages indicates “what” each subsystem must achieve, thinking in terms of class categories helps address the “who and how” in an object-oriented design.

Software development is risky business. Understanding the requirements and creating a formal design are solid ways of reducing that risk. You can use the package and class category techniques discussed here as building blocks for a strong object-oriented modeling foundation. They are invaluable tools when working on mission-critical, complex, object-oriented projects.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.