改訂新版 良いコード/悪いコードで学ぶ設計入門
―保守しやすい 成長し続けるコードの書き方

[表紙]改訂新版 良いコード/悪いコードで学ぶ設計入門 ―保守しやすい 成長し続けるコードの書き方

紙版発売
電子版発売

A5判/408ページ

定価3,520円(本体3,200円+税10%)

ISBN 978-4-297-14622-1

電子版

→学校・法人一括購入ご検討の皆様へ

書籍の概要

この本の概要

本書は,より成長させやすいコードの書き方と設計を学ぶ入門書です。筆者の経験をふまえ構成や解説内容を見直し,より実践的な一冊になりました。

システム開発では,ソフトウェアの変更が難しくなる事態が頻発します。 コードの可読性が低く調査に時間がかかる, コードの影響範囲が不明で変更すると動かなくなる, 新機能を追加したいがどこに実装すればいいかわからない……。

変更しづらいコードは,成長できないコードです。 ビジネスの進化への追随や,機能の改善が難しくなります。

成長できないコードの問題を,設計で解決します。

こんな方におすすめ

  • コードの設計スキルに興味がある人
  • 日々,悪いコードと向き合っていて改善したい人
  • より良いコードを書きたい人

本書のサンプル

本書の紙面イメージは次のとおりです。画像をクリックすることで拡大して確認することができます。

サンプル画像1

サンプル画像2

サンプル画像3

サンプル画像4

サンプル画像5

目次

  • 改訂新版 まえがき
  • はじめに
  • 謝辞

第1章 悪しき構造の弊害を知覚する

  • 1.1 意味不明な命名
  • 1.2 理解を困難にする条件分岐のネスト
  • 1.3 さまざまな悪魔を招きやすいデータクラス
    • 1.3.1 仕様変更時に牙をむく悪魔
    • 1.3.2 重複コード
    • 1.3.3 修正漏れ
    • 1.3.4 可読性低下
    • 1.3.5 未初期化状態(生焼けオブジェクト)
    • 1.3.6 不正値の混入
  • 1.4 悪魔退治の基本

第2章 設計の初歩

  • 2.1 省略せずに意図が伝わる名前を設計する
  • 2.2 変数を使い回さない,目的ごとの変数を用意する
  • 2.3 ベタ書きせず,目的ごとのまとまりでメソッド化
  • 2.4 関係し合うデータとロジックをクラスにまとめる

第3章 カプセル化の基礎―ひとつにまとめる―

  • 3.1 クラス単体で正常に動作するよう設計する
    • 3.1.1 データクラスは単体での正常動作が困難
    • 3.1.2 クラスが自分自身でドメインモデルの完全性を保証する
    • 3.1.3 悪魔に負けない,頑強なクラスの構成要素
  • 3.2 成熟したクラスへ成長させる設計術
    • 3.2.1 コンストラクタで確実に正常値を設定する
    • 3.2.2 計算ロジックをデータ保持側に寄せる
    • 3.2.3 不変で思わぬ動作を防ぐ
    • 3.2.4 変更したい場合は新しいインスタンスを作成する
    • 3.2.5 メソッド引数やローカル変数にもfinalを付け不変にする
    • 3.2.6 「値の渡し間違い」を型で防止する
    • 3.2.7 現実の営みにはないメソッドを追加しないこと
  • 3.3 悪魔退治の効果を検証する
  • 3.4 プログラム構造の問題解決に役立つ設計パターン
    • 3.4.1 完全コンストラクタ
    • 3.4.2 値オブジェクト
    • Column 種類の異なる言語と本書のノウハウ

第4章 不変の活用―安定動作を構築する―

  • 4.1 再代入
    • 4.1.1 不変にして再代入を防ぐ
    • 4.1.2 引数も不変にする
  • 4.2 可変がもたらす意図せぬ影響
    • 4.2.1 ケース1 可変インスタンスの使い回し
    • 4.2.2 ケース2 関数による可変インスタンスの操作
    • 4.2.3 副作用のデメリット
    • 4.2.4 関数の影響範囲を限定する
    • 4.2.5 不変にして予期せぬ動作を防ぐ
  • 4.3 不変と可変の取り扱い方針
    • 4.3.1 デフォルトは不変に
    • 4.3.2 どんなとき可変にしてよいか
    • 4.3.3 正しく状態変更するメソッドを設計する
    • 4.3.4 コード外とのやりとりは局所化する

第5章 バラバラなデータとロジックをカプセル化する実践技法

  • 5.1 プリミティブ型執着
  • 5.2 staticメソッドの誤用
    • 5.2.1 staticメソッドはインスタンス変数を使えない
    • 5.2.2 インスタンス変数を使う構造につくり変える
    • 5.2.3 インスタンスメソッドのフリしたstaticメソッドに注意
    • 5.2.4 どうしてstaticメソッドが使われてしまうのか
    • 5.2.5 どういうときにstaticメソッドを使えばいいのか
  • 5.3 初期化ロジックの分散
    • 5.3.1 privateコンストラクタ+ファクトリメソッドで目的別初期化
    • 5.3.2 生成ロジックが増えすぎたらファクトリクラスを検討すること
  • 5.4 共通処理クラス(Common・Util)
    • 5.4.1 さまざまなロジックが雑多に置かれがち
    • 5.4.2 オブジェクト指向設計の基本に立ち返ろう
    • 5.4.3 横断的関心事
  • 5.5 結果を返すために引数を使わないこと
    • Column C#のoutキーワード
  • 5.6 多すぎる引数
    • 5.6.1 意味のある単位ごとにクラス化する
  • 5.7 アクセス連鎖
    • 5.7.1 尋ねるな,命じろ

第6章 関心の分離という考え方―分けて整理する―

  • 6.1 関心の分離の基本
    • 6.1.1 インスタンス変数ごとにクラスを分割する
    • 6.1.2 依存関係を図式化しよう
  • 6.2 目的の違いを見破り,分離しカプセル化する
  • 6.3 インターフェイスと実装の分離
    • 6.3.1 関心の分離がうまくいかない原因

第7章 関心が混ざったコードを分けて整理する実践技法

  • 7.1 ロジックの流用
    • 7.1.1 単一責任の原則
    • 7.1.2 責任が単一になるようクラスを設計する
    • 7.1.3 DRY原則の誤用
    • Column クソコード動画「共通化の罠」
  • 7.2 継承による関心の混在
    • 7.2.1 スーパークラス依存
    • 7.2.2 継承より委譲
    • 7.2.3 継承による悪しき共通化
    • Column クソコード動画「継承」
  • 7.3 関心が混在する各種事例と対処方法
    • 7.3.1 なんでもpublic
    • 7.3.2 privateメソッドだらけ
    • 7.3.3 スマートUI
    • 7.3.4 巨大データクラス
    • 7.3.5 トランザクションスクリプトパターン
    • 7.3.6 神クラス
    • 7.3.7 巨大なクラスの対処法

第8章 条件分岐―迷宮化した分岐処理を解きほぐす技法―

  • 8.1 条件分岐のネストによる可読性低下
    • 8.1.1 早期returnでネスト解消
    • 8.1.2 コードの見通しを悪くするelse句も早期returnで解決
  • 8.2 switch文の重複
    • 8.2.1 即座にswitch文を書いてしまう
    • 8.2.2 同じ条件式のswitch文が複数書かれていく
    • 8.2.3 仕様変更時の修正漏れ(case文追加漏れ)
    • 8.2.4 爆発的に増殖するswitch文の重複
    • 8.2.5 条件分岐を一箇所にまとめる
    • 8.2.6 よりスマートにswitch文重複を解消するinterface
    • 8.2.7 interfaceをswitch文重複に応用(ストラテジパターン)
    • Column クソコード動画「switch文」
  • 8.3 interface設計の考え方を身につけよう
    • 8.3.1 機能を取り換える単位を見つける
    • 8.3.2 結果と入力が同じかどうかを確認する
    • 8.3.3 interfaceを定義する
    • 8.3.4 interfaceを実装したクラスをつくる
    • 8.3.5 機能を取り換えるしくみをつくる
  • 8.4 条件分岐の重複とネスト
    • 8.4.1 ポリシーパターンで条件を集約する
  • 8.5 型の判定で分岐しないこと
  • 8.6 フラグ引数
    • 8.6.1 メソッドを分離する
    • 8.6.2 ストラテジパターンで機能を取り換えられるようにする
  • 8.7 interfaceの使いこなしが中級者への第一歩

第9章 コレクション―ネストを解消する構造化技法―

  • 9.1 自前でコレクション処理を実装してしまう
    • Column 車輪の再発明
  • 9.2 ループ処理中の条件分岐ネスト
    • 9.2.1 continueで条件分岐のネストを解消する
    • 9.2.2 breakもネスト解消に役立つ
  • 9.3 バラバラなコレクション処理
    • 9.3.1 コレクション処理をカプセル化する
    • 9.3.2 外部へ渡す場合はコレクションを変更できなくする

第10章 設計の健全性をそこなうさまざまな悪魔たち

  • 10.1 デッドコード
  • 10.2 YAGNI原則
  • 10.3 マジックナンバー
  • 10.4 文字列型執着
  • 10.5 グローバル変数
    • 10.5.1 カプセル化とパッケージ依存の設計で影響範囲を小さくする
  • 10.6 null問題
    • 10.6.1 nullを返さない,渡さない,代入しない
    • 10.6.2 null安全
  • 10.7 例外の握り潰し
    • 10.7.1 原因分析困難に陥り開発者を疲弊させる
    • 10.7.2 問題検出時にけたたましく叫ばせる
  • 10.8 設計秩序を破壊するメタプログラミング
    • 10.8.1 リフレクションによるクラス構造および値の変更
    • 10.8.2 型の強みを活かせなくなる,クラス名やメソッド名のハードコード
    • 10.8.3 デメリットを理解し用途を限定すること
  • 10.9 技術駆動パッケージング
  • 10.10 サンプルコードのコピペ
  • 10.11 銀の弾丸

第11章 名前設計―あるべき構造を見破る名前―

  • 11.1 悪魔を呼び寄せる名前
    • 11.1.1 関心事ごとに分割する
    • 11.1.2 関心事にふさわしい命名
    • 11.1.3 大雑把で意味が不明瞭な名前
  • 11.2 名前を設計する―目的駆動名前設計
    • 11.2.1 可能な限り具体的で,意味が狭い,目的に特化した名前を選ぶ
    • 11.2.2 存在駆動ではなく目的駆動で名前を考える
    • 11.2.3 どんな業務目的があるか分析する
    • 11.2.4 声に出して話してみる
    • 11.2.5 利用規約を読んでみる
    • 11.2.6 違う名前に置き換えられないか検討する
    • 11.2.7 関心が分離されているか点検する
  • 11.3 設計時の注意すべきリスク
    • 11.3.1 名前無頓着になるな
    • 11.3.2 仕様変更時の「意味の変化」に警戒
    • 11.3.3 構造改善を妨げるアンカリング効果
    • 11.3.4 会話には登場するがコード上に登場しない名前に注意
    • 11.3.5 名前を知らないものは知覚できない
    • 11.3.6 形容詞で区別しているときはクラス化のチャンス
  • 11.4 意図がわからない名前
    • 11.4.1 技術駆動命名
    • Column 技術駆動命名を用いる分野もある
    • 11.4.2 ロジック構造をなぞった名前
    • 11.4.3 驚き最小の原則
  • 11.5 構造を歪ませてしまう名前
    • 11.5.1 データクラスになりがちな名前
    • 11.5.2 DTO(Data Transfer Object)
    • 11.5.3 クラスが巨大化する名前
    • Column クソコード動画「Managerクラス」
    • 11.5.4 文脈よって意味や扱いが異なる名前
    • 11.5.5 連番命名
  • 11.6 名前的に居場所が不自然なメソッド
    • 11.6.1 「動詞+目的語」のメソッド名に注意
    • 11.6.2 可能な限り動詞1語で済む名前にする
    • 11.6.3 不適切な居場所のbooleanメソッド
  • 11.7 名前の省略
    • 11.7.1 意図がわからなくなる省略
    • 11.7.2 基本的に名前は省略しないこと
    • 11.7.3 そのほか省略をどう判断するか

第12章 コメント―保守と変更の正確性を高める書き方―

  • 12.1 退化コメント
    • 12.1.1 コメントは劣化コピーにすぎないことを理解すること
    • 12.1.2 ロジックの挙動をなぞるだけのコメントは退化しやすい
  • 12.2 コメントで命名をごまかす
  • 12.3 目的や仕様変更時の注意点を読み手に伝えること
  • 12.4 コメントのルール まとめ
  • 12.5 ドキュメントコメント

第13章 メソッド(関数) ―良きクラスには良きメソッドあり―

  • 13.1 必ず自身のクラスのインスタンス変数を使うこと
  • 13.2 不変をベースに予期せぬ動作を防ぐ関数にすること
  • 13.3 尋ねるな,命じろ
    • Column クソコード動画「カプセル化」
  • 13.4 コマンド・クエリ分離
  • 13.5 引数
    • 13.5.1 引数は不変にすること
    • 13.5.2 フラグ引数は使わない
    • 13.5.3 nullを渡さない
    • 13.5.4 出力引数は使わない
    • 13.5.5 引数は可能な限り少なく
  • 13.6 戻り値
    • 13.6.1 「型」を使って戻り値の意図を表明すること
    • 13.6.2 nullを返さない
    • 13.6.3 エラーは戻り値で返さない,例外をスローすること
    • Column メソッドの名前設計
    • Column staticメソッドの扱いに注意

第14章 モデリング―クラス設計の土台―

  • 14.1 邪悪な構造に陥りがちなUserクラス
  • 14.2 モデリングの考え方とあるべき構造
    • 14.2.1 システムとは何か
    • 14.2.2 システム構造とモデリング
    • 14.2.3 ソフトウェア設計におけるモデリング
  • 14.3 良くないモデルの問題点と解決方法
    • 14.3.1 Userとシステムの関係
    • 14.3.2 仮想世界を表現する情報システム
    • 14.3.3 目的別にモデリングする
    • 14.3.4 モデルはモノではなく目的達成手段
    • 14.3.5 単一責任とは単一目的
    • 14.3.6 モデルの見直し方
    • 14.3.7 モデルと実装は必ず相互にフィードバックする
    • Column クソコード動画「Userクラス」
  • 14.4 機能性を左右するモデリング
    • 14.4.1 裏に隠れた真の目的を見破る
    • 14.4.2 機能性をイノベートする「深いモデル」

第15章 リファクタリング―既存コードを成長に導く技―

  • 15.1 リファクタリングの流れ
    • 15.1.1 ネストを解消し,コードの見通しを良くする
    • 15.1.2 意味のある単位にロジックをまとめる
    • 15.1.3 条件を読みやすくする
    • 15.1.4 ベタ書きロジックを目的を表すメソッドに置き換える
  • 15.2 安全にリファクタリングする方法
    • 15.2.1 コードの課題を整理する
    • 15.2.2 テストコードを用いたリファクタリングの流れ
  • 15.3 あやふやな仕様を理解するための分析方法
    • 15.3.1 仕様分析方法1:仕様化テスト
    • 15.3.2 仕様分析方法2:試行リファクタリング
  • 15.4 IDE のリファクタリング機能
    • 15.4.1 リネーム(名前の変更)
    • 15.4.2 メソッド抽出
  • 15.5 リファクタリングで注意すべきこと
    • 15.5.1 機能追加とリファクタリングを同時にやらない
    • 15.5.2 スモールステップで実施する
    • 15.5.3 無駄な仕様は削除することも視野に
    • Column Railsアプリケーションのリファクタリング

第16章 設計の意義と設計への向き合い方

  • 16.1 本書はなんの設計について書いたものなのか
  • 16.2 設計しないと開発生産性が低下する
    • 16.2.1 要因1:バグを埋め込みやすくなる
    • 16.2.2 要因2:可読性が低下する
    • 16.2.3 木こりのジレンマ
    • 16.2.4 一生懸命仕事した感覚だけが残って生産性は悪いまま
    • 16.2.5 国家規模の経済損失
  • 16.3 ソフトウェアとエンジニアの成長性
    • 16.3.1 エンジニアにとっての資産とは何か
    • 16.3.2 レガシーコードに人は引きずられやすい
    • 16.3.3 レガシーコードは高品質設計を妨げる
    • 16.3.4 レガシーコードは本来やるべき開発の工数を減少させる
  • 16.4 課題を解決する
    • 16.4.1 課題が見えないとそもそも設計する意識が生まれない
    • 16.4.2 知覚容易な課題と知覚困難な課題がある
    • 16.4.3 理想形を知ってはじめて課題を知覚できる
    • 16.4.4 変更容易性を比較できないジレンマ
  • 16.5 コードの良し悪しを判断する指標
    • 16.5.1 実行可能コードの行数
    • Column クラスを分割すると読みにくくなる?
    • 16.5.2 循環的複雑度
    • 16.5.3 チャンク
  • 16.6 コード分析をサポートする各種ツール
    • 16.6.1 Code Climate Quality
    • 16.6.2 Understand
    • 16.6.3 Visual Studio
    • Column シンタックスハイライトを品質可視化に利用する
  • 16.7 設計対象と費用対効果
    • 16.7.1 パレートの法則(80:20の法則)
    • 16.7.2 サービスの中心的領域,コアドメイン
    • 16.7.3 重点設計対象の選定には業務知識が必要
  • 16.8 時間を操る超能力者になろう

第17章 設計を妨げる開発の進め方との戦い

  • 17.1 コミュニケーション
    • 17.1.1 コミュニケーションが希薄だと設計品質に問題が生じる
    • 17.1.2 コンウェイの法則
    • 17.1.3 心理的安全性
  • 17.2 設計
    • 17.2.1 「早く終わらせたい」心理が品質低下の罠
    • 17.2.2 粗悪なコードはきれいなコードを書くより常に遅い
    • 17.2.3 設計と実装のフィードバックサイクルを回す
    • 17.2.4 厳密に設計しすぎず,サイクルを回し続けるのがコツ
    • 17.2.5 「パフォーマンスが落ちるからクラスを追加しない」は正しい?
    • 17.2.6 設計ルールを多数決で決めるとコード品質は最低になる
    • 17.2.7 設計ルールづくりのポイント
  • 17.3 実装
    • 17.3.1 割れ窓理論とボーイスカウトの規則
    • 17.3.2 既存コードを信用せず,冷静に正体を見破る
    • 17.3.3 コーディング規約を利用しよう
    • 17.3.4 命名規約
  • 17.4 レビュー
    • 17.4.1 コードレビューをしくみ化しよう
    • 17.4.2 コードを設計視点でレビューしよう
    • 17.4.3 敬意と礼儀
    • 17.4.4 定期的に改善タスクを棚卸しすること
  • 17.5 チームの設計力を高める
    • 17.5.1 影響力を持つレベルにまで仲間を集める
    • 17.5.2 基本はスモールステップ
    • 17.5.3 実感が大事,手を動かしてみよう
    • 17.5.4 フォローアップ勉強会を開いてみよう
    • 17.5.5 勉強会のバッドノウハウ
    • 17.5.6 リーダーやマネージャーに設計と費用対効果の話をする
    • 17.5.7 設計責任者を立てる

第18章 設計技術の理解の深め方

  • 18.1 さらにステップアップするための設計技術書紹介
    • 18.1.1 現場で役立つシステム設計の原則〜変更を楽で安全にするオブジェクト指向の実践技法
    • 18.1.2 リーダブルコード―より良いコードを書くためのシンプルで実践的なテクニック
    • 18.1.3 リファクタリング 既存のコードを安全に改善する(第2版)
    • 18.1.4 Clean Code アジャイルソフトウェア達人の技
    • 18.1.5 レガシーコード改善ガイド
    • 18.1.6 レガシーソフトウェア改善ガイド
    • 18.1.7 レガシーコードからの脱却―ソフトウェアの寿命を延ばし価値を高める9つのプラクティス
    • 18.1.8 エンジニアリング組織論への招待〜不確実性に向き合う思考と組織のリファクタリング
    • 18.1.9 プリンシプルオブプログラミング 3年目までに身につけたい一生役立つ101の原理原則
    • 18.1.10 Clean Architecture 達人に学ぶソフトウェアの構造と設計
    • 18.1.11 エリック・エヴァンスのドメイン駆動設計
    • 18.1.12 ドメイン駆動設計をはじめよう―ソフトウェアの実装と事業戦略を結びつける実践技法
    • 18.1.13 セキュア・バイ・デザイン 安全なソフトウェア設計
    • 18.1.14 ドメイン駆動設計入門 ボトムアップでわかる!ドメイン駆動設計の基本
    • 18.1.15 ドメイン駆動設計 モデリング/実装ガイド
    • 18.1.16 ドメイン駆動設計 サンプルコード& FAQ
    • 18.1.17 テスト駆動開発
    • Column バグ退治RPG『バグハンター2 REBOOT』
  • 18.2 設計スキルを高める学び方
    • 18.2.1 インプットは2/アウトプットは8
    • 18.2.2 設計効果を意識する
    • 18.2.3 悪魔の構造を見破る練習
    • 18.2.4 リファクタリングで大幅スキルアップ
    • 18.2.5 設計の良し悪しを説明できることがスキルアップにつながる
    • Column C#と長き旅,そして設計への道
    • 18.2.6 動くコードを書いたら,設計し直してからコミット
    • 18.2.7 設計技術書でさらなる高みを目指そう
  • 参考文献
  • 索引

著者プロフィール

仙塲大也(せんばだいや)

X(旧Twitter) : ミノ駆動(@MinoDriven

青森県出身。大手電機メーカーからWeb業界へ転身。アプリケーションアーキテクトとして,リファクタリングやアーキテクチャ改善,若手の設計スキル育成といった,設計全般を推進する業務に従事。悪しきコードとの戦いの中で設計の魅力に気付く。暇さえあれば脳内でリファクタリングしている。X(旧Twitter)ではプログラミングの風刺動画を不定期で投稿。

登壇実績多数。Developers Summitではベストスピーカー賞など受賞多数。