?

Log in

No account? Create an account
Main

Ruby и IoC

Ковыряюсь в руби. Появился некоторый навык и теперь хочется докопаться до подробностей.

Полез посмотреть, как там с моей навязчивой идеей об IoC. Для PHP эта концепция красиво и легковесно (300 строк кода) решена в Phemto (рус. перевод здесь). Более продвинуто концепция реализована в компоненте для Symfony.

В Руби, однако, такая концепция не дает столь замечательных результатов, поскольку там в класс можно добавлять и переопределять методы уже после того, как класс объявлен и объект создан. А также там есть механизм модулей:

# connection_provider.rb
 
module ConnectionProvider
  def connection
    # open a database connection and return it
  end
end
 
# reopening the class to mix the module in
class Repository
  include ConnectionProvider
end


Т.е. минимальная инъекция может быть сделана средствами языка.

В сообществе есть Jamis Buck, который сначала сделал тяжелый IoC для руби – Copland. О котором делал доклад на рубиконф в 2004. По следам доклада Jim Weirich написал статью Dependency Injection in Ruby о том, как можно сделать легкий DI контейнер без тяжелой артиллерии.

Подход, изложенный в статье очень похож на Phemto, о котором я уже говорил.

Вдохновившись такой легковесностью, Jamis Buck делает еще один фреймворк, -- Needle

Он пытается использовать концепт в своих проектах. В частности в библиотеке Net::SSH 1. И постепенно приходит к выводу, что фреймворк для IoC в Руби не нужен, -- все, что нужно от DI можно сделать встроенными средствами. Таким образом ценность концепции DI для руби сохраняется.

В результате автор двух фреймворков пишет длинный лирично-исторический пост LEGOs, Play-Doh, and Programming.

Ну что ж, пока не попробуешь, не поймешь насколько удобно без библиотеки для контейнера. В PHP, из-за отсутствия гибкости, данный подход очень часто спасал от неконтролируемых зависимостей.

Дополнительное чтение:
Fabio Kung, Ruby and dependency injection in a dynamic world

Comments

какой может быть ioc без интерфейсов?
я пока паршиво ориентируюсь в руби, т.е. могу только цитировать :) однако думаю, что суть ioc в том, что у нас зависимости разрешаются исходя из типов (интерфейсов). Тем не менее интерфейсы в данном случае выступают, как предоставляемые объектами сервисы. А это можно определить просто ключевыми словами (символы в Руби):

container = DI::Container.new
container.register(:logger) { Logger.new )

logger = container.logger

а поскольку в руби есть блоки, то можно делать довольно гибкие объявления:
container.register(:logger) { Logger.new("logfile.log") }

В результате вполне себе получается характерный для DI конфиг:
отсюда: http://onestepback.org/index.cgi/Tech/Ruby/DependencyInjectionInRuby.rdoc

  def create_application
    container = DI::Container.new
    container.register(:logfilename) { "logfile.log" }
    container.register(:db_user) { "jim" }
    container.register(:db_password) { "secret" }
    container.register(:dbi_string) { "DBI:Pg:example_data" }

    container.register(:app) { |c|
      app = WebApp.new(c.quotes, c.authenticator, c.database)
      app.logger = c.logger
      app.set_error_handler c.error_handler
      app
    }

    container.register(:quotes) { |c|
      StockQuotes.new(c.error_handler, c.logger)
    }

    container.register(:authenticator) { |c|
      Authenticator.new(c.database, c.logger, c.error_handler)
    }

    container.register(:database) { |c|
      DBI.connect(c.dbi_string, c.db_user, c.db_password)
    }

    container.register(:logger) { |c| Logger.new(c.logfilename) }
    container.register(:error_handler) { |c|
      errh = ErrorHandler.new
      errh.logger = c.logger
      errh
    }
  end
>в класс можно добавлять и переопределять методы уже после того, как класс объявлен и объект создан

Очень прикольно, особенно, когда у тебя незнакомый проект без тестов. Или даже ты сам это сделал, а потом забыл. И имена методов скажем не статично задаются, а каким-нибудь билдером хитрым строятся.

И в один прекрасный момент тебе надо найти ошибку в таком коде ;-)

По той же самой причине, я против runkit, например. Менять в runtime код очень-очень плохо. Таким приемом оправдано пользоваться только в тех случаях, когда надо намерянно запутать код, например, когда ты пишешь какую-либо защиту, во всех остальных случаях - это ахтунг, имхо.
тесты в таких местах никто не отменял.

в javascript такие добавления методов в объект используется широко и вроде успешно.

мне трудно спорить, я только пока впитываю :) но, если язык позволяет не допускать ошибок и неясностей в таких местах, то почему нет?
Ну это как сказать - успешно. Разобраться что откуда пришло в таком коде задача не из легких.

С моей точки зрения любой код должен хорошо искаться с помощью любой программы поиска текста в файлах. По стектрейсу в логе должно быть понять где и что произошло. В идеале ошибку можно найти просто прочитав внимательно код, а не имполняя его в дебаггере.
я не освоился еще пока до конца с этой кухней, так, что не буду строить предположений. не готов пока спорить, очень новая для меня эта материя.

(Anonymous)

порно в 3d

Бери здесь... "порно молодые галерея " http://www.google.com/url?sa=t&source=web&cd=201&ved=0CBUQFjAAOMgB&url=http%3A%2F%2Fv7em.com%2F&CBUQFjAAOMgBDimagymnanync

(Anonymous)

рисованное порно лара крофт

Анкеты и видео от гугл (рисованное порно комикс) http://www.google.com/url?sa=t&source=web&cd=201&ved=0CBUQFjAAOMgB&url=http%3A%2F%2Fv7em.1.vg%2F&CBUQFjAAOMgBDypeVoffheelf
Использую IoC, те кто ругает - просто не умеют готовить ;)
Вы недооцениваете мощь IoC