I started today by reading "The Quiet Crisis unfolding in Software Development". It is a great article about leadership, metrics, ownership, building better products and much more.
It made me think of the teams I have worked on and the values/structures we put in place around code.
My current team at DWP are probably the first to actually have a document to talk about approaches to code or testing.
We already have the Digital By Default service standards and the service manual which covers topics like progressive enhancement and accessibility.
This also doesn't cover things such as code linting and styles, though both our Java and Node services have standards applied to them.
Development Practices and Patterns
The software we develop is being delivered using an incremental agile approach to identifying and delivering new system functionality. User stories are identified and prioritised by the Product Owner from a backlog along with along with supporting technical tasks. These stories are delivered across sprints as features that add new customer value to the existing version of working software.
- We will write the minimal amount of code to produce working software.
- We will remove any unused or deprecated code. Code will not be commented out or left in for 'future use'.
- @Ignore is not allowed to prevent a test from running 'temporarily' because it does not pass.
- All working code must be accompanied by new or updated tests.
- Writing tests first should be preferred over coding and then writing tests.
- All code must be peer reviewed before being considered done.
- We will adopt standard libraries and practices and document them. When our practices change we will update the documentation.
Git our version control system of choice.
Development will be done on the 'master' branch (in what is sometimes called Trunk-based development). We will only create branches were absolutely necessary. This has the following benefits:
- It is simpler
- Integrating early highlights any issues
- It encourages incremental small code changes which reduces risk
- We avoid the cost of merging code
- We avoid the cost of managing branches
- It better supports Continuous Integration
- Code integration issues are highlighted sooner as opposed to when branches are merged
- We reduce the waste of unreleased features/functionality and the risks they introduce with regards to late integration, regression testing and redundant code,
We will track release versions using the git commit version history. This still allow us to create a production 'fix' branch if required. Any 'fix' should be introduced into the 'master' branch as soon as is possible to allow normal development to continue.
Feature toggles will be considered if there is requirement to develop and release functionality at different points as opposed to the user of feature branches. However once a feature is introduced and stable the toggle should be removed to reduce the overhead of managing this capability.
Testing and Assurance
Testing and assurance of the working software is built into the development and delivery lifecycle via:
- Software Patterns - are used to establish good practice within the team and to provide a shared view on how the system is and can be further developed
- Code Reviews - of all code are used to maintain consistent coding practices, understand and share each others code and establish common working practices
- Documentation - decisions, library choices and common practice within the development process are briefly documented together with examples of working code
- Unit testing - used to check and assure the behaviour of the individual class and interface interactions
- Integration testing - used to check and assure the function of individual system components with the components/systems they interact with
- Functional Acceptance Tests - functionally test that the delivered software meets the functional acceptance requirements associated with it: validation; error handling; identified constraints
- User Acceptance Tests - user focused tests at the feature level that assure that the delivered software aligns with the identified user need
Were possible a test first approach using TDD/BDD is adopted when delivering software.
Continuous Integration is used to automate the execution of the building and testing of the various software components that are being incrementally delivered.
Automation were possible of software and infrastructure tasks are encouraged in order to aid repeatability and quality and also as a form of documenting critical processes and deliverables as code.