You are on page 1of 150

The Rational Edge: e-zine for the Rational Community

Copyright IBM Corporation 2004.

Page 1 of 1
http://www-106.ibm.com/developerworks/rational/rationaledge/

Search for:

within

All of dW

Search help
IBM home
developerWorks

About IBM

>

Rational

| Products & services | Support & downloads | My account

>

| Privacy | Terms of use | Contact

The Rational Edge--July 2004

7/15/2004

The Rational Edge: Issue contents

Page 1 of 2

Copyright IBM Corporation 2004.

Search for:

within

All of dW

Search help
IBM home
developerWorks

>

Rational

| Products & services | Support & downloads | My account

>

Issue contents

issue contents

Editor's notes July 2004

archives

Have you ever wondered about the relationship between the creation of use cases and the
creation of code? In good development practice (not just in theory), use cases guide
development teams directly into the coding process. Although there are many steps to this
transformation, Gary K. Evans's puts us on a clear path that begins with writing solid use
cases, which leads to better analysis, then design, and finally coding. Part 1 concludes with
the analysis portion. Next month, we will complete the journey.
And you'll find much more this month in the list of contents below.
Happy iterations,
Mike Perrow
Editor-in-Chief
Features
z Getting from use cases to code
Part 1: Use case analysis
by Gary Evans
The first in a two-part series, this article
presents a case study that analyzes the
requirements captured in use cases and
transforms them into implementable
representations that can be directly coded.
z

Writing good requirements is a lot like


writing good code
by Jim Heumann
By employing many of the same principles
and concepts they already use to write
code, developers can effectively serve as
requirements engineers. This article
reviews those principles and explains how
to apply them to create good requirements.
The IBM Software Development
Platform partner ecosystem
by Peter Stolinsky
A rich ecosystem of hundreds of IBM
partners extends the IBM Software
Development Platform, delivering products
and services that span the entire

subscribe

submit an article

contact us

Entire issue in .pdf

Teams and projects


z Enhancing RUP for CMMI compliance: A
methodological approach
by Walcelio Melo
This paper traces the approach Unisys GPS
Blueprinting used to evaluate the Rational
Unified Process in support of the Unisys
Business Blueprint, a business and systems
modeling architecture that integrates
business vision and IT execution to drive
organizational agility.
z

RUP iteration planning


by Anthony Crain
This article traces the steps required to plan
sequential software project iterations while
following the IBM Rational Unified Process.
The author illustrates RUP templates and
associated workflows in order to produce a
plan relevant to the essential RUP
disciplines.

RUP work components


by Kirti Vaidya
This article discusses the concept of work
components, which encapsulate work done
to achieve individual objectives. In the

Download the
entire issue in .pdf
(1.0 MB)

The Rational Edge--July 2004

7/15/2004

The Rational Edge: Issue contents

Page 2 of 2

application development lifecycle and


address both horizontal and domainspecific business needs. This article
describes that ecosystem and its value to
IBM clients.
z

context of IBM Rational Unified Process, or


RUP, we can think of a work component as
a higher-order workflow detail that is
tangible to the stakeholders and has one
objective, one owner, and one result. We
will define work components and examine
their structure and realization. We will also
explore how to use work components to
build and review RUP plans, develop
organization-wide work components, and
estimate a project in terms of work
components.

New whitepaper! Bridging the chasm


between development and operations
A new whitepaper exploring deployment
challenges and how to bridge the gap
between software builds and deployments.

Theory and practice


z

Formally speaking: How to apply OCL


by Gary Pollice
This article discusses various uses of OCL
(Object Constraint Language) for both
developers and testers. IT also enumerates
the many advantages of the language,
which is part of the UML specification.

Rational reader
z Book review: Eric Meyer on CSS:
Mastering the Language of Web Design
by Eric A. Meyer
Reviewed by Kerry McKay
McKay reviews a book designed for
experienced HTML users who want to
improve their Web design capabilities.
Using a project-oriented approach, the book
takes readers step by step through ways of
applying cascading style sheet (CSS)
techniques for purposes ranging from online
greeting cards to input forms.
z

About IBM

Book excerpt: Absolute Java


"Arrays (Chapter 6*)
by Walter Savitch
From a new introductory book on Java
designed for both novice and experienced
programmers, this chapter covers arrays
and references, programming with arrays,
and multidimensional arrays.

| Privacy | Terms of use | Contact

7/15/2004

Copyright IBM Corporation 2004.

http://www-106.ibm.com/developerworks/rational/library/5383.html
Search for:

within
Search help

IBM home
developerWorks

Products & services

Support & downloads

My account

> Rational

Getting from use cases to code Part 1: Use-Case Analysis


Contents:
Use-Case Analysis activity

Gary Evans
Independent Object Technology Evangelist, Evanetics
13 Jul 2004

Example use case


Use-Case Analysis step 1: Create a use-case realization
Use-Case Analysis step 2: Supplement the use-case descriptions
Use-Case Analysis step 3: Find analysis classes from use-case
behavior

from The Rational Edge: The first in a two-part series, this article presents a case study that analyzes the
requirements captured in use cases and transforms them into implementable representations that can be directly
coded.

Use-Case Analysis step 4: Describe the classs responsibilities


Use-Case Analysis step 5: Establish associations between analysis
classes
Use-Case Analysis step 6: Distribute behavior to analysis classes
Use case analysis step 7: Describe attributes and associations

Writing use cases to capture the software requirements that are


visible to system actors has been a common practice since Ivar
Jacobson introduced them in 1992. But a common confusion has
accompanied this practice. Once I have my use cases, how do I use
them to get to my code? This two-part article series will present a
case study that analyzes the requirements captured in use cases
and transforms them into implementable representations that can be
directly coded. My goal is to sufficiently clarify this transformation so
that you can immediately apply these ideas to your current, or next,
software project.

Use-Case Analysis step 8: Qualify analysis mechanisms


Conclusion
Acknowledgements
References
Further Reading
Notes
About the author
Rate this article

Subscriptions:
dW newsletters
dW Subscription
(CDs and downloads)

The IBM Rational Unified Process (RUP) advocates writing use cases to capture the operational requirements of a software system. Use cases are actually
a constituent of a larger requirements package of documents collectively known as the Software Requirements Specification (SRS), which contains all the
requirements for a software project. The SRS includes the following requirements artifacts:

Use Case Model, which consists of:


1. Use case diagram: A visual representation of system users (actors) and the services they request from the system.
2. Actor definitions: A textual description of the requestors of services provided by your system, and services provided to your system.
3. Use case descriptions: Textual descriptions of the major services provided by the system under discussion.

Supplementary Specification: A document that captures the system-wide requirements, and those functional aspects of the system which are neither
visible to the systems actors, nor local to a specific use case.

These requirements artifacts become inputs to the subsequent analysis and design activities of the Analysis and Design discipline in RUP. Exactly which
requirements artifacts are produced, of course, depends on the forces driving your development effort. If you are doing hot fixes (i.e., critical bug fixes on a
product already in production) you might not have any requirements documents, only bug reports that indicate the released software does not meet its originally
stated requirements. If you are doing a maintenance or enhancement release of software (i.e., adding new functionality to an existing product) you might have
one or two use cases describing how these new functions interact with a user, but you would not have a Supplementary Specification because no changes to
the non-functional properties of the software have occurred.
In this discussion I am assuming a brand-new, green-field development project for software that does not yet exist. This will be an object-oriented project
using the Unified Modeling Language (UML) to represent concepts and relationships. I am also assuming that the reader is comfortable with the concepts of
class and object, and is at least comfortable with reading UML version 1.x or 2.0 class diagrams, sequence diagrams, and collaboration diagrams.

Use-Case Analysis activity


This narrative will focus on the Use Case Analysis activity in RUP. As you can see in Figure 1, this activity incorporates artifacts which are normally produced in
the RUP Architectural Analysis activity.

The Rational Edge--July 2004


http://www-106.ibm.com/developerworks/rational/library/5383.html (1 of 20)7/17/2004 5:41:24 AM

Getting from use cases to code Part 1: Use-Case Analysis

Figure 1: Workflow for Architectural Analysis (early Elaboration)


Admittedly, a rigorous approach to describing the software development process would embrace the larger architectural perspective of enterprise systems, and
questions of reuse. But I will not be formally discussing the Architectural Analysis activity for three reasons:
1. My goal is to focus on the lower-level artifacts and activities used and carried out by developers, not architects.
2. It would expand the scope of this series beyond a reasonable length for a non-book publication, and
3. It is my experience as a process and architecture consultant that the discipline of performing architectural analysis is not embraced by a large
percentage of software development organizations. If you are currently doing architectural analysis, then you will have already performed some of the
steps I cover in this article. It is always commendable to take an architectural perspective on a new, or large, project. But if you are not currently
embracing architectural analysis, then the approach in this series will illustrate the minimal steps that should help you gather some of this needed
information.
The purpose of the Use-Case Analysis activity is:

To identify the classes that perform the various flows of events in a use case.

To distribute the use-case behavior to those classes, using use-case realizations.

To identify the responsibilities, attributes, and associations of the classes.

To note the usage of architectural mechanisms to provide the functionality needed by the use case, and the software system in general.

We can alternately say that the goal of Use-Case Analysis is to take our understanding of the requirements in the systems use cases and iteratively transform
those requirements into representations that support the business concepts, and meet the business goals of those requirements. In Use Case Design we will
transform these business concepts into classes, objects and relationships, components, interfaces, etc., which can be implemented in an executable
environment.
The diagram in Figure 2 is taken from the RUP Analysis and Design Activity Overview, which illustrates where the Use Case Analysis activity occurs within the
context of the other Analysis and Design activities.

http://www-106.ibm.com/developerworks/rational/library/5383.html (2 of 20)7/17/2004 5:41:24 AM

Getting from use cases to code Part 1: Use-Case Analysis

Figure 2: Use-Case Analysis activity in RUP


Use Case Analysis is composed of several steps in RUP [RUP2003]:

For each use case in an iteration


1. Create a use case realization
2. Supplement the Use-Case descriptions (if necessary)
3. Find Analysis Classes from Use-Case Behavior
4. Distribute Behavior to Analysis Classes

For each resulting analysis class


1. Describe the Classs Responsibilities
2. Describe the Classs Attributes and Associations

Define Class Attributes

Establish Associations between Analysis Classes

Describe Event Dependencies between Analysis Classes

Reconcile the Use Case Realizations

Establish Traceability

Qualify Analysis Mechanisms

Evaluate the Results of Use-Case Analysis

Please note that the order of these steps is not cast in stone. The actual sequence you follow may differ according to your understanding of the domain you are
analyzing, your experience with RUP or UML, your personal preferences for the models you use, or the metaphor you follow for characterizing the properties of
your analysis classes (e.g., responsibility-centric, behavior-centric, or data-centric approaches). What is important is that you achieve a comprehensive
expression of the problem you are to solve (note that we achieve a comprehensive definition of the solution we have chosen in Use-Case Design, which is the
subject of Part 2 in this series). I will follow most, but not all, of these steps in this article, and I will change the sequence somewhat. As I discuss each step, I
will explain why I have found a slightly different sequence to be beneficial when teaching object-oriented analysis and design (OOAD) to people who are new to
RUP and OOAD.
As Figure 3 illustrates, there are some specific activities that separate the writing of a use case from its implementation in code. This illustration also shows the
steps recommended by RUP within the context of Use Case Analysis. This diagram will become our visual roadmap as the remainder of this paper addresses
the specific tasks within these activities.
http://www-106.ibm.com/developerworks/rational/library/5383.html (3 of 20)7/17/2004 5:41:24 AM

Getting from use cases to code Part 1: Use-Case Analysis

Figure 3: The steps of use case analysis

Example use case


To facilitate our understanding of what we do with use cases after we discover and develop them, we need to start with a sample use case. Consider this very
brief use case for a hypothetical browser-based software system for an auto rental company. Such a system may have a half-dozen or so use cases allowing
their customers to request various services, such as:

Reserve a Vehicle

Cancel a Reservation

View Rental History

View or Edit Customer Profile

Join Awards Program, etc.

To simplify our modeling, I will assume that our rental agency does not support corporate accounts, only individual accounts.
To keep our example simple and understandable, we will focus on just one of these use cases. Here is a use case description for the use case: Reserve a
Vehicle.

Use Case: Reserve a Vehicle.

1. This use case begins when a customer indicates he wishes to make a reservation for a rental car.
2. The system prompts the customer for the pickup and return locations of the reservation, as well as the pickup and return dates and times. The customer indicates the desired locations and dates.
3. The system prompts for the type of vehicle the customer desires. The customer indicates the vehicle type.
4. The system presents all matching vehicles available at the pickup location for the selected date and time. If the customer requests detail information on a particular vehicle, the system presents this information to the
customer.
5. If the customer selects a vehicle for rental, the system prompts for information identifying the customer (full name, telephone number, email address for confirmation, etc.). The customer provides the required
information.
6. The system presents information on protection products (such as damage waiver, personal accident insurance) and asks the customer to accept or decline each product. The customer indicates his choices.
7. If the customer indicates accept reservation, the system informs the customer that the reservation has been completed, and presents the customer a reservation confirmation.
8. This use case ends when the reservation confirmation has been presented to the customer.

This use-case description is necessarily generic: it is not specific to a Web-based application, nor is it specific to the situation where a human being walks up to
a rental counter and requests a vehicle to rent. This description addresses only the what, not the how, of the system what is the behavior of the system and
the corresponding behavior of the use-case actor (i.e., the customer). If you substitute customer service representative for the system above, you will have a
http://www-106.ibm.com/developerworks/rational/library/5383.html (4 of 20)7/17/2004 5:41:24 AM

Getting from use cases to code Part 1: Use-Case Analysis

reasonably accurate description of what happens when a human walks into the rental office to get a vehicle. In this case, the reservation confirmation presented
to the customer in Step 7 is the printed rental agreement.
Alternately, if you are planning on implementing a Web-based interface, this use case describes that approach also, if you recognize that multiple steps in a use
case can be combined into a single browser page (e.g., steps 2 & 3 would most certainly be on the same page). In the Web environment, the reservation
confirmation presented to the customer in step 7 is the confirmation number associated with the rental transaction, presented to the actor on the transaction
summary Web page.
Also note the style of the use case. It is written in active voice and present tense. Active voice is clear and emphatic, while passive voice is a weaker
presentation. E.g., John throws the ball is active voice. The doer of the action, John, precedes the verb. The passive voice equivalent of this sentence is: The
ball is thrown by John, or just The ball is thrown, leaving the thrower unspecified. Here the doer of the action, John, follows the verb. Invariably, in passive
voice, the doer is contained within a prepositional phrase initiated with the word by. Keep your use case descriptions clear and consistent. Use active voice,
present tense. Use a limited and clear vocabulary. Do not introduce unnecessary words, and be consistent. For example, dont use the word customer, then
client, then business patron just to be creative. Your reader will conclude that you might be discussing three separate actors, with different security profiles
and authorizations!
Now that we have this use case as a starting point, lets follow the RUP steps of Use Case Analysis.

Use-Case Analysis step 1: Create a use-case realization


The first step in RUPs Use-Case Analysis is to create what RUP calls a use case realization. Before we get into a formal definition of a realization, lets step
back and ask, What really is a use case? and What do we need to validate our use case? Our written use case is a description of a process: a business
process for allowing a customer to reserve a vehicle from our business. It states that we will follow a certain flow of events (step B occurs after step A, etc.), and
we will enforce certain business rules, such as not processing a rental request unless we get a first name and last name of the renter, and not processing a
rental request for a vehicle which is not available at the pickup location on the specified date.
Since we are doing an object-oriented software system, the behavior of our use case must be carried out by the classes and objects in our system. But so far
we dont have any classes or objects yet, so we have to discover the classes that we will need to carry out the process in our use cases. And we have to
specify which classes will interact to provide the behavior we have designated in our use case.
As Figure 4 illustrates, a use-case realization is really a collection of several UML diagrams which together validate that we have the classes, responsibilities,
and object interactions necessary to provide the behavior in our use case process.

Figure 4: A RUP use-case realization for an airline reservation system


Specifically, a use-case realization is normally represented using:

A UML class diagram for those classes participating in the use case on which we are focusing (sometimes called a View of Participating Classes class
diagram.), and
One or more UML interaction diagrams to describe which objects interact, and the interfaces which these objects will invoke to carry out the work of the
use-case process. UML defines two types of interaction diagrams: a sequence diagram (shown in Figure 4), and a collaboration diagram. Either
diagram can be effective.

This sounds like a lot to do in this first step, doesnt it? Yes, and actually this first step is a housekeeping task when you are using a CASE tool such as Rational
Rose or Rational XDE, and really means create a place to hold your use-case realization. We will develop the actual class and interaction diagrams later in
this process. But now we know the content we will be developing to populate our use-case realization: a class diagram and one or more interaction diagrams.

Use-Case Analysis step 2: Supplement the use-case descriptions


While you are in an analysis mindset, your use case description will generally address only the behavior of the system that is externally visible to an actor using
the system. It is quite acceptable to describe in summary fashion some of the internal, non-visible behavior of the system, but do not attempt to design your
http://www-106.ibm.com/developerworks/rational/library/5383.html (5 of 20)7/17/2004 5:41:24 AM

Getting from use cases to code Part 1: Use-Case Analysis

system in the use-case description.


As an example, consider Step 4 in our use case: The system presents all matching vehicles available at the pickup location for the selected date and time. If
the customer requests detail information on a particular vehicle, the system presents this information to the customer. Hmmm, do we have a data source that
will provide these matching vehicles? We might know that the vehicle schedules are maintained for all rental locations by a CICS application on an MVS
mainframe accessed by LU6.2 APPC, but lets not be so specific yet. Lets make it clear that what we have to do is go outside the boundary of our reservation
system, without specifying how we expect to do this. Here is the same Step 4, now supplemented to indicate a new data source we will simply call Vehicle
Inventory: the system accesses the vehicle inventory for the pickup location, and presents a new page with all vehicles of the specified categories available
at the pickup location for the selected date and time.
Here we have specified that there is an external data source of vehicle information, and made high-level reference to presentation via Web pages. This was an
isolated example of supplementing, but our use-case reader can now get a better understanding of the total geography of behavior involved in the use case.
In an iterative development process such as RUP you move from analysis to design in a very short time. In a 4-week iteration in the Construction phase (midproject), you may spend the first week capturing your requirements, doing your Analysis and Design disciplines, and then spend the last three weeks writing
and testing the code for the iteration. Your analysis-level use-case descriptions will focus on what behavior the system will exhibit, but you might need to
enhance those descriptions to include more internal interactions so your customer or business analysts can be confident you have not left out significant
business processing. Bear in mind that you want to supplement the use-case descriptions only to the point that you can effectively determine the analysis
classes in your system. The identification of design-level classes (e.g., trees, stacks, queues, collections, etc.) should be deferred to a later discipline (i.e.
design).

Example: Supplement the Reserve a Vehicle use case


Lets assume our system will be a browser-based Web application. We want to provide our customers with on-line capability to make their own vehicle rental
reservations whenever it is convenient for them to do so. We may need to supplement our use-case description to make it more specific to our target
environment, without going overboard into design (that comes later).
Here is the Reserve a Vehicle use case in a more specific expression, still focusing on what is done, rather than how:

Use Case: Reserve a vehicle to a customer (supplemented)

1. This use case begins when a customer enters our rental Website page.
2. The system presents fields to prompt the customer for the pickup and return locations of the reservation, and the pickup and return dates and times. The customer indicates his desired locations and dates. The system
also presents an option for the customer to limit the vehicle search to specific categories of vehicles e.g., compact, SUV, full-size, etc. The customer may specify a search category, or categories, if desired. The
default is to search for all categories of vehicles. If the customer is participating in our rental awards program, he may enter his awards identification number in a separate field on the page. If this field is filled in, the
system will access the customers rental profile, which the system will retain to pre-populate any required information.
3. If the customer indicates he wishes to continue the reservation session, the system accesses the vehicle inventory for the pickup location, and presents a new page with all vehicles of the specified categories available
at the pickup location for the selected date and time. With each vehicle the system presents a base rate, which may be discounted based on the customers rental profile. If the customer requests detail information on
a particular vehicle, the system obtains this information from the vehicle inventory and presents it to the customer.
4. If the customer selects a vehicle for rental, the system presents a new page which prompts for information identifying the customer (full name, telephone number, email address for confirmation, credit card issuer,
etc.). If a customer profile exists, the system pre-populates all known values. Some fields are mandatory; others (such as email address) are optional. The customer provides any remaining required information. The
system also presents information on protection products (damage waiver, personal accident insurance, etc.) and their daily costs, and asks the customer to accept or decline each product. The customer indicates his
choices.
5. If the customer indicates accept reservation, the system presents a page summarizing the reservation (type of vehicle, dates and times, any elected protection products and their charges, total rental cost), and
presents the customer a reservation confirmation. If the system has an email address for the customer, the system sends a reservation confirmation to that address.
6. This use case ends when the reservation confirmation has been presented to the customer.

In this supplemented version we are clearly describing the behavior of a browser-based application, specifying a fair amount of behavior that is not visible to the
customer actor. But there is no design-level information in the use case yet.

Is it necessary to provide this additional detail for every use case?


No, its not. But remember that detail means detail not implementation. The goal is to get just enough detail to understand the analysis classes you will
need in your system, and to get consensus from your customer or business analysts that your use case meets their goals. If your first cut at a use case
description is a bit thin in helping you identify some analysis classes, then do the supplemented use-case.
Caution: Its not easy to find this middle ground between abstract specification at one extreme, and implementation specification at the other. It takes time and
practice. Work with it, find help, and remember its better to err toward abstraction if you are not sure how detailed you should be. Its easier to add some detail
that you missed than to rummage around in a quagmire of implementation details from which you will find it almost impossible to extricate yourself.

Why should I do the high-level use case at all? Why not just do a supplemented use case?
The answer is, the abstract use case (light on internal behavior) is the most generic description of behavior. What if you wanted to do a client/server version of
the Reserve a Vehicle use case? If you started with a browser-specific version, you would have to re-write the whole thing from scratch when you changed your
target platform. The generic version is technology-agnostic, and that is a great value when you are not ready, or able, to specify the production environment.
Additionally, the abstract version lets your Business Analysts or Subject Matter Experts focus on what the systems business behavior will be, rather than the
implementation which they may not understand at all.

Use-Case Analysis step 3: Find analysis classes from use-case behavior


http://www-106.ibm.com/developerworks/rational/library/5383.html (6 of 20)7/17/2004 5:41:24 AM

Getting from use cases to code Part 1: Use-Case Analysis

According to RUP, the purpose of this step is to identify a candidate set of analysis classes which will be capable of performing the behavior described in our
use cases. So far we dont have any classes, so our main goal will be to identify the analysis classes we need in our Auto Rental system.
But this raises a very interesting and important question: Just what is an analysis class? There are two answers, really. First, a business-level analysis class is
one that is essential to the business domain, without reference to implementation or technology constraints. For example, a banking system has Bank
Customer, Account, Account Transaction, etc., and it does not matter if this is a new e-commerce system or a savings and loan system from the 1890s.
Second, RUP extends this definition by defining analysis classes in three disjoint categories: as entity, controller, and boundary classes. RUPs entity classes
are roughly equivalent to the business-level analysis classes above. Controller classes are process-aware, and sequence-aware: they control and direct the
flow of control of an execution sequence. It is common to find a controller class enforcing the process behavior of a use case. Boundary classes mediate the
transfer of information and events between the software being executed and the outside world. Boundary classes handle the input and output functions required
by a software system.
In my experience teaching object technology and modeling, I have found that teams employing RUPs entity, controller, and boundary categories jump too
quickly into a design mindset, without performing adequate analysis of the problem they are trying to solve. In fact, it is quite clear that controllers and boundary
classes are actually technology classes, not business classes. They are part of the solution domain defined in design, not part of the problem domain described
in analysis. So, in this article I am going to concentrate on the business-level, technology-agnostic analysis classes, and leave alone almost all technology
issues until we discuss design. Be aware that the activity of finding these business-level classes is normally performed in RUPs Architectural Analysis activity
if your project is pursuing that degree of RUP conformance.
With that said, lets recall that the focus of a use case description is behavior what services the system will provide to the actors who are requestors of those
services. There is nothing object-oriented about use-case descriptions, but these descriptions can be used to discover the classes or objects in our system.
Classes can be discovered in many different ways, from different sources:

General domain knowledge

Previous systems that are similar

Enterprise models / Reference architectures

CRC (Class/Responsibility/Collaborator) sessions

Glossary of terms

Data mining

One simple technique for discovering classes is known as grammatical dissection, and I will illustrate that. In grammatical dissection we identify the nouns in our
requirements. Of these nouns (and adjective-noun pairs):

Some will become classes.

Some will become attributes of a class.

Some will have no significance at all for our requirements.

Lets identify and underline the nouns (skipping pronouns such as he) in our supplemented use case for Reserve a Vehicle, as follows:
Use Case: Reserve a Vehicle to a customer (Supplemented).
1. This use case begins when a customer enters our rental Website page.
2. The system presents fields to prompt the customer for the pickup and return locations of the reservation, and the pickup and return dates and times.
The customer indicates his desired locations and dates. The system also presents an option for the customer to limit the vehicle search to specific
categories of vehicles e.g., compact, SUV, full-size, . The customer may specify a search category, or categories, if desired. The default is to
search for all categories of vehicles. If the customer is participating in our rental awards program, he may enter his awards identification number in a
separate field on the page. If this field is filled in, the system will access the customers rental profile, which the system will retain to pre-populate any
required information.
3. If the customer indicates he wishes to continue the reservation session, the system accesses the vehicle inventory for the pickup location, and presents
a new page with all vehicles of the specified categories available at the pickup location for the selected date and time. With each vehicle the system
presents a base rate, which may be discounted based on the customers rental profile. If the customer requests detail information on a particular
vehicle, the system obtains this information from the vehicle inventory and presents it to the customer.

http://www-106.ibm.com/developerworks/rational/library/5383.html (7 of 20)7/17/2004 5:41:24 AM

Getting from use cases to code Part 1: Use-Case Analysis

4. If the customer selects a vehicle for rental, the system presents a new page which prompts for information identifying the customer (full name,
telephone number, email address for confirmation, credit card issuer,.). If a customer profile exists, the system pre-populates all known values. Some
fields are mandatory; others (such as email address) are optional. The customer provides any remaining required information. The system also
presents information on protection products (damage waiver, personal accident insurance, etc.) and their daily costs, and asks the customer to accept
or decline each product. The customer indicates his choices.
5. If the customer indicates accept reservation, the system presents a page summarizing the reservation (type of vehicle, dates and times, any elected
protection products and their charges, total rental cost), and presents the customer a reservation confirmation. If the system has an email address for
the customer, the system sends a reservation confirmation to that address.
6. This use case ends when the reservation confirmation has been presented to the customer.
Note that every occurrence of any noun, or adjective-noun pair, has been underlined. We have lots of duplicates, so gather the distinct nouns/pairs into a single
list in Table 1, sorted alphabetically:

Table 1: Candidate nouns/entities

How do we identify which of these candidate nouns really describe classes in our problem domain? A very usable approach is to challenge each candidate
noun with a few simple questions shown in Figure 5:

1. Is this candidate inside our system boundary?


If not, it might be an actor of our system.
2. Does this candidate have identifiable behavior for our problem domain?
(i.e., can we name the services/functions that are needed in our problem domain and that this candidate would own and
provide?)
3. Does this candidate have identifiable structure?
(i.e., can we identify some set of data this candidate should own and manage?)
4. Does this candidate have relationships with any other candidates?

http://www-106.ibm.com/developerworks/rational/library/5383.html (8 of 20)7/17/2004 5:41:24 AM

Getting from use cases to code Part 1: Use-Case Analysis

Figure 5: Questions for discovering analysis classes


If you find a no, then the candidate is probably not a class; move on to the next candidate. If the answer is yes, keep asking the questions. If you get all yes
answers, conclude the candidate is a class, and get the next candidate to evaluate.
If we challenge each of our candidates with these questions, we should obtain results similar to Table 2:

Table 2: Noun challenge results

http://www-106.ibm.com/developerworks/rational/library/5383.html (9 of 20)7/17/2004 5:41:24 AM

Getting from use cases to code Part 1: Use-Case Analysis

http://www-106.ibm.com/developerworks/rational/library/5383.html (10 of 20)7/17/2004 5:41:24 AM

Getting from use cases to code Part 1: Use-Case Analysis

http://www-106.ibm.com/developerworks/rational/library/5383.html (11 of 20)7/17/2004 5:41:24 AM

Getting from use cases to code Part 1: Use-Case Analysis

Note that rental location has been added although it was not part of the use case. In talking with our Subject Matter Experts (SMEs), we learned that the normal
business vocabulary uses location to refer to both an address, and to a rental branch. To resolve the ambiguity, we agreed to use the term rental location for
the business location where rentals and returns are conducted.
From this list we extract those candidates that we have designated yes. This yields the following list of analysis classes:

Wow! Thats only eight analysis classes versus the thirty nine candidates we started with. The four questions have helped us rapidly narrow our focus and
thats a good thing.
But what if we made a mistake? What if we missed a real class, or we included a class that we should not have? It doesnt matter, really. The iterative nature
of RUP will reveal our errors, and allow us to correct them with minimum damage to work we have already done. The goal of analysis and design is not to get it
all right up front. The goal is to get it right when you need to have it right. Getting started is often the hardest part of any task, and we have now made the leap
from having no objects to having objects (or from having no classes to having classes). What is important is that we have started, and we can begin to move
forward in an object-oriented perspective.
We now have completed the first three steps in RUPs Use Case Analysis activity:

For each use case in an iteration


1. Create a use case realization
2. Supplement the Use-Case Descriptions (if necessary)
3. Find Analysis Classes from Use-Case Behavior

If we follow RUP rigorously, the next RUP step will be:


4. Distribute Behavior to Analysis Classes
Again, I am going to deviate a bit from the standard RUP flow, with the following justification: Consider where we are. We have just identified eight entities that
we believe are classes in our Auto Rental system. Before we do anything else, we need to add content to these eight entities to be sure they are classes.
There are three basic approaches for fleshing out our analysis classes:

A data-driven approach

A behavior-driven approach, or

A responsibility-driven approach.

http://www-106.ibm.com/developerworks/rational/library/5383.html (12 of 20)7/17/2004 5:41:24 AM

Getting from use cases to code Part 1: Use-Case Analysis

The data-driven approach is very popular with people coming from a database, or procedural, background. They see the world in terms of data, and data
relationships, and tend to populate their classes first with data usually with no strategy on how to assign operations (i.e., functions) to the class. This is fine,
but data is only half of the total picture. Indeed, the very concept of a class involves the intimate association of data with the operations that manipulate that
data.
The behavior-driven approach takes this dual nature into account. It populates a class first with the operations that the class will perform, and determines from
those operations the data that should be owned by the class. Very good, but how do I make sure that the operations I assign to a class are coherent? And how
do I distinguish between operations and classes, so that I know this operation belongs in this class, but that other operation should be in a different class? We
need a filter, some kind of discriminator that will help us make good decisions about our operations. This filter is what the responsibility-driven approach gives
us.
A responsibility-driven approach starts with a large-grained view of the class and first assigns responsibilities to that class. This approach describes first the
mission statement of a class in the context of the problem domain in which we are working. This mission statement is a declaration of the services the class
will provide to requestors of those services. In military terms, the responsibilities are strategic; the operations and data are tactical (subservient to, and a means
2

of achieving, the strategy).

And once we identify our class responsibilities, we should construct an analysis class diagram to capture the structure of the relationships among our classes.
This structure is usually inherent in the business domain we are modeling, and a UML analysis class diagram gives us a visual representation of this
relationship structure.
So, the deviation I am recommending produces the following change to the standard RUP flow (sequence changes are in bold):

For each resulting analysis class


1. Describe the Classs Responsibilities
2. Establish Associations between Analysis Classes (analysis class diagram)
3. Distribute Behavior to Analysis Classes (discover operations)
4. Describe each Classs Attributes and Associations

Define Class Attributes

Describe Event Dependencies between Analysis Classes

Use-Case Analysis step 4: Describe the classs responsibilities


This step is done for each analysis class we have identified. A responsibility of a class describes the services that this class will provide in our system, and that
no other class will provide. Responsibilities in different classes must not overlap.
Based on our understanding of our vehicle rental domain, and in consultation with our vehicle rental SMEs and business analysts, we can document
responsibilities for each analysis class, as shown in Table 3.

Table 3: Responsibilities for each analysis class

http://www-106.ibm.com/developerworks/rational/library/5383.html (13 of 20)7/17/2004 5:41:24 AM

Getting from use cases to code Part 1: Use-Case Analysis

James Rumbaugh et al. defines an object, or class, as a concept, abstraction, or thing with crisp boundaries and meaning for the problem at hand [my
emphasis]. It is primarily through the definition of responsibilities that you can give a class crisp boundaries, a clear definition of what it does, and does not,
do.

http://www-106.ibm.com/developerworks/rational/library/5383.html (14 of 20)7/17/2004 5:41:24 AM

Getting from use cases to code Part 1: Use-Case Analysis

What if we made a mistake in our responsibilities? Again, it doesnt matter. We have a starting point and we will move forward. It is common to adjust the
responsibilities of classes as we learn more about our system. This is just another example of where we use refactoring to help us build better models and
better software.

Use-Case Analysis step 5: Establish associations between analysis classes


Now that we have defined our class responsibilities, we will develop an initial UML class diagram to identify the relationships among our analysis classes. There
are four simple tasks we must conduct to develop a class diagram:
1. Identify the classes to be modeled (we have already done this).
2. Identify which of these analysis classes have some kind of relationship with each other.
3. For any two classes that have some relationship, identify the semantics of the relationship: is it association, aggregation, composition, or inheritance?
4. For non-inheritance relationships, identify the multiplicity on the relationship. (Multiplicity is an indication of how many objects of that class might be
related on one object of this class? Its very similar to cardinality in the data modeling world.)
By applying these steps, in conjunction with our identified class responsibilities, we arrive at the UML class diagram shown in Figure 6.

Figure 6: Analysis class diagram for vehicle rental system


There are three types of UML relationship shown on this class diagram, indicated by different line styles. The simple solid line indicates an association
relationship. This is used to indicate that the two connected classes are in a peer-to-peer relationship and that each class can request the services provided by
the other class through its operations.
The filled-in diamond on the line between Reservation and ProtectionProduct is called composition (or, non-shareable aggregation). This relationship is a
whole/part or ownership relationship. In this class diagram the composition symbol means that the Reservation owns and manages the zero-or-more (*)
ProtectionProducts that are included in the Reservation. Further, composition dictates that if the Reservation is destroyed, the ProtectionProducts owned by the
Reservation must also be destroyed since they have no business significance if they are not part of a Reservation.
The unfilled diamond on the line between VehicleInventory and Vehicle is called aggregation (or, shareable aggregation). This is also a whole/part or
ownership relationship, but in aggregation we do not destroy the parts (Vehicle) when we destroy the whole (VehicleInventory). This makes sense: just
because a particular RentalLocation will no longer rent cars (it will become a service-only location) the Vehicles may be temporarily orphaned but we dont
destroy the objects representing the vehicles, we just reassign them to another VehicleInventory.
The numbers and * symbols at the ends of the relationship lines are called multiplicity specifiers. These symbols denotes the number of, for instance, Vehicles
associated with one Customer. Or, conversely, the number of Customers associated with one Vehicle. In this class diagram we have multiplicity that says, for
each Customer, we have zero or more (*) Vehicles reserved (either at one time, or over time). Reading this in the opposite direction, we have for each Vehicle,
it is reserved by no Customer, or possibly many Customers (over time, obviously).
In analysis we are trying to make sure we can express and understand the problem for which we are building a solution. The analysis class diagram is a vehicle

http://www-106.ibm.com/developerworks/rational/library/5383.html (15 of 20)7/17/2004 5:41:24 AM

Getting from use cases to code Part 1: Use-Case Analysis

for Business Analysts and Subject Matter Experts to review with the technical people, and migrate the model toward a proper description of the problem being
solved.
Now we have classes, responsibilities, and a class diagram to show the structure of relationships among the classes. But so far we have no internals of the
classes no operations and no attributes. And the class diagram is a static picture. How can we be sure that these classes really can carry out the process
described in our use cases? Ah, that is what the next step is for, and it is an all-important step because it maps our use-case descriptions into potential
operations on our analysis classes.

Use-Case Analysis step 6: Distribute behavior to analysis classes


How will these classes behave and interact to carry out the work of the Reserve a Vehicle use case? We show this by creating a UML interaction diagram to
capture the interactions between objects of our analysis classes. Recall that UML Sequence diagrams and Collaboration diagrams are each types of interaction
diagrams, and are part of our use-case realization. In Figure 7, I show an analysis-level Sequence diagram for the Reserve a Vehicle use case.

Figure 7: Reserve a Vehicle analysis sequence diagram


Click to enlarge
You will notice that I have introduced a non-business class UCController in this diagram. This Use Case Controller class represents a generic placeholder
to receive events and messages from the human actor. I have found that most readers of analysis-level Sequence diagrams get very confused when a
business class (e.g., RentalLocation or Reservation) acts as a receiver of actor messages. So, I often add to my analysis interaction diagrams a generic Use
Case Controller to represent this intelligence, and simplify the readers understanding. In design we will rename this to ReserveAVehicleController, but for now I
want the name to remain generic so UCController can be used on every analysis-level Sequence diagram.
Both sequence diagrams and collaboration diagrams contain almost identical information, they just present it differently. Choosing which diagram to use is often
a matter of convenience and personal preference. In the sequence diagram the objects are aligned at the top of the diagram, and they have dashed lifelines
that extend downward. The horizontal arrows with numbered text are called messages. In a Sequence diagram, the sequence of messages is shown
positionally: time proceeds down the page, so a message low in the diagram is sent after a message that is above it. The messages start on one objects
lifeline, and always terminate on a lifeline, usually another objects lifeline, but sometimes on the sending objects own lifeline (see Figure 7, message #21).

http://www-106.ibm.com/developerworks/rational/library/5383.html (16 of 20)7/17/2004 5:41:24 AM

Getting from use cases to code Part 1: Use-Case Analysis

The sequence diagram offers a significant advantage over the collaboration diagram, which is the script on the left-hand side of the diagram. This text is taken
from the use case, or scenario, that the sequence diagram depicts. The script on this diagram is just a terse rendering of the text in the Reserve a Vehicle use
case. Placing the script into the diagram makes the context of the messages very clear, and links the messages and objects back to the original use case. It is
always the case that a given statement in the use case will map to one or more messages sent between the objects in your system. The Sequence diagram
makes this explicit.
I want to emphasize a very important characteristic of analysis-level interaction diagrams: the messages show intent, not implementation, not even interface. In
the Reserve a Vehicle Sequence diagram the messages simply indicate what I want done by the receiving object, not the signature of a function call. This
deeper interface detail is addressed in design, but now we only want to be sure our classes have the responsibilities to do the work of the use case.
How did we know to send these particular messages to these classes? By following our responsibility definitions. For example, in Step 8, the RentalLocation is
asked to meet its responsibility of determining what vehicles are available. In Step 9, the VehicleInventory is asked to retrieve all vehicles for this location that
can match the requested rental dates and times. In Step 10, each Vehicle in inventory is asked if it is available to meet these rental criteria. Notice that all of this
knowledge is not in the RentalLocation object. We have distributed the intelligence in our system across all of our analysis classes, so that each class can act
on a small set of requests that are within its defined responsibilities.

UML note: Objects To name or not to name?


On the Sequence diagram the object boxes have no name preceding the :<classname>. These are called anonymous objects. But it is possible to give objects
a name. If we have a class called Account we would show it as:
Account

If we create two objects from this Account class definition, FredsStash, and EthelsMadMoney, they would be shown as:

FredsStash : Account

EthelsMadMoney : Account

The one on the left, for example, indicates that FredsStash is an object of type Account. How do you know if you should name an object or leave it
anonymous? If you have a special entity in your system that has a well-known name, you might want to use a named object to represent it. Or, if you want to
build a diagram with sample objects (similar to sample tables in a logical data model) you could use named objects. But for most modeling purposes,
anonymous objects are sufficient. We are most interested in the services (functions) a class and object provide, and the name of the object does not affect what
the class or object can do.

Use case analysis step 7: Describe attributes and associations


In analysis, you will discover some of the attributes (i.e., class data variables) that your classes will need in order to meet their responsibilities. From our list of
class responsibilities we can deduce certain attributes for our analysis classes. Additional attributes can be determined from general domain knowledge (e.g., it
makes sense that each Vehicle object should have a unique identifier attribute corresponding to the physical vehicles federally-mandated Vehicle Identification
Number).
UML note: Classes in UML have three subcompartments, as shown below, using Account as the class example.

The class diagram shown in Figure 8 shows our vehicle rental analysis classes, the relationships between them, and an initial start on the attributes appropriate
to be owned in each class. These are simply the attributes most evident from the class responsibilities. Note that these attributes do not even have datatypes
yet because data types are a design issue.

http://www-106.ibm.com/developerworks/rational/library/5383.html (17 of 20)7/17/2004 5:41:24 AM

Getting from use cases to code Part 1: Use-Case Analysis

Figure 8: Initial assignment of class attributes


It is enough at this point to only specify that a Customer class has an address attribute. How the address is structured, or even if the address needs to become
a class itself, can be decided later. You will notice that VehicleInventory has no attributes yet. This will become an interface to our external, vehicle information
repository, and I am not at all sure what data attributes are needed yet. Well discover them as we move further into the project.

Use-Case Analysis step 8: Qualify analysis mechanisms


An analysis mechanism is a high-level architectural component that provides a service needed by the problem domain, not the technical, solution domain. For
example, in an insurance domain it is a business requirement that the information in our Policy, Claim, and other objects must be maintained across usages of
a Policy Management application. This business requirement translates into an analysis mechanism called Persistence: the maintenance of information and
state even when the application is not executing. Note that we do not specify Oracle SQL, or SQL Server, which are specific implementations supporting the
function of persistence. We just list persistence, and we will later describe design mechanisms and implementation mechanisms which will become platform- or
vendor-specific.
An example of the relationship among analysis, design, and implementation mechanisms is shown in Table 4:

Table 4: Relationships among analysis, design, and implementation mechanisms

Some common analysis mechanisms are:

Persistence

Communication (between processes, or applications)

http://www-106.ibm.com/developerworks/rational/library/5383.html (18 of 20)7/17/2004 5:41:24 AM

Getting from use cases to code Part 1: Use-Case Analysis

Exception handling

Event notification mechanisms

Messaging

Security

Distribution (i.e., distributed objects)

Legacy interface

In our Vehicle Rental system, we need to specify analysis mechanisms for:

Conclusion
In Part 1 of this series on Getting from use cases to code, we have traveled from a single use case, with no knowledge of classes in our system, to a point
where we have identified the classes needed to support the goals of that use case, the relationships among those classes, and the attributes needed by those
classes, and we have specified several analysis mechanisms that identify services we will need to refine into design and implementation perspectives.
If we repeat this use case analysis process with another use case, we will discover some additional analysis classes, define their responsibilities, new
relationships to other analysis classes, perhaps discover new analysis mechanisms, and we will develop another collaboration diagram or sequence diagram to
further demonstrate how our classes interact. This demonstrates the incremental aspect of RUP: each task, or iteration, builds on, and adds to, the work done
previously.
We have accomplished a lot, but we are not yet ready to begin writing code. Now we are at a point to turn our attention to Use-Case Design, which is the
subject of Part 2 in this series.

Acknowledgements
I am grateful to Peter Eeles and Zoe Eason of IBM Rational for their insightful comments and suggestions on an earlier draft of this paper.

References
Wirfs-Brock, Rebecca. Designing Object-Oriented Software. Prentice-Hall, 1990. A classic in object thinking and modeling. Introduces the significance of the
responsibility-driven approach to software modeling and design.
Rumbaugh, Jim, et al. Object-Oriented Modeling and Design. Prentice-Hall, 1991, pg. 21. The defining book on the Object Modeling Technique, a major
influence on the Unified Modeling Language.
The Rational Unified Process, version 2003.06.00.65. Rational Software Corporation.

Further Reading
Ambler, Scott. The Object Primer, 2nd ed. SIGS, 2001. Covers end-to-end object-oriented development with a single case study.
Fowler, Martin. UML Distilled, 3rd ed. Addison-Wesley, 2004. Best introduction to UML (version 2.0) for those learning UML for the first time.
Taylor, David. Object Technology: A Managers Guide. Addison-Wesley, 1998. One of the best introductions to object-thinking ever written.

http://www-106.ibm.com/developerworks/rational/library/5383.html (19 of 20)7/17/2004 5:41:24 AM

Getting from use cases to code Part 1: Use-Case Analysis

Bell, Donald. UML basics An introduction to the Unified Modeling Language, in The Rational Edge, June 2003: http://www-106.ibm.com/developerworks/
rational/library/769.html
Bell, Donald. UML basics: The activity diagram, in The Rational Edge, September 2003: http://www-106.ibm.com/developerworks/rational/librarycontent/
RationalEdge/sep03/f_umlbasics_db.pdf
Bell, Donald. UML basics: The class diagram, in The Rational Edge, November 2003: http://www-106.ibm.com/developerworks/rational/librarycontent/
RationalEdge/nov03/t_modelinguml_db.pdf
Bell, Donald. UMLs sequence diagram, in The Rational Edge, January 2004: http://www-106.ibm.com/developerworks/rational/library/3101.html

Notes
1

All references in this series to RUP incorporate the content of RUP version 2003.06.00. All models and code in this series have been generated using IBM
Rational Extended Developer Environment (XDE) Developer Plus for Java version 2003.06.

For more information on the responsibility-driven approach, see Rebecca Wirfs-Brocks book, Designing Object-Oriented Software. Prentice-Hall, 1990.

Rumbaugh, Jim, et al., Object-Oriented Modeling and Design. Prentice-Hall, 1991, pg. 21.

About the author


Gary K. Evans is the founder of Evanetics, Inc., a consulting company dedicated to reducing risk on software projects through agile techniques and process. He is the author of over a
dozen papers on object technology and tools, and is a frequent speaker at major software conferences. He is an avid soccer player, but loves even more working with small development
teams, training them in OOAD and agile RUP, and then working with them side-by-side to deliver the right software faster than they ever thought possible.

What do you think of this document?


Killer! (5)

Good stuff (4)

So-so; not bad (3)

Comments?

developerWorks

> Rational

About IBM

Privacy

Terms of use

Contact

http://www-106.ibm.com/developerworks/rational/library/5383.html (20 of 20)7/17/2004 5:41:24 AM

Needs work (2)

Lame! (1)

Writing good requirements is a lot like writing good code


Copyright IBM Corporation 2004.

Page 1 of 8
http://www-106.ibm.com/developerworks/rational/library/5170.html

Search for:

within
Use + - ( ) " "

IBM home
developerWorks

All of dW

Search help

| Products & services | Support & downloads | My account

> Rational

Writing good requirements is a lot like writing good


code
Jim Heumann
IBM
30 Jun 2004
from The Rational Edge: By employing many of the same principles and concepts they already use
to write code, developers can effectively serve as requirements engineers. This article reviews
those principles and explains how to apply them to create good requirements.

Contents:
Follow a structure
Use practices that ensure
quality
Elaborate with comments
Know the language
Follow guidelines

Many software development teams do not have


requirements engineers; developers elicit, write, and
manage all requirements. This makes sense in terms of
resource efficiency: Developers can collect and write
requirements during their down time, before serious
coding begins. However, the drawback is that
programmers are not usually trained in the techniques
and tools for writing good requirements. As a result they
often struggle, work inefficiently, and sometimes produce
substandard requirement specifications.

Understand the operating


environment
Follow established principles
Use automated tools
Manage change
Planning
Good developers can write
good requirements
Notes

To write good code, developers must know many things:


basic concepts such as controls structures and calling
conventions; at least one programming language, including its syntax and structure; fundamentals about
the operating system; and how to use technologies such as compilers, debuggers, and IDEs. The good
news is that they can leverage all of this knowledge to write good requirements. By employing many of the
same principles and concepts they already use to write code, developers can effectively serve as
requirements engineers.
Let's look at some of the programming concepts developers can use.

About the author


Rate this article
Subscriptions:
dW newsletters
dW Subscription
(CDs and downloads)

Follow a structure
All programming languages have a structure. Structure refers to how various parts of a program are defined and how they relate to each
other. Java programs are structured with classes, COBOL programs have various "divisions," and C programs have a main program with
subroutines.
Just as programs have a specific structure, so do requirements. Imagine if you were to put all the code you wrote for a C program into the
main program it would become unreadable and impossible to maintain. Similarly, if your requirements specification is merely a giant list
in no particular order, you will not be able to use it. A group of requirements always has structure, whether you realize it or not. The
optimum way to structure in requirements is to organize them by different types, which often correspond to different levels.
To understand the distinctions among different types, let's look at four example requirements for an insurance claims processing
application:
1.

We must be able to reduce our backlog of claims.

2.

The system must be able to automatically check claim forms for eligibility issues.

3.

The system shall determine whether a claimant is already a registered user, based on his/her social security number.

4.

The system shall support the simultaneous processing of up to 100 claims.

The Rational Edge--July 2004

7/15/2004

Writing good requirements is a lot like writing good code

Page 2 of 8

Your intuition may tell you that there is something different about each of these requirements. The first is very high level; it expresses a
business need without even mentioning a system. The second expresses what the system should do, but still at a pretty high level; it's still
too broad to translate directly into code. The third is a lower-level requirement; it does provide enough detail about what the software must
do to enable you to write code. And the fourth requirement, though very detailed, does not tell you what the system must do; instead, it
specifies how fast the system must be. These requirements are very typical of those you will get as you talk to users and other
stakeholders. Perhaps you can see why putting them all into one big, uncategorized list would lead to confusion.
You can make requirements much more usable by putting them into categories, or types, such as:
z

Business needs

Features

Functional software requirements

Non-functional software requirements

These are the types suggested in IBM Rational Unified Process, or RUP. They are by no means the only possible types, but they
represent one useful approach. Early in your project, you should decide on what types to use. Then, as you collect information from
stakeholders, decide which of the requirement types they are describing, and write the requirement.
Note that you can specify functional software requirements in one of two formats: declarative and use case. The third requirement above
is stated in declarative form; it is quite granular and uses a "shall" statement. The other form is a use case. It also specifies what the
system should do, at a level low enough to write code from. However, it provides more context about how the user and the system will
interact to perform something of value. (See below for more detail on use cases.) Before you begin collecting requirements for a project,
you should decide which type of functional requirement you want to use and then be consistent.

Use practices that ensure quality


You know that it is possible to write good code and bad code. There are many ways to write bad code. One is to use very abstract
function and variable names such as routineX48, PerformDataFunction, DoIt, HandleStuff, and do_args_method. These names do
not provide any information about what the methods or procedures do, forcing the reader to dig into the code to find out. Another bad
practice is to use single-letter variable names such as i, j, and k. You cannot easily search for these with a simple text editor, and the
functions are unclear.
Of course, you can write bad requirements in many ways, too. Probably the worst offense is ambiguity. If two people can interpret a
requirement in different ways, the requirement is ambiguous. For example, here is a requirement from a real requirements specification:
The application must be extremely stable with numerous users logged in simultaneously. Speed must not be sacrificed.
The words extremely and numerous are open to broad interpretation so this requirement is ambiguous. In fact, to achieve clarity, you
should really express it as three highly specific requirements:
1.

Mean time between system failures must be no greater than once per week.

2.

The system shall support 1,000 simultaneous users, all doing queries against the database at the same time, without crashing or
losing data.

3.

The average response time of the system shall be less than one second with up to 1,000 simultaneous users.

Quality requirements have many more attributes; see the IEEE guidelines for more information.1

Elaborate with comments


Well-written programs include comments that add information to the code to explain what it is doing or why it was written a certain way. A
good comment does not explain how the code does something which should be obvious from the code itself instead, it provides
knowledge that helps users, maintainers, and reviewers to understand what the code does and ensure quality. Similarly, requirements

7/15/2004

Writing good requirements is a lot like writing good code

Page 3 of 8

have attributes information that makes the requirements more understandable or usable. As you elicit the requirements you should
also discover attribute information. For example, one important attribute is origin: Where did the requirement come from? Keeping track of
your sources will save significant time if you need to go back for more information. Another attribute is user priority. If a user gives you fifty
requirements, he should also let you know how important each one is relative to the others. Then later in the project lifecycle, when time
is getting short and you realize you cannot meet every requirement, at least you will know which ones are most important.
Just as there are no rules that tell you exactly what comments to write in your code, there is no universal list of the "right" attributes. Origin
and priority are almost always useful, but you should define others that are suited to your project. As you gather requirements, try to
anticipate what information the team might need when you start to design the system and write code.

Know the language


Obviously, developers must know the language they use for coding, whether it is Java, COBOL, C++, C, Visual Basic, Fortran or one of
many others. To write good code, you must understand the language's nuances. Although basic programming concepts are the same in
each language, they take different approaches to specific operations. For example, the Java loop structure uses "for"; Fortran's is "DO". In
C you call a subroutine by referencing its name, with parameters; in Fortran you use a CALL statement.
To write requirements well you must also know the language. Most requirements are written in a natural language (French, English, etc.).
Natural languages are very powerful but also very complex; developers not trained in composition sometimes have difficulty
communicating complex ideas in writing. We don't have space for a full-blown writing lesson here, but some guidelines can help.
First, use complete sentences for declarative requirements (i.e., those expressed as shall statements or with a similar structure); check
for a subject and verb in each sentence.
Second, use simple sentences. Statements consisting of only one independent clause that conveys a single idea are easier to understand
and easier to verify or test. If your requirement seems too complex for simple sentences, try breaking it down into smaller requirements
that you can more easily define. Compound and complex sentences may introduce dependencies (branching); in other words, they may
describe variables that depend on certain actions. The result is often an unnecessarily complicated requirement that makes testing
difficult.
Simple sentence: The system shall be able to display the elapsed time for the car to make one circuit around the track.
Compound sentence: The system shall be able to display the elapsed time for the car to make one circuit around the
track, and the time format shall be hh:mm:ss. (This is two requirements; one is a functional requirement specifying what the
system should do, and the other is a user interface requirement specifying the time format.)
Complex sentence: The system shall be able to display the elapsed time for the car to make one circuit around the track
within 5 seconds of the lap completion. (This also is two requirements; a functional requirement, and a performance
requirement.)
To write adequate tests based on the compound or complex example, you would have to separate the two requirements within each one.
Why not make it easy and do that to begin with? Here is one way to translate the complex sentence above into simple sentences:
The system shall be able to display the elapsed time for the car to make one circuit around the track.
The format for elapsed time display shall be hh:mm:ss.
The elapsed time display shall appear within 5 seconds of the end of a lap.
Notice that, in addition to being more testable, these requirements are easier to read.
Here's one more tip for writing good requirements: Use a consistent document format. You already have a format or template for writing
code. Use one for writing requirements, too. Consistency is the key; each specification document should use the same headings, fonts,
indentions, and so forth. Templates can help. In effect, they act as checklists; developers writing requirements don't have to start from
scratch or reinvent the wheel to write a specification that looks good. If you want example templates, RUP has many.

Follow guidelines
Most development teams use coding guidelines such as the following:

7/15/2004

Writing good requirements is a lot like writing good code

Page 4 of 8

Place module specifications and implementations in separate files (C++).

Indent your code within the scope of a code block (Java).

Place the high-activity data elements at the beginning of each group of the WORKING STORAGE SECTION variables (COBOL).

You should use guidelines for writing requirements, too. For example, if you decide to specify software requirements with use cases, then
your guidelines should tell you how to write the flows of events. Use-case flows of events explain how the system and a user (actor)
interact to do something significant. Your guidelines should describe what goes in the main flow (the success scenario) and what goes in
alternate flows (exception scenarios), as well as how to structure these flows. They should also suggest lengths for both flows and
individual steps within them. If you decide to use traditional, declarative requirements, then the guidelines should explain how to write
them. Fortunately, many of these guidelines already exist in RUP and other respected sources, so you need not write them yourself.2

Understand the operating environment


To develop good code, you must know the machine on which your system will run and how to use its operating system. If it is Windows,
you must know MFC and .Net. If it is Linux, you must know UNIX system calls.
To be good at writing requirements you must understand not the operating system but the operator. You must also understand not the
user interface but the user. Java developers think about classpaths; requirements writers think about getting people on the right path to a
class (or workshop).
Eliciting requirements is a people-centric task. You don't make up requirements; you gather them from other people. This may be
challenging for introverted developers, but if they apply their existing skills in the right way, they can be successful.
Often, users do not know what they want; or if they do, they don't know how to describe it. Developers have skills that can help: They
often have to decipher arcane and cryptic error messages from the compiler. For example, a Java developer writing an applet might
encounter this message:
load: com.mindprod.mypackage.MyApplet.class can't be instantiated.
java.lang.InstantiationException: com/mindprod/mypackage/MyApplet

What does it mean? If the developer is not sure, she will investigate by looking in her code, the compiler documentation, and maybe even
via a search engine such as Google. Eventually she will figure it out: Her code is missing the default constructor for the applet she is
writing.
If you were collecting requirements for a weather forecasting system and a stakeholder told you that the system should be able to
"...display wind speed and direction at various heights in the atmosphere over a 200 square mile area, using standard arrows with little
tails," you would need to dig deeper. You might ask to see a report from a similar system, consult a book on meteorology, or ask another
stakeholder to describe the request more accurately. You would keep investigating until you had enough detail about the desired
functionality. Then you would restate the requirements to make them clear and unambiguous, providing enough detail to support a
design.
Another tip for eliciting requirements is to try not to ask leading questions. Although you may have ideas about what users should want, if
you let those slip out, you may not get a true picture of what they really want. Instead, ask open-ended questions such as, "What separate
data displays would you like to see?" and avoid questions such as, "Do you want to see a combined air pressure and temperature chart?"

Follow established principles


Among the basic principles for designing and writing good programs are information hiding, coupling, and cohesion. Each one has its
counterpart for writing good requirements.

Information hiding
This refers to the principle that the user/caller of a piece of code should not be able to access, or even know about, the data's internal
details. All access and modifications to the data should be through function calls. That way, you can change the internal data structures
without affecting the calling programs.
This is a good principle for requirements too, especially if you are expressing them in use cases. As we noted above, use cases have
flows of events. Poorly written use cases often have flows of events that are packed full of data definitions. Consider this basic flow of
events for a use case called Manage Purchase Request:

7/15/2004

Writing good requirements is a lot like writing good code

Page 5 of 8

Basic flow of events:


1.

The system displays all pending purchase requests.

2.

Each pending request will include the following information about the request (limit by char):
{

Approval ID (internal only)

PO #

Reference ID

Distributor Account Abbreviated Name

Dealer Account Name (first 10)

Dealer Account Number

Reason Codes

Amount Requested

Request Date

Assigned to (Internal)

Comments Indicator

3.

The Approval Admin can do one of the following 1) approve 2) reject 3) cancel or 4) assign the request. He/she chooses 1)
approve.

4.

...and so forth until all steps are complete.

Of the fifteen lines shown, eleven are dedicated to telling what data goes with a pending request. This is important information, but it
obscures what is happening in the use case. A better solution is to hide the data somewhere else. The steps would then look like this:
Basic flow of events:
1.

The system displays all pending purchase requests.

2.

The Approval Admin can do one of the following 1) approve 2) reject 3) cancel or 4) assign the request. He/she chooses 1)
approve.

3.

... and so forth until all steps are complete.

Pending purchase requests is underlined and italicized to indicate that the data is defined elsewhere (usually in the special requirements
section of the use case or perhaps in a glossary). This makes the flow of events, which represents the true functional requirements, much
easier to read and understand.

Coupling and cohesion


For those who write code, coupling refers to the principle that individual modules in a program should be as independent as possible.
Processing in one module should not depend on knowledge of the internal workings in another module. Cohesion, refers to the principle
that inside a given module, all the code should work to accomplish a single goal. These principles make a program both easier to
understand and easier to maintain.
These principles apply to requirements, too particularly to use cases. Use cases should stand alone (i.e., have little or no coupling).3
Each use case should specify a significant chunk of functionality and show how the system provides value to an actor. The actor focus is
important; you can specify what the system does for the actor without worrying about ordering the use cases sequentially.

7/15/2004

Writing good requirements is a lot like writing good code

Page 6 of 8

All the functionality in one use case should be about accomplishing one goal of an actor (i.e., have high cohesion). In a system for a
typical automated teller machine (ATM), one use case would be "Withdraw Cash" and another "Transfer Funds." Each use case
concentrates on a single goal. If you were to combine these functions into a single use case, it would have low cohesion (and undesirable
dependencies).
However, be aware that many use-case beginners go overboard and create too many low-level use cases. I once saw a model for a
bank's debt collection system that had 150 use cases with names such as "Modify Data." This project had a team of ten and was
scheduled to last about a year. However, the organization was having a lot of trouble moving forward because these use cases were too
fragmented. They described low-level functions that didn't specify value to the user; they were hard to understand and hard to use. Each
use case was extremely cohesive, but consequently the use cases had a high degree of coupling. Raising the level to more specific
activities such as "Collect Debt" yielded appropriate degrees of both cohesion and coupling.

Use automated tools


Developers use software tools to do their jobs. It is not possible to compile code by hand, so they always use compilers. Integrated
development environments (IDEs) are growing more comprehensive and more popular as organizations strive for efficiency. UML
modeling tools for code generation and reverse engineering are also used widely.
Automated tools are also extremely useful for writing and managing requirements. The first step toward automation is to use a word
processor. Using Microsoft Word to record requirements represents a significant step up from keeping them on whiteboards or paper
napkins, or in someone's head. A word processor provides spell checking, formatting, and document templates that function as
"containers" for requirements. You can keep them all in one place and send them around for review. However, Word documents cannot
help you sort and filter large requirements lists or establish traceability.
Spreadsheets such as Microsoft Excel facilitate more sophisticated sorting and filtering, but at the expense of losing the context a
document provides. Also, you can use spreadsheets for traceability, but the operations are still manual.
A homegrown tool based on a database has some of the same advantages as a spreadsheet; plus, they are often pretty good for doing
filtering and traceability. However, because the tool's functionality is often specific to a given project structure, it is hard to adapt. It may
also lack complete and up-to-date documentation.
Tools designed specifically for requirements management (RM tools) are usually a little more complex than Word or Excel but not nearly
as complicated as a compiler or an IDE. They also offer significant advantages:
z

Almost all RM tools allow you to import existing requirements documents into the tool. If both the tool and your documents are
good, the tool will be able to identify automatically the actual requirements in the document. IBM Rational RequisitePro provides
a dynamic link from the requirements in the document to those stored in the tool (or backend database), so that the requirements
are always "live."

RM tools allow you to easily create requirement types and give them attributes. This allows for sorting and filtering, giving the user
a flexible query mechanism to find requirements of interest quite easily. These tools also allow you to sort requirements by
attribute values. For example, if you had the attributes "user priority" and "risk" for your feature requirement type, you could create
the following query: "Show me all the high-priority, high-risk features." This could help you decide which features to implement in
early iterations to ensure that you do not leave out important functionality and that you mitigate risk early in the project.

Good RM tools provide traceability between requirements; a really good one provides traceability to other tools and artifacts, such
as designs and tests. Traceability is an important capability that helps you validate and verify your system.

A requirements management best practice is to track each requirement's history. An RM tool can help with this, too. It tells you not
only the requirements' origin, but also why decisions were made and who made them.

RM tools can also help with baselining: taking a "snapshot" of your requirements at a particular point in time that you can compare
to future snapshots. A baseline provides a stable set of requirements upon which to work. It also provides a branch point in the
project lifecycle that you can reference, should you want to copy your requirements for a new development effort.

So, like compilers and IDEs, RM tools help developers do things they could not easily do manually (or perhaps not at all) and helps them
achieve greater efficiency.

Manage change
Good development shops manage the changes to their code. Developers write code according to designs and specifications; they do not
add features at their own discretion. In addition, the code is under source control; when they change the code, developers specify why

7/15/2004

Writing good requirements is a lot like writing good code

Page 7 of 8

they did it. Periodically, they also baseline the code, integrate it, and test it for release.
Requirements need change control, too. Change is inevitable; it is important to plan for it. At the beginning of a project, requirements are
usually (and appropriately) in a state of flux. But at some point, before too much code gets written, it is important to draw a line in the sand
and create a requirements baseline. After that, requirements changes must be approved, typically by an appointed Change Control Board
(CCB). However, some organizations designate just one or two people to review change requests periodically.
Teams that do not have a requirements change control process must field change requests from all quarters and often have difficulty
saying "no." If you want to avoid this, along with having to constantly rewrite code to keep pace with the requirements changes, start a
CCB or the equivalent. A process for reviewing changes can help ensure that the changes you make will provide business value and that
everyone understands their impact. Changes with no business value simply eat up resources with little reward. Similarly, changes that do
have business value but would also have great impact on existing requirements, designs, code, and tests may not be worth the effort.
Another way to assess a change's potential value and feasibility is through traceability. It allows you to track (trace) the justification for a
requirement and understand all related artifacts. By tracing a software requirements to higher-level business, or user requirements, you
can ensure that it has value. If you cannot trace it in this way, the software requirement probably does not have a business justification. In
addition, by tracing from high-level to low-level requirements and on to design, code, and test, you can easily see the impact of a
requirements change. A traceability matrix or better yet an RM tool will clearly show all relevant artifacts and provide the knowledge
necessary to decide whether a change request is worthwhile.

Planning
Most successful software development projects have a plan that guides the project, specifying who does what, how things will be done
and what the milestones will be. The architect typically creates a document that provides a comprehensive overview of the system's
architecture. It also enables communication between the architect and other project team members regarding architecturally significant
decisions and guides developers as they implement the system.
Like these plan documents, a requirements management (RM) plan can provide tremendous benefit to a project. For developers who
write requirements, the plan describes necessary requirements artifacts, along with requirement types and their respective attributes. It
specifies information the developers must collect and mechanisms for controlling requirements changes.
As we saw earlier, requirement types might include business needs, features, and functional and non-functional software requirements.
You may also have user requirements and marketing requirements. A plan encourages you to think about and specify requirement types
you will need, which in turn helps to ensure consistency and readability for written requirements.
As we also noted earlier, attributes provide supplemental information that helps you understand and use requirements specifications more
effectively.
The RM plan also describes the documents you will use. RUP recommends three categories: a vision document, use-case documents,
and a supplementary specification document describing requirements that do not warrant use cases.
The RM plan also describes the change management process so that everyone on the project will understand it.
If you are already working on a project that does not have an RM plan, you can write one yourself. It doesn't have to be long: One or two
pages might contain all the information you need to promote the creation of consistent, high-quality requirements.

Good developers can write good requirements


The principles and practices developers typically apply to creating code can serve them well when they have to elicit and record
requirements. If you are a developer who thinks that you do not have the background or education to write effective requirements, I hope
this article has convinced you otherwise. Simply apply the knowledge and the principles you use every day to this new task, and you will
succeed.

Notes
1 IEEE Recommended Practice for Software Requirements Specifications, Software Engineering Standards Committee of the IEEE

Computer Society. Approved 25 June 1998


2 In RUP, look under Artifacts -> Requirements Artifact Set -> Use-Case Model -> Use-Case Modeling Guidelines. Also see IEEE

Recommended Practice for Software Requirements Specifications, Software Engineering Standards Committee of the IEEE Computer
Society. Approved 25 June 1998

7/15/2004

Writing good requirements is a lot like writing good code

Page 8 of 8

3 Unified Modeling Language, or UML, includes the concepts of extend and includes. You can learn about these advanced topics in IBM

Rational Unified Process. Another good reference is Use Case Modeling by Kurt Bittner and Ian Spence (Addison-Wesley 2003).

About the author


Jim Heumann has worked in the software industry since 1982, doing analysis, development, design, training, and project management for
both large and small organizations. Since joining Rational in 1998, he has focused on helping customers understand and implement
software development processes and tools. Currently, as IBM Rational's requirements management evangelist, he specializes in frontend development issues. He holds an M.S. in management information systems from the University of Arizona.

What do you think of this document?


Killer! (5)

Good stuff (4)

So-so; not bad (3)

Needs work (2)

Lame! (1)

Comments?

Submit feedback
developerWorks

About IBM

> Rational

| Privacy | Terms of use | Contact

7/15/2004

The IBM Software Development Platform partner ecosystem


Copyright IBM Corporation 2004

Page 1 of 7
http://www-106.ibm.com/developerworks/rational/library/5360.html

Search for:

within
Use + - ( ) " "

IBM home
developerWorks

All of dW

Search help

| Products & services | Support & downloads | My account

> Rational

The IBM Software Development Platform partner


ecosystem
Peter Stolinsky
IBM
12 Jul 2004
from The Rational Edge: A rich ecosystem of hundreds of IBM partners extends the IBM Software
Development Platform, delivering products and services that span the entire application
development lifecycle and address both horizontal and domain-specific business needs. This article
describes that ecosystem and its value to IBM clients.
The IBM Software Development Platform offers clients a
simplified, modular approach to automating and integrating
the software development process. Open and proven, it
enables companies to develop software to better respond
to their competition and their own clients. A rich ecosystem
of hundreds of IBM partners adds value to this platform,
delivering products and services that span the entire
application development lifecycle and address both
horizontal and domain-specific business needs. These
partners also use the IBM Software Development Platform
in their own development efforts, leveraging the
ecosystems technology, technical support, and marketing
resources. This article describes that ecosystem and the
value it brings to IBM clients.

Contents:
The IBM Software
Development Platform
business partner ecosystem
The Eclipse tools integration
platform
Components of the IBM
Software Development
Platform
Support for the IBM
business partner ecosystem
About the author
Rate this article
Subscriptions:
dW newsletters
dW Subscription
(CDs and downloads)

One of the major success factors for enterprises pursuing an On Demand business model is software development capability. In fact,
software development capability is a strategic corporate resource. More than ever, corporate responsiveness and agility depend on IT
initiatives. And based on its experience with thousands of projects, IBM has learned that the most successful IT departments follow four
imperatives to deliver high-quality software quickly and at a lower cost than is typical:
z
z
z
z

Develop iteratively
Focus on architecture
Continuously ensure quality
Manage change and assets

These imperatives are the foundation of a multifaceted, integrated IBM Software Development Platform that can help developers build,
integrate, extend, modernize, and deploy software-based systems. IBMs primary objective for this Platform and its broad partner
ecosystem is to help clients optimize their software development processes and improve their ability to operate as an On Demand
business. Because the IBM Software Development Platform has an extensible architecture based on open standards, IBM clients can
choose from a range of complementary approaches and tools from IBM and other industry participants that effectively extend the Platform.
The IBM Software Development Platform is grounded in a holistic view of the application development lifecycle and its challenges. The On
Demand business model requires that development platforms support a rich, integrated development and deployment experience. This
approach is congruent with the desire developers have to acquire knowledge and skills that span the full lifecycle, from understanding the
business to monitoring and managing running applications. The Platform combines products and services from multiple sources that
support this full lifecycle involvement for corporate and individual developers, software vendors, and systems integrators.
By supporting open source and heterogeneous environments, and clearly defining application programming interfaces (APIs), the IBM
Software Development Platform ensures easy integration of new tools and lowers the cost of developing and integrating new enterprise
applications within existing environments. It also enables IT organizations to provide extended functionality quickly and easily, and at
relatively low cost.

The Rational Edge--July 2004

The IBM Software Development Platform partner ecosystem

Page 2 of 7

The IBM Software Development Platform business partner ecosystem


This extensible platform facilitates the integration of new functions and technology. Its modularity enables developers to adapt to new
standards and include them in the platform. As new industry standards are ratified, such as Unified Modeling Language (UML) 2.0 and
the Reusable Asset Specification (RAS), IBM will incorporate them and add value to the platform.
IBM business partners offer enrichments to the IBM Software Development Platform that
meet a wide range of developer and project team needs, including application and
industry expertise, implementation services, and extensions to the platform. The
participation of more and more business partners creates an ecosystem effect. The
Platform becomes richer and more valuable to both partners and clients which in turn
attracts new partners and clients who also contribute to and benefit from the Platforms
increasing value.

Unisys consultants and clients benefit


from the IBM Software Development
Platform
Unisys Corporation uses the IBM Software
Development Platform to help better serve its
customers and deliver differentiated services
in the fiercely competitive systems integration
business. The Platform, which includes
The IBM Software Development Platform partner ecosystem comprises a broad range of Rational tools and best practices, helps
companies some focusing on technology development and others on services delivery Unisys implement model-driven architectures
all striving to help developers and project teams using the Platform. For example,
and develop Web services.
ecosystem members contribute:
z
z
z

Horizontal extensions that add functionality for specific tasks, such as project risk
management, project impact assessment, and so on.
Horizontal integrations with other development tools, applications, and
frameworks to support work throughout the application development lifecycle.
Domain-specific extensions to enable functionality for specific industries and
industry applications.

The ecosystem is a key reason that the IBM Software Development Platform is an
industry leader. IBM plans to continue improving both its technology and the program
framework supporting the Platforms ecosystem to make it even easier for new partners
to join in.

As part of its 3D Visual Enterprise approach,


Unisys creates a digital map of each clients
business from business strategy to
infrastructure implementation. To accomplish
this, Unisys needed a set of tools and
processes that could extend beyond the
traditional software development space and
incorporate business architecture as well as
detailed services-based architecture into
these visual models. The Unisys team also
focuses on increasing software reusability
and leveraging its intellectual capital, so they
needed technologies that would support
these goals as well.

The Eclipse tools integration platform


The IBM Software Development Platform is based on the Eclipse platform, and many
business partner contributions are built using Eclipse as well. IBM is a founding member
of The Eclipse Foundation, a nonprofit, member-supported corporation that hosts
community-based open source projects. IBM contributed $40 million (US dollars) in
software tools to start the Eclipse project, which creates royalty-free technology and a
universal platform for development tools integration, modeling, testing, and rich-client
construction that offers deep levels of semantic integration.

Our decision to use IBM Rational solutions


was not based on any one tool; it was the
notion that this is a holistic strategy of how to
build a solution, says Ed Ferrara, architect
director at Unisys. The platforms
combination of Rational tools, support for
UML, best practices, and process provides a
complete solution for his companys needs.
The Eclipse platform provides an open environment for enterprise development with the Using UML and IBM Rational Unified
Process, as well as BPEL (Business
capability to support all phases of the application development lifecycle, including
Process Execution Language)based
analysis, requirements, design, development, testing, software configuration
representations of our clients business
management, defect tracking, project management, and so on. Its main components
architecture, we can get disparate
include a universal platform for development tool integration and a Java development
environment built with Eclipse. Many organizations extend the platform and use it to build populations different groups all
understanding exactly what we are doing and
tools that support specific kinds of development approaches and technologies. At the
what we are building. Unisys then uses RUP
heart of the Eclipse platform is an extensive toolset with core capabilities, plus support
and other tools in the IBM Software
for extensions through a plug-in architecture.
Development Platform to enable reuse of
software artifacts across teams and projects,
More than fifty major software companies are members of the Eclipse Foundation,
which benefits both Unisys consultants and
contributing software and using Eclipse technology within their products. Eclipse
their clients.
technology is available to anyone online, and software developers have made more than
21 million download requests. This widespread interest in and use of Eclipse gives it
maturity and breadth; it spurs ongoing development and increasing value. Figure 1 shows the core Eclipse framework and some of the
extension APIs.

7/15/2004

The IBM Software Development Platform partner ecosystem

Page 3 of 7

Figure 1: Components of a development-tool chain based on the Eclipse framework, with potential
integration points
The Eclipse Modeling Framework
The Eclipse Modeling Framework (EMF) is a fundamental part of Eclipse, enabling the platforms modeling capabilities to interoperate
with other tools and applications. Developers can use the modeling framework and code generation facility to build tools and other
applications based on a structured data model. Described in the XML Metadata Interchange (XMI) specification an Object
Management Group (OMG) specification for adding information descriptors for data EMF provides tools and runtime support to
produce a set of Java classes for the model, a set of adapter classes that enable viewing and command-based editing of the model, and
a basic editor. Models can be specified using annotated Java, XML documents, or modeling tools such as IBM Rational Rose, and then
imported into EMF.
Most important, EMF serves as a common alphabet and provides a foundation for interoperability with other EMF-based tools and
applications. The UML standard for representing business and data models works in conjunction with EMF to create a common language.
Using this language, two applications that use the same API can exchange meaningful information. UML is currently evolving, based on
industry and user feedback; IBM, in conjunction with the OMG and other industry participants, is focusing significant effort on developing
UML 2.0.

The Eclipse C/C++ Development Tools project


The Eclipse Foundation is expanding the capabilities of Eclipse for millions of C/C++ developers through the C/C++ Development Tools
(CDT) project, which will provide a fully functional IDE for the Eclipse platform. The CDT project has released version 1.2 and is currently
working on version 2.0, to be finalized later this year. Several project members have already released commercial products based on
CDT 1.2, including QNX, Red Hat, Timesys, and Tensilica.

The Eclipse Hyades project


This new open source project focuses on full lifecycle integration of advanced test and trace facilities for automated software quality. The
Hyades Project Framework will make it easier to integrate a broad range of functional verification, quality assessment, and load-testing
tools with the Eclipse platforms workbench and other tools. Now in its early form, the Hyades Testing Framework provides a single view
of test assets and the testing lifecycle for all tools in the IBM Software Development Platform. It facilitates integration of test activities
throughout the lifecycle, encouraging test-first approaches to development and enhancing traceability from test artifacts to other lifecycle
artifacts.
With its shared open integration framework, Hyades supports better tool interoperability and gives developers more choice in vendors and
access to a richer set of offerings. Because it does not specify a testing methodology, it provides flexibility and substantial opportunities
for services partners to add value. This will allow Hyades-based tools to address a full range of Automated Software Quality assurance

7/15/2004

The IBM Software Development Platform partner ecosystem

Page 4 of 7

processes from static code analysis through automated functional testing and performance testing.
Hyades will implement an OMG-defined UML testing profile to maintain test case, test trace, test objective, and verification artifacts. It will
allow testers to evaluate objectives related to performance and scalability for a range of real-world deployment environments, including
alternate mixes of server and network interconnection technologies. It will also support new approaches to quality assessment testing that
link the initial requirements definition, an object-oriented application model, and test-management evaluation tools.

Components of the IBM Software Development Platform


The IBM Software Development Platform is built with a set of shared components and models targeted to serve each member of a
software development team (see Figure 2). All models are defined using EMF, which enables them to interoperate with other tools and
applications. The Platform also takes advantage of an infrastructure for effective teamwork, including requirements, code, test, systems,
security, and project management capabilities. The infrastructure is built using IBM middleware components, including WebSphere Portal,
WebSphere Application Server, DB2, Lotus Domino, and Tivoli Identity Manager and Configuration Manager. Openness enables
integration with other leading middleware and application solutions.
IBM is committed to evolving the IBM Software Development Platform by increasing integration among core components and enhance
developer and team productivity capability. IBM will also increase the Platforms openness to help clients and business partners easily
integrate new components into their own solutions. IBM also plans to update and enhance Platform elements on a regular basis,
leveraging recent technology innovations and contributions from other organizations.

Figure 2: The IBM Software Development Platform supports development teams and individuals in the
development process
The following sections describe the Platforms component products and relevant ecosystem member activities that add value to the
Platform.

IBM WebSphere Application Server


The IBM WebSphere Application Server (WSAD) and its complementary business partner offerings enable companies to build, test,
deploy, and manage mission-critical J2EE applications. Enterprises can choose from a wide array of vendors offering WSAD-based
solutions that fit almost any unique need.

IBM WebSphere Studio Workbench


The WebSphere Studio Workbench is optimized for developing WSAD applications. Based on the Eclipse framework, the IBM
WebSphere Studio Workbench is a runtime integration platform that enables tool providers to build platform-neutral, enterprise-ready
application development tools. The WebSphere Studio Tool Development Kit (TDK), included with WebSphere Studio Workbench, helps
tool builders create plug-ins for WebSphere Studio Workbench that integrate with one another. The Ready for IBM WebSphere Studio
software validation program certifies integrations and plug-ins for IBMs Java IDE family and WebSphere Studio Workbench.

7/15/2004

The IBM Software Development Platform partner ecosystem

Page 5 of 7

IBM Tivoli software


IBM Tivoli Monitoring watches over essential system resources to detect bottlenecks and potential problems and to automatically
recover data in critical situations. Using IBM Tivoli Monitoring with Rational testing tools, developers can simulate multiple clients,
projecting how a system is likely to respond under load. They then can set accurate performance objectives for the software under
development; they can measure for these objectives during the test phase, using the same Tivoli Monitoring software.
IBM Tivoli Identity Manager provides the security within the IBM Software Development Platform, enabling developers to add security
access, identity management, and privacy management to protect software development projects. Managers can also use it to assign
appropriate tools, authorize access to an application under development, and offer benefits, based on roles such as developer, architect,
and tester, and on individual identities. For example, they may want to automatically load tools from a central source onto an individuals
personal machine. Tivoli Identity Manager includes a suite of security functions that are easy to deployits single sign-on and automated
password management can help cut project costs.
The IBM Tivoli Configuration Manager automates the distribution of code and provides the ability to undo changes if they cause
problems. Its software distribution module enables rapid and efficient deployment of complex, mission-critical applications in development
and production environments to multiple locations from a central point.

IBM Lotus products and tools


IBM Lotus Domino is a multi-platform foundation for collaboration and e-business. This
enterprise-class messaging and collaboration system is built to maximize worker
productivity by leveraging the experience and expertise of individuals, teams, and
extended communities. It helps maximize server availability with clustering, transaction
logging, server fault recovery, and automated diagnostic tools; it also helps reduce the
time and cost of software deployment and configuration.

Flashline, LogicLibrary, and Codagen


integrations with Rational products
extend the IBM Software Development
Platform
Flashline is a repository for managing both
Reusable Asset Specification (RAS) and nonRAS assets. It integrates with a broad set of
the IBM Software Development Platform

IBM Lotus Domino Designer helps developers rapidly build, test, and deploy security- components, including ClearCase,

rich IBM Lotus Notes or Lotus Domino collaborative and/or mission-critical applications. ClearQuest, XDE and WebSphere Studio
Using the Lotus Domino Toolkit for WebSphere Studio, developers can start building
Application Developer. Flashline Inc. uses
JavaServer Pages simply by dragging and dropping existing Domino design elements, the IBM Software Development Platform to
such as forms, views, and agents.
increase enterprise visibility into how teams
are creating and using software assets. This
allows IT managers to determine whether

IBM Lotus Enterprise Integrator allows a high-performance, scalable exchange of


data between Lotus Domino and relational database systems as well as native access to they are in compliance with corporate and
those database systems. With point-and-click ease, developers can create, manage, and architectural mandates and helps to reduce
duplication of effort. As projects are
schedule batch and real-time access to provide integration with relational systems such
deployed, Flashline automatically tracks both
as DB2 and Oracle databases or enterprise resource planning (ERP) systems such as
time and cost savings attributable to reuse of
SAP. This product enables the rapid creation of automated business-process solutions
existing assets. It also enables software
that can increase employee productivity.
developed and managed in any of the IBM
Software Development Platform tools to be
The IBM Lotus Workplace Builder is an application development framework for
leveraged across projects and throughout an
building project-based collaborative applications.
enterprise. Through integration with IBM
Rational ClearCase, Flashline captures and
extends metadata about key software assets,
IBM DB2 Universal Database
making them easier to discover, evaluate,
The IBM DB2 Universal Database (UDB) plays an important role in the IBM Software
and reuse in multiple projects. Through
Development Platform by enabling developers to write in one format and by supporting
integration with IBM Rational ClearQuest,
development for both Java and Microsoft .NET applications. All elements of the DB2
Flashline includes details, such as defects
portfolio database servers, business intelligence software, enterprise content
and change requests within its asset
management software, data management tools, and information integration software
metadata.
support the On Demand business model.
The IBM DB2 and Linux Validation Program is the basis for the Ready for IBM DB2
Software for Linux certification. This program provides a process for ensuring that DB2
UDB operates successfully within a variety of Linux environments. It specifically tests for
DB2 UDB interoperability with operating systemlevel software on Linux. Vendors that
have undergone the Linux validation process can use the certification in their marketing
campaigns, assuring clients and partners that their product has been tested with DB2
UDB for interoperability.

IBM Rational development tools


For many years, IBM Rational Suite tools have set the benchmark for software

LogicLibrarys Logidex is a software


development asset (SDA) metadata catalog
that simplifies the creation, migration, and
integration of enterprise applications. Logidex
provides broad support for the IBM Software
Development Platform, including integration
with IBM WebSphere Studio, Eclipse, IBM
Rational XDE, and IBM Rational ClearCase,
as well as support for the Reusable Asset
Specification (RAS) and the IBM Rational
Unified Process (RUP). Validated as Ready

7/15/2004

The IBM Software Development Platform partner ecosystem

development infrastructures in thousands of corporations worldwide. Now, as part of the


IBM Software Development Platform ecosystem, Rational continues the long history of
partnering with software vendors and service providers to extend Rational tools, starting
with RoseLink, a strong ecosystem that helped to drive Rational Rose to its leadership
position in visual modeling. Rational software vendor and services partners have built
strong businesses within this ecosystem, extending Rational Rose and providing
services to customers implementing it in their organizations.
The ecosystem around Rational tools has also led to the development of hundreds of
plug-ins for everything from process for RUP IBM Rational Process Workbench, for
example to asset management repository integrations with Rational ClearCase. IBM
Rational is continuing to enhance both role-based and team infrastructure functionality in
all its solutions. It is also working to ensure that a broad range of technology and
services partners can easily integrate and extend the IBM Software Development
Platform, using its open APIs.
IBM Rational ClearCase, a leading software configuration management solution, has a
long history of helping developers manage software and provide a stronger user
experience through integration with IDEs. Rational ClearCase integrates with several
IDEs, including WebSphere Studio Application Developer, QNX Neutrino, and Green
Hills RTOS.
IBM Rational Rose and Rational Rose XDE software products are leaders in the visual
modeling market. They provide open APIs to facilitate partner integrations and
complementary product development. With horizontal tools ranging from the Flashline
Registry and LogicLibrary Logidex integrations to the JacZone WayPointer UML
modeling tool and Codagen Architect, the Rational Rose XDE ecosystem is thriving (see
sidebar).
The partner ecosystem for IBM Rational Unified Process, or RUP, was born in
2001, shortly after the introduction of Rationals J2EE process plug-in for RUP. From
there, Rational launched Rational Process Workbench (RPW), designed specifically to
facilitate partner plug-ins for RUP. This spawned a series of plug-ins and extensions,
ranging from the Fair Isaacs RUP Plug-in for Business Rules and the Klocworks RUP
Plug-in for Existing Software Reuse to Jaczones incorporation of RUP best practices in
its Waypointer UML modeling tool.

Page 6 of 7

for IBM WebSphere Studio Software, Logidex


tightly integrates with both WebSphere
Studio and Eclipse. The Logidex RAS Plug-in
for Rational XDE makes it easy for
developers to search, access, and use RAS
assets and to import them into Rational XDE
for UML-based development activities. The
Logidex ClearCase Asset Adapter enables
users to quickly and easily incorporate legacy
software assets from Rational ClearCase into
a Logidex library. Logidexs workflow
capabilities allow enterprises to configure
approval processes that support adherence
to RUP.
Logidexs support for the IBM Software
Development Platform allows business
analysts, architects and developers to easily
capture software assets and artifacts and
bring them directly into their Eclipse or
WebSphere Studio workspace enabling
reuse of software assets throughout the
enterprise and helping customers reduce the
time and complexity of their application
development and integration projects.
Codagen Technologies offers model-driven
architecture tools to support the development
of both J2EE and Microsoft .NET
applications. Codagen Architect integrates
with Rational Rose XDE to take advantage of
the IBM Software Development Platform and
its unique capabilities to support both J2EE
and .NET development. Using Codagen
Architect with XDE increases the abstraction
level for application modeling and
architecture, promotes the separation of
business logic from implementation, and
enables developers to concentrate on
application logic rather than architectural
code.

The strong market position of IBM Rational TestStudio has also encouraged strong
partner involvement. Products such as Scapa StressTest are integrated with Rationals
test products to broaden their value.We have already seen the benefits of integrating
our product with IBM Rational Visual Test software, and with the additional integration
of IBM Rational Suite TestStudio software, we provide a first-class test management framework option for our customers, says Scapa
CEO Mike Norman. This framework also allows companies to manage our Citrix testing tool in the same TestStudio they use to manage
their existing Rational test tools.

Support for the IBM business partner ecosystem


The IBM PartnerWorld program offers business partners access to technology, world-class technical support, software development
tools, education, and comarketing opportunities. Serving more than 90,000 partners, it provides a core set of benefits plus special
additions for support of certain IBM brands including Rational, WebSphere, Lotus and DB2 and the IBM Software Development
Platform.

Special programs for the IBM Software Development Platform


PartnerWorld partners that focus on the IBM Software Development Platform can participate in special Ready for IBM programs, tailored
for products such as WebSphere Studio and DB2 Software for Linux, that provide additional targeted support, enablement, marketing,
and promotion. IBM plans to add a comprehensive Ready for IBM Rational Software validation and certification program for these
partners, which will also provide special enablement and marketing benefits.
IBMs developerWorks Web portal rated one of the best developer Web sites by Summit Strategies and recipient of the 2004 Jolt
award for Best Community Site posts technical assistance and educational materials for PartnerWorld members that are writing
applications to run on IBM and other platforms. At the end of 2003, approximately 3.5 million developers were registered with

7/15/2004

The IBM Software Development Platform partner ecosystem

Page 7 of 7

developerWorks.

Emphasis on vertical solutions


Today's IBM clients want complete solutions tailored to their industry. That is why IBM is aligning with software vendors along industry
and vertical-market lines. IBMs new go-to-market and enablement programs, initiatives, and PartnerWorld technical and marketing
assistance will help its business partners leverage On Demand opportunities. In combination, PartnerWorlds strong support for IBM
business partners and the value of the IBM Software Development Platform ecosystem will continue to help corporate developers,
individual developers, and services companies stay competitive in an increasingly On Demand world.

About the author


Peter Stolinsky, director of business development for the IBM Rational brand, has spent more than twenty years in the high technology
industry. Before IBM acquired Rational, as director of business development he was responsible for Rational's ISV alliance team and
platform partnerships. Prior to that, he directed corporate strategic alliances for Xerox Corporation and led the companys marketing and
channel strategy for desktop and color printers, software solutions, and services. He has also held senior marketing, business
development, and management positions at a number of successful start-ups involved in a range of software and hardware applications.
He attended Skidmore College and Fairleigh Dickinson University, completing a B.A. in English and business as well as course work
toward an M.B.A. in marketing and finance.

What do you think of this document?


Killer! (5)

Good stuff (4)

So-so; not bad (3)

Needs work (2)

Lame! (1)

Comments?

Submit feedback
developerWorks

About IBM

> Rational

| Privacy | Terms of use | Contact

7/15/2004

Enhancing RUP for CMMI compliance: A methodological approach


Copyright IBM Corporation 2004.

http://www-106.ibm.com/developerworks/rational/library/5318.html

Search for:

within
Use + - ( ) " "

IBM home
developerWorks

Page 1 of 15

All of dW

Search help

| Products & services | Support & downloads | My account

> Rational

Enhancing RUP for CMMI compliance: A


methodological approach
Walcelio Melo
Unisys Corporation
8 Jul 2004

Contents:
The approach
New process elements

Conclusion
from The Rational Edge: This paper traces the approach Unisys GPS Blueprinting used to evaluate
References
the Rational Unified Process in support of the Unisys Business Blueprint, a business and systems
modeling architecture that integrates business vision and IT execution to drive organizational agility. Appendix A: Related work
IBM Rational Unified Process, or RUP, provides an
outstanding foundation that allows Unisys to achieve a
higher level of process capabilities in many different CMMI
process areas. Moreover, RUP allows the selection and
customization of its process elements to adhere to the
particularities inherent in each Unisys Global Public
Sector project, program, or business unit.

Notes
About the author
Rate this article
Subscriptions:
dW newsletters
dW Subscription
(CDs and downloads)

However, RUP is weak in some CMMI process areas. In a


comprehensive study performed by the Software
Engineering Institute, RUP was assessed against CMMI
Continuous Representation.2 Although RUP performed
well in most of the CMMI process areas, the assessment concluded that RUP was weak in the areas of Supplier Agreement Management
and Technical Solution process area practices.
In this paper1, I describe new process elements that allow RUP to overcome these weaknesses. I discuss some experiences in which
RUP has been used to assist IT organizations in achieving a higher level of process capabilities, then present the software process
improvement approach that we are using to guide our work. I also describe the new process elements that would be created to overcome
the identified weakness related to CMMI assessment.

A philosophy of improving process


A "software process" includes all the activities necessary to manage, develop, acquire, and maintain software products or services. The
existence of a defined and sustained process offers a foundation for organizational planning and continuous improvement. When software
process is well-established in an organization, it serves as a vehicle for learning, reuse, and the promotion of best practices.
To improve software process quality, we must understand the organization that will benefit from the improvement. The best way to gain
this understanding is by studying representative sample projects, and paying particular attention to their development, management,
support, and operational practices. This helps identify points in the process that need to be improved, missing practices that need to be
included, and practices used in some projects that would bring business benefits if extended to the entire organization.
To help evaluate process practices and identify improvement opportunities, we can compare current capabilities of an organization's
processes with the best practices recommended by a reference model. This comparison serves as a basis to derive improvement plans,
and specifically allows us to evaluate an organization's capability to produce quality results on time and under the stipulated budget.3
Several reference models for process capability determination have been proposed, including CMMI (Capability Maturity Model Integration) and ISO/IEC 15504 (a standard for software process assessment agreed by ISO and the International Electrotechnical
Commission). They suggest process practices that should be implemented in an organization to better perform and successfully achieve
its business goals. Although ISO/IEC 15504 is an international standard for determining process capability, in the US the CMMI is
unquestionably the most popular model, and CMMI complies with the ISO/IEC 1504 standard.

The Rational Edge--July 2004

7/15/2004

Enhancing RUP for CMMI compliance: A methodological approach

Page 2 of 15

CMMI is designed to help an organization improve processes used to manage the development, acquisition, and maintenance of products
or services. CMMI is used as a guide for selecting process improvement strategies by facilitating the determination of current process
capabilities and the identification of the issues most critical to software quality and process improvement.

The problem
Based on the assumption that there are fundamental practices that should be incorporated in all the processes executed in the
organization, a standard process for an organization is typically defined by considering best practices and suggestions from international
standards, industrial organizations, governmental guidelines, in-house best practices, etc. (e.g., RUP, ISO/IEC 12207, etc). But for each
project, the standard process must be adapted to the particularities of the organization and the project itself.
Following this strategy, Unisys created the Unisys Business Blueprint. This is a business and systems modeling architecture that
integrates business vision and IT execution to drive organizational agility. To make organizations successful in meeting the requirements
of today's fast-paced information world Unisys has developed Blueprinting to align business with information technology and provide
traceability across the whole enterprise. Blueprinting is now the foundation for most of the Unisys business operations, including Unisys
GPS geographies, programs, and projects. All are encouraged to use Unisys Business Blueprint Methodology for development,
management, and transition of Unisys solutions.
RUP is an important component of Unisys Business Blueprint. RUP allows us to select and customize its process elements to adhere to
the particularities inherent in each Unisys GPS project, program, or business unit. Moreover, RUP provides an outstanding foundation
that allows Unisys to achieve a higher level of process capabilities in many different CMMI process areas.
However, RUP is weak in some CMMI process areas. In a comprehensive study performed by the Software Engineering Institute, RUP
was assessed against CMMI Continuous Representation.4 Although RUP performed well in most of the CMMI process areas, the
following weaknesses were identified:
Supplier Agreement Management is out of the scope of RUP; that is, RUP in its current form does not explicitly deal with
managing work from external suppliers to the project. This is an issue for projects in which Unisys needs to employ
subcontractors.
RUP does not explicitly support all the Technical Solution Process Area's practices. For example, RUP does not explicitly
cover consideration of design alternatives except at the architectural level, and RUP does not explicitly cover the use of
selection criteria for product solutions or components.
In a 2003 study, Manzoni and Price evaluated RUP against SW-CMM.5 For each key practice (KP) identified in each key process area
(KPA) of SW-CMM levels 2 and 3, the Rational Unified Process was assessed to determine whether it satisfied the KPA or not. The report
concluded that an organization using RUP would need to complement it to conform to SW-CMM. According to the study, SW-CMM key
process areas best supported by RUP are requirements management, software project planning, software project tracking and oversight,
software configuration management, organization process definition, and software product engineering. RUP offers good support to both
integrated software management and inter-group coordination KPAs; RUP offers low support for software quality assurance, organization
process focus, and peer review KPAs; and RUP does not support software subcontract management or training KPAs.
Based on these analytical studies, we conclude that an organization would need to enhance its version of RUP to improve its process
capabilities.

The approach
In this section, I will describe the approach Unisys GPS Blueprint is using to enhance Unisys Blueprint Methodology to increase its level
of compliance with CMMI. As indicated in Figure 1, there is a symbiotic relationship between assessment, capability maturity
determination, and process improvement.6 The capacity determination of a process in our case, the Unisys Blueprint methodology, or
more precisely the RUP product is used to identify weaknesses that motivate improvements. Such improvements reflect changes in
the process in our case, changes to the RUP product.

7/15/2004

Enhancing RUP for CMMI compliance: A methodological approach

Page 3 of 15

Figure 1: Software process assessment and improvement


Models are used as references for process assessment and for determining improvement opportunities. Nevertheless, software process
continuous improvement demands a disciplined approach. In our case, we have adopted an incremental, inductive improvement
approach called the Quality Improvement Paradigm QIP.
QIP has been successfully applied for many years at several organizations. HP, Daimler-Benz, NASA, Nokia, and Motorola7 offer a few
examples where higher levels of maturity and return on investment have been obtained via the use of QIP and its supporting methods.

QIP: A two-loop feedback process


The QIP is a two-loop feedback process that includes a project loop and an organization loop.8 This is a variation of the scientific method
consisting of the steps illustrated in Figure 2:

Figure 2: QIP intra- and inter-loop


As shown in Figure 2, the QIP process involves the following steps:
1.

Characterize and understand the organization and its process capabilities. To do so, perform capability determination and process

7/15/2004

Enhancing RUP for CMMI compliance: A methodological approach

Page 4 of 15

assessment of the current projects and its environment with respect to reference models and metrics.
2.

Set quantifiable goals for successful project performance and improvement.

3.

Choose the appropriate process and supporting techniques, methods, and tools. New processes may need to be created.
However, it is much more likely that existing processes will be tailored to fulfill the gaps identified during the characterization and
understanding of the organization.

4.

Execute the processes, construct the products, and collect and validate the prescribed data. According to AINSI,9 after issues are
identified and improvement options determined, a pilot project should be executed using new practices and/or tools. The scope,
participants, and project evaluation strategy should be defined before its execution. After the pilot project execution is finished and
the results are analyzed, the technology might be transferred to the rest of the organization or other pilot projects should be
executed.

5.

Analyze the data to evaluate the current practices, determine problems, record findings, and recommend future project
improvements. This step is crucial to the success of this solution. It is here that both project and organization learning is leveraged.
The feedback obtained by analyzing the measurable goals and process effectiveness will support the continuous improvement of
both our business and our methodology.

6.

Package the experience in the form of models and other forms of structured knowledge.

The following sections outline the approach to be used in each of the above steps.
Capability determination and process assessment
In the study performed by the Software Engineering Institute, RUP was assessed against CMMI Continuous Representation.10 The
weaknesses of RUP regarding this reference model have been identified and suggestions for improvement have been outlined.
Set quantifiable goals
The Goal/Question/Metric (GQM) is the method for defining software measurement.11 GQM allows us to define a measurement model on
three levels:
z

Conceptual level (goal): A goal is defined for an object, for a variety of reasons, with respect to various models of quality, from
various points of view, and relative to a particular environment/project.

Operational level (question): A set of questions is used to define models of the object of study and then focuses on that object to
characterize the assessment or achievement of a specific goal.

Quantitative level (metric): A set of metrics, based on the models, is associated with every question in order to answer it in a
measurable way.

Table 1 provides a sample of a Goal-Questions-Metrics model used in our study.

Table 1: GQM sample

GOAL

Purpose

Improve RUP

Issue

Process Capability level

Process Area

Technical Solution and Supplier Management

Viewpoint

Process Engineer

Environment

Solution Development

QUESTION What is the current level of compliance between RUP and CMMI Technical Solution process area?
METRIC

# of CMMI Technical Solution process practices supported by RUP

7/15/2004

Enhancing RUP for CMMI compliance: A methodological approach

Page 5 of 15

# of CMMI Technical Solution specific goals supported by RUP


QUESTION What is the current level of support RUP provides vis--vis CMMI Supplier Management process area?
# of CMMI Supplier Management process practices supported by RUP
METRIC
# of CMMI Supplier Management specific goals supported by RUP

Choose the processes


Based on the characterization of the environment and the defined objectives, we have to choose the appropriate processes for
improvement, as well as the process tools and supporting methods, making sure they agree with the objectives.
Table 2 presents the specific process practices within the CMMI Technical Solution process area that have low or medium support by
RUP according to SEI assessment.

Table 2: Specific process practices from CMMI Technical Solution and Supplier Agreement Management
process areas weakly supported by RUP
Process Area

Specific Goal

Specific Process
Practice

Description

Technical Solution

SG 1 Select Product-Component
Solutions

TS SP 1.1-1

Develop Alternative Solutions and Selection


Criteria

TS SP 1.1-2

Develop Detailed Alternative Solutions and


Selection Criteria

TS SP 1.3-1

Select Product-Component Solutions

SG 2 Develop the Design

TS SP 2.4-3

Perform Make, Buy, or Reuse Analyses

SG 1 Establish Supplier
Agreements

SAM SP 1.1-1

Determine Acquisition Type

SAM SP 1.2-1

Select Suppliers

SAM SP 1.3-1

Establish Supplier Agreements

SAM SP 2.1-1

Review COTS Products

SAM SP 2.2-1

Execute the Supplier Agreement

SAM SP 2.3-1

Accept the Acquired Product

SAM SP 2.4-1

Transition Products

Supplier Agreement
Management

SG 2 Satisfy Supplier
Agreements

Table 3 shows the process models we analyzed and their compliance with CMMI Technical Solution's Specific Process practices. CMMI
Supplier Agreement Management's Specific Process practices are not included since RUP does not provide any specific support to them.
The compliance level is indicated by Low, Medium or High (L, M, H).

Table 3: Process models vs. Technical Solution process area


Process Analyzed

SP 1.1-1 SP 1.1-2 SP 1.3-1 SP 2.4-3

NASA SEL COTS-based process


OTSO COTS Selection Process

SPC's Subcontracting Products or Services for Software-Intensive Systems L

7/15/2004

Enhancing RUP for CMMI compliance: A methodological approach

RUP

Page 6 of 15

Note that the RUP benchmarking was extracted from Gallagher & Brownsword 2001 RUP/CMMI tutorial.12 Our results can be further
explained as follows:
Rational Unified Process. We replicated here the results of the assessment conducted by SEI where RUP was benchmarked against
CMMI Continuous Representation. Only the specific practices considered as either low or medium supported by RUP are shown.
NASA SEL COTS-based process.13 After investigating fifteen projects developed according to NASA COTS-based software
development, Morisio and colleagues proposed new process elements for COTS (Commercial Off-the-Shelf available software)
identification, selection, and integration. For instance, the requirement process was enhanced with the following activities: make versus
buy decision, COTS identification and selection, and COTS familiarization. Table 4 shows the synergy between this process model and
the CMMI Technical Solution process area.

Table 4: Synergy between NASA SEL COTS-based process (Morisio et al., 2001) and CMMI Technical
Solution process area
Specific
Process
Procedure

Description

NASA SEL
COTS-based
process

Comments

TS SP 1.3-1

Select the product component


solutions that best satisfy the
criteria established.

Requirements
Definition.

Requirements for the project are sketched out to guide


the identification of COTS. In addition, COTS are
identified and evaluated using vendor documentation,
reviews, peer experiences and suggestions.

COTS
Identification and
Selection.
TS SP 2.4-3

Evaluate whether the product


components should be developed,
purchased, or reused based on
established criteria.

Make Versus Buy


Decision I.

These two make vs. buy decision activities analyze in


detail different tradeoffs among requirements satisfied,
risks accepted, and cost.

Make Versus Buy


Decision II.

OTSO COTS Selection Process. Kontio14 proposes a method for searching, screening and evaluting COTS. This method was
successfully applied in two case studies carried out with Hughes Corporation in the EOS program developed for NASA. Software
Productivity Consortium embraced this method as part of its COTS purchase process (SPC, 1989). Table 5 presents the synergy
between OTSO and CMMI Technical Solution and Supplier Management process areas.

Table 5: Synergy between OTSO and CMMI Technical Solution and Supplier Management process areas
Specific
Process
Procedure

Description

OTSO Process
Elements

Comments

TS SP 1.1-1

Develop alternative solutions and


selection criteria.

Search criteria
definition

It produces the criteria necessary to conduct the


selection and evaluation of the component alternatives.

TS SP 1.1-2

Develop detailed alternative


solutions and selection criteria.

Detailed
evaluation
criteria
definition
Weighing of
criteria

It provides guidance on how to elaborate requirements


for the COTS into a well-defined measurement criteria
set. These criteria are used to select, screen and
evaluate COTS, thereby creating alternative solutions.

7/15/2004

Enhancing RUP for CMMI compliance: A methodological approach

TS SP 1.3-1

Select the product component


solutions that best satisfy the
criteria established.

SAM SP 2.1-1

Review candidate COTS products


to ensure they satisfy the
specified requirements that are
covered under a supplier
agreement.

Analysis of results

Page 7 of 15

It is used to perform analysis on the financial and


qualitative data resulting from the criteria-based
evaluation and to decide which component(s) will be
selected for inclusion in the system.
OTSO process as a whole. OTSO provides detailed
guidance for:
z
z
z

Developing criteria for evaluating COTS


products
Evaluating candidate COTS products against
requirements and evaluation criteria
Selecting COTS products to be acquired or
reused

SPC's Subcontracting Products or Services for Software-Intensive Systems Guidebook. This provides a process for managing
subcontracting of products or services. The first activity of this process is to perform the make vs. buy analysis. This activity describes the
use of a balanced scorecard to identify and focus on business needs when evaluating make versus buy alternatives (SPC, 2001). The
scorecard contains financial performance, customer satisfaction, internal process, learning and innovation, and sourcing liability factors,
along with strategies to optimize performance for those factors that relate to business needs. Table 6 presents the synergy between this
process, more specifically between the activity to perform make vs. buy analsyis and the CMMI Technical Solution.

Table 6: Synergy between SPC's guidebook and CMMI Technical Solution and Supplier Management
process areas
Specific
Process
Practices

Description

SPC's Process
Element

TS SP 2.4-3

Evaluate whether the


Perform Make vs.
product components should Buy Analysis
be developed, purchased,
or reused based on
established criteria.

SAM SP
1.1-1

Determine the type of


acquisition for each product
or product component to be
acquired.

SAM SP
1.2-1

Select suppliers based on


an evaluation of their ability
to meet the specified
requirements and
established criteria.

Solicit and Select


Supplier

Comments

The option to purchase any of the candidate COTS products is


compared to the option to build a similar product in-house with both
options evaluated against previously established decision criteria.

Via its sub-activity 'Determine Contract Type,' Solicit and Select


Supplier recommends the type of acquisition for each product or
product component to be acquired.
It treats the 'contract type' specification before beginning the supplier
relationship as a key to mitigate risk early on.
SPC fulfills the CMMI recommendation to select suppliers based on
an evaluation of their ability to meet the specified requirements and
established criteria. The CMMI specified practices for 'Select
Suppliers' are fulfilled in one or many of the following exit artifacts:
z
z
z
z
z

Supplier evaluation criteria


Solicitation materials
Solicited supplier list
Evaluations of each prospective supplier's ability to perform
with associated risks
Identification of product or service to be acquired, with
preferred supplier and alternates

7/15/2004

Enhancing RUP for CMMI compliance: A methodological approach

SAM SP
1.3-1

Establish and maintain


formal agreements with the
supplier

Agree to Terms

SPC fulfills the CMMI recommendation to establish and maintain


formal agreements with the supplier. The CMMI specified practices
for 'Establish Supplier Agreements' are fulfilled in one or many of the
following exit artifacts:
z
z
z
z
z

SAM SP
2.1-1

SAM SP
2.2-1

Review candidate COTS


products to ensure they
satisfy the specified
requirements that are
covered under a supplier
agreement.

Perform activities with the


supplier as specified in the
supplier agreement.

Perform
Make vs.
Buy
Analysis
Solicit and
Select
Supplier

Manage the
Relationship

Solicit and Select Supplier also indirectly addresses this specific


practice by leveraging a component evaluation process. As indicated
before, OTSO provides detailed guidance for screening, evaluating,
and selecting COTS products. Therefore, SPC recommends the use
of component evaluation process when the make or buy decision is
oriented towards the acquisition of COTS products.
SPC fulfills the CMMI recommendation to perform activities with the
supplier as specified in the supplier agreement.
The CMMI specified practices for 'Execute the Supplier Agreement'
are fulfilled in one or many of the following exit artifacts:

z
z

Ensure that the supplier


agreement is satisfied
before accepting the
acquired product.

Accept the
Products and
Services

Transition the acquired


products from the supplier
to the project.

Transition the
Product or
Service

Supplier progress and status reports


Audit and review reports
Technical and management review reports
Action Items
Documentation of work product and document deliveries

SPC fulfills the CMMI recommendation to ensure that the supplier


agreement is satisfied before accepting the acquired product. The
CMMI specified practices for 'Accept the Acquired Product' are
fulfilled in one or many of the following exit artifacts:
z

SAM SP
2.4-1

SOW
Supplier agreement (e.g., contract, MOU)
Update of the project's plans and risk plans
Supplied product or service specifications
SMP (Supplier Management Plan)

During Perform Make vs. Buy Analysis activity, evaluation criteria


needed to meet the business objectives are documented and trade
studies are performed.

z
z
z

SAM SP
2.3-1

Page 8 of 15

Reviews or test cases are performed, and acceptance criteria


are met.
Required deliverables are placed under CM.

SPC fulfills the CMMI recommendation to transition the acquired


products from the supplier to the project.
The CMMI specified practices for 'Transition Products' are fulfilled in
one or many of the following exit artifacts:
z
z
z
z
z

Delivered product with user and maintenance guides


Transition plans
Training plans
Support and maintenance plans
Transition audit and test results, report, and corrective action
plan

In this section, we presented an overview of the process models we investigated to address the weakness of RUP with regards to CMMI
Technical Solution and Supplier Management process areas. Three process models (in addition to RUP) were analyzed. We indicated the
level of synergy of these processes and CMMI. The three cited processes inspired us to propose the creation of new process elements to
extend RUP. Later on, we will present how this was done.

7/15/2004

Enhancing RUP for CMMI compliance: A methodological approach

Page 9 of 15

Packaging experiences for project and corporate learning


Once the measurable goals are set, the processes are chosen and executed. Then, it is time to analyze the results, package the
experience and lessons learned, and save these packages in our corporate repository for reuse and continuous improvement. By doing
so, our assets can be reused and can evolve. In addition, as prescribed in Figure 2, we should consider them for the further iterations in
the same project or leverage them across the organization.
To package our experience, we have extended RUP. In the next section, these new elements are presented.

New process elements


Figure 3 shows an overview of the new process elements that we have created. In the following paragraphs I provide a high-level
description of these new process elements. To create the elements, we have used Spearmint,15 a graphical modeling tool for describing
software development processes. The tool's conceptual schema of process information is a subset of the OMG's Software Process
Engineering Metamodel (SPEM) specification. The tool utilizes a graphical notation close to UML. A full description of the new elements
can be provided under request.16

7/15/2004

Enhancing RUP for CMMI compliance: A methodological approach

Page 10 of 15

Figure 3: New process elements


Based on the analyses of process models cited in the previous section, we proposed that the following activities be added to our version
of RUP.
Perform the make vs. buy analysis. The make vs. buy analysis is the decision-making process to determine whether to implement a
COTS solution or build a custom solution. The project manager is assigned this activity. As noted by Morisio and his colleagues, the use
of COTS in a project is a key decision that impacts all subsequent phases and the success of the project. Therefore, the main project
stakeholders should participate in this analysis and final decision.
Define COTS evaluation scope. This planning activity is performed by the project manager to define the scope for the activities involved

7/15/2004

Enhancing RUP for CMMI compliance: A methodological approach

Page 11 of 15

in the component evaluation process.17 The organizational characteristics provided in the Software Development Document, customer
needs indicated in the Vision document, and project specifications provided in the Software Requirement Specification (SRS) and
Supplementary Specification are used by the project manager to create the component evaluation plan. This plan would enrich the
Software Development Document and defines the level of effort for each activity to be performed in the component evaluation process.
Each iteration may require this plan be redefined for one or more of the process activities. Further details about Software Development
Document, SRS, Supplementary Specification and Vision artifacts can be found in RUP.
Perform COTS evaluation. This activity addresses the problems of evaluating, comparing, and selecting components.18 This activity
would complement the Analysis and Design discipline more precisely, the workflow detail: perform architectural synthesis activity.
Although this activity focuses on off-the-shelf components, it applies to all types of components large or small. This activity is strongly
related to the architectural synthesis. It deals with evaluating components that already exist within the project or that have been created in
previous iterations or system versions, or COTS that have been requested to be part of the system. The architect is primarily responsible
for this activity. As recommended by Kontio (1995) and SPC, this activity can be decomposed in the following sub-activities: search and
screen candidates, define evaluation criteria, evaluate component alternatives, and analyze evaluation results. Figure 4 shows the
product flow of these sub-activities.
Based on the results provided by this activity, the architect can generate change requests related to the proposed architecture and/or
requirements. These change requests would be managed using the project change management process as recommended in RUP. The
main output of this activity would be a list of selected components indicating the components chosen for inclusion in the system as a
result of the evaluation process. As far as RUP artifacts are concerned, this list would be included in the Software Architecture Document.

Figure 4: Component evaluation product flow


Purchase COTS product and service agreement. This activity's main goal is to acquire the select components. It is also recommended
to purchase a service agreement that provides support and upgrades to the acquired components.19

7/15/2004

Enhancing RUP for CMMI compliance: A methodological approach

Page 12 of 15

Transition COTS product. This activity's main goal is to transit the acquired products from the supplier to the project.20 The project
manager must ensure that an adequate infrastructure is in place to receive, store, use, and maintain the acquired components. In
addition, appropriate training must be provided for those involved in receiving, storing, using, and maintaining the acquired products.
Finally, the project manager should make sure that storing, distributing, and using the acquired products are performed according to the
terms and conditions specified in the supplier agreement or license.

Conclusion
RUP is the de facto industry standard for project lifecycle development and management. Unisys integrates RUP into its Business
Blueprint methodology to provide a highly mature process across the entire organization. However, RUP presents low-process capability
regarding some CMMI software process areas and needs improvement. To clearly identify these weaknesses and improve RUP to
overcome them, we have used an empirically validated and technically sound software process improvement approach called QIP. As a
result, a process model based on the Rational Unified Process concepts was proposed to enhance RUP compliance to CMMI. To verify
the efficiency and efficacy of the proposed process model, we are currently validating it on pilot projects. To roll it out in the entire
organization, we are proposing the integration of this new capability via a CMMI plug-in for RUP. Finally, we believe that other groups can
apply the approach we have described in this paper to mitigate risks in other process areas.

References
V. Basili, G. Caldiera and D. Rombach, "The Goal Question Metric Approach."Encyclopedia of Software Engineering. Wiley 1994.
V. R. Basili, M. K. Daskalantonakis, R. H. Yacobellis. "Technology Transfer at MOTOROLA," IEEE Software, 11(2): 70-76.
L. Briand; K. El Eman; W. L. Melo. "AINSI: An inductive method for software process improvement: concrete steps and guidelines." In K.
El Eman and N. H, Madhavji (eds.), Elements of Software Process Assessment and Improvement. 1999. IEEE Press.
CMMI Product Team. Capability Maturity Model Integration (CMMISM), Version 1.1, Continuous Representation, CMU/SEI-2002-TR-011,
2002.
CMMI Product Team. Capability Maturity Model Integration (CMMISM), Version 1.1, Staged Representation, CMU/SEI-2002-TR-012,
ESC-TR-2002-012, 2002.
K. El Emam; J.-N. Drouin; W. Melo. SPICE: The Theory and Practice of Software Process Improvement and Capability Determination.
IEEE Press. 1998.
B. Gallagher & L. Brownsword. "The Rational Unified Process and the Capability Maturity Model Integrated Systems/Software
Engineering." RUP/CMMI Tutorial ESEPG, 2001.
R. Grady, Successful Software Process Improvement, Prentice-Hall, 1997.
T. Kilpi, "Implementing a Software Metrics Program at Nokia," IEEE Software, 18(6):72-77, 2001.
J. Kontio. "A Case Study in Applying a Systematic Method for COTS Selection,"Proc. of the 18th Int. Conf. on Software Engineering, IEEE
CS Press, March 1996.
F. McGarry et .al. "An Overview of the NASA Software Engineering Laboratory." NASA SEL, Technical Reports, SEL-94-005, 1994.
ISO/IEC TR 15504-1. "Information technology Software process assessment Part 1: Concepts and introductory guide." 1998.
L.V. Manzoni, "Using a Workflow Management System to Support Software Development Based on Extended Rational Unified Process to
Reach Maturity Model Levels 2 and 3," Master Dissertation, Inst. of Informatics, Federal Univ. of Rio Grande do Sul, Porto Alegre, Brazil,
2001, http://www.inf.ufrgs.br/amadeus/atuais/lisandra.html.
L. V. Manzoni & R. T. Price. "Identifying Extensions Required by RUP to Comply with CMM Levels 2 and 3." IEEE TSE, Vol. 29, No. 2,
February 2003.
M. Morisio, C.B. Seaman, V.R. Basili, A.T. Parra, S.E. Kraft, S.E. Condon. "COTS-Based Software Development: Processes and Open
Issues."Journal of Software and Systems, 2001.
M. Paulk. Capability Maturity Model for Software, Version 1.1. Addison-Wesley.1993.

7/15/2004

Enhancing RUP for CMMI compliance: A methodological approach

Page 13 of 15

Software Productivity Consortium (SPC). Component Evaluation Process. SPC-98091-CMC. 1999.


Software Productivity Consortium (SPC). "Subcontracting Products or Services for Software-Intensive Systems." SPC-2000039-MC,
September 2001.
Rational Software. "Reaching CMM Levels 2 and 3 with the Rational Unified Process." White Paper. 2001.
R. W. Reitzig; Carlo Rodriguez; Gary Holt. "Achieving Capability Maturity Model Level 2 with the Rational Unified Process." Gognenceinc
Integrated Software Engineering. www.cognence.com. White Paper. 2002.
R. W. Reitzig; John B. Miller; Dave West; Raymond L. Kile. "Achieving Capability Maturity Model Integration Maturity Level 2 Using IBM
Rational Software's Solutions." Rational White Paper. 2003.
R. W. Reitzig. "Using Rational Software Solutions to Achieve CMMI Level 2."The Rational Edge. Jan. 2003.

Appendix A: Related work


RUP is one of the pillars of Unisys Blueprint Methodology. RUP has been claimed as a "software process improvement tool" that would
help an organization or project to achieve a higher level of process capabilities. In this section, we highlight some studies that advocate
RUP as such a tool. We do not intend to cover all the experiences already conducted about this subject, but to show a sample related to
our proposal.
Reitzig and his colleagues (2002) identified various RUP roles, disciplines, templates, and activities that would apply in satisfying the
various CMM Level 2 key practice areas. To deal with the weakness of RUP regarding SW-CMM Level 2-3, they recommended using
other processes in combination with RUP. For instance, regarding the lack of RUP support for the supplier management process, they
claimed that an organization could become compliant with this process area by using the IEEE Std 1062 Recommended Practice for
Software Acquisition. This standard outlines the recommended steps an organization should follow when undergoing a software
acquisition effort. According to Reitzig et. al., if the standard were used correctly, many of the supplier management procedures asked for
by the SW-CMM would be produced.
In another white paper Rational Software (2001) describes how Rational Unified Process can support an organization that is trying to
achieve SW-CMM Level 2-3. High-level recommendations are provided on how to cover RUP weaknesses regarding SW-CMM Level 2-3
(Rational, 2001).
Reitzig and his colleagues (2003) provide guidelines on how an organization that uses RUP can accelerate the attainment of CMMI
maturity Level 2, and have a solid foundation for maturity level 3. Since the Technical Solution process area is only requested in CMMI
Staged Representation Level 3, they did not address the weaknesses identified in RUP regarding compliance with this process area.
Regarding the supplier management process area, which is required in CMMI Staged Representation Level 2, they indicated that many of
the practices required by the CMMI in the Supplier Agreement Management process area are not specifically addressed by RUP. Reitizig
(2003) complements this study by indicating supplementary standards and practices that could be leveraged to overcome RUP
weaknesses regarding CMMI Level 2-3, but he does not explicitly indicate how RUP should be enhanced to incorporate his
recommendations.
Manzoni and Price (2003) after identifying the issues of RUP with regards to SW-CMM proposed creating new process elements to
improve RUP. For instance, they proposed a new discipline for dealing with supplier management and new procedures to estimate and
track critical computer resources. Detailed descriptions of such new elements can be found in Manzoni (2001). These cited studies are
very useful for confirming the weaknesses of RUP with regards to CMMI compliance. Also, they provide overall guidance on how RUP
could be enhanced to overcome such issues.

Notes
1Any opinions, findings, and conclusions or recommendations expressed in this paper are those of the author(s) and do not necessarily
reflect the views of Unisys Corporation.
2B. Gallagher & L. Brownsword. "The Rational Unified Process and the Capability Maturity Model Integrated Systems/Software

Engineering." RUP/CMMI Tutorial ESEPG, 2001.


3 M. Paulk. Capability Maturity Model for Software, Version 1.1. Addison-Wesley.1993.
4 B. Gallagher & L. Brownsword. "The Rational Unified Process and the Capability Maturity Model Integrated Systems/Software

7/15/2004

Enhancing RUP for CMMI compliance: A methodological approach

Page 14 of 15

Engineering." RUP/CMMI Tutorial ESEPG, 2001.


5 L. V. Manzoni & R. T. Price, "Identifying Extensions Required by RUP to Comply with CMM Levels 2 and 3," IEEE TSE, Vol. 29, No. 2,

February 2003.
6 K. El Emam; J.-N. Drouin; W. Melo. SPICE: The Theory and Practice of Software Process Improvement and Capability Determination.

IEEE Press. 1998.


7 The success with QIP is documented for most of these companies in the studies cited here: For HP, see R. Grady, Successful Software

Process Improvement, Prentice-Hall, 1997. For NASA, see F. McGarry et. al. "An Overview of the NASA Software Engineering
Laboratory," NASA SEL, Technical Reports, SEL-94-005, 1994. For Nokia, see T. Kilpi, "Implementing a Software Metrics Program at
Nokia", IEEE Software, 18(6):72-77, 2001. For Motorola, see V. R. Basili, M. K. Daskalantonakis, R. H. Yacobellis. "Technology Transfer
at Motorola," IEEE Software, 11(2): 70-76.
8 V. Basili, "Software Improvement Feedback Loops: The SEL Experience," 10th Software Development Expo & Conference (SODEC),

Tokyo, Japan, June 2001.


9 L. Briand; K. El Eman; W. L. Melo. "AINSI: An inductive method for software process improvement: concrete steps and guidelines," in K.
El Eman and N. H, Madhavji (eds.), Elements of Software Process Assessment and Improvement. IEEE Press: 1999.
10 B. Gallagher & L. Brownsword, 2001. Op. cit.
11 V. Basili, G. Caldiera and D. Rombach, "The Goal Question Metric Approach."Encyclopedia of Software Engineering. Wiley 1994.
12 B. Gallagher & L. Brownsword, "The Rational Unified Process and the Capability Maturity Model Integrated Systems/Software

Engineering," RUP/CMMI Tutorial ESEPG: 2001.


13 M. Morisio, C.B. Seaman, V.R. Basili, A.T. Parra, S.E. Kraft, S.E. Condon, "COTS-Based Software Development: Processes and Open
Issues," Journal of Software and Systems, 2001. It is important to point out that Morisio's COTS-based process provides new elements to
an already existing NASA COTS-based software development, which is essentially different from the Rational Unified Process. It is out of
the scope of this paper to compare NASA COTS-based software development to RUP. Our goal here is to indicate that the ideas
proposed by Morisio and his colleagues have influenced our decision to create new process elements to enhance our corporate process
and increase our compliance to CMMI.
14 J. Kontio. "A Case Study in Applying a Systematic Method for COTS Selection," Proc. of the 18th Int. Conf. on Software Engineering,

IEEE CS Press, March 1996.


15 http://www.iese.fhg.de/Spearmint_EPG/
16 A full description of the new elements can be provided under request.
17 Software Productivity Consortium (SPC). Component Evaluation Process. SPC-98091-CMC. 1999.
18 Ibid. See also J. Kontio. "A Case Study in Applying a Systematic Method for COTS Selection,"Proc. of the 18th Int. Conf. on Software
Engineering, IEEE CS Press, March 1996.
19 Software Productivity Consortium, 1999. Op. cit.
20 Ibid.

7/15/2004

RUP iteration planning

Page 1 of 13

Copyright IBM Corporation 2004.

http://www-106.ibm.com/developerworks/rational/library/5335.html

Search for:
Use + - ( ) " "
IBM home
developerWorks

All of dW

within

Search help

| Products & services | Support & downloads | My account

> Rational

RUP iteration planning


Anthony Crain
IBM
12 Jul 2004
from The Rational Edge: This article traces the steps required to plan sequential software project
iterations while following the IBM Rational Unified Process. The author illustrates RUP templates
and associated workflows in order to produce a plan relevant to the essential RUP disciplines.
When planning an iteration using IBM Rational Unified
Process, or RUP, people often get confused about how
to start. Although templates in RUP itself and MS Project
tools can help auto-generate a RUP style plan, creating a
plan manually can really help you understand and
manage your RUP iteration.

Contents:
Input artifacts
Creating the iteration plan
Summary
Notes
About the author
Rate this article
Subscriptions:
dW newsletters
dW Subscription
(CDs and downloads)

In this article I will show how simple it is to create an


accurate iteration plan using the basic RUP toolset.

Input artifacts
To create your iteration plan you really only need two
basic inputs. First, you need to know what RUP phase the planned iteration belongs to, and second, you need a well-written RUP
development case. Knowing the phase will allow you to create the right kind of plan. Having the development case will tell you exactly
what the plan should contain.

Development case redefined


Creating a plan from a development case is actually fairly easy, as you will see, once we understand what this artifact is all about. I have
been told by RUP enthusiasts that the development case artifact is not useful. This is wildly untrue. In fact, I will show you how it can
single-handedly drive your project management planning.
I will note that, as with almost every RUP template Ive ever used, the development case artifact could be improved. However, dont
misinterpret that statement. RUP templates are far better than anything I could create from scratch. But given their elevated starting point,
along with my ability to architect information for maximum communication, I see room for improvement. Naturally, each of us brings great
experience to the table that we can use to improve a basic set of artifacts. And if we dont keep reusing and improving each others' basic
artifacts i.e., starting points we will always be starting from scratch and will only get so far in our effort. By launching ourselves from
someone elses starting point we can fly high indeed and start to create world class artifacts.
Therefore, to create a fully optimized development case artifact, I started with the RUP template. You will notice that RUP is heavily
artifact-focused, yet there is little guidance on how to use those artifacts differently in each phase. The definition in RUP for the
development case states: The development case describes the development process that you have chosen to follow in your project.
So the artifact focus of the development case template doesnt completely reflect its definition. In my current best practice development
case template, I recommend focusing on what workflow details you plan to execute, then focus on the artifacts within the context of each
workflow detail. If you are not sure what a workflow detail is, click on any RUP discipline, and the activity diagram will show the workflow
details. For example, there are only six workflow details in the Requirements discipline.

The Rational Edge--June 2004

7/15/2004

RUP iteration planning

Page 2 of 13

Figure 1: The RUP Requirements workflow


Note that the RUP discipline workflow diagrams (which are actually stereotyped UML activity diagrams) cover one iteration from the point
of view of this discipline. The start state at the top is the start of the iteration, and the end state is the end of the iteration. Some
misinterpret this as the start and end of the project, a throwback from waterfall thinking; or they mistake this as the start and end of the
discipline, assuming that each discipline occurs in chronological order. In other words, some assume that the end state depicted here
precedes the start state of the Analysis and Design workflow, but that isnt necessarily true.
By acknowledging that this is the start and end of the iteration, and not the project, we can encourage more parallel work, and study the
dependencies between tasks. Therefore, these activity diagrams drive iterative project planning.

Writing the development case


As I mentioned, to create your iteration plan, you will need a development case. Therefore, it is important that you ensure it gets
completed quickly and correctly. It shouldnt take but a few hours for a new team to assemble a first draft for the current iteration.
To write the development case, assign the nine disciplines (or the subset of disciplines you are using on your project if not all nine) to the
most appropriate team members. Their job is to look at the workflow details and decide which ones they will actually need to execute, and
which ones they wont. At first it feels like you have to know a lot about RUP to make that judgment, but that isnt necessarily the case.
Knowing the definitions of the four RUP phases may be all you really need. Lets look at an example.

7/15/2004

RUP iteration planning

Page 3 of 13

Figure 2: The RUP Requirements workflow


Tasks on plan
Given that the Inception phase involves creating a first-cut usage model of the solution and establishing the measurable value of the
solution idea but not gathering the detailed requirements, the question becomes: Which of the workflow details shown in Figure 2 (which
is identical to Figure 1) will you need? Lets consider what each of these workflow details requires.
Analyze the problem is about agreeing on the problem and creating the measures that will prove its value to the organization.
Understand stakeholder needs is about sharing the problem and value with key stakeholders and finding out what their needs are
surrounding the solution idea.
Define the system is about creating features from needs and outlining use cases, activities which show nicely the high-level
requirements and the overall usage model of the system.
Manage the scope of the system is about modifying the scope of what you will deliver based on results so far and selecting the order in
which to attack the use-case flows.
Refine the system definition is about detailing use-case flows with the stakeholders in order to create a detailed Software Requirement
Specification (SRS) that can serve as the contract between your team and your client and that can drive design and test activities.
Manage changing requirements is about how to handle incoming requirement changes once the project has begun.

7/15/2004

RUP iteration planning

Page 4 of 13

Based on these descriptions and the description of Inception, I would probably expect analyze the problem, understand stakeholder
needs, define the system, and manage the scope of the system to be planned for the first inception iteration, but not the other two
workflow details. If Inception had more than one iteration I might see manage changing requirements kicking in, but still not refine the
system definition. Your decisions might be different and it might also differ for each project under your care.
It is not the project managers job to decide which workflow details to perform in each iteration; it is the teams decision. Basically, the job
of the project manager comes down to three tasks, and everything else folds up into them: 1. Plan/Re-Plan 2. Track to Plan 3. Manage
Risks to the Plan. Thats pretty much it. I consider status activities part of tracking-to-plan. And Im open to disagreement on this
simplification.
After the team decides what to do via a development case, the project manager should create the plan from the development case they
create. Lets consider one more example of how to tailor the generic RUP workflow based on the current RUP phase, this time using the
Analysis and Design workflow in RUP.

Figure 3: The RUP Analysis and Design workflow


Picking which workflow details to include in the development case for the Inception phase is easy, even without individual descriptions of
each workflow detail. The activity diagram (Figure 3) clearly indicates that in the Inception phase the only workflow detail needed is to
perform architectural synthesis, which is an ugly term for building an architectural proof of concept.
As shown in Figure 3, this workflow detail is optional; however, my projects rarely skip this step. The workflow detail perform architectural
synthesis consists of two major steps: 1) deciding if you need a proof of concept, and then 2) building it if you decide you needed one.
Most projects need to analyze their risks to determine if a proof of concept is needed, and there are some great best practices to help you
make this decision. Therefore, deciding on the need for a proof of concept is not a step that is usually skipped, and I dont see perform
architectural synthesis as more optional than the other five workflow details in Figure 3 for most projects. The optional guard is likely tied
to the fact that most projects do NOT need an Inception proof of concept, so the building portion of perform architectural synthesis is
optional and frequently skipped in the Inception phase.
In the Elaboration phase, teams build an incremental release (internal or external) that proves the chosen solution architecture can

7/15/2004

RUP iteration planning

Page 5 of 13

support the requirements of the solution. This requires taking the highest-risk requirements all the way through code to test and possibly
internal or external deployment. Given this, we will probably need all five of the other workflow details in the Elaboration phase.
During the Construction phase, we build the rest of the flows that we didnt build as part of elaboration, and we are no longer worried
about architecture, focused instead on delivering the highest value solution possible. Based on this, we probably would only need analyze
behavior, design components, and design the database.
During the Transition phase, when we are supporting the solution once it has been fully deployed, we would use the same activities as in
Construction; but the focus would be more on change requests than use cases.
You can repeat this exercise for the workflow details of the Requirements discipline shown above and for all of the other seven disciplines
of RUP. The best part is that you dont need to do this for all four phases at once! Remember that writing the development case and
planning based on it is iterative, so you can focus on this iteration only and, therefore, only on the current phase. If the next iteration on
the plan will belong to the next RUP phase, then you can proceed to detail your next phase in your development case. This is easier,
quicker, and more accurate than waterfall planning for an entire project at once.
Children tasks
If you do the above for each workflow it shouldnt take too long to create a development case for a single phase. But we do need to add a
few children tasks. Many managers try to add the activities within each workflow detail, but in general this will cause problems.
First, this will result in significant delays to creating your plan, as there are an awful lot of activities within the workflow details. You will
likely spend more time planning some of these tasks than implementing them. You can create a very manageable plan without that added
level of detail. Second, many of the activities repeat in different workflow details. Just check out the first four workflow details in the
requirements discipline, and you will see the develop vision activity appear every time, with no indication of what is different in each RUP
phase. So I recommend that you avoid using the RUP activities on your project plan.
On the other hand, we do need to understand what resources are being applied to what tasks. So instead of making each activity a child
task to the workflow detail in our development case, we should create one child task per role involved in the workflow detail that we plan
to use. Lets look at some examples.

Figure 4: Details for the Perform Architectural Synthesis workflow detail

7/15/2004

RUP iteration planning

Page 6 of 13

Notice in Figure 4, in the yellow rectangle, that there is only one resource with three activities. In this case we do not need to add any
children tasks to the plan, as the single role will handle all activities.

Figure 5: Details for the Define a Candidate Architecture workflow detail


In the workflow detail shown in Figure 5, we have two participants: the software architect and the designer. So we will create two child
tasks for this workflow detail. We need to invent names to represent each subtask on the plan. If the activity does not repeat, we can use
its name directly. Architectural analysis does repeat, but only in perform architectural synthesis; so we can call this child task architectural
analysis here, because we havent already used that name.
Use-case analysis, on the other hand, occurs in so many workflow details that we avoid using that name. We chose use key abstractions
instead. That is, we know from experience that using key abstractions is one of the major concepts of this step. Until you gain similar
experience you will have to make your best guess.
Another way to look at this is that we are creating children tasks per yellow area, not per activity. We then abstract a new name based on
the whole yellow areas purpose. We can use the activity name if it occurs uniquely within RUP. In my opinion, RUP authors should not
reuse activity names, but this approach allows me to manage that for myself.
Knock-off tasks
The last step after finding the children tasks is to list key "knock-off tasks" in the development case and to include key input or output
artifacts as well. A list of knock-off tasks is like a to-do list of small objectives. (If you dont like the term knock-off task, you can use a
different one, but it should indicate that the list includes fairly granular to-do items.)

7/15/2004

RUP iteration planning

Page 7 of 13

Identifying the knock-off tasks is an area in which a consultant or someone with significant RUP experience can dramatically reduce the
time to value. We are NOT trying to duplicate RUP here. We are simplifying RUP considerably in this step. You will still need to use RUP
for additional details.
Here are a couple of examples. For Analysis and Design, the knock-off tasks for each workflow detail might look like the list in Table 1,
which Ive taken from the standard development case I give to my clients.

Table 1: A simple development case

7/15/2004

RUP iteration planning

Page 8 of 13

7/15/2004

RUP iteration planning

Page 9 of 13

This standard example is fairly simple. It does not describe the input and output artifacts, but this amount of detail is extremely valuable to
the team. And although this development case is fairly simplistic, it fits on a single page, which also can be an advantage to a new team.1
Table 2 shows more complex entry for a single workflow detail in the project management discipline. This is taken from another
development case template that I share with my clients (note that the business context in Table 2 is different from that in Table 1).

Table 2: A more complex entry for a single workflow detail


Conceive New Project
Knock-off tasks

z
z
z

Write business
case
Write Risk List
Share with PRA
and gain
funding for
Inception phase

Purpose

Purpose is to justify funding by putting together a quick


document to show the idea for the project. In the future, new
team members can read this to see how the project has been
positioned to the PRA, and to get a high-level introduction to
the system. The business case will be updated at each
iteration. The risk list will be updated often.

Role

Project
manager

Average time
Established
environment

New
environment

1 day

1 day

Input Artifacts: None


Output Artifacts: business case, risk list, review record funding inception
Tools: IBM Rational ClearQuest for risk list, Word for business case, e-mail with acceptance for review record

In the example shown in Table 2, far more detail has been provided. This level of detail evolved over time. Trying to get to this level of
detail on every workflow detail at once would take more time than our projects have to spare.
Remember, while it is the job of the project manager to ensure a development case is written to guide their planning, the team that will be
following the plan should create the development case together. This is how the team influences what gets placed on the plan.

Creating the iteration plan


At this point you should have the development case in place. You have probably figured out that creating the work breakdown structure
wont be hard once the development case is written.
But there are still a few final tips and thoughts Id like to share. Using a planning tool, such as Microsoft Project, you will find it simple to
place each workflow detail onto the plan. On previous projects I have tried two different approaches for organizing the work breakdown
structure (using Gantt charts like the one in Figure 6 below). Ive tried to organize the tasks on the plan in chronological order, and Ive
tried organizing the tasks by discipline. These two approaches have different advantages and drawbacks.
Lets take a look at an actual project in which our current best practices for laying out the tasks in the work breakdown structure were
determined in RUP.
Grouping tasks: A lesson in confusion
In chronological order, the plan might appear as depicted in Figure 6. Based on an actual project on which I was a consultant, each task
was color coded to match (as closely as possible using MS Projects color palette) the colors of the RUP disciplines.

7/15/2004

RUP iteration planning

Page 10 of 13

Figure 6: Iteration plan organized chronologically


While you cant easily read the details of this plan, you can tell by the colors, and by the position of the Gantt chart bars, that this plan was
not organized by discipline but rather by time. Each task precedes or starts with the next one. For example, the first two tasks are in the
project manager discipline, and so are the last two. Clearly, the PM discipline tasks were not grouped.
Using a sequential order gave project managers a clearer understanding of what came next in this project, but it became difficult to
reconcile this sequence with the development case because the development case was grouped according to discipline in other words,
all the project manager tasks were together, all of the requirement tasks were together, and so forth. The table of contents based on that
development case is shown in Table 3 below.

Table 3: A development case organized by discipline

7/15/2004

RUP iteration planning

Page 11 of 13

So the plan was in sequential order, but the development case was in discipline order, and the project managers had a harder time trying
to reconcile the two. To fix this problem, the project managers attempted to modify the template so that the workflow details were in
sequential order to better match the iteration plan. The table of contents then looked more like Table 4.

Table 4: Development case reorganized by sequence

7/15/2004

RUP iteration planning

Page 12 of 13

This worked well for planning because the project managers could, for the most part, cut and paste the table of contents into their project
plan. But now it became harder for the rest of the team to find the tasks they owned, since they were no longer logically grouped, so
ultimately this was deemed a poor choice. We saved the template, of course, to remind ourselves of the attempt. By the way, the current
recommendation for iteration plans in RUP is to organize both the plan and the development case by discipline.
Writing queries to identify critical tasks
During that project, we also created a few Microsoft Project queries to help the project managers look for a clear, single view of
interdependent tasks. This is because the plans could span pages vertically, and a task listed low on a given page might be slated for the
first week with many entries for subsequent weeks above it.
The queries are easy to write: List all tasks starting this week (or whatever dates you choose), list all tasks ending this week, and list all
tasks ongoing this week. The project manager would then run these three queries and print out the results, then proactively wander
around to the team asking Are you going to start this on time? Are you going to complete this on time? How are these items going? How
can I help?
Using the RUP work order
In addition to the workflow details, I recommend that you put in the role-specific children tasks as well, and assign them the appropriate
resources. But DONT put in the knock-off tasks, or your plan will be too granular to manage well. It will take too long to create and will be
difficult to modify when changes become necessary.
Instead, use another RUP artifact called the work order, which RUP defines as follows: The work order is the project manager's means of
communicating what is to be done, and when, to the responsible staff. It becomes an internal contract between the Project Manager and
those assigned responsibility for completion.
It goes on to say you can use a whiteboard, and the project plan for tracking, or use IBM Rational ClearQuest to track them automatically.
The idea is you jot down the knock-off tasks with the resource responsible for the task separate from the project plan. When the knock-off
tasks are done, the work order is complete and we mark it complete in MS Project. There is even an integration between MS Project and
ClearQuest that allows you to plan in MS Project, generate work order records, and have the plan update itself when the work orders are
marked complete in ClearQuest.
Another technique is to assign all the work orders to the team member, who can jump from one to another if the work orders get blocked,
raising any needed risks (also via IBM Rational ClearQuest) in the process. If a team member ever runs out of work orders he can camp
out in front of the PMs office with a sandwich until he gets new ones, or he can switch to another project and get new work orders from
different managers.
The point is this: If you plan too deeply, your planning will simply take too long and be difficult to manage and track against. Work orders
can give you the granular level of management you need without the overhead.

7/15/2004

RUP iteration planning

Page 13 of 13

Summary
A well-written development case should show the projects process not just the artifacts. The process is described by outlining which
workflow details the project will be targeting. The project team writes the development case. The project manager uses the development
case to create a work breakdown structure in his preferred tool and works with the team to assign times and dependencies. The plan
should not detail the activity level but should have one subtask per workflow detail if there is more than one role involved. The
development case should list detailed knock-off tasks for each task, but these should not be in the iteration plan. Instead, work orders
should be used to track the more granular knock-off tasks.

Notes
1 In appearance, this development case differs widely from the standard RUP template in that it doesnt discuss artifacts at all. See my

article on the artifacts of Analysis and Design to understand the three artifacts you will need to use for all six of these steps.

About the author


Anthony Crain is a software engineering specialist with the IBM Rational Services Organization. In addition to helping clients
roll out the IBM Rational Unified Process, or RUP, he also trains engineers in requirements management with use
cases, Object-Oriented Analysis and Design (OOAD), and RUP. He learned OOAD and use-case modeling while at Motorola
for five years, then sharpened his skills at Rational. An honors graduate from Northern Arizona University, he holds a B.S. in
computer science and engineering.

What do you think of this document?


Killer! (5)

Good stuff (4)

So-so; not bad (3)

Needs work (2)

Lame! (1)

Comments?

Submit feedback
developerWorks

About IBM

> Rational

| Privacy | Terms of use | Contact

7/15/2004

RUP work components

Page 1 of 10

Copyright IBM Corporation 2004.

http://www-106.ibm.com/developerworks/rational/library/5317.html

Search for:

within
Use + - ( ) " "

IBM home
developerWorks

All of dW

Search help

| Products & services | Support & downloads | My account

> Rational

RUP work components


Kirti Vaidya
Covansys
8 Jul 2004
from The Rational Edge: This article discusses the concept of work components, which
encapsulate work done to achieve individual objectives. In the context of IBM Rational Unified
Process, or RUP, we can think of a work component as a higher-order workflow detail that is
tangible to the stakeholders and has one objective, one owner, and one result. We will define work
components and examine their structure and realization. We will also explore how to use work
components to build and review RUP plans, develop organization-wide work components, and
estimate a project in terms of work components.
IBM Rational Unified Process, or RUP, suggests that
project managers construct plans before beginning a
project but does not provide detailed guidelines for doing
so. This can create challenges:
z

Contents:
What is a work component?
Structure of a work
component
Realizing a work component
Setting up a RUP project
schedule using work
components
Benefits of work components
Assessing project status
using work components
Developing organizationwide work components
Estimating projects using
work components

Although project managers may know what major


pieces of work need to be done within each phase,
constructing an actual Gantt chart for the iteration
schedule might be difficult. Trying to incorporate all
of RUP's phases, disciplines, activities, and so
forth may feel overwhelming.

Work components in the


industry now

Even when project managers do succeed in creating a Gantt chart, the major units of work get
shredded across various disciplines and the work does not flow in the typical way, from top left to
bottom right in the chart. This makes it hard for business and technical managers to see continuity
for the work unit.

Subscriptions:
dW newsletters

Notes
About the author
Rate this article

dW Subscription
(CDs and downloads)

Often such charts evolve into big, incoherent artifacts that demand a lot of maintenance on the
project manager's part but deliver little incremental planning value.

Figure 1 below shows a typical Gantt chart for the RUP Elaboration phase, including workflow details under disciplines. For example,
"design components" is a workflow detail under the Analysis and Design discipline.

The Rational Edge--July 2004

7/15/2004

RUP work components

Page 2 of 10

Figure 1 : A typical RUP Elaboration Gantt chart


Click to enlarge
Let's suppose the PM (project manager) has asked a PMO (project management office) member to review this Gantt chart. Here's how
the conversation might go:
PMO:
PM:
PMO:
PM:
PMO:

So what are you doing in this plan?


We are detailing the requirements, plus building and testing a prototype.
Hmm, I don't see all of that reflected here.
Let me explain. See the details in boldface under Analysis and Design, Implementation, and Test? Those are the prototype,
or summary, tasks.
Then why don't you group them as such and bring this plan back to me?

The PMO wants to look at the summary tasks (disciplines and then workflow details) to quickly understand the chart's main themes
major objectives the project team plans to accomplish. Unfortunately, the project manager did not make the chart easy to understand; the
major objectives, who owns them, and their expected results are inconspicuous.
So how do you capture the essence of RUP in a Gantt chart, while keeping the chart readable and manageable?

What is a work component?


The answer lies in one of RUP's six best practices: Use component architectures. In a planning context, we will name these architectures
work components. In the above example, the project manager could encapsulate the workflow details he boldfaced under the work
component "build architectural prototype." The Gantt chart would then look like the one in Figure 2. The PM could also encapsulate other
workflow details and expand each workflow detail with activities.

7/15/2004

RUP work components

Page 3 of 10

Figure 2 : RUP Elaboration Gantt chart showing a work component that encapsulates workflow details
Click to enlarge
We define work components as follows:
A work component is a work planning entity that encapsulates all work done towards achieving one objective under the
responsibility of one owner, in terms of one or more workflows enacted by one or more workers. These workflows may
generate none or more work products based on none or more inputs, and deliver one result that fulfils the objective and is
tangible to the key beneficiaries of the work component.
Put simply, a work component has:
{

One objective

One owner

One or more workflows enacted by one or more workers

One tangible result

A work component is somewhat like a printed circuit board1 with well-defined I/O (inputs/outputs) and a specific functionality. Just as with
a circuit board, as long as the work component satisfies its objective, the "wiring" inside need not concern the user. And, like circuit
boards, work components can range from very complex to quite simple, depending upon the depth of activities it encapsulates.
For example, the work component "define QA strategy" might be very simple because a knowledgeable QA manager is the owner and
sole resource for it, whereas the work component "build architectural prototype" might be very complex. (In some organizations the
complexity level might be reversed!)
Work components are polymorphic; you can reuse them if you first customize them for your particular implementation. In other words, two
work components might have the same name, objective, owner, and result but different workflow details, roles, activities, and work

7/15/2004

RUP work components

Page 4 of 10

products. Consider our example work component:


Work component: build architectural prototype
Objective:
Owner:
Result:

To build an incremental, executable prototype that baselines the architecture.


Architect
An incremental, executable prototype that baselines the architecture.

An organization might create this work component for a greenfield project to prototype the architecture. Subsequently, if it wanted to use
the work component for a project to enhance an application developed in a previous project, it might keep the same name, objective,
owner, and result but omit the workflow details "analyze behavior" and "structure the implementation model." Or, if it wanted to use the
work component in a project to implement RUP within the organization, again it would keep the same name, objective, owner, and result
but use very different workflow details, roles, activities, and work products related to process architecture rather than application
architecture.

Work components in a RUP context


In a RUP context, we can think of a work component as a tangible, higher-order workflow detail2 with one objective, owner, and result. It
simplifies the way RUP describes work and enables managers to better visualize and understand inputs and outcomes.
RUP describes work in terms of disciplines; each discipline has activities that take place within certain iterations. The iterations, in turn,
take place within phases. The project Gantt chart included in RUP is structured as follows:
phase->discipline->workflow detail->activities (optional)
As we already noted, this structure distributes the tasks associated with a single unit of work across the chart, making it difficult to see the
cumulative results.
By using work components, you can show these outcomes much more clearly in a format that is familiar to both business and technical
managers. Work components appear on the Gantt chart as well-defined work units that result in tangible outputs and flow from the chart's
top left to bottom right corner.

Structure of a work component


Figure 3 shows a schematic for a work component within a RUP context.

Figure 3: Schematic for a work component in RUP showing essential parts


Table 1 shows the essential parts of the work component in Figure 1.

7/15/2004

RUP work components

Page 5 of 10

Table 1: Essential parts for a RUP work component


Work component

A named work component

Objective

Work component objective

Owner

Work component owner

Inputs (optional)

0 or more inputs (may be artifacts)

Work products (optional) 0 or more outputs (may be artifacts)


Discipline (optional)

A discipline as defined by RUP

Workflow

A workflow including roles, activities, and artifacts as defined by RUP

Result

The tangible result from the work component

Note that the term workflow as we use it in Figure 1 and Table 1 is synonymous with RUP workflow detail. Also, an input is not
synonymous with an entry point. You can have entries and dependencies between work components anywhere within a workflow detail
(similar to the entries and dependencies on a printed circuit board).
Figure 4 is an example of the work component "build architectural prototype," which could be used in the Elaboration phase of a RUP
project.

Figure 4: Example work component: "build architectural prototype"

Realizing a work component


You can realize a work component in terms of a ganttlet (i.e., a Gantt chart unit that realizes a work component) and a specification, as

7/15/2004

RUP work components

Page 6 of 10

we will see below.

Work component ganttlet


Figure 5 is a Gantt chart. For Microsoft Project users, it is a project template file (extension ".mpt") that includes tasks, (expected)
durations, work products and resources. You can adapt this template for your organization and reuse it for different projects. When project
managers build a project schedule, they can insert the template as a subproject and easily create a framework for customizing and
executing the work component. We will explain this more fully later. For example, the ganttlet for the work component "define scope"
could look like the one in Figure 5.

Figure 5: Ganttlet for the work component "define scope"


Click to enlarge

Work component specification


This specification is similar to function specifications in programming languages or operating systems. It could take the form of a help
page. For example, Figure 6 shows the specification for the work component "define scope."

7/15/2004

RUP work components

Page 7 of 10

Figure 6: Example specification (partial) for the work component "define scope"

Setting up a RUP project schedule using work components


To set up a RUP-based project schedule (Gantt chart) on Microsoft Project using work components, perform the following steps:
1.
2.
3.

Create a coarse-grained project schedule.


Insert and customize work components for the current iteration.
Insert and customize work components for the next iteration.

A full explanation of this process is beyond the scope of this article. Organizations using work components (such as Covansys) make
step-by-step guidelines available for users on their intranets.3
The completed plan could look like the one in Figure 7.

7/15/2004

RUP work components

Page 8 of 10

Figure 7: A RUP project schedule using work components


Now let's assume, as we did earlier, that the PM (project manager) asks a PMO member to review this Gantt chart. Here is how the
exchange might go this time:
PMO:
PM:
PMO:
PM:
PMO:

Oh, so you are creating the architectural prototype in Elaboration.


Yes, we are detailing the requirements, plus building and testing a prototype.
I can see that here...
The prototype tasks are in boldface under "analysis and design," "implementation," and "test."
OK, that's fine. I don't need any more detail.

The PMO now understands the Gantt chart's main themes major things the project will accomplish. The PM has made these
conspicuous by encapsulating planning elements into work components.

Benefits of work components


As we have seen, work components offer many benefits.
z

They reduce the complexity of Gantt charts that detail widely dispersed tasks by encapsulating workflow details.

Unlike summary tasks, they assign single ownership and a single result to major chunks of work, thereby improving accountability
and assessment capability.

They present stakeholders with a clear, functional picture of what they need to know (e.g., in Figure 7, a business owner could
readily identify the work component "define scope").

Organizations can store and make them available to users through work component libraries with corresponding online help.

7/15/2004

RUP work components

Page 9 of 10

Standard work components can have default workflow details, activities, resources, and work products that users can instantiate
and customize.

They provide common measures for assessment and work estimation across organizations.

Assessing project status using work components


By definition work components make it easier to assess status. The status should reflect how far the work has progressed toward the
desired tangible end result.
For example, "build architectural prototype" would be 100 percent complete when its result, "an incremental, executable prototype that
baselines the architecture" is 100 percent complete. One way to determine the degree of completion is to assign intermediate milestones
within the work component. In this example, the milestones could be: design review, completion of subsystem build for QA, and
successful release of the prototype.
You can also assess status by inspecting other details within work components, based on attributes of the project you would like to roll up
and report on. These might include:
z

Work products

Individual disciplines

Individual workflows

Developing organization-wide work components


Just as with any other component-based architecture, you can leverage a project plan architecture based on work components to gain
substantial benefits for your organization in terms of standardization, reuse, and ROI improvement. For example, one path might be:
z

Develop organization-wide guidelines for writing work components.

Develop an organization-wide framework for collecting and reviewing feedback on work components in active projects.

Appoint work component affinity teams such as:


{
{

A project management work component team consisting of work component owners for "set up project," "manage
Inception," and so forth.
A requirements work component team consisting of owners of work components for "define scope", "detail requirements"
and "detail user interface."

Have each work component team collect feedback on its components from designated pilot projects.

Have the teams modify and finalize the work components, based on the guidelines and feedback. As we mentioned above, you
can have multiple implementations of a work component (e.g., complex, medium, and light).

Have the teams formally archive and publish their work components for organization-wide use.

Estimating projects using work components


Work components are also good for estimating projects. Typically organizations use function points, features, or use cases to specify
work to be done. They then translate these into effort estimates through productivity and resource multipliers that are usually
organization-specific and track to organizational work components. We can think of the effort required for each work component as
follows:
work component effort = core effort + effort per requirement unit
You can track both measures on the right side of this equation by work component and then use the results to generate estimates. For
example, the core effort for the work component "define scope" is predicated on setting up the supporting work (including work products
such as the requirements management plan) and in many cases performing business modeling (under well-established constraints). The
effort per requirement unit is predicated on the number of features, the number and type of use cases plus supplementary specifications,

7/15/2004

RUP work components

Page 10 of 10

and the user interface. An organizational record of the effort required for "define scope" on small, medium and large projects would
provide a basis for estimating the effort required to define Inception-level scope for a given project type.

Work components in the industry now


Covansys and other organizations have already created work components for RUP communities to use within their software development
operations. This article reflects the current state of the art. As more organizations use work components, we can expect to see
organizational or even industrial work component libraries. Relevant qualitative and quantitative data will accompany each entry, helping
to further the concept's development to the software industry's benefit.

Notes
1 A printed circuit board contains electronic components and pins for input and output connections. Once the board is plugged in to a

circuit, it delivers specific functionality amplifying the sound in a radio, for example.
2 A grouping of activities performed in close collaboration to accomplish some result. Typically, the activities are performed either in
parallel or iteratively, with output from one activity serving as input for another activity. Grouping these activities in a workflow detail
provides a higher level of abstraction and improves the comprehensibility of workflows.
3 If you or your organization is interested in using work components, I invite you to contact me at 847-969-3049 or
kvaidya@covansys.com.

About the author


Kirti Vaidya, a senior director at Covansys, is an expert in the implementation of IBM Rational Unified Process, or RUP. In addition to
serving as a RUP implementation mentor in various industry segments, he has created many successful business models for large
corporations, using the Unified Modeling Language (UML). An active participant in a yearlong RUP implementation workshop led by IBM
Rational, he has also made significant contributions to the brands Web site, Recently he co-authored a two-part RUP Implementation
Guide for publication in The Rational Edge and led sessions at two successive IBM Rational user conferences.
After starting his IT career as an analyst/ programmer, he spent many years working first as a project manager and then a Project
Management Office (PMO) member while living in the USA, India, Germany, Japan, and Australia. He has been active from pre-sales to
delivery in development projects ranging from Web-based solutions and enterprise integration solutions to data warehouses, portals, and
application maintenance solutions. He holds a first rank masters degree in electrical engineering and also earned a postgraduate
certificate in software technology.

What do you think of this document?


Killer! (5)

Good stuff (4)

So-so; not bad (3)

Needs work (2)

Lame! (1)

Comments?

Submit feedback
developerWorks

About IBM

> Rational

| Privacy | Terms of use | Contact

7/15/2004

Formally speaking: How to apply OCL


Copyright IBM Corporation 2004

Page 1 of 6
http://www-106.ibm.com/developerworks/rational/library/5390.html

Search for:

within
Use + - ( ) " "

IBM home
developerWorks

All of dW

Search help

| Products & services | Support & downloads | My account

> Rational

Formally speaking: How to apply OCL


Gary Pollice
Worcester Polytechnic Institute
14 Jul 2004

Contents:
What are formal methods?
UML and OCL

OCL as a specification
from The Rational Edge: This article discusses various uses of OCL (Object Constraint Language)
language
for both developers and testers. IT also enumerates the many advantages of the language, which is
Testers like it, too
part of the UML specification.
Conclusion
If you were a computer science or software engineering
References
major in college, you probably had to take a course in the
Notes
foundations of computer science or formal methods. And
if you did, you probably thought, What will I ever use this
About the author
for?
Rate this article
Since I have devoted a significant part of my career to
working with language tools, formal methods are
important to me. But they also have a lot of value for
software practitioners, especially when they are
embedded in a specification language, such as OCL
(Object Constraint Language). In this article, I will share
with you why I value OCL and how I apply it.

Subscriptions:
dW newsletters
dW Subscription
(CDs and downloads)

What are formal methods?


Formal methods are the mathematical foundations for many technologies and practices that software engineers use. Joseph Goguen
says that formal methods are syntactic in essence but semantic in purpose.1 What he means is that formal methods are concerned with
form with the syntax of statements, predicates, and so on. They are also concerned with content.
Formal specification languages represent one area of formal methods. Among the best known are Larch, VDM, and Z. Most of these
languages are based on first-order logic with set theory. Many have supporting tools basically theorem provers that accept a
specification written in the formal language and evaluate it for consistency, completeness, and accuracy.
These languages describe what a program should do rather than how it should do it. Often they are syntactically simple and semantically
rich they use the symbols of mathematical logic (e.g.,
).

Unfortunately, understanding simple expressions in these languages such as


can be difficult, even for people with a
2
solid math education. But just because these languages are difficult to understand doesn't mean they are useless. Some kinds of
software must be developed and quality tested more rigorously than other kinds. For example, compilers must work correctly all the time,
so they are excellent candidates for formal specifications. Of course, we should always strive for bug-free software, but if a compiler
generates incorrect code, the consequences will be more dire than if a grocery list program fails.

UML and OCL


In addition to compilers, another component in many software developers toolkits today has a strong formal background: Unified
Modeling Language (UML). This language fits Goguens description of a formal method. It is syntactic in essence, offering a well-defined
way to construct a model. It is also semantic in purpose that is, it is designed to convey meaning. Much information can be encoded in
a UML model. But it is not always easy to construct syntactically correct and semantically rich models of software using just UML
diagrams. The rules for which type of arrowhead and which type of connector to use for which purpose can be just as confusing as the
syntax for a programming language such as Java. And then, even if you can construct a correct UML diagram, there is much information
that it will not convey.

The Rational Edge--July 2004

7/15/2004

Formally speaking: How to apply OCL

Page 2 of 6

However, OCL, a formal specification language that is part of the UML specification, enables you to annotate models with expressions
that clarify meaning. In UML 1.1, the main purpose of OCL was to identify the constraints on model elements. For example, it could help
you indicate that, to be assigned a room, a specific course must have at least six students enrolled. With OCL you could annotate the
association between the Course and Classroom classes to represent the constraint, as shown in Figure 1. As an alternative to the note
shown in this figure, you could use a constraint connector between the Course and Classroom classes.

Figure 1: Using OCL to indicate a constraint on assigning a classroom to a course


UML 2.0 has expanded the role of OCL to include queries, business rule specification, and other types of expressions. If Model Driven
Architecture (MDA) succeeds in taking hold, it will be in part because of OCL. It allows us to annotate models and convey specifications
that generate accurate code. I also use OCL to help clarify my focus on critical testing areas. As many developers do not know how to
apply OCL in these ways, I will devote the rest of this article to showing readers how I do it.

OCL as a specification language


Since my undergraduate days as a mathematics major, Ive enjoyed using some form of logical notation to express program design. One
of my professors at Rutgers University designed a programming language based on the predicate calculus3 that allowed me to write a
specification using the language of logic, encode it to a file, and compile it to a program that satisfied the specification. The effective
semantic richness was incredible.
Once, I experimented to see how using this predicate-calculus language (PCL) compared to using an Algol-like language. I wrote a
program to copy and transform a disk file to another form, applying certain filtering and transformation rules. First, I wrote it in PCL, using
six lines (expressions) of code; it was accepted and ran the first time.
Writing the very same program in the Algol-like language required more than 600 lines of code. So the savings PCL afforded, in terms of
what I had to write, was two orders of magnitude.4 Plus, I discovered an unexpected value in writing the PCL program first: I could use it
to specify my second implementation in the Algol-like language, which also compiled and executed correctly the first time! After that, I
began to write specifications in PCL whenever possible, and an amazing number of my programs compiled and ran correctly the first
time. So I found that logic was indeed useful outside of the classroom.
The biggest problem with PCL, though, was its bizarre syntax. If you have ever written an APL program, you can understand what Im
talking about. Although APL programmers love(d) their language, it is mostly unintelligible to mere mortals who have to program in
COBOL, C, or some other more common language. PCL suffered from the same problems.
However, now we have OCL, whose authors realized that ease-of-use and understandability were pretty important if they wanted to see
the language adopted by a wide audience. If you spend a little time studying the OCL specification and look at some examples, you can

7/15/2004

Formally speaking: How to apply OCL

Page 3 of 6

jump right into using it to specify programs.


Just as with UML, you can spend a lot of time and effort getting an OCL specification to obey all the syntax rules and requirements. But
you can expend much less effort and still write something that is useful and understandable. Lets refer to this as using semiformal
methods. You can do this when you get stuck; instead of attempting to follow every rule in OCL, use only the parts of it that are familiar to
you, or that your audience will find easy to understand.

A simple example
In last months column we looked at a triangle tester program that accepted three numbers and determined what type of triangle, if any,
has sides with corresponding lengths. Lets specify this in OCL.
Our method, kindOfTriangle, returned the object TriangleType, which enabled us to determine the type of triangle. The specification
for this method is shown in Code sample 1.

Code sample 1: Triangle tester kindOfTriangle specification


At first glance the code sample looks rather long. It also looks like some sort of pseudo code; which it is in a way. But lets look a little
closer. First of all, the specification is long because Ive formatted it that way. I could probably shorten it by ten lines if I wanted to. But it
still takes up less space than would the same specification written out in English prose. After presenting the next couple of features of this
specification Ill explain some of the OCL syntax and semantics.
The second thing to notice is that the specification is just that a specification that says what the effect of executing the method
kindOfTriangle will be. It says nothing about how to implement the method. This is a key attribute of specifications: They must be free of
implementation details, which may be difficult if we are using natural language. Often we have preconceived notions about

http://qacma.cupertino.ibm.com/cma/PreviewXMLArticle?CONTENT_ID=5390

7/16/2004

Formally speaking: How to apply OCL

Page 4 of 6

implementation details, such as what the data storage mechanism should be. If we remove implementation details, we get to the heart of
the problem and create a clearer specification.
The third feature of an OCL specification is that it is declarative, specifying only the what and not the how. There is no description of any
change in state or assignment to variables. OCL expressions are said to be side-effect free. In short, what you see is what you get.
Now lets go back and analyze Code sample 1. The first line tells us what the specification applies to its context. It is for the
kindOfTriangle operation in the TriangleTester class, and the operation returns a value of type TriangleType. Other kinds of context
declarations are defined in OCL for UML classifiers, attributes, and operations.
The second line describes the preconditions for this operation things that must be true for the operation to work properly. If you are
practicing design by contract,5 and the client must guarantee that contract conditions are met before invoking an operation, the clients
part of the contract is specified by the preconditions.
The rest of the specification consists of the post-conditions. This is the service side of the contract. If the preconditions are met, the
implementer agrees to produce the results specified by the post-conditions. If you have programmed in almost any modern programming
language, you should be able to read and understand the post-condition specification.
There is more to OCL than just context, preconditions, and post-conditions. It has syntax for describing invariants in a context, initial
values, queries, and so on. Also, OCL does not employ a lot of mathematical notation. Most of its notation is readily accessible to
software developers.
Jotting down specifications in OCL, whether you are planning to include them in a formal document, make them into comments in your
code, or throw them away, is a useful exercise. It helps you, as a software developer, to clarify what your real task is. But its not the only
use for OCL.

Testers like it, too


Test cases should be derived from specifications, but this may be difficult to do, especially if the specifications are written in prose in a
long document. Use cases are useful for giving testers enough information to perform system-level and black-box tests to ensure that the
system delivers value to the client. Analysis and design activities decompose a system into classes and subsystems that need to be
tested. OCL can be helpful here.
Lets start looking at the use-case level of a system specification. If you are familiar with use cases, you know that they already have precondition and post-condition attributes. With a little training, you could probably instruct everyone on how to read enough OCL to
understand pre-conditions and post-conditions written in it.6 This can help requirements specifiers focus on clarity and ensure that the use
case is consistent, coherent, and of real value to the actor.
If you describe the pre- and post-conditions of your use case with OCL, you can then make them the specification of your specification
and review the use-case flows of events to determine if they accurately reflect the OCL. You can also ensure that the flows of events
address all the constraints and visible results.
Testers can use the pre- and post-conditions to write their system-level test cases. For example, in the specification in Code sample 1, we
can quickly identify some test cases and construct a table to ensure that we have at least tested all possible result combinations. Our test
case table might look like Table 1.

Table 1: Triangle tester test cases

7/15/2004

Formally speaking: How to apply OCL

Page 5 of 6

The tests described in Table 1 clearly are not complete. However they provide at least a basic test of the post-conditions defined in the
Code sample 1 specification. Depending upon the priority and criticality of the feature and the risks of not completely testing all possible
combinations, we can either stop here or add as many test cases as necessary.
I have found that creating test cases from OCL specifications is a straightforward task. Programmers and testers who use OCL can
become very good at ensuring that the specifications are correct and the tests really address them. In fact, you could use OCL in
combination with the TFP technique I described in last months column to design tests from a well-formed, independent specification.
When I teach software testing classes at WPI, I have students write OCL specifications for methods that lack other specifications. This
helps them do a better job of testing because they are able to isolate the methods real requirements or those the implementer
perceives and write appropriate tests for them. Sometimes, implementers find that perceived requirements do not match actual ones.
OCL can help by creating a concise, readable, and analyzable specification.

Conclusion
OCL is not the only formal language that can be used for specification, nor is it the most rigorous or complete one. But it does have some
important things going for it:
z

It does not have overly complicated mathematical symbols and rules.

It is easy to learn and begin applying.

It is part of a standard adopted by many organizations.

It will be supported by many new tools under development.

You do not even need to use OCL with the rest of UML to realize its benefits. Like any new technique, you have to learn it, begin to use it,
refine your skills, and keep in mind the end goal: producing reliable software.
In general, it is useful to study and embrace formal methods as a way of thinking. The software professionals I know who have done so
are, in my opinion, some of the best analysts, designers, and programmers that I have ever had the privilege of working with. There is
something about thinking formally that is well-suited to developing computer software. If you have a chance to take a course in formal
methods, I urge you to do so and then note how it makes you better at what you do.

References
Information about OCL and the OCL specification can be found at http://www.omg.org.
Jos Warmer and Anne Kleppe, The Object Constraint Language, 2e. Addison-Wesley, 2003 (ISBN: 0321179366)

7/15/2004

Formally speaking: How to apply OCL

Page 6 of 6

Joseph A. Goguens Web page contains his publications on software engineering, architecture, formal methods, and methodology:
http://www.cs.ucsd.edu/users/goguen/projs/swarch.html
Peter Ryan and Chris Sennett, eds., Formal Methods in Systems Engineering. Springer-Verlag, 1993. (ISBN: 3540197516)

Notes
1 Joseph A. Goguen in the Introduction to Formal Methods in Systems Engineering, Ryan and Sennett, ed., Springer-Verlag, 1993.
2 This particular expression declares succinctly that an ordered collection, x, of n+1 integers, or some other comparable type, is sorted in
ascending order.
3 The predicate calculus is a logic consisting of predicate expressions that evaluate whether something is true or false. It has the typical

logical operations, such as AND and OR, and relational operators such as =, <, and so on.
4 An order of magnitude is a factor of ten. Two orders of magnitude sounds much more impressive than 100 times, dont you think?
5 Design by contract is associated mainly with Dr. Bertrand Meyer and his Eiffel programming language. See

http://archive.eiffel.com/doc/manuals/technology/contract/ for more information.


6 In their book, The Object Constraint Language, Second Edition, Warmer and Kleppe provide an alternate OCL syntax that is easier for

business modelers to use and understand. OCL can be quite flexible in the syntax area.

About the author


Gary Pollice is a Professor of Practice at Worcester Polytechnic Institute, in Worcester, MA. He teaches software
engineering, design, testing, and other computer science courses, and also directs student projects. Before entering the
academic world, he spent more than thirty-five years developing various kinds of software, from business applications to
compilers and tools. His last industry job was with IBM Rational Software, where he was known as "the RUP Curmudgeon"
and was also a member of the original Rational Suite team. He is the primary author of Software Development for Small
Teams: A RUP-Centric Approach, published by Addison-Wesley in 2004. He holds a B.A. in mathematics and M.S. in
computer science.

What do you think of this document?


Killer! (5)

Good stuff (4)

So-so; not bad (3)

Needs work (2)

Lame! (1)

Comments?

Submit feedback
developerWorks

About IBM

> Rational

| Privacy | Terms of use | Contact

7/15/2004

Book review: Eric Meyer on CSS: Mastering the Language of Web Design
Copyright IBM Corporation 2004.

http://www-106.ibm.com/developerworks/rational/library/5188.html

Search for:

within
Use + - ( ) " "

IBM home
developerWorks

Page 1 of 2

All of dW

Search help

| Products & services | Support & downloads | My account

> Rational

Book review: Eric Meyer on CSS: Mastering the


Language of Web Design
Kerry McKay
Worcester Polytechnic Institute
2 Jul 2004

Contents:
Notes
About the author

from The Rational Edge: McKay reviews a book designed for experienced HTML users who want to Rate this article
improve their Web design capabilities. Using a project-oriented approach, the book takes readers
Subscriptions:
step by step through ways of applying cascading style sheet (CSS) techniques for purposes
dW newsletters
ranging from online greeting cards to input forms.
Eric A. Meyer
New Riders, 2002
ISBN: 0-7357-1245-X
Cover price: US$45.00
352 pages

dW Subscription
(CDs and downloads)

This is a wonderful book for HTML-proficient coders who wish to enhance the look and feel of their Web pages. In it, Meyer shows various
cascading style sheet (CSS) techniques that coders can use to update outdated HTML-only sites into manifestations of modern Web
technology. He assumes that readers have a basic knowledge of HTML and CSS, and will edit pure text files rather than using
WYSIWYG1 editors or Web editing tools such as Dreamweaver.
Meyer briefly examines motives for moving from the realm of straight HTML into the
Projects in Eric Meyer on CSS
world of a global style configuration with CSS. An external CSS file works just like a
1. Converting an existing page (stripping
configuration file, defining the aesthetic attributes of a page. By defining style elements in
a bloated HTML document down to a
a central location either a separate file or at the beginning of an HTML document
streamlined HTML file with
you can more easily change the look of an element type without having to modify each
accompanying CSS)
instance of it.
2. Styling a press release
3. Styling an events calendar
The book's style is very casual and interactive, which makes it feel like direct guidance
4. Bringing hyperlinks to life
from a teacher rather than a formal, impersonal manual or how-to book. Meyer's
5. How to skin a menu (adding effects to
discussions are also very detailed without being verbose, and he throws in the
make a menu attractive)
occasional (sometimes corny) joke. All the examples are straightforward and
6. Styling for print
unambiguous; Meyer's instructions leave nothing to question.
7. Making an input form look good
8. Creating an online greeting card
Each of the book's thirteen chapters contains an independent project (see sidebar).
9. Creating a multicolumn layout
Every project is a hands-on tool, carefully designed to give you everything you need to
10. Sneaking out of the box (adding
understand a particular task. At the beginning of each one, Meyer explicitly describes the
curves and acute/obtuse angles)
point of the project. From there, he starts with a plain, basic file and progressively
11. Positioning a better design (creating
modifies the style sheet and HTML in small, easy-to-digest steps. The book highlights
interesting page layouts without
the code changes at each step and includes a browser snapshot as well. By the time you
tables)
arrive at the end of a chapter, you know exactly what each line of code in the project's
12. Fixing your backgrounds (creating
style sheet means and why it is there.
cool, scrolling effects with fixed
backgrounds)
13.
Eric Meyer on CSS in CSS (recreating
For those who like to play along at home, the book has a companion Web site
the book layout in a browser)
(http://www.ericmeyeroncss.com) containing the projects' code. Meyer also provides
bonus materials and more examples for the book's lessons on this site. Although it does
not offer explanations for some of the fancier tricks, you can simply grab the style sheets and work through them on your own.
Overall, this book is extremely useful and easy to follow. Its clean, elegant examples would translate well for almost any use. For me, the
only disappointment was the book's length; it's awfully short for the price, especially considering how much space the illustrations take up.
Nevertheless, I found the content to be of high enough quality to interest me in purchasing the sequel: More Eric Meyer on CSS. And

The Rational Edge--July 2004

7/15/2004

Book review: Eric Meyer on CSS: Mastering the Language of Web Design

Page 2 of 2

personally, I'd toss this book at any friend who ever mutters, "I'm thinking of making a Web site..."

Notes
1 "What You See Is What You Get" editors require you to know little or nothing about the underlying structure of a document. The editor

displays exactly how the resulting document will appear.

About the author


Kerry McKay is currently earning an M.S. in the department of computer science at Worcester Polytechnic Institute, where
she also completed a B.S. in computer science. Most of her graduate studies have focused on cryptography and computer
security; she is also interested in Web technologies and theory. After receiving her M.S. degree, she plans to pursue a Ph.D.
in computer science.

What do you think of this document?


Killer! (5)

Good stuff (4)

So-so; not bad (3)

Needs work (2)

Lame! (1)

Comments?

Submit feedback
developerWorks

About IBM

> Rational

| Privacy | Terms of use | Contact

7/15/2004

Book excerpt: Absolute Java -- "Arrays (Chapter 6*)


Copyright IBM Corporation 2004.

Page 1 of 1
http://www-106.ibm.com/developerworks/rational/library/5419.html

Search for:

within
Use + - ( ) " "

IBM home
developerWorks

All of dW

Search help

| Products & services | Support & downloads | My account

> Rational

Book excerpt: Absolute Java -- "Arrays (Chapter


6*)
15 Jul 2004

Contents:
Rate this article

from The Rational Edge: From a new introductory book on Java designed for both novice and
experienced programmers, this chapter covers arrays and references, programming with arrays,
and multidimensional arrays.

Subscriptions:
dW newsletters
dW Subscription
(CDs and downloads)

from Absolute Java by Walter Savitch


(Addison-Wesley, 2004)

Written by one of the most widely read authors in the area of programming, Absolute Java offers complete coverage of the Java
programming language. It provides all the tools necessary for both experienced and novice programmers to master the language,
including thorough coverage of the Java Library, complete and fully executable code samples, sections highlighting programming tips and
common pitfalls, and logically ordered coverage of Java topics. To reinforce learning, the books chapters conclude with a summary,
answers to self-test exercises, and programming projects.
In Chapter 6, Savitch discusses arrays, including arrays and references, programming with arrays, and multidimensional arrays.
*Chapter 6 is posted in its entirety by permission from Addison-Wesley.
Chapter 6 pdf file (192 K)

What do you think of this document?


Killer! (5)

Good stuff (4)

So-so; not bad (3)

Needs work (2)

Lame! (1)

Comments?

Submit feedback
developerWorks

About IBM

> Rational

| Privacy | Terms of use | Contact

The Rational Edge--July 2004

7/15/2004

5640_ch06.fm Page 305 Friday, November 14, 2003 6:18 AM

CHAPTER

Arrays
6.1

INTRODUCTION TO ARRAYS 306


Creating and Accessing Arrays 307
The length Instance Variable 311
Tip: Use for Loops with Arrays 311
Pitfall: Array Indices Always Start with Zero 312
Pitfall: Array Index Out of Bounds 313
Initializing Arrays 313
Pitfall: An Array of Characters Is Not a String 315

6.2

ARRAYS AND REFERENCES 316


Arrays Are Objects 316
Pitfall: Arrays with a Class Base Type 318
Arrays Parameters 319
Pitfall: Use of = and == with Arrays 323
Arguments for the Method main 326
Methods that Return an Array 327

6.3

PROGRAMMING WITH ARRAYS 329


Partially Filled Arrays 329
Example: A Class for Partially Filled Arrays 333

Tip: Accessor Methods Need Not Simply Return


Instance Variables 339
Privacy Leaks with Array Instance Variables 340
A Preview of Vectors 342
Example: Sorting an Array 342

6.4 MULTIDIMENSIONAL ARRAYS 346


Multidimensional Array Basics 346
Using the length Instance Variable 350
Ragged Arrays 351
Multidimensional Array Parameters and Returned
Values 352
Example: A Grade Book Class 353
CHAPTER SUMMARY 359
ANSWERS TO SELF-TEST EXERCISES 360
PROGRAMMING PROJECTS 367

5640_ch06.fm Page 306 Friday, November 14, 2003 6:18 AM

Arrays
Memory is necessary for all the operations of reason.
Blaise Pascal, Penses

INTRODUCTION
An array is a data structure used to process a collection of data that is all of the
same type, such as a list of numbers of type double or a list of strings. In this
chapter we introduce you to the basics of defining and using arrays in Java.

PREREQUISITES
Section 6.1 requires only Chapters 1 through 3 and Section 4.1 of Chapter 4.
Indeed, much less than all of Section 4.1 is needed. All you really need from
Section 4.1 is to have some idea of what an object is and what an instance
variable is.
The remaining sections require Chapters 1 through 5 with the exception
that Section 5.4 on packages and javadoc is not required.

6.1

Introduction to Arrays
It is a capital mistake to theorize
before one has data.
Sir Arthur Conan Doyle,
Scandal in Bohemia (Sherlock Holmes)

Suppose we wish to write a program that reads in five test scores and performs
some manipulations on these scores. For instance, the program might compute the highest test score and then output the amount by which each score
falls short of the highest. The highest score is not known until all five scores
are read in. Hence, all five scores must be retained in storage so that after the
highest score is computed each score can be compared to it. To retain the five
scores, we will need something equivalent to five variables of type int. We
could use five individual variables of type int, but keeping track of five variables is hard, and we may later want to change our program to handle 100
scores; certainly, keeping track of 100 variables is impractical. An array is the
perfect solution. An array behaves like a list of variables with a uniform naming mechanism that can be declared in a single line of simple code. For example, the names for the five individual variables we need might be score[0],

5640_ch06.fm Page 307 Friday, November 14, 2003 6:18 AM

Introduction to Arrays

307

score[1], score[2], score[3], and score[4]. The part that does not change, in this
case score, is the name of the array. The part that can change is the integer in the
square brackets [].

CREATING AND ACCESSING ARRAYS


In Java, an array is a special kind of object, but it is often more useful to think of an
array as a collection of variables all of the same type. For example, an array that behaves
like a collection of five variables of type double can be created as follows:
double[] score = new double[5];

This is like declaring the following to be five variables of type double:


score[0], score[1], score[2], score[3], score[4]

These individual variables that together make up the array are referred to in a variety of
different ways. We will call them indexed variables, though they are also sometimes
called subscripted variables or elements of the array. The number in square brackets is
called an index or a subscript. In Java, indices are numbered starting with 0, not starting
with 1 or any number other than 0. The number of indexed variables in an array is called
the length or size of the array. When an array is created, the length of the array is given
in square brackets after the array name. The indexed variables are then numbered (also
using square brackets) starting with 0 and ending with the integer that is one less than
the length of the array.
The following

indexed variable
subscripted
variable
index, subscript
size, length

double[] score = new double[5];

is really shorthand for the following two statements:


double[] score;
score = new double[5];

The first statement declares the variable score to be of the array type double[]. The
second statement creates an array with five indexed variables of type double and makes
the variable score a name for the array. You may use any expression that evaluates to a
nonnegative int value in place of the 5 in square brackets. In particular you can fill a
variable with a value read from the keyboard and use the variable in place of the 5. In
this way the size of the array can be determined when the program is run.
An array can have indexed variables of any type, but they must all be of the same
type. This type is called the base type of the array. In our example, the base type of the
array score is double. To declare an array with base type int, simply use the type name
int instead of double when the array is declared and created. The base type of an array
can be any type. In particular it can be a class type.

base type

5640_ch06.fm Page 308 Friday, November 14, 2003 6:18 AM

308

Chapter 6 Arrays

DECLARING

AND

CREATING

AN

ARRAY

You declare an array name and create an array in almost the same way that you create and name
objects of classes. There is only a slight difference in the syntax.

SYNTAX:
Base_Type[] Array_Name = new Base_Type[Length];
The Length may be given as any expression that evaluates to a nonnegative integer. In particular
Length can be an int variable.

EXAMPLES:
char[] line = new char[80];
double[] reading = new double[300];
Person[] specimen = new Person[100];
Person is a class.

Each of the five indexed variables of our example array score can be used just like
any other variable of type double. For example, all of the following are allowed in Java:
score[3] = 32;
score[0] = score[3] + 10;
System.out.println(score[0]);

The five indexed variables of our sample array score are more than just five plain
old variables of type double. That number in square brackets is part of the indexed variables name. So, your program can compute the name of one of these variables. Instead
of writing an integer constant in the square brackets, you can use any expression that
evaluates to an integer that is at least 0 and at most 4. So, the following is allowed:
System.out.println(score[index] + " is at position " + index);

where index is a variable of type int that has been given one of the values 0, 1, 2, 3, or 4.
When we refer to these indexed variables grouped together into one collective item,
we will call them an array. So, we can refer to the array named score (without using
any square brackets).
The program in Display 6.1 shows an example of using our sample array score as
five indexed variables, all of type double.
Note that the program can compute the name of an indexed variable by using a variable as the index, as in the following for loop:
for (index = 0; index < 5; index++)
System.out.println(score[index] + " differs from max by "
+ (max score[index]));

5640_ch06.fm Page 309 Friday, November 14, 2003 6:18 AM

Introduction to Arrays

309

Display 6.1 An Array Used in a Program (Part 1 of 2)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class ArrayOfScores
{
/**
Reads in 5 scores and shows how much each
score differs from the highest score.
*/
public static void main(String[] args) throws IOException
{
BufferedReader keyboard =
new BufferedReader(new InputStreamReader(System.in));
double[] score = new double[5];
int index;
double max;
This form of input is covered in
String inputLine;
Chapter 2, Section 2.3.

18
19
20
21
22
23
24
25
26
27

System.out.println("Enter 5 scores, one per line:");


score[0] = stringToDouble(keyboard.readLine( ));
max = score[0];
for (index = 1; index < 5; index++)
{
score[index] = stringToDouble(keyboard.readLine( ));
if (score[index] > max)
max = score[index];
//max is the largest of the values score[0],..., score[index].
}

28
29
30
31
32
33
34
35
36
37
38

System.out.println("The highest score is " + max);


System.out.println("The scores are:");
for (index = 0; index < 5; index++)
System.out.println(score[index] + " differs from max by "
+ (max score[index]));
}
private static double stringToDouble(String stringObject)
{
return Double.parseDouble(stringObject.trim());
}
}

The methods parseDouble and trim are


discussed in Chapter 5 in the subsection entitled
Wrapper Classes.

5640_ch06.fm Page 310 Friday, November 14, 2003 6:18 AM

310

Chapter 6 Arrays

Display 6.1 An Array Used in a Program (Part 2 of 2)


SAMPLE DIALOGUE
Enter 5 scores, one per line:
80
99.9
75
100
85.5
The highest score is 100
The scores are:
80.0 differs from max by 20
99.9 differs from max by 0.1
75.0 differs from max by 25
100.0 differs from max by 0.0
85.5 differs from max by 14.5

Due to imprecision in floating-point


arithmetic, this value will probably only
be a close approximation to 0.1.

A Common Way to Visualize an Array:

Indices

80

99.9

75

100

85.5

The array score

square
brackets []

score[3]

Do not confuse the three ways to use the square brackets [] with an array name.
First, the square brackets can be used to create a type name, such as the double[] in the
following:
double[] score;

Second, the square brackets can be used with an integer value as part of the special
syntax Java uses to create a new array, as in
score = new double[5];

The third use of square brackets is to name an indexed variable of the array, such as
or score[3], as illustrated by the following line:

score[0]

max = score[0];

5640_ch06.fm Page 311 Friday, November 14, 2003 6:18 AM

Introduction to Arrays

311

As we mentioned previously, the integer inside the square brackets can be any
expression that evaluates to a suitable integer, as illustrated by the following:
int next = 1;
score[next + 3] = 100;
System.out.println(
"Score at position 4 is " + score[next + 3]);

Note that, in the preceding code, score[next + 3] and score[4] are the same
indexed variable, because next + 3 evaluates to 4.

THE length INSTANCE VARIABLE


In Java an array is considered to be an object, and, like other objects, it might have
instance variables. As it turns out, an array has only one public instance variable, which
is named length. The instance variable length is automatically set to the size of the
array when the array is created. For example, if you create an array as follows,
double[] score = new double[5];

then score.length has a value of 5.


The length instance variable can be used to make your program clearer by replacing
an unnamed constant, such as 5, whose meaning may not be obvious, with a meaningful name like score.length. In Display 6.2 we have rewritten the program in Display
6.1 using the length instance variable.
The length instance variable cannot be changed by your program (other than by
creating a new array with another use of new).1 For example, the following is illegal:
score.length = 10;//Illegal

Tip

USE for LOOPS

WITH

ARRAYS

The second for loop in Display 6.2 illustrates a common way to step through an entire array
using a for loop:
for (index = 0; index < score.length; index++)
System.out.println(score[index] + " differs from max by "
+ (max score[index]));

The for loop is ideally suited for performing array manipulations.

The technical details are as follows: The instance variable length is created when the array is
created and is declared to be public final int.

5640_ch06.fm Page 312 Friday, November 14, 2003 6:18 AM

Chapter 6 Arrays

312

Display 6.2 The length Instance Variable


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

public class ArrayOfScores2


The sample dialog is the same as in Display 6.1.
{
/**
Reads in 5 scores and shows how much each
score differs from the highest score.
*/
public static void main(String[] args) throws IOException
{
BufferedReader keyboard =
new BufferedReader(new InputStreamReader(System.in));
double[] score = new double[5];
int index;
double max;
String inputLine;

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

This class also contains the method


stringToDouble, even though it is not shown.
The method stringToDouble is defined in
Display 6.1.

System.out.println("Enter " + score.length + " scores, one per line:");


score[0] = stringToDouble(keyboard.readLine( ));
max = score[0];
for (index = 1; index < score.length; index++)
{
score[index] = stringToDouble(keyboard.readLine( ));
if (score[index] > max)
max = score[index];
//max is the largest of the values score[0],..., score[index].
}
System.out.println("The highest score is " + max);
System.out.println("The scores are:");
for (index = 0; index < score.length; index++)
System.out.println(score[index] + " differs from max by "
+ (max score[index]));
}
}

Pitfall

ARRAY INDICES ALWAYS START

WITH

ZERO

The indices of an array always start with 0 and end with the integer that is one less than the size of the
array.

5640_ch06.fm Page 313 Friday, November 14, 2003 6:18 AM

Introduction to Arrays

313

Pitfall

ARRAY INDEX OUT

OF

BOUNDS

The most common programming error made when using arrays is attempting to use a nonexistent
array index. For example, consider the following:
int[] a = new int[6];

When using the array a, every index expression must evaluate to one of the integers 0 through 5.
For example, if your program contains the indexed variable a[i], the i must evaluate to one of
the six integers 0, 1, 2, 3, 4, or 5. If i evaluates to anything else, that is an error. When an index
expression evaluates to some value other than those allowed by the array declaration, the index is
said to be out of bounds. If your program attempts to use an array index that is out of bounds,
then your program will end with an error message.2 Note that this is a run-time error message, not
a compiler error message.
Array indices get out of bounds most commonly at the first or last iteration of a loop that processes the array. So, it pays to carefully check all array processing loops to be certain that they
begin and end with legal array indices.

INITIALIZING ARRAYS
An array can be initialized when it is declared. When initializing the array, the values
for the various indexed variables are enclosed in braces and separated with commas.
The expression with the braces is placed on the right-hand side of an assignment operator. For example:
int[] age = {2, 12, 1};

The array length (size) is automatically set to the number of values in the braces. So,
this initializing declaration is equivalent to the following statements:
int[] age = new int[3];
age[0] = 2;
age[1] = 12;
age[2] = 1;

You can also initialize array elements using a for loop. For example:
double[] reading = new double[100];
int index;
for (index = 0; index < reading.length; index++)
reading[index] = 42.0;

2
Technically speaking, an ArrayIndexOutOfBoundsException is thrown. We will discuss
exceptions in Chapter 9. Until you learn about handling exceptions, exceptions will simply
appear as error conditions to you.

illegal
array index

5640_ch06.fm Page 314 Friday, November 14, 2003 6:18 AM

314

automatic
initialization

Chapter 6 Arrays

If you do not initialize the elements of an array, they will automatically be initialized
to a default value for the base type. The default values are the usual ones. For numeric
types the default value is the zero of the type. (For base type char the default value is the
nonprintable zeroth character (char)0, not the space character.) For the type boolean
the default value is false. For class types, the default value is null. For example, if you
do not initialize an array of doubles, each element of the array will be initialized to 0.0.
Self-Test Exercises
1. In the array declaration
String[] word = new String[5];

what is
a. the array name?
b. the base type?
c. the length of the array?
d. the range of values an index accessing this array can have?
e. one of the indexed variables (or elements) of this array?
2. In the array:
double[] score = new double[10];

what is
a. the value of score.length?
b. the first index of score?
c. the last index of score?
3. What is the output of the following code?
char[] letter = {'a', 'b', 'c'};
for (int index = 0; index < letter.length; index++)
System.out.print(letter[index] + ", ");

4. What is the output of the following code?


double[] a = {1.1, 2.2, 3.3};
System.out.println(a[0] + " " + a[1] + " " + a[2]);
a[1] = a[2];
System.out.println(a[0] + " " + a[1] + " " + a[2]);

5640_ch06.fm Page 315 Friday, November 14, 2003 6:18 AM

Introduction to Arrays

5. What is wrong with the following piece of code?


int[] sampleArray = new int[10];
for (int index = 1; index <= sampleArray.length; index++)
sampleArray[index] = 3*index;

6. Suppose we expect the elements of the array a to be ordered so that


a[0] a[1] a[2] ...

However, to be safe we want our program to test the array and issue a warning in case it
turns out that some elements are out of order. The following code is supposed to output
such a warning, but it contains a bug; what is the bug?
double[] a = new double[10];
<Some code to fill the array a goes here.>
for (int index = 0; index < a.length; index++)
if (a[index] > a[index + 1])
System.out.println("Array elements " + index +
" and " + (index + 1) + " are out of order.");

Pitfall

AN ARRAY

OF

CHARACTERS IS NOT

STRING

An array of characters, such as the array a created below, is conceptually a list of characters and
so is conceptually like a string:
char[] a = {'A', ' ', 'B', 'i', 'g', ' ', 'H', 'i', '!'};

However, an array of characters, like a, is not an object of the class String. In particular, the following is illegal in Java:
String s = a;

Similarly, you cannot normally use an array of characters, like a, as an argument for a parameter
of type String.
It is, however, easy to convert an array of characters to an object of type String. The class
String has a constructor that has a single parameter of type char[]. So, you can obtain a
String value corresponding to an array of characters, like a, as follows:
String s = new String(a);

The object s will have the same sequence of characters as the array a. The object s is an independent
copy; any changes made to a will have no effect on s. Note that this always uses the entire array a.

315

5640_ch06.fm Page 316 Friday, November 14, 2003 6:18 AM

316

Chapter 6 Arrays

There is also a String constructor that allows you to specify a subrange of an array of characters
a. For example,
String s2 = new String(a, 2, 3);

produces a String object with 3 characters from the array a starting at index 2. So, if a is as
above, then
System.out.println(s2);

outputs
Big

Although an array of characters is not an object of the class String, it does have some things in
common with String objects. For example, you can output an array of characters using
println, as follows,
System.out.println(a);

which produces the output


A Big Hi!

provided a is as given above.

6.2

Arrays and References


A little more than kin, and less than kind.
William Shakespeare, Hamlet

Just like a variable of one of the class types youve seen, a variable of an array type holds
a reference. In this section we explore the consequences of this fact, including a discussion of array parameters. We will see that arrays are objects and that array types can be
considered class types, but somewhat different kinds of class types. Arrays and the
kinds of classes weve seen before this chapter are a little more than kin, and less than
kind.

ARRAYS ARE OBJECTS


There are two ways to view an array: as a collection of indexed variables, and as a single
item whose value is a collection of values of the base type. In Section 6.1 we discussed
using arrays as a collection of indexed variables. We will now discuss arrays from the
second point of view.

5640_ch06.fm Page 317 Friday, November 14, 2003 6:18 AM

Arrays and References

317

An array can be viewed as a single item whose value is a collection of values of the
base type. An array variable (as opposed to an array indexed variable) names the array as
a single item. For example, the following declares a variable of an array type:
double[] a;

This variable a can and will contain a single value. The expression
new double[10]

creates an array object and stores the object in memory. The following assignment
statement places a reference to (the memory address of ) this array object in the variable a:
a = new double[10];

Typically we combine all this into a single statement as follows:


double[] a = new double[10];

Notice that this is almost exactly the same as the way that we view objects of a class
type. In Java, an array is considered an object. Whenever Java documentation says that
something applies to objects, that means that it applies to arrays as well as objects of the
class types weve seen up to now. You will eventually see examples of methods that can
take arguments that may be objects of any kind. These methods will accept array
objects as arguments as well as objects of an ordinary class type. Arrays are somewhat
peculiar in how they relate to classes. Some authorities say array types are not classes
and some authorities say they are classes. But, all authorities agree that the arrays themselves are objects. Given that arrays are objects, it seems that one should view array
types as classes, and we will do so. However, although an array type double[] is a class,
the syntax for creating an array object is a bit different. To create an array, you use the
following syntax:
double a = new double[10];

You can view the expression new double[10] as an invocation of a constructor that uses
a nonstandard syntax. (The nonstandard syntax was used to be consistent with the syntax used for arrays in older programming languages.)
As we have already seen, every array has an instance variable named length, which is
a good example of viewing an array as an object. As with any other class type, array
variables contain memory addresses, or, as they are usually called in Java, references. So
array types are reference types.3
Since an array is an object, you might be tempted to think of the indexed variables
of an array, such as a[0], a[1], and so forth, as being instance variables of the object.
3

In many programming languages, such as C++, arrays are also reference types just as they are
in Java. So, this detail about arrays is not peculiar to Java.

5640_ch06.fm Page 318 Friday, November 14, 2003 6:18 AM

318

Chapter 6 Arrays

This is actually a pretty good analogy, but it is not literally true. Indexed variables are
not instance variables of the array. Indexed variables are a special kind of variable peculiar to arrays. The only instance variable in an array is the length instance variable.
An array object is a collection of items of the base type. Viewed as such, an array is
an object that can be assigned with the assignment operator and plugged in for a
parameter of an array type. Since an array type is a reference type, the behaviors of
arrays with respect to assignment =, ==, and parameter passing mechanisms are the
same as what we have already described for classes. In the next few subsections we discuss these details about arrays.

ARRAYS ARE OBJECTS


In Java, arrays are considered to be objects, and, although there is some disagreement on this
point, you can safely view an array type as a class type.

ARRAY TYPES ARE REFERENCE TYPES


A variable of an array type holds the address of where the array object is stored in memory. This
memory address is called a reference to the array object.

Pitfall

ARRAYS

WITH A

CLASS BASE TYPE

The base type of an array can be of any type, including a class type. For example, suppose Date
is a class and consider the following:
Date[] holidayList = new Date[20];

This creates the 20 indexed variables holidayList[0], holidayList[1], ..., holidatList[19]. It is important to note that this creates 20 indexed variables of type Date. This
does not create 20 objects of type Date. (The index variables are automatically initialized to
null, not to an object of the class Date.) Like any other variable of type Date, the indexed variables require an invocation of a constructor using new to create an object. One way to complete
the initialization of the array holidayList is as follows:
Date[] holidayList = new Date[20];
for (int i = 0; i < holidayList.length; i++)
holidayList[i] = new Date();

5640_ch06.fm Page 319 Friday, November 14, 2003 6:18 AM

Arrays and References

319

If you omit the for loop (and do not do something else more or less equivalent), then when you
run your code, you will undoubtedly get an error message indicating a null pointer exception.
If you do not use new to create an object, an indexed variable like holidayList[i] is just a
variable that names no object and hence cannot be used as the calling object for any method.
Whenever you are using an array with a class base type and you get an error message referring to
a null pointer exception, it is likely that your indexed variables do not name any objects and
you need to add something like the above for loop.

ARRAYS PARAMETERS
You can use both array indexed variables and entire arrays as arguments to methods,
although they are different types of parameters. We first discuss array indexed variables
as arguments to methods.
An indexed variable can be an argument to a method in exactly the same way that
any variable of the array base type can be an argument. For example, suppose a program contains the following declarations:

indexed variable
arguments

double n = 0;
double[] a = new double[10];
int i;

If myMethod takes one argument of type double, then the following is legal:
myMethod(n);

Since an indexed variable of the array a is also a variable of type double, just like n, the
following is equally legal:
myMethod(a[3]);

There is one subtlety that does apply to indexed variables used as arguments. For
example, consider the following method call:
myMethod(a[i]);

If the value of i is 3, then the argument is a[3]. On the other hand, if the value of i is
0, then this call is equivalent to the following:
myMethod(a[0]);

The indexed expression is evaluated to determine exactly which indexed variable is


given as the argument.
You can also define a method that has a formal parameter for an entire array so that
when the method is called, the argument that is plugged in for this formal parameter is
an entire array. Whenever you need to specify an array type, the type name has the

entire array
parameters

5640_ch06.fm Page 320 Friday, November 14, 2003 6:18 AM

320

Chapter 6 Arrays

ARRAY INDEXED VARIABLES

AS

ARGUMENTS

An array indexed variable can be used as an argument anyplace that a variable of the arrays
base type can be used. For example, suppose you have the following:
double[] a = new double[10];

Indexed variables such as a[3] and a[index] can then be used as arguments to any method
that accepts a double as an argument.

form Base_Type[], so this is how you specify a parameter type for an entire array, For
example, the method doubleArrayElements, given in what follows, will accept any
array of double as its single argument:
public class SampleClass
{
public static void doubleArrayElements(double[] a)
{
int i;
for (i = 0; i < a.length; i++)
a[i] = a[i]*2;
}
<The rest of the class definition goes here.>
}

To illustrate this, suppose you have the following in some method definition,
double[] a = new double[10];
double[] b = new double[30];

and suppose that the elements of the arrays a and b have been given values. Both of the
following are then legal method invocations:
SampleClass.doubleArrayElements(a);
SampleClass.doubleArrayElements(b);

Note that no square brackets are used when you give an entire array as an argument to
a method.
An array type is a reference type just as a class type is, so, as with a class type argument, a method can change the data in an array argument. To phrase it more precisely,
a method can change the values stored in the indexed variables of an array argument.
This is illustrated by the preceding method doubleArrayElements.
An array type determines the base type of an array argument that may be plugged in
for the parameter, but it does not specify the length of the array. An array knows its

5640_ch06.fm Page 321 Friday, November 14, 2003 6:18 AM

Arrays and References

321

length and stores it in the length instance variable. The same array parameter can be
replaced with array arguments of different lengths. Note that the preceding method
doubleArrayElements can take an array of any length as an argument.

ARRAY PARAMETERS

AND

ARRAY ARGUMENTS

An argument to a method may be an entire array. Array arguments are like objects of a class, in
that the method can change the data in an array argument; that is, a method can change the values stored in the indexed variables of an array argument. A method with an array parameter is
defined and invoked as illustrated by the following examples. Note that the array parameter
specifies the base type of the array, but not the length of the array.

EXAMPLES (OF

ARRAY PARAMETERS):

public class AClass


{
public static void listChars(char[] a)
{
int i;
for (i = 0; i < a.length; i++)
System.out.println(a[i] + " ");
}
public static void zeroAll(int[] anArray)
{
int i;
for (i = 0; i < anArray.length; i++)
anArray[i] = 0;
}
...
}

EXAMPLES (OF

ARRAY ARGUMENTS):

char[] c = new char[10];


int[] a = new int[10];
int[] b = new int[20];
<Some code to fill the arrays goes here.>
AClass.listChars(c);
AClass.zeroAll(a);
AClass.zeroAll(b);

Note that a
rra
different le ys a and b have
ngths. Also
note that n
square bra
o
cke
arguments ts are used with arra
y
.

length of array
arguments

5640_ch06.fm Page 322 Friday, November 14, 2003 6:18 AM

Chapter 6 Arrays

322

Self-Test Exercises
7. Consider the following class definition:
public class SomeClass
{
public static void doSomething(int n)
{
<Some code goes in here.>
}
<The rest of the definition is irrelevant to this question.>

Which of the following are acceptable method calls?


int[] a = {4, 5, 6};
int number = 2;
SomeClass.doSomething(number);
SomeClass.doSomething(a[2]);
SomeClass.doSomething(a[3]);
SomeClass.doSomething(a[number]);
SomeClass.doSomething(a);

8. Write a method definition for a static void method called oneMore, which has a formal
parameter for an array of integers and increases the value of each array element by one.
(The definition will go in some class, but you need only give the method definition.)
9. Write a method named outOfOrder that takes as a parameter an array of double and
returns a value of type int. This method will test the array for being out of order, meaning
that the array violates the condition:
a[0] <= a[1] <= a[2] <= ...

The method returns -1 if the elements are not out of order; otherwise, it returns the index
of the first element of the array that is out of order. For example, consider the declaration
double[] a = {1.2, 2.1, 3.3, 2.5, 4.5,
7.9, 5.4, 8.7, 9.9, 1.0};

In the array above, a[2] and a[3] are the first pair out of order, and a[3] is the first
element out of order, so the method returns 3. If the array were sorted, the method would
return 1.
10. What is wrong with the following method definition? It will compile but does not work as
you might hope.
public static void doubleSize(int[] a)
{
a = new int[a.length * 2];
}

5640_ch06.fm Page 323 Friday, November 14, 2003 6:18 AM

Arrays and References

323

Pitfall

USE

OF = AND == WITH

ARRAYS

Array types are reference types; that is, an array variable contains the memory address of the
array it names. The assignment operator copies this memory address. For example, consider the
following code:

assignment
with arrays

double[] a = new double[10];


double[] b = new double[10];
int i;
for (i = 0; i < a.length; i++)
a[i] = i;
b = a;
System.out.println("a[2] = " + a[2] + " b[2] = " + b[2]);
a[2] = 42;
System.out.println("a[2] = " + a[2] + " b[2] = " + b[2]);

This will produce the following output:


a[2] = 2.0 b[2] = 2.0
a[2] = 42.0 b[2] = 42.0

The assignment statement b = a; copies the memory address from a to b so that the array variable b contains the same memory address as the array variable a. After the assignment statement,
a and b are two different names for the same array. Thus, when we change the value of a[2], we
are also changing the value of b[2].
Unless you want two array variables to be two names for the same array (and on rare occasions
you do want this), you should not use the assignment operator with arrays. If you want the arrays
a and b in the preceding code to be different arrays with the same values in each index position,
then instead of the assignment statement
b = a;

you need to use something like the following:


int i;
for (i = 0; (i < a.length) && (i < b.length); i++)
b[i] = a[i];

Note that the above code will not make b an exact copy of a, unless a and b have the same length.
The equality operator == does not test two arrays to see if they contain the same values. It tests
two arrays to see if they are stored in the same location in the computers memory. For example,
consider the following code:
int[] c = new int[10];
int[] d = new int[10];

==

with arrays

5640_ch06.fm Page 324 Friday, November 14, 2003 6:18 AM

324

Chapter 6 Arrays

int i;
for (i =
c[i]
for (i =
d[i]

0; i < c.length; i++)


= i;
0; i < d.length; i++)
= i;

if (c == d)
System.out.println("c and d are equal by ==.");
else
System.out.println("c and d are not equal by ==.");

This produces the output


c and d are not equal by ==

even though c and d contain the same integers in the same indexed variables. A comparison
using == will say they are not equal because == only checks the contents of the array variables c
and d, which are memory addresses, and c and d contain different memory addresses.
If you want to test two arrays to see if they contain the same elements, then you can define an
equalArrays method for the arrays, just as you defined an equals method for a class. Display
6.3 contains one possible definition of equalArrays for arrays in a small demonstration class.

Display 6.3 Testing Arrays for Equality (Part 1 of 2)


1
2
3
4
5
6
7
8
9

public class DifferentEquals


{
/**
A demonstration to see how == and an equalArrays method are different.
*/
public static void main(String[] args)
{
int[] c = new int[10];
int[] d = new int[10];

10
11
12

int i;
for (i = 0; i < c.length; i++)
c[i] = i;

13
14

for (i = 0; i < d.length; i++)


d[i] = i;

The arrays
ca
same integ nd d contain the
ers in each
index
position.

5640_ch06.fm Page 325 Friday, November 14, 2003 6:18 AM

Arrays and References

Display 6.3 Testing Arrays for Equality (Part 2 of 2)


15
16
17
18

if (c == d)
System.out.println("c and d are equal by ==.");
else
System.out.println("c and d are not equal by ==.");

19

System.out.println("== only tests memory addresses.");

20
21
22
23
24
25

if (equalArrays(c, d))
System.out.println(
"c and d are equal by the equalArrays method.");
else
System.out.println(
"c and d are not equal by the equalArrays method.");

26
27

System.out.println(
"An equalArrays method is usually a more useful test.");

28

29
30
31
32
33
34
35
36
37
38
39
40
41
42

public static boolean equalArrays(int[] a, int[] b)


{
if (a.length != b.length)
return false;
else
{
int i = 0;
while (i < a.length)
{
if (a[i] != b[i])
return false;
i++;
}
}

43
44
45

return true;
}
}

SAMPLE DIALOGUE
c and d are not equal by ==.
== only tests memory addresses.
c and d are equal by the equalArrays method.
An equalArrays method is usually a more useful test.

325

5640_ch06.fm Page 326 Friday, November 14, 2003 6:18 AM

326

Chapter 6 Arrays

ARGUMENTS FOR THE METHOD main


The heading for the main method of a program looks as if it has a parameter for an
array of base type of String:
public static void main(String[] args)

The identifier args is in fact a parameter of type String[]. Since args is a parameter, it
could be replaced by any other non-keyword identifier. The identifier args is traditional, but it is perfectly legal to use some other identifier.
We have never given main an array argument, or any other kind of argument, when
we ran any of our programs. So, what did Java use as an argument to plug in for args?
If no argument is given when you run your program, then a default empty array of
strings is automatically provided as a default argument to main when you run your
program.
It is possible to run a Java program in a way that provides an argument to plug in for
this array of String parameters. You do not provide it as an array. You provide any
number of string arguments when you run the program, and those string arguments
will automatically be made elements of the array argument that is plugged in for args
(or whatever name you use for the parameter to main). This is normally done by running the program from the command line of the operating system, like so:
java YourProgram Do Be Do

This will set args[0] to "Do", args[1] to "Be", args[2] to "Do", and args.length
to 3. These three indexed variables can be used in the method main, as in the following
sample program:
public class YourProgram
{
public static void main(String[] args)
{
System.out.println(args[1] + " " + args[0]
+ " " + args[1]);
}
}

If the above program is run from the command line as follows,


java YourProgram Do Be Do

the output produced by the program will be


Be Do Be

Be sure to note that the argument to main is an array of strings. If you want numbers,
you must convert the string representations of the numbers to values of a number type
or types.

5640_ch06.fm Page 327 Friday, November 14, 2003 6:18 AM

Arrays and References

THE METHOD main HAS

AN

327

ARRAY PARAMETER

The heading for the main method of a program is as follows:


public static void main(String[] args)

The identifier args is a parameter for an array of base type String. The details are explained in
the text.

METHODS THAT RETURN AN ARRAY


In Java, a method may return an array. You specify the return type for a method that
returns an array in the same way that you specify a type for an array parameter. For
example, the following is an example of a method that returns an array:
public static char[] upperCaseVersion(char[] a)
{
char[] temp = new char[a.length];
char i;
for (i = 0; i < a.length; i++)
temp[i] = Character.toUpperCase(a[i]);
return temp;
}

Self-Test Exercises
11. Give the definition of a method called halfArray that has a single parameter for an array
of base type double and that returns another array of base type double that has the same
length and in which each element has been divided by 2.0. Make it a static method. To
test it, you can add it to any class or, better yet, write a class with a test program in the
method main.
12. What is wrong with the following method definition? It is an alternate definition of the
method by the same name defined in the previous subsection. It will compile.
public static char[] upperCaseVersion(char[] a)
{
char i;
for (i = 0; i < a.length; i++)
a[i] = Character.toUpperCase(a[i]);
return a;
}

5640_ch06.fm Page 328 Friday, November 14, 2003 6:18 AM

328

Chapter 6 Arrays

RETURNING

AN

ARRAY

A method can return an array. The details are basically the same as for a method that returns an
object of a class type.

SYNTAX (FOR

A TYPICAL WAY OF RETURNING AN ARRAY):

public static Base_Type[] Method_Name(Parameter_List)


{
Base_Type[] temp = new Base_Type[Array_Size]
<Some code to fill temp goes here.>
return temp;
}

The method need not be static and need not be public. You do not necessarily need to use a local
array variable like temp.

EXAMPLE (ASSUMED

TO BE IN A CLASS DEFINITION):

public static int[] incrementedArray(int[] a, int increment)


{
int[] temp = new int[a.length];
int i;
for (i = 0; i < a.length; i++)
temp[i] = a[i] + increment;
return temp;
}

ARRAY TYPE NAMES


Whenever you need an array type name, whether for the type of an array variable declaration, the
type of an array parameter, or the type for a method that returns an array, you specify the type
name in the same way.

SYNTAX:
Base_Type[]

EXAMPLES:
double[] a = new double[10];
int[] giveIntArray(char[] arrayParameter)
{ ... }

5640_ch06.fm Page 329 Friday, November 14, 2003 6:18 AM

Programming with Arrays

6.3

329

Programming with Arrays


Never trust to general impressions, my boy
but concentrate yourself upon details.
Sir Arthur Conan Doyle,
A Case of Identity (Sherlock Holmes)

In this section we discuss partially filled arrays and discuss how to use arrays as class
instance variables.

PARTIALLY FILLED ARRAYS


Often the exact size needed for an array is not known when a program is written or the
size may vary from one run of the program to another. One common and easy way to
handle this situation is to declare the array to be of the largest size the program could possibly need. The program is then free to use as much or as little of the array as is needed.
Partially filled arrays require some care. The program must keep track of how much
of the array is used and must not reference any indexed variable that has not been given
a meaningful value. The program in Display 6.4 illustrates this point. The program
reads in a list of golf scores and shows how much each score differs from the average.
This program will work for lists as short as 1 score, as long as 10 scores, and of any
length in between. The scores are stored in the array score, which has 10 indexed variables,

partially filled
array

Display 6.4 Partially Filled Array (Part 1 of 4)


Contrary to normal practice, this allows fractional scores, like
71.5. However, this makes it a better example for our purposes.
(Anyway, when I play golf, losing a ball is only half a stroke
penalty. Try it sometime.)

1
2
3

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

4
5
6

public class GolfScores


{
public static final int MAX_NUMBER_SCORES = 10;

7
8
9
10
11
12
13
14
15

/**
Shows differences
*/
public static void
{
double[] score
int numberUsed

between each of a list of golf scores and their average.


main(String[] args) throws IOException
= new double[MAX_NUMBER_SCORES];
= 0;

System.out.println("This program reads golf scores and shows");


System.out.println("how much each differs from the average.");

5640_ch06.fm Page 330 Friday, November 14, 2003 6:18 AM

Chapter 6 Arrays

330

Display 6.4 Partially Filled Array (Part 2 of 4)


16
17
18
19

System.out.println("Enter golf scores:");


numberUsed = fillArray(score);
showDifference(score, numberUsed);
}

20
21
22
23
24
25
26
27
28
29

/**
Reads values into the array a. Returns the number of values placed in the array a.
*/
public static int fillArray(double[] a) throws IOException
{
System.out.println("Enter up to " + a.length
+ " nonnegative numbers, one per line.");
System.out.println("Mark the end of the list with a negative number.");
BufferedReader keyboard =
new BufferedReader(new InputStreamReader(System.in));

30
31
32
33
34
35
36
37
38
39
40

double next;
int index = 0;
next = stringToDouble(keyboard.readLine( ));
while ((next >= 0) && (index < a.length))
{
a[index] = next;
index++;
next = stringToDouble(keyboard.readLine( ));
//index is the number of array indexed variables used so far.
}
//index is the total number of array indexed variables used.

41
42
43

if (next >= 0)
System.out.println("Could only read in "
+ a.length + " input values.");

44
45

return index;

46
47
48
49
50

/**
Precondition: numberUsed <= a.length.
a[0] through a[numberUsed-1] have values.
Returns the average of numbers a[0] through a[numberUsed-1].
*/

The value of index is the number of


values stored in the array.

5640_ch06.fm Page 331 Friday, November 14, 2003 6:18 AM

Programming with Arrays

331

Display 6.4 Partially Filled Array (Part 3 of 4)


51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

public static double computeAverage(double[] a, int numberUsed)


{
double total = 0;
for (int index = 0; index < numberUsed; index++)
total = total + a[index];
if (numberUsed > 0)
{
return (total/numberUsed);
}
else
{
System.out.println("ERROR: Trying to average 0 numbers.");
System.out.println("computeAverage returns 0.");
return 0;
}
}

67
68
69
70

private static double stringToDouble(String stringObject)


{
return Double.parseDouble(stringObject.trim());
}

71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

/**
Precondition: numberUsed <= a.length.
The first numberUsed indexed variables of a have values.
Postcondition: Gives screen output showing how much each of the first
numberUsed elements of the array a differ from their average.
*/
public static void showDifference(double[] a, int numberUsed)
{
double average = computeAverage(a, numberUsed);
System.out.println("Average of the " + numberUsed
+ " scores = " + average);
System.out.println("The scores are:");
for (int index = 0; index < numberUsed; index++)
System.out.println(a[index] + " differs from average by "
+ (a[index] average));
}
}

5640_ch06.fm Page 332 Friday, November 14, 2003 6:18 AM

332

Chapter 6 Arrays

Display 6.4 Partially Filled Array (Part 4 of 4)


SAMPLE DIALOGUE
This program reads golf scores and shows
how much each differs from the average.
Enter golf scores:
Enter up to 10 nonnegative numbers, one per line.
Mark the end of the list with a negative number.
69
74
68
-1
Average of the 3 scores = 70.3333
The scores are:
69.0 differs from average by 1.33333
74.0 differs from average by 3.66667
68.0 differs from average by 2.33333

but the program uses only as much of the array as it needs. The variable numberUsed
keeps track of how many elements are stored in the array. The elements (that is, the
scores) are stored in positions score[0] through score[numberUsed 1]. The details
are very similar to what they would be if numberUsed were score.length and the entire
array were used. Note that the variable numberUsed usually must be an argument to any
method that manipulates the partially filled array. For example, the methods showDifference and computeAverage use the argument numberUsed to ensure that only meaningful array indices are used.
Self-Test Exercises
13. Complete the definition of the following method that could be added to the class GolfScores in Display 6.4:
/**
Precondition: numberUsed <= argumentArray.length;
the first numberUsed indexed variables of argumentArray
have values.
Returns an array of length numberUsed whose ith element
is argumentArray[i] - adjustment.
*/
public static double[] differenceArray(
double[] argumentArray, int numberUsed, double adjustment)

14. Rewrite the class GolfScores from Display 6.4 using the method differenceArray
from exercise 13.

5640_ch06.fm Page 333 Friday, November 14, 2003 6:18 AM

Programming with Arrays

333

15. Rewrite the class GolfScores from Display 6.4 making the array of scores a static variable.
Also, make the int variable numberUsed a static variable. Start with Display 6.4, not with the
answer to exercise 14. Hint: All, or at least most, methods will have no parameters.

Example

A CLASS

FOR

PARTIALLY FILLED ARRAYS

If you are going to use some array in a disciplined way, such as using the array as a partially filled
array, then it is often best to create a class that has the array as an instance variable and to have
the constructors and methods of the class provide the needed operations as methods. For example, in Display 6.5 we have written a class for a partially filled array of doubles. In Display 6.6 we
have rewritten the program in Display 6.4 using this class.
In Display 6.6 we have written the code to be exactly analogous to that of Display 6.4 so that you
could see how one program mirrors the other. However, this resulted in occasionally recomputing
a value several times. For example, the method computeAverage has the following expression
three times:
a.getNumberOfElements()

Since the PartiallyFilledArray a is not changed in this method, these each return the same
value. Some programmers advocate computing this value only once and saving the value in a
variable. These programmers would use something like the following for the definition of computeAverage rather than what we used in Display 6.6. The variable numberOfElementsIna is
used to save a value so it need not be recomputed.
public static double computeAverage(PartiallyFilledArray a)
{
double total = 0;
double numberOfElementsIna = a.getNumberOfElements( );
for (int index = 0; index < numberOfElementsIna; index++)
total = total + a.getElement(index);
if (numberOfElementsIna > 0)
{
return (total/numberOfElementsIna);
}
else
{
System.out.println(
"ERROR: Trying to average 0 numbers.");
System.out.println("computeAverage returns 0.");
return 0;
}
}

alternative coding

5640_ch06.fm Page 334 Friday, November 14, 2003 6:18 AM

334

Chapter 6 Arrays

This is not likely to produce a noticeable difference in the efficiency of the program in Display 6.6,
but if the number of elements in the PartiallyFilledArray were large so that the for loop
would be executed many times, it might make a difference in a situation where efficiency is critical.

Display 6.5 Partially Filled Array Class (Part 1 of 4)


1
2
3
4
5
6
7
8
9
10

/**
Class for a partially filled array of doubles. The class enforces the
following invariant: All elements are at the beginning of the array in
locations 0, 1, 2, and so forth up to a highest index with no gaps.
*/
public class PartiallyFilledArray
{
private int maxNumberElements; //Same as a.length
private double[] a;
private int numberUsed; //Number of indices currently in use

11
12
13
14
15
16
17
18
19

/**
Sets the maximum number of allowable elements to 10.
*/
PartiallyFilledArray()
{
maxNumberElements = 10;
a = new double[maxNumberElements];
numberUsed = 0;
}

20
21
22
23
24
25
26
27
28
29
30
31
32
33

/**
Precondition arraySize > 0.
*/
PartiallyFilledArray(int arraySize)
{
if (arraySize <= 0)
{
System.out.println("Error Array size zero or negative.");
System.exit(0);
}
maxNumberElements = arraySize;
a = new double[maxNumberElements];
numberUsed = 0;
}

5640_ch06.fm Page 335 Monday, November 24, 2003 6:08 PM

Programming with Arrays

Display 6.5 Partially Filled Array Class (Part 2 of 4)


34
35
36
37
38
39
40
41
42
43
44
45
46
47

PartiallyFilledArray(PartiallyFilledArray original)
{
if (original == null)
{
System.out.println("Fatal Error: aborting program.");
System.exit(0);
Note that the instance variable a is
}
a copy of orignal.a. The
maxNumberElements =
following
would not be correct:
original.maxNumberElements;
a
=
original.a;
numberUsed = original.numberUsed;
This point is discussed in the
a = new double[maxNumberElements];
subsection entitled Privacy Leaks
for (int i = 0; i < numberUsed; i++)
with Array Instance Variables.
a[i] = original.a[i];
}

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63

/**
Adds newElement to the first unused array position.
*/
public void add(double newElement)
{
if (numberUsed >= a.length)
{
System.out.println("Error: Adding to a full array.");
System.exit(0);
}
else
{
a[numberUsed] = newElement;
numberUsed++;
}
}

64
65
66
67
68
69
70

public double getElement(int index)


{
if (index < 0 || index >= numberUsed)
{
System.out.println("Error:Illegal or unused index.");
System.exit(0);
}

71
72

return a[index];

335

5640_ch06.fm Page 336 Friday, November 14, 2003 6:18 AM

336

Chapter 6 Arrays

Display 6.5 Partially Filled Array Class (Part 3 of 4)


73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91

/**
index must be an index in use or the first unused index.
*/
public void resetElement(int index, double newValue)
{
if (index < 0 || index >= maxNumberElements)
{
System.out.println("Error:Illegal index.");
System.exit(0);
}
else if (index > numberUsed)
{
System.out.println(
"Error: Changing an index that is too large.");
System.exit(0);
}
else
a[index] = newValue;
}

92
93
94
95
96
97
98
99
100
101

public void deleteLast()


{
if (empty())
{
System.out.println("Error:Deleting from an empty array.");
System.exit(0);
}
else
numberUsed;
}

102
103
104
105
106
107
108
109
110
111
112

/**
Deletes the element in position index. Moves down all elements with
indices higher than the deleted element.
*/
public void delete(int index)
{
if (index < 0 || index >= numberUsed)
{
System.out.println("Error:Illegal or unused index.");
System.exit(0);
}

113
114
115
116

for (int i = index; i < numberUsed; i++)


a[i] = a[i + 1];
numberUsed;
}

5640_ch06.fm Page 337 Friday, November 14, 2003 6:18 AM

Programming with Arrays

337

Display 6.5 Partially Filled Array Class (Part 4 of 4)


117
118
119
120

public boolean empty()


{
return (numberUsed == 0);
}

121
122
123
124

public boolean full()


{
return (numberUsed == maxNumberElements);
}

125
126
127
128
129
130
131
132
133
134

public int getMaxCapacity()


{
return maxNumberElements;
}
public int getNumberOfElements()
{
return numberUsed;
}
}

Display 6.6 Display 6.4 Redone Using the Class PartiallyFilledArray (Part 1 of 3)
1
2
3

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

4
5
6
7
8

/**
Demonstrates Using the class PartiallyFilledArray,
*/
public class GolfScoresVersion2
{

public static final int MAX_NUMBER_SCORES = 10;

10
11
12
13
14
15
16

Sample dialog is the same as in Display 6.4.

/**
Shows the differences between each of a list of golf scores and their average.
*/
public static void main(String[] args) throws IOException
{
PartiallyFilledArray score =
new PartiallyFilledArray(MAX_NUMBER_SCORES);

5640_ch06.fm Page 338 Friday, November 14, 2003 6:18 AM

338

Chapter 6 Arrays

Display 6.6 Display 6.4 Redone Using the Class PartiallyFilledArray (Part 2 of 3)
17
18

System.out.println("This program reads golf scores and shows");


System.out.println("how much each differs from the average.");

19
20
21
22

System.out.println("Enter golf scores:");


fillArray(score);
showDifference(score);
}

23
24
25
26
27
28
29
30
31
32

/**
Reads values into the PartiallyFilledArray a.
*/
public static void fillArray(PartiallyFilledArray a) throws IOException
{
System.out.println("Enter up to " + a.getMaxCapacity( )
+ " nonnegative numbers, one per line.");
System.out.println("Mark the end of the list with a negative number");
BufferedReader keyboard = new BufferedReader(
new InputStreamReader(System.in));

33
34
35
36
37
38

double next = stringToDouble(keyboard.readLine( ));


while ((next >= 0) && (!a.full()))
{
a.add(next);
next = stringToDouble(keyboard.readLine( ));
}

39
40
41
42

if (next >= 0)
System.out.println("Could only read in "
+ a.getMaxCapacity( ) + " input values.");
}

43
44
45
46

private static double stringToDouble(String stringObject)


{
return Double.parseDouble(stringObject.trim());
}

47
48
49
50
51
52
53
54

/**
Returns the average of numbers in the PartiallyFilledArray a.
*/
public static double computeAverage(PartiallyFilledArray a)
{
double total = 0;
for (int index = 0; index < a.getNumberOfElements( ); index++)
total = total + a.getElement(index);

5640_ch06.fm Page 339 Friday, November 14, 2003 6:18 AM

Programming with Arrays

339

Display 6.6 Display 6.4 Redone Using the Class PartiallyFilledArray (Part 3 of 3)
55
56
57
58
59
60
61
62
63
64
65

66
67
68
69
70
71
72
73
74
75
76
77
78
79

/**
Gives screen output showing how much each of the
elements in the PartiallyFilledArray a differ from the average.
*/
public static void showDifference(PartiallyFilledArray a)
{
double average = computeAverage(a);
System.out.println("Average of the " + a.getNumberOfElements( )
+ " scores = " + average);
System.out.println("The scores are:");
for (int index = 0; index < a.getNumberOfElements( ); index++)
System.out.println(a.getElement(index) + " differs from average by "
+ (a.getElement(index) average));
}

80

if (a.getNumberOfElements() > 0)
{
return (total/a.getNumberOfElements());
}
else
{
System.out.println("ERROR: Trying to average 0 numbers.");
System.out.println("computeAverage returns 0.");
return 0;
}

Tip

ACCESSOR METHODS NEED NOT SIMPLY RETURN INSTANCE VARIABLES


Note that in the class PartiallyFilledArray in Display 6.5, there is no accessor method that
returns a copy of the entire instance variable a. The reason that was not done is that, when the
class is used as intended, a user of the class PartiallyFilledArray would have no need for
the entire array a. That is an implementation detail. The other methods that start with get allow a
programmer using the class to obtain all the data that he or she needs.

5640_ch06.fm Page 340 Friday, November 14, 2003 6:18 AM

340

Chapter 6 Arrays

PRIVACY LEAKS WITH ARRAY INSTANCE VARIABLES


In Chapter 5 we explained why it is a compromise of privacy for a class to have an accessor (or other method) that returns a reference to a private mutable object. As we noted
there, an accessor method should instead return a reference to a deep copy of the private
object. (See the Pitfall subsection of Chapter 5 entitled Privacy Leaks.) At the time we
had in mind returning the contents of a private instance variable of a class type. However, the lesson applies equally well to private instance variables of an array type.
For example, suppose that, despite what we said in the previous Programming Tip,
you decide that you want an accessor method for the array instance variable in the class
PartiallyFilledArray in Display 6.5. You might be tempted to define the accessor
method as follows:
public double[] getInsideArray()// Problematic version
{
return a;
}

As indicated in the comment, this definition has a problem. The problem is that this
accessor method allows a programmer to change the array object named by the private
instance variable a in ways that bypass the checks built into the mutator methods of the
class PartiallyFilledArray. To see why this is true suppose we had added this definition
of the method getInsideArray to the class PartiallyFilledArray, and consider the following code:
PartiallyFilledArray leakyArray =
new PartiallyFilledArray(10);
double[] arrayName = leakyArray.getInsideArray( );

The variable arrayName and the private instance variable a now contain the same reference, so both arrayName and the private instance variable a name the same array. Using
arrayName as a name for the array named by the private instance variable a, we can now
fill the indexed variables of a in any order and need not fill the array starting at the first
element. This violates the spirit of the private modifier for the array instance variable
a. For this reason, the accessor method getInsideArray should return a deep copy of
the array named by the private instance variable a. A safe definition of getInsideArray
is the following:
public double[] getInsideArray()// Good version
{
//Recall that maxNumberElements == a.length.
double[] temp = new double[maxNumberElements];
for (int i = 0; i < maxNumberElements; i++)
temp[i] = a[i];
return temp;
}

5640_ch06.fm Page 341 Friday, November 14, 2003 6:18 AM

Programming with Arrays

341

If a private instance variable is an array type that has a class as its base type, then you
need to be sure to make copies of the class objects in the array when you make a copy
of the array. This is illustrated by the toy class in Display 6.7.
Display 6.7 also includes a copy constructor. As illustrated in that display, the copy
constructor should make a completely independent copy of the array instance variable
(that is, a deep copy) in the same way that the accessor method does. This same point is
also illustrated by the copy constructor in Display 6.5.
Display 6.7 Accessor Method for an Array Instance Variable
1
2
3
4
5
6
7

/**
Demonstrates the correct way to define an accessor
method to a private array of class objects.
*/
The class Date is defined in Display 4.11, but you
public class ToyExample
do not need to know the details of the definition
{
to understand the point of this example.
private Date[] a;

8
9
10
11
12
13

public ToyExample(int arraySize)


{
a = new Date[arraySize];
for (int i = 0; i < arraySize; i++)
a[i] = new Date();
}

14
15
16
17
18
19
20

public ToyExample(ToyExample object)


{
int lengthOfArrays = object.a.length;
this.a = new Date[lengthOfArrays];
for (int i = 0; i < lengthOfArrays; i++)
this.a[i] = new Date(object.a[i]);
}

21
22
23
24
25
26
27

public Date[] getDateArray()


{
Date[] temp = new Date[a.length];
for (int i = 0; i < a.length; i++)
temp[i] = new Date(a[i]);
return temp;
}

Copy constructor for ToyExample

Copy constructor for Date

Accessor method

Copy constructor for Date

<There presumably are other methods that are not shown,

but they are irrelevant to the point at hand.>


28

5640_ch06.fm Page 342 Friday, November 14, 2003 6:18 AM

342

Chapter 6 Arrays

A PREVIEW OF VECTORS
Java and many other programming languages have objects known as vectors, which are
very much like objects of our class PartiallyFilledArray in Display 6.5. However,
even after you learn about vectors, there will still be situations where the class PartiallyFilledArray is preferable to vectors. We will discuss vectors in Chapter 15.

Self-Test Exercises
16. Define a method named removeAll that can be added to the class PartialyFilledArray. The method removeAll has no parameters. When invoked the method removeAll
deletes all the elements in its calling object.
17. Define a method named increaseCapacity that can be added to the class PartiallyFilledArray in Display 6.5. The method has one int parameter named newCapacity
that increases the capacity of the PartialyFilledArray so that it can hold up to newCapacity numbers. If newCapacity is less than or equal to maxNumberOfElements, then
the method does nothing. If newCapacity is greater than maxNumberOfElements, then
maxNumberElements is set equal to newCapacity and a new array of length newCapacity is created for the array instance variable a. The old values of the array instance variable
are copied to the newly created array.

Example

SORTING

AN

ARRAY

In this example we define a method called sort that will sort a partially filled array of numbers so
that they are ordered from smallest to largest.
The procedure sort has one array parameter a. The array a will be partially filled, so there is an
additional formal parameter called numberUsed, which tells how many array positions are used.
Thus, the heading for the method sort will be
public static void sort(double[] a, int numberUsed)

The method sort rearranges the elements in array a so that after the method call is completed,
the elements are sorted as follows:
a[0] a[1] a[2] ... a[numberUsed 1]

selection sort

The algorithm we use to do the sorting is called selection sort. It is one of the easiest of the sorting algorithms to understand.

5640_ch06.fm Page 343 Friday, November 14, 2003 6:18 AM

Programming with Arrays

343

One way to design an algorithm is to rely on the definition of the problem. In this case the problem is to sort an array a from smallest to largest. That means rearranging the values so that a[0]
is the smallest, a[1] the next smallest, and so forth. That definition yields an outline for the
selection sort algorithm:
for (int index = 0; index < numberUsed; index++)
Place the indexth smallest element in a[index]

There are many ways to realize this general approach. The details could be developed by using
two arrays and copying the elements from one array to the other in sorted order, but using one
array should be both adequate and economical. Therefore, the method sort uses only the one
array containing the values to be sorted. The method sort rearranges the values in the array a by
interchanging pairs of values. Let us go through a concrete example so that you can see how the
algorithm works.
Consider the array shown in Display 6.8. The selection sort algorithm will place the smallest value
in a[0]. The smallest value is the value in a[4]. So, the algorithm interchanges the values of
a[0] and a[4]. The algorithm then looks for the next smallest element. The value in a[0] is now
the smallest element, so the next smallest element is the smallest of the remaining elements a[1],
a[2], a[3],..., a[9]. In the example in Display 6.8 the next smallest element is in a[6], so the
algorithm interchanges the values of a[1] and a[6]. This positioning of the second smallest element is illustrated in the fourth and fifth array pictures in Display 6.8. The algorithm then positions the third smallest element, and so forth. As the sorting proceeds, the beginning array
elements are set equal to the correct sorted values. The sorted portion of the array grows by adding elements one after the other from the elements in the unsorted end of the array. Notice that
the algorithm need not do anything with the value in the last indexed variable, a[9], because
once the other elements are positioned correctly, a[9] must also have the correct value. After all,
the correct value for a[9] is the smallest value left to be moved, and the only value left to be
moved is the value that is already in a[9].
The definition of the method sort, included in a class, is given in Display 6.9. sort uses the
method indexOfSmallest to find the index of the smallest element in the unsorted end of the
array, then it does an interchange to move this next smallest element down into the sorted part of
the array.
The method interchange, shown in Display 6.9, is used to interchange the values of indexed
variables. For example, the following call will interchange the values of a[0] and a[4]:
interchange(0, 4, a);

A sample use of the sort method is given in Display 6.10.

indexOfSmallest

5640_ch06.fm Page 344 Friday, November 14, 2003 6:18 AM

Chapter 6 Arrays

344

Display 6.8 Selection Sort


Unsorted array
a[0]

a[1]

a[2]

a[3]

a[4]

a[5]

a[6]

a[7]

a[8]

a[9]

11

17

15

19

28

12

11

17

15

19

28

12

11

17

15

19

28

12

11

17

15

19

28

12

11

17

15

19

28

12

11

12

15

17

19

28

.
.
.
3

Self-Test Exercises
18. How would you need to change the method sort in Display 6.9 so that it can sort an array
of values of type double into decreasing order, instead of increasing order?
19. If an array of int values has a value that occurs twice (like b[0] == 42 and b[7] == 42)
and you sort the array using the method SelectionSort.sort, will there be one or two
copies of the repeated value after the array is sorted?

5640_ch06.fm Page 345 Friday, November 14, 2003 6:18 AM

Programming with Arrays

345

Display 6.9 Selection Sort Class (Part 1 of 2)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

public class SelectionSort


{
/**
Precondition: numberUsed <= a.length;
The first numberUsed indexed variables have values.
Action: Sorts a so that a[0] <= a[1] <= ... <= a[numberUsed - 1].
*/
public static void sort(double[] a, int numberUsed)
{
int index, indexOfNextSmallest;
for (index = 0; index < numberUsed 1; index++)
{//Place the correct value in a[index]:
indexOfNextSmallest = indexOfSmallest(index, a, numberUsed);
interchange(index,indexOfNextSmallest, a);
//a[0] <= a[1] <=...<= a[index] and these are the smallest
//of the original array elements. The remaining positions
//contain the rest of the original array elements.
}
}
/**
Returns the index of the smallest value among
a[startIndex], a[startIndex+1], ... a[numberUsed - 1]
*/
private static int indexOfSmallest(int startIndex,
double[] a, int numberUsed)
{
double min = a[startIndex];
int indexOfMin = startIndex;
int index;
for (index = startIndex + 1; index < numberUsed; index++)
if (a[index] < min)
{
min = a[index];
indexOfMin = index;
//min is smallest of a[startIndex] through a[index]
}
return indexOfMin;
}

5640_ch06.fm Page 346 Friday, November 14, 2003 6:18 AM

346

Chapter 6 Arrays

Display 6.9 Selection Sort Class (Part 2 of 2)


/**
Precondition: i and j are legal indices for the array a.
Postcondition: Values of a[i] and a[j] have been interchanged.
*/
private static void interchange(int i, int j, double[] a)
{
double temp;
temp = a[i];
a[i] = a[j];
a[j] = temp; //original value of a[i]
}
}

6.4

Multidimensional Arrays
Two indices are better than one.
Anonymous

Java allows you to declare arrays with more than one index. In this section we describe
these multidimensional arrays.

MULTIDIMENSIONAL ARRAY BASICS


array declarations
indexed variables

It is sometimes useful to have an array with more than one index, and this is allowed in
Java. The following creates an array of characters called page. The array page has two
indices: the first index ranging from 0 to 29 and the second from 0 to 99.
char[][] page = new char[30][100];

This is equivalent to the following two steps:


char[][] page;
page = new char[30][100];

The indexed variables for this array each have two indices. For example, page[0][0],
page[15][32], and page[29][99] are three of the indexed variables for this array. Note
that each index must be enclosed in its own set of square brackets. As was true of the
one-dimensional arrays we have already seen, each indexed variable for a multidimensional array is a variable of the base type, in this case the type char.

5640_ch06.fm Page 347 Friday, November 14, 2003 6:18 AM

Multidimensional Arrays

347

Display 6.10 Demonstration of the SelectionSort Class


1
2
3
4
5

public class SelectionSortDemo


{
public static void main(String[] args)
{
double[] b = {7.7, 5.5, 11, 3, 16, 4.4, 20, 14, 13, 42};

6
7
8
9
10
11
12

System.out.println("Array contents before sorting:");


int i;
for (i = 0; i < b.length; i++)
System.out.print(b[i] + " ");
System.out.println();

13
14
15
16
17
18

System.out.println("Sorted array values:");


for (i = 0; i < b.length; i++)
System.out.print(b[i] + " ");
System.out.println();

SelectionSort.sort(b, b.length);

}
}

SAMPLE DIALOGUE
Array contents before sorting:
7.7 5.5 11.0 3.0 16.0 4.4 20.0 14.0 13.0 42.0
Sorted array values:
3.0 4.4 5.5 7.7 11.0 13.0 14.0 16.0 20.0 42.0

An array may have any number of indices, but perhaps the most common number
of indices is two. A two-dimensional array can be visualized as a two-dimensional display with the first index giving the row and the second index giving the column. For
example, the array indexed variables of the two-dimensional array a declared and created as
char[][] a = new char[5][12];

can be visualized as follows:


a[0][0],
a[1][0],
a[2][0],
a[3][0],
a[4][0],

a[0][1],
a[1][1],
a[2][1],
a[3][1],
a[4][1],

a[0][2],
a[1][2],
a[2][2],
a[3][2],
a[4][2],

...,
...,
...,
...,
...,

a[0][11]
a[1][11]
a[2][11]
a[3][11]
a[4][11]

5640_ch06.fm Page 348 Friday, November 14, 2003 6:18 AM

348

Chapter 6 Arrays

You might use the array a to store all the characters on a (very small) page of text that
has five lines (numbered 0 through 4) and 12 characters on each line (numbered 0
through 11).

DECLARING

AND

CREATING

MULTIDIMENSIONAL ARRAY

You declare a multidimensional array variable and create a multidimensional array object in
basically the same way that you create and name a one-dimensional array. You simply use as
many square brackets as there are indices.

SYNTAX:
Base_Type[]...[] Variable_Name = new Base_Type[Length_1]...[Length_n];

EXAMPLES:
char[][] a = new char[5][12];
char[][] page = new char[30][100];
double[][] table = new double[100][10];
int[][][] figure = new int[10][20][30];
Person[][] entry = new Person[10][10];
Person is a class.

A
multidimensional
array is an
array of arrays

In Java, a two-dimensional array, such as a, is actually an array of arrays. The above


array a is actually a one-dimensional array of size 5, whose base type is a one-dimensional
array of characters of size 12. This is diagrammed in Display 6.11. As shown in that display, the array variable a contains a reference to a one-dimensional array of length 5 and
with a base type of char[]; that is, the base type of a is the type for an entire onedimensional array of characters. Each indexed variable a[0], a[1], and so forth contains a reference to a one-dimensional array of characters.
A three-dimensional array is an array of arrays of arrays, and so forth for higher
dimensions.
Normally, the fact that a two-dimensional array is an array of arrays need not concern you, and you can usually act as if the array a is actually an array with two indices
(rather than an array of arrays, which is harder to keep track of ). There are, however,
some situations where a two-dimensional array looks very much like an array of arrays.
For example, you will see that when using the instance variable length, you must think
of a two-dimensional array as an array of arrays.

5640_ch06.fm Page 349 Friday, November 14, 2003 6:18 AM

Multidimensional Arrays

349

Display 6.11 Two-Dimensional Array as an Array of Arrays


char[][] a = new char[5][12];

Code that fills the array is not shown.


a

a[1][2]

Blank entries contain the


space (blank) character.
a[0]

10

11

a[1]
a

a[2]
t

a[3]

a[4]
a

We will see that these can and should


be replaced with expressions involving
the length instance variable.

int row, column;


for (row = 0; row < 5; row++)
{
for (column = 0; column < 12; column++)
System.out.print(a[row][column]);
System.out.println();
}

Produces the following output:


Once upon
a time
there were
three little
programmers.

5640_ch06.fm Page 350 Friday, November 14, 2003 6:18 AM

350

Chapter 6 Arrays

USING THE length INSTANCE VARIABLE


Suppose you want to fill all the elements in the following two-dimensional array with 'Z':
char[][] page = new char[30][100];

You can use a nested for loop such as the following:


int row, column;
for (row = 0; row < page.length; row++)
for (column = 0; column < page[row].length; column++)
page[row][column] = 'Z';

Lets analyze this nested for loop in a bit more detail. The array page is actually a
one-dimensional array of length 30, and each of the 30 indexed variables page[0]
through page[29] is a one-dimensional array with base type char and with a length
of 100. That is why the first for loop is terminated using page.length. For a twodimensional array like page, the value of length is the number of first indices or, equivalently, the number of rowsin this case, 30. Now lets consider the inside for loop.
The 0th row in the two-dimensional array page is the one-dimensional array page[0],
and it has page[0].length entries. More generally, page[row] is a one-dimensional array
of chars, and it has page[row].length entries. That is why the inner for loop is terminated
using page[row].length. Of course, in this case, page[0].length, page[1].length, and so
forth through to page[29].length are all equal and all equal to 100. (If you read the
optional section entitled Ragged Arrays, you will see that these need not all be equal.)

Self-Test Exercises
20. What is the output produced by the following code?
int[][] myArray = new int[4][4];
int index1, index2;
for (index1 = 0; index1 < myArray.length; index1++)
for (index2 = 0;
index2 < myArray[index1].length; index2++)
myArray[index1][index2] = index2;
for (index1 = 0; index1 < myArray.length; index1++)
{
for (index2 = 0;
index2 < myArray[index1].length; index2++)
System.out.print(myArray[index1][index2] + " ");
System.out.println();
}

5640_ch06.fm Page 351 Friday, November 14, 2003 6:18 AM

Multidimensional Arrays

351

21. Write code that will fill the array a (declared and created below) with numbers typed in at
the keyboard. The numbers will be input five per line, on four lines.
int[][] a = new int[4][5];

Hint: It will help to use the class StringTokenizer.


22. Write a method definition for a static void method called echo such that the following
method call will echo the input described in exercise 21, and will echo it in the same format
as we specified for the input (that is, four lines of five numbers per line):
Class_Name.echo(a);

RAGGED ARRAYS
There is no need for each row in a two-dimensional array to have the same number of
entries. Different rows can have different numbers of columns. These sorts of arrays are
called ragged arrays.
To help explain the details, lets start with an ordinary, nonragged two-dimensional
array, created as follows:
double[][] a = new double[3][5];

This is equivalent to the following:


double[][] a;
a = new double[3][];
a[0] = new double[5];
a[1] = new double[5];
a[2] = new double[5];

The line
a = new double[3][];

makes a the name of an array with room for 3 entries, each of which can be an array of
doubles that can be of any length. The next three lines each create an array of doubles
of length 5 to be named by a[0], a[1], and a[2]. The net result is a two-dimensional
array of base type double with three rows and five columns.
If you want, you can make each of a[0], a[1], and a[2] a different length. The following code makes a ragged array b in which each row has a different length:
double[][] b;
b = new double[3][];
b[0] = new double[5];
b[1] = new double[10];
b[2] = new double[4];

5640_ch06.fm Page 352 Friday, November 14, 2003 6:18 AM

Chapter 6 Arrays

352

There are situations in which you can profitably use ragged arrays, but most applications do not require them. However, if you understand ragged arrays, you will have a
better understanding of how all multidimensional arrays work in Java.

MULTIDIMENSIONAL ARRAY PARAMETERS AND RETURNED VALUES


array arguments

Methods may have multidimensional array parameters and may have a multidimensional array type as the type for the value returned. The situation is similar to that of
the one-dimensional case, except that you use more square brackets when specifying
the type name. For example, the following method will display a two-dimensional
array in the usual way as rows and columns:4
public static void showMatrix(int[][] a)
{
int row, column;
for (row = 0; row < a.length; row++)
{
for (column = 0; column < a[row].length; column++)
System.out.print(a[row][column] + " ");
System.out.println();
}
}

returning an array

If you want to return a multidimensional array, you use the same kind of type specification as you use for a multidimensional array parameter. For example, the following
method returns a two-dimensional array with base type double:
/**
Precondition: Each dimension of a is at least
the value of size.
The array returned is the same as the size-by-size
upper-left corner of the array a.
*/
public static double[][] corner(double[][] a, int size)
{
double[][] temp = new double[size][size];
int row, column;
for (row = 0; row < size; row++)
for (column = 0; column < size; column++)
temp[row][column] = a[row][column];
return temp;
}

It is worth noting that this method works fine for ragged arrays.

5640_ch06.fm Page 353 Friday, November 14, 2003 6:18 AM

Multidimensional Arrays

353

Example

A GRADE BOOK CLASS


Display 6.12 contains a class for grade records in a class whose only recorded scores are quiz
scores. An object of this class has three array instance variables. One is a two-dimensional array
named grade that records the grade of each student on each quiz. For example, the score that
student number 4 received on quiz number 1 is recorded in grade[3][0]. Since the student
numbers and quiz numbers start with 1 and the array indices start with 0, we subtract one from
the student number or quiz number to obtain the corresponding array index.
All the raw data is in the array grade, but two other arrays hold computed data. The array studentAverage is used to record the average quiz score for each of the students. For example, the
program will set studentAverage[0] equal to the average of the quiz scores received by student 1, studentAverage[1] equal to the average of the quiz scores received by student 2, and
so forth. The array quizAverage will be used to record the average score for each quiz. For
example, the program will set quizAverage[0] equal to the average of all the student scores for
quiz 1, quizAverage[1] will record the average score for quiz 2, and so forth. Display 6.13 illustrates the relationship between the arrays grade, studentAverage, and quizAverage. In that
display, we have shown some sample data for the array grade. The data in grade, in turn, determine the values that are stored in studentAverage and in quizAverage. Display 6.13 also
shows these computed values for studentAverage and quizAverage. The two arrays studentAverage and quizAverage are created and filled by the constructor that creates the
GradeBook object. (The constructors do this by calling private helping methods.)
The no-argument constructor for the class GradeBook obtains the data for the array instance
variable grade via a dialog with the user. Although this is not my favorite way to define a noargument constructor, some programmers like it and you should see an example of it. Another
alternative would be to have a no-argument constructor that essentially does nothing and then
have an input method that sets all the instance variables including creating the array objects.
A very simple demonstration program along with the dialog it produces is given in Display 6.14.

Self-Test Exercises
23. Write a method definition for a method with the following heading. The method is to be
added to the class GradeBook in Display 6.12.
/**
Returns the grade that student numbered studentNumber
received on quiz number quizNumber.
*/
public int getGrade(int studentNumber, int quizNumber)

no-argument
constructor

5640_ch06.fm Page 354 Friday, November 14, 2003 6:18 AM

354

Chapter 6 Arrays

Display 6.12 A Grade Book Class (Part 1 of 4)


1
2
3

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;

4
5

public class GradeBook


{

6
7

private int numberOfStudents; // Same as studentAverage.length.


private int numberOfQuizzes; // Same as quizeAverage.length.

8
9
10

private int[][] grade; //numberOfStudents rows and numberOfQuizzes columns.


private double[] studentAverage;
private double[] quizAverage;

11
12
13
14
15
16
17

public GradeBook(int[][] a)
{
if (a.length == 0 || a[0].length == 0)
{
System.out.println("Empty grade records. Aborting.");
System.exit(0);
}

18
19
20
21
22
23

numberOfStudents = a.length;
numberOfQuizzes = a[0].length;
fillGrade(a);
fillStudentAverage();
fillQuizAverage();
}

24
25
26
27
28
29
30
31

public GradeBook(GradeBook book)


{
numberOfStudents = book.numberOfStudents;
numberOfQuizzes = book.numberOfQuizzes;
fillGrade(book.grade);
fillStudentAverage();
fillQuizAverage();
}

32
33
34
35

public GradeBook() throws IOException


{
BufferedReader keyboard = new BufferedReader(
new InputStreamReader(System.in));

5640_ch06.fm Page 355 Friday, November 14, 2003 6:18 AM

Multidimensional Arrays

355

Display 6.12 A Grade Book Class (Part 2 of 4)


36
37

System.out.println("Enter number of students:");


numberOfStudents = stringToInt(keyboard.readLine( ));

38
39

System.out.println("Enter number of quizzes:");


numberOfQuizzes = stringToInt(keyboard.readLine( ));

40

grade = new int[numberOfStudents][numberOfQuizzes];

41
42
43
44
45
46
47
48
49
50
51

for (int studentNumber = 1;


studentNumber <= numberOfStudents; studentNumber++)
for (int quizNumber = 1;
quizNumber <= numberOfQuizzes; quizNumber++)
{
System.out.println("Enter score for student number "
+ studentNumber);
System.out.println("on quiz number " + quizNumber);
grade[studentNumber 1][quizNumber 1] =
stringToInt(keyboard.readLine( ));
}

52
53
54

fillStudentAverage();
fillQuizAverage();
}

55
56
57
58

private static int stringToInt(String stringObject)


{
return Integer.parseInt(stringObject.trim());
}

59
60
61

private void fillGrade(int[][] a)


{
grade = new int[numberOfStudents][numberOfQuizzes];

62
63
64
65
66
67
68
69
70

This class should have more accessor and mutator


methods, but we have omitted them to save space. See
Self-Test Exercises 23 through 26.

for (int studentNumber = 1;


studentNumber <= numberOfStudents; studentNumber++)
{
for (int quizNumber = 1;
quizNumber <= numberOfQuizzes; quizNumber++)
grade[studentNumber][quizNumber] =
a[studentNumber][quizNumber];
}
}

5640_ch06.fm Page 356 Friday, November 14, 2003 6:18 AM

Chapter 6 Arrays

356

Display 6.12 A Grade Book Class (Part 3 of 4)


71
72
73
74
75
76

/**
Fills the array studentAverage using the data from the array grade.
*/
private void fillStudentAverage()
{
studentAverage = new double[numberOfStudents];

77
78
79
80
81
82
83
84
85
86
87
88

for (int studentNumber = 1;


studentNumber <= numberOfStudents; studentNumber++)
{//Process one studentNumber:
double sum = 0;
for (int quizNumber = 1;
quizNumber <= numberOfQuizzes; quizNumber++)
sum = sum + grade[studentNumber 1][quizNumber 1];
//sum contains the sum of the quiz scores for student number studentNumber.
studentAverage[studentNumber 1] = sum/numberOfQuizzes;
//Average for student studentNumber is studentAverage[studentNumber 1]
}
}

89
90
91
92
93
94

/**
Fills the array quizAverage using the data from the array grade.
*/
private void fillQuizAverage()
{
quizAverage = new double[numberOfQuizzes];

95
96
97
98
99
100
101
102
103
104
105

for (int quizNumber = 1; quizNumber <= numberOfQuizzes; quizNumber++)


{//Process one quiz (for all students):
double sum = 0;
for (int studentNumber = 1;
studentNumber <= numberOfStudents; studentNumber++)
sum = sum + grade[studentNumber 1][quizNumber 1];
//sum contains the sum of all student scores on quiz number quizNumber.
quizAverage[quizNumber 1] = sum/numberOfStudents;
//Average for quiz quizNumber is the value of quizAverage[quizNumber 1]
}
}

106
107
108
109

public void display()


{
for (int studentNumber = 1;
studentNumber <= numberOfStudents; studentNumber++)

5640_ch06.fm Page 357 Friday, November 14, 2003 6:18 AM

Multidimensional Arrays

357

Display 6.12 A Grade Book Class (Part 4 of 4)


110
111
112
113
114
115
116

{//Display for one studentNumber:


System.out.print("Student " + studentNumber + " Quizzes: ");
for (int quizNumber = 1;
quizNumber <= numberOfQuizzes; quizNumber++)
System.out.print(grade[studentNumber 1][quizNumber 1] + " ");
System.out.println(" Ave = " + studentAverage[studentNumber 1] );
}

117
118
119
120
121
122
123

System.out.println("Quiz averages: ");


for (int quizNumber = 1; quizNumber <= numberOfQuizzes; quizNumber++)
System.out.print("Quiz " + quizNumber
+ " Ave = " + quizAverage[quizNumber 1] + " ");
System.out.println();
}
}

Display 6.13 The Two-Dimensional Array grade


quiz 1

quiz 2

quiz 3

student 1

10

10

10

10.0

studentAverage[0]

student 2

1.0

studentAverage[1]

student 3

7.7

studentAverage[2]

student 4

10

7.3

studentAverage[3]

7.0

5.0

7.5

quizAverage[0]

quizAverage[1]

quizAverage[2]

studentAverage

quizAverage

5640_ch06.fm Page 358 Friday, November 14, 2003 6:18 AM

Chapter 6 Arrays

358

Display 6.14 Demonstration of the Class GradeBook


1
2
3
4
5
6
7
8
9
10

import java.io.IOException;
public class GradeBookDemo
{
public static void main(String[] args) throws IOException
{
GradeBook book = new GradeBook();
book.display();
}
}

SAMPLE DIALOGUE
Enter number of students:
4
Enter number of quizzes:
3
Enter score for student number 1
on quiz number 1
10
Enter score for student number 1
on quiz number 2
10
<The rest of the input dialog is omitted to save space.>
Student 1 Quizzes: 10 10 10 Ave = 10.0
Student 2 Quizzes: 2 0 1 Ave = 1.0
Student 3 Quizzes: 8 6 9 Ave = 7.66666666667
Student 4 Quizzes: 8 4 10 Ave = 7.33333333333
Quiz averages:
Quiz 1 Ave = 7.0 Quiz 2 Ave = 5.0 Quiz 3 Ave = 7.5

24. Write a method definition for a method with the following heading. The method is to be
added to the class GradeBook in Display 6.12.
/**
Changes the grade for student number studentNumber
on quiz number quizNumber to newGrade.
*/
public void changeGrade(int studentNumber,
int quizNumber, int newGrade))

5640_ch06.fm Page 359 Friday, November 14, 2003 6:18 AM

Chapter Summary

359

25. Write a method definition for a method with the following heading. The method is to be
added to the class GradeBook in Display 6.12.
/**
Returns an array with the average quiz score for each student.
*/
public double[] getStudentAverages()

26. Write a method definition for a method with the following heading. The method is to be
added to the class GradeBook in Display 6.12.
/**
Returns an array with the average score for each quiz.
*/
public double[] getQuizAverages()

Chapter Summary

An array can be used to store and manipulate a collection of data that is all of the
same type.
The indexed variables of an array can be used just like any other variables of the base
type of the array.
Arrays are objects that are created with new just like the class objects we discussed
before this chapter (although there is a slight difference in the syntax used).
A for loop is a good way to step through the elements of an array and perform
some program action on each indexed variable.
The most common programming error made when using arrays is to attempt to
access a nonexistent array index. Always check the first and last iterations of a loop
that manipulates an array to make sure it does not use an index that is illegally small
or illegally large.
The indexed variables of an array can be used as an argument to be plugged in for a
parameter of the arrays base type.
A method can have parameters of an array type. When the method is invoked, an
entire array is plugged in for the array parameter.
A method may return an array as the value returned by the method.
When using a partially filled array, your program needs an additional variable of
type int to keep track of how much of the array is being used.
An instance variable of a class can be of an array type.
If you need an array with more than one index, you can use a multidimensional
array, which is actually an array of arrays.

5640_ch06.fm Page 360 Friday, November 14, 2003 6:18 AM

360

Chapter 6 Arrays

ANSWERS

TO

SELF-TEST EXERCISES

1. a. word
b. String
c. 5
d. 0 through 4 inclusive
e. any of the following would be correct:
word[0], word[1], word[2], word[3], word[4]
2. a. 10
b. 0
c. 9
3. a, b, c,
4. 1.1 2.2 3.3
1.1 3.3 3.3

5. The for loop uses indices 1 through sampleArray.length, but the correct indices are 0
through sampleArray.length 1. The last index, sampleArray.length, is out of
bounds. What was probably intended is the following:
int[] sampleArray = new int[10];
for (int index = 0; index < sampleArray.length; index++)
sampleArray[index] = 3*index;

6. The last value of index is a.length 1, which is the last index of the array. However,
when index has the value a.length 1, a[index + 1] has an index that is out of bounds
since index + 1 is one more than the largest array index. The for loop ending condition
should instead be index < a.length 1.
7. SomeClass.doSomething(number); //Legal.
SomeClass.doSomething(a[2]); //Legal.
SomeClass.doSomething(a[3]); //Illegal. Index out of bounds.
SomeClass.doSomething(a[number]); //Legal.
SomeClass.doSomething(a); //Illegal.

8. public static void oneMore(int[] a)


{
for (int i = 0; i < a.length; i++)
a[i] = a[i] + 1;
}

9. public static int outOfOrder(double[] a)


{
for (int index = 0; index < a.length 1; index++)
if (a[index] > a[index + 1])

5640_ch06.fm Page 361 Friday, November 14, 2003 6:18 AM

Answers to Self-Test Exercises

361

return (index + 1);


return 1;
}

10. This method is legal but pointless. When invoked, it has no effect on its argument. The
parameter a is a local variable that contains a reference. The reference does indeed get
changed to a reference to an array of double the size of the argument, but that reference
goes away when the method ends. A method can change the values of the indexed
variables of its argument, but it cannot change the reference in the array variable used as
an argument.
11. public static double[] halfArray(double[] a)
{
double[] temp = new double[a.length];
for (int i = 0; i < a.length; i++)
temp[i] = a[i]/2.0;
return temp;
}

12. The method will compile and run. However, it will change the values of its array argument.
If you want to change the values in the array argument, a void method would make more
sense. If you want to return an array, you should probably return a new array (as in the version in the previous subsection), not return a changed version of the argument array.
13. /**
Precondition: numberUsed <= argumentArray.length;
the first numberUsed indexed variables of argumentArray
have values.
Returns an array of length numberUsed whose ith element
is argumentArray[i] - adjustment.
*/
public static double[] differenceArray(
double[] argumentArray, int numberUsed, double adjustment)
{
double[] temp = new double[numberUsed];
for (int i = 0; i < numberUsed; i++)
temp[i] = argumentArray[i] adjustment;
return temp;
}

14. The only changes are to add the method differenceArray and to rewrite the method
showDifference as follows (the complete class definition is in the file GolfScoresExercise.java on the accompanying CD):
public static void showDifference(double[] a,
int numberUsed)
{
double average = computeAverage(a, numberUsed);
System.out.println("Average of the " + numberUsed
+ " scores = " + average);

extra code on CD

5640_ch06.fm Page 362 Friday, November 14, 2003 6:18 AM

362

Chapter 6 Arrays

double[] difference =
differenceArray(a, numberUsed, average);
System.out.println("The scores are:");
for (int index = 0; index < numberUsed; index++)
System.out.println(a[index] +
" differs from average by "
+ difference[index]);
}

extra code
on CD

15. The main differences are to remove parameters, replace the array name a by score, and
make the method fillArray a void method. This code is in the file GolfScoresStaticExercise.java on the accompanying CD.
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
public class GolfScoresStaticExercise
{
public static final int MAX_NUMBER_SCORES = 10;
private static double[] score =
new double[MAX_NUMBER_SCORES];
private static int numberUsed = 0;
/**
Shows differences between each of a list of golf scores
and their average.
*/
public static void main(String[] args) throws IOException
{
System.out.println(
"This program reads golf scores and shows");
System.out.println(
"how much each differs from the average.");
System.out.println("Enter golf scores:");
fillArray();
showDifference();
}
/**
Reads values into the array score.
*/
public static void fillArray() throws IOException
{
System.out.println("Enter up to " + score.length
+ " nonnegative numbers, one per line.");

5640_ch06.fm Page 363 Friday, November 14, 2003 6:18 AM

Answers to Self-Test Exercises

System.out.println(
"Mark the end of the list with a negative number.");
BufferedReader keyboard = new BufferedReader(
new InputStreamReader(System.in));
double next;
int index = 0;
next = stringToDouble(keyboard.readLine( ));
while ((next >= 0) && (index < score.length))
{
score[index] = next;
index++;
next = stringToDouble(keyboard.readLine( ));
//index is the number of
//array indexed variables used so far.
}
//index is the total number of array indexed variables used.
if (next >= 0)
System.out.println("Could only read in "
+ score.length + " input values.");
numberUsed = index;
}
/**
Precondition: numberUsed <= score.length.
score[0] through score[numberUsed-1] have values.
Returns the average of numbers ascore[0] through
score[numberUsed-1].
*/
public static double computeAverage()
{
double total = 0;
for (int index = 0; index < numberUsed; index++)
total = total + score[index];
if (numberUsed > 0)
{
return (total/numberUsed);
}
else
{
System.out.println(
"ERROR: Trying to average 0 numbers.");
System.out.println("computeAverage returns 0.");
return 0;
}
}

363

5640_ch06.fm Page 364 Friday, November 14, 2003 6:18 AM

364

Chapter 6 Arrays

private static double stringToDouble(String stringObject)


{
return Double.parseDouble(stringObject.trim());
}
/**
Precondition: numberUsed <= score.length.
The first numberUsed indexed variables of score have values.
Postcondition: Gives screen output showing how much each of the
first numberUsed elements of the array a differ from the average.
*/
public static void showDifference()
{
double average = computeAverage();
System.out.println("Average of the " + numberUsed
+ " scores = " + average);
System.out.println("The scores are:");
for (int index = 0; index < numberUsed; index++)
System.out.println(score[index] +
" differs from average by "
+ (score[index] average));
}
}

16. public void removeAll()


{
numberUsed = 0;
}

17. public void increaseCapacity(int newCapacity)


{
if (newCapacity > numberUsed)
{
maxNumberElements = newCapacity;
double[] temp = new double[newCapacity];
for (int i = 0; i < a.length; i++)
temp[i] = a[i];
a = temp;
}//else do nothing.
}

18. All you need to do to make your code work for sorting into decreasing order is to replace
the < with > in the following line of the definition of indexOfSmallest:
if (a[index] < min)

However, to make your code easy to read, you should also rename the method
indexOfSmallest to indexOfLargest, rename the variable min to max, and rename the
variable indexOfMin to indexOfMax. You should also rewrite some of the comments to
reflect these changes.

5640_ch06.fm Page 365 Friday, November 14, 2003 6:18 AM

Answers to Self-Test Exercises

365

19. If an array has a value that occurs more than once and you sort the array using the method
SelectionSort.sort, then there will be as many copies of the repeated value after the
array is sorted as there originally were in the array.
20. 0 1 2 3
0 1 2 3
0 1 2 3
0 1 2 3

21. The answer is given along with the answer to exercise 22.
22. This program is on the CD that comes with this book.
import
import
import
import

extra code
on CD

java.io.BufferedReader;
java.io.InputStreamReader;
java.io.IOException;
java.util.StringTokenizer;

public class DoubleExerciseAnswer


{
public static final int ROWS = 4;
public static final int COLUMNS = 5

public static void main(String[] args) throws IOException


{
//Answer to Self-Test Exercise 21:
BufferedReader keyboard = new BufferedReader(
new InputStreamReader(System.in));
int[][] a = new int[ROWS][COLUMNS];
String inputLine;
System.out.println("Enter " + ROWS*COLUMNS +
" numbers, " + COLUMNS + " per line, on "
+ ROWS + " lines:");
int row, column;
for (row = 0; row < ROWS; row++)
{
inputLine = keyboard.readLine();
StringTokenizer numberList =
new StringTokenizer(inputLine);
for (column = 0; column < COLUMNS; column++)
a[row][column] =
Integer.parseInt(numberList.nextToken());
}
System.out.println("You entered:");
echo(a);
}

5640_ch06.fm Page 366 Friday, November 14, 2003 6:18 AM

366

Chapter 6 Arrays

//Answer to Self-Test Exercise 22:


public static void echo(int[][] a)
{
int row, column;
for (row = 0; row < a.length; row++)
{
for (column = 0; column < a[row].length; column++)
System.out.print(a[row][column] + " ");
System.out.println();
}
}
}

23. If the array indices are out of bounds, then Java will halt the program with an error message, so no other checks on the parameters are needed.
/**
Returns the grade that student numbered studentNumber
received on quiz number quizNumber.
*/
public int getGrade(int studentNumber, int quizNumber)
{
return grade[studentNumber][quizNumber];
}

24. If the array indices are out of bounds, then Java will halt the program with an error message, so no other checks on the parameters are needed.
/**
Changes the grade for student number studentNumber
on quiz number quizNumber to newGrade.
*/
public void changeGrade(int studentNumber,
int quizNumber, int newGrade)
{
grade[studentNumber][quizNumber] = newGrade;
}

25. /**
Returns an array with the average quiz score for each student.
*/
public double[] getStudentAverages()
{
int arraySize = studentAverage.length;
double[] temp = new double[arraySize];
for (int i = 0; i < arraySize; i++)
temp[i] = studentAverage[i];
return temp;
}

5640_ch06.fm Page 367 Friday, November 14, 2003 6:18 AM

Programming Projects

367

26. /**
Returns an array with the average score for each quiz.
*/
public double[] getQuizAverages()
{
int arraySize = quizAverage.length;
double[] temp = new double[arraySize];
for (int i = 0; i < arraySize; i++)
temp[i] = quizAverage[i];
return temp;
}

PROGRAMMING PROJECTS
Many of these Programming Projects can be solved using AWs CodeMate.
To access these please go to: www.aw-bc.com/codemate.
1. Write a program that reads in the average monthly rainfall for a city for each month of the
year and then reads in the actual monthly rainfall for each of the previous 12 months. The
program then prints out a nicely formatted table showing the rainfall for each of the previous 12 months as well as how much above or below average the rainfall was for each
month. The average monthly rainfall is given for the months January, February, and so
forth, in order. To obtain the actual rainfall for the previous 12 months, the program first
asks what the current month is and then asks for the rainfall figures for the previous 12
months. The output should correctly label the months. There are a variety of ways to deal
with the month names. One straightforward method is to code the months as integers and
then do a conversion to a string for the month name before doing the output. A large
switch statement is acceptable in an output method. The month input can be handled in
any manner you wish so long as it is relatively easy and pleasant for the user. Include a loop
that allows the user to repeat this entire calculation until the user requests that the program
end.
2. Write a static method called deleteRepeats that has a partially filled array of characters as
a formal parameter and that deletes all repeated letters from the array. Since a partially
filled array requires two arguments, the method will actually have two formal parameters:
an array parameter and a formal parameter of type int that gives the number of array positions used. When a letter is deleted, the remaining letters are moved one position to fill in
the gap. This will create empty positions at the end of the array so that less of the array is
used. Since the formal parameter is a partially filled array, a second formal parameter of
type int will tell how many array positions are filled. This second formal parameter cannot
be changed by a Java method, so have the method return the new value for this parameter.
For example, consider the following code:
char
a[0]
a[1]
a[2]

a[10];
= 'a';
= 'b';
= 'a';

5640_ch06.fm Page 368 Friday, November 14, 2003 6:18 AM

368

Chapter 6 Arrays

a[3] = 'c';
int size = 4;
size = deleteRepeats(a, size);

After this code is executed, the value of a[0] is 'a', the value of a[1] is 'b', the value of
a[2] is 'c', and the value of size is 3. (The value of a[3] is no longer of any concern,
since the partially filled array no longer uses this indexed variable.) You may assume that
the partially filled array contains only lowercase letters. Write a suitable test program for
your method.
3. The standard deviation of a list of numbers is a measure of how much the numbers deviate
from the average. If the standard deviation is small, the numbers are clustered close to the
average. If the standard deviation is large, the numbers are scattered far from the average.
The standard deviation of a list of numbers n1, n2, n3, and so forth is defined as the square
root of the average of the following numbers:
(n1 - a)2, (n2 - a)2, (n3 - a)2, and so forth.

The number a is the average of the numbers n1, n 2, n3, and so forth.
Define a static method that takes a partially filled array of numbers as its argument and
returns the standard deviation of the numbers in the partially filled array. Since a partially
filled array requires two arguments, the method will actually have two formal parameters,
an array parameter and a formal parameter of type int that gives the number of array positions used. The numbers in the array will be of type double. Write a suitable test program
for your method.
4. Write a program that reads numbers from the keyboard into an array of type int[]. You
may assume that there will be 50 or fewer entries in the array. Your program allows any
number of numbers to be entered up to 50 numbers. The output is to be a two-column
list. The first column is a list of the distinct array elements; the second column is the count
of the number of occurrences of each element. The list should be sorted on entries in the
first column, largest to smallest.
For the array
12 3 12 4 1 1 12 1 1 1 2 3 4 2 3 12

the output should be


N
4
3
2
1
1
12

Count
2
3
2
4
1
4

5. An array can be used to store large integers one digit at a time. For example, the integer
1234 could be stored in the array a by setting a[0] to 1, a[1] to 2, a[2] to 3, and a[3] to

5640_ch06.fm Page 369 Friday, November 14, 2003 6:18 AM

Programming Projects

369

4. However, for this exercise you might find it more useful to store the digits backward;
that is, place 4 in a[0], 3 in a[1], 2 in a[2], and 1 in a[3]. In this exercise you will write

a program that reads in two positive integers that are 20 or fewer digits in length and then
outputs the sum of the two numbers. Your program will read the digits as values of type
char so that the number 1234 is read as the four characters '1', '2', '3', and '4'. After
they are read into the program, the characters are changed to values of type int. The digits
will be read into a partially filled array, and you might find it useful to reverse the order of
the elements in the array after the array is filled with data from the keyboard. (Whether or
not you reverse the order of the elements in the array is up to you. It can be done either way
and each way has its advantages and disadvantages.) Your program will perform the addition by implementing the usual paper-and-pencil addition algorithm. The result of the
addition is stored in an array of size 20 and the result is then written to the screen. If the
result of the addition is an integer with more than the maximum number of digits (that is,
more than 20 digits), then your program should issue a message saying that it has encountered integer overflow. You should be able to change the maximum length of the integers
by changing only one named constant. Include a loop that allows the user to continue to
do more additions until the user says the program should end.
6. Design a class called BubbleSort that is similar to the class SelectionSort given in Display 6.9. The class BubbleSort will be used in the same way as the class SelectionSort,
but it will use the bubble sort algorithm.
The bubble sort algorithm checks all adjacent pairs of elements in the array from the beginning to the end and interchanges any two elements that are out of order. This process is
repeated until the array is sorted. The algorithm is as follows:

Bubble Sort Algorithm to Sort an Array a


Repeat the following until the array a is sorted:
for (index = 0; index < a.length 1; index++)
if (a[index] > a[index + 1])
Interchange the values of a[index] and a[index + 1].

The bubble sort algorithm is good for sorting an array that is almost sorted. It is not
competitive to other sorting methods for most other situations.
7. Enhance the definition of the class PartiallyFilledArray (Display 6.5) in the following
way: When the user attempts to add one additional element and there is no room in the array
instance variable a, the user is allowed to add the element. The object creates a second array
that is twice the size of the array a, copies values from the array a to the users new array,
makes this array (or more precisely its reference) the new value of a, and then adds the element to this new larger array a. Hence, this new class will have no limit (other than the
physical size of the computer) to how many numbers it can hold. The instance variable
maxNumberElements remains and the method getMaxCapacity is unchanged, but these
now refer to the currently allocated memory and not to an absolute upper bound. Write a
suitable test program.

5640_ch06.fm Page 370 Friday, November 14, 2003 6:18 AM

370

Chapter 6 Arrays

8. Write a program that will allow two users to play tic-tac-toe. The program should ask for moves
alternately from player X and player O. The program displays the game positions as follows:
1
4
7

2
5
8

3
6
9

The players enter their moves by entering the position number they wish to mark. After
each move, the program displays the changed board. A sample board configuration is
X
4
O

X
5
8

O
6
9

9. Write a program to assign passengers seats in an airplane. Assume a small airplane with seat
numberings as follows:
1
2
3
4
5
6
7

A
A
A
A
A
A
A

B
B
B
B
B
B
B

C
C
C
C
C
C
C

D
D
D
D
D
D
D

The program should display the seat pattern, with an 'X' marking the seats already
assigned. For example, after seats 1A, 2B, and 4C are taken, the display should look like:
1
2
3
4
5
6
7

X
A
A
A
A
A
A

B
X
B
B
B
B
B

C
C
C
X
C
C
C

D
D
D
D
D
D
D

After displaying the seats available, the program prompts for the seat desired, the user types
in a seat, and then the display of available seats is updated. This continues until all seats are
filled or until the user signals that the program should end. If the user types in a seat that is
already assigned, the program should say that that seat is occupied and ask for another
choice.

You might also like