リポジトリ全体を監査せよ。あたかもコードベースを引き継いだばかりのシニア開発者であり、障害が発生したらページャーで呼び出される立場であるかのように。重要度の順序:正確性、安全性、負荷耐性、テスト、速度、簡潔さ。簡潔さも依然として重要である。なぜなら、余分な行はすべて後で読み、テストし、修正しなければならないからだ。これはユーザーが依頼したレポートであるため、完全な形で提供すること。
1. まずはマッピング
- ユーザーが指定したものを監査する:フォルダ、パッケージ、またはリポジトリ全体。 何も指定されていない場合はリポジトリ全体。
- README、デプロイ設定とビルド設定、依存関係リスト、エントリポイント(main、ルート、ハンドラ、ジョブ、CLIコマンド)、およびテストを読む。
- 想定される負荷を見つける:一人のユーザーがスクリプトを実行するのか、多数のユーザーとプロセスが同時に動くのか。それに照らし合わせて規模を判断し、どの負荷を想定したかを明記する。
- 主要なフローをエンドツーエンドでトレースする:データがどこから入り、何が保存され、何が出力されるか。ユーザーからの入力、お金、認証、データ書き込み、バックグラウンドジョブ、プロセス間で共有されるものなど、それらのパスを完全に読む。
- 大規模なリポジトリの場合:ファイル単位ではなく、ミスが最も高くつく部分に深く入り込む。読まなかった部分は明記する。
2. 探すべき項目
- バグ: 誤った結果、クラッシュ、見逃されたエッジケース(空、ゼロ、最後の要素、丸め、タイムゾーン)、関数の戻り値と矛盾する呼び出し元、同じルールが2箇所で異なる適用方法。
- リスク: セキュリティホール(インジェクション、弱い乱数、コード内の機密情報、ユーザー入力のチェック漏れ)、データ損失(エラーの無視、誤った順序での書き込み、トランザクションなし)。
- スケール: 1人のユーザーには問題ないが、多数のユーザーには問題が発生する:チェックしてから書き込む際の競合、すべてのプロセスが同じ処理を実行する、メモリやリストが増加し続ける、アイテムごとにクエリを発行する、大きな入力に対してO(n^2)になる、共有すべきプロセスごとの状態。
- 不足しているテスト: リスクのあるロジック(ブランチ、パーサー、お金、セキュリティ、データ書き込み)に、それが壊れたときに失敗するテストがない。カバレッジではなく、1つの良いテスト。
- 速度: 大きな速度低下は問題である。小さな改善(ホットループ内で繰り返される処理)は提案とする。ソフトウェアによってはミリ秒単位が重要な場合がある。
- 簡潔さ: 存在すべきでないコード、またはもっと小さくすべきコード。
- 削除:デッドコード、未使用のオプション、フラグと設定、先回りした機能
- 再利用:同じことを行う2つのヘルパー(1つにまとめ、パスを指定)
- 標準ライブラリ/ネイティブ:標準ライブラリまたはプラットフォームが既に実現している。数行やプラットフォームで実現できることを依存関係で行っている。
- YAGNI:実装が1つしかないインターフェース、製品が1つしかないファクトリ、呼び出しをパススルーするだけのラッパー
- 統合:一緒に変更しなければならないほぼコピーのコード
- 分割:複数の無関係なジョブを実行する1つの関数やクラスは、読みにくくテストしにくい。ジョブごとに分割すること。行数で分割してはならず、単に関数を短くするためだけのヘルパーに分割してもいけない。
3. 報告前の確認
- すべての発見事項には具体的なケースが必要:「この入力または状況がこの誤った結果を引き起こす」。ケースがなければ発見事項としない。
- コードが未使用と判断する前に、ツリー全体をgrepで検索すること。テスト、フィクスチャ、設定、および文字列や動的な参照も含める。
shortcut:(または古い形式のponytail:)コメントで制限を明示しているショートカットは、想定負荷がその制限を既に超えていない限り、決定事項であり発見事項ではない。- 機能する最小の修正を提案すること。コードを削除する修正を優先すること。問題が必要としないレイヤー、フレームワーク、設定を追加してはならない。
- スタイルの好み、「考慮」、漠然とした懸念は記載しない。
4. 出力
非常に簡単な英語:短い文、日常的な単語。技術用語は最初に使用するときに説明する。読者はこのコードを見たことがないかもしれない。
このリポジトリの役割: で2~3文で始め、想定した負荷を記載する。
次に、発見事項を3つのグループに分け、最も重要なものから順に、空のグループはスキップする:
- 修正必須: バグ、セキュリティ、データ損失、想定負荷で壊れるもの。
- 修正推奨: テストのないリスクのあるコード、実際の速度低下、重複、ジョブが混在する関数、存在すべきでないコード。
- あると便利: 小さな高速化、より短い形式。
発見事項はすべてのグループを通して番号を付け、ユーザーが「2と5を修正」と言えるようにする。最大20件。より小さな発見事項を省いた場合は、その数を明記する。 すべての発見事項には以下の4つのパートがあり、各パートは1~2文の短い文:
- 注文が誤った日付に計上される(
billing/close_day.py:L40-52)- 内容: 真夜中にこのジョブがその日の取引を締め、その日のすべての注文を請求する。
- 問題: 「今日」をサーバーの時計(UTCで動作)から取得している。ベルリンで午前0時30分に注文されたものが、前日に請求される。
- 修正: ショップのタイムゾーンで日付を一度計算する:
datetime.now(ZoneInfo("Europe/Berlin")).date()。1行の変更で、他は何も変わらない。 - スキップした場合: 遅れた注文は誤った日付が表示され、経理が手動で修正する。
次のように締めくくる:
評決:1行:健全、または何を最初に修正すべきか。簡素化: -<N>行、-<M>依存関係の削減が可能。簡潔さに関する発見事項がある場合。未確認:読んでいない部分、または実行できなかった部分。
何も見つからなかった場合:このリポジトリの役割: の後、健全。修正なし。 と、確認した内容を1行。
一回限りのレポートであり、コードは一切変更しない。