Skip to content
This repository has been archived by the owner on Aug 3, 2023. It is now read-only.

Commit

Permalink
Update what-is-this.md
Browse files Browse the repository at this point in the history
  • Loading branch information
jk708 committed Dec 8, 2014
1 parent 8b1f93b commit 0cdb6f6
Showing 1 changed file with 34 additions and 93 deletions.
127 changes: 34 additions & 93 deletions what-is-this.md
@@ -1,99 +1,53 @@
Что это? Зачем и для кого? Как этим пользоваться?
## Что такое YModules?

На эти вопросы я давно хотел получить ответы, но стеснялся их задать. Спросить и прослыть тупицей? Дудки,
я лучше помолчу. Если вы такой же робкий, этот документ именно для вас :)
Модульная система `YModules` применяется к уже готовым блокам, поэтому пригодится вам на последнем этапе разработки.

Что это?
--------
Вы web-разработчик, пишете сайты; на страницах верстаете формочки с контролами,
различные компоненты, большие и маленькие; для большинства из них
пишете клиентский js-код? Вот и продолжайте это делать. Пока у вас нет своего кода,
модульная система вам не нужна. Никому не нужен пустой фантик без конфеты внутри.
Допустим, клиентский JavaScript-код вашего сайта уже написан. Теперь код отдельных компонентов можно разместить по контейнерам, называемым `модулями`.

Модуль - это фантик, в который вы заворачиваете свою конфету. На фантике написано имя конфеты и больше ничего. Вот вы
и поняли, что такое модуль. Оберните код пяти своих контролов каждый в свой отдельный фантик,
у вас получится 5 модулей — система из пяти **ваших** модулей. Конфеты ссыпают в корзинку для сладостей,
откуда конфеты удобно таскать детям. Модульная система и есть такая корзинка.
Модуль подобен фантику от конфеты, на котором написано её название и который по сути является просто обёрткой. Система модулей, в свою очередь, напоминает корзинку с разными сладостями, из которой удобно доставать приглянувшиеся конфеты, определяя нужную по фантику.

Модуль - это контейнер, внутрь которого вы помещаете код своего компонента, и захлопываете крышку. Только, в отличие
от герметичного стального контейнера, "стенки" модуля прозрачные, невидимые. Их словно и нет. А профит есть. Много
профита.
## Зачем использовать модули?

Чтобы понять, для чего нужны модули, вспомним, как обычно связывают между собой объекты, реализующие функциональность сайта.

Зачем это и для кого?
--------------------
Как вы связываете компоненты между собой? Например, вы объявляете на странице блок с формой авторизации,
пишете для неё клиентский javascript-код, в котором описываете поведение формы: нажали на кнопку сабмита — отправь
авторизационные данные аяксом, а не через стандартный `form.submit()`.
Рассмотрим пример: объявим на странице блок с формой авторизации и напишем для неё клиентский JavaScript-код. В нём опишем поведение формы: пусть после нажатия на кнопку `Submit` авторизационные данные отправляются с помощью Ajax, а не через стандартный `form.submit()`.

И допустим, в проекте уже есть специальный компонент "кнопка", в котором реализовано всё поведение кнопки,
например, "если меня нажали, нужно что-то сделать, не знаю что - это решает другой компонент,
в который меня пригласят поработать".
Допустим, в проекте уже определён специальный компонент `кнопка`, для которого задано конкретное поведение. Логически поведение может быть следующим:

То есть, ваша "форма" должна уметь найти кнопку, заполучить её внутрь себя, и слушать на ней событие клика.
*По клику совершается некое действие. Действие определяется компонентом, из которого кнопка была вызвана*.

Как вы определяете, что кнопка **уже готова** взаимодействовать с другими блоками?
Таким образом, форма авторизации должна суметь найти кнопку, вызвать её и слушать событие клика на ней.

Блоки и компоненты тесно связаны и зависят друг от друга, поэтому важно учитывать, готов ли каждый из них для взаимодействия. Модульная система отслеживает готовность всех компонентов за вас и избавляет от необходимости вручную поддерживать зависимости между сущностями в актуальном виде. Это позволяет избегать конфликтов в работе сайта и делает его структуру более логичной.

Модульная система умеет это делать вместо вас. Она избавляет вас от головной боли отслеживать зависимости между
компонентами, поддерживать руками эти зависимости в актуальном состоянии. Это реализовано примерно как наследование,
когда в коде компонента явно указано, от какого класса наследоваться. Только модульная система занимается не наследованием,
а зависимостями между компонентами. Ваш модуль говорит вслух: "для моей корректной работы нужен такой-то компонент".
Две основные функции модуля:

Если вы оформляете форму в виде ymaps-модуля, вы просто декларируете зависимость от кнопки, и знаете,
что код формы будет активирован тогда, когда для этого всё готово, в частности, кнопка готова слушать событие
клика на себя. Вам не нужно самому отслеживать готовность ваших компонентов. Это делает за вас модульная система.
* объявлять себя;
* объявлять, какие модули необходимы для корректной работы данного.

При оформлении формы, к примеру, в виде ymaps-модуля, в нём можно задекларировать зависимость от кнопки. При этом, код формы будет активирован только тогда, когда всё для этого будет готово. В частности, когда кнопка будет готова слушать событие клика на себе.

Как этим пользоваться?
---------------------
````javascript
modules.define(
'A',
['B', 'C'],
function(provide, b, c) {
var a = {};

provide(a);
}
);
````

В этом примере ваш собственный код - единственная строка:
````javascript
var a = {};
````

Всё остальное - обёртка, фантик. Именно этот фантик делает из вашего кода модуль.
Внутрь фантика (специальные js-конструкции) вы складываете нужные ингредиенты (зависимости от других
модулей), перемешиваете, как вам хочется (пишете код своего компонента), фантик скручиваете и втыкаете
в бок зубочистку-флажок с именем модуля. Вы сделали модуль "форма".
## Как использовать модули?

Давайте посмотрим на конфету внимательно.
Напишем для примера код модуля. Для начала объявим модуль с помощью метода `define()` и назовём его `A`:

Так объявляется модуль. Позовите метод `define()`
````javascript
modules.define(
);
````

Скажите модулю: "Тебя зовут `А`"
````javascript
modules.define(
'A'
);
````

Потом добавьте: "Вообще-то ты зависишь от модулей `В` и `С`"
Объявим также, что наш модуль зависит от модулей `B` и `C`:

````javascript
modules.define(
'A',
['B', 'C'],
);
````

Опишите код модуля в анонимной функции. В него параметрами придёт код модулей `B` и `С`,
и вы сможете использовать их внутри модуля.
Опишем код модуля `A` в анонимной функции. Код модулей `B` и `C` придёт в эту функцию в виде параметров, которые можно будет использовать внутри нашего `A`:

````javascript
modules.define(
'A',
Expand All @@ -104,42 +58,43 @@ modules.define(
);
````

Чтобы другие модули могли использовать этот модуль, пусть ваш модуль громко произнесёт вслух:
"Модуль `А` - это я!". Вы делаете это методом `provide(а)`
С помощью метода `provide(a)` разрешим, в свою очередь, другим модулям использовать наш:

````javascript
modules.define(
'A',
['B', 'C'],
function(provide, b, c) {
var a = {};

provide(a);
}
);
````

И, наконец, напишите свой компонент. Пусть это будет что-нибудь хорошее ;)
И, наконец, поместим внутрь обёртки начинку – новый компонент `var a = {}`:

````javascript
modules.define(
'A',
['B', 'C'],
function(provide, b, c) {
var a = 'Yandex is a good company';
var a = 'Candies are awesome';

provide(a);
}
);
````

Всё. Сложности закончились :)
Готово. Наш компонент помещён в удобный контейнер и доступен для взаимодействия с другими компонентами, расположенными в их собственных модулях.

Вот другой абстрактный пример – код модуля, отвечающего за форму логина:

А вот так, к примеру, может выглядеть код модуля, отвечающий за форму логина. Создадим фантик,
позовём в него кнопку и что-нибудь запрограммируем внутри:
````javascript
modules.define(
'y-form',
['y-button'],
function(provide, button) {
//помещаем код компонента внутрь модуля:
var form = getElementById('my-form');
form.on('submit', onSubmited);

Expand All @@ -149,29 +104,15 @@ modules.define(
}
form.submit();
}
//конец кода компонента

provide(form);
}
);
````

Это выдуманный пример, он вообще нерабочий. В теле анонимной функции мы программируем поведение формы в
зависимости от того, активна или неактивна кнопка. А после этого методом `provide(form)` выбрасываем вверх флаг:
"Форма — это я". Теперь и этот модуль может быть вызван другими модулями. Метод `provide` - это выкинутая вверх рука
и всемирно известное: "Свободная касса!"

Возвращаясь к аналогии с конфетой, фантик — это метод `define()` с анонимной функцией внутри. В фантик воткнута зубочистка, за которую конфетку удобно взять — это метод `provide()`. Модуль
независим и работоспособен, потому что он будет запущен только после того, как все зависимости будут предоставлены
(правильные программисты используют термины "разрезолвлены" или "разрешены") внутрь модуля.

Осталось сказать, что зависимости резолвятся асинхронно, дерево зависимостей строится в рантайме,
модули можно переопределять и доопределять. А теперь возвращаю вас к главной странице инструмента: https://github.com/ymaps/modules

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

PS. Кстати, дерево зависимостей, построенное модульной системой, можно использовать в любом файловом сборщике,
потому что имя модуля легко мапится на имя файла,в котором этот модуль хранится. И тогда
вы ещё и собирать файлы руками не будете, всё будут делать роботы ;)
Здесь, в теле анонимной функции, мы программируем поведение формы в зависимости от того, активна кнопка или нет. Используя метод `define()`, мы определяем сам модуль с анонимной функцией внутри. Используя метод `provide()`, мы заявляем, что данный модуль может быть вызван другими.

Модули независимы и запускаются лишь в случае, если все их зависимости зарезолвлены. Резолвятся они асинхронно, и дерево зависимостей строится в рантайме. Модули можно переопределять и доопределять в любой момент.

Багрепорты, сложные вопросы и благодарности присылайте на dfilatov@yandex-team.ru :)
Дерево зависимостей модульной системы также можно и удобно использовать в любом файловом сборщике: имя модуля легко мапится на имя файла, в котором этот модуль хранится.

0 comments on commit 0cdb6f6

Please sign in to comment.