Computer >> 컴퓨터 >  >> 프로그램 작성 >> Ruby

Ruby에서 상태 머신을 생성하기 위해 AASM Gem을 사용하는 방법

오늘은 상태 머신, 작동 방식 및 AASM gem을 사용하여 Ruby 프로젝트에서 사용하는 방법에 대해 알아보겠습니다.

지금 :

신호등을 상상해보세요...

빨간색, 녹색 또는 노란색일 수 있습니다.

색상이 바뀌면 다음 색상은 현재를 기반으로 합니다. 하나.

Ruby에서 상태 머신을 생성하기 위해 AASM Gem을 사용하는 방법

시각 장애인이 언제 건널 수 있는지 알 수 있도록 소리를 내는 종류라고 가정해 보겠습니다.

지금 :

당신은 이것을 위한 소프트웨어를 작성하고 있습니다.

매번 어떤 소리를 재생하고 다음에 어떤 색상을 내야 하는지 어떻게 알 수 있나요?

다음과 같은 if 문을 작성할 수 있습니다.

if @light.state == "green"
  @light.play_green_sound
end

if @light.state == "green"
  @light.change_to_yellow
end

# ...

이 상태 확인 코드는 어디에나 있습니다!

이를 어떻게 개선할 수 있습니까?

객체 지향 디자인 원칙을 적용하면 상태 디자인 패턴을 재발견하게 됩니다.

상태 디자인 패턴이란 무엇입니까?

상태 디자인 패턴은 상태 머신을 구현하는 한 가지 방법입니다.

3개의 구성요소가 필요합니다. :

  • Context 클래스, 이 클래스는 현재 상태를 알고 있습니다.
  • State 클래스에서 이 클래스는 개별 상태에서 구현해야 하는 메서드를 정의합니다.
  • 모든 주에 대해 하나의 클래스. 이 클래스는 State에서 상속됩니다. 수업

신호등 예에서 컨텍스트는 TrafficLight입니다. 그 자체.

그리고 상태는 Green입니다. , Red &Yellow .

모든 주에서 무엇을 해야 할지 알게 될 것입니다.

큰 이점 ?

모든 상태는 자신을 알고 있으므로 현재 상태를 확인할 필요가 없습니다. 이는 종종 복잡성의 원인이 되는 덜 조건부 문장으로 변환됩니다.

신호등 구현

이 패턴의 실제 구현을 위한 코드를 살펴보겠습니다.

다음은 TrafficLight입니다. :

class TrafficLight
  def initialize
    @state = nil
  end

  def next_state(klass = Green)
    @state = klass.new(self)

    @state.beep
    @state.start_timer
  end
end

기본 State는 다음과 같습니다. :

class State
  def initialize(light)
    @light = light
  end

  def beep
  end

  def next_state
  end

  def start_timer
  end
end

예, 이 3가지 방법은 비어 있습니다.

이 "인터페이스"를 정의하는 것은 다른 프로그래밍 언어(예:Java)의 일반적인 규칙이지만 Ruby에서는 널리 사용되지 않습니다.

이것은 데모용입니다.

그러나 우리는 여전히 initialize 모든 상태에 컨텍스트가 필요하기 때문에 모든 상태 간의 메서드 (TrafficLight object) 상태 변경 신호 .

지금 :

3가지 상태가 서로 매우 유사해 보이기 때문에 그 중 하나에 대한 코드를 보여 드리겠습니다.

다음은 Green입니다. 상태:

class Green < State
  def beep
    puts "Color is now green"
  end

  def next_state
    @light.next_state(Yellow)
  end

  def start_timer
    sleep 5; next_state
  end
end

모든 상태는 다음으로 전환하는 방법과 시기를 알고 있습니다.

AI 게임 예시

상태 머신을 사용하여 RubyWarrior와 같이 현재 상태에 의존하는 게임을 해결할 수 있습니다.

RubyWarrior에서는 플레이어 개체와 보드가 제공됩니다.

목표는 :

  • 보드의 모든 적을 물리치세요
  • HP를 0 이상으로 유지하면서 출구에 도달

한 번에 하나씩 이동할 수 있으며 레벨을 완료하려면 좋은 선택을 해야 합니다.

현재 상태를 보면 선택하는 데 도움이 됩니다.

이것이 상태 머신이 좋은 솔루션인 이유입니다.

예시 :

class Attacking < State
  def play(warrior)
    warrior.attack!

    @player.set_state(Healing) unless enemy_found?(warrior)
  end
end

이것은 우리 전사가 있을 수 있는 상태 중 하나입니다. 시야에 적이 없을 때 Healing로 이동합니다. 전투 피해로부터 회복하는 상태입니다.

AASM 보석 사용

전환이 유효한지 확인하면서 현재 상태를 추적하려면 AASM과 같은 상태 머신 gem을 사용할 수 있습니다.

이 보석은 이벤트라는 아이디어를 기반으로 제작되었습니다. (조명 스위치를 누르는 것과 같은) 다른 상태로의 전환을 트리거합니다.

예시 :

require 'aasm'

class Light
  include AASM

  aasm do
    state :on, :off

    event :switch do
      transitions :from => :on, :to => :off, :if => :on?
      transitions :from => :off, :to => :on, :if => :off?
    end
  end
end

이 클래스를 사용하는 방법 :

light = Light.new

p light.on?
# true

light.switch

p light.on?
# false

이 상태 머신을 사용하면 현재 상태가 "꺼짐"인 경우에만 "켜짐" 상태로 전환할 수 있습니다. 상태 전환 중에 특정 코드를 실행하기 위해 여러 콜백(전/후)을 가질 수도 있습니다.

이러한 콜백 다음과 같은 항목이 포함될 수 있습니다.

  • 이메일 보내기
  • 상태 변경 기록
  • 실시간 모니터링 대시보드 업데이트

또한 AASM에는 ActiveRecord를 사용하여 현재 상태를 데이터베이스에 저장하는 옵션이 있습니다. .

AASM 보석 비디오

요약

상태 머신, 상태 디자인 패턴 및 AASM gem에 대해 배웠습니다! 내 Ruby 뉴스레터(구독자 7000명 이상)를 구독하여 지금 계속 학습하여 새 기사 및 구독자 전용 Ruby 팁을 놓치지 마세요. .

이제 이러한 새로운 아이디어로 연습할 시간입니다 🙂

읽어주셔서 감사합니다!