# リファクタリングしてみた（ハギスの移動距離）

### 適用したリファクタリング名

• 一時変数から問い合わせメソッドへ（Replace Temp with Query）
• 条件文の分解（Decompose Conditional）

### プロダクトコード（ruby）

#### before

```class Haggis
def initialize(primary_force, secondary_force, mass, delay)
@primary_force, @secondary_force, @mass, @delay = primary_force, secondary_force, mass, delay
end

def distance_traveled(time)
primary_acc = @primary_force / @mass
primary_time = [time, @delay].min
result = 0.5 * primary_acc * primary_time * primary_time
secondary_time = time - @delay
if (secondary_time > 0)
primary_vel = primary_acc * @delay
secondary_acc = (@primary_force + @secondary_force) / @mass
result += primary_vel * secondary_time + 5 * secondary_acc * secondary_time * secondary_time
end
result
end
end
```

#### after

```class Haggis
def initialize(primary_force, secondary_force, mass, delay)
@primary_force, @secondary_force, @mass, @delay = primary_force, secondary_force, mass, delay
end

def distance_traveled(time)
result = primary_distance_traveled(time)
result += secondary_distance_traveled(time) if accelerate_secondary?(time)
result
end

def primary_distance_traveled(time)
0.5 * primary_acc * primary_time(time) * primary_time(time)
end

def secondary_distance_traveled(time)
primary_vel * secondary_time(time) + 5 * secondary_acc * secondary_time(time) * secondary_time(time)
end

def primary_acc
@primary_force / @mass
end

def secondary_acc
(@primary_force + @secondary_force) / @mass
end

def primary_time(time)
[time, @delay].min
end

def secondary_time(time)
time - @delay
end

def primary_vel
primary_acc * @delay
end

def accelerate_secondary?(time)
secondary_time(time) > 0
end
end
```

### テストコード（rspec）

#### before

```describe Haggis do
let(:primary_force){ 10 }
let(:secondary_force){ 20 }
let(:mass){ 2 }
let(:delay){ 5 }
let(:haggis){ Haggis.new(primary_force, secondary_force, mass, delay) }

describe 'distance_traveled(time)' do
subject{ haggis.distance_traveled(time) }
context 'secondary_time <= 0' do
let(:time){ 5 }
it{ should == 62.5 }
end
context 'secondary_time > 0' do
let(:time){ 6 }
it{ should == 162.5 }
end
end
end
```

#### after

```describe Haggis do
let(:primary_force){ 10 }
let(:secondary_force){ 20 }
let(:mass){ 2 }
let(:delay){ 5 }
let(:time){ 10 }
let(:haggis){ Haggis.new(primary_force, secondary_force, mass, delay) }

describe 'distance_traveled(time)' do
let(:primary_distance_traveled){ 62.5 }
let(:secondary_distance_traveled){ 2000 }
before do
haggis.should_receive(:accelerate_secondary?).with(time).and_return(accelerate_secondary_key)
haggis.should_receive(:primary_distance_traveled).with(time).and_return(primary_distance_traveled)
end
subject{ haggis.distance_traveled(time) }

context 'not accelerate secondary' do
let(:accelerate_secondary_key){ false }
before do
haggis.should_not_receive(:secondary_distance_traveled)
end
it{ should == 62.5 }
end
context 'accelerate secondary' do
let(:accelerate_secondary_key){ true }
before do
haggis.should_receive(:secondary_distance_traveled).with(time).and_return(secondary_distance_traveled)
end
it{ should == 2062.5 }
end
end

describe 'primary_distance_traveled(time)' do
subject{ haggis.primary_distance_traveled(time) }
it{ should == 62.5 }
end

describe 'secondary_distance_traveled(time)' do
subject{ haggis.secondary_distance_traveled(time) }
it{ should == 2000 }
end

describe 'accelerate_secondary?(time)' do
before do
haggis.should_receive(:secondary_time).with(time).and_return(secondary_time)
end
subject{ haggis.accelerate_secondary?(time) }

context 'secondary_time > 0' do
let(:secondary_time){ 1 }
it{ should be_true }
end
context 'secondary_time <= 0' do
let(:secondary_time){ 0 }
it{ should be_false }
end
end
end
```

※ 参考資料
リファクタリング:Rubyエディション6.7 一時変数の分割（Split Temporary Variable）（p.147〜149）