лучший / самый элегантный способ обмена объектами между стеком приложений / промежуточных программ, установленных в стойку?

Какова наилучшая идиома для совместного использования объекта между приложениями/промежуточными программами, установленными в стойке?

Например, на этом config.ru есть два приложения Sinatra, сопоставленные с разными конечными точками:

class App1 < Sinatra::Base
  # ...
end

class App2 < Sinatra::Base
  # ...
end

map '/app1' do
  run App1
end

map '/app2' do
  run App2
end

Теперь, если этим двум приложениям необходимо совместно использовать объект, будь то коннектор базы данных или любой другой объект, какая идиома подойдет для этого лучше всего?

В основном я вижу два варианта:

1- Создайте константу на уровне config.ru и просто ссылайтесь на эту константу в приложениях. Например:

SHARED_OBJECT = "hello world"

class App1 < Sinatra::Base
  get '/' do
    SHARED_OBJECT
  end
end

class App2 < Sinatra::Base
  get '/' do
    SHARED_OBJECT
  end
end

map '/app1' do
  run App1
end

map '/app2' do
  run App2
end

2- Создайте объект singleton на уровне config.ru и используйте его в приложениях. Например:

class SharedObject
  include Singleton

  def test
    @test ||= "hello world"
  end
end

class App1 < Sinatra::Base
  get '/' do
    SharedObject.instance.test
  end
end

class App2 < Sinatra::Base
  get '/' do
    SharedObject.instance.test
  end
end

map '/app1' do
  run App1
end

map '/app2' do
  run App2
end

Комментарии/предложения?
Колин


person Colin Surprenant    schedule 01.04.2011    source источник
comment
У меня нет прямого опыта в этом, поэтому я не буду публиковать это как ответ, но лично я бы использовал константу (например, DB = Sequel...) вместо синглтона. _И (лично) я не вижу никакой пользы от использования одноэлементного шаблона в классе по сравнению с модулем с self. методами.   -  person Phrogz    schedule 02.04.2011


Ответы (1)


Я бы переместил общий объект в отдельный файл и пространство имен. Если бы это был объект подключения к базе данных, это могло бы выглядеть так:

# config.ru:
require 'lib/my_app/database'
...
class App1 < Sinatra::Base
  get '/' do
    MyApp::Database.with_connection do |conn|
      ...
    end
  end
end

# lib/my_app/database:
module MyApp
  module Database
    def self.with_connection(&block)
      ...
    end
  end
end

Я вижу в этом несколько преимуществ:

  1. это уменьшает размер вашего config.ru файла, улучшая читаемость
  2. это разделяет задачи -- config.ru относится к стоечным приложениям; lib/my_app/database.rb о базах данных
  3. это облегчает извлечение. В какой-то момент вы, возможно, захотите разделить App1 и App2 на отдельные проекты и включить подключение к базе данных в качестве жемчужины. Это легко сделать, когда код базы данных находится в отдельном модуле и файле.

Комментарий Phrogz о том, что констант достаточно и не нужны синглтоны, мудр.

person James A. Rosen    schedule 06.04.2011
comment
Я полностью согласен с перемещением каждого класса/модуля в отдельный файл. Мой пример был автономным в config.ru, чтобы быть максимально кратким для целей этого вопроса. Ваше предложение по использованию модуля для инкапсуляции общих объектов имеет смысл. Я опубликую ответ, чтобы немного подробнее остановиться на этой теме. - person Colin Surprenant; 07.04.2011
comment
вот суть с примером модуля глобальной конфигурации, который я только что сделал gist.github.com/908474 - person Colin Surprenant; 07.04.2011
comment
и кстати, это действительно шаблон singleton-as-module, который я предпочитаю использовать миксин singleton. - person Colin Surprenant; 08.04.2011