thumbnail

※本ブログの目的と内容1、著作者の方へ2

基本定理

コードは他の人が最短時間で理解できるように書く。「コードの量」ではなく「理解にかかる時間」を最小にする。

短いコードを書く

要求を詳しく調べれば、問題をもっと簡単にできる。 そうすれば必要なコードは少なくなる。往々にして、プロジェクトに欠かせない機能は過剰に見積もられてしまう。その結果、多くの機能が完成しないか、全く使われないか、アプリケーションを複雑にする。 プログラマというのは、実装にかかる労力を過小評価するもの。実装にかかる時間を楽観的に見積もったり、将来的に必要となる保守や文章化などの「負担」時間を忘れたりする。

新しいコードを書かない

  • 要求を削除する
  • 問題を簡単にする
  • 標準ライブラリを使う
    簡潔なコードを書くのに欠かせないのは、ライブラリが何を提供してくれているかを知ること

軽量なコードを維持する

  • 重複コードを削除する
  • 未使用コードや無用機能を削除する

名前

最善の名前とは、誤解されない名前である。

いい名前

  • 目的や値を表す
  • 抽象的ではなく具体的
  • 「単語」として大切な情報を含む
  • 単位を含む

Tips

  • プロジェクト固有の省略形はダメ
  • スコープが小さければ、情報を詰め込む必要はない
  • エンティティ(変数、クラス、メンバ変数、定数)ごとに異なるフォーマット(アンダースコア・ダッシュ・大文字)を使う
  • ブール値の変数名には、頭にis・has・can・shouldなどをつける
  • 否定形は避ける
  • getは「軽量アクセサ」のみ許される
  • 直行する概念は、無理にまとめず別々に使えるようにする
  • イテレータが複数あるときは、明確な名前をつける

コメント

記録すべき自分の考え

  • なぜコードが他のやり方ではなくこうなったのか
  • コードの欠陥
  • 背景

実例を使う

すべての機能を「見せる」

// 実例: Strip("abba/a/ba", "ab") は"/a/"を返す
String Strip(String str, String chars) { ... }

Tips

  • コードからすぐに分かることをコメントに書かない
  • ひどい名前はコメントをつけずに名前を変える
  • 「ライターズ・ブロック」を乗り越えるには、とにかく書き始めるしかない
  • これからコードをどうしたいのか、自由にコメントを書く
  • 全体像を理解できるコメント書く
    新しいチームメンバーにとって、最も難しいのは「全体像」の理解

変数

説明変数

式を表す変数(式の分割)

before
if line.split(":")[0].strip() == "root":
after
username = line.split(":")[0].strip()
if username == "root":

要約変数

管理や把握を簡単にする変数(大きなコードの塊を小さな名前に置き換える)

before
if (request.user.id == document.owner.id) { ... }
if (request.user.id != document.owner.id) { ... }
after
final boolean user_owns_document = (request.user.id == document.owner.id)
if (user_owns_document) { ... }
if (!user_owns_document) { ... }

変数の削除

  • コードが読みやすくならない変数は削除する
  • 制御フロー変数を削除する
    • タスクをできるだけ早く完了する(早期return)

その他

  • すべての変数の「スコープを縮める」のはいい考え
  • イミュータブルはトラブルになる傾向が少ない

制御フロー

「ガード節」を使い、 ネストは避ける。

条件式の引数の並び順

  • 左側 調査対象の式(変化する)
  • 右側 比較対象の式(変化しない)

if/elseブロックの並び順

  • 条件は肯定形を使う
  • 単純な条件を先に書く
  • 関心を引く条件や目立つ条件を先に書く

テスト

新しいテストの追加や修正を簡単にすることが大切。テストは、「こういう状況と入力から、こういう振る舞いと出力を期待する」のレベルまで要約できる。

優れたテストの書き方

  • テストが何をしているのか、1つの文で記述する
  • 役立つエラーメッセージを出力する
  • 適度にテストが分割されている
  • 極端な入力値を使ってテストする

テスト容易性と設計

テスト容易性の低いコード
特性 テスト容易性の問題 設計の問題
グローバル変数 テストごとに初期化する必要がある 関数にどんな副作用があるのかわかりにくい
多くの外部コンポーネントに依存 最初に足場を設定しなければいけないので、テストを書くのが難しい 任意の変更にどんな影響があるのかを理解するのが難しい等
コードが非決定的な動作 テストは当てにならず、信頼できない プログラムを論理的に判断できなくなる等
テスト容易性の高いコード
特性 テスト容易性の利点 設計の利点
クラスが小さい テストするのにセットアップがあまり必要にならない 状態の少ないクラスは単純で理解しやすい
クラス・関数が1つのことをしている テストケースが少なくて済む システムが疎結合である
他のクラスにあまり依存していない 各クラスは独立してテストできる クラスは他の部分を気にすることなく簡単に修正や削除ができる
インターフェースが明確 明確な動作をテストできる 再利用しやすい

その他

スタイル

コードの「見た目」をよくすれば、コードの構造も改善できる。ただし、一貫性のあるスタイルは、「正しい」スタイルよりも大切。

  • 似ているコードは似ているように見せる
  • 重複を排除するとコードは簡潔になる
  • 意味のある順番にコードを並べる
  • コードも段落で分ける

関数

理想とは程遠いインターフェースに妥協しない。エンジニアリングとは、大きな問題を小さな問題に分割して、それぞれの解決策を組み立てることに他ならない。

  • プロジェクト固有コードから汎用コードを分離する
  • 小さな関数を作りすぎると、逆に読みにくくなってしまう
  • 「一度に1つのタスク」を適用する

その他

  • 読みにくいコードがあれば、まずはそこで行われているタスクをすべて列挙する。そこには別の関数(やクラス)に分割できるタスクがある
  • プログラムを簡単な言葉で説明する。説明することでコードがより自然になっていく
  1. 本ブログは「本を読み、理解した内容の備忘録(自分用)」を目的としている。重要なアイディアを昇華させ、自分の言葉でまとめるように努めている 

  2. 内容に不快を感じ、ブログの取り下げを希望される著作者の方は、個別にご連絡いただけると幸いに思う