2021年5月5日水曜日

読みやすいコードを書くためのテクニック


4月から社会人になり仕事でコードを書くので、今のうちから基礎を固めるためにも関連する技術書を最近Amazonで何冊か買ってみました。

読みやすいコードを書くためのテクニックについて記している『リーダブルコード -より良いコードを書くためのシンプルで実践的なテクニック』もその中の一つで、先日やっと一通り読み終えられたので自分向けのメモも兼ねて概要をまとめてみたいと思います。

※本の要約ではなく、自分が勉強になった部分をピックアップする形で書いています。


■リーダブルコードとは?


まずはじめに、リーダブルコードがどういう本であるかについて簡単に概要を書いてみたいと思います。

リーダブルコードは、プログラミングにおいて「読みやすいコード」を書くための基礎的なテクニックや心がけるべきことをまとめている本です。読みやすいというのは「見やすい」ということだけでなく、「理解しやすい」という意味も含んでいます。

リーダブルコードでは、読みやすさについて「コードは他の人が最短時間で理解できるように書かなければならない」というように表しています。

プログラムのコードを書く時、動くことを優先して可読性が低いコードを書いてしまうと、自分や自分以外がコードを見返した時に「ここの処理何をやっているのか分からない...」と内容の理解に時間がかかったり、コードの修正や追加の作業が困難になってしまう可能性もあります。

それを防ぐためには普段から「他の人が見て理解しやすいコードを書くことを心がける」ことが必要になります。具体的にどういうことをすれば良いのかについてのテクニックをまとめているのがリーダブルコードです。


■読みやすいコードを書くためのテクニック

本で述べられていたことについて、どの章の内容も大事ですが個人的に特に次のことを実践していきたいと思いました:

  • 他の人に見られることや、後でテストすることを意識する
  • 変数名と関数名は分かりやすく、意味のある名前にする
  • コードの見た目を整える
  • 適切なコメントを書く
  • シンプルに書く

・他の人に見られることや、後でテストすることを意識する

これはかなり大事だと感じました。自分で書いたコードが他の人にも見られる、ということを意識するだけでも自然と読みやすいコードを書くようになると思います。

また「後でテストを行うことを意識しながらコードを書く」ことも大事です。例えば、プログラムが密結合していて一つの処理で色々な関数が呼ばれていたり、必要な引数が多く存在したりしているとテストコードが書きにくくなり、テストの実施も面倒になります。
あとでテストを行うということを意識しながら開発すると、自然と読みやすいコードを書くことにもつながります。

(ちなみに、コードを書く前にテストコードを書くというプログラミング手法も存在します。これはTDD(テスト駆動開発)と言い、コードを書いてからテストを書くよりもコードの品質が大きく向上すると言われています。)


・変数名と関数名は分かりやすく、意味のある名前にする

変数や関数に適切な名前をつけるようにするとコードの可読性がかなり増します。名前の付け方について、本で述べられていた例としては

− 役割を的確に・具体的に表す単語を用いる:

例えばweb上からページを取得する関数を考える時、
getPage()
という抽象的な名前にするよりも
downloadPage()
という名前の方が動作を明確に表すことができます。

また、取得したデータをフィルタリングする時、 filterData() という名前にするよりも、特定のデータのみを抽出するのであれば
selectData()
特定のデータのみを除外するのであれば
excludeData()
のように目的を表す名前をつけた方が明確になります。

他にも、関数の仮引数の名前を決める時に delay や limit というようにするのではなく delay_secs や max_kbps のように単位を表す言葉をつけたりすると、ミリ秒を扱う関数なのに秒数を渡してしまった、のように扱う値のミスを抑えることができます。

− 理由なくtmpやiといった名前を多用するのは避ける:

一時的に値を格納するための変数を tmp としたり、for文の中で使用するループイテレータを i とすることは多くあると思います。

tmpのスコープが狭い場合やfor文の設計上問題がない場合はこのままでも大丈夫ですが、例えばfor文が入れ子になっている場合、 i, j, k, ... とつけるよりも扱う値にあった名前(例として member_i, user_i, count_i, ...)をつけるようにすると、インデックスの付け間違い等の誤りに気づきやすくなったりします。

− 長すぎる名前にしない(簡潔にする)

処理内容をしっかり表そうと冗長な名前にしてしまうとかえって分かりづらくなるので、 ConvertToString() を ToString() としたり、 CheckDocument() を CheckDoc() とするなど不必要な部分を削除することも必要です。


・コードの見た目を整える

読みやすいコードを書く上ではコードの「見た目」を良くすることも重要です。見た目を良くするやり方としては、

commands[] = {{"timeout", NULL, cmd_spec_timeout}, {"timestamping", &opt.timestamping, cmd_boolean}, {"tries", &opt.ntry, cmd_number_inf}, ...};
ではなく

// スマホだと表示が崩れるかもしれません、
commands[] = {
    {"timeout",         NULL,                    cmd_spec_timeout}, 
    {"timestamping",   &opt.timestamping,     cmd_boolean}, 
    {"tries",             &opt.ntry,                cmd_number_inf},
     ...
};

のように空白や改行をうまく使って一貫性のあるレイアウトにしたり、同じような処理を行っている部分を関数にしてまとめてしまう、処理が似ている部分ごとに段落分けする、などが挙げられます。


・適切なコメントを書く

コードだけで意図が伝わることが理想的ですが、処理が複雑になってくるとそれは困難であるのと言葉があると読み手の理解度は飛躍的に良くなるので、コメントを残すことは非常に大切です。

どのような場面でどのようなコメントを残すべきかというと、
// メールを送信する外部サービスを呼び出している(1分でタイムアウト)
void SendMail(string to, string subject, string body);
のようにコードの利用者が直面すると考えられる問題への補足説明や、
// ...
//実例: Strip("abba/a/ba", "ab") は "/a/" を返す
String Strip(String src, String chars) { ... }
のように関数を実行した場合の具体的な実行例、
image_quality = 0.72;  // 0.72ならユーザはファイルサイズと品質の面で妥協できる。
のようにそのような実装を行った意図などが挙げられます。他にもコード記述時の自分の考えやコードの欠陥なども、もしある場合はコメントとして残しておくと読み手としては助かります。

なお反対に、関数名や変数名、コードからすぐに分かることやコードと等価なことをコメントに書くのは意味がないので、そういったことはコメントに残すべきではありません。


・シンプルに書く

抽象的な書き方をしてしまいましたが、様々な場面で言えることなので書かせていただきました。あるタスクを行う関数においてタスクと無関係な処理を書かないようにしたり、過剰な機能を持たせないようにする、for文などネストを浅くできるものは浅くするなど、基本的にはシンプルに書くようにしましょう。

ただし何でも短くシンプルに書けば良いという訳でもなく、シンプルに書くとかえって意図が伝わりにくくなるような場面などでは、多少コードが長くなっても読み手が理解しやすいように書くようにした方が良いです。


今回は自分が特に気を付けたいことをピックアップして書かせていただきましたが、リーダブルコードには他にもコードを読みやすくするための様々なテクニックや心がけが書かれています。お時間があればぜひ読んでみてください。

最後まで読んでくださりありがとうございました!

このエントリーをはてなブックマークに追加

0 comments:

コメントを投稿