アヒルタイピングに光を流す



ステージの設定
アヒルのタイピングは、一般的にダイナミックな言語のrubyistsや他のユーザーによって使用されます.コンサート照明チームがバンドの照明を設定するのを手伝ってアヒルタイピングを披露しますRubyConf 2020 ルビーの話Coverage モジュールです.

舞台設計
我々のコンサートのためにステージを照らすために、我々は使用する明りの広い範囲を持ちます.
我々は信頼できる、またはPAR , ライト.
class CanLight
  def trigger(color:, effect:)
  ...
  end
end
我々はspotlights 各々のバンドメンバーに尋ねられます.
class Spotlight
  def trigger(color:, effect:)
  ...
  end
end
空想があるmoving lights ステージ間の多彩な報道のために.
class MovingLight
  def trigger(color:, effect:)
  ...
  end
end

私たちもbeam projector より強力なスポットライト効果のために.
class BeamProjector
  def trigger(color:, effect:)
    ...
  end
end
これらのライトのどれがここで重要でないか.通知するキーは、すべてを呼び出すことによってすべてを操作することですtrigger メソッド.

軽いタッチ
舞台照明技術者は、バンドのように、コンサートでパフォーマーです.すべての単一の曲のすべての単一のノートについては、彼らはステージの視覚的美学がちょうど設定されていることを確認する必要があります.
これらのライトのすべては、中央のコントローラーによって管理されます.
class LightingController
  def initialize
    @powered_lights = {}
  end

  def turn_on_lights
    @powered_lights[:beam_projector] = BeamProjector.new
    @powered_lights[:can] = CanLight.new
    @powered_lights[:moving_light] = MovingLight.new
    @powered_lights[:spotlight] = Spotlight.new
  end
end
私が言及したように、あらゆる歌のあらゆるメモのために、彼らは明りが正確に彼らが想定しているように見えるようにする必要があります.これは照明の構成として追跡されます.
class LightingComposition
  attr_reader :light_name
  attr_reader :color
  attr_reader :effect
end

ステージでライトにダッキング
バンドがショーをしているので、照明技術者は注意のためにメモに従い、構成を適用する必要があります.
class Song
  def play
    @notes.map do |note|
      composition = []

      composition << Thread.new { @guitar.play(note) }
      composition << Thread.new { @vocal.sing(note) }
      composition << Thread.new { @drum.hit(note) }
      composition << Thread.new { @keyboardist.program(note) }
      composition << Thread.new { @lighting.set_lighting(note) }

      composition.map(&:value)
    end
  end
end
我々の異なる明りの各々が同じメッセージに反応するのでtrigger ) 同じサインで、照明コントローラは、それがどんな光であるかについて、気にかけるか、知っている必要がありません.それが知っているすべては、それが送る必要があるということです
トリガ信号と必要な構成を適用します.
class LightingController
  def set_lighting(note)
    lighting_composition = note.lighting

    trigger(@powered_lights[lighting_composition.light_name], lighting_composition)
  end

  def trigger(light, composition)
    light.trigger(
      color: composition.color,
      effect: composition.effect,
    )
  end
end
The LightingController 's trigger 方法はアヒルタイピングを利用している.Rubyはオブジェクトのどんな種類のオブジェクトを呼び出しているかを気にかけませんlight 引数.すべての問題は、それが応答することですtrigger . 私たちも話し合ったとき、アヒルのタイピングを使いました.我々のギターは、アンプが音を作ったか、それが音をたてたとしても、気にかけませんでした.すべて
実行時にRubyを満たすための事項は、我々が応答して渡すオブジェクトがplay 引数を受け取ります.

静止照明
静的な言語や別のタイピングシステムに慣れているなら、クラスの集合が何をするのか共通の動作を定義する必要があります.たとえば、Javaを使用してインターフェイスを定義しましょう
我々の明りのために.
interface Light {
  void trigger(Color color, LightingEffect effect)
}
それから、我々の明りの各々は、このインターフェースを実装します.そして、光が引き起こされるとき、彼らがすることの彼ら自身の実装を定義します.
class Spotlight implements Light {
  @Override
  public void trigger(Color color, LightingEffect effect) {
    // Turn the light on or off
  }
}
我々は今設定できますLightingController 's trigger あらゆる種類の光を受け入れる方法.
class LightingController {
  public void trigger(Light light, LightingComposition composition) {
    light.trigger(composition.color, composition.effect);
  }
}
これはJavaの型システムを満たしますLight インターフェイスはtrigger 引数の型を受け入れるメソッドです.
Rubyでアヒルタイピングのため、この契約を定義して強制する必要はありません.しかし、ルビー3はshipping 型を定義する方法
署名RBS . RBSはインターフェースを定義するメカニズムを含んでいますhere .

ロックオン
アヒルタイピングは、Rubyや他の動的言語のコアデザイン機能ですしかし、それはある程度の信頼を必要とします.すべてがランタイムで決定されるので、オブジェクトがそれを必要とするメソッドに反応しないメソッドに渡すのを止める何もありません.これは例外を生成しますが、そのフィードバックを得るには遅すぎるかもしれません.しかし、多くのrubyistsに、このアプローチがしばしば提供する柔軟性は、コストを上回る.
あなたが静的タイピングシステムから来ているか、議論として提供されることになっていることについてより多くの方向または施行を望むならば、RBSによるインタフェースタイプを定義することを調査してください.
我々のコンサートシリーズは、構成と委任に関する議論を続けます.

This post originally published on The Gnar Company blog.