Software Development Magazine - Project Management, Programming, Software Testing |
Scrum Expert - Articles, tools, videos, news and other resources on Agile, Scrum and Kanban |
Agile Development with ICONIX Process
Doug Rosenberg, Matt Stephens and Mark Collins-Cope
Introduction
ICONIX Process is a minimalist, use-case driven object modeling process that is well suited to agile Java development. It uses a core subset of UML diagrams, and provides a reliable method of getting from use cases to source code in as few steps as possible. It's described in the book Agile Development with ICONIX Process.
Because the process uses a minimal set of steps, it's also well suited to agile development, and can be used in tandem with test-driven development (TDD) to help "plug the gaps" in the requirements.
The book describes the use case driven analysis and design process in detail, with lots of examples using UML, C# and Java. However, for this book excerpt, we focus on how to combine unit testing with up-front UML modeling, to produce a really rigorous software design. The process begins with the use cases and UML diagrams, then moves into Java source code via Junit.
Test-Driven Development with ICONIX Process
In this book, we put together an example system using "vanilla" test-driven development (TDD). We then repeat the example using a mixture of TDD and ICONIX modeling. In the excerpt below, we show this aspect of agile ICONIX development.
The premise behind TDD is that you write the unit tests first, then write the code to make the tests pass. The process of doing this in theory lets you design the code as you write it. However, we prefer a more rigorous, "higher-level" design approach, which we describe here.
How Agile ICONIX Modeling and TDD Fit Together
There's a prevailing opinion in the agile world that "formal" up-front design modeling and TDD are mutually exclusive. However, we're going to demonstrate that TDD can in fact be particularly effective with an up-front design method like ICONIX Process.
ICONIX Process takes the design to a low level of detail via sequence diagrams-one sequence diagram for each use case. These diagrams are used to allocate behaviors to the class diagrams. The code can then be written quickly without much need for refactoring. However, the coding stage is still not exactly a brainless activity. The programmer (who, incidentally, should also be actively involved in the design modeling stage) still needs to give careful thought to the low-level design of the code. This is an area to which TDD is perfectly suited.
The "Vanilla" Example Repeated Using ICONIX Modeling and TDD
Let's pause and rewind, then, back to the start of the TDD example that we covered in the previous chapter. To match the example, we're going to need a system for travel agent operatives to place hotel bookings on behalf of customers.
To recap, the following serves as our list of requirements for this initial release:
Create a new customer.
Create a hotel booking for a customer.
Retrieve a customer (so that we can place the booking).
Place the booking.
As luck would have it, we can derive exactly one use case from each of these requirements (making a total of four use cases). For this example, we'll focus on the first use case, "Create a New Customer".
Let's start by creating a domain model that contains the various elements we need to work with, as shown in Figure 1. As you can see, it's pretty minimal at this stage. As we go through analysis, we discover new objects to add to the domain model, and we possibly also refine the objects currently there. Then, as the design process kicks in, the domain model swiftly evolves into one or more detailed class diagrams.
Figure 1. Domain model for the hotel booking example
The objects shown in Figure 1 are derived simply by reading through our four requirements and extracting all the nouns. The relationships are similarly derived from the requirements. "Create a hotel booking for a customer," for example, strongly suggests that there needs to be a Customer object that contains Booking objects. In a real project, it might not be that simple-defining the domain model can be a highly iterative process involving discovery of objects through various means, including in-depth conversations with the customer, users, and other domain experts. Defining and refining the domain model is also a continuous process throughout the project's life cycle.
If some aspect of the domain model turns out to be wrong, we change it as soon as we find out, but for now, it gives us a solid enough foundation upon which to write our use cases.
Here's the use case for "Create a New Customer":
Basic Course: The system shows the Customer Details page, with a few default parameters filled in. The user enters the details and clicks the Create button; the system validates that all the required fields have been filled in; and the system validates that the customer name is unique and then adds the new Customer to the database. The system then returns the user to the Customer List page.
Alternative Course: Not all the required fields were filled in. The system informs the user of this and redisplays the Customer Details form with the missing fields highlighted in red, so that the user can fill them in.
Alternative Course: A customer with the same name already exists. The system informs the user and gives them the option to edit their customer details or cancel.
This use case probably has more user interface details than you're used to seeing in a use case. This is a characteristic of "ICONIX-style" use cases: they're quite terse, but they are very closely tied to the domain model, and to the classes that you'll be designing from.
Next, we draw a robustness diagram - i.e. a picture version of the use case (see Figure 2).
Figure 2. Robustness diagram for the Create a New Customer use case
A robustness diagram shows conceptual relationships between objects. Because it's an "object drawing" of the use case text, it occupies a curious space halfway between analysis and design. Nevertheless, mastering robustness analysis is the key to creating rigorous designs from clear, unambiguous use cases.
The robustness diagram shows three types ofobject:
Boundary objects (a circle with a vertical line at the left) - these represent screens, JSP pages and so forth
Entities (a circle with a horizontal line at the bottom) - these are the data objects (e.g. Customer, Hotel Booking)
Controllers (a circle with an arrow-head at the top) - these represent actions that take place between other objects (i.e. Controllers are the verbs)
Note that in the book, we take the "Create a New Customer" use case and robustness diagram through several iterations, using the robustness diagram to polish up and "disambiguate" the use case text. For brevity we just show the finished version here).
Page 2 Back to the archive list
This article was originally published in the Spring 2005 issue of Methods & Tools
Methods & Tools Testmatick.com Software Testing Magazine The Scrum Expert |