September 27, 2015

RESTful software requirements specification (part 1 of 4)



The quality of a software product largely depends on the quality of its underlying specification. In this article, I’d like to show how to build a software requirements specification with software engineering design and architecture best practices such as REST, object-orientation and DRY built in.

Finding a common engineering language

As a software programmer, I typically depend on receiving a high quality software requirements specification in a project where we have dedicated business analysts. However, experience shows that there are typically huge discrepancies between how requirements specifications are designed and what programmers expect as a working ground to build solid software.

In some of the more extreme cases, all I receive is a collection of GUI-mockups alongside some plaintext explanations regarding e.g. mask-to-mask navigation.

Let me make it very clear that this is not simply the requirement engineer’s fault but rather the result of failing to find a common language which both, programmers and requirements engineers, understand.

In this article which is clearly written from a programmer’s perspective, I’d like to show how to apply software engineering design principles at the stage of requirements specification already which, as a result, produces a high quality software specification written in the language programmers understand: precise, detailed, well-defined, and in accordance to engineering best practices such as component reusage and DRY (don’t repeat yourself).

The building blocks

The main underlying architectural principles for this kind of common software design I’d like to suggest are object-orientation and REST (and I18N principles), for these reasons:
  • Object-orientation means thinking in business objects, actors, “nouns”. This is also known as “domain-driven design”. It mimics real-world thinking and is most typically the main underlying principle of the programming language in use, thus easy to implement.
  • REST is an architecture principle which reduces service interfaces (as in e.g. web client – backend server communication) to CRUD (create / read / update / delete) operations on business objects, actors, “nouns”. That’s right, it’s a perfect match for object orientation and largely adapted in many software frameworks, thus easy to implement. I’ve made an entire blog post about REST basics earlier this year.
  • I18N or internationalization / localization which typically means preparing the software to work with different UI languages. Instead of “hard-coding” output texts, we use text ids which are mapped to the actual translation, based on the language chosen at runtime. This highly increases software maintainability, and is built into most software frameworks, thus easy to implement.
These architecture principles match well any typical web client/server application.

Even if the software product is not based on these principles, applying them at the specification stage offers many of the advantages discussed presently.

To apply these principles, we build the actual software specification by using four types of commonly used UML diagrams plus UI mockups. Ideally, there is only little need for plain texts. For each aspect of the system (e.g. for each use case), we create the artifacts presented below.

In order to specify the server side implementation:
  • First of all, using the class diagram, we identify the participant business objects, their properties and their relation to each other. This diagram should be accompanied by a table with a definition of every property of every business model. We can later on basically generate our source code model classes (and, subsequently, our DB tables) from the diagram and the business properties table.
  • After that, we draw a state diagram for each business model identified in the previous diagram. Using these state diagrams, we identify the state transactions that occur within each of our classes, now viewed as “resources”. We can later on basically generate our RESTful service implementation from these diagrams.
In order to specify the client side implementation:
  • At first, we draw a use case diagram for the actual use case (a.k.a. user story). Although drawing a use case diagram is optional, it helps visualizing the information written down in the actual use case. The use case diagram is different from the other diagrams in that typically, we only draw one diagram for all use cases of the project / sub-system.
  • The class diagram (see above) is also needed for the client-side implementation.
  • Then, we draw an activity diagram illustrating the use case previously identified in more detail. We can later on use these diagrams to determine the detailed page flow for every user interaction in the UI.
  • Finally, we design the actual UI mockups, typically one for each activity previously identified.
It’s important to stick to the order of these design steps for server and client specification, respectively. However, depending on manpower or other factors, server and client implementations may either start in parallel or subsequently.

In an agile development environment (e.g. Scrum), these design steps will typically be followed immediately by the actual software implementation which are both part of the same sprint. This reduces the risks a loss of focus would bring and enables fast feedback cycles. Whilst this approach is clearly preferable for many reasons, the method explained in this article also works in “traditional”, more waterfall-like projects.

We use well-known UML diagram types only to facilitate common understanding. However, we will use them in a very pragmatic way. It’s more important to convey the important information through the diagram than trying to artificially stick closely to a diagram type’s formal definition.

I do also advocate pragmatic tool usage: We really want to use tools which are lightweight and easy to use with a minimum amount of functionality. Hence, I use the open source tool UMLet to draw UML diagrams and the open source tool Pencil to draw UI mock-ups.

Let’s build it

Enough now of the theoretic part! Let’s create an example application from scratch using this specification methodology. In the following sections, I will for a buch of example use cases run through each stage of software specification, as explained above, and for each stage, immediately show how its design would be reflected by the actual software source code. Note that in reality, implementing the source code would rather be the last step for each use case after the design is done.

For the understanding of this articles, it’s not important to actually understand the source code examples. Feel free to skip them if you’re only interested in the software specification view.

For the sake of this example, I use this very pragmatic web application tech stack:
  • AngularJS with Restangular for the client because there’s hardly any easier way to build a modern REST-consuming web client.
  • Java EE 7 JAX-RS for the REST server because there’s hardly any easier way to build a modern REST-producing web server.
The entire application source code is available on the accompanying GitHub repository.

In the following sections, specification work is marked in yellow; client implementation is marked in light blue and server implementation is marked in darker blue.

Actually, the example application will use REST on two layers:
  • The AngularJS single page application will feature RESTful URLs for user-friendly navigation.
  • The Java EE 7 web-service is implemented as a true RESTful server.
The example application should implement these three use cases based on an artificial “online book store”:
  1. The user can open a page with detail information (ISBN, title) about a book in the catalogue.
  2. After choosing a book, the user can order it, specifying the desired delivery date.
  3. The user can cancel his order at any time before delivery date.

For your reference, this is how the final application will look like:
#/books #/books/1?bookId=1
#/users/0/orders/new?bookId=1 #/users/0/orders?created=1

Use case diagram: Visualizing the information

Specification

Creating a use case diagram usually means identifying the “actors” and assigning them the use cases. Typically, there’s a single actor “user”, or one actor per user type (admin, normal user,…).

Here is a possible outcome after drawing all the user cases of the example application into a single diagram:

We only have one user here. We use “extends” to show that ordering a book implies having opened the book details in a previous step.

Implementation

There is no implementation at this stage.

Pages: 1 2 3 4