Помощь с «Масштабируемой архитектурой приложения JavaScript» - PullRequest
11 голосов
/ 21 апреля 2011

Я создаю большое приложение javascript и решил использовать дизайн архитектуры масштабируемого приложения Николаса Закаса: http://developer.yahoo.com/yui/theater/video.php?v=zakas-architecture

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

Например .. У меня есть три модуля: Upload, Window и Manager.

При нажатии на параметр загрузки открывается всплывающее окно с формой загрузки. Также ссылка есть на окно «Менеджер».

При нажатии на ссылку менеджера обновляется всплывающее окно для отображения инструментов администратора ...

...

Для меня это было наиболее разумно (псевдокод):

upload module:
  upload option click --> sandbox.notification('need pop up window', [...html markup for form...])

manager module:
  manager link click --> sandbox.notification('need pop up window', [...html markup for admin tools...])

window module:
  sandbox.listen('need pop up window') --> calls createPopUpWindow( passed in html markup  )

... Однако это идет вразрез с философией, поскольку модули загрузки и управления специально «запрашивают» оконный модуль на выполнение каких-либо действий, поэтому они знают об этом ...

Итак, единственный другой способ, которым я могу придумать, это сделать:

upload module:
  upload option click --> sandbox.notification('upload option clicked', [...html markup for form...])

manager module:
  manager link click --> sandbox.notification('manager link clicked', [...html markup for admin tools...])

window module:
  sandbox.listen('upload option clicked') --> calls createPopUpWindow( passed in html markup  )
  sandbox.listen('manager link clicked') --> calls createPopUpWindow( passed in html markup  )

.. Но это кажется гораздо менее интуитивным, и, честно говоря, я думаю, что это делает мой код намного менее понятным, потому что, глядя на уведомление модуля загрузки «нажата опция загрузки», я не могу сказать, что это должно делать. случается, когда на него нажимают ... Мне нужно искать все остальные мои файлы для модулей, которые его слушают ..... Что, я думаю, можно рассматривать как преимущество, потому что несколько модулей могут захотеть ответить на опцию загрузки ', где, поскольку' нужное всплывающее окно 'может быть явно адресовано только одним модулем.

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

У меня также есть другая ситуация, которая еще более проблематична. Два модуля: Track и Container. Контейнер имеет много дорожек, и первоначально у меня просто были функции дорожек внутри модуля контейнера - но поскольку длина кода в модуле начала расти, я решил разделить их на свои собственные модули для чистого кода ... В любом случае, поскольку контейнеру необходимо знать о его дорожках и иметь возможность ссылаться на них внутри, единственный способ, которым я мог это настроить, был сделать:

containerObject = function(name) {
    this.name                       = name;
    this.video_track                = {'name': 'video',   'markup': sandbox.notification('create-track', 'video')}
    this.audio_track                = {'name': 'audio_1', 'markup': sandbox.notification('create-track', 'audio')}
    ....etc....
};

Таким образом, модуль Track выполняет sandbox.listen ('create-track') и указывает на функцию, которая возвращает новый объект track данного типа ..... Возможно, просто не стоит иметь track будь его собственным модулем ...... Так как это единственное место, где я присваиваю значение, основанное на вызове уведомления.

Мне бы очень хотелось услышать, что другие программисты, знакомые с архитектурой pub / sub, могут сказать об этой теме ......

Пожалуйста, дайте мне ваши мысли и советы.

Спасибо.

1 Ответ

11 голосов
/ 21 апреля 2011

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

Ваша проблема может быть выражена в:

  1. Вы хотите, чтобы функциональные возможности были разбиты на модули
  2. Вы хотите, чтобы модули были настолько автономными, насколько это возможно, с как можно меньшим количеством внешних связей
  3. Модули должны работать с другими модулями воднако «великая схема вещей»

№ 3 - это то, что вызывало у вас проблемы - вы хотите, чтобы модули были независимыми, но затем для взаимодействия вашей программы с другими модулями необходимо, чтобы ваша программа работала.

Типичным решением для модуля является открытие «стандартизированных» каналов связи с внешним миром.Не должно волновать (или иметь значение), сколько, какие, где или какие объекты находятся на другой стороне этих каналов.Он просто принимает команды от входных каналов и отправляет уведомления на выходные каналы.Замечательным побочным эффектом является возможность простого модульного тестирования модуля.

Обратите внимание, что ваши модули не должны заботиться о другой стороне - о четырех W

, что - не должно заботитьс какими классами или объектами он общается (или слушает)

где - не должно волновать, где находится другая сторона (сервер? или в том же браузере)

, которая - не должнане важно, с каким патикульным объектом он общается (с президентом или просто с работником)

сколько - не должно волновать, сколько объектов он говорит / слушает одновременно

Затем вы связываете весь график с основной конфигурацией.Это основная концепция, лежащая в основе Dependency Injection.

Что касается сантехники, есть несколько способов / шаблонов, которые это можно сделать:

  1. События и обработчики
  2. Опубликовать / подписаться
  3. Контейнер IOC / DI
  4. Комбинация выше
...