良いコメントが良い設計を導く
序
こんにちは、株式会社スマートショッピング エンジニアの hi6okuni です。
年末に読んでいた書籍「A Philosophy of Software Design」(以降、本書と呼ぶ)のコードコメントに関する章(Chapter13&15)が特に印象深かったため、今後自らのコーディング時にも意識したいアイデアをまとめました。
要旨
コメントを適切に記述することは、特にインターフェイス(クラスやメソッド)において重要です。これにより、直感性が高まり、抽象化が十分に行われているかを確認する手助けになります。そのため、コメントはソフトウェア設計プロセスの重要な一部と位置づけられます。
2種類のコメントタイプ
まず、コメントを2種類に分類します。
1️⃣ コードをより詳細化するコメント(lower-level comment)
2️⃣ コードをより抽象化するコメント(higher-level comment)
どちらも必要なコメントとしつつ、本書では後者のコメントをより重視しています。
1️⃣ コードを詳細化するコメント(lower-level comment)
変数名などに残すタイプのコメントで、宣言した対象の単位や境界値、null許容などの詳細を明示することで、コードの正確性を高めます。こちらのタイプのコメントも必要ではあるが、命名でカバーできる範囲が広く必ずしもコメントが必要ではないタイプになります。コードの実装詳細の説明もこちらのタイプに属すると思います。
📝 コメントのコツ
- 大原則、コード自体から読み取れない情報を残す。
- 変数名で用いられている言葉以外の言葉を使って説明し直すと良い。違う言葉で言い換えてあげるだけでもコードの読み手に新しい価値を提供できる。
// Tips:
// horizontalを「左右両側」、paddingを「空白の量」と言い換えて読み手に新しい情報を提供する
// 命名で表現できていない「ピクセル」という単位の情報を提供する
// 各行のテキストの左右両側に残す空白の量をピクセル単位で指定する
const textHorizontalPadding int = 4
「言い換えてあげるだけ」というと簡単に聞こえますが、読み手の視点に立って役立つ言い換えを行うのは意外と高度な「おもてなし」力が試されている気がします。気が利く書き手になれるように日々精進します。
2️⃣ コードを抽象化するコメント(higher-level comment)
主にクラスやメソッドなどのインターフェイスに残すタイプのコメントで、コードの直感性を高めます。インターフェイスを切る作業はコードを抽象化する作業ですが、命名などで伝えきれない抽象化された内容を自然言語でコメントとして補足し、直感性を強化します。抽象化の精度について本書では、「メソッドの利用者がそのメソッドの実装詳細を読まないといけない状態は利用者のコードリーディング時間を無駄に生み出しており、インターフェイスの果たす役割である抽象化に失敗している」と述べています。もっともなことですが、個人的には普段各レイヤーを縦横無尽にコードジャンプして色んな実装詳細を結局読んでいるため耳が痛い話でした。
良い抽象化が行われているインターフェイスには必ずコメントが必要になります。 良い抽象化を「複雑な実装詳細が隠蔽されてシンプルなインターフェイスが提供されていること」であるとした時、その抽象化を説明する手段として「コード」だけを用いると具体的かつ詳細的になりすぎて説明が不足します。言い換えると、命名だけで支えられるインターフェイスは、その抽象化が弱いことを示していると言えるでしょう。
インターフェイス以外の部分でも、コードの挙動について、実装詳細自体を説明するのではなく、実装時の書き手の意図や思考を残すコメント(いわゆるwhyやwhy notのコメント)も、大きく分けるとこちらに分類されると捉えています。
📝 コメントのコツ
- インターフェイスが果たす全体の役割や目的を俯瞰的に捉えて、重要な情報を抽出する。
- 実装詳細の内容は書かない。(逆に実装詳細しか書くことがない場合、そのインターフェイスの抽象化が不足している。)
// Tips:
// マルチスレッド環境での使用に言及し、命名だけでは伝わらない「複数のユーザーやシステムから同時にアクセスされる状況」が想定されていることを強調する
// TaskManagerは、タスクの管理を行うためのシステムです。
// この構造体は、タスクの追加、削除、および照会の各操作を効率的に実行できるように設計されています。
// 全ての操作はスレッドセーフであり、マルチスレッド環境においても安全に使用できるため、
// 複数のユーザーやシステムから同時にアクセスされる状況でも、タスクの整合性とアクセスの効率を保つことが可能です。
type TaskManager struct {
// ...
}
こちらのタイプのコメントの方が前者のタイプよりも書くことが難しいとされています。その要因の一つとしてエンジニアが抽象を具体にする作業(つまりコーディング)をより好む傾向にあることが挙げられていましたが、個人的な感覚としても正しい指摘のように感じました。
システム設計の道具としてのコメント
本書では、自然言語を利用できる「コメント」が最も抽象化を体現できる手段と捉えて、コードを書き始める前に先にコメントを書く「コメントファーストアプローチ」を採用することで、抽象化の具合を点検し、より良いシステムデザインを導くことができると主張しています。 コメントを書くことが最も物事を抽象化する行為であり、良い抽象化はそのまま良いシステム設計と紐づきます。例えばコメントを書くプロセスの中で、
- メソッドに対して、コメントが長く複雑になる場合、インターフェイスが複雑性の隠蔽に失敗している
- メソッドに対して、実装詳細しかコメントとして書くことがない場合、抽象化が不足している
- 変数名に対して、コメントが長く複雑になる場合、変数の置き方が正しくない
上記のようなシステム設計の点検を事前に済ませることになるため、いきなりコードから書き出すアプローチよりも、結果的に良い設計を導くことができるという考え方です。個人の意見としては、主張する内容自体には納得できますが、実際の業務の中で実践できるイメージはなぜかあまり湧きませんでした。本書の中では開発効率が悪化しない理由もいくつか述べられていましたが、適切なコメントを考えて書く作業に慣れていないせいか、どうしても大幅に効率が落ちてしまいそうな予感がします。。
感想
コメントは書かずに済むなら書かない方が良い/優れている印象を漠然と抱いていました。しかし本書で述べられている抽象化とコメントの関係性を踏まえると、良い設計であればあるほどコメントの必要性も高まることが理解できました。コメントに対するスタンスの最右翼が本書の提案するコメントファーストアプローチで最左翼がコメント不要論のUncle Bobなら、私のスタンスは中道左派から中道右派くらいに遷移しました。ゴメンね、Uncle Bob。
参考文献
📝 A Philosophy of Software Design by John K. Ousterhout
Discussion