My Design Process – Activity Diagrams and Wireframing
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.
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 to 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.
Wireframes are described on Wikipedia as being a visual guide that describes the skeletal structure of a user interface. In other words, a wireframe describes what will be on each screen of the application. This content normally includes text fields and tables of information for the user, buttons that allow the user to take actions, and navigation controls to allow the user to move through the application to complete their work. When I started building this process, I followed the classic approach of using the wireframe to describe the structure of a page, but not give any advice to the styling (colors, fonts, etc). This leads to artifacts that look something like this:
This wireframe describes the home page for a demonstration project that I am using in my current Pluralsight course, but it serves as a good example of a classic wireframe. You can see that we have some sort of image in the upper left corner (denoted by the box with the x through it). This is, presumably, a company logo. In the upper right, we see a region that holds links for us to navigate through the site. The main region of the page is taken by some text (the gray bars), followed by the three primary categories that we are driving the user to. At the bottom of the page, we have a small section to contain social media links.
Wireframes like this are intended to facilitate discussions about how an application should be structured without introducing styling cues that can distract from the important discussion about how the application will function. However, I have found that the users that I often interact with are not able to separate these topics so easily. As a result, the lack of styling becomes a distraction. In effect, it backfires. As a result, I’ve started created wireframes that look like this:
As you can see, I have added colors, images, and typography to describe the visual design of the application as well as the structure. This is often done by partnering with a visual designer to deliver the best visual experience possible. While this is more time-intensive than a simple gray-scale image, it is still much faster to iterate on these images than is possible in the final application code.
So why, you may ask, is this the right time to create wireframes? Well it turns out that the other part of this step, the creation of activity diagrams, will describe how the user interacts with the system to implement each use-case described in the previous step. Since the user often requires a visual interface to facilitate this interaction, it makes sense to capture how the application exposes the function in the wireframe as well as how the system will respond to that interaction via the activity diagrams.
In the last post, I discussed how I create use-case diagrams in order to identify the ways in which a user will be interacting with the system that is being designed. This allowed us to identify the highest level functions that will be a part of the system in order to meet the requirements that were gathered in the second phase. Additionally, the components of the system that will probably be involved in the implementation of the function.
Activity diagrams are used to expand the use case with the intention of describing how the user and components will actually interact. These “activities” specify what the component does including any communication that it will have with the other systems. To illustrate this, let’s walk through how a user might log into an application. For this discussion, let’s adopt the component design from our first stage that looks like this:
This system involves a web browser that will display the user interface and send user actions to the server for processing. The server consists of a controller layer, which will receive the browser’s request for action, a model layer which will implement the business logic and interact with the data store, and a view layer which will prepare a response for the browser to display the effect of their action. Finally, a data store is present to provide long-term storage for the application.
When considering this system, and the user’s desire to login, we end up with a use-case diagram like this:
As you can see, we are expecting that every component in our system will have a role to play in the login process, but we haven’t specified any detail yet. The Activity Diagram will supply that.
Step 1 – Swim lanes
The first step in creating the activity diagram is to make sure that the diagram stays organized. Our goal for this is to describe the specific functions that each component must have in order to implement the use case. Swimlanes organize the activities in a way that allows the functions for each component to be easily identified. We are going to need one lane per component plus the user, so our initial diagram looks like this:
Step 2 – Adding Activities
The next step is to start to describe how the components will interact.
We show here that the user starts the process by clicking on the login link. The browser will then forward the request to the controller which simply forward the request to the view layer. It sends the page back to the browser which renders it. Notice that the lines of communication follow the component diagram and each activity clearly describes what the component needs to do at each step. You’ll also notice that the activities are not overly technical. The intention is to keep ourselves in the mind set of mapping the process, not the actual programming constructs that are involved in implementing the process.
So far, we have the login page show to the user, let’s continue to flesh this out by handling the user submitting their credentials.
At this point, we have engaged every component in the system to lookup the user’s credentials, so it looks like our use-case diagram was correct. This isn’t always the case, and that’s fine. The goal of my layered approach is to allow me to focus on one part of the problem at a time. As I move through the layers, I always discover bad assumptions that I made previously. That is actually one of the key benefits that I reap from this technique – by constantly going over through the design, but digging a bit deeper every time, my overall understanding of the solution grows.
Step 3 – Branching Flows
We do, however, have a bit of a problem: what happens if the user enters the wrong credentials? So far our diagram has had a nice, linear flow. Our next step will have to handle the case where the user logs in successfully, and one where they fail to login. Our next diagram will show that.
Finally, we have the full flow of the activity defined. Notice the diamond symbol in the server-controller’s swim lane. That symbol indicates that the activity will take different paths based on some condition. In this case, if the user record was found, we direct to the logged view, otherwise, we will request a login failure. This resides in the controller since it is what is responsible for directing the response based on what the model gives it. After that decision is made, the controller will request the correct view from the view layer. Then we have the last new symbol. That thick vertical bar at the bottom of the view swim lane indicates that multiple paths are joining back together. This is done because the browser will have the same action of showing the view regardless of which view it receives.
Until this point, the design process has been working to define the boundaries of the system (via requirements gathering and component diagram creation) and how they interact at a very high level (via use case diagrams). With that landscape defined, wireframes and activity diagrams are used to determine what the application’s interfaces will look like and how the components of the system will work together to provide the required functionality. By organizing the diagrams into swim lanes, a clear picture of each component’s functions can be seen.
Depending on who will be building the software, this may be the last step of the process. However, there are many times when we want even more clarity on how the application will be built in order to comply with internal development standards. In those situations, the last, and most time-intensive part of the process will be started – the creation of sequence diagrams. These diagrams are created for every component in each of the activity diagrams. Each of these diagrams illustrates the actual software objects (e.g. classes and objects) that are being called along with their message signatures. In short, this next level is as close as we can get to defining the software system without actually writing code.