Subscribed unsubscribe Subscribe Subscribe

リファクタリング写経日記

Replace Subclass with Fields(サブクラスからフィールドへ)

コードの臭い 定数を返すメソッド以外に違いのないサブクラスがある。 リファクタリングコード refactor (replace subclass with fields) テストコード # rspec describe Female do let(:bree) { Female.new } describe 'female?' do subject { bree.female?…

Replace Type Code with Module Extension(タイプコードからモジュールのextendへ)

コードの臭い クラスのふるまいに影響を与えるタイプコードが使われている。 リファクタリングコード refactor (replace type code with module extension) テストコード # rspec describe MountainBike do let(:instance_params) { { :type_code => :rigid,…

Replace Type Code with Polymorphism(タイプコードからポリモーフィズムへ)

コードの臭い クラスのふるまいに影響を与えるタイプコードが使われている。 リファクタリングコード refactor (replace type code with polymorphism) テストコード # rspec describe MountainBike do let(:instance_params_of_rigid) { { :type_code => :r…

Change Unidirectional Association to Bidirectional(片方向リンクから双方向リンクへ)

コードの臭い 互いのメンバを使わなければならない2つのクラスがあるが、片方向のリンクしかない。 リファクタリングコード refactor (change unidirectional association to bidirectional) テストコード # rspec describe Order do let(:order) { Order.n…

Replace Hash with Object(ハッシュからオブジェクトへ)

コードの臭い 異なる種類のオブジェクトを格納し、複数の目的のために渡され、使われているHashがある。 リファクタリングコード refactor (replace hash with object) テストコード # rspec describe Client do let(:new_network) { { :nodes => [], :old_n…

配列からオブジェクトへ(Replace Array with Object)

コードの臭い 一部の要素が別の意味を持つようなArrayがある。 リファクタリングコード refactor (replace array with object) テストコード # rspec describe Client do let(:row) { [] } let(:client) { Client.new(row) } describe 'name' do before do r…

参照から値へ(Change Reference to Value)

コードの臭い イミュータブル(書き換え不能)で小さく、管理しにくい参照オブジェクトを持っている。 リファクタリングコード refactor (change reference to value) テストコード # rspec describe Currency do let(:currency_1_new) { Currency.new("USD"…

値から参照へ(Change Value to Reference)

コードの臭い 同じインスタンスをいくつも生成するクラスがある。 リファクタリングコード refactor (change value to reference) テストコード # rspec describe Client do describe 'self.number_of_orders_for(orders, customer)' do let(:order_1) { Ord…

データ値からオブジェクトへ(Replace Data Value with Object)

コードの臭い データやふるまいの追加を必要とするデータ項目がある。 リファクタリングコード refactor(replace data value with object) テストコード # rspec describe Client do describe 'self.number_of_orders_for(orders, customer)' do let(:orde…

自己カプセル化フィールド(Self Encapsulate Field)

◯ コードの臭い フィールドに直接アクセスしているが、フィールドとの密結合が不都合になってきている。 ◯ リファクタリングする理由 サブクラスが情報の取得方法をメソッドでオーバーライドできるため、データの管理方法に柔軟性が生まれる。 ◯ リファクタ…

横流しブローカーの除去(Remove Middle Man)

◯ リファクタリングすべき時 クラスが単純な委譲をやり過ぎている。 ◯ リファクタリングした方がいい理由 委譲オブジェクトに追加するメンバが増えてきた際、サーバーに委譲メソッドを追加する負担を抑えるため。 ◯ リファクタリングコード refactor(remove…

委譲の隠蔽(Hide Delegate)

◯ リファクタリングすべき時 クライアントがオブジェクト内の委譲クラスを呼び出している。 ◯ リファクタリングする理由 変更の影響が及ぶのがサーバーまでに限られ、クライアントには影響が及ばなくなる。 ◯ リファクタリングコード refactor(hide delegat…

クラスのインライン化(Inline Class)

◯ リファクタリングした方がいい状況 クラスが大した仕事をしていない。 ◯ リファクタリングコード refactor(inline class) ◯ テストコード # rspec describe Person do let(:person){ Person.new } describe 'telephone_number' do before do person.offi…

クラスの抽出(Extract Class)

◯ 適用すべき時 2つのクラスで行うべき仕事をしている1個のクラスがある。 ◯ リファクタリングした方がいい理由 クラスが大きすぎると、簡単に理解できない ◯ リファクタリングコード refactor(extract class) ◯ テストコード # rspec describe Person do …

フィールドの移動(Move Field)

適用すべき時 フィールドが、自分のクラスよりも他クラスからよく使われている。 リファクタリングコード(1) refactor(move field) リファクタリングコード(2) refactor(move field)<自己カプセル化フィールドの使用> テストコード describe Account…

メソッドの移動(Move Method)

◯ 適用すべき時 メソッドが、自分のクラスよりも他クラスの機能を使ったり、他クラスから利用されたりする。 ◯ リファクタリングした方がいい理由 メソッドを移動すると、クラスは、関連する機能を簡潔に実装した単純なものになる。 ◯ リファクタリングコー…

evalを実行時からパース時へ(Move Eval from Runtime to Parse Time)

◯ 適用すべき時 evalを使わなければならないが、evalの実行回数を減らしたい。 ◯ リファクタリングコード refactor(move eval from runtime to parse time) ◯ テストコード # rspec describe Person do before do class EmployeeNumberGenerator; end end …

動的レセプタの分離(Isolate Dynamic Receptor)

◯ 適用すべき時 method_missingを使っているクラスが容易に書き換えられなくなってきている。 ◯ リファクタリングコード 動的レセプタの分離(Isolate Dynamic Receptor) ◯ テストコード #rspec describe Recorder do let(:recorder){ Recorder.new } descr…

Replace Dynamic Receptor with Dynamic Method Definition

適用すべき時 デバッグが大変なmethod_missingを使わずに、動的に定義したいメソッドがある。 リファクタリングコード(1) method_missingを使わない動的な委譲 テストコード(1) #rspec describe Decorator do let(:post){ Post.new } let(:decorator){…

Dynamic Method Definition

◯ 適用すべき時 動的に定義すれば、もっと簡潔に定義できるメソッドがある。 ◯ ポイント コードの重複が出てきた場合は、動的定義に切り替える 動的定義にすると、メソッド定義での誤りが減る 「動的メソッド定義」の最大の目的は、読みやすくメンテナンスし…

Remove Unused Default Parameter

◯ 適用すべき時 引数がデフォルト値を持っているが、その引数を指定せずにメソッドが呼び出されることはない。 ◯ ポイント ソフトウェアでは、使われていない柔軟性は悪である。 (使われていない)柔軟性は、メンテナンスのために時間を食い、バグが入る余…

Introduce Class Annotation

◯ ポイント 宣言的な構文でコードの目的が明確につかめる場合に適用すると、コードの意図を明確にできる ◯ リファクタリングコード refactor<introduce class annotation(クラスアノテーションの導入)> ◯ テストコード search_criteria_spec.rb※参考資料…

Extract Surrounding Method

◯ ポイント ユニークなコードが中央にあるメソッドを抽出する時に適用する インフラストラクチャコード(ex. コレクションを反復するためのコード)を隠して、ビジネスロジックを前面に押し出すことができる ◯ リファクタリングコード refactor(Extract Sur…

Replace Loop with Collection Closure Method

ポイント ループを取り除いてコレクションクロージャメソッドを使うと、コードをたどりやすくなる。 コレクションクロージャメソッドは、コレクションの中を行き来したり、派生コレクションを作ったりするためのインフラストラクチャコードを隠してくれる 複…

アルゴリズム変更

ポイント 複雑なアルゴリズムから単純なアルゴリズムに変更する 大きくて複雑なアルゴリズムを取り替えるのは難しい アルゴリズムを変更しやすくするために、出来る限りメソッドを分解しておく必要がある リファクタリングdiff refactor(substitute algorith…

メソッドからメソッドオブジェクトへ

ポイント ローカル変数がじゃまをして、「メソッドの抽出」を行いにくい場合に適用する ローカル変数は、メソッドオブジェクトの属性になる メソッドオブジェクトにすると、引数渡しの心配をせずに「メソッドの抽出」を行えるようになる コード 6.9-after · …

引数への代入の除去

ポイント 引数への代入を安易に行うと、引数自体が変更されているのかどうかを気にする必要が出てくる →rubyの場合、値渡しなので引数自体は変更されない プロダクトコード(ruby) before class Order def discount(input_val, quantity, year_to_date) inp…

Extract Method(メソッドの抽出)

所感 プロダクトコード Introduce Explaining Variable(説明用変数の導入)と同様に、プロダクトコードが読みやすくなった。また、「base_price」のロジックを再利用できるようになった。 テストコード Introduce Explaining Variable(説明用変数の導入)…

Introduce Explaining Variable(説明用変数の導入)

Product Codeがちょっと読みやすくなったか。Test codeの改善はあまり期待できなさそう。 ◯ Product code(ruby) # before class Order attr_accessor :quantity attr_accessor :item_price def initialize (quantity, item_price) @quantity = quantity @ite…

Replace Temp with Chain(一時変数からチェインへ)

テストコードがすっきりしました。 before:add_option(arg) →after:and(arg)before # product code(ruby) class Select def options @options ||= [] end def add_option(arg) options << arg end end # test code(rspec) describe Select do let(:select)…