🐚

リーダブルコード要約(備忘録)

2022/04/17に公開

自然なコードは忘れても見るだけで思い出すことができる

おはようございます
こんにちは
ほたー

C#勉強備忘録では主にC#と呼ばれるプログラミング言語の文法をまとめていました。
次のステップとしてWindows Formsを使ったアプリケーション作りを学んでいます。
理由としてはビジュアルで訴えた方が学習の全体像を話しやすく、人に伝わりやすいということをもくもく会の発表から教わったためです。
UdemyでC#を勉強する順番を学び、文法の次はコーディングルールということで リーダブルコード を読み進めることに決めました。
リーダブルコードはオライリージャパンより出版された書籍であり、プログラムのコーディングをより美しくするための原則が書かれています。著者 Dustin Boswell、Trevor Foucher、訳者 角 征典となります。
https://www.oreilly.co.jp/books/9784873115658/

本書は第Ⅰ部~第Ⅳ部、全15章構成になっています。
最後に訳者を知り、Rubyやgroongaのコミッタとしても著名である須藤功平氏による解説が収録されています。
1文で主張したいこと、主張をサポートするポイント、補足説明の順番で要点をまとめます。

理解しやすい名前(1章~4章)

ポイント

  1. 理解するまでにかかる時間が最短になるコードを書く
  2. 変数名は意味が通じる単語にする
  3. コードを読む人が書いた人と異なる解釈をするような名前にしない
  4. コードの書き方、並べ方に意味を持たせよう

1章~4章では読み手がコードを見て理解するまでにかかる時間を最短にするための原則が紹介されていました。コードの「表面上」の改善手法です。
3章の冒頭で全ポイントに通じる鍵となる考えが記載されていましたので引用します。

名前が「他の意味と間違えられることはないだろうか?」と何度も自問自答する。

本書でいう読み手とは会社の同僚や上司、社外の相手先のみならず未来の自分も含まれています。
変数やメソッド名は具体的な名前を使って詳細に説明することで名前だけ見て何をするために存在しているのかがわかるようになります。
例えば自分はユーザーのパスワードを変更する処理をするメソッドをchangePasswordメソッドという名前にしています。
このメソッド名がchangeのような何を更新するかわからない名前やupdPwのような省略された名前では後から見返した時に頭を抱えてしまいます。

コードの書き方、並べ方については一貫性と意味のあるやり方でコードを整形すれば美しいだけでなく修正が楽になります。
例えばCakePHPではBehaviorやTraitの仕組みを利用することで似たようなコードを押し込んで、Model(Table)クラスで使いまわすことができるようになります[1]

正確で簡潔なコメント(5章~6章)

ポイント

  1. ひどいコードの補足説明はいらない、直そう
  2. プログラムの要点、自分が困ったことはコメントに記録する
  3. それやこれといった代名詞を避ける、変換できる言葉を探す
  4. 読み手や未来の自分が読んで興奮しないように正確で簡潔なコメントが求められる

5章~6章ではコメントすべきポイントに正確で簡潔な説明文を入れるための原則が紹介されていました。
5章の冒頭で全ポイントに通じる鍵となる考えが記載されていましたので引用します。

コメントの目的は書き手の意図を読み手に知らせることである

つまり未来にコードを読む場合を想定して文中のコードを採用した理由を受け入れられるように書きます。
コメントすべき箇所として以下の3点があることがわかりました。

  • 実装自分が困った箇所
  • ファイルやクラスの一番上
  • 定義した定数
    逆にコメントすべきでない箇所としてコードからすぐ抽出できる箇所、ひどいコードの捕捉説明があることがわかりました。
    ひどいコードの補足説明は悪あがきと言ってもいいので直すと意図が通じやすくなります。

他のポイントとして「それ」や「これ」といった代名詞を避けること、読んで興奮するようなコメントを書かないことが挙げられます。
コメントには簡潔で正確な文章が求められており、仰々しさや長文は求められていません。

プログラムの切り分け(7章~9章)

ポイント

  1. 比較を書くときは変わらない値を右に書く
  2. if/else文を書く際はreturnする条件があれば上に持ってくることでネストを少なくする
  3. ワンライナーで複数の処理をかくなら説明変数を定義して分解した方がわかりやすい
  4. グローバル変数は使わない、変数のスコープをできるだけ小さくする
  5. 1度しか使わない変数は削除する

7章~9章ではプログラムの流れを追う際に立ち止まったり読み返さないようにするための原則が紹介されていました。
7章の冒頭で全ポイントに通じる鍵となる考えが記載されていましたので引用します。

条件やループなどの制御フローはできるだけ「自然」にする。コードの読み手が立ち止まったり読み返したりしないように書く

食べ物を食べるときにまず細かく切り分け、次に歯で噛んで食べやすいように砕くようなイメージと考えました。
if/else文では肯定形(true)から書き始め、決まりきった結果を返す条件があれば上に持ってくる方が行数が少なくなり、まとまりが良いことがわかりました。
1つの処理の行数は少ない方がいいですが、複数の処理をするならば式を表す変数(説明変数)を定義するとより理解しやすくなることもわかりました。

本書では論理式を読みやすくするための手法としてド・モルガンの法則が紹介されていました。
ド・モルガンの法則は野矢茂樹(著)入門!論理学[2]96ページで次のように紹介されていました。

  1. (AまたはB)ではない⇔(Aではない)かつ(Bではない)
  2. (AかつB)ではない ⇔(Aではない)まとは(Bではない)
    論理学の手法が紹介されていましたが 複雑なロジックをより簡単にする方法がないか探す ということが大事だと感じました。

9章ではプログラム内で使わない変数の削除や変数のスコープを小さくすることで軽量にする手法が紹介されていました。
またグローバル変数を使うと外部から書き換えられる可能性があるので変数を内側の関数だけがアクセスできる「プライベート」スコープにすることも大事だとわかりました。
さらに変数に1度だけ書き込むようにすればより流れがわかりやすくなります。

一度に一つのタスク(10章~13章)

ポイント

  1. プログラムから汎用的なコードを独立させる
  2. コードの各行に対してプログラム上の課題を解決しているのか問いかける
  3. 書いたプログラムを分割し、一度に一つのタスクを行うように書く
  4. 書いたコードの動作について知識を持っていない人でも理解できるようなマニュアルを書く
  5. 読みやすいコードは何も書かないコード、不要なコードは捨てる

10章~13章ではコードを再構成し、より説明しやすいプログラムを作るための原則が紹介されていました。
13章の冒頭で全ポイントに通じる鍵となる考えが記載されていましたので引用します。

最も読みやすいコードは、何も書かれていないコードだ

コードの量が少ないほど、理解に必要な時間が減ります。
プログラムで実行するタスクを分割することで、1タスク内のコードの量が少なくなります。
タスク内で修正が必要になった際にピンポイントで突き止められる点からも、より便利で自然なコードになります。
他の機能でも流用できそうな処理は汎用的なコードとして独立させます。
ポイント4については現在職場で進めているプロジェクトで1ステップ内の全タスクが終了するごとにマニュアルを書いており直近でヒットする考えだと思いました。
操作手順に加え注意点を書きますが、利用者に対して表示している画面だけではわからないことがプログラム内部にあるので辿る必要があります。
タスクが1度に1つのことをしていればよりマニュアルを書く時間を減らせたなあ と思いました。
あとは仕様から削除した機能はマニュアルだけでなくプログラムからも削除した方が軽量化されるので良いです。
いつか読むと買った本が積まれているので尚更そう思います。

本番を簡単にするためのテスト(14章)

ポイント

  1. 本番環境にデプロイするコードを単純にするためにテストコードを書く
  2. テストには有効な入力値を使う
  3. プログラムの作りが単純で、一つしか求めず、他のコンポーネントから独立しているとテストしやすい

14章ではテストコードがなぜ必要か、どういった作り方が良いかが書かれています。
C#で次にテスト駆動開発を学ぼうと考えているので、今後に通じる内容と考えました。
14章の冒頭で全ポイントに通じる鍵となる考えが記載されていましたので引用します。

他のプログラマが安心してテストの追加や変更ができるように、テストコードを読みやすくする。

つまり本番用のコードを読みやすくするにはテストコードを作るのが大切ということです。
加えて読みやすくて保守しやすいものであれば本番用のコードが理解しやすくなります。
テスト用の値は検証に必要な最低限の値を選びます。
本書で示された例の一つに正の値のみ取得してソートする関数において正の値、負の値だけでなく重複した値、空文字まで4つのテストを行う例がございました。
テスト用の関数の命名は Test_<関数名>() という形式にすると分かりやすくなります。
またテスト用に作成した関数が1つのことだけ行っていると用を足して流すくらい単純になります。

発生した課題の解決(15章)

ポイント

  1. 最初から全仕様を決めるのではなく、後から機能実装に応じて発生した問題から設計仕様を修正する。

15章ではウェブサーバの直近1分間と直近1時間の転送バイト数を把握する処理で発生した問題と解決法が紹介されています。細部については割愛します。
重要なのは最初から全仕様を決め込むのではなく、機能実装に応じて発生した問題から設計仕様を変更するプロセスが大事だということです。
アジャイル開発と言い換えることもできるんですかね。
発生した問題を自分だけで抱え込まずに、職場にいる先輩に話すと新しい設計が浮かび上がるという経験がありましたので腑に落ちました。

最後に

本書を通し、良いコードとは冒頭で述べたように 自然なコードは忘れても見るだけで思い出すことができるコード だと結論付けました。
コーディングルールを学習した次はC#を使ったテスト駆動開発を学びます。
テスト駆動開発はテストを通すために本番用のプログラムを実装する手法のことを言います。
本書の10~14章の内容に近く、単純で一つを検証する分かりやすいコードを書く必要があります。

自分の考えになりますが、本書は以下の4点のいずれかに当てはまる方が読むと共感しやすいと感じました。

  • 書いたコードを辿るのに時間をかけている
  • 1年前に書いたコードを修正することになり、どのような動作をしていたか思い出そうとした。すると必要以上に時間がかかり業務時間内にタスクをこなしきれなかった。
  • 新しい言語を学び、文法だけでなくコーディング手法を学びたくなった
  • コーディングの原則がどういったものか忘れたので学びなおしたい

自分は4点のいずれにも当てはまります。
先輩が書いたコードの添削コミットをしていたのを見て、より目的地にたどり着きやすくなったと感じました。
それから職場に「リーダブルコード」や「レガシーコードからの脱却[3]」を持ち込んでいます。
リーダブルコードを読むとコーディングの要諦が掴みやすくなると思いますが、読んだだけではダメで実践あるのみ、と考えています。
そして続けること、コードで伝えることは解説に書かれておりましたが、大切な行動です。

以上になります。
ありがとうございました。Thank you。

脚注
  1. Behaviorを使うか、Traitにするか ↩︎

  2. 入門!論理学 ↩︎

  3. レガシーコードからの脱却 ↩︎

Discussion