Read-only mirrors. Development, issues and pull requests are on GitHub.

summaryrefslogtreecommitdiffhomepage
path: root/Guide/NAMING.md
diff options
context:
space:
mode:
authorLeitwolf112026-10-18 20:00:39 +0300
committerLeitwolf112026-10-18 20:00:39 +0300
commit8d1fb4807edc7920fbecd0554c9c61625827e19c (patch)
treedd3d7e1d4f48ca27140a2bd5f970817ad02ae35a /Guide/NAMING.md
downloadprogmasoft-cpp-8d1fb4807edc7920fbecd0554c9c61625827e19c.tar.gz
Write the first revision of Progmasoft C++ Style
Progmasoft C++ Style is a style guide for C++20, written for anyone who wants a complete rule set to adopt. It writes down the conventions the Progmasoft C++ projects already follow (naming, the clang-format and clang-tidy profiles, exception-free error handling, Doxygen) and decides what they left open. Thirteen chapters under Guide/: 1. Principles: what the guide optimizes for and how to decide a case it does not cover. 2. Formatting: the full .clang-format profile, the reason for each choice, and the rules the tool cannot apply. 3. Naming: casing for every kind of name, acronyms, choosing words, namespaces, files. 4. Files and headers: extensions, #pragma once, includes, what goes in a header, the order inside a class, file size, vendored code. 5. Language: functions, auto, initialization, const and constexpr, casts, integers, strings, enumerations, templates and concepts, lambdas, control flow, and the features not used. 6. Types and classes: struct or class, final, construction, the rule of zero, inheritance, operators, strong types, optional and variant. 7. Errors: no exceptions by default, Expected and Error, invariants, fatal defects, destructors, diagnostics. 8. Ownership and memory: owners and borrowers, views and lifetimes, RAII, containers and deterministic iteration, allocation, undefined behavior. 9. Comments and documentation: Doxygen for public declarations, comments that explain why, TODOs that name an issue. 10. C interfaces: C11 headers, prefixes, opaque types, ownership and failure across the boundary, stability. 11. Concurrency: sharing less, threads, locks, thread-safety annotations, atomics, statics. 12. Testing: unit tests, fuzzing, sanitizers, benchmarks, coverage. 13. Tooling: the compiler flags, the full .clang-tidy profile with the reason for every disabled check, other checks, version pinning. The guide prescribes no test, fuzzing or benchmark framework and no error library; it prescribes how they are used. ADOPTING.md explains how a project points to the guide, copies the profiles and records its deviations. CONTRIBUTING.md explains how to propose a change. The text is licensed under CC BY 4.0. The configuration and code examples are dedicated to the public domain under CC0 1.0, so projects can copy them under their own license. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'Guide/NAMING.md')
-rw-r--r--Guide/NAMING.md94
1 files changed, 94 insertions, 0 deletions
diff --git a/Guide/NAMING.md b/Guide/NAMING.md
new file mode 100644
index 0000000..d575ec8
--- /dev/null
+++ b/Guide/NAMING.md
@@ -0,0 +1,94 @@
+<!-- SPDX-FileCopyrightText: 2026 Progmasoft <support@progmasoft.com> -->
+<!-- SPDX-License-Identifier: CC-BY-4.0 -->
+
+# 3. Naming
+
+A name is the shortest documentation a thing gets, and the one a reader sees most. The casing tells the reader what kind
+of thing a name is before they look it up; the words tell them what it is for.
+
+## 3.1 Casing
+
+| Kind | Style | Example |
+| --- | --- | --- |
+| Namespace | `PascalCase` | `Progmasoft::Tala::Analysis` |
+| Class, struct, union, enum, concept, type alias | `PascalCase` | `ControlFlowGraph`, `using BlockId = std::uint32_t;` |
+| Template type parameter | `PascalCase` | `template<typename Value>` |
+| Function, member function, static member function | `PascalCase` | `AnalyzeLiveness`, `graph.BlockCount()`, `Rectangle::Create` |
+| Local variable, parameter | `camelCase` | `blockCount`, `const Node &node` |
+| Public data member of a struct | `camelCase` | `point.x`, `edge.successor` |
+| Private and protected data member | `camelCase_` | `bits_`, `blocks_` |
+| Constant: `constexpr`, `const` at namespace scope, static constant member | `kPascalCase` | `kMaximumDepth` |
+| Enumerator | `kPascalCase` | `Color::kRed` |
+| Template value parameter | `kPascalCase` | `template<std::size_t kSize>` |
+| Macro | `UPPER_SNAKE_CASE` with a project prefix | `EXAMPLE_ASSERT` |
+| C function and type in a C interface | `snake_case` with a project prefix | `example_parser_create` |
+
+The trailing underscore marks state that an object keeps for itself. A reader who sees `blocks_` inside a member
+function knows it is the object's own field and not a local or a parameter, without any other prefix.
+
+Public data members of a struct have no underscore: a struct is a plain bundle of values that callers read and write
+directly (see [Types and classes](TYPES-AND-CLASSES.md#61-struct-or-class)).
+
+## 3.2 Acronyms and abbreviations
+
+An acronym is one word and is cased as one: `HttpClient`, `ParseUtf8`, `xmlReader`, `kMaxUrlLength`. Two capital
+letters in a row are allowed only for a two-letter acronym that would be unreadable otherwise: `IOError` is wrong,
+`IoError` is right, but `LLVM` stays `LLVM` in a namespace that names the library (`Backend::LLVM`), because that is
+the product's own spelling.
+
+Spell words out. `count`, `index`, `message`, `position` rather than `cnt`, `idx`, `msg`, `pos`. Abbreviations that are
+more common than the word itself are fine: `id`, `url`, `utf8`, `min`, `max`, `ptr` only when it names a pointer whose
+pointee is the subject.
+
+## 3.3 Choosing the words
+
+- **Types are nouns**: `Lexer`, `TokenStream`, `DiagnosticSink`.
+- **Functions are verbs, or questions**: `Parse`, `EmitObject`, `IsEmpty`, `HasErrors`, `CanInline`.
+- **A function that returns a property without work is named for the property**: `Size()`, `Name()`, `Entry()`. No
+ `Get` prefix; reserve `Get` for a lookup that can fail, such as `GetSymbol(id) -> Expected<Symbol>`.
+- **A setter says what it changes**: `SetName`, `Reset`, `Assign`.
+- **Booleans read as statements**: `isVisible`, `hasBody`, `shouldRetry`, `available`. Avoid negatives that cause
+ double negation: `isEnabled`, not `isNotDisabled`.
+- **A factory that validates is `Create`**; one that reads from a source is `From…` or `Parse…`; one that converts is
+ `To…`.
+- **Units go in the name when the type does not carry them**: `timeoutMilliseconds`, `sizeBytes`, `widthPixels`.
+ Prefer a type that carries the unit, such as `std::chrono::milliseconds`.
+- **The scope decides the length.** A loop index over three lines may be `index`; a member that lives for the whole
+ program needs a name that explains itself out of context.
+- **Do not repeat the context.** Inside `class Parser`, the member is `Parse`, not `ParserParse`; in namespace
+ `Diagnostics`, the type is `Sink`, not `DiagnosticsSink`, unless it is also used outside that namespace without a
+ qualifier.
+
+## 3.4 Namespaces
+
+A project's code lives under one root namespace named for the organization or the project, then one level per product
+and component: `Progmasoft::Tala::Backend::LLVM`. Use C++17 nested namespace definitions:
+`namespace Progmasoft::Tala::Analysis`.
+
+Each component owns one namespace and every name in it. Two components do not add declarations to the same namespace.
+
+An implementation detail that must be visible in a header, such as a helper of a template, lives in a nested `Detail`
+namespace, which callers must not use.
+
+A project may keep a short lowercase namespace for a stable data model that is used heavily and qualified often, such
+as an intermediate representation (`tala::core`, `tala::xpp`). This is a deliberate, documented exception, not a second
+convention.
+
+## 3.5 Files
+
+A file is named after the main thing it declares, in the casing of that thing: `ControlFlowGraph.hpp` and
+`ControlFlowGraph.cpp`. A file with several small related declarations is named after their common subject:
+`Diagnostics.hpp`. A directory names a component: `Analysis/`, `Backend/`.
+
+Test files add `Tests`: `ControlFlowGraphTests.cpp`. A benchmark adds `Benchmark`, a fuzz target `Fuzz`.
+
+## 3.6 What not to name things
+
+- Names that differ only in case: `Value` and `value` in the same scope.
+- Names starting with an underscore followed by a capital letter, or containing a double underscore anywhere: the
+ standard reserves them for the implementation.
+- Hungarian notation and type prefixes: `pNode`, `strName`, `iCount`, `m_size`. The type is in the declaration, and
+ `clang-tidy` and the editor show it.
+- `Manager`, `Helper`, `Util`, `Data`, `Info` and `Handler` as the whole meaning of a name. Say what the thing manages
+ or helps with.
+- A name that lies. When the behavior of a function changes, its name changes with it.