8年ぶりにプログラマに復帰したのでリーダブルコードを読みました


f:id:fullstuck_sato:20210212125523j:plain
リーダブルコード(美味しいパスタ)

マネックス・ラボでferciの開発と運用をやっている、佐藤です。しばらくソフトウェア開発の本を読んでいなかったので、今更ながらリーダブルコードを読んでみました。

 

なぜ読もうと思ったのか

 私の経歴を簡単に書くと、2012年まではひたすらC++でプログラムを書いていました。一方でインフラも作れるようになりたく、2013年からマネックスでインフラの仕事を始めました。そしてferciチームでインフラを作ったのはいいものの、パブリッククラウドを使っていると、普段はあまりやることがありません。そのとき、ferciのフロントエンドはベンダーさんに依存している側面もあったので、2020年からフロントエンドの開発もやるようになりました。

 そしてiOSのアプリをSwiftで書き始めたわけですが、ソースコードがうまく頭に入ってきません。もちろん時間をかければ少しずつ頭に入ってくるんですが、それでも、常に頭を使って読まなければいけません。前にC++を書いていたときはそうでもなかったはずなのですが。その理由のヒントがないだろうか、と思って読み始めました。

 リーダブルコードという本は原著が2011年11月に、日本語訳は2012年6月に出版されています。読んでみると、当時のGoogleで使われていたであろう言語(C++やPython)を前提とした解説もちらほら散見されるので、今の時代に適用するならばこうしたことも気にした方が良いのでは、という視点で書評を書いてみます。

クロージャの機能をコメントで説明する

 ここ10年くらいで勢いをつけてきた現代的なプログラミング言語の多くは、クロージャの機能を持っています。特に、非同期処理を書くときに、メソッドチェーンと組み合わせてクロージャで非同期な呼び出しと戻り値の処理を書くことが多いと思います。そのときに、mapやfilter、subscriber関数に渡したクロージャで行っている処理について情報がありません。情報がないと書いたのは、名前がついた関数呼び出しをしていれば関数名が情報を持っているけれども、それが無いということです。この失われた情報を補うためには、クロージャの内部をパッと見てわかる内容に留めるか、ある程度複雑なのであれば多少のコメントで処理内容を記載するのが良いのではと思います。

クロージャの引数は説明変数を付けた方がいい

 Swiftのmapのように、クロージャの引数を$0,$1といったように変数の宣言を省略できる場合がありますが、場合によっては一度意味のある名前の変数名に置き換えた方が良いだろうと思います。その言語に慣れているメンバーだけで開発して運用するのであれば不要なのかもしれませんが、他の領域を担当しているメンバーが調査の目的で読み始めたときに、頭を悩ませる可能性があります。

 特にKotlinの場合には、スコープ関数を使うと暗黙的にitという無機質な名前で値がクロージャに渡されます。できるだけ意味のある説明変数を定義した方が、読み手の負担を減らすことができるのではないでしょうか。

コメントはある程度は書いた方がいい

 クラス名とプロパティ、関数名がわかりやすい名前で、綺麗に整理されて書かれていると大体の場合はそのクラスの機能は理解できますが、冗長になったとしても、多少のコメントはあった方が読む人は楽かもしれません。特に汎用的な機能は、簡単にでも良いのでコメントがあると、コード全体が頭に入って来やすいように思います。リーダブルコードの最終章ではカウンタの実装を例にして読みやすいコードの実装例を示していますが、クラス名と関数名をわかりやすい名前に修正した後に、それらに2,3行程度のコメントを書いています。

サンプルコードを書くときも手を抜かない

 私も時々変数名を省略してしまうことがあって、後から考えてみると、実験用の小さい(手抜き)コードを書いたりした後に、プロダクションのコードを書くときにもうっかり省略してしまうことが多いです。つまりは、普段から手を抜かず、名前はいつでもきちんとつける、ということを習慣にすべきかなと思います。

 今の時代はGitHubやブログで簡単にコードを公開できる時代です。今コードを書いている人が手を抜いて読みづらいコードを書くと、これからソフトウェア開発を学ぶ人も読みづらいコードを書いてしまう癖がついてしまいます。OutputStreamをosと略したり(そのストリームは何を開いているんだっけ?)、fugaやhogeといった名前を使わない(その名前からはもはや何も頭に入ってこない)ことが大事ではないかと。

多くの言語にもある書き方で書く

 ほとんどの言語はif elseによる分岐、forによるループを持っているのでは無いかと思います。そして、これらをシンプルに書けるシンタックスシュガーも同時に持っていて、その言語を特徴付けるものにもなっていたりします。ただ、シンタックスシュガーも使いすぎると使い方にムラが出たり、読みづらくなることがあったりします。そういうときは、他の言語と同じ書き方の方が読みやすいのではないか?と一度考えてみることが大切かもしれません。具体例を挙げると、Pythonの条件式even_or_odd = ‘even’ if value % 2 == 0 else ‘odd’’や、KotlinのoptionalValue?.also{} ?: run {}などは、一考の余地があるように思います。Pythonの条件式の場合にはevenを代入したと思ったらその後にifが来たりと、順番に読むとよくわからないですね。Pythonに慣れていれば、全体を見てすぐに頭に入ってくるのでしょうが、慣れていないと混乱します。条件がシンプルで、戻す値が定数などであれば使っても良いなどの決めを入れて、プロジェクトの規約に含めるのが良いのではないでしょうか。Kotlinの場合にはいまだにどのスコープ関数を使うべきかといった議論をよく見かけるので、そういう場合はもはやif elseで良いのではと思います。

全体的に

 結局のところ、読みやすいコードを書くということは、読みやすい文書を作ることと同じなのだろうと思います。適切な言葉を選んで、程よい分量で、段落を切ったり装飾をする。必要に応じて図を入れる。これができる人は、きっと読みやすいコードを書く能力も持っているのではないでしょうか。

佐藤 俊介マネックス・ラボ