SDLC

Diligence

User Interface Testing

We transform our user stories in Jira into a test plan. The test plan is then scripted to provide an automated, system-level testing of the user interface and overall customer experience. This can be run headlessly in an automated pipeline.

As with the code-level tests above, system-level tests are written to prove the existence of bugs before they are fixed. In this way we build a library of tests that grow over time and provide ever more reassurance.

User Acceptance Testing

We test the system in real-world scenarios with real-world users, to validate that it meets their requirements and expectations.

Non-functional Testing

Some or all of the below may be necessary

Bug reporting

Bug reports should include the following attributes to assist in understanding and speedy resolution:


Develop

SOLID Principles:

YAGNI, ‘You ain’t gonna need it’:

Good developers will often:

There are many excellent development practises that contribute to clean and dry code (see below) but that can also be time-consuming and may not ultimately be needed. We aim to balance these against the YAGNI principle.

DRY, “Don’t repeat yourself”:

We look for opportunities to reduce the amount of code we write by encapsulating functionality into discreet, reusable functions. We balance this against the YAGNI principle.

Documenting / Commenting

Informative comments provide help to the next developer to work on an area of code, even when that developer is the original author at some point in the future. We write comments because we recognise that reading code is harder than writing it.

Complex areas of code are especially important to comment, often noting the paths not taken. Public APIs are specified using Open API (swagger).

TDD

Test driven development front-loads the overhead of testing and lowers the overall cost of development. We identify errors early and at a time then the code has been freshly written.

Unit tests provide evidence that a single unit of code works, typically in isolation. Integration tests, sometimes called “sociable unit tests”, provide evidence that a whole sequence of code works together.

When bugs are found we write new automated tests that prove the bug exists before we fix it. Although our initial testing is included in the cost of the story or task in Jira, bug reports that have been promoted beyond a developer environment are triaged via a new ticket in Jira.

Our pipeline collects test-coverage metrics when it executes our tests so that we can monitor and improve on this.

GIT Source Control

Semantic Versioning:

We use git commit tagging to designate versions according to semver principles.

Feature Branching:

Developers create feature branches named after their ticket

Avoiding ‘fox-trot’ Merges:

We rebase our feature branches on top of the master branch and then merge the feature branch back into the master. This ensures that origin/master is always the 1 parent in every merge.

Pull Requests and Peer Review:

Github supports a peer review process that our developers use to validate each other’s code before we merge it into the master branch. This process help raise the quality of the code written and can prevent errors and misunderstandings from entering the main work stream.

Security

Common Principles


Deploy

CI/CD

Branch Protection

The master branch of the project is projected from direct changes. Changes can only be merged into the master branch, and then only when certain conditions are met.

Feature Branch Triggers

Code can be pushed to a feature branch without consequence. Raising a pull request should do the following:


    The PR name is linted against a Jira ticket.

    The code is compiled.

    The code is subject to static analysis for security purposes.

    The unit and integration tests are run.We only run in-process tests here. Some integration tests may be run later.


    Code coverage is collected

    A new artifact is created for this build.


    *A new resource group is created in the cloud and the artifact + any requisite data is deployed there using IaC.

    *The system tests are run against the newly created environment.Integration tests that require an environment will be run here.


    *Code coverage is collected

    * Branch-level deployment is an advanced strategy and a good target to aim for.

    Pushing to a feature branch with an outstanding Pull Request re-runs the above checks.If branch-level development is present the testing environment can be safely torn down.


    Master Branch Triggers

    The code can be merged to the master branch with at least 1 acceptance in the PR process. Merging into master triggers the same actions as above but with deployment to UAT

    Release Management

    Creating a new tag for a commit on master that matches the semver pattern triggers several sequential actions:

      The Staging environment for this project is updated with the infrastructure code from the tagged commit.

      The artifact that was created for the tagged commit is deployed to Staging. This process can be triggered manually by specifying the commit to deploy, which facilitates a rollback if we deploy malfunctioning code.

      Infrastructure as Code

      Our infrastructure is written in declarative yaml, it is executed as part of our pipeline and stored in source control.

      Monitoring

      Logging in the Cloud

      In a cloud environment it can be very challenging to debug software. We should implement detailed logging across the system, both to monitor healthy activity and to shine a light on errors. We will utilise the cloud provider's native logging services for this

      Health Checks

      Health checks ensure the system is up and responding, and may be used to verify specific system functionalities.

      Alerting

      If an error occurs, or a health check fails, an alert should be triggered to notify the relevant team members as soon as possible

      Design

      Baseline Technical Specifications

      Where an existing solution is already in place, analyse its implementation, assess the strengths and weaknesses of the implementation, and decide if any parts can be reused. Do this from a technical and user-oriented perspective.

      Identify the architecture patterns, technologies used, data flows, security measures and so on.Identify 3 party interactions and their mechanisms.


      rd

      Target Technical Specifications:

      Provide technical solutions that fulfil the agreed requirements. Identify software languages, service interactions, database choices, cloud providers, third party suppliers and other strategic choices.

      APIs may also be defined here with the understanding that these are prone to change as the project progresses.

      Security is planned from the outset, including where data will be stored and encrypted, defensive network topologies and both authorisation and authentication are considered.

      Robustness is planned from the outset, with redundancy in storage and infrastructure across multiple zones or regions. Traffic management, load balancing and DNS records all contribute to this.

      Scalability is planned from the outset, either with serverless infrastructure, VM scale-sets or containers and container orchestration. Database partitioning should be considered.

      Where there is more than one viable solution, a list of the pros and cons should be collated.

      Engage the development team early in this process, their input will ensure the design is technically feasible and utilises their skills effectively. Defining the technical architecture should be a collaborative process, with developers having the opportunity to propose their own solutions and clarify their understanding.Technical architecture is a guide for development, not a rigid plan. Allow for flexibility of implementation but ensure the overall structure and principles are adhered to.


      Gather Team and Stakeholder Feedback

      Technical assistance is offered to the wider team and key stakeholders to guide them through the implications of the choices they make at this level. The pros and cons of the viable solutions must be discussed and a strategy chosen that is aligned to achieving both technical feasibility and financial sustainability.