Thursday, May 19, 2011

Proposed design principles for internal design

In my current project we are to implement additional functionality in an existing code base. The system is SOA-based, composed of many sub systems, each implementing a set of services, as detailed by the architectural guidelines given to the project. In practice this means that each sub system hosts a set of domain logic behind a façade of Java EE Stateless Session Beans or Message Driven Beans. As the service façade approach is described in detail in the guidelines, any guidelines of the internal design is equally absent. Therefore I’ve, with great inspiration from the DDD community, put together this list of design principles for proposed use within the project, but I think they could be equally applied to internal design of most administrative IT-systems. What do you think? Should something be added or subtracted?

General design principles

  • Adhere to the Single Responsibility Principle (SRP), i.e. every module (class/method) has one responsibility, not several.
  • Choose names from the business domain for classes, methods, attributes, parameters and variables.
  • Use domain objects as parameters instead of primitives like string or int.
  • Design the system such that domain classes can be unit tested individually.
  • Each (part of a) sub system should use one design metaphor, either 
    • domain centered - business logic placed in domain objects, preferable when changes to state is most important -  or
    • service centered – business logic placed in stateless services that operate on data in DTO:s, preferable when the data flow is most important. 

From this follows

  • Keep business logic and technical implementation details separate, i.e. do not combine these two types of complexity.
  • Adhere to Command Query Separation (CQS), i.e. each method should be either a command (having a side-effect and possibly returning a result) or a query (returning a result without any side-effect).

On a more detailed level

  • As a tool for communication use the following stereotypes for objects implementing the business domain logic:
    • Value Objects – immutable, created when needed, not persisted.
    • Entities – mutable (as per allowed by business rules), loaded/persisted through Repositories.
    • Repository – interface describing load/persist of Entities.
    • Factory – interface describing creation of Entities and Value Objects when external dependencies (to Repositories, Factories or Services) must be fulfilled.
    • Service – stateless class housing business logic that operate on data in DTO:s
  • Dependencies are preferably handled through dependency injection to facilitate loose coupling between objects.

Application of principles
These principles define a solid approach to design of new (sub) systems. When used in work with an existing code base it can be used for continuously applying small improvements in accordance with “the boy scout rule” and as vision to compare with current state in order to form a road map for larger refactoring efforts.

Friday, May 6, 2011

No man is an island

What’s the most common reason for failure in a software project, or perhaps in any project? You will get many different answers depending on who you ask. The designers might say “The requirements were not clear enough and the programmers didn't follow the architecture”. Testers on the other hand might say “The programmers never delivered what we were supposed to get when we were supposed to get it” and programmers tend to say “We got lots of ‘bug-reports’ that where really outside the scope”. The list can be long, but at the end of the day it all comes down to lack of communication.

Let’s face it, developing software is a complex and creative handiwork. That’s why we try to stay away from the over-planned, defined, way of waterfall and turn to iteration based approaches like RUP or Scrum. True iterations give us great feedback to base the next, (hopefully) better, version on. However, working with iterations is not enough. The saying “No man is an island” origins back to about year 1600 and is as true as ever when it comes to software projects. For many years we have set up the projects so that specialist testers form a test team, specialist designers form a design team, specialist programmers form implementation teams, and so on. This for sure brings advantages in having specialists learning from each other becoming even more specialised. But it also introduces a great deal of hand-overs between the teams, each missing some vital information. I believe this way of organising the development project is one of the key reasons why projects fail.

In the agile community we talk about “Cross-functional teams“, meaning that people with different specializations work together to achieve a common goal. In software development that means that a programmer sits next to a designer and a tester, working together on transforming a requirement into a piece of well designed, well tested code ready for production. The agile practices are all about maximizing communication, e.g. by locating people in the same room with access to broadband communication aids such as whiteboards.

If you are currently in a project where the test team and development team sit at different floors and the primary tool for communication is release notes, then you have a superb opportunity to increase the likeliness of project success just by re-locating so that developers and tester form collaborative teams working together on both design, test design, implementation and test execution.