📖

「リーダブルコード」を読み終えて 〜 技術書の備忘録

に公開

https://share.google/ixOe6HthvbX0DETob

『リーダブルコード』を読み終えたので、特に重要だと思ったポイントを整理しておきます。
自分はサーバーサイド Ruby on Rails、フロントエンド Next.js (React) の技術スタックで開発しているので、日々の業務で使える形に落とし込んでまとめました。

本書のひとこと概要

「優れたコード」とは何かという定義を明確にし、誰かがそのコードを理解するまでにかかる時間を最短にするための、具体的で実践的なテクニックが学べる書籍です。

特に重要だと感じた章をピックアップ

「優れた」コードの定義

本書における読みやすさの基本定理は、「コードは他の人が最短時間で理解できるように書かなければいけない」という点に集約されます。
単に「コードが短い」ことが良いのではなく、たとえ行数が増えたとしても、読み手が立ち止まらずに理解できる「安心感」があるコードこそが優れたコードです。

Next.js での例:複雑な条件レンダリング

三項演算子を重ねるよりも、早期リターン(ガード節)を使って「何を表示しないか」を先に処理したほうが、メインのロジックが直感的に理解しやすくなります。

// ❌悪い例:簡潔だが、条件が増えると追いかけるのが大変
const UserProfile = ({ user, isLoading }) => {
  return isLoading ? <Spinner /> : !user ? <Error /> : <Details user={user} />
};

// ⭕️良い例:読み手が最短時間で理解できる「安心感」のあるコード
const UserProfile = ({ user, isLoading }) => {
  if (isLoading) return <Spinner /> // 早期リターンで例外を先に排除
  if (!user) return <Error />

  return <Details user={user} />
};

名前に情報を詰め込む / 誤解されない名前を付ける

  • 明確な単語を選ぶ: get や data のような「空虚な単語」を避け、より明確で「カラフル」な単語を選ぶことで、関数の意図を正確に伝えられます。
  • 単位を付加する: 時間を扱う変数なら delay ではなく delay_ms とする。
  • 誤解を招く名前を避ける: filter() は「選択」なのか「除外」なのか曖昧なため、select() や exclude() を検討する。
  • 関数(変数)名で意図を伝える:名前は「短いコメント」として機能させるべきです。名前だけで役割が分かるようにする。

JavaScript での例:関数名で意図を伝える

// ❌悪い例:短い名前をコメントで補足している
const calc = (subtotal, taxRate) => {
  // 小計に税率を足した金額を返す
  return subtotal + subtotal * taxRate;
};

// ⭕️良い例:関数名だけで「何を返すか」が伝わる
const calculateTotalWithTax = (subtotal, taxRate) => {
  return subtotal + subtotal * taxRate;
};

JavaScript での例:誤解されない名前を付ける

// ❌悪い例:filter は「選択」か「除外」か分からない
const filterUsers = (users) => users.filter((user) => !user.isDeleted);

// ⭕️良い例:「除外」であることが明確
const excludeDeletedUsers = (users) => users.filter((user) => !user.isDeleted);

制御フローを読みやすくする

条件分岐やループなどの制御フローは、「自然」でなければいけません。
読み手がコードを読み返したり、頭の中に条件を記憶し続けたりする事態を避けます。

  • 条件式の並び: 左側に「調査対象(変化する値)」、右側に「比較対象(安定した値)」を置く(例:if (age >= 18))。
  • if/else の並び: 否定形よりも肯定形、単純な条件、あるいは関心を引く条件を先に書く。
  • ネストを浅くする: 早期リターンを使って、直線的なコードを目指す。

Ruby on Rails での例:Controller 内での早期リターン

ネストが深いと、どの条件の中にいるのか把握するのが難しくなります。

# ❌悪い例:ネストが深く、条件を最後まで覚えておく必要がある
def update
  if logged_in?
    if current_user.admin?
      # 更新処理...
    else
      flash[:error] = "権限がありません"
    end
  else
    redirect_to login_path
  end
end

# ⭕️良い例:ガード節でネストを削除
def update
  return redirect_to login_path unless logged_in?
  return flash[:error] = "権限がありません" unless current_user.admin?

  # 更新処理(ここがメインロジックだと一目でわかる)
end

巨大な式を分割する / 一度に 1 つのことを

一度に複数のタスクを行うコードは理解を妨げます。
巨大な式は、意味のある単位で「説明変数」や「要約変数」に代入し、タスクを 1 つずつ片付けていくように構成します。

Next.js (React) での例:複雑なロジックの要約

// ❌悪い例:一度に複数の条件を評価しており、意図が読み取りにくい
return (
  <div>
    {user.id === document.ownerId && !document.isLocked && <EditButton />}
  </div>
);

// ⭕️良い例:要約変数を使って「概念」を定義する
const canEdit = user.id === document.ownerId;
const isEditable = !document.isLocked;
const shouldShowEditButton = canEdit && isEditable;

return <div>{shouldShowEditButton && <EditButton />}</div>

無関係の下位問題を抽出する

「この関数が結局何をしたいのか(高レベルの目標)」を自問し、その目標に直接関係のない「下位問題」を別の関数に切り出します。
これにより、メインのロジックがシンプルになり、切り出された関数は再利用可能なユーティリティとして独立します。

Next.js での例:フォーマット処理の抽出

コンポーネントの本質的な役割から、データの整形ロジックを分離します。

// ❌悪い例:URLのクリーンアップ処理がコンポーネントに混ざっている
const ProfileLink = ({ websiteUrl }) => {
  // 下位問題:URLの整形
  const displayUrl = websiteUrl.replace(/^https?:\/\//, "").replace(/\/$/, "");

  return <a href={websiteUrl}>{displayUrl}</a>
};

// ⭕️良い例:メインロジックが明確になり、整形処理は再利用可能になる。(下位問題は別ファイルに切り出して定義する)
const ProfileLink = ({ websiteUrl }) => {
  return <a href={websiteUrl}>{formatUrlForDisplay(websiteUrl)}</a>
};

終わりに

『リーダブルコード』を読んで特に重要だと感じた点をまとめてきました。
Web アプリ開発はコードの量も膨大になるし、チームで開発することが基本になります。
チームメンバーのためはもちろん、未来の自分も助けることになるので、何度も手元で読み返して習得したいと思います。

Discussion