Software Technical Design Guide

Harrison Ainsworth

http://www.hxa.name/
artifex (ατ) hxa7241 (dοτ) org

2007-04-12

Summary

A short guide for software technical design: in the form of a procedure and sets of activities and properties. It is a re-synthesis of notes from the referenced sources. (1200 words)

subject
Software development, Programming, Technical design, Process
uri
http://www.hxa.name/articles/content/software-design-subprocess_hxa7241_2001.html
license
Creative Commons BY-SA 3.0 License.

Contents

Scope And Context

Design for software can be divided like design for building: into architecture and engineering. Architecture is the external, product design that forms the usable features. Engineering is the internal, technical design that forms non-usable features. This is the same as Brooks' conception in ‘The Mythical Man-Month’.

Engineering/technical design is the subject of this article.

(Let us not use the term ‘Architecture’ as a grandiloquence for high-level design. And ‘architected’ and ‘architecting’ are absolutely objectionable!)

Fundamentals

Separating

The essence of software technical design is representation: creating, with standard means, a well-defined internal structure for the product. It is partly analysis, or separating, of ideas, and partly synthesis, or construction of ideas.

The most important action is to clearly separate the constituent ideas: since assembling pieces is easier than taking them apart. ‘Separating’ means making the ideas rationally manipulable — expressing them closely with language, patterns, data structures, OS services, etc.

Objects

The principal separating technique and abstract element is the Object/Data-type. Data is more unchanging than operations on it, so structuring a system around data gives more fundamental stability. And the most sophisticated and abstract means of data representation is object based. (as from Meyer: ‘Object-Oriented Software Construction’)

Not everything should be an object/class/type, but the main forms should follow, or depend on, data rather than function.

Generality

The highest priority is to reuse as much as possible. Packages, components, patterns, code, etc., should all be the first sources or constituents of design concepts.

The remaining, non-general, part should be designed completely ad hoc. No effort should be made to generalise it. It should instead have properties of simplicity, complete factoring, minimal connectivity, etc. (as from Beck: ‘Extreme Programming Explained’)

Designs should reuse generality, but create the particular.

But

Substantial evidence that measures these and provides convincing judgements is not known.

Sub-Process

The sub-process covers work for each iteration, after requirements (and architectural design) and before implementation. (Analysis and Design parts of ‘USDP-Distilled eXtreme Documentation’)

There are three ordered steps: dividing, connecting, and sequencing. Each contains activities to perform, properties to achieve, and the step's input and output.

Preview:

  • Input — architectural design and requirements.
  • Steps:
    1. Dividing — find the essential entities of the product, as well as their supporting utilities.
    2. Connecting — define relationships, classifications, groupings, and packagings.
    3. Sequencing — define workflow and contexts, and rough interfaces.
  • Output — classes, packages, sequences.

Sub-process input

  • Architectural design and requirements.

1: Dividing

The aim is to find the basic, essential entities of the product, as well as their supporting utilities.

Input

Architectural design and requirements.

Output

A set of incipient classes consisting of just names and roles (as class document/diagram).

Activities
Follow input concepts

Translate rough ‘objects’ from architecture and requirements into initial data objects. Also take from concepts in the general subject domain.

Build bottom-up

Extract the obvious smallest and most basic elements involved.

Reuse other design

Copy and integrate other projects, components, and patterns.

Properties
Direct mapping

Concept divisions in the architectural and requirements inputs, and in the domain more generally, are well-established. They set a particular ‘grain’ to work with.

Purity

Elements should be in their simplest, smallest form. No more division should be possible. This includes: complete factorisation — there should be no duplication; slimness — separate core data types and ‘views’ for them.

Non-sequencialisation

All sequence should be separated from data objects. Convert temporal ordering into logical constraints on methods — signatures taking certain types.

2: Connecting

The aim is to define the way the classes are statically related to each other, classified, grouped, or isolated from each other.

Input

Architectural design and requirements.

Output from Dividing.

Output

Classes with references and inheritances, stereotype classifications, packages (as class document/diagram, and package document/diagram).

Activities
Group broadly

Group elements into packages and classifications. Use semantic affinity to lead to logical form.

Arrange relations

Define composition and inheritance between objects.

Reuse other design

Copy and integrate other projects, components, and patterns.

Properties
Minimal connection

An element should use only primitives/built-ins, or less good, only standard-library/universals, otherwise few other elements.

If a class contains objects of another class, then the containing class should be sending messages to the contained objects — containment relation should imply uses relation.

Objects contained in the same containing class should not have uses relationships between them.

Interfaces should use only primitives or polymorphic types. Non-polymorphic types are equivalent to un-encapsulated data.

Stable dependence

Elements of similar volatility should be grouped. Dependencies should rest on less volatile elements. And dependencies should be one-way.

Polymorphic inheritance

Inheritance should be restricted to type: from abstract to concrete. Otherwise, prefer composition to inheritance.

3: Sequencing

The aim is to make a set of workflow context classes that arrange the entities classes into sequences of activity. Also to begin defining the interfaces of all classes.

Input

Architectural design and requirements.

Output from Connecting.

Output

Classes, interface sketches, method sketches (as class document/diagram, and sequence document/diagram).

Activities
Translate use-cases

  1. Create a new workflow context class for each use-case.
  2. Decide which classes are involved along the course of each use-case.
  3. Determine what information each part of the use-case requires.
  4. Sketch public method declarations throughout all classes to supply the required information.
Reuse other design

Copy and integrate other projects, components, and patterns.

Properties
Layering

Entity classes should have no dependence on the workflow classes. Activity involving interaction between entities should be handled within the workflow classes. Entity classes should be, mostly, hidden behind workflow classes.

Interfaces

Service offered should be: convenient, complete, primitive. Parts should be temporally unordered (except for construction and destruction).

Sub-process output

  • Class document/diagram — showing names, roles, associations (direction, ownership), inheritances, classifications, interface sketches
  • Package document/diagram — showing lists of classes
  • Sequence document/diagram — showing method names/intentions

Implementation guides

Class interface

  • Separate commands and queries — commands change object state and return nothing; queries only read object state and return results.
  • Separate options and operands — operands are more essential and unchanging than options, options are things its possible to find defaults for. The arguments of a method should only include operands — an operand argument represents an object on which the method will operate — an option argument represents a mode of operation.

Class implementation

  • Translate preconditions into: method signatures taking types having certain invariants.
  • Ensure invariants and axioms as postconditions in methods.
  • Ensure invariants before self method calls in non accessors.

References