Below are some key principles I keep in mind when creating a new application from scratch or take over a legacy application that is going to stick around for a while.
Automated testing for an application is key to your ability to change your application quickly. I would even go as far as saying that having good testing is more important than having a great design as we mostly learn about our problem domain along the way, hence need to change. Testing will give us the confidence to continuously refactor our code without breaking functionality. When writing tests I typically follow a few principles such as
- Don’t just do Unit Tests, but cover End-To-End tests ( or integration tests ) to verify business functionality of your application.
- Mock application boundaries to ensure there is no dependency to downstream systems as this will cause intermittent failures and make your pipeline unreliable. ( Yes people tend to ignore red builds if tests are flaky.. surprising I know .. )
- If you have downstream systems that are critical, think about having smoke / contract tests against a test environment. This will allow you to detect breaking changes before they actually get shipped into production, even if they didn't tell you. Having said that don’t make them part of your pipeline as they will likely break frequently.
- Use frameworks such as testcontainers.com, ( my personal favourite ) which allow you to keep your tests as close to a real deployment as possible.
Having an easy to use DevOps pipeline is key for both developers and the deployment teams. The pipelines together with testing should provide fast feedback to developers. It should include steps to release your software as this will prevent manual errors during deployments.
A few key things I believe are essential
- Split up your pipeline into logical steps, ( e.g. build, unit test, integration test, package etc. ). This allows you to optimise and parallelise steps. Don’t forget to carry over artifacts where needed to avoid builds being re-run unnecessarily and wasting time.
- Setup a single pipeline for your code base to build, package, test and deploy if you can as this simplifies maintenance and increases consistency. Btw. this doesn't mean you have to only use one file but it should be one pipeline. If you have to split up build and release pipelines try to not have more than one of each.
- Try to maintain your pipeline config in a yaml file instead of using a GUI ( even if tempting at the beginning ). This allows you to keep your pipeline configuration as part of your code incl. history. Makes it a lot easier to keep track of how it evolves over time ( and allow you to rollback )
- Model the pipeline to your development workflow, e.g if you use feature branches ensure you run automated tests but not necessarily build a container for each pipeline run.
- If you can, include steps needed to create release documentation as part of the pipeline. ( who does like to do that manually anyway ?? )
There are many more things but I think above is a good start to build an application that will be a joy to work on even if it is a few years old.
Good points! Hope all is well.
Since 15ys barely nothing changed 😂