5.5 KiB
What is this
Contains a written down set of principles and other information on //base/util. Please add to it!
About //base/util:
This directory is meant to house common utilities that can be shared across the whole Chromium codebase. //base is similar, but due to the way //base grew over time, it has not been well organized to allow for fine-grained ownership. Also, there is a mixture of commonly useful utility code and extremely subtle code with performance and security implications. The combination of the two lead to a small number of //base OWNERS enforcing a very high quality bar over a diverse bag of code. The goal of //base/util is to avoid both these issues. Over time, functionality in //base proper will sorted into //base/util and one of two things will occur:
- //base becomes empty and subdirs in //base/util get moved up to //base
- A distinct "core" //base module is distilled out.
We will iterate on this purpose as we add more functionality into this directory.
Structure of //base/util:
- No files other than README.md, and OWNERS are allowed in the top-level directory.
- Subdirectories should be named for a class of functionality; it should be relatively easy to browse the directory and find a utility.
- There is no top-level BUILD.gn. Subdirectories will have their own and are allowed to reference other subdirectories.
Responsibilities of //base/util/OWNERS
- Creating new categories.
- Helping dedupe and organize code being added.
- Ensuring the directory is somewhat browseable.
It is specifically NOT the OWNERS job to gatekeep what is a "good pattern" for Chromium code. Obviously they can still object, but the objection should be considered similar to any other Chromium dev objection.
There will be cases when a utility is deemed to be more negative than positive after it has been landed. The //base/util/OWNERS may aide in coordinating and tracking removal, but responsibility for actually deleting the code and its uses falls to the category OWNERS.
Guidelines for adding code to //base/util/{category}
- You will be added to an OWNERS file under //base/util/category and be responsible for maintaining your addition.
- A //base/util/OWNER must approve of the location of your code.
- Code must be needed in at least 2 places in Chrome and have no "higher layered" directory (eg "//ui/base, //media/base, etc.), that could facilitate sharing.
- Code must have unittests, and coverage should be > 95%.
- Code must have clear usage documentation for all the APIs.
- Public APIs must be in
::util
namespace. All implementation details should be in::util::internal
. Macros, which are not namespaceable, are permitted but should be used sparingly and cause a small pang of guilt. - Implementation and expected usage must be understandable by another OWNER in your subdirectory; if creating a new subdirectory you must find a co-OWNER.
- New subdirectories should have their own BUILD.gn files.
Why not just put new utilities in //base/FooDir?
At some point, //base/util directories could get moved back into //base. Until then, //base/util will
- make a distinct separation between "common useful utility code" from the "extremely subtle code with performance and security implications" that //base also houses.
- remove //base/OWNERS as a bottleneck.
The boundary is still a work-in-progress, but should clear itself up with time after some of the more obviously "utility-esque" classes are moved.
How does this differ from //components
Both //components and //base/util contain subdirectories that are (a) intended for reuse. In addition, //components imposes no global layering in Chromium, so a subdirectory placed in //components can be used from most-to-all layers in the codebase, subject to the dependencies that that subdirectory itself holds.
In spite of these similarities, there are conceptual differences: //components contains things are closer to full features or subsystems (eg autofill, heap profiler, cloud devices, visited link tracker) that are not really intended for large scale reuse.
There is some overlap and at some point it will become a judgment call, but in general, //components are a better fit if the code in question is a feature, module, or subsystem. //base/util is better if it is a more narrow construct such as a data structure, coding primitive, etc.
Why not the "Rule-of-3?"
The Rule-of-3 is a simple guidance on when it makes sense to extract common functionality out versus duplicating it. It has commonly been used in //base as a way of measuring "how general" is this functionality.
Unfortunately, there are reasons for wanting to share code beyond just cleanliness. For example, if you need to guarantee exact behavior across two modules, duplication is not proper even if there will ever only be 2 users.
Furthermore, there is a chicken-and-egg problem that prevents incremental adoption of a utility. For example, someone introduces ThingerDoer in //foo/bar. Later, ThingerDoer is wanted in //foo/qux, but this still fails the rule-of-3 test, MyDoer is created. When //foo/waldo wants it, it's completely a game of chance whether or not the CL author manages to find both classes, wants to spend the time to determine if they've diverged, and then tries to abstract it.
As such, the rule-of-3 runs contrary to the goal of sharing that //base/util is designed to facilitate.
Tips
- if doing a mass-move of code, look at
//tools/git/mass-rename.py