The step between specifying requirements to working on a system design can be tricky. Fortunately, the basis on which the step is made can be calculated. Paul Reed thoroughly explains how the transition should progress and offers some instructions on how to move properly through this phase.
One of the bigger challenges facing software projects is determining when and how to begin the transition from specifying requirements to working on a system design. Questions arise during this phase, such as: "I'm on an Agile project-what design artifacts should I produce and when?"; "My project creates use cases; do I detail all the use cases first and then jump into design?"; and "Which requirements should I tackle first in design?"
First Thing's First
To think about design implies the project team has given thought to the requirements and their associated priorities and has generally accepted architectural principles. The first element, requirements and their priorities, is unique to each project. The second, architectural principles, has likely been considered within your organization many times and has been used to implement other software applications into production.
I am continually amazed at how organizations harvest few assets (both software and architectural patterns) from prior projects for the benefit of those yet to come. In my experience, large organizations have a difficult time harvesting existing architectural patterns. Smaller organizations more commonly leverage their software architectures horizontally across projects. The larger organizations that I work with have fragmented the architectures. Projects will find that just a small amount of design modeling early in the project's lifecycle will afford greater identification of patterns, leading to more sound solutions.
To transition from analysis to design, the team needs to understand the project's quality attributes (e.g., security, maintainability, usability, and reliability) as well as design and implementation constraints (e.g., a delivery platform). These nonfunctional requirements (quality attributes and design and implementation constraints) should be elicited in consort with functional requirements (e.g., stories, use cases, and data models). Some teams define these early in their project charter or software requirements specification, if one is used. (Agile projects tend to shun full-blown specification documents where possible.) In any case, these nonfunctional requirements must be defined and are necessary for a safe and sound transition from analysis to design.
Given the delivery platform per design and implementation constraints, quality attributes, and any existing architectural standards; the design staff can-in tandem as requirements are elicited-work on the design. Priorities count, because without the prioritized requirements and prior knowledge of delivery platform, the bare minimum the design team could produce is an analysis-view class diagram, which isn't enough to say the team has a sound design or has thought about any difficult architectural decisions. So, the design team also needs to understand the customer's priorities.
What Maps to What?
In her two-part series on StickyMinds.com, Ellen Gottesdiener makes the excellent point that the "pressure" your project finds itself under will drive what models the requirements team produces. In my experience as an architect on numerous projects, I've found the same three design models-software architecture schematic, class diagram, and sequence diagram-regardless of what the requirements team delivered.
I'll illustrate in the following sections how the team can utilize these three design tools in the project's lifecycle.
The simplest of the three models, but the one that usually surfaces the greatest amount of debate, is the overall view of the system's proposed architecture. This may include a visual picture of the hardware and perhaps where the various software components and subsystems will reside and run (e.g., database, middleware). It will also show the "layering" approach that should be taken on the project with respect to the software's design. Software layers are typically the user interface, business logic, and data access.
These documents usually get packaged as part of a software architecture document. Regardless of the document or style you follow, enough can't be said about the importance of getting it down and basing architectural decisions off of it--decisions that will impact the rest of the project going forward.
Let's say your project team is using SCRUM or XP and producing user stories, and you have a healthy backlog in place to drive the next several sprints (i.e., iterations). I suggest pulling your product owner/customer's high-priority user stories from the backlog and creating an initial class "blitz" from the backlog. A class blitz is nothing more than quickly sketching out, in a low-tech fashion, the analysis classes identified from the requirement models produced to date. If the team has produced a conceptual data model-even a sketch or rough draft of it-you're that much better off.
Architects and developers on an agile project are already part of the delivery team, so nothing should be "thrown over the wall" to you. People in this position should think about design each day.
I blitz a high-level class diagram from the backlog. This is primarily driven from the nouns I find in the backlog of user stories. These eventually become entity classes. (The unified modeling language (UML) suggests three types of classes: entity, control, and interface.)
If the delivery team has given any thought to themes (some functional area, user group, story group, or anything else that makes sense for the product owner), then that theme is an early indicator of a possible class or classes that will act as the software "conductors" for the related stories. If themes are absent, as designer you need to find them. Why? Themes become essential to your design: they are the control classes. Control classes provide for the demarcation point where transactions begin and end. They coordinate with the other classes to ensure the business rules are enforced. Should something go wrong along the way, it's the control classes that roll back any changes that have been made as a result of the transaction.
Once you understand the design structure with classes, you should explore interactions with a bit of sequence diagramming. A sequence diagram illustrates how your classes carry out the work specified in user stories. In most cases, you only need to create sequence diagrams for the highest-priority stories. Remember, on an agile project you want to eliminate waste (unused artifacts) and rework. So fewer sequence diagrams should be your mantra; focus on those that will help you visualize the design flow prior to coding.
While I have seen marvelous results with agile projects, I also see a very high amount of rework done as a result of not having a clear understanding of the overall architectural pattern the application will follow.
I recently worked on a project where there was disagreement on how the data retrieved from the backend database would be delivered to the other objects in the design. At the center of the debate was whether or not the data should be delivered as a Microsoft dataset object or as a lightweight class that wrapped the data. It wasn't until the third sprint that reason won out and the lightweight-class approach was chosen. It turned out that two other projects in a different department had already made the same decision on prior projects. Teams must stop, pause, consider, and decide. A fair amount of heavy lifting was required to go back and modify the code from the first three sprints as a result of this late architectural decision. I know some readers will say that agile methods accept rework as part of the planning for future iterations. That said, a small amount of design modeling can get answers to these questions early, resulting in an even smoother agile experience.
If you use the RUP or a modified waterfall development method, you are likely producing use cases to articulate user requirements. I find the best way to arrive at use cases is by first deriving an event list. Using Ellen Gottesdiener's definition from her book, The Software Requirements Memory Jogger, events are the stimuli that trigger the system to carry out some function and their responses. Ultimately, the events are further detailed in the project's use cases.
Use your event list and whatever you have captured in the use cases (e.g., a list of named scenarios, such as "benefit clerk enters a new claim for an existing employee"). Produce an initial class diagram with events and use cases or scenarios. As with user stories, if I have a conceptual data model as well, the more sound the class diagram. These classes eventually become entity classes. From a design perspective, a single use case is an early indicator of a possible class (or classes) that will act as the software "conductor" for the scenarios contained within the use case. These eventually become control classes.
Sequence diagrams are derived by elaborating on scenarios within the use cases, just as they elaborate on user stories. Use cases can provide you with a clear-cut indicator on where to start your design models. Look for the main scenario or pathway through the use case. You don't have to produce one for every scenario through each use case. This depends on the development team that's going to build the software.
Regardless of how I got to the sequence diagrams, I also like to produce one sequence diagram showing all the classes reflecting my software architecture (depicted previously on my software architecture schematic). That is, if it's a .NET, Web-based application, I will have interface classes that are .ASPX pages. If it's a Java application, I'll have interface classes that are .JSP pages. This one sequence diagram would also have the backend classes that translate the entity classes into SQL calls or XPATH streams, depending on my persistence strategy. There isn't a need to do more than one of these sequence diagrams because they're basically the same (from an intent perspective) for all interactions with the system.
In reality, both agile and non-agile projects should use a combination of models to express both the requirements and design. Picking the right models for the type of project is an important decision. Whether you're using less formal or more formal methods, you must produce a roadmap to ensure your customer gets what they chartered you to do in the first place. That's a working solution done in a cost-effective and timely fashion.
- Ellen Gottesdiener, The Software Requirements Memory Jogger
- Paul Reed, Developing Applications with Java and the UML
- Paul Reed, Developing Applications with Visual Basic and the UML