アジャイル検定Lv.2 勉強メモ - リファクタリング
アジャイル検定Lv.2 出題範囲
- モデリング
- オブジェクト指向設計:継承、インターフェース、ポリモーフィズム、疎結合、Dependency Injection
- コーディング
- コーディングルール:ツールによる確認(checkstyle)
- ペアプログラミング
- リーダビリティ(コードの読みやすさ)
- テストコード(Mock、Testing frameworkなど)
- 静的解析ツール(SonarQube)
- ドキュメンテーション
- 構成管理
- チーム開発:SCM(ソースの変更管理システム)、分散型(git)、集中型(Subversion、CVS 等)
- ブランチ戦略:ブランチとマージ、レビュー・受入(プルリクエスト)
- コンテナ技術
- テスト
- TDD:Junit(モックを使ったテスト、テスト結果レポートの見方、網羅率C0,C1,C2) 品質管理のためのテスト(パフォーマンステスト、結合テスト、総合テスト・システムテスト) ユーザー受入テスト、ブラックボックステスト、ホワイトボックステスト
- 常時結合
- 自動化の導入:何時動かして結果から何を読み取るか、自動化の導入効果、何を自動化するか(ビルド⇒テスト⇒デプロイ等)
- 何のため、誰のために、常時結合(CI)をおこなうのか
- デザインパターン
- リファクタリング
- マーティン・ファウラー「リファクタリング」(コードの不吉な匂い等)
- オブジェクト指向設計原則(Principles Of Object Oriented Design)
- チームのスキル
- スプリント計画
- 自己組織化されたチーム:メンバーの行動規範(コミュニケーション、自立と協調)
- レトロスペクティブ(振り返り)
リファクタリング
- リファクタリングとは
- プログラムの外部から見た動作を変えずにソースコードの内部構造を整理すること
- なぜリファクタリングを行うのか
- 機能を追加するため、こまめにリファクタリングを続けて、コードを読みやすく変更しやすい状態を保つ
- リファクタリングを行うタイミング
- コードレビュー時
- 機能追加時
- バグフィックス時
- コードリーディング時
- コードの不吉な臭いを感じたとき
- etc
コードの不吉な臭い
- 奇妙な名前
- メソッドやクラスの名前が奇妙な場合
- 不適切な命名は理解するのが難しい
- 適切な名前が思いつかない場合は、設計が良くない兆候
- メソッドやクラスの名前が奇妙な場合
- 重複したコード
- 同じコードが複数箇所にある場合
- 重複コードがあると、複数箇所に同じ修正を行う必要がある
- 重複コードを1箇所にまとめる
- 同じコードが複数箇所にある場合
- 長すぎるメソッド
- メソッド名が長い場合
- 短いメソッド名の方が理解しやすい
- 短く役割が明確なメソッドを書く
- メソッド名が長い場合
- 長すぎるパラメータリスト
- メソッドの引数が多い場合
- パラメータが多いと、1つ1つが何を意味しているのか理解しづらくなる
- 新たなデータが必要になった時にパラメータリストの変更が必要となる
- メソッドの引数が多い場合
- グローバルデータ
- 変更可能なデータ
- クラス内部のデータを変更している場合
- データを変更すると予期しないバグを生み出す
- データを書き換えるのではなく、変更後の新しいデータを持ったオブジェクトを返す
- クラス内部のデータを変更している場合
- 変更の偏り
- 1つのクラスが異なる理由で何度も変更されるような場合
- 異なる役割にも変更の影響が出てしまう
- クラスの役割が多すぎるので、役割を明確にし変更理由が1つになるようにする
- 1つのクラスが異なる理由で何度も変更されるような場合
- 変更の分散
- 1つの理由で複数のクラスが変更されるような場合
- 変更すべき箇所が分散すると、重要な変更を実装し忘れる場合が出てしまう
- 1つの理由で複数のクラスが変更されるような場合
- 機能の横恋慕
- クラスのメソッドが、別クラスのデータやメソッドとばかり処理を行っている場合
- 役割の所在が異なっているため、メソッドを別クラスに移動させる
- クラスのメソッドが、別クラスのデータやメソッドとばかり処理を行っている場合
- データの群れ
- 同じ様なデータのグループが、複数箇所で使われている場合
- 同じ役割であるため、1つのクラスにデータをまとめる
- 同じ様なデータのグループが、複数箇所で使われている場合
- 基本データ型への執着
- 基本データ型ばかりを使っている場合
- 基本データ型をクラスに置き換えることで保守性を上げる
- 基本データ型ばかりを使っている場合
- 繰り返されるSwitch文
- 同じ様なSwitch文が何度も出てくる場合
- 分岐を追加した場合に、すべてのSwitch文を変更する必要がある
- Switch文の代わりにポリモーフィズムを使う
- 同じ様なSwitch文が何度も出てくる場合
- ループ
- 怠け者
- 十分な仕事をせず、理解したり保守するコストに見合わない場合
- 不要なクラスは削除する
- 十分な仕事をせず、理解したり保守するコストに見合わない場合
- 疑わしき一般化
- 将来必要になるという理由で書いたが、実際には使われず無駄になっている場合
- 無駄に複雑になっているため、よりシンプルな方に変更する
- 将来必要になるという理由で書いたが、実際には使われず無駄になっている場合
- 一時的属性
- 特定の状況でしか使われないインスタンス変数がある場合
- コードを理解しづらくなる
- 別のクラスに切り出す
- 特定の状況でしか使われないインスタンス変数がある場合
- メッセージの連鎖
- 複数のクラスを経由するメソッドチェーンがある場合
- チェーンの途中で呼び出されるクラスに強く依存してしまう
- 委譲を利用してチェーンを隠蔽する
- 複数のクラスを経由するメソッドチェーンがある場合
- 仲介人
- クラス内のメソッドのほとんどが委譲を行っている場合
- 仲介人を除去して、委譲先のオブジェクトと直接処理を行う
- クラス内のメソッドのほとんどが委譲を行っている場合
- インサイダー取引
- クラス間で過度にデータの交換を行っている場合
- クラス間の結合が強くなってしまう
- クラス間で共通して使用するデータを持つクラスを用意する
- クラス間で過度にデータの交換を行っている場合
- 巨大なクラス
- 1つのクラスで多くの処理を行っている場合
- クラスに役割が多すぎる
- インスタンス変数を整理したり、親クラスに処理をまとめたりする
- 1つのクラスで多くの処理を行っている場合
- クラスのインターフェース不一致
- 置き換えたいクラスのインターフェースが異なっている場合
- 他のクラスへ置き換え可能にするには、インターフェースが同じである必要がある
- インターフェースが同じになるようにする
- 置き換えたいクラスのインターフェースが異なっている場合
- データクラス
- 属性・getter・setterしか持たないクラスがある場合
- 必要な処理が誤った場所に書かれている可能性が高い
- データクラスを使用しているコードを、データクラス自身に持たせられないか検討する
- 属性・getter・setterしか持たないクラスがある場合
- 相続拒否
- 子クラスが親クラスの一部しか利用していない場合
- 継承階層が間違っている
- メソッド・変数の階層を変更したり、継承を移譲に変えたりする
- 子クラスが親クラスの一部しか利用していない場合
- コメント
- 詳細なコメントが書かれている場合
- コードの分かりづらさを補うためにコメントが記述されている
- コメントを書かなくても内容が分かるようにする
- 詳細なコメントが書かれている場合