Refactoring is defined as the process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its internal structure.
We can identify three decisions made by managers concerning code refactoring:
- Iterative refactoring: your application can’t be developed perfectly in the first iteration, even if the team has the best architects, designers, and developers. The easy way to do refactoring without investing a lot of money and without wasting time is to integrate it into the development process and do it after each iteration.
- Refactoring when it’s necessary: after the application is deployed, some bugs are reported; if resolving them takes a lot of time, or some client needs are very complex to develop and integrate into the existing system, refactoring can be a good solution to improve the quality of the code base. But in this case it can be very risky, and we have to take care to avoid regressions in the existing code.
- No refactoring: sometimes, even if there are many problems in the existing application, refactoring is never started, because the boss does not want to invest in this process, and the support team has to deal with the stress generated by all the bugs and feedback.
If your team regularly refactors their C++ projects and has chosen to use some new C++11/C++14 features, it’s useful to know how other well-known C++ projects refactored their code to use the new standards.
The Chrome browser is a good project to look at: they refactor their code base regularly, and as soon as the new standards were approved and supported by compilers, the Chrome development team chose to move forward with these new standards.
The Chrome browser is a mature C++ project, and it’s very interesting to explore how the code is implemented and designed. Indeed, Chrome is used by millions of users, which requires its development team to write efficient code.
If you decide to refactor your C++ code base to use the new standards’ features, it’s recommended to take a look at this interesting Google document, which lists the allowed C++11/C++14 features and also the banned ones.
What’s most relevant in this document is the banned features and the reasons why they are banned; it’s highly recommended to review this list and check if it’s also applicable to your projects.
Here are the banned C++11/C++14 features from the document:
C++11 Banned Features
| Feature or Library | Snippet | Description | Documentation Link | Notes and Discussion Thread |
|---|---|---|---|---|
| Inline Namespaces | inline namespace foo { ... } |
Allows better versioning of namespaces | Inline namespaces | Banned in the Google Style Guide. Unclear how it will work with components. |
long long Type |
long long var = value; |
An integer of at least 64 bits | Fundamental types | Use a stdint.h type if you need a 64bit number. Discussion thread |
| Ref-qualified Member Functions | class T {
void f() & {}
void f() && {}
};
t.f(); // first
T().f(); // second
std::move(t).f(); // second |
Allows class member functions to only bind to |this| as an rvalue or lvalue. | const-, volatile-, and ref-qualified member functions | Banned in the Google Style Guide. May only be used in Chromium with explicit approval from styleguide/c++/OWNERS. Discussion Thread |
| User-Defined Literals | type var = literal_value_type |
Allows user-defined literal expressions | User-defined literals | Banned in the Google Style Guide. |
| thread_local storage class | thread_local int foo = 1; |
Puts variables into thread local storage. | Storage duration | Some surprising effects on Mac (discussion, fork). Use SequenceLocalStorageSlot for sequence support, and ThreadLocal/ThreadLocalStorageotherwise. |
C++14 Banned Features
| Feature | Snippet | Description | Documentation Link | Notes and Discussion Thread |
|---|---|---|---|---|
| Function return type deduction | auto f() { return 42; }
decltype(auto) g() { return 42; } |
Allows the return type of a function to be automatically deduced from its return statements, according to either template or decltype rules. |
Return type deduction | Temporarily banned since it can cause infinite loops in clang. We expect to allow this once that bug is fixed. Usage should be rare, primarily for abstract template code. Discussion thread |
| Generic lambdas | [](const auto& x) { ... } |
Allows lambda argument types to be deduced using auto (according to the rules that apply to templates). |
lambda expressions | Temporarily banned since it can cause infinite loops in clang. We expect to allow this once that bug is fixed. Discussion thread |
C++11 Banned Library Features
| Feature | Snippet | Description | Documentation Link | Notes and Discussion Thread |
|---|---|---|---|---|
| Aligned storage | std::aligned_storage<10, 128> |
Uninitialized storage for objects requiring specific alignment. | std::aligned_storage | MSVC 2017's implementation does not align on boundaries greater than sizeof(double) = 8 bytes. Use alignas(128) char foo[10]; instead. Patch where this was discovered. |
| Bind Operations | std::bind(function, args, ...) |
Declares a function object bound to certain arguments | std::bind | Use base::Bind instead. Compared to std::bind, base::Bind helps prevent lifetime issues by preventing binding of capturing lambdas and by forcing callers to declare raw pointers as Unretained. Discussion thread |
| C Floating-Point Environment | <cfenv>, <fenv.h> |
Provides floating point status flags and control modes for C-compatible code | Standard library header <cfenv> | Banned by the Google Style Guide due to concerns about compiler support. |
| Date and time utilities | <chrono> |
A standard date and time library | Date and time utilities | Overlaps with Time APIs in base/. Keep using the base/ classes. |
| Exceptions | <exception> |
Enhancements to exception throwing and handling | Standard library header <exception> | Exceptions are banned by the Google Style Guide and disabled in Chromium compiles. Note that the noexcept specifier is explicitly allowed above. Discussion thread |
| Function Objects | std::function |
Wraps a standard polymorphic function | std::function | Use base::Callback instead. Compared to std::function, base::Callback directly supports Chromium's refcounting classes and weak pointers and deals with additional thread safety concerns. Discussion thread |
| Ratio Template Class | std::ratio<numerator, denominator> |
Provides compile-time rational numbers | std::ratio | Banned by the Google Style Guide due to concerns that this is tied to a more template-heavy interface style. |
| Regular Expressions | <regex> |
A standard regular expressions library | Regular expressions library | Overlaps with many regular expression libraries in Chromium. When in doubt, use re2. |
| Shared Pointers | std::shared_ptr |
Allows shared ownership of a pointer through reference counts | std::shared_ptr | Needs a lot more evaluation for Chromium, and there isn't enough of a push for this feature. Google Style Guide. Discussion Thread |
| Thread Library | <thread> and related headers, including
<future>, <mutex>, <condition_variable> |
Provides a standard multithreading library using std::thread and associates |
Thread support library | Overlaps with many classes in base/. Keep using the base/ classes for now. base::Thread is tightly coupled to MessageLoop which would make it hard to replace. We should investigate using standard mutexes, or unique_lock, etc. to replace our locking/synchronization classes. |
C++14 Banned Library Features
This section lists C++14 library features that are not allowed in the Chromium codebase.
| Feature | Snippet | Description | Documentation Link | Notes and Discussion Thread |
|---|---|---|---|---|
std::chrono literals |
using namespace std::chrono_literals;
auto timeout = 30s; |
Allows std::chrono types to be more easily constructed. |
std::literals::chrono_literals::operator""s | Banned because <chrono> is banned. |
Conclusion
Exploring the source code of well-known open source projects to discover their design and implementation choices is maybe the best way to learn to write efficient code. Indeed, well-known C++ projects are generally developed by C++ experts who do their best to apply best practices.
To sum up, take a look at the Chromium source code — rest assured it won’t be a waste of time.
