Giter Site home page Giter Site logo

double_dispatch's Introduction

double_dispatch

Maintainability

Call different functions depending on the runtime types of two objects. Extremely simple to use and extend.

I personally use it to compensate the lack of method overloading in Ruby and separate concerns into smaller modules.

Usage

  1. Define a unique dispatch_id for each class using the dispatch_as method.
class Dog
  include DoubleDispatch

  dispatch_as :dog

  def pet
    #...
  end
end

class Human
  include DoubleDispatch

  dispatch_as :human

  attr_accessor :name

  def initialize(name)
    @name = name
  end
end
  1. Write concrete functions for each class you want handle
module Salutations
  def salute_to_human(human)
    "Hi #{human.name}!"
  end

  def salute_to_dog(dog)
    dog.pet

    "Woof woof!"
  end
end
  1. Call double_dispatch to handle different non-necessary-polymorphic objects.
Dog.new.double_dispatch(:salute_to, Salutations)
# => "Woof woof!"

Human.new("Emiliano").double_dispatch(:salute_to, Salutations)
# => "Hi Emiliano!"

Common patterns

Create modules to encapsulate the logic

This is my favourite pattern. Using the same example described above, we can create a better internal API if we encapsulate all the salutation logic into a single module

module Salutations
  def self.salute(somebody)
    somebody.double_dispatch(:salute_to, self)
  end

  def salute_to_human(human)
    "Hi #{human.name}!"
  end

  def salute_to_dog(dog)
    dog.pet

    "Woof woof!"
  end
end

And then, we use the module in a cleaner way:

Salutations.salute Dog.new
# => "Woof woof!"

Salutations.salute Human.new("Emiliano")
# => "Hi Emiliano!"

Use class.name as dispatch_id

I frequently find myself using the same dispatch_id as the class name, so I used to extend DoubleDispatch with the following snippet

module DoubleDispatch
  module ByClassName
    module ClassMethods
      def dispatch_id
        @dispatch_id ||= self.name.split('::').last.downcase
      end
    end

    def self.included(base)
      base.include(::DoubleDispatch)
      base.extend(ClassMethods)
    end
  end
end

Use table's name as dispatch_id

Most of the time, we will use Active Record objects (or Sequel models, etc) in our system and we want to identify these models by the table name.

Since this gem is flexible and easy to extend, I suggest to extend DoubleDispatch with a specific module using the ORM-specific methods.

For example, an extension for Sequel models would be:

module DoubleDispatch
  module ByTableName::Sequel
    module ClassMethods
      def dispatch_id
        @dispatch_id ||= self.table_name
      end
    end

    def self.included(base)
      base.include(::DoubleDispatch)
      base.extend(ClassMethods)
    end
  end
end

And use this logic in a single line:

class User < Sequel::Model
  include DoubleDispatch::ByTableName::Sequel

  ...
end

As you can see, it won't need to call dispatch_as method, but you can always call it and overwrite the dispatch_id. This is extremely useful when you define more than a model over the same table name.

double_dispatch's People

Contributors

emancu avatar

Stargazers

 avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.