Software Quality Assurance : An Example Document
Software Quality Assurance integrates the entire software development process. This includes defining requirements and integration, architecture and design, coding conventions, code reuse, source code control and revision, code reviews and testing regimen.
Defining Requirements and Integration
Requirements typically definitions follow the procedures established in the Quality Management System for Project Management
A Project Management repository will include a category for software products. This category will include a software product checklist (contract, source code, requirements, design, tools and tech, testing, distribution, docs and metadata, and post-project work)
A project manager will provide a Product Description, which defines the acceptance criteria for the software project; the Product Description is subject to change as the project develops.
The Project Manager shall determine release management, based on the satisfaction of client acceptance requirements, and teh future integration into subsequent projects and programmes.
Architecture and Design
The software Design Principles analyses the requirements of the Product Description to generate an architecture design. Analysis shall include:
* Communication and clarification with stakeholders if there is ambiguities in requirements, in accordance to the communication strategy adopted by the project.
* Identifying potential conflicts in requirements and resources, proposing solutions, and resolving conflicts to the client's acceptance.
* Maintaining records of the analysis.
When the analysis is complete, a software architecture will be produced. The software architecture will indicate the relationships and properties between elements of the software system at a high level. It will also indicate particular practises selected for implementation, where deemed appropriate. The particular architecture description language (ADL), view model, framework, and style pattern, will vary according to the specific project and team members involved.
In accordance with the project's communication strategy, the architecture will be provided to the client for review. Once accepted, the record of the architecture will be retained to encourage reuse of designs between projects, and within the current project.
In the implementation of the architecture, coding conventions will be followed. Conventions reduce the cost of maintenance, improve readability, provides an easier pathway for refactoring, and easier task automation.
All coders must follow the convention established at the start of the project.
All code should be self-documenting, that is, it should be written in a way that:
* Has a consistent naming convention within the program which applies for that language throughout the project.
* Has identifiers (variables, types, functions, etc) are written in a descriptive and human-understandable manner ("Pascal-style"), rather than a terse and abstract manner ("Fortran-style"). Avoid type notation (e.g., Hungarian notation or positional notation).
* At the beginning of each file or the start of a method definition should provide an overview to establish the external context for the code, except in the case of math-based formulas etc.
* Provides clarity and readability from following structured and procedural programming paradigms, with deviations for the case of early exit (e.g., return statements, exception handling), coroutines, and state machines, etc.
For file portability, ensure that the editor is saving with tabs, not spaces and that the editor is saving files in the Unix format of terminating newlines with a LF, rather than the LF+CR combinations, as commonly used in MS-Windows, or other. File names must not include spaces.
For other conventions preference is given to use;
* the formatting conventions of the language that is being used, or;
* the formatting conventions of the the person who contributed original code to the project, or;
* the conventions via the IDE that is being used, or;
* the tools that can enforce the formatting convention at the time the code is committed.
Coders should use existing, tested, and documented, software knowledge when building new software systems rather than to developing all components of the entire system without reference to prior work.
Code reuse is both opportunistic and planned. It is opportunistic in the sense that when provided with work packages within a project that coders must seek existing components that they can reuse. It is planned in the sense that coders must write code with components that will be reusable in future projects.
In order of preference, (a) seek well-known libraries, design patterns, and frameworks to solve a problem (b) then seek code snippets (including other developers in the company) that have been reviewed and have a compatible license, and modify according to the requirements. If neither of these strategies provides working code, then write the code from scratch.
Source Code Control and Revision
A source code repository must be established at the start of a project. Such a repository must be accessible to the company. If the project requires a private source code repository prefer to mirror as much as possible to a repository that is accessible to the company.
The revision control system should include atomic operations, file locking, version merging. Either a distributed or client-server synchronisation model can be adopted by the project.
Commits should be frequent, with separate commits for source code content changes and formatting changes, to assist in clarity in code diffs.
It is strongly preferred to commit code that passes all automated (unit, functional and integration) tests. Build failures should be fixed immediately.
Source code development must also be integrated with a system for tracking bugs and feature requests.
Code Reviews and Testing Regimen
Production of source code should be carried out with pair programming as often as feasible, which allows for code reviews to be carried out simultaneous to code production.
Individual units of source code should be tested for fitness. Where applicable, test cases should be carried out with normal inputs, and boundary condition inputs, and out-of-bounds inputs.
In accordance with test-driven development, test-cases are carried out first in a complex system to ensure that the feature does not already exist. If it does not pass, a minimum level of code should be generated to pass the requisite tests, which is then refactored to satisfy general principles in coding conventions and those particular to the project. Automated refactoring tools should be used when available. After refactoring, the test case then should be rerun.
Runtime diagnostics should be conducted to aid in analysing potential "soft" errors, with use of common logging libraries.