Comments 32
Не холивара ради, но интереса — около года назад видел статью парня, который на английском языке жестоко агрил насчет того, что люди не создают модули, а пишут значит mvc-приложения, а он, значит, видел весь смысл в модулях, а те делил на еще более мелкие модули.
Страница та выпадала в гугле по какому-то жутко умному запросу про MVC и не могла быть найдена просто так — просто была мусором в сети с кучей комментариев в стиле «хватит агрить парень, мир какой он есть!»
А сейчас вот, куча фамилий, сотни диаграм, на выходе вывод — ребята, вы неправильно понимаете MVC. Пора прекратить класть файлики в папки views, а нужно просто писать модули, которые имеют самостоятельный html/js, ну то есть вас пару лет за нос водили, теперь идем в другую сторону.
Радость то! Пришло таки :)
К слову о фасадах — это было очень круто разжевано в о-рейли, паттерны проектирования, они там писали контроллер для «умного дома» в упрощенном варианте. И использовали паттерн Фасад как мега-модуль (который по сути объединяет десяток Комманд), паттерн Контроллер — как навесить на каждую кнопку пульта действие (для независимости к каждой кнопке вешалось действие в виде объекта), а паттерн Команда (это когда конкретное действие описывается как класс, который станет объектом)
Может я конечно пол-статьи не понял, я такой паренек, который значит «увлекается в свободное время», а на работе умничать времени нету. Любопытно взглянуть на простейший пример нотации такого приложения, в котором логика контроллера внешнего модуля отвечающего за layout (имеющего вещи которые нужно сделать при инициализации) — не связана с модулем какой-нибудь драной кнопки или выпадающего меню, и как это сделать вне связей их друг с другом.
exports он разумеется есть, но чтобы добиться полной независимости, очень любопытно увидеть пример. на любом языке.
Любопытно взглянуть на простейший пример нотации такого приложения, в котором логика контроллера внешнего модуля отвечающего за layout (имеющего вещи которые нужно сделать при инициализации) — не связана с модулем какой-нибудь драной кнопки или выпадающего меню, и как это сделать вне связей их друг с другом.
Я не очень понял, что вы имеете ввиду. Мы разрабатываем так, что есть корневой модуль, он внутри себя содержит "layout" модуль (или сразу от него наследуется), в который помещает модули экранов, которые может провязать друг с другом, через реактивные свойства. Например:
$my_app $mol_view
sub /
<= Layout $mol_book
pages /
<= Menu $my_task_menu
selected => task_selected
<= Details $my_task_details
task <= task_selected -
Тут мы создаём корневой компонент, который внутрь себя помещает "книжную раскладку", в которую помещает две панели: меню со списком задач и подробности по выбранной задаче. При этом обе панели друг о друге не знают ничего, но корневой компонент берёт выбранную задачу из писка задач и биндит её на показываемую задачу в "подробностях".
Если раскрывать вопрос по демонстрации: ну вот в качестве примера написать на этой позиции обычный такой landing-site с одной стороны на 2 страницы (чтобы была первая и вторая), с другой стороны с отправкой на email письма например, с третьей стороны с поддержкой «тем» и «языков»,
Ну то есть в каждой из сфер по два примера, и самое обидное — связать их так, чтобы была минимальная связность.
Обычно моя проблема в том, что модуль, который я внедряю в чей-то битрикс-говнокод так или иначе требует взаимодействия с самим битриксом. И начинаются связи и невозможность разделить его на маленькие модули — загоны в стиле — а где хранить ссылки на уже созданные объекты? если их хранить в каждом дочернем модуле, то это затраты памяти, делать их через статику — трудности в поддержке потом, когда видишь Class::method() и понимаешь что походу пора идти читать, что там в классе и когда писали.
Даже целиком выписывая программу на интерфейсах и передавая только готовые объекты из функции в функцию все равно вдалбливаешься в необходимость некой шины, которая контроллирует все что было сделано и вся модульная структура снова сыпется по кусочкам или наполняется статическими вызовами.
Где баланс? Показал бы только пример кода.
Рассмотреть контроллер под конкретные случаи типа — контроллер шаблона. Это контроллер вообще? Нет наверное. С другой стороны ему нужно подготовить css/js под конкретный модуль, а родительскому — под себя и еще забрать у всех потомков и так рекурсией хрен знает сколько раз, чтобы была одна точка контроля на каждом уровне. Вот где самый расколбас.
Написать api на контроллерах, который возвращает json и принимает get/post/head быстро и легко — и поддерживать потом тоже легко. А вот когда начинается игра в «продвижение сайта» — начинается веселуха. Вот у тебя скрипты в модуле лежат — ты их слил в один красиво так, родительский модуль подхватил… и тут понимаешь, что jquery был в одном модуле и в другом — оппа уже dependency. А если депы, то значит контроль версий. А если контроль версий — то нужна шина — глобальный модуль, отвечающий за другие модули.
И поди его сделай фасадом, поди пойми, что в нем команда, а что просто объект, учитывая что весь код по сути состоит тоже ведь из команд. И вот эта двойственность слов — под словом команда можно понять это это и вон то — все губит. Вместо красивого кода получается опять связанный клубок ниток.
Опять же — примеры нужны, хоть какие-нибудь. Не картинки, а код — с определением в стиле «давайте представим что вот этот обьект — это команда».
И он же следит за dependency, и он же сжимает код и в общем-то молодец даже
Это чертовски удобно, когда пишешь яваскрипт код под такую верстку, и в стилях вложенности по минимуму, и редактировать легко.
Молекулы? Что?
БЭМ от Яндекса — это костыль, который пытается бороться с отсутствием вложенности и namespace'ов в СSS. Туда же все эти OOCSS и прочие извращения.
Любить button button--state-danger
или там .media__img--rev
— это стокгольмский синдром.
То, что предлагает http://patternlab.io ортогонально BEM'у. Это подход к проектированию интерфейсов:
- выделяем из интерфейса самые мелкие самодостаточные переиспользуемые компоненты: кнопки, поля ввода и т.п. Это «атомы»
- Эти мелкие компоненты объединяются в более крупные блоки, которые тоже можно произвольно использовать заново: «поле поиска с кнопкой поиска» (состоящее из «поле ввода», «кнопка»), «меню» (состоящее из «кнопка», «список»(который состоит из «элемент для показа текста»)). Это «молекулы»
- и так далее: «молекулы» компонуются в более сложные структуры. Эти более сложные структуры в еще более сложные и т.п.
Более подробно в Atomic Design: http://atomicdesign.bradfrost.com/table-of-contents/
Я так и не понял, почему вы противопоставляете "матрёшку" БЭМ-у. БЭМ — это один из способов реализовать ту самую "матрёшку", когда более крупные компоненты состоят из более мелких. И для этого вовсе не надо вводить странную номенклатуру "Атом -> Молекула -> Организм -> Шаблон -> Страница". Любой компонент ("блок" в терминологии БЭМ) может состоять из любых других компонент ("элемент" в терминологии БЭМ), которые также могут состоять из компонент и тд.
Все ваши претензии упираются в правила именования, которые можно выбирать любые. Мы, например, автоматически генерируем такие бэм-аттрибуты: my_sign_in_submit mol_view mol_button mol_button_type="major"
— они позволяют точно понять где и зачем объявлен тот или иной стиль.
Например, следующее правило, добавляет всем нашим компонентам одни и те же стили по умолчанию, без влияния на не наши элементы:
[mol_view] {
transition: all ease .1s;
}
А следующий задаёт особый размер нашей кнопке сабмита на форме входа:
[my_sign_in_submit] {
font-size: 2rem;
}
Прелесть полного именования в самодокументированности, которую вы теряете при использовании коротких имён в изолированных контекстах. Изоляция контекстов позволяет не конфликтовать именам в рантайме. Но в мозгах программистов они всё-равно будут конфликтовать. Так что вам в любом случае придётся "восстанавливать контекст". С полными именами контекст у вас всегда перед глазами, а в стилях нет автогенерированной абракадабры, обеспечивающей уникальность имён.
Если провести аналогию на жизнь — то каждый человек называет вещи своими именами отличными от других человеков (блоков в нашем случае).
Таким нехитрым образом блоков могут быть тысячи (человеки) — элемент (дом-нода) для каждого из них свое имя имеет. А модификатор — это пометка, что элемент имеет вариации в пределах карты мира данного человека.
Зачем двойные тире — я не использую. Двойное подчеркивание кстати ничего, вместо верблюда то.
block-block__element-element_modif, и все классы в таком виде.
Вложенность только там, где есть _modif, т.к. в пределах вариации дочерние элементы могут отличаться внешне.
Вроде все просто?
Поясните вашу точку зрения с бесконечным усложнением, потому что мне не понятна причина выбрасывать на помойку текущее решение.
Я конечно ожидаю, что вы можете сейчас отреагировать не так как я ожидаю, но в этом случае сможем завершить дискуссию
Вы говорите о композиции компонент управляемой данными. Реализуется это достаточно не сложно. Но при чём тут БЭМ и вообще CSS?
Так работает, например, визуализатор маркдауна. В результате парсинга получается AST, по которому собирается дерево компонент.
Контент нод в структуре может быть любым.
И каждая нода — отдельный блок. Они же не зависимы, раз компонуются как угодно.
В прямом смысле слова достаточно сложно.
Дано — «разобранные» компоненты
Должны получить
Я может чего-то не понимаю, но вроде ничего сложного тут нет:
var data = [
{"a":{"parent":"b"}},
{"c":{"parent":"b"}},
{"d":{"from":"a"}},
{"d":{"from":"c"}}
];
var components = {};
var imports = {};
// prepare
for (var i in data) {
var item = data[i];
var componentName = Object.keys(item)[0];
var itemData = item[componentName];
if (itemData.parent != undefined) {
parentComponentName = itemData.parent;
components[componentName] =
{parentName: parentComponentName, children: {}};
components[parentComponentName] = {parentName: null, children: {}};
}
if (itemData.from != undefined) {
var fromComponentName = itemData.from;
imports[fromComponentName] = componentName;
}
}
// make
for (var i in data) {
var item = data[i];
var componentName = Object.keys(item)[0];
var itemData = item[componentName];
if (itemData.parent != undefined) {
parentComponentName = itemData.parent;
components[parentComponentName].children[componentName] =
imports[componentName];
}
}
// clean
for (var i in components) {
if (components[i].parentName != null) {
delete components[i];
} else {
delete components[i].parentName;
}
}
console.log(JSON.stringify(components, null, 2));
/*
{
"b": {
"children": {
"a": "d",
"c": "d"
}
}
}
*/
Вы можете теперь сослаться на то, что я лентяй или как угодно поступить, но я правда ожидаю от вас примера из жизни как это работает, и почему это легче для каких задач. Пока вижу голые фразы, намеки на почитать — но зачем мне читать бескрайние берега? Разводил мало в жизни? Давайте уже работать, а не демонстрировать, если хотите программирование на новый уровень.
Мы похоже на разных языкх разговаривем.
Что такое "сборка компонент"? и зачем дизаинерам знать имя родительского? Что такое "цепочки"? что за "ключи" генерируются и зачем?
Это вы описываете какое-то своё решение не понятно какой задачи. Если нужно "соединять независимые компоненты друг с другом", то это легко делается через биндинги. Пример, я приводил выше.
о «загрязнении» Модели настройками интерфейса
На "подумать" для желающих:
допустим у меня есть чекбокс и текстовое поле, которое должно быть доступно для редактирования (enabled) только если галочка стоит; а если она не стоит, то текстовое поле должно быть пустое. Так вот, где эта логика должна быть прописана, в M, V или C?
допустим, у меня одна и та же информация отображается одновременно и в таблице, и в списке; если в таблице выбрана какая-то строка - где должна информация об этом выделении храниться, в M, V или C?
Охота на мифический MVC. Построение пользовательского интерфейса