Cover....1
Title Page....2
Copyright and Credits....3
Dedication....4
Contributors....5
Table of Contents....8
Preface....16
Chapter 1: Coding Standards in C++....24
The difference between good code and bad code....24
Why coding standards are important....25
Code convention....26
Language features limitations....28
General guidelines....28
Readability, efficiency, maintainability, and usability....29
Readability....29
Efficiency....30
Maintainability....30
Usability....33
Summary....33
Chapter 2: Main Software Development Principles....34
SOLID....34
The Single Responsibility Principle....35
The Open-Closed Principle....37
The Liskov Substitution Principle....40
The Dependency inversion principle....43
The KISS principle....45
The KISS and SOLID Principles together....46
Side effects and immutability....47
Con.1 – by default, make objects immutable....47
Con.2 – by default, make member functions const....48
Con.3 – by default, pass pointers and references to const....50
Con.4 – use const to define objects with values that do not change after construction....50
Con.5 – use constexpr for values that can be computed at compile time....50
Constness and data races....51
Summary....55
Chapter 3: Causes of Bad Code....56
The need to deliver the product....57
The developer’s personal taste....57
Multiple ways of solving the same problem in C++....58
Revisiting Bob and Alice’s example....58
Raw pointers and C functions versus Standard Library functions....58
Inheritance versus templates....59
Example – handling errors....61
Projects using different approaches....61
Lack of knowledge in C++....62
Using raw pointers and manual memory management....62
Incorrect use of smart pointers....63
Efficient use of move semantics....63
Misusing const correctness....64
Inefficient string handling....65
Undefined behavior with lambdas....65
Misunderstanding undefined behavior....66
Misuse of C-style arrays....66
Insufficient pointer usage....67
Building std::shared_ptr....67
Copying std::shared_ptr by value....67
Cyclic dependencies with std::shared_ptr....68
Checking the std::weak_ptr status....69
Summary....69
Chapter 4: Identifying Ideal Candidates for Rewriting – Patterns and Anti-Patterns....72
What kind of code is worth rewriting?....73
Smelly code and its basic characteristics....73
Anti-patterns....90
The pitfalls of magic numbers – a case study on data chunking....98
Legacy code....100
Summary....104
Chapter 5: The Significance of Naming....106
General naming principles....107
Descriptiveness....107
Consistency....107
Unambiguity....108
Pronounceability....109
Scope and lifetimes....109
Avoid encoding type or scope information....110
Class and method naming....113
Naming variables....114
Utilize namespaces....115
The use of domain-specific language....117
Balancing long names and comments in code....119
Exploring popular C++ coding conventions – Google, LLVM, and Mozilla....120
Summary....121
Chapter 6: Utilizing a Rich Static Type System in C++....122
Utilizing Chrono for time duration....123
Improving Pointer Safety with not_null and std::optional....123
The pitfalls of raw pointers....124
Using not_null from the Guidelines Support Library....124
Utilizing std::optional for optional values....126
A comparison between raw pointers and nullptr....126
Leveraging std::expected for expected results and errors....126
Strong typing with enum class and scoped enumerations....128
A review of enum class....128
The benefits over traditional enums....128
Real-world scenarios....129
Leveraging the standard library’s type utilities....129
std::variant – a type-safe union....129
std::any – type-safe containers for any type....130
Advanced type techniques....131
Avoiding common pitfalls in advanced type usage....133
Writing robust code with type checks....133
Implicit conversions and type coercion....134
Summary....136
Chapter 7: Classes, Objects, and OOP in C++....138
Good candidates for classes....139
Cohesion....139
Encapsulation....139
Reusability....139
Abstraction....139
Real-world entities....139
Manage complexity....140
Minimizing class responsibilities through encapsulation....140
Usage of structs and classes in C++....144
Common method types in classes – getters and setters....146
Inheritance in C++....147
Evolution of inheritance in C++....150
Implementation of inheritance at the binary level....150
Pros and cons of inheritance....150
Base class – Discount....154
Derived class – SeasonalDiscount....155
Derived class – ClearanceDiscount....155
Tight coupling problems....156
Solution – decouple with the strategy pattern....156
Templates and generic programming....160
What are templates good for?....160
Generic algorithms....160
Container classes....161
How templates work....163
How templates are instantiated....164
A real-world example of template usage in C++....165
Defining currencies....165
Defining assets....168
Using the financial system....169
Disadvantages of using templates in system design....169
Summary....176
Chapter 8: Designing and Developing APIs in C++....178
Principles of minimalistic API design....178
Techniques for achieving minimalism....179
Real-world examples of minimalistic API design....182
Common pitfalls and how to avoid them....184
Important caveats of developing shared libraries in C++....184
Shared libraries within a single project....184
Shared libraries for wider distribution....185
Example – MessageSender class....185
Summary....189
Chapter 9: Code Formatting and Naming Conventions....190
Why is code formatting important?....190
Overview of existing tools that facilitate compliance with coding conventions....191
cpplint....192
Artistic Style....193
Uncrustify....193
Editor plugins....194
Clang-Format....195
Clang-Format configuration – a deep dive into customizing your formatting rules....196
Leveraging existing presets....196
Extending and overriding presets....197
Ignoring specific lines with Clang-Format....198
Endless options for configuration....199
Version control and sharing....199
Integrating Clang-Format into the build system....199
Clang-Format report examples....201
Extending for code format checks for CI....205
Clang-Format support across various editors....206
Checking name styling....207
Integrating Clang-Tidy into the build system....209
Checking source code name styling with Clang-Tidy....210
Fixing naming issues automatically....213
Important caveats....214
Example project....215
Clang-Tidy support across various editors....215
Summary....216
Chapter 10: Introduction to Static Analysis in C++....218
The essence of static analysis....218
Leveraging newer compiler versions for enhanced static analysis....219
Compiler settings to harden C++ code....219
GCC....220
Clang....220
MSVC....221
Static analysis via multiple compilers....221
Highlighting compiler differences – unused private members in GCC versus Clang....222
Highlighting compiler differences – compiler checks for uninitialized variables....222
Exploring static analysis with Clang-Tidy....224
Categories of checks in Clang-Tidy....224
Expanding Clang-Tidy’s capabilities with custom checks....225
Fine-tuning Clang-Tidy for customized static analysis....227
Overview of static analysis tools – comparing PVS-Studio, SonarQube, and others to Clang-Tidy....228
PVS-Studio....229
SonarQube....229
Other notable tools....229
Comparison with Clang-Tidy....230
Summary....230
Chapter 11: Dynamic Analysis....232
Compiler-based dynamic code analysis....233
ASan....233
LeakSanitizer (LSan)....253
MemorySanitizer (MSan)....254
TSan....256
UBSan....260
Dynamic code analysis with Valgrind....262
Setting up Valgrind....262
Memcheck – the comprehensive memory debugger....262
Helgrind – threading error detector....264
Performance impact, fine-tuning, and limitations....266
Other notable tools in the Valgrind suite....267
Data Race Detector (DRD) – a thread error detector....267
Cachegrind....267
Callgrind....267
Massif....267
Dynamic heap analysis tool (DHAT)....267
Summary....268
Chapter 12: Testing....270
Test-driven development....271
Unit testing in C++....272
C++ unit testing frameworks....272
Google Test and Google Mock....273
Integrating Google Test into a C++ project....273
Usage of Google Test in C++ projects....275
Writing a simple test....275
Using a test fixture....276
The main function....277
Running Google Test tests....277
Advanced features of Google Test....279
Using gMock in C++ projects....280
Example of using gMock....281
Mocking non-virtual methods via dependency injection....284
Mocking with templates....286
The Nice, the Strict, and the Naggy....288
Other notable C++ unit testing frameworks....292
Catch2....292
Boost.Test....292
Doctest....292
Google Test versus Catch2 versus Boost.Test versus Doctest....292
Good candidates for unit tests....293
E2E testing in software development....294
E2E testing frameworks....294
When to use E2E testing....294
Situations favoring E2E testing....295
Complex interactions....295
Real-world environment testing....296
Automatic test coverage tracking tools....297
Automatic test coverage tracking tools with examples....297
Utilizing hit maps for enhanced test coverage analysis....298
Recommendations for code coverage....300
Summary....301
Chapter 13: Modern Approach to Managing Third Parties....302
Overview of linking and shared V threads::ThreadsS static libraries....303
Managing third-party libraries in C++....304
Installing libraries with OS package managers....304
Using Git as a third-party manager via submodules....305
Using CMake FetchContent to download libraries....305
Conan – advanced dependency management....306
Conan configuration and features....306
Library locations and Conan Center....306
Configuring static or dynamic linking....307
Extending Conan with custom packages....307
CMake integration....308
Other build system integration....308
Custom integration....309
Conclusion....309
vcpkg....309
Key differences from Conan....309
Operating system support....310
Example of configuring a project with vcpkg....310
Utilizing Docker for C++ builds....311
Summary....319
Chapter 14: Version Control....322
What is a good commit?....323
The principle of singular focus....323
The art of communication....323
The art of refinement....324
Conventional Commits specification....325
Linking code to context....325
Overview and intent....326
Options and usage....326
Origins and adoption....328
Advantages of Conventional Commits....328
Commitlint – enforcing commit message standards....328
Installation....329
Configuration....329
Local usage....329
Customizing rules....330
Basic configuration....330
Custom rule configuration....331
Scope and subject configuration....331
Customizing and sharing configurations....332
Integration with CI....332
Generating changelogs....335
Installation....335
GitCliff usage....335
Utilizing git-bisect in bug hunting....339
Summary....342
Chapter 15: Code Review....344
What is a code review and why is it needed?....344
Benefits of code reviews....345
Preparing for code reviews....346
Clear guidelines....346
Self-review....347
How to pass a code review....348
Discuss big features with reviewers and code owners before writing code....348
Go over your code before publishing it....348
Make sure the code is compliant with the code convention....348
Code review is a conversation, not an order....348
Remember – your code is not you....349
How to efficiently dispute during a code review....349
Clear justification for changes....349
Reciprocal explanation from reviewees....349
Direct communication....350
Involving additional perspectives....350
How to be a good reviewer....350
Initiate the conversation....350
Maintain politeness and respect....350
Review manageable chunks....351
Avoid personal bias....351
Focus on understandability....351
Summary....352
Index....354
About Packt....364
Other Books You May Enjoy....365
Improve readability and understandability of code using C++ best practices
Despite the prevalence of higher-level languages, C++ is still running the world, from bare-metal embedded systems to distributed cloud-native systems. C++ is on the frontline whenever there is a need for a performance-sensitive tool supporting complex data structures. The language has been actively evolving for the last two decades.
This book is a comprehensive guide that shows you how to implement SOLID principles and refactor legacy code using the modern features and approaches of C++, the standard library, Boost library collection, and Guidelines Support Library by Microsoft. The book begins by describing the essential elements of writing clean code and discussing object-oriented programming in C++. You'll explore the design principles of software testing with examples of using popular unit testing frameworks such as Google Test. The book also guides you through applying automated tools for static and dynamic code analysis using Clang Tools.
By the end of this book, you'll be proficient in applying industry-approved coding practices to design clean, sustainable, and readable real-world C++ code.
This book will benefit experienced C++ programmers the most, but is also suitable for technical leaders, software architects, and senior software engineers who want to save on costs and improve software development process efficiency by using modern C++ features and automated tools.