私が思う『良いコード』とは何かを語りたい
久しぶりにシステムエンジニアっぽい話題。
良いコードというのはケース・バイ・ケースであり案件によって異なるものですので、あくまで『私が思う良いコード』についてです。
私がコードに対して持ってる座右の銘は、これです。
動く汚いコードより、動かない綺麗なコード
動く汚いコードはトラブルが発生して動かなくなったときに「なぜ動かないか」が解らず修正が困難ですが、動かない綺麗なコードは誰かが動くように直せば動き、修正が簡単です。故に、トラブルが発生したときのメンテナンス工数に差が出ます。トラブルは必ず発生するものですからね。動く汚いコードを綺麗にするには多大なるコストが掛かりますが、動かない綺麗なコードを動くようにするのはそれほど難しいことではないでしょう。一切トラブルも追加開発も発生しないと仮定するならば動く汚いコードでも問題ありませんが、果たしてそんなことがありうるでしょうか? むしろ、トラブルは起こらないと仮定して開発することに無理があります。よって、動かない綺麗なコードの方が価値がある、と考えています。それはつまり、綺麗であることに大きな価値があるということです。
こう書くと、では綺麗なコードとは何かという話になると思うのですが、綺麗なコードとは「読んで狙いが解るコード」です。*1。
逆に、開発中のみならず、後々メンテナンスしているときにも一番困るのは、『そのコードが何を実現したいコードなのかが解らない』ことです。これ、なんの為に書いてあるの? この条件文は何のために必要なの? というコードです。
単純な話、実装は設計で決められたことをコードに落とし込む作業ですので、コードの内容や実現したいものはそれ以前のフェーズのドキュメントに含まれています。ですので、そういうことは明確でなくて良いでしょう*2。
明確にすべきは、実装の都合上で変則的に書かざるを得なくなった場合など、実装者しか知りえない情報です。本来は、そういう場合はコードを「誰が読んでも意味が通るように修正する」のがまず第一なのですが、それすら難しいと「なぜそのように書いたか」のコメントが必要です。
良くあるパターンですが、読むだけで明確なことにコメントが付いていて不可解な部分についてはノーコメント、というのもあります。下記の例は、読むだけで明確なことにコメントが付いている例です。
// トランザクションを接続文字列を使って作成 Transaction tran = new Transaction(connectionString); // トランザクションを開始 tran.Begin(); // アダプターを作成 Adapter adapter = new Adapter(tran); // リーダーを作成する DataReader dr = adapter.GetReader(sqlCommand); // データコンテナを宣言 Hoge hoge = new Hoge(); while (dr.Read()) { // データを読み込む hoge.Add(dr["fuga"]); } // リーダーを破棄 dr.Dispose(); // アダプターを破棄 adapter.Dispose(); // トランザクションを破棄 tran.Dispose() // 取得した値を返す return hogehoge;
うん、読めば解ることですので、コメント要らないですね。上記のようなコメントは、一行たりとも要らないと私は考えています。こういうのは、(ある程度読める人なら)コードを見ただけで判断付くことです。であれば伝える必要はありません。
こういう、冗長なコメントが多いと、本当に必要なコメントが埋もれます。場合によってはこのような冗長なコメントばかりで、必要なコメントが無いことのほうが多い。これはなぜかというと、多くの人が特にコメントの意味を意識しないで書いているからだと考えています。
私がコードを書くとき・レビューするときに意識するのは、以下の3点です。
- 実装者以外の人間が読んで狙いを理解することができるか?
- 狙いを理解できない場合、そのコードを読みやすく単純化することができるか?
- 単純化することができない場合、的確なコメントをつける
これらは超基本的なことであり、最低限満たすべきものだと考えています。これらの基本が解決できたところで、リファクタリングを始めます。
オブジェクト指向、便利ですね。リファクタリング、素晴らしいです。凝集度を上げて結合度を下げるクラス設計、サイクロマティック複雑度が限りなく低い構造、などなど……。考えればきりがないほど「やるべき基本的なこと」はあります。が、それより前に、もっと超基本的なこととして上記のようなことを実装者とレビュアーは意識するべきだと考えています。
読み間違いは書き手の粗相。メンテナンスが必要以上に難しいコードは、実装者の責任が殆どです。読めない人間を責めるのは難しい。もちろん、言語についての不理解ゆえに読めないのだとしたら、それは読む人間の読解力の問題ですけれどね。コードはみんなの共有物、自分だけが読めたらいいなんてもし思ってる人がいたら、その考えはすぐに捨てて欲しいと思います。だいたい、自分で書いたコードだって半年もしたら意味を忘れてしまいますよ。そんなもんです。
実装の時には時間が無くて、という意見はごもっともではありますし痛いくらい解るのですが、では最初から読みやすくなるよう工夫できないか考えるのが良いです。後から手を入れるときにもです。書くときに「これって後から読んだ人が解るのか?」と自分の書いたコードに対して検証をし続けることです。それを、強く意識しなくても読みやすく書けるよう手癖にするのが肝要だと考えています。忙しいときにコードが汚くなるのは、忙しいからではなく、忙しいことで実装者が焦るからです。これはある程度仕方ないこと。であれば、焦っても大丈夫なように手癖にするのです。手癖になっていれば、後から修正するコストは結構減らせるものです。後々で効いてくるのはこういうことだったりします。
最後に、最低限これだけは読んどけ、という本を一冊挙げておきます。新人には、この本の第一章だけでも読んでおいて欲しいです。デザインパターンやコードコンプリート、インサイド○○なんかよりも断然こっちが先です。