루비로 배우는 객체지향 디자인 - 3장 의존성 관리하기

By: Jun Heo
Posted: October 10, 2021

아래의 코드 기반으로 변경해 보면서 의존성을 이해해보자

# chainring(앞 톱니수), cog(뒷 톱니수), rim(바퀴테 지름), tire(타이어 높이)
# ratio(기어비)
class Gear
  attr_reader :chainring, :cog, :rim, :tire
  def initialize(chainring, cog, rim, tire)
    @chainring = chainring
    @cog = cog
    @rim = rim
    @tire = tire
  end

  def ratio
    chainring / cog.to_f
  end

  def gear_inches
    ratio * Wheel.new(rim, tire).diameter
  end
end

class Wheel
  attr_reader :rim, :tire

  def initialize(rim, tire)
    @rim = rim
    @tire = tire
  end

  def diameter  
    rim + (tire * 2)
  end

  def circumference
    diameter * Math::PI
  end
end

puts Gear.new(52, 11, 26, 1.5).gear_inches

Gear class안에서 Wheel class를 선언하고 사용하기 때문에 Gear는 Wheel에 대해 모두 알아야 해서 결합도가 높다. Gear는 Wheel class의 diameter method만 필요하므로 Wheel class의 선언을 바깥에서 하고 Gear로 주입할 수 있도록 변경하면 Gear는 Wheel자체는 몰라도 되고 diameter만 알아도 되기 때문에 결합도를 낮춰 의존성을 줄일 수 있다.

# chainring(앞 톱니수), cog(뒷 톱니수), rim(바퀴테 지름), tire(타이어 높이)
# ratio(기어비)
class Gear
  attr_reader :chainring, :cog, :rim, :tire
  def initialize(chainring, cog, rim, tire)
    @chainring = chainring
    @cog = cog
    @rim = rim
    @tire = tire
  end

  def ratio
    chainring / cog.to_f
  end

  def gear_inches
    ratio * Wheel.new(rim, tire).diameter
  end
end

class Wheel
  attr_reader :rim, :tire

  def initialize(rim, tire)
    @rim = rim
    @tire = tire
  end

  def diameter  
    rim + (tire * 2)
  end

  def circumference
    diameter * Math::PI
  end
end

# 인스턴스 생성을 격리 시키기
class Gear
  attr_reader :chainring, :cog, :rim, :tire
  def initialize(chainring, cog, rim, tire)
    @chainring = chainring
    @cog = cog
    @rim = rim
    @tire = tire
  end
  
  def gear_inches
    ratio * wheel.diameter
  end
  ...
    
# 정의된 wheel method를 통해 인스턴스 만들기
class Gear
  attr_reader :chainring, :cog, :rim, :tire
  def initialize(chainring, cog, rim, tire)
    @chainring = chainring
    @cog = cog
    @wheel = Wheel.new(rim, tire)
  end
  
  def gear_inches
    ratio * wheel.diameter
  end
  
  def wheel
    @wheel ||= Wheel.new(rim, tire)
  end
  ...
    
# 의존성을 클래스 내부의 메서드 속에 캡슐화시켜 놓기
  def gear_inches
    ratio * diameter
  end
  
  def diameter
    wheel.diameter
  end

해시를 통하여 인자를 넘긴다.

팩토리는 다른 객체를 만들기 위해 존재하는 객체이다. 팩토리는 다른 클래스의 인스턴스를 생성하기 위해서만 존재한다.

자기 자신보다 덜 변하는 것들에 의존하라