TheRationalEdge_July2004

150
Search for: within All of dW Search help IBM home | Products & services | Support & downloads | My account developerWorks > Rational > About IBM | Privacy | Terms of use | Contact Page 1 of 1 The Rational Edge: e-zine for the Rational Community 7/15/2004 © Copyright IBM Corporation 2004. http://www-106.ibm.com/developerworks/rational/rationaledge/ The Rational Edge--July 2004

description

itembbvcxfg

Transcript of TheRationalEdge_July2004

Page 1: TheRationalEdge_July2004

Search for: within All of dW

Search help

IBM home | Products & services | Support & downloads | My account

developerWorks > Rational >

About IBM | Privacy | Terms of use | Contact

Page 1 of 1The Rational Edge: e-zine for the Rational Community

7/15/2004

© Copyright IBM Corporation 2004. http://www-106.ibm.com/developerworks/rational/rationaledge/

The Rational Edge--July 2004

Page 2: TheRationalEdge_July2004

Search for: within All of dW

Search help

IBM home | Products & services | Support & downloads | My account

developerWorks > Rational >

Issue contents Editor's notes — July 2004

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 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.

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

Teams and projects 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.

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

issue contents

archives

subscribe

submit an article

contact us

Entire issue in .pdf

Download the entire issue in .pdf (1.0 MB)

Page 1 of 2The Rational Edge: Issue contents

7/15/2004

© Copyright IBM Corporation 2004.

The Rational Edge--July 2004

Page 3: TheRationalEdge_July2004

application development lifecycle and address both horizontal and domain-specific business needs. This article describes that ecosystem and its value to IBM clients.

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.

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.

Theory and practice

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 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.

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.

About IBM | Privacy | Terms of use | Contact

Page 2 of 2The Rational Edge: Issue contents

7/15/2004

Page 4: TheRationalEdge_July2004

Search for: within

Search help

IBM home | Products & services | Support & downloads | My account

developerWorks > Rational

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

Use-Case Analysis activity

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

Use-Case Analysis step 4: Describe the class’s 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

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)

Gary EvansIndependent Object Technology Evangelist, Evanetics13 Jul 2004

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.

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.

The IBM Rational Unified Process® (RUP®) advocates writing use cases to capture the operational requirements of a software system.1 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 system’s 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.

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

© Copyright IBM Corporation 2004. http://www-106.ibm.com/developerworks/rational/library/5383.html

The Rational Edge--July 2004

Page 5: TheRationalEdge_July2004

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 system’s 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

Page 6: TheRationalEdge_July2004

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 Class’s Responsibilities

2. Describe the Class’s 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

Page 7: TheRationalEdge_July2004

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

Figure 3: The steps of use case analysis

Example use caseTo 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

Page 8: TheRationalEdge_July2004

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, don’t 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, let’s follow the RUP steps of Use Case Analysis.

Use-Case Analysis step 1: Create a use-case realization The first step in RUP’s Use-Case Analysis is to create what RUP calls a use case realization. Before we get into a formal definition of a realization, let’s 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 don’t 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, doesn’t 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

Page 9: TheRationalEdge_July2004

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 let’s not be so specific yet. Let’s 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 (mid-project), 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 caseLet’s 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 customer’s 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 customer’s 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, it’s 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: It’s 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 it’s better to err toward abstraction if you are not sure how detailed you should be. It’s 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 system’s 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

Page 10: TheRationalEdge_July2004

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 don’t 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. RUP’s 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 RUP’s 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 RUP’s Architectural Analysis activity — if your project is pursuing that degree of RUP conformance.

With that said, let’s 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.

Let’s 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 customer’s 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 customer’s 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

Page 11: TheRationalEdge_July2004

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

Page 12: TheRationalEdge_July2004

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

Page 13: TheRationalEdge_July2004

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

Page 14: TheRationalEdge_July2004

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

Page 15: TheRationalEdge_July2004

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! That’s only eight analysis classes versus the thirty nine candidates we started with. The four questions have helped us rapidly narrow our focus — and that’s 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 doesn’t 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 RUP’s 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

Page 16: TheRationalEdge_July2004

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 of achieving, the strategy).2

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 Class’s Responsibilities

2. Establish Associations between Analysis Classes (analysis class diagram)

3. Distribute Behavior to Analysis Classes (discover operations)

4. Describe each Class’s Attributes and Associations

■ Define Class Attributes

■ Describe Event Dependencies between Analysis Classes

Use-Case Analysis step 4: Describe the class’s responsibilitiesThis 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

Page 17: TheRationalEdge_July2004

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

James Rumbaugh et al.3 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

Page 18: TheRationalEdge_July2004

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

What if we made a mistake in our responsibilities? Again, it doesn’t 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 classesNow 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?” It’s 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 don’t 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

Page 19: TheRationalEdge_July2004

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 classesHow 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 diagramClick 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 reader’s 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 object’s lifeline, and always terminate on a lifeline, usually another object’s lifeline, but sometimes on the sending object’s 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

Page 20: TheRationalEdge_July2004

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 associationsIn 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 vehicle’s 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

Page 21: TheRationalEdge_July2004

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. We’ll discover them as we move further into the project.

Use-Case Analysis step 8: Qualify analysis mechanismsAn 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

Page 22: TheRationalEdge_July2004

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:

ConclusionIn 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.

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

ReferencesWirfs-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 ReadingAmbler, 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 Manager’s 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

Page 23: TheRationalEdge_July2004

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. “UML’s sequence diagram,” in The Rational Edge, January 2004: http://www-106.ibm.com/developerworks/rational/library/3101.html

Notes1 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.

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

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

About the authorGary 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) Needs work (2) Lame! (1)

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

Page 24: TheRationalEdge_July2004

Search for: within All of dW

Use + - ( ) " " Search help

IBM home | Products & services | Support & downloads | My account developerWorks > Rational

Writing good requirements is a lot like writing good codeJim 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.

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.

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.

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.

Contents:Follow a structureUse practices that ensure quality Elaborate with comments Know the languageFollow guidelinesUnderstand the operating environmentFollow established principles Use automated toolsManage changePlanningGood developers can write good requirements Notes

About the authorRate this article

Subscriptions:dW newsletters

dW Subscription (CDs and downloads)

Page 1 of 8Writing good requirements is a lot like writing good code

7/15/2004

© Copyright IBM Corporation 2004. http://www-106.ibm.com/developerworks/rational/library/5170.html

The Rational Edge--July 2004

Page 25: TheRationalEdge_July2004

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:

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

Page 2 of 8Writing good requirements is a lot like writing good code

7/15/2004

Page 26: TheRationalEdge_July2004

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:

Page 3 of 8Writing good requirements is a lot like writing good code

7/15/2004

Page 27: TheRationalEdge_July2004

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:

Page 4 of 8Writing good requirements is a lot like writing good code

7/15/2004

Page 28: TheRationalEdge_July2004

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.

Page 5 of 8Writing good requirements is a lot like writing good code

7/15/2004

Page 29: TheRationalEdge_July2004

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:

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

Page 6 of 8Writing good requirements is a lot like writing good code

7/15/2004

Page 30: TheRationalEdge_July2004

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

Page 7 of 8Writing good requirements is a lot like writing good code

7/15/2004

Page 31: TheRationalEdge_July2004

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 front-end development issues. He holds an M.S. in management information systems from the University of Arizona.

What do you think of this document?

Comments?

Killer! (5) Good stuff (4) So-so; not bad (3) Needs work (2) Lame! (1)

Submit feedback developerWorks > Rational

About IBM | Privacy | Terms of use | Contact

Page 8 of 8Writing good requirements is a lot like writing good code

7/15/2004

Page 32: TheRationalEdge_July2004

Search for: within All of dW

Use + - ( ) " " Search help

IBM home | Products & services | Support & downloads | My account developerWorks > Rational

The IBM Software Development Platform partner ecosystemPeter 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 ecosystem’s technology, technical support, and marketing resources. This article describes that ecosystem and the value it brings to IBM clients.

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:

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. IBM’s 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.

Contents:The IBM Software Development Platform business partner ecosystemThe Eclipse tools integration platformComponents of the IBM Software Development PlatformSupport for the IBM business partner ecosystem

About the authorRate this article

Subscriptions:dW newsletters

dW Subscription (CDs and downloads)

Page 1 of 7The IBM Software Development Platform partner ecosystem© Copyright IBM Corporation 2004 http://www-106.ibm.com/developerworks/rational/library/5360.html

The Rational Edge--July 2004

Page 33: TheRationalEdge_July2004

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 Platform’s increasing value.

The IBM Software Development Platform partner ecosystem comprises a broad range of companies — some focusing on technology development and others on services delivery — all striving to help developers and project teams using the Platform. For example, ecosystem members contribute:

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 Platform’s ecosystem to make it even easier for new partners to join in.

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.

The Eclipse platform provides an open environment for enterprise development with the capability to support all phases of the application development lifecycle, including analysis, requirements, design, development, testing, software configuration management, defect tracking, project management, and so on. Its main components 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 tools that support specific kinds of development approaches and technologies. At the heart of the Eclipse platform is an extensive toolset with core capabilities, plus support for extensions through a plug-in architecture.

More than fifty major software companies are members of the Eclipse Foundation, contributing software and using Eclipse technology within their products. Eclipse 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.

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 Rational tools and best practices, helps Unisys implement model-driven architectures and develop Web services.

As part of its 3D Visual Enterprise approach, Unisys creates a digital map of each client’s 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.

“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 platform’s combination of Rational tools, support for UML, best practices, and process provides a complete solution for his company’s needs. “Using UML and IBM Rational Unified Process,® as well as BPEL (Business Process Execution Language)–based representations of our client’s business architecture, we can get disparate populations — different groups — all understanding exactly what we are doing and what we are building.” Unisys then uses RUP and other tools in the IBM Software Development Platform to enable reuse of software artifacts across teams and projects, which benefits both Unisys consultants and their clients.

Page 2 of 7The IBM Software Development Platform partner ecosystem

7/15/2004

Page 34: TheRationalEdge_July2004

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 platform’s 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 platform’s 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

Page 3 of 7The IBM Software Development Platform partner ecosystem

7/15/2004

Page 35: TheRationalEdge_July2004

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 Platform’s 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 Platform’s 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 IBM’s Java IDE family and WebSphere Studio Workbench.

Page 4 of 7The IBM Software Development Platform partner ecosystem

7/15/2004

Page 36: TheRationalEdge_July2004

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 individual’s personal machine. Tivoli Identity Manager includes a suite of security functions that are easy to deploy—its 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.

IBM Lotus Domino Designer® helps developers rapidly build, test, and deploy security-rich IBM Lotus Notes® or Lotus Domino collaborative and/or mission-critical applications. Using the Lotus Domino Toolkit for WebSphere Studio, developers can start building JavaServer Pages™ simply by dragging and dropping existing Domino design elements, such as forms, views, and agents.

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 those database systems. With point-and-click ease, developers can create, manage, and schedule batch and real-time access to provide integration with relational systems such as DB2 and Oracle databases or enterprise resource planning (ERP) systems such as SAP. This product enables the rapid creation of automated business-process solutions that can increase employee productivity.

The IBM Lotus Workplace Builder is an application development framework for building project-based collaborative applications.

IBM DB2 Universal Database The IBM DB2 Universal Database™ (UDB) plays an important role in the IBM Software Development Platform by enabling developers to write in one format and by supporting development for both Java and Microsoft .NET applications. All elements of the DB2 portfolio — database servers, business intelligence software, enterprise content management software, data management tools, and information integration software — 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 system–level 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

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 non-RAS assets. It integrates with a broad set of the IBM Software Development Platform components, including ClearCase, ClearQuest, XDE and WebSphere Studio Application Developer. Flashline Inc. uses the IBM Software Development Platform to increase enterprise visibility into how teams are creating and using software assets. This allows IT managers to determine whether they are in compliance with corporate and architectural mandates and helps to reduce duplication of effort. As projects are deployed, Flashline automatically tracks both time and cost savings attributable to reuse of existing assets. It also enables software developed and managed in any of the IBM Software Development Platform tools to be leveraged across projects and throughout an enterprise. Through integration with IBM Rational ClearCase, Flashline captures and extends metadata about key software assets, making them easier to discover, evaluate, and reuse in multiple projects. Through integration with IBM Rational ClearQuest, Flashline includes details, such as defects and change requests within its asset metadata.

LogicLibrary’s 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

Page 5 of 7The IBM Software Development Platform partner ecosystem

7/15/2004

Page 37: TheRationalEdge_July2004

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 Rational’s 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 Jaczone’s incorporation of RUP best practices in its Waypointer UML modeling tool.

The strong market position of IBM Rational TestStudio® has also encouraged strong partner involvement. Products such as Scapa StressTest are integrated with Rational’s 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.

IBM’s 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

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. Logidex’s workflow capabilities allow enterprises to configure approval processes that support adherence to RUP.

Logidex’s 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.

Page 6 of 7The IBM Software Development Platform partner ecosystem

7/15/2004

Page 38: TheRationalEdge_July2004

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. IBM’s 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, PartnerWorld’s 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 company’s 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?

Comments?

Killer! (5) Good stuff (4) So-so; not bad (3) Needs work (2) Lame! (1)

Submit feedback developerWorks > Rational

About IBM | Privacy | Terms of use | Contact

Page 7 of 7The IBM Software Development Platform partner ecosystem

7/15/2004

Page 39: TheRationalEdge_July2004

Search for: within All of dW

Use + - ( ) " " Search help

IBM home | Products & services | Support & downloads | My account developerWorks > Rational

Enhancing RUP for CMMI compliance: A methodological approachWalcelio Melo Unisys Corporation 8 Jul 2004

from The Rational Edge: 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.

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.

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.

Contents:The approachNew process elementsConclusionReferencesAppendix A: Related workNotes

About the authorRate this article

Subscriptions:dW newsletters

dW Subscription (CDs and downloads)

Page 1 of 15Enhancing RUP for CMMI compliance: A methodological approach

7/15/2004

© Copyright IBM Corporation 2004. http://www-106.ibm.com/developerworks/rational/library/5318.html

The Rational Edge--July 2004

Page 40: TheRationalEdge_July2004

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.

Page 2 of 15Enhancing RUP for CMMI compliance: A methodological approach

7/15/2004

Page 41: TheRationalEdge_July2004

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

Page 3 of 15Enhancing RUP for CMMI compliance: A methodological approach

7/15/2004

Page 42: TheRationalEdge_July2004

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:

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

Page 4 of 15Enhancing RUP for CMMI compliance: A methodological approach

7/15/2004

Page 43: TheRationalEdge_July2004

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

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

# 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?

METRIC# of CMMI Supplier Management process practices supported by RUP

# of CMMI Supplier Management specific goals 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

Supplier Agreement Management

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

SG 2 Satisfy 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

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

NASA SEL COTS-based process M H

OTSO COTS Selection Process H H H L

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

Page 5 of 15Enhancing RUP for CMMI compliance: A methodological approach

7/15/2004

Page 44: TheRationalEdge_July2004

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

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

RUP M L M L

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.

COTS Identification and Selection.

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.

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.

Make Versus Buy Decision II.

These two make vs. buy decision activities analyze in detail different tradeoffs among requirements satisfied, risks accepted, and cost.

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.

Page 6 of 15Enhancing RUP for CMMI compliance: A methodological approach

7/15/2004

Page 45: TheRationalEdge_July2004

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

TS SP 1.3-1 Select the product component solutions that best satisfy the criteria established.

Analysis of results 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.

SAM SP 2.1-1 Review candidate COTS products to ensure they satisfy the specified requirements that are covered under a supplier agreement.

OTSO process as a whole. OTSO provides detailed guidance for:

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

Specific Process Practices

Description SPC's Process Element

Comments

TS SP 2.4-3 Evaluate whether the product components should be developed, purchased, or reused based on established criteria.

Perform Make vs. Buy Analysis

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.

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

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:

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

Page 7 of 15Enhancing RUP for CMMI compliance: A methodological approach

7/15/2004

Page 46: TheRationalEdge_July2004

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.

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:

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)

SAM SP 2.1-1

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

Perform Make vs. Buy Analysis Solicit and Select Supplier

During Perform Make vs. Buy Analysis activity, evaluation criteria needed to meet the business objectives are documented and trade studies are performed.

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.

SAM SP 2.2-1

Perform activities with the supplier as specified in the supplier agreement.

Manage the Relationship

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:

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

SAM SP 2.3-1

Ensure that the supplier agreement is satisfied before accepting the acquired product.

Accept the Products and Services

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:

Reviews or test cases are performed, and acceptance criteria are met. Required deliverables are placed under CM.

SAM SP 2.4-1

Transition the acquired products from the supplier to the project.

Transition the Product or Service

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:

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

Page 8 of 15Enhancing RUP for CMMI compliance: A methodological approach

7/15/2004

Page 47: TheRationalEdge_July2004

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

Page 9 of 15Enhancing RUP for CMMI compliance: A methodological approach

7/15/2004

Page 48: TheRationalEdge_July2004

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

Page 10 of 15Enhancing RUP for CMMI compliance: A methodological approach

7/15/2004

Page 49: TheRationalEdge_July2004

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

Page 11 of 15Enhancing RUP for CMMI compliance: A methodological approach

7/15/2004

Page 50: TheRationalEdge_July2004

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.

Page 12 of 15Enhancing RUP for CMMI compliance: A methodological approach

7/15/2004

Page 51: TheRationalEdge_July2004

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

Page 13 of 15Enhancing RUP for CMMI compliance: A methodological approach

7/15/2004

Page 52: TheRationalEdge_July2004

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.

Page 14 of 15Enhancing RUP for CMMI compliance: A methodological approach

7/15/2004

Page 53: TheRationalEdge_July2004

Search for: within All of dW

Use + - ( ) " " Search help

IBM home | Products & services | Support & downloads | My account developerWorks > Rational

RUP iteration planningAnthony 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.

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 I’ve ever used, the development case artifact could be improved. However, don’t 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 don’t 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 else’s 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 doesn’t 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.

Contents:Input artifactsCreating the iteration planSummaryNotes

About the authorRate this article

Subscriptions:dW newsletters

dW Subscription (CDs and downloads)

Page 1 of 13RUP iteration planning

7/15/2004

© Copyright IBM Corporation 2004. http://www-106.ibm.com/developerworks/rational/library/5335.html

The Rational Edge--June 2004

Page 54: TheRationalEdge_July2004

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 isn’t 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 shouldn’t 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 won’t. At first it feels like you have to know a lot about RUP to make that judgment, but that isn’t necessarily the case. Knowing the definitions of the four RUP phases may be all you really need. Let’s look at an example.

Page 2 of 13RUP iteration planning

7/15/2004

Page 55: TheRationalEdge_July2004

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? Let’s 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.

Page 3 of 13RUP iteration planning

7/15/2004

Page 56: TheRationalEdge_July2004

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 manager’s job to decide which workflow details to perform in each iteration; it is the team’s 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. That’s pretty much it. I consider status activities part of tracking-to-plan. And I’m 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. Let’s 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 don’t 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

Page 4 of 13RUP iteration planning

7/15/2004

Page 57: TheRationalEdge_July2004

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 didn’t 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 don’t 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 shouldn’t 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. Let’s look at some examples.

Figure 4: Details for the Perform Architectural Synthesis workflow detail

Page 5 of 13RUP iteration planning

7/15/2004

Page 58: TheRationalEdge_July2004

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 haven’t 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 area’s 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 don’t 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.)

Page 6 of 13RUP iteration planning

7/15/2004

Page 59: TheRationalEdge_July2004

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 I’ve taken from the standard development case I give to my clients.

Table 1: A simple development case

Page 7 of 13RUP iteration planning

7/15/2004

Page 60: TheRationalEdge_July2004

Page 8 of 13RUP iteration planning

7/15/2004

Page 61: TheRationalEdge_July2004

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

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 won’t be hard once the development case is written.

But there are still a few final tips and thoughts I’d 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). I’ve tried to organize the tasks on the plan in chronological order, and I’ve tried organizing the tasks by discipline. These two approaches have different advantages and drawbacks.

Let’s 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 Project’s color palette) the colors of the RUP disciplines.

Conceive New Project

Knock-off tasks Purpose Role Average time

Established environment

New environment

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

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.

Project manager

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

Page 9 of 13RUP iteration planning

7/15/2004

Page 62: TheRationalEdge_July2004

Figure 6: Iteration plan organized chronologically

While you can’t 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

Page 10 of 13RUP iteration planning

7/15/2004

Page 63: TheRationalEdge_July2004

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

Page 11 of 13RUP iteration planning

7/15/2004

Page 64: TheRationalEdge_July2004

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 DON’T 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 PM’s 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.

Page 12 of 13RUP iteration planning

7/15/2004

Page 65: TheRationalEdge_July2004

Summary A well-written development case should show the project’s 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 doesn’t 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?

Comments?

Killer! (5) Good stuff (4) So-so; not bad (3) Needs work (2) Lame! (1)

Submit feedback developerWorks > Rational

About IBM | Privacy | Terms of use | Contact

Page 13 of 13RUP iteration planning

7/15/2004

Page 66: TheRationalEdge_July2004

Search for: within All of dW

Use + - ( ) " " Search help

IBM home | Products & services | Support & downloads | My account developerWorks > Rational

RUP work componentsKirti 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:

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. 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. 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.

Contents:What is a work component?Structure of a work componentRealizing a work componentSetting up a RUP project schedule using work componentsBenefits of work componentsAssessing project status using work components Developing organization-wide work components Estimating projects using work componentsWork components — in the industry nowNotes

About the authorRate this article

Subscriptions:dW newsletters

dW Subscription (CDs and downloads)

Page 1 of 10RUP work components

7/15/2004

© Copyright IBM Corporation 2004. http://www-106.ibm.com/developerworks/rational/library/5317.html

The Rational Edge--July 2004

Page 67: TheRationalEdge_July2004

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:

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.

PMO: So what are you doing in this plan? PM: We are detailing the requirements, plus building and testing a prototype. PMO: Hmm, I don't see all of that reflected here. PM: Let me explain. See the details in boldface under Analysis and Design, Implementation, and Test? Those are the prototype,

or summary, tasks. PMO: Then why don't you group them as such and bring this plan back to me?

Page 2 of 10RUP work components

7/15/2004

Page 68: TheRationalEdge_July2004

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

Page 3 of 10RUP work components

7/15/2004

Page 69: TheRationalEdge_July2004

products. Consider our example work component:

Work component: build architectural prototype

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.

Objective: To build an incremental, executable prototype that baselines the architecture.Owner: ArchitectResult: An incremental, executable prototype that baselines the architecture.

Page 4 of 10RUP work components

7/15/2004

Page 70: TheRationalEdge_July2004

Table 1: Essential parts for a RUP 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

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

Page 5 of 10RUP work components

7/15/2004

Page 71: TheRationalEdge_July2004

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."

Page 6 of 10RUP work components

7/15/2004

Page 72: TheRationalEdge_July2004

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. Create a coarse-grained project schedule. 2. Insert and customize work components for the current iteration. 3. 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.

Page 7 of 10RUP work components

7/15/2004

Page 73: TheRationalEdge_July2004

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:

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.

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.

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

Page 8 of 10RUP work components

7/15/2004

Page 74: TheRationalEdge_July2004

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:

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:

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,

Page 9 of 10RUP work components

7/15/2004

Page 75: TheRationalEdge_July2004

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 [email protected].

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 brand’s 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?

Comments?

Killer! (5) Good stuff (4) So-so; not bad (3) Needs work (2) Lame! (1)

Submit feedback developerWorks > Rational

About IBM | Privacy | Terms of use | Contact

Page 10 of 10RUP work components

7/15/2004

Page 76: TheRationalEdge_July2004

Search for: within All of dW

Use + - ( ) " " Search help

IBM home | Products & services | Support & downloads | My account developerWorks > Rational

Formally speaking: How to apply OCLGary Pollice Worcester Polytechnic Institute 14 Jul 2004

from The Rational Edge: 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.

If you were a computer science or software engineering major in college, you probably had to take a course in the foundations of computer science or formal methods. And if you did, you probably thought, “What will I ever use this for?”

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.

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 solid math education.2 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 Goguen’s 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.

Contents:What are formal methods?UML and OCLOCL as a specification languageTesters like it, tooConclusionReferencesNotes

About the authorRate this article

Subscriptions:dW newsletters

dW Subscription (CDs and downloads)

Page 1 of 6Formally speaking: How to apply OCL

7/15/2004

© Copyright IBM Corporation 2004 http://www-106.ibm.com/developerworks/rational/library/5390.html

The Rational Edge--July 2004

Page 77: TheRationalEdge_July2004

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, I’ve 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 I’m 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

Page 2 of 6Formally speaking: How to apply OCL

7/15/2004

Page 78: TheRationalEdge_July2004

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. Let’s 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 month’s 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. Let’s 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 let’s look a little closer. First of all, the specification is long because I’ve 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 I’ll 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

Page 3 of 6Formally speaking: How to apply OCL

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

Page 79: TheRationalEdge_July2004

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 let’s 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 client’s 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 it’s 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.

Let’s start looking at the use-case level of a system specification. If you are familiar with use cases, you know that they already have pre-condition 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

Page 4 of 6Formally speaking: How to apply OCL

7/15/2004

Page 80: TheRationalEdge_July2004

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 month’s 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 method’s 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:

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)

Page 5 of 6Formally speaking: How to apply OCL

7/15/2004

Page 81: TheRationalEdge_July2004

Joseph A. Goguen’s 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,” don’t 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?

Comments?

Killer! (5) Good stuff (4) So-so; not bad (3) Needs work (2) Lame! (1)

Submit feedback developerWorks > Rational

About IBM | Privacy | Terms of use | Contact

Page 6 of 6Formally speaking: How to apply OCL

7/15/2004

Page 82: TheRationalEdge_July2004

Search for: within All of dW

Use + - ( ) " " Search help

IBM home | Products & services | Support & downloads | My account developerWorks > Rational

Book review: Eric Meyer on CSS: Mastering the Language of Web DesignKerry McKay Worcester Polytechnic Institute 2 Jul 2004

from The Rational Edge: 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.

Eric A. Meyer New Riders, 2002 ISBN: 0-7357-1245-X Cover price: US$45.00 352 pages

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 world of a global style configuration with CSS. An external CSS file works just like a configuration file, defining the aesthetic attributes of a page. By defining style elements in a central location — either a separate file or at the beginning of an HTML document — you can more easily change the look of an element type without having to modify each instance of it.

The book's style is very casual and interactive, which makes it feel like direct guidance from a teacher rather than a formal, impersonal manual or how-to book. Meyer's discussions are also very detailed without being verbose, and he throws in the occasional (sometimes corny) joke. All the examples are straightforward and unambiguous; Meyer's instructions leave nothing to question.

Each of the book's thirteen chapters contains an independent project (see sidebar). Every project is a hands-on tool, carefully designed to give you everything you need to understand a particular task. At the beginning of each one, Meyer explicitly describes the point of the project. From there, he starts with a plain, basic file and progressively modifies the style sheet and HTML in small, easy-to-digest steps. The book highlights the code changes at each step and includes a browser snapshot as well. By the time you arrive at the end of a chapter, you know exactly what each line of code in the project's style sheet means and why it is there.

For those who like to play along at home, the book has a companion Web site (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

Contents:Notes

About the authorRate this article

Subscriptions:dW newsletters

dW Subscription (CDs and downloads)

Projects in Eric Meyer on CSS 1. Converting an existing page (stripping

a bloated HTML document down to a streamlined HTML file with accompanying CSS)

2. Styling a press release 3. Styling an events calendar 4. Bringing hyperlinks to life 5. How to skin a menu (adding effects to

make a menu attractive) 6. Styling for print 7. Making an input form look good 8. Creating an online greeting card 9. Creating a multicolumn layout

10. Sneaking out of the box (adding curves and acute/obtuse angles)

11. Positioning a better design (creating interesting page layouts without tables)

12. Fixing your backgrounds (creating cool, scrolling effects with fixed backgrounds)

13. Eric Meyer on CSS in CSS (recreating the book layout in a browser)

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

7/15/2004

© Copyright IBM Corporation 2004. http://www-106.ibm.com/developerworks/rational/library/5188.html

The Rational Edge--July 2004

Page 83: TheRationalEdge_July2004

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?

Comments?

Killer! (5) Good stuff (4) So-so; not bad (3) Needs work (2) Lame! (1)

Submit feedback developerWorks > Rational

About IBM | Privacy | Terms of use | Contact

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

7/15/2004

Page 84: TheRationalEdge_July2004

Search for: within All of dW

Use + - ( ) " " Search help

IBM home | Products & services | Support & downloads | My account developerWorks > Rational

Book excerpt: Absolute Java -- "Arrays” (Chapter 6*)15 Jul 2004

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.

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 book’s 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)

Contents:Rate this article

Subscriptions:dW newsletters

dW Subscription (CDs and downloads)

What do you think of this document?

Comments?

Killer! (5) Good stuff (4) So-so; not bad (3) Needs work (2) Lame! (1)

Submit feedback developerWorks > Rational

About IBM | Privacy | Terms of use | Contact

Page 1 of 1Book excerpt: Absolute Java -- "Arrays” (Chapter 6*)

7/15/2004

© Copyright IBM Corporation 2004. http://www-106.ibm.com/developerworks/rational/library/5419.html

The Rational Edge--July 2004

Page 85: TheRationalEdge_July2004

CHAPTER

6

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 359ANSWERS TO SELF-TEST EXERCISES 360PROGRAMMING PROJECTS 367

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

Page 86: TheRationalEdge_July2004

6

Arrays

Memory is necessary for all the operations of reason.

Blaise Pascal,

Pensées

INTRODUCTION

An

array

is a data structure used to process a collection of data that is all of thesame type, such as a list of numbers of type

double

or a list of strings. In thischapter 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 fromSection 4.1 is to have some idea of what an object is and what an instancevariable is.

The remaining sections require Chapters 1 through 5 with the exceptionthat Section 5.4 on packages and

javadoc

is not required.

Introduction to Arrays

It is a capital mistake to theorizebefore 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 performssome manipulations on these scores. For instance, the program might com-pute the highest test score and then output the amount by which each scorefalls short of the highest. The highest score is not known until all five scoresare read in. Hence, all five scores must be retained in storage so that after thehighest score is computed each score can be compared to it. To retain the fivescores, we will need something equivalent to five variables of type

int

. Wecould use five individual variables of type

int

, but keeping track of five vari-ables is hard, and we may later want to change our program to handle 100scores; certainly, keeping track of 100 variables is impractical. An array is theperfect solution. An array

behaves like a list of variables with a uniform nam-ing mechanism that can be declared in a single line of simple code. For exam-ple, the names for the five individual variables we need might be

score[0]

,

6.1

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

Page 87: TheRationalEdge_July2004

Introduction to Arrays 307

score[1]

,

score[2]

,

score[3]

, and

score[4]

. The part that does not change, in thiscase

score

, is the name of the array. The part that can change is the integer in thesquare brackets

[]

.

■ CREATING AND ACCESSING ARRAYS

In Java, an array is a special kind of object, but it is often more useful to think of anarray as a collection of variables all of the same type. For example, an array that behaveslike 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 ofdifferent ways. We will call them indexed variables

, though they are also sometimescalled subscripted variables

or elements

of the array. The number in square brackets iscalled an index

or a subscript

. In Java,

indices are numbered starting with

0

, not

startingwith

1

or any number other than

0

. The number of indexed variables in an array is calledthe length

or size

of the array. When an array is created, the length of the array is givenin square brackets after the array name. The indexed variables are then numbered (alsousing square brackets) starting with

0

and ending with the integer that is

one less thanthe length of the array.

The following

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[]

. Thesecond statement creates an array with five indexed variables of type

double

and makesthe variable

score

a name for the array. You may use any expression that evaluates to anonnegative

int

value in place of the

5

in square brackets. In particular you can fill avariable with a value read from the keyboard and use the variable in place of the

5

. Inthis 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 sametype. This type is called the base type

of the array. In our example, the base type of thearray

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 arraycan be any type. In particular it can be a class type.

indexed variablesubscripted variable

index, subscript

size, length

base type

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

Page 88: TheRationalEdge_July2004

308 Chapter 6 Arrays

Each of the five indexed variables of our example array

score

can be used just likeany 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 plainold variables of type

double

. That number in square brackets is part of the indexed vari-able’s name. So, your program can compute the name of one of these variables. Insteadof writing an integer constant in the square brackets, you can use any expression thatevaluates 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 usingany square brackets).

The program in Display 6.1 shows an example of using our sample array

score

asfive indexed variables, all of type

double

.

Note that the program can compute the name of an indexed variable by using a vari-able 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]));

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.

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

Page 89: TheRationalEdge_July2004

Introduction to Arrays 309

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

1 import java.io.BufferedReader;2 import java.io.InputStreamReader;3 import java.io.IOException;

4 public class ArrayOfScores5 {6 /**7 Reads in 5 scores and shows how much each8 score differs from the highest score.9 */

10 public static void main(String[] args) throws IOException11 {12 BufferedReader keyboard = 13 new BufferedReader(new InputStreamReader(System.in));14 double[] score = new double[5];15 int index;16 double max;17 String inputLine;

18 System.out.println("Enter 5 scores, one per line:");19 score[0] = stringToDouble(keyboard.readLine());20 max = score[0];21 for (index = 1; index < 5; index++)22 {23 score[index] = stringToDouble(keyboard.readLine());24 if (score[index] > max)25 max = score[index];26 //max is the largest of the values score[0],..., score[index].27 }

28 System.out.println("The highest score is " + max);29 System.out.println("The scores are:");30 for (index = 0; index < 5; index++)31 System.out.println(score[index] + " differs from max by " 32 + (max − score[index])); 33 }34 private static double stringToDouble(String stringObject)35 {36 return Double.parseDouble(stringObject.trim());37 }38 }

This form of input is covered in Chapter 2, Section 2.3.

The methods parseDouble and trim are discussed in Chapter 5 in the subsection entitled “Wrapper Classes.”

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

Page 90: TheRationalEdge_July2004

310 Chapter 6 Arrays

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 thefollowing:

double[] score;

Second, the square brackets can be used with an integer value as part of the specialsyntax 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 asscore[0] or score[3], as illustrated by the following line:

max = score[0];

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

SAMPLE DIALOGUE

Enter 5 scores, one per line:8099.97510085.5The highest score is 100The scores are:80.0 differs from max by 2099.9 differs from max by 0.175.0 differs from max by 25100.0 differs from max by 0.085.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:

0 1 2 3 4

80 99.9 75 100 85.5

The array scorescore[3]

Indices

squarebrackets []

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

Page 91: TheRationalEdge_July2004

Introduction to Arrays 311

As we mentioned previously, the integer inside the square brackets can be anyexpression 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 sameindexed 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 haveinstance variables. As it turns out, an array has only one public instance variable, whichis named length. The instance variable length is automatically set to the size of thearray 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 replacingan unnamed constant, such as 5, whose meaning may not be obvious, with a meaning-ful name like score.length. In Display 6.2 we have rewritten the program in Display6.1 using the length instance variable.

The length instance variable cannot be changed by your program (other than bycreating a new array with another use of new).1 For example, the following is illegal:

score.length = 10;//Illegal

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

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.

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

Page 92: TheRationalEdge_July2004

312 Chapter 6 Arrays

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.

Display 6.2 The length Instance Variable

1 import java.io.BufferedReader;2 import java.io.InputStreamReader;3 import java.io.IOException;

4 public class ArrayOfScores25 {6 /**7 Reads in 5 scores and shows how much each8 score differs from the highest score.9 */

10 public static void main(String[] args) throws IOException11 {12 BufferedReader keyboard = 13 new BufferedReader(new InputStreamReader(System.in));14 double[] score = new double[5];15 int index;16 double max;17 String inputLine;

18 System.out.println("Enter " + score.length + " scores, one per line:");19 score[0] = stringToDouble(keyboard.readLine());20 max = score[0];21 for (index = 1; index < score.length; index++)22 {23 score[index] = stringToDouble(keyboard.readLine());24 if (score[index] > max)25 max = score[index];26 //max is the largest of the values score[0],..., score[index].27 }

28 System.out.println("The highest score is " + max);29 System.out.println("The scores are:");30 for (index = 0; index < score.length; index++)31 System.out.println(score[index] + " differs from max by " 32 + (max − score[index]));33 }34 }

This class also contains the method stringToDouble, even though it is not shown. The method stringToDouble is defined in Display 6.1.

The sample dialog is the same as in Display 6.1.

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

Page 93: TheRationalEdge_July2004

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 pro-cesses 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 valuesfor 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 oper-ator. 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 discussexceptions in Chapter 9. Until you learn about handling exceptions, exceptions will simplyappear as error conditions to you.

illegal array index

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

Page 94: TheRationalEdge_July2004

314 Chapter 6 Arrays

If you do not initialize the elements of an array, they will automatically be initializedto a default value for the base type. The default values are the usual ones. For numerictypes the default value is the zero of the type. (For base type char the default value is thenonprintable zeroth character (char)0, not the space character.) For the type booleanthe default value is false. For class types, the default value is null. For example, if youdo 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]);

automatic initialization

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

Page 95: TheRationalEdge_July2004

Introduction to Arrays 315

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 A 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 fol-lowing 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.

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

Page 96: TheRationalEdge_July2004

316 Chapter 6 Arrays

Arrays and ReferencesA little more than kin, and less than kind.

William Shakespeare, Hamlet

Just like a variable of one of the class types you’ve seen, a variable of an array type holdsa reference. In this section we explore the consequences of this fact, including a discus-sion of array parameters. We will see that arrays are objects and that array types can beconsidered class types, but somewhat different kinds of class types. Arrays and thekinds of classes we’ve seen before this chapter are a little more than kin, and less thankind.

■ ARRAYS ARE OBJECTS

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

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

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

Page 97: TheRationalEdge_July2004

Arrays and References 317

An array can be viewed as a single item whose value is a collection of values of thebase type. An array variable (as opposed to an array indexed variable) names the array asa 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 assignmentstatement places a reference to (the memory address of ) this array object in the vari-able 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 classtype. In Java, an array is considered an object. Whenever Java documentation says thatsomething applies to objects, that means that it applies to arrays as well as objects of theclass types we’ve seen up to now. You will eventually see examples of methods that cantake arguments that may be objects of any kind. These methods will accept arrayobjects as arguments as well as objects of an ordinary class type. Arrays are somewhatpeculiar in how they relate to classes. Some authorities say array types are not classesand some authorities say they are classes. But, all authorities agree that the arrays them-selves are objects. Given that arrays are objects, it seems that one should view arraytypes 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 thefollowing syntax:

double a = new double[10];

You can view the expression new double[10] as an invocation of a constructor that usesa nonstandard syntax. (The nonstandard syntax was used to be consistent with the syn-tax used for arrays in older programming languages.)

As we have already seen, every array has an instance variable named length, which isa good example of viewing an array as an object. As with any other class type, arrayvariables contain memory addresses, or, as they are usually called in Java, references. Soarray types are reference types.3

Since an array is an object, you might be tempted to think of the indexed variablesof 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 arein Java. So, this detail about arrays is not peculiar to Java.

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

Page 98: TheRationalEdge_July2004

318 Chapter 6 Arrays

This is actually a pretty good analogy, but it is not literally true. Indexed variables arenot instance variables of the array. Indexed variables are a special kind of variable pecu-liar 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 isan object that can be assigned with the assignment operator and plugged in for aparameter of an array type. Since an array type is a reference type, the behaviors ofarrays with respect to assignment =, ==, and parameter passing mechanisms are thesame as what we have already described for classes. In the next few subsections we dis-cuss 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], ..., holi-datList[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 vari-ables 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 318 Friday, November 14, 2003 6:18 AM

Page 99: TheRationalEdge_July2004

Arrays and References 319

■ 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 variablesas arguments to methods.

An indexed variable can be an argument to a method in exactly the same way thatany variable of the array base type can be an argument. For example, suppose a pro-gram contains the following declarations:

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, thefollowing is equally legal:

myMethod(a[3]);

There is one subtlety that does apply to indexed variables used as arguments. Forexample, 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 is0, then this call is equivalent to the following:

myMethod(a[0]);

The indexed expression is evaluated to determine exactly which indexed variable isgiven as the argument.

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

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.

indexed variable arguments

entire array parameters

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

Page 100: TheRationalEdge_July2004

320 Chapter 6 Arrays

form Base_Type[], so this is how you specify a parameter type for an entire array, Forexample, the method doubleArrayElements, given in what follows, will accept anyarray 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 thefollowing 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 toa method.

An array type is a reference type just as a class type is, so, as with a class type argu-ment, 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 infor the parameter, but it does not specify the length of the array. An array knows its

ARRAY INDEXED VARIABLES AS ARGUMENTS

An array indexed variable can be used as an argument anyplace that a variable of the array’s 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.

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

Page 101: TheRationalEdge_July2004

Arrays and References 321

length and stores it in the length instance variable. The same array parameter can bereplaced with array arguments of different lengths. Note that the preceding methoddoubleArrayElements 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 val-ues 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);

length of array arguments

Note that arrays a and b have different lengths. Also note that no square brackets are used with array arguments.

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

Page 102: TheRationalEdge_July2004

322 Chapter 6 Arrays

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 322 Friday, November 14, 2003 6:18 AM

Page 103: TheRationalEdge_July2004

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:

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.0a[2] = 42.0 b[2] = 42.0

The assignment statement b = a; copies the memory address from a to b so that the array vari-able 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 computer’s memory. For example, consider the following code:

int[] c = new int[10];int[] d = new int[10];

assignmentwith arrays

==with arrays

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

Page 104: TheRationalEdge_July2004

324 Chapter 6 Arrays

int i;for (i = 0; i < c.length; i++) c[i] = i;for (i = 0; i < d.length; i++) d[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 public class DifferentEquals2 {3 /**4 A demonstration to see how == and an equalArrays method are different.5 */6 public static void main(String[] args)7 {8 int[] c = new int[10];9 int[] d = new int[10];

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

13 for (i = 0; i < d.length; i++)14 d[i] = i;

The arrays c and d contain the same integers in each index position.

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

Page 105: TheRationalEdge_July2004

Arrays and References 325

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

15 if (c == d)16 System.out.println("c and d are equal by ==.");17 else18 System.out.println("c and d are not equal by ==."); 19 System.out.println("== only tests memory addresses.");

20 if (equalArrays(c, d))21 System.out.println(22 "c and d are equal by the equalArrays method.");23 else24 System.out.println(25 "c and d are not equal by the equalArrays method.");

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

28 }

29 public static boolean equalArrays(int[] a, int[] b)30 {31 if (a.length != b.length)32 return false;33 else34 {35 int i = 0;36 while (i < a.length)37 {38 if (a[i] != b[i])39 return false;40 i++;41 }42 } 43 return true;44 } 45 }

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.

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

Page 106: TheRationalEdge_July2004

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 anarray 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, itcould be replaced by any other non-keyword identifier. The identifier args is tradi-tional, but it is perfectly legal to use some other identifier.

We have never given main an array argument, or any other kind of argument, whenwe 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 ofstrings is automatically provided as a default argument to main when you run yourprogram.

It is possible to run a Java program in a way that provides an argument to plug in forthis array of String parameters. You do not provide it as an array. You provide anynumber of string arguments when you run the program, and those string argumentswill 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 run-ning 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.lengthto 3. These three indexed variables can be used in the method main, as in the followingsample 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 typeor types.

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

Page 107: TheRationalEdge_July2004

Arrays and References 327

■ METHODS THAT RETURN AN ARRAY

In Java, a method may return an array. You specify the return type for a method thatreturns an array in the same way that you specify a type for an array parameter. Forexample, 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;}

THE METHOD main HAS AN 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.

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 327 Friday, November 14, 2003 6:18 AM

Page 108: TheRationalEdge_July2004

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 328 Friday, November 14, 2003 6:18 AM

Page 109: TheRationalEdge_July2004

Programming with Arrays 329

Programming with ArraysNever trust to general impressions, my boybut 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 classinstance variables.

■ PARTIALLY FILLED ARRAYS

Often the exact size needed for an array is not known when a program is written or thesize may vary from one run of the program to another. One common and easy way tohandle this situation is to declare the array to be of the largest size the program could pos-sibly 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 muchof the array is used and must not reference any indexed variable that has not been givena meaningful value. The program in Display 6.4 illustrates this point. The programreads 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 anylength in between. The scores are stored in the array score, which has 10 indexed variables,

6.3

partially filled array

Display 6.4 Partially Filled Array (Part 1 of 4)

1 import java.io.BufferedReader;2 import java.io.InputStreamReader;3 import java.io.IOException;

4 public class GolfScores5 {6 public static final int MAX_NUMBER_SCORES = 10;

7 /**8 Shows differences between each of a list of golf scores and their average.9 */

10 public static void main(String[] args) throws IOException11 {12 double[] score = new double[MAX_NUMBER_SCORES];13 int numberUsed = 0;

14 System.out.println("This program reads golf scores and shows");15 System.out.println("how much each differs from the average.");

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.)

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

Page 110: TheRationalEdge_July2004

330 Chapter 6 Arrays

Display 6.4 Partially Filled Array (Part 2 of 4)

16 System.out.println("Enter golf scores:");17 numberUsed = fillArray(score);18 showDifference(score, numberUsed);19 }

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

30 double next;31 int index = 0;32 next = stringToDouble(keyboard.readLine());33 while ((next >= 0) && (index < a.length))34 {35 a[index] = next;36 index++;37 next = stringToDouble(keyboard.readLine());38 //index is the number of array indexed variables used so far.39 }40 //index is the total number of array indexed variables used.

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

44 return index;45 }

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

The value of index is the number of values stored in the array.

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

Page 111: TheRationalEdge_July2004

Programming with Arrays 331

Display 6.4 Partially Filled Array (Part 3 of 4)

51 public static double computeAverage(double[] a, int numberUsed)52 {53 double total = 0;54 for (int index = 0; index < numberUsed; index++)55 total = total + a[index];56 if (numberUsed > 0)57 {58 return (total/numberUsed);59 }60 else61 {62 System.out.println("ERROR: Trying to average 0 numbers.");63 System.out.println("computeAverage returns 0.");64 return 0;65 }66 }

67 private static double stringToDouble(String stringObject)68 {69 return Double.parseDouble(stringObject.trim());70 }

71 /**72 Precondition: numberUsed <= a.length.73 The first numberUsed indexed variables of a have values.74 Postcondition: Gives screen output showing how much each of the first75 numberUsed elements of the array a differ from their average.76 */77 public static void showDifference(double[] a, int numberUsed)78 {79 double average = computeAverage(a, numberUsed);80 System.out.println("Average of the " + numberUsed81 + " scores = " + average);82 System.out.println("The scores are:");83 for (int index = 0; index < numberUsed; index++)84 System.out.println(a[index] + " differs from average by "85 + (a[index] − average));86 }87 }

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

Page 112: TheRationalEdge_July2004

332 Chapter 6 Arrays

but the program uses only as much of the array as it needs. The variable numberUsedkeeps track of how many elements are stored in the array. The elements (that is, thescores) are stored in positions score[0] through score[numberUsed − 1]. The detailsare very similar to what they would be if numberUsed were score.length and the entirearray were used. Note that the variable numberUsed usually must be an argument to anymethod that manipulates the partially filled array. For example, the methods showDif-ference and computeAverage use the argument numberUsed to ensure that only mean-ingful array indices are used.

Self-Test Exercises

13. Complete the definition of the following method that could be added to the class Golf-Scores 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.

Display 6.4 Partially Filled Array (Part 4 of 4)

SAMPLE DIALOGUE

This program reads golf scores and showshow 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.697468-1Average of the 3 scores = 70.3333The scores are:69.0 differs from average by −1.3333374.0 differs from average by 3.6666768.0 differs from average by −2.33333

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

Page 113: TheRationalEdge_July2004

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 exam-ple, 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 com-puteAverage 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 333 Friday, November 14, 2003 6:18 AM

Page 114: TheRationalEdge_July2004

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 Class for a partially filled array of doubles. The class enforces the 3 following invariant: All elements are at the beginning of the array in4 locations 0, 1, 2, and so forth up to a highest index with no gaps.5 */6 public class PartiallyFilledArray7 {8 private int maxNumberElements; //Same as a.length9 private double[] a;

10 private int numberUsed; //Number of indices currently in use

11 /**12 Sets the maximum number of allowable elements to 10.13 */14 PartiallyFilledArray()15 {16 maxNumberElements = 10;17 a = new double[maxNumberElements];18 numberUsed = 0;19 }

20 /**21 Precondition arraySize > 0.22 */23 PartiallyFilledArray(int arraySize)24 {25 if (arraySize <= 0)26 {27 System.out.println("Error Array size zero or negative.");28 System.exit(0);29 }30 maxNumberElements = arraySize;31 a = new double[maxNumberElements];32 numberUsed = 0;33 }

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

Page 115: TheRationalEdge_July2004

Programming with Arrays 335

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

34 PartiallyFilledArray(PartiallyFilledArray original)35 {36 if (original == null)37 {38 System.out.println("Fatal Error: aborting program.");39 System.exit(0);40 }41 maxNumberElements = 42 original.maxNumberElements;43 numberUsed = original.numberUsed;44 a = new double[maxNumberElements];45 for (int i = 0; i < numberUsed; i++)46 a[i] = original.a[i];47 }

48 /**49 Adds newElement to the first unused array position.50 */51 public void add(double newElement)52 {53 if (numberUsed >= a.length)54 {55 System.out.println("Error: Adding to a full array.");56 System.exit(0);57 }58 else59 {60 a[numberUsed] = newElement;61 numberUsed++;62 }63 }

64 public double getElement(int index)65 {66 if (index < 0 || index >= numberUsed)67 {68 System.out.println("Error:Illegal or unused index.");69 System.exit(0);70 }

71 return a[index];72 }

Note that the instance variable a is a copy of orignal.a. The following would not be correct:a = original.a;This point is discussed in the subsection entitled “Privacy Leaks with Array Instance Variables.”

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

Page 116: TheRationalEdge_July2004

336 Chapter 6 Arrays

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

73 /**74 index must be an index in use or the first unused index.75 */76 public void resetElement(int index, double newValue)77 {78 if (index < 0 || index >= maxNumberElements)79 {80 System.out.println("Error:Illegal index.");81 System.exit(0);82 }83 else if (index > numberUsed)84 {85 System.out.println(86 "Error: Changing an index that is too large.");87 System.exit(0);88 }89 else90 a[index] = newValue;91 }

92 public void deleteLast()93 {94 if (empty())95 {96 System.out.println("Error:Deleting from an empty array.");97 System.exit(0);98 }99 else

100 numberUsed−−;101 }

102 /**103 Deletes the element in position index. Moves down all elements with104 indices higher than the deleted element.105 */106 public void delete(int index)107 {108 if (index < 0 || index >= numberUsed)109 {110 System.out.println("Error:Illegal or unused index.");111 System.exit(0);112 }

113 for (int i = index; i < numberUsed; i++)114 a[i] = a[i + 1];115 numberUsed−−;116 }

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

Page 117: TheRationalEdge_July2004

Programming with Arrays 337

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

117 public boolean empty()118 {119 return (numberUsed == 0);120 }

121 public boolean full()122 {123 return (numberUsed == maxNumberElements);124 }

125 public int getMaxCapacity()126 {127 return maxNumberElements;128 }129130 public int getNumberOfElements()131 {132 return numberUsed;133 }134 }

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

1 import java.io.BufferedReader;2 import java.io.InputStreamReader;3 import java.io.IOException;

4 /**5 Demonstrates Using the class PartiallyFilledArray,6 */7 public class GolfScoresVersion28 {

9 public static final int MAX_NUMBER_SCORES = 10;

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

Sample dialog is the same as in Display 6.4.

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

Page 118: TheRationalEdge_July2004

338 Chapter 6 Arrays

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

17 System.out.println("This program reads golf scores and shows");18 System.out.println("how much each differs from the average.");

19 System.out.println("Enter golf scores:");20 fillArray(score);21 showDifference(score);22 }

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

33 double next = stringToDouble(keyboard.readLine());34 while ((next >= 0) && (!a.full()))35 {36 a.add(next);37 next = stringToDouble(keyboard.readLine());38 }

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

43 private static double stringToDouble(String stringObject)44 {45 return Double.parseDouble(stringObject.trim());46 }

47 /**48 Returns the average of numbers in the PartiallyFilledArray a.49 */50 public static double computeAverage(PartiallyFilledArray a)51 {52 double total = 0;53 for (int index = 0; index < a.getNumberOfElements(); index++)54 total = total + a.getElement(index);

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

Page 119: TheRationalEdge_July2004

Programming with Arrays 339

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.

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

55 if (a.getNumberOfElements() > 0)56 {57 return (total/a.getNumberOfElements());58 }59 else60 {61 System.out.println("ERROR: Trying to average 0 numbers.");62 System.out.println("computeAverage returns 0.");63 return 0;64 }65 }

66 /**67 Gives screen output showing how much each of the68 elements in the PartiallyFilledArray a differ from the average.69 */70 public static void showDifference(PartiallyFilledArray a)71 {72 double average = computeAverage(a);73 System.out.println("Average of the " + a.getNumberOfElements()74 + " scores = " + average);75 System.out.println("The scores are:");76 for (int index = 0; index < a.getNumberOfElements(); index++)77 System.out.println(a.getElement(index) + " differs from average by "78 + (a.getElement(index) − average));79 }

80 }

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

Page 120: TheRationalEdge_July2004

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 acces-sor (or other method) that returns a reference to a private mutable object. As we notedthere, an accessor method should instead return a reference to a deep copy of the privateobject. (See the Pitfall subsection of Chapter 5 entitled “Privacy Leaks.”) At the time wehad in mind returning the contents of a private instance variable of a class type. How-ever, 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 classPartiallyFilledArray in Display 6.5. You might be tempted to define the accessormethod as follows:

public double[] getInsideArray()// Problematic version{ return a;}

As indicated in the comment, this definition has a problem. The problem is that thisaccessor method allows a programmer to change the array object named by the privateinstance variable a in ways that bypass the checks built into the mutator methods of theclass PartiallyFilledArray. To see why this is true suppose we had added this definitionof the method getInsideArray to the class PartiallyFilledArray, and consider the fol-lowing code:

PartiallyFilledArray leakyArray = new PartiallyFilledArray(10);double[] arrayName = leakyArray.getInsideArray();

The variable arrayName and the private instance variable a now contain the same refer-ence, so both arrayName and the private instance variable a name the same array. UsingarrayName as a name for the array named by the private instance variable a, we can nowfill the indexed variables of a in any order and need not fill the array starting at the firstelement. This violates the spirit of the private modifier for the array instance variablea. For this reason, the accessor method getInsideArray should return a deep copy ofthe array named by the private instance variable a. A safe definition of getInsideArrayis 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 340 Friday, November 14, 2003 6:18 AM

Page 121: TheRationalEdge_July2004

Programming with Arrays 341

If a private instance variable is an array type that has a class as its base type, then youneed to be sure to make copies of the class objects in the array when you make a copyof 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 copyconstructor 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 isalso illustrated by the copy constructor in Display 6.5.

Display 6.7 Accessor Method for an Array Instance Variable

1 /**2 Demonstrates the correct way to define an accessor 3 method to a private array of class objects.4 */5 public class ToyExample6 {7 private Date[] a;

8 public ToyExample(int arraySize)9 {

10 a = new Date[arraySize];11 for (int i = 0; i < arraySize; i++)12 a[i] = new Date();13 }

14 public ToyExample(ToyExample object)15 {16 int lengthOfArrays = object.a.length;17 this.a = new Date[lengthOfArrays];18 for (int i = 0; i < lengthOfArrays; i++)19 this.a[i] = new Date(object.a[i]);20 }

21 public Date[] getDateArray()22 {23 Date[] temp = new Date[a.length];24 for (int i = 0; i < a.length; i++)25 temp[i] = new Date(a[i]);26 return temp;27 } <There presumably are other methods that are not shown, but they are irrelevant to the point at hand.>

28 }

The class Date is defined in Display 4.11, but you do not need to know the details of the definition to understand the point of this example.

Copy constructor for Date

Copy constructor for Date

Copy constructor for ToyExample

Accessor method

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

Page 122: TheRationalEdge_July2004

342 Chapter 6 Arrays

■ A PREVIEW OF VECTORS

Java and many other programming languages have objects known as vectors, which arevery 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 Partial-lyFilledArray 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 PartialyFilledAr-ray. 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 Partially-FilledArray 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 newCa-pacity 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 newCapac-ity 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]

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

selection sort

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

Page 123: TheRationalEdge_July2004

Programming with Arrays 343

One way to design an algorithm is to rely on the definition of the problem. In this case the prob-lem 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 ele-ment is illustrated in the fourth and fifth array pictures in Display 6.8. The algorithm then posi-tions 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 add-ing 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.

indexOf-Smallest

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

Page 124: TheRationalEdge_July2004

344 Chapter 6 Arrays

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?

Display 6.8 Selection Sort

.

.

.

a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9]

8 6 11 17 3 15 5 19 28 12

8 6 11 17 3 15 5 19 28 12

3 6 11 17 8 15 5 19 28 12

3 6 11 17 8 15 5 19 28 12

3 5 11 17 8 15 6 19 28 12

3 5 6 8 11 12 15 17 19 28

Unsorted array

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

Page 125: TheRationalEdge_July2004

Programming with Arrays 345

Display 6.9 Selection Sort Class (Part 1 of 2)

1 public class SelectionSort2 {3 /**4 Precondition: numberUsed <= a.length;5 The first numberUsed indexed variables have values.6 Action: Sorts a so that a[0] <= a[1] <= ... <= a[numberUsed - 1].7 */8 public static void sort(double[] a, int numberUsed)9 {

10 int index, indexOfNextSmallest;11 for (index = 0; index < numberUsed − 1; index++)12 {//Place the correct value in a[index]:13 indexOfNextSmallest = indexOfSmallest(index, a, numberUsed);14 interchange(index,indexOfNextSmallest, a);15 //a[0] <= a[1] <=...<= a[index] and these are the smallest16 //of the original array elements. The remaining positions17 //contain the rest of the original array elements.18 }19 }

20 /**21 Returns the index of the smallest value among22 a[startIndex], a[startIndex+1], ... a[numberUsed - 1]23 */24 private static int indexOfSmallest(int startIndex,25 double[] a, int numberUsed)26 {27 double min = a[startIndex];28 int indexOfMin = startIndex;29 int index;30 for (index = startIndex + 1; index < numberUsed; index++)31 if (a[index] < min)32 {33 min = a[index];34 indexOfMin = index;35 //min is smallest of a[startIndex] through a[index]36 }37 return indexOfMin;38 }

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

Page 126: TheRationalEdge_July2004

346 Chapter 6 Arrays

Multidimensional ArraysTwo indices are better than one.

Anonymous

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

■ MULTIDIMENSIONAL ARRAY BASICS

It is sometimes useful to have an array with more than one index, and this is allowed inJava. The following creates an array of characters called page. The array page has twoindices: 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. Notethat each index must be enclosed in its own set of square brackets. As was true of theone-dimensional arrays we have already seen, each indexed variable for a multidimen-sional array is a variable of the base type, in this case the type char.

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

array declarationsindexed variables

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

Page 127: TheRationalEdge_July2004

Multidimensional Arrays 347

An array may have any number of indices, but perhaps the most common numberof indices is two. A two-dimensional array can be visualized as a two-dimensional dis-play with the first index giving the row and the second index giving the column. Forexample, the array indexed variables of the two-dimensional array a declared and cre-ated as

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

can be visualized as follows:

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

Display 6.10 Demonstration of the SelectionSort Class

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

6 System.out.println("Array contents before sorting:");7 int i;8 for (i = 0; i < b.length; i++)9 System.out.print(b[i] + " ");

10 System.out.println();11 12 SelectionSort.sort(b, b.length);

13 System.out.println("Sorted array values:");14 for (i = 0; i < b.length; i++)15 System.out.print(b[i] + " ");16 System.out.println();17 }18 }

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.0Sorted array values:3.0 4.4 5.5 7.7 11.0 13.0 14.0 16.0 20.0 42.0

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

Page 128: TheRationalEdge_July2004

348 Chapter 6 Arrays

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

In Java, a two-dimensional array, such as a, is actually an array of arrays. The abovearray a is actually a one-dimensional array of size 5, whose base type is a one-dimensionalarray of characters of size 12. This is diagrammed in Display 6.11. As shown in that dis-play, the array variable a contains a reference to a one-dimensional array of length 5 andwith a base type of char[]; that is, the base type of a is the type for an entire one-dimensional array of characters. Each indexed variable a[0], a[1], and so forth con-tains a reference to a one-dimensional array of characters.

A three-dimensional array is an array of arrays of arrays, and so forth for higherdimensions.

Normally, the fact that a two-dimensional array is an array of arrays need not con-cern 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 thinkof a two-dimensional array as an array of arrays.

DECLARING AND CREATING A 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.

Amultidimensional

array is anarray of arrays

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

Page 129: TheRationalEdge_July2004

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.

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 upona timethere werethree littleprogrammers.

a[0]

a[1]

a[2]

a[3]

a[4]

a

0 1 2 3 4 5 6 7 8 9 10 11

O n c e u p o n

a t i m e

t h e r e w e r e

t h r e e l i t t l e

p r o g r a m m e r s .

Blank entries contain the space (blank) character.

a[1][2]

We will see that these can and should be replaced with expressions involving the length instance variable.

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

Page 130: TheRationalEdge_July2004

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';

Let’s analyze this nested for loop in a bit more detail. The array page is actually aone-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 lengthof 100. That is why the first for loop is terminated using page.length. For a two-dimensional array like page, the value of length is the number of first indices or, equiv-alently, the number of rows—in this case, 30. Now let’s 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 arrayof chars, and it has page[row].length entries. That is why the inner for loop is terminatedusing page[row].length. Of course, in this case, page[0].length, page[1].length, and soforth through to page[29].length are all equal and all equal to 100. (If you read theoptional 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 350 Friday, November 14, 2003 6:18 AM

Page 131: TheRationalEdge_July2004

Multidimensional Arrays 351

■ RAGGED ARRAYS ✜

There is no need for each row in a two-dimensional array to have the same number ofentries. Different rows can have different numbers of columns. These sorts of arrays arecalled ragged arrays.

To help explain the details, let’s start with an ordinary, nonragged two-dimensionalarray, 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 ofdoubles that can be of any length. The next three lines each create an array of doublesof length 5 to be named by a[0], a[1], and a[2]. The net result is a two-dimensionalarray 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 fol-lowing 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];

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);

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

Page 132: TheRationalEdge_July2004

352 Chapter 6 Arrays

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

■ MULTIDIMENSIONAL ARRAY PARAMETERS AND RETURNED VALUES

Methods may have multidimensional array parameters and may have a multidimen-sional array type as the type for the value returned. The situation is similar to that ofthe one-dimensional case, except that you use more square brackets when specifyingthe type name. For example, the following method will display a two-dimensionalarray 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(); }}

If you want to return a multidimensional array, you use the same kind of type spec-ification as you use for a multidimensional array parameter. For example, the followingmethod 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;}

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

array arguments

returning an array

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

Page 133: TheRationalEdge_July2004

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 stu-dentAverage 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 stu-dent 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 illus-trates 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, deter-mine 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 stu-dentAverage 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 no-argument 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 353 Friday, November 14, 2003 6:18 AM

Page 134: TheRationalEdge_July2004

354 Chapter 6 Arrays

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

1 import java.io.BufferedReader;2 import java.io.InputStreamReader;3 import java.io.IOException;

4 public class GradeBook5 {

6 private int numberOfStudents; // Same as studentAverage.length.7 private int numberOfQuizzes; // Same as quizeAverage.length.

8 private int[][] grade; //numberOfStudents rows and numberOfQuizzes columns.9 private double[] studentAverage;

10 private double[] quizAverage;

11 public GradeBook(int[][] a)12 {13 if (a.length == 0 || a[0].length == 0)14 {15 System.out.println("Empty grade records. Aborting.");16 System.exit(0);17 }

18 numberOfStudents = a.length;19 numberOfQuizzes = a[0].length;20 fillGrade(a);21 fillStudentAverage();22 fillQuizAverage();23 }

24 public GradeBook(GradeBook book)25 {26 numberOfStudents = book.numberOfStudents;27 numberOfQuizzes = book.numberOfQuizzes;28 fillGrade(book.grade);29 fillStudentAverage();30 fillQuizAverage();31 } 32 public GradeBook() throws IOException33 {34 BufferedReader keyboard = new BufferedReader(35 new InputStreamReader(System.in));

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

Page 135: TheRationalEdge_July2004

Multidimensional Arrays 355

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

36 System.out.println("Enter number of students:");37 numberOfStudents = stringToInt(keyboard.readLine());

38 System.out.println("Enter number of quizzes:");39 numberOfQuizzes = stringToInt(keyboard.readLine());

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

41 for (int studentNumber = 1; 42 studentNumber <= numberOfStudents; studentNumber++)43 for (int quizNumber = 1; 44 quizNumber <= numberOfQuizzes; quizNumber++)45 {46 System.out.println("Enter score for student number "47 + studentNumber);48 System.out.println("on quiz number " + quizNumber);49 grade[studentNumber − 1][quizNumber − 1] =50 stringToInt(keyboard.readLine());51 }

52 fillStudentAverage();53 fillQuizAverage();54 }

55 private static int stringToInt(String stringObject)56 {57 return Integer.parseInt(stringObject.trim());58 }

59 private void fillGrade(int[][] a)60 {61 grade = new int[numberOfStudents][numberOfQuizzes];

62 for (int studentNumber = 1; 63 studentNumber <= numberOfStudents; studentNumber++)64 {65 for (int quizNumber = 1; 66 quizNumber <= numberOfQuizzes; quizNumber++)67 grade[studentNumber][quizNumber] = 68 a[studentNumber][quizNumber];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.

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

Page 136: TheRationalEdge_July2004

356 Chapter 6 Arrays

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

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

77 for (int studentNumber = 1; 78 studentNumber <= numberOfStudents; studentNumber++)79 {//Process one studentNumber:80 double sum = 0;81 for (int quizNumber = 1; 82 quizNumber <= numberOfQuizzes; quizNumber++)83 sum = sum + grade[studentNumber − 1][quizNumber − 1];84 //sum contains the sum of the quiz scores for student number studentNumber.85 studentAverage[studentNumber − 1] = sum/numberOfQuizzes;86 //Average for student studentNumber is studentAverage[studentNumber − 1]87 }88 }

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

95 for (int quizNumber = 1; quizNumber <= numberOfQuizzes; quizNumber++)96 {//Process one quiz (for all students):97 double sum = 0;98 for (int studentNumber = 1; 99 studentNumber <= numberOfStudents; studentNumber++)

100 sum = sum + grade[studentNumber − 1][quizNumber − 1];101 //sum contains the sum of all student scores on quiz number quizNumber.102 quizAverage[quizNumber − 1] = sum/numberOfStudents;103 //Average for quiz quizNumber is the value of quizAverage[quizNumber − 1]104 }105 }

106 public void display()107 {108 for (int studentNumber = 1; 109 studentNumber <= numberOfStudents; studentNumber++)

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

Page 137: TheRationalEdge_July2004

Multidimensional Arrays 357

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

110 {//Display for one studentNumber:111 System.out.print("Student " + studentNumber + " Quizzes: ");112 for (int quizNumber = 1; 113 quizNumber <= numberOfQuizzes; quizNumber++)114 System.out.print(grade[studentNumber − 1][quizNumber − 1] + " ");115 System.out.println(" Ave = " + studentAverage[studentNumber − 1] );116 }

117 System.out.println("Quiz averages: ");118 for (int quizNumber = 1; quizNumber <= numberOfQuizzes; quizNumber++)119 System.out.print("Quiz " + quizNumber 120 + " Ave = " + quizAverage[quizNumber − 1] + " ");121 System.out.println();122 }123 }

quizAverage[0]

quizAverage[1]

quizAverage[2]

Display 6.13 The Two-Dimensional Array grade

student 1 10 10 10 10.0 studentAverage[0]

student 2 2 0 1 1.0 studentAverage[1]

student 3 8 6 9 7.7 studentAverage[2]

student 4 8 4 10 7.3 studentAverage[3]

quizAverage 7.0 5.0 7.5

quiz

1

quiz

2

quiz

3 studentAverage

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

Page 138: TheRationalEdge_July2004

358 Chapter 6 Arrays

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))

Display 6.14 Demonstration of the Class GradeBook

1 import java.io.IOException;23 public class GradeBookDemo4 {5 public static void main(String[] args) throws IOException6 {7 GradeBook book = new GradeBook();8 book.display();9 }

10 }

SAMPLE DIALOGUE

Enter number of students:4Enter number of quizzes:3Enter score for student number 1on quiz number 110Enter score for student number 1on quiz number 210

<The rest of the input dialog is omitted to save space.>

Student 1 Quizzes: 10 10 10 Ave = 10.0Student 2 Quizzes: 2 0 1 Ave = 1.0Student 3 Quizzes: 8 6 9 Ave = 7.66666666667Student 4 Quizzes: 8 4 10 Ave = 7.33333333333Quiz averages:Quiz 1 Ave = 7.0 Quiz 2 Ave = 5.0 Quiz 3 Ave = 7.5

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

Page 139: TheRationalEdge_July2004

Chapter Summary 359

■ 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 array’s 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.

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

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

Page 140: TheRationalEdge_July2004

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.31.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 360 Friday, November 14, 2003 6:18 AM

Page 141: TheRationalEdge_July2004

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 ver-sion 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 GolfScoresExer-cise.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 361 Friday, November 14, 2003 6:18 AM

Page 142: TheRationalEdge_July2004

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]);}

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 GolfScoresStatic-Exercise.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.");

extra codeon CD

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

Page 143: TheRationalEdge_July2004

Answers to Self-Test Exercises 363

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; } }

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

Page 144: TheRationalEdge_July2004

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 364 Friday, November 14, 2003 6:18 AM

Page 145: TheRationalEdge_July2004

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 30 1 2 30 1 2 30 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 java.io.BufferedReader;import java.io.InputStreamReader;import java.io.IOException;import 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); }

extra code on CD

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

Page 146: TheRationalEdge_July2004

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 mes-sage, 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 mes-sage, 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 366 Friday, November 14, 2003 6:18 AM

Page 147: TheRationalEdge_July2004

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 AW’s 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 previ-ous 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 posi-tions 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[10];a[0] = 'a';a[1] = 'b';a[2] = 'a';

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

Page 148: TheRationalEdge_July2004

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, n2, 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 posi-tions 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 Count 4 2 3 3 2 2 1 4−1 1−12 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 368 Friday, November 14, 2003 6:18 AM

Page 149: TheRationalEdge_July2004

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 addi-tion 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 encoun-tered “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 Dis-play 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 begin-ning 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 user’s new array, makes this array (or more precisely its reference) the new value of a, and then adds the ele-ment 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 369 Friday, November 14, 2003 6:18 AM

Page 150: TheRationalEdge_July2004

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 2 34 5 67 8 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 X O4 5 6O 8 9

9. Write a program to assign passengers seats in an airplane. Assume a small airplane with seat numberings as follows:

1 A B C D2 A B C D3 A B C D4 A B C D5 A B C D6 A B C D7 A B C 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 X B C D2 A X C D3 A B C D4 A B X D5 A B C D6 A B C D7 A B C 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.

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