Design principles

While I prefer to cover principles imposed on the design by others outside the project under policies, I use this chapter to explain the design principles that are specifically chosen to direct the design and implementation of this solution.

The design principles are aimed at achieving all the design qualities within the confines of the design constraints.

As the solution architect, I define most design principles based on experience from past projects. Even in previous projects where my role was business analyst or technical project manager, I have always observed and learned from the proceedings with an architect’s mindset.

The design principles primarily provide direction for designers and developers, but I always go to great lengths to share them with the project’s SMEs, BAs, the project manager and other stakeholders.

Having a list of accepted design principles have often helped the team steer clear of making spontaneous decisions in the heat of the moment that would work against the design goals.

I recommend that this chapter contains a table with the following columns:

PrincipleRationaleConsequences
Shared entities must have dual identities.While data coming from external systems usually carry their own identity, there is never any guarantee that their identity is truly unique. Especially during testing, copy/pasting and messy test data often lead to duplicate identifiers in data from external systems.

This threatens integrity, non-repudiation, testability and operability, which in turn leads to increased development time and higher costs of ownership.
All incoming entities are assigned a truly unique identifier in the responding services.

Both the externally provided and the internally assigned identifier are stored in the internal data, and passed to all external systems in all integrations.

External systems must use the internally assigned identifier when referring to shared entities in this architecture.
Client services pass requests to backend services.Passing synchronous requests to asynchronous backend services helps achieve performance, capacity, scalability, operability and recoverability design goals.External systems must provide callback APIs to receive the results of asynchronous backend processing.

An MQ server is required to pass requests to backend services.

Temporary unavailability in core components are handled by retying backend processing until successful.
Services requests and responses include version informationBeing able to see in logs which software version called a service, and which version of the service responded significantly reduces the investigation efforts, in turn lowering the long-term cost of ownership.External systems are required to pass version information in all requests.

The development environment is set up to automatically update version information in the source code when files are checked in.
The table shows example design principles I have defined in various projects.

Design principles aren’t automatically followed. Developers rarely read the architecture documentation. The architect needs to review as much code as possible, participate in as many meetings as possible, constantly being on the lookout for situations where the team strays from the design principles.