verbalize

文章書く練習…。

リーダブル・コード(1)

私は現在,人に自分のコードを見てもらう機会はそう多くありません.しかし,今年度は卒業研究を行ったため,作ったプログラムを研究室に残す必要があり,どうせ残すなら読みやすいコードにしたいな,と思い本書を手に取りました.

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

まず,私自身がもともとプログラミングする上でなんとなく意識していたことは次のようなことです.

  • 変数名はより短くするよりも,より客観的に意味が通るものにすべき
  • 変数や関数の命名法は統一すべき
  • 処理は巧妙に短く書くのではなく,多少長くてもストレートに書くべき
  • コメントは書いたほうが良い

この内,日頃最も難しいと感じていた部分はやはり変数名です.客観的に意味の通るちょうどよい名前というのはそう簡単に思いつくものではなく,大体省略形にしたり,特に意味のない単語を割り当てたりしていました.

この記事では,「リーダブルコード」を読んで,特に自分が実践したいと思ったことについてまとめていきます.また,今回は「リーダブル・コード」の第一部のみをピックアップし,基本的には「表面的な部分を変更する」ことでよりコードをリーダブルにする方法をまとめたものです.

1. 命名はより的確な単語を使う

それが思いつかないから困ってるという話なわけですが,ここで言いたいことは,すぐに思いつく「汎用的な単語」を安易に選択せず,より「限定的なニュアンスの単語」を選択するべきだということです.

例えば,

#インターネットからページ情報を取得する
def GetPage(url):

のような関数ならば,GetではなくFetchDownloadを使うとわかりやすくなります.「取得する」んだからとりあえず…と汎用的な単語であるgetを使うと意味がぼやけるのです.他にも,

#textの最後を切り落として「...」をつける
def Clip(text, length):

のような関数では,よくあるlengthを引数として使ってしまいがちですが,長さ(length)の単位によってもっと具体的に

単位 引数
行数 row
文字数 char
単語数 word
バイト数 byte

などを使い分けるのが適切です.このように,より限定的な意味の単語を選択することで読み手の誤解を減らし,わかりやすくすることができます.自分は他にもmakeやconvertを多用する傾向にあるので気をつけたいです.

ただ,ここで問題なのが,それを意識しながらコードを書いても,結局的確な単語を選ぶことは難しいということです.その分野に精通していて,かつ経験もないといけません.なのでまず, 類語辞典codic を使うということを実践していきたいです.これらのサイトを使うことは単に和英辞書を使うよりもおそらく効果的です.まぁ結局は関連分野の用語を学んだり,ソースコードを読んだりできるとベストですかね...

www.kaoriya.net

また,いくら的確な名前でも,長い名前にはどうしてもうんざりしてしまいます.これについては「補完機能を使え」とのことでした.vimならCtrl-Pで補完できます.

2. 命名はパターンに落とし込む

命名においてもうひとつ実践したいのが,わかりやすい命名方法のパターンを学び利用することです. 例えば,

def ConvertToString():

のような関数の場合,Convertは省略して,ToStringだけの方がスマートになります.このように前置詞+名詞の省略形をパターンとして使うことが有効だと考えられます.また,変数名に属性を加えるとわかりやすくなります.これには,

time_s = 10
delay_ms = 100

のように属性として単位を後ろに付けたり,

plaintext_password = "12345"

のようにパスワードが暗号化されていないことを明示するといったものが挙げられます.1つ前に登場したClip()でも,引数のlengthには限界値のニュアンスがあるのでmax_をつけたりするとわかりやすくなります.

3. 命名法はうまく使い分ける

命名法はオブジェクトの種類に応じて変えることで,一種のシンタックスハイライトのようになり,判別しやすくなるという利点があります.よってコード内で完全に統一しなければならないというわけではなく,以下のように「関数名はキャメルケース,変数名はスネークケース」のようによく使われるみたいです.

def ListenToMusic(song_title):

4. コードからすぐわかることをコメントに書かない

今年度の始め頃に,「前年度の研究プログラムを引き継いだは良いが,まるでコメントが書いてない!最悪だ!」というケースを頻繁にみかけました.確かに,「それは最悪かも知れないな」と思うわけですが,そのような事態を受けてか来年度のためにプログラムを残すにあたって「とりあえずコメントは書いてあればまし」みたいな雰囲気がありました.しかし.例えば

# 音声ファイルのパスをコマンドライン引数で受け取る
audio_file = sys.argv[1]

# 音声から振幅値とサンプリング周波数を抽出する
amplitude, sampling_rate = WaveRead(audio_file)

# FFTをして周波数解析する
spectrum = FastFourierTransform(amplitude)

にあるようなコメントは本当に必要でしょうか.これはなんとなく今思いついたコードですが,コメントを書かずとも関数名,変数名,処理の流れから何をしているかが十分に読み手に伝わると思います.このようなコメントを書くのであれば,例えばamplitude配列の要素数が2の累乗になっていない場合,FastFourierTransform()はどのような動作をするのかを簡潔に書いたり,処理のさらに細かい部分の説明を書くべきです.

5.コメントで自分の考えを記録する

また,コメントでは自分がなぜそのようなコード書いたのかということや,そのコードの注意点についてまさに「コメント」しておくことも重要です.例えば,

# 合理的な限界値.人間はこんなに読めない.
MAX_RSS_SUBSCRIPTIONS = 1000

のようなものです.これによって,その記述がなぜそのようになっているのかを読み手に示すことができます.他にも,

# TODO: amplitudeが2の累乗でない場合にはDFTをするようにする
spectrum = FastFourierTransform(amplitude)

のようにTODO:を使って課題点を示したり,

# spectrumのi番目の要素は,i*len(amplitude)/sampling_rate[Hz]の振幅スペクトルの値である
spectrum = FastFourierTransform(amplitude)

のように,あらかじめひっかかりやすい点を明示することで質の良いコメントを残すことができます.他にも,処理の流れやまとまりについて簡単な要約文を残しておくことも有効でしょう.