«A designer knows he has achieved perfection not when there is nothing left to add, but when there is nothing left to take away.» Antoine de Saint-ExupĂ©ry

Our software engineering practice aims for a systematic best practice approach to design, development, operation, and maintenance of software, covering the following disciplines:

  • Analysis, design, development, and implementation
  • Distributed systems architecture, design, interfaces
  • Application design, development
  • Security
  • Data modeling, mapping, conversion
  • Database design, administration, query optimisation, performance tuning, database conversion
  • Data analysis, reporting, data warehousing, extract-transform-load development, data capture, conversion, cleaning, migration
  • Continuous quality assurance testing
  • Implementation

Design approach

In our software design and implementation we are guided by the following principles (in descending order of importance):

  • Simplicity
    The design must be simple, both in implementation and interface. It is more important for the interface to be simple than for the implementation.
  • Correctness
    The design must be correct in all observable aspects. Incorrectness is not allowed.
  • Consistency
    The design must be consistent. A design is allowed to be slightly less simple and less complete to avoid inconsistency. Consistency is as important as correctness.
  • Completeness
    The design must cover as many important use cases as is practical. All reasonably expected use cases must be covered. Simplicity is not allowed to overly reduce completeness.

Continuous testing

Our continuous quality assurance testing aims to:

  • Assess business risk coverage.
  • Establish a safety net that helps protect the customer/user.
  • Provide a stable test environment, available on demand.
  • Seamlessly integrate into the software delivery pipeline and toolchain.
  • Deliver actionable feedback, appropriate for each stage of the delivery pipeline.

Theory

What is good software design? We consider software design to be good, if it is flexible, robust, and reusable, that is, if it exhibits none of the following traits associated with bad design:

  • Rigidity
    It is hard to change because every change affects too many other parts of the system.
  • Fragility
    When making a change, unexpected parts of the system break.
  • Immobility
    It is hard to reuse in another application because it cannot be disentangled from the current application.

Our learning and understanding of systems architecture and application design has evolved over decades and has been informed by software engineering theory and best practice, and guided by methodologies.

  • Model-driven architecture and engineering
    • Increases productivity by maximising compatibility between systems via re-use of standardised models.
    • Simplifies the process of design via models of recurring design patterns in the application domain.
    • Promotes communication between individuals and teams working together using standardised terminology and best practices of the application domain.
  • Domain-specific models and languages
    • Dedicated to a particular problem domain, problem representation, and/or solution technique.
    • Supports higher-level abstractions than general-purpose modeling.
    • Requires less effort and fewer low-level details to specify a given problem domain.
  • RESTful web services
    • Scalability of component interactions.
    • Generality of interfaces.
    • Independent deployment of components.
    • Intermediary components to reduce latency, enforce security, and encapsulate legacy systems.

Design principles and patterns

In our search for better ways of writing high-quality, maintainable, and testable code we have adopted design and coding standards that comply with our design principles:

  • Separation of Concerns
    The separation of concerns design pattern separates aspects of a subject matter into well-defined layers, allowing in-depth study and focus on one aspect at a time in isolation from others for the sake of its own consistency. Examples of aspects are:
    • Separate 'what is to be done' from 'how to do it'.
    • Separate content from form, layout, and style.
    • Separate presentation (view) from business logic, data processing, and database access (model).
    • Separate configuration from operation.
    • Use modular design to separate program classes into distinct features that overlap in functionality as little as possible to achieve encapsulation, that is, information hiding and transparency of operation.
  • Dependency Inversion
    The dependency injection design pattern achieves inversion of control and avoids and untangles tightly coupled code:
    • Objects should dependent upon abstractions and not upon implementations,
    • High level modules should not depend upon low level modules. Both should depend upon abstractions,
    • Abstractions should not depend upon details. Details should depend upon abstractions.
  • Abstraction
    reduces duplication of information in a program
    • Each significant piece of functionality in a program should be implemented in just one place in the source code. Where similar functions are carried out by distinct pieces of code, it is generally beneficial to combine them into one by abstracting out the varying parts.
  • Don't Repeat Yourself
    reduces repetition of information and so allows modification of any single element in a system without having to change other logically-unrelated elements:
    • Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.

Guiding lights