My Design Process – Requirements Gathering
I am currently doing a series of posts where I am documenting my personal software design process. This process has been developed to support the environment that my designs are currently deployed into – a fairly large retail company that needs to control the rate that applications are deployed to the stores in order to limit the number of distractions that threaten to pull the sales staff from their primary role of, well, selling.
I make no claim that this should be viewed as the “one-right way” to design applications. I imagine that I would have a radically different process if I were building publically facing websites for a conference. My goal is to document my process for solving the problems that I am facing.
My first post gave an overview of the process, but I’ll repeat some of it here for convenience.
Currently, my design process flows through the following stages
This stage involves the specification of the high-level components that make up the proposed software system and describes, very generally, how they will interact.
In the requirements gathering stage, all available documentation from the business owners are gathered and recorded. This often includes conversations with program management to ensure that each requirement is understood.
The requirements are then distilled down into individual use-cases that the software system will implement in order to meet the requirements. Also, the components that are likely involved in the use-case are identified.
Activity Diagrams and Wireframing
This stage involves the creation of activity diagrams (aka flow charts) to show how the user and system components will actually interact to implement each use-case. Also, since the interaction of the user and the system are starting the be specified, the structure of the user-interface (aka wireframes) are created at this time as well.
The final, and most time intensive stage, is the creation of sequence diagrams. These diagrams contain the detailed information about how the system operates to implement the process illustrated by the activity diagrams.
In this post, I would like to walk through the process that I use to gather and distill the application’s requirements down to a manageable subset. These will then define the functionality that the rest of the design should enable.
In the last post, we developed a component design that looks like this:
To summarize that post, we have three high level components:
– A web browser that will receive server-generated HTML and send data back using standard form posts
– A data store that is responsible for enabling long-term storage and retrieval of data
– A web server that implements the MVC design pattern
o The controller receives requests from the browser and forwards them to the model for processing. It then takes the response from the model and forwards that to the view.
o The model implements the business logic and interacts with the data store
o The view receives the processed data from the controller and transforms that into HTML for presentation by the client.
We developed this based on some theoretical conversations that we actually the pre-cursors to the requirements. I’ll repeat them here, since they will form our starting point. Our want users to be able to:
– create an account
– log on and log off of the application
– create a friend request
– accept or reject a friend request
– post an update to their friends
– see the posts from their friends
These initial requirements were required in order to allow us to scope out the major components, but these are normally gathered several weeks or months before the formal design process is started since the business is typically still feeling their way forward at this point.
To start the requirements gathering, the first step that I take is to gather as much documentation as I can. This may be in the form of a scoping document that is developed between the program manager and the business, API (application program interface) documentation for any other services that the application must interact with, or email conversations and meeting notes.
Any material that I can get is stored in a project drive but I work from hard-copy printout. I will typically read each document (at least) twice.
The first time is intended to give me an idea about the general goals of the document and the perspective that the author is coming from, in case there is an obvious bias.
The second read through is why the hardcopy is critical. This read-through requires a highlighter and is a detailed search for anything that the document is putting forward as either a requirement of the application or an assumption about how the system should work. During this phase, I have a couple of guidelines that I try to adhere to:
Don’t evaluate the requirement against the solution
I have found that it is easy to try to think about how the system will handle each requirement. This is dangerous since it can lead to premature revisions of the design. This task is important, but is handled later in the process.
Avoid looking for mutually exclusive requirements
This is another tricky goal since it seems like such a good idea. The problem with this is that a lot of requirements that might be considered mutually exclusive at first can be reconciled later.
After gathering all of the requirements that I can find, it is now time to analyze the results. In this phase, the requirements that have been gathered are categorized and some initial judgments are made about each requirement. More specifically, every requirement is tagged with the following information:
This is vital information when having discussions about requirements and the context for the requirement is required. It can go a long way to understanding why something was asked for, especially when some requirements have to be modified to manage the scope of the project.
The “kind” of requirement helps to group requirements by what aspect of the system they are constraining. For example, the need to “create a friend request” is a functional requirement since it is a function that the application must support internally. On the other hand, “retrieve latest tweets from user’s Twitter feed” would be an interface requirement since our system must interact with another system (Twitter in this case).
While not a critical step in the process, I like to do this in order to group the requirements mentally and get an idea about where the system needs to be the most sophisticated. An application that has a lot of functional requirements is going to need a strong internal structure to manage the number of functions that it needs to manage. In contrast, if the requirements are heavily slanted toward interfaces, then the design should have a flexible and easily discovered interface to import and export data from other systems.
Software can’t be any better than the degree in which it meets it requirements. The first part of ensuring that the requirements are met is to identify them (this phase), however, this isn’t enough. Somehow, the software needs to be verified to meet those requirements. By identifying a verification method at this point, I, as the designer, communicate my assumptions about who will be responsible for taking the primary responsibility for proving that a function exists. There are four kinds of methods that I generally use:
This method means that the requirement will be met systematically be the design. An example of a requirement will be solved in this way would be: “The system will store its data in xyz database”. A requirement like this is fundamental and, normally, reflects the standard process for building software in the organization. There is no need to have a downstream team verify, it will be addressed by the design of the system itself.
I use the “test” method to indicate that I expect that the build team will verify this functionality through their automated test suite. An example of this kind of requirement is: “All posts are stored with a timestamp of when they were created”. This requirement doesn’t imply any user experience and cannot be guaranteed by the system design, so the developers will have to prove that it is going to happen.
Inspection and Demonstration
These two methods are similar in that the quality assurance (QA) team handles them, although they are subtly different.
The inspection method means that the QA team member will execute some sort of test script and then check the results. An example of a method that could be verified in this way is: “When the user enters invalid credentials, then the attempt is written to the application log”.
The demonstration method is, in my opinion, the weakest method for verifying a requirement. It is typically used for requirements that are transient and difficult to capture. An example of this type of requirement is: “The application’s user interface uses the company standard color scheme.”
Perhaps the most important tag for a requirement is the risk. Identifying the risk allows the rest of the team to know where my concerns about the project lie. This often drives follow-up conversations with the program management team about what the high-risk items are and how they might be remediated. In short, it is a way for me to say that I believe that the requirement is valid, but I’m not sure that I will be able to design a system that complies with it.
Once all of the requirements have been gathered and analyzed, they are discussed with program management to ensure that they align with their goals. Additionally, any decisions that are required for conflicting or high-risk requirements are either made, or assigned to someone to address. After these decisions are made, the component design is revised, if required, to accommodate the requirements.
The goal of the requirements gathering stage is to locate all of the goals and wishes that the people involved with an application have. These requirements are then analyzed to determine how easily they will be to implement and, when implemented, how they will be verified. Finally, the requirements are reviewed with the project’s leadership to ensure that all issues are addressed so that the design can proceed smoothly.
With the requirements settled upon and reconciled with the component diagram, we are ready to establish the use-cases. This stage will introduce high level functions that the system will provide and which components will interact to provide them.