このリポジトリ固有のコーディング規約と、ファイル種別ごとに 指摘されなくても 適用すべき業界 best practice をまとめたもの。
運用方針:
- ファイルを編集する前に、その種別の節を一度確認する
- 規約に反する既存コードを見つけても、スコープを膨らませず別 PR で揃える
- 新しい知見が出たらこのドキュメントに追記する (Claude / contributors どちらでも)
最初は薄い。気付いたものから追記していくこと。
apt-get installの複数行引数はアルファベット順にソートする (Docker docs: Sort multi-line arguments)。 重複追加防止 + merge conflict 低減 + レビュー性向上のため。--no-install-recommendsを必ず付ける。recommends で余計な dev tool が 入ると image が膨らみ、CI の container init が遅くなる。- BuildKit cache mount を活用:
--mount=type=cache,target=/var/cache/apt,sharing=lockedで apt のダウン ロードキャッシュを保持。 - multi-stage で「dev」「ci」を分ける: 人間用 (zsh / sudo 等) を
devstage、CI 用 minimal をbasestage に。同じ Dockerfile の中に同居させてtarget:で切り替える形 (.devcontainer/Dockerfile 参照)。
- 警告フラグは
target_compile_options(... PRIVATE ...)で target スコープに。add_definitions(...)のディレクトリスコープは避ける (フラグが意図しない 別 target に漏れる)。 -Dの universal フラグは cmake/Options.cmake のCCBENCH_*CACHE 変数に集約。コマンドラインから上書き可能にしておく (例:cmake -S . -B build -DCCBENCH_KEY_SIZE=16)。- 新しいプロトコルは
ccbench_add_protocol(...)で宣言 (cmake/ProtocolHelpers.cmake 参照)。 個別のfile(GLOB)/add_executable/add_definitions群は書かない。 cmake_minimum_required(VERSION X.Y)は迂闊に上げない — devcontainer の cmake バージョンと CI の cmake バージョンの両方で評価する。
- action は明示的なメジャー版を pin (
actions/checkout@v6のように)。@mainや@v6.1.2のような floating / patch pin は避ける。 - container job では
--user root+ gitsafe.directory設定が必要。 詳細は #46 の経緯参照。 paths-ignoreで無関係な変更で CI が動かないようにする (docs/, README.md 等)。- secrets はリポジトリ secrets 経由でのみ参照。ハードコードしない。
tx.readの戻り値は必ず check する。詳細は下記tx.readreturns Status — check it。- 未初期化のローカル変数は宣言時に default-init する (
int x = 0;/T* p = nullptr;)。GCC 13 の-Wmaybe-uninitializedが #44 で実バグを表面化した 経緯あり。 autoで受けたStatusを読み捨てない。意図的に捨てたい場合は(void) func(...)+ 理由のコメント、捨てたくない場合は明示的に check。
tx.read はヒット時に Status::OK、ミス時に Status::WARN_NOT_FOUND を返す。ミス時には *body は そのまま (= nullify されない) なので、tx.status_ == TransactionStatus::aborted だけチェックしても不十分 — 前回の read で得た古い body ポインタがそのまま deref されてしまい、Debug+ASan では HeapObject::cast_to の assertion で死に、Release では garbage data を読む。必ず次の形で書く:
Status stat = tx.read(s, key, &body);
if (tx.status_ == TransactionStatus::aborted) return false;
if (stat != Status::OK) return false; // do not skip thisこれは過去 PR #58 で実際に get_material_cost() で抜けていた箇所が
-Werror=unused-variable で表面化したことがある — レビューで指摘する前に
ここを読む / 書く側で意識する。
- commit する前に、変更した C++ ソース (
.cc/.hh/.cpp) をclang-formatで整形する。設定はリポジトリ直下の .clang-format。手元で揃えておけば、後述の CI チェック (#63) との往復が減る。 - 基本は
git clang-formatで staged 差分の範囲だけ整形する。clang-format -i <file>はファイル全体を整形してしまうため、まだ format が揃っていないファイルを触ると無関係な大量差分が混ざる (コードベース全体の一括 reformat は #74 で対応中 — それが merge される までは特にgit clang-formatを使うこと)。 - 大規模な reformat は本来の変更と別 commit / 別 PR にする。整形差分に 本質的な変更が埋もれてレビュー性が落ちるのを防ぐ。
- format チェックを CI に入れる作業は #63 で追跡している。CI が緑になれば 「format 違反のまま merge される」ことはなくなるが、それまでは push 前に 手元で当てる運用で防ぐ。
set -euo pipefailを冒頭に置く (早期失敗 + 未定義変数の検出 + パイプ 途中の失敗を見逃さない)。- long flag を優先 (
--no-install-recommends/--platform)。ワンライナー でない限り、後で見たときに読みやすい方を選ぶ。
- 全体的に 日本語と英語の混在 OK。ただし 1 つのセクションでは統一する。
- コードブロックには言語タグ (
```sh,```cmake,```cpp等) を 付けて GitHub の syntax highlight を効かせる。 - 相対リンクは repository root からの絶対パスではなく、文書からの相対パス で書く (../include/foo.hh のように)。
- 新しい規約に気付いたら、まず追記する (PR レビューで毎回指摘するより ドキュメントに 1 回書いた方が長期コスト低い)。
- 規約の理由は短く併記する: 「なぜそうするか」が分からないと、規約が形骸化 して破られる。
- 規約を曲げるべき例外を見つけたら、その例外もこのドキュメントに書く。