September 27, 2015

RESTful software requirements specification (part 2 of 4)


Pages: 1 2 3 4

Class diagram: Designing the business models

Specification

The business models are the main entities in an object-oriented / REST-based architecture. Identifying them helps shifting the “action” / “verb” centric use case view to a “object” / “noun” centric view. Typically, all we have to do is literally identify the nouns in the use case descriptions: These are candidates for business models.

Here is a possible class diagram:

We have also extracted the properties of each business model and modeled their relations. Note that it’s perfectly valid to start with a very raw model and flesh it out even during implementation phase. At least, this is true for a real agile approach which is clearly to be preferred. For instance, during implementation we may find that we don’t actually need a “catalogue” object, or that it would be nice to have a “name” property for a “user”.

Also note that relationships between entities are labeled here. This will help us identify the resource URLs later on.

Based on the class diagram which really should serve as an overview, we can specify each business model and its properties in detail. For each property, we should at least specify:
  • its name as a unique identifier (in camelCase)
  • its real-world name, i.e. how it should be labeled and referred to in the UI (this is I18N built in)
  • its type
  • its default value, i.e. how it is presented to the user in a new mask
  • its validation constraints, i.e. what are valid values
For this example class diagram, we may come up with this definition:
Object Property Text EN Type Default Constraints
User - user - - -
User name name String - not empty
User orders orders List<Order> - -
Order - order - - -
Order deliveryDate delivery date Date tomorrow not emptymust be in the future
Order book book Book - not empty
Book - book - - -
Book isbn ISBN String - not empty
Book title title String - not empty

This diagram is typically built in close collaboration between business analysts and programmers.

It contains every information needed to implement the business model.

Implementation

With the information from the class diagram and the business objects property details, we can build the server-side business models as POJO Java classes. Here, for instance, is the Order model:
public class Order extends BaseHalModel {
    @NotNull
    private Book book;
    @NotNull
    @Future
    private Date deliveryDate;

    // getters / setters
}
The source code for the other model classes are avilable on the project’s GitHub repository.

Note that validation constraints are included declaratively into the model using Bean Validation constraints.

On the client side, the business model only exists as a JSON object which get automatically serialized / deserialized to / from the server.

We can, however, already define the I18N key mapping for localization, here using an AngularJS’s I18N module:
var translations = {
    'entity.id': 'Id',
    
    'book': 'Book',
    'book.isbn': 'ISBN',
    'book.title': 'Title',
    
    'order': 'Order',
    'order.deliveryDate': 'Delivery date',
};
A reasonable naming scheme would be entity.property, as shown in this example.

Activity diagram: Designing the page-flow

Specification

Based on the information we got from the use cases and the business models, we can now split each use case in actual UI masks and define the page-flow between these masks.

We can actually design page flow and the respective UI masks in parallel, with the information of one fostering understanding of the other.

Here’s an activity diagram for the three example use cases:
This clearly is a borderline UML-compliant version of an activity diagram, but it contains a lot of schematized information which will help us building the UI.
  • The URLs are actual RESTful URLs of the actual UI masks. Because these URLs are RESTful, they already contain the actual status information required to initialize themselves. I have here assigned an arbitrary unique id number for each URL to make it easier to refer to it in subsequent specification steps.
  • The arrows symbolize links or buttons. I have marked links which actually trigger server-side write operations (PUT, POST, DELETE) with their respective HTTP verb. Other links are assumed to be red-only (GET). This information is optional, but it helps shaping the overall picture.
  • Variables are marked with a colon (:). Where reasonable, we use a naming scheme based on the business model, e.g. :book.id makes it clear that this variable is the value of a book’s id.
  • Apart from RESTful URLs, we can also use request parameters such as ?bookId=:book.id.
At this stage, we do not define where the variable values come from. Although the simple yet precise notation makes it almost obvious for most variables, we will specify this later in the UI mockups.

Note that to keep this example brief, I have neglected error handing behavior, e.g. what navigation steps are triggered when a validation constraint violation occurs. Of course, this would be part of a real world page flow design as well.

Of course, it also makes sense to unify URL building wherever possible: Stick to a common schema for every resource. Here, I’m using the microformats standard definition.

Implementation

At this stage, only client side work is required. Based on the information in the activity diagram, we can already build the routing (mapping URLs to actual HTML file resources). In AngularJS, this is done by configuring the routeProvider:
app.config(function ($routeProvider) {
    $routeProvider
            .when('/books', {
                templateUrl: 'views/books/list.html',
                controller: 'BooksListCtrl'
            })
            .when('/books/:id', {
                templateUrl: 'views/books/show.html',
                controller: 'BooksShowCtrl'
            })
            .when('/users/:userId/orders', {
                templateUrl: 'views/orders/list.html',
                controller: 'OrdersListCtrl'
            })
            .when('/users/:userId/orders/:id', {
                templateUrl: 'views/orders/edit.html',
                controller: 'OrdersEditCtrl'
            })
            .otherwise({
                redirectTo: '/books'
            });
})
Conveniently, AngularJS’ routing URL syntax matches the colon-style from our diagram; thus we can easily build one out of the other.


Pages: 1 2 3 4