仕事でもオープンソースで活動する際も、可読性の高いコードを書くというのは非常に重要なポイントです。
ただ、「可読性」という言葉がとてもあいまいであるのもまた事実。
可読性を上げろ、という号令は売上を上げろ並みに漠然としていますし、またその結果として「俺にとってはわかりやすいコード」が氾濫するということもままあります。
そのため、ここではまず可読性とは何ぞやということを簡単に定義し、それを実現するための方法について紹介していくという感じにしたいと思います。
可読性について
個人的に重要と感じる点は以下3点です。
-
一般的である
例えば、文字列を分割する処理は「Split」という名前が一般的です。そのため、これ以外の名前をつけると(BunkatsuとかDivideとか)基本可読性が下がります。
どういう名前が一般的かは言語によっても異なるため、プログラミング一般と使っている言語双方を加味して、自然な名前を付けるのが重要な点となります。 -
英語として読める
プログラムはほぼ英語ですが、このため英語として読めると可読性が高いです。
例えば、If input.Valid() Then
よりもIf input.IsValid() Then
の方が(微妙に)可読性は高いです。
それと、よくやりがちなのが微妙な短縮です。ColumnNameをCNameにするといったたぐいのものです。せいぜい数文字しか変わらずコードの補完もあるため、通じない可能性のある短縮をするくらいならきっちり書いた方が良いです。 -
短い
長い文書より短い文書の方が読みやすいように、基本短い方が読みやすいです。
ただ、糖衣構文を利用し呪文のようなif文を書いた方がいいというわけではありません。
まずそもそも書かなければならないコード量を減らし、その上で適切な分割を行うということが重要です。
「一般的な処理名で記述されていて英語としても読める、短いコード」。
本文中ではこれを可読性の高いコードとし、それを実現するためのTipsについて紹介します。
一般的である
一般的にしていくには、前述の通りプログラミング全般における常識と、使う言語の文化双方を考慮することが重要です。
先ほどのSplitや他にはtoStringなど、またクラス名は大文字から始めるといった類のものは、概ねどの言語でも共通するものです。これはプログラミング全般における常識です。
これに加え、言語独自の文化というのもあります。
例えば、Key/Valueを持つクラスはJava的にはMap(Map、HashMapなど)ですが.NET的にはDictionaryです。
また、Javaではプロパティ項目に大文字をつけるなんて考えられませんが、.NETではlist.Countのようにプロパティは大文字から始まります(ガイドラインを見てみると、これ以外の差異についてもよくわかると思います。)。
このように言語や環境によって何が一般的かは異なり、また時代によっても変わっていくため実装する言語に合わせスタイルを臨機応変に変えていくのが重要となります。
ただ、多くの開発者は生まれ育った時代と言語のポリシーに束縛されると思います。かくいう私もJava出身のため最初はgetter/setterがない.NETに若干のキモさを感じざるを得ませんでしたし、1.5に入った拡張forへの違和感もありました。
そのため、可読性の高いコードを書いていく場合いったん生まれ育った故郷を離れる必要があります。なるべく新規の構文で書いたり他の言語を身に着けたりするのは、その一助になると思います。
英語として読める
文法として筋が通っていて単語が省略されていないというのが基本筋になります。
変数は主語、関数は動詞、これらで英文を書く、というような心がけが必要です。
下の二つは同じ2つの座標間の距離を計算するものですが、2つめの方が可読性は高いはず。
def calc(a, b, c, d):
return math.sqrt((a - c) ** 2 + (b - d) ** 2)
def measure_distance(x1, y1, x2, y2)
return math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2)
距離なら座標が思い浮かぶx
やy
を使った方が断然処理のイメージもわくはずです。
繰り返しになりますが、変数・関数、そして引数の名前まで、処理を「読める」名前を決定します。長いコメントを書くぐらいならプログラムを読めるようにしたほうがいいです。
名前付けでは、名詞動詞の組み合わせは間違えやすいので注意が必要です(CheckAuthorizeでなくCheckAuthorizationなど)。
やろうとしている処理を英語で書いてみてGoogleにかける、というのはメソッド名の検討などに役立ちます(日本語単語の英語を探すのでなく)。文脈の中で適切な用法であるものにするには、単語より文書で検索した方が良いです。
テクニック的な面では、メソッドチェーンはこの点の可読性を向上させるのに有用です。
メソッドチェーンを利用した例(イメージ)
sql.add(filter.on("POINT").greaterEqual(0).lessThan(1))
list.where((item) -> item.hasValue).select()
特に.NETではLINQとオブジェクトプロパティを利用しかなり可読性を上げられます。
基本クラスのを拡張することで可読性を上げられるケースもあります。
Dim SystemCode = "CX01".toSystemCode()
If list.hasNGItem Then ...
※ただ、基本クラスの拡張が可能かどうかは言語に依存します(.NETではExtension、Rubyではオープンクラス、Scalaでは暗黙型変換からの拡張etc...)。数理系の処理である場合、Operator Overrideも有用な選択肢です(ただ、デバッグ性を落とす危険もはらんでいるので、使用に当たっては注意が必要)。
##短い
処理を短くするのに重要な点は、下記点です。
- 書かない努力をする
- 実装しない努力をする
- 構造化する
1点目ですが、まずもって「そもそもそのプログラムを作るべきなのか」という点は良く問うべきです。最も可読性が高いプログラムは存在しないプログラムであるということを忘れてはなりません。
2点目は、既存のライブラリがあるならそれを活用し、そもそも必要のない処理は書かないようにするべしということです。
ただ、これは闇雲にgemなどを入れればいいというわけではありません。特に数年前に更新されたきりのものやあまり使われていないライブラリをじゃんじゃん入れるなんてことをすると目も当てられない惨事になります。
そんなことをしなくても最近は言語自体の標準ライブラリが充実しているので、その機能を探すだけでも書かなくていいコードを減らすことができます(Pythonのcollectionsなど)。ライブラリを導入する場合は実績があるメジャーなライブラリ(apache commonsなど)を検討します。
なんにせよ、「書かなければ読む必要はない」ですし、その動作が既に保障されているものであればいうことはありません。
3点目でようやく、構造化、つまり適切なクラス化や機能分割を検討します。
ここは「自分の頭だけで考えない」ことが重要です。
世の中には、デザインパターン、そしてアンチパターンをはじめとし様々な「こうしたほうがいい」「これはよくない」といったプラクティスが既に存在します。まずこれらの知識をきちんと吸収し、設計を独りよがりなものにしないことが重要です。
最近のフレームワークでは、チュートリアルが非常に充実しておりそこに設計で気を付けるべき点なども書いてあります(Reactの例)。とかく「動けばOK」という風になりがちですが、英語だろうとチュートリアルと開発者ガイドの2ページぐらいはきちんと上から下まで読む価値はあると思います。
ただ、闇雲にパターンにはめようとすると逆に無理が出たりするので、知識をベースとしたうえで「その現場で最も効率的な」設計を行うことが重要です。なんにせよ知識がないと「ここはObserverで行こうか」みたいな議論も発想も出てこないので、基礎的な知識については知っておく必要があります。
上記点に気を付けることで可読性の高いコードを書くことができる、はず。