The post, Software Reviews, demonstrated the value of basing reviews upon business quality expectations. The post, Software Principles, reviewed the foundational concepts found within solid software solutions. The Software Review Checklists in today’s post can be used as a starting point to validate the quality of the work product for each phase of the software development lifecycle.
Checklist Review Guide
If you have not already read the post, Software Principles, now would be a good time. Most of the questions for the Design and Code Checklists are based upon these foundational principles. Having at least an awareness of these principles will help you understand the reason for the questions.
As each phase is based on work from the previous phase, each checklist is cumulative. The design or code phases may reveal missing information from the requirements. Therefore those missing requirements will need to be verified as part of the design review to ensure they are complete.
The code review should also include the checklist from the design review. Rarely does the code reflect the intended design perfectly. Failure to recheck the final code base with the design review checklist can result in design flaws and maintenance issues within the code base. The design check in the code review isn’t about how well the design was implemented but instead verifies how well the final software architecture follows design guidelines. Refactoring plays a strategic part in any code review to ensure the quality of the final product.
Requirements Review
- Have you read Karl Wiegers, Software Requirements?
- Is the business model, process flow and software product technology roadmap adequately documented to the point that the development staff can implement the system, feature or requirement?
- Is the business documentation readily available to the development staff?
- Is it clear what business processes and systems are impacted by the application and how those systems are related?
- Are the actions, results and effects of each feature clearly described?
- Are the feature’s requirements complete and clearly documented?
- Are the requirements documented in measurable terms that can be used to test if the feature is implemented correctly?
- Have non-function, quality requirements been clearly documented so that it can be determined how well the features and requirements have been implemented?
- Is it clear how the requirement will impact or be impacted by other systems?
- Are change requests clearly documented?
- Who requested the feature, requirement or change?
- Who approved the change?
- Why the change was necessary?
- Who implemented the change?
- Why the change was implemented in the way that it was coded?
Design Review
- Does the architecture resemble known code patterns?
- Would the system benefit from the use of an existing code pattern or would the pattern increase functionality beyond cost benefits?
- Is documentation adequate to allow a new developer to understand how to construct the system?
- Entity relationship diagram
- Class diagram
- Sequence diagram
- Activity diagram
- State diagram
- System impact diagram
- Each entity should have a single, clearly defined purpose.
- Does the routine execute a specific action? If it executes more than one action split the routine.
- Does the routine get a specific value?
- Would generalizing the entity provide additional capabilities at a reasonable cost?
- Does the entity clearly implement its behavior or is it unnecessarily complex? Consider splitting the entity into multiple, smaller, more refined purposeful entities. Rewrite the algorithm to make it clearer to understand.
- Are the entities clearly and logically organized?
- Are the entities organized so that they are loosely coupled but have tight cohesion?
- Does the entity have as little knowledge about the other entity as possible or is it required to be aware of more information or behavior than needed? If the answer is more then refactor the consuming entity’s interface by splitting it into a more refined interface.
- Does the entity reference information specific to its purpose? If the entity is referencing information that it does not need consider refactoring the consuming entity into smaller, more refined entities.
- Does the entity have knowledge of an entity that it does not need to manage? Move the actions against the unnecessary or unrelated entity into an entity that should be aware.
- When modifying an existing application.
- Is the new feature being added to an existing class? New functionality should not be added to a class. Only bug fixes can occur to a class. Create a new class that inherits from the existing class adding the new features to the derived class.
- Was new behavior defined in a new interface?
- Create a new interface that inherits from the original interface adding the new functionality to the derived interface.
- A class may implement new functionality when a new interface is added to the class so long as all consuming entities use the interface reference and not the class reference and as long as the new behavior is in alignment with the specific purpose of the class.
- Does the class or interface implement behavior that could be organized into a more refined entity? If the entity forces consumers to reference unnecessary behaviors or if the entity contains behaviors that are not specific to its purpose then refactor the entity into two or more entities.
Refactoring and Code Review
- Business Impact
- Does the code actually provide all the necessary features?
- Are all the feature’s requirements implemented?
- Are any implemented features out of scope?
- Are the implemented features intuitive to the target audience?
- Can the code be easily matched to a requirement, feature or constraint?
- Are all the features and requirements proven?
- How well are the features and requirements implemented? Refer to the quality chart.
- Interface Consumption, Security, Reliability and Usability Focus.
Failure to follow these guidelines may expose the system to code injection attacks, cross-site attacks, buffer overflows or other similar security attacks.- Are all function arguments validated?
- Value required?
- Value out of range?
- Does the value contain the correct format or syntax?
- Is the value within length expectations?
- Does the value contain necessary information?
- Are all results validated?
- Is the state of the entity validated?
- Connection is open?
- Value is instantiated?
- File open? Closed?
- Are configurable options managed outside the application or hard-coded into the application?
- Are all function arguments validated?
- Readability (best reviewed by a developer who was not involved in the coding phase)
- Is the name of each class and routine descriptive and understandable to a new developer?
- Is the algorithm short, straightforward, readable and understandable?
Avoid focus on whitespace, bracketing and other stylistic issues except when it has an obvious impact on readability or unless your working with F# where whitespace has significant meaning. - Can the routine be viewed within a single screen or does it require scrolling to view?
- Can the routine be written more concisely without increasing complexity?
- Does each interface, class, structure, enumerator, routine, constant, variable and parameter follow industry standard casing conventions for the specified language?
- Is each interface, class, structure, enumerator and routine well documented?
- Are units or optional values defined as constants or configurable options?
- Are constants, options, calculations, formulas and complex algorithm’s well documented?
- Does the documentation explain why an entity exists, why the algorithm is designed in the way that it is coded, the expected result of the action and how the result should be used?
- Are comments used to identify missing functionality, unresolved issues or reasons for commented out code blocks?
- If an error is thrown from a line will it be clear which statement in the line broke?
- Technology
- Do all code paths (loops, recursive routines, event sinks) have clear exit strategies or is the code at risk of causing an infinite loop or negatively impacting performance?
- Are system resources managed correctly?
- Resources deallocated?
- Objects disposed?
- Are file handles closed?
- Are streams flushed?
- Connections closed?
- Is the correct technology applied to the problem?
- Should an array be used instead of a collection?
- Should a StringBuilder be used?
- Are errors properly handled?
- Is the code rewriting existing functionality that can be found in another API?
- Does the code conform to the specified language’s best practices guidelines as defined by the manufacturer? Most manufacturers provide a language guide and/or a human interface guide so that the system is usable, secure and maintainable.
- Documentation
- Has the test strategy been adequately documented?
- Configure a test environment
- Configure the application to work in the test environment
- Initializing test data
- Running the various test cases
- Determining validity of test results
- Restoring the test environment for another test run
- Tearing down the test environment
- Has the deployment process (install, configure, update, rollback, remove) been adequately documented?
- Has the support model that defines how to enhance the system adequately documented?
- Has design documentation been updated to reflect the new reality from the code phase?
- Has the test strategy been adequately documented?
Leave a Reply