Code Reviews, when done right – will make you a Hero!
Best Practices approach for conducting Effective Code Reviews for Software Development Success!
Code Reviews
By John Arrizza
Purpose
The intent of code reviews is to ensure the source code is as easy to understand as possible and therefore finding defects requires minimal effort.
To achieve that goal, code reviews typically focus on:
- Readability
- Compliance to architectural conventions
- Compliance to coding conventions
- Compliance to unit testing conventions
- Compliance to project conventions
Readability
Source code is read by a diverse set of engineers and developers. Having a consistent style, formatting, etc. ensures that there is minimal effort to read and understand the source code.
- Consistent formatting – check that coding style conforms to a common standard across all source files. E.g.
- indent 2 spaces, do not use tabs
- Maximum line length
- Brace placement
- Mandatory braces “{ }” on all if/else/while/for statements
- Specific formatting standards for various document types:
- .c
- .cpp
- .h
- .mk
- .json
- .xml
- etc.
- Documentation style – check that documentation in the source code conforms to a common standard across all source code. E.g.
- Every file has a block comment at the top with a set of mandatory fields and optional fields as applicable:
- Mandatory – copyright notice
- Mandatory – module or component this file belongs to
- Etc,
- Every class has a block comment with mandatory and optional fields as applicable
- Every method has a block comment with mandatory and optional fields as applicable
- All comment blocks shall be compliant with doxygen parsing and layout standards (Note: doxygen is an automated documentation generation utility)
- etc.
- Every file has a block comment at the top with a set of mandatory fields and optional fields as applicable:
- Tracing Conventions – check that all files/classes/methods conform to documentation conventions for tracing to other documents e.g. to the sub-system SDS, to architectural or other high-level design document(s). E.g. Block comments could have a field that indicates:
- an SDS-id to reference that design element
- A reference to a document name in a block comment
- An id to a Unit Trace file or unit test function
- Naming Conventions – check the names of various entities conform to a common standard. E.g.
- Directories e.g. capitalization, snake case, vs camel case
- Source files e.g. snake case vs camel case
- File extensions e.g. .h, vs .hpp
- For C/C++: .h file names match .cpp file names
- Class names e.g. class name matches enclosing file name
- Function names e.g. snake case vs camel case, names for getters and setters and other common behaviors
- Variable names e.g. member names vs external names vs public/global names
- Etc.
- Abbreviation conventions – check that abbreviation standards are followed and/or others are disallowed. E.g.
- “_ptr” – indicates a pointer
- “-fd” – indicates a file descriptor
- Etc.
Compliance to architectural conventions
Architectural conventions ensure that to achieve behaviors required of the system, various implementation techniques and standards are consistently followed.
- Only use certain architectural features
- Multithreading and Multiprocessing conventions
- Globals and singleton conventions
- Startup, shutdown and abort conventions
- Data content and format conventions
Compliance to coding conventions
Coding conventions ensure that low level behaviors that are required of the module or component, various implementation techniques and standards are consistently followed.
- Compliance to external standards
- Switches and nested ifs conventions
- Looping conventions
- Preconditions and guard clause conventions
- Memory allocation and deallocation conventions
- Linking conventions
Compliance to unit testing conventions
Unit Testing conventions ensure that various testing outcomes can be obtained by consistently following various implementation techniques and standards.
- Branch vs line coverage
- Mocks and stubs conventions
- Documentation standards and conventions
- Naming conventions
Compliance to project conventions
Each project will have various other conventions to ensure consistent behaviors and adherence to various implementation techniques and standards.
- I18N (Internationalization) conventions – check that all literal and other strings conform to standards that ensure multi-language compatibility. E.g.
- Use Unicode or UTF-16 etc.
- use wchar_t
- All strings for each language are in a property file and are identified by a text id. All source code uses text ids, not literal strings
- etc.
- Use of exceptions – check that exceptions are thrown and handled in a consistent way. E.g.
- Only use exceptions defined by the project, not language standards
- Do not have empty catch blocks
- etc.
- Communication protocol conventions – ensure any inter-process or client-server communication is consistently implemented:
- Do not use buffered I/O
- Read all input one character at a time
- Only use buffered I/O, only read entire buffers at a time
- Prefer fixed size buffers
- etc.
- Thread and process oriented conventions – ensure that threading and process models and standards are enforced. E.g.
- Only use pthread or boost threads or another common threading library
- Each thread shall have a thread name
- Each thread id is stored in a global queue
- IPC (inter-process communication) shall be via local sockets or shared memory or message queues or another common IPC library
- Mutexes or semaphores or critical section shall be used in various scenarios
- Signals and signal handlers shall be used in various scenarios, e.g. ctrl-c handling, sigabort signals
- Inter process or inter thread communication shall have queues protected by mutexes.
- Etc.
- RTOS (Real-time operating system) conventions – ensure that various RT conventions and standards are enforced. E.g.
- ISRs (Interrupt Service Requests) shall not use stdout or logging facilities
- All incoming events from external devices shall be saved in a mutex protected queue
- Certain RTOS functions are disallowed
- Certain RTOS functions must be used in certain scenarios
- All task priorities shall be N except in certain, justified, scenarios
- Etc.
- OS (operating system) conventions – ensure that interactions with the OS are consistent. E.g.
- All OS interactions shall use system() or a project specific function
- The following OS functions shall not be used
- etc.
- Stdin/stdout/stderr conventions – ensure the use of printf, scanf or other language specific facilities follow a consistent standard. E.g.
- Do not use printf, scanf, etc.
- Only allow printf in certain, justified, scenarios
- Only use project specific logging facilities e.g. LOG()
- Use printk in drivers, do not use printf, etc.
- Etc.
- Versioning and version strings – ensure that all components in the system follow a consistent standard for versioning and version strings. E.g.
- Version strings shall be Major.Minor.Fix.Build
- Major is incremented in various scenarios
- Etc.
- Language features – ensure that the use of certain language features are consistently followed or are disallowed.
John Arrizza is a (software development lifecycle) Process Improvement consultant for Advantu, and supports our clients on an ongoing basis. His expertise helps client teams reduce costly rework and methodically shrink time-to-market, while dramatically increasing customer satisfaction with their products.
Want to verify your Coding Practices are Up to Best Practice Standards?
Take a minute and request a Free Coding Practice Assessment (form below) – you may be closer than you think