-
Notifications
You must be signed in to change notification settings - Fork 0
18 Summary of Dos and Don'ts
JackHeeley edited this page Dec 5, 2020
·
19 revisions
- Do familiarise yourself with this quality reference, (so that you fully understand these dos and don'ts).
- Do manage life-cycle costs by requiring teams to agree standards of code hygiene (such as these dos and don'ts).
- Do communicate general design constraints, and identify different constraints affecting different types of code.
- Do make unit testing and peer reviewing an integral part of every developer's job.
- Do measure track and try to improve unit test and peer review coverage and effectiveness.
- Do revise this checklist regularly.
- Do have a clearly specified set of target environments.
- Do select and maintain a viable re-usability strategy.
- Don't embed platform dependencies into business logic.
- Do use encapsulation to hide complexity, and consider matching architectural components with domain expertise.
- Do adopt a balanced architecture with decomposition in layers (depth and width guided by less-than-five rule).
- Do apply PIMPL pattern to decouple client from implementation, and to allow each to change independently.
- Don't use Boost unless you really have a strong reason, and until you have considered alternatives.
- Do identify cross-cutting issues and have a consistent response to them.
- Do use utf8-everywhere paradigm.
- Do use RAII, and structured exception handling.
- Do prepare a logging strategy early.
- Do use test-driven development.
- Do set and track test coverage targets.
- Don't let platform dependencies limit portability of tests of business logic.
- Don't include platform headers in business logic code.
- Do use ISO C++17 with STL and GSL for business logic.
- Do provide domain specific functional support libraries.
- Don't expect RAII techniques to restore system state (processes can be signalled to stop abruptly).
- Do develop unit tests in parallel with deliverable code.
- Do consider unit tests and deliverable code as integral when planning and budgetting.
- Do extend unit tests to maintain and improve coverage.
- Do regularly measure unit test coverage.
- Don't check-in code without an assessment procedure.
- Do include peer review as a check-in time requirement.
- Do include unit-test results as a check-in time requirement.
- Do invest in people. Select the best possible tools, and provide time and budget for training.
- Do express important checklist points in multiple ways to provide clarity, emphasis and attention.
- Don't expect to learn modern c++ on-the-job.
- Do take time to revise templates. To troubleshoot your code effectively it helps to read and understand STL.
- Don't rely on comment statements for code understanding, and don't over comment.
- Do use intellisense to comment public class functions parameters and return values in headers.
- Do use smart pointers and avoid raw pointers (except with legacy API's).
- Don't try to learn modern c++ on-the-job.
- Do take time to study modern c++ language, STL and GSL.
- Do take time to understand C++ Core guidelines, and use static analyzers to assess your code.
- Do read and assess UTF-8 manifesto, and follow utf-8 everywhere programming rules.
- Don't embed naked operating system calls into business logic.
- Do continously attend to analysis and design in agile projects
- Do regularly assess and manage structure and modularity.
- Don't choose a flat architecture, but do balanced decomposition, in some depth, to less-than-five guidelines.
- Do watch for emerging trends in interface counts and complexity.
- Do establish early how language and tools (eg namespaces and libraries) will act as containers for architectural components.
- Don't forget that goal of encapsulation is to hide complexity, and to limit (localize) need for specific domain expertises.
- Do invest time in selecting the best names for component libraries classes functions and data members.
- Do recognise difficulties in making name selection as a strong indicator of a weakness in design concept or decomposition.
- Don't use acronyms or short forms in names.
- Don't write functions that are much longer than the number of lines visible in the editing window.
- Do write short file and class header comments, and include reference links to design support material.
- Do indicate known limitations with //FIXME: and //TODO: comments
- Do use intellisense comments in headers to document public class interface.
- Do use intellisense comments in source files to document encapsulated functions and data.
- Do design and implement so that business logic can be rehosted at reasonable cost.
- Do design and implement so that support logic can be re-used on other projects.
- Don't get hung up on perfect portability if this isn't a recognized (budgetted) pre-requisite.
- Do start test driven development immediately.
- Don't extend feature content without adding unit tests to cover new features.
- Do monitor test coverage regularly, and set goals to continuously improve.
- Don't allow technical debt to accumulate.
- Do select a unit test framework that will remain viable for the anticipated life-cycle of the solution.
- Do accommodate your answer to cross-cutting issues in unit tests.
- Do use utf8-everywhere coding paradigm in unit tests.
- Do consider unit test support libraries, and building a mock-up framework to assist stateful unit testing.
- Do identify limit and isolate stateful behavior, and favour stateless design for classes.
- Do use PIMPL to localize legacy code styles and use of legacy and system API's.
- Do rigorously apply UTF-8 everywhere, STL GSL and ISO C++ in (.hpp) public interfaces for PIMPL classes.
- Do use precompiled headers and #pragma once.
- Do explicitly include the headers used by headers (.hpp) in the headers themselves.
- Do explicitly include the headers used by source (.cpp) in the source files themselves.
- Don't include platform headers in project headers (.hpp). Restrict platform header use to PIMPL .cpp files.
- Do peer review to confirm asppropriate rule-of-five and rule-of-zero design choices.
- Do apply C++ Core guidance using static analysers frequently, or at build time.
- Do use RAII as primary strategy for avoiding memory leaks.
- Don't rely on RAII techniques to restore system state. (consider also need for signal handlers).
- Do exploit RAII by favouring structured exception handling and throwing std::exceptions when unmanaged errors arise.
- Do consider adding locus/context to exceptions (see error::context) to accelerate time to fix.
- Do favour smart pointers and spans, over use of raw pointers.
- Do make good use of auto type derivation.
- Don't use explicit gsl::as_span on a vector when an automatic typecast is implicit.
- Do take time to study STL features and use patterns, with emphasis on containers and algorithms.
- Do take time to study and understand templates, so you can read and follow STL implementations.
- Do use precompiled header as a place to disable C++ Core false positives and unwanted warnings.
- Do apply a logging strategy that is not locked to a specific logger implementation.
- Do consider all the dos and don'ts from "Effective Modern C++".
- Do keep records and make regular (e.g. quarterly quality reports) giving trends in test coverage, peer review results and bugs found.
- Do regularly assess quality reports and use them to attend to any systematic process weakeness they indicate.
- Do occasionally assess quality reports to reconsider value of sub-classification of issues to identify common causes.
- Do consider check-in time as a compliance opportunity. Write-down and enforce your check-in process that uses a derivative of this quality guidance in the way that you find most acceptable and effective.
- Do consider periodic quality report dates as a compliance opportunity. Assess overall development process effectiveness critically at these points, to promote responsiveness in continuous improvement.
- Do configure warning levels.
- Don't let builds report warnings (Fix code!)
- Do use #pragmas to explictly disable specific instances of particular warnings (after assessment, as last resort).
- Do enable code analysis on build.
- Do strongly favour passing input parameters as const reference.