Выбор подходящей архитектуры — ключевая часть построения интерфейса службы.
Девелопер Анна Карпелевич рассказала студентам Школы разработки интерфейсов , что такое архитектура, какие функции она выполняет и какие проблемы решает. Из лекции вы сможете узнать о самых популярных архитектурных подходах во фронтенде: Model-View-* и Flux. - Добрый вечер.
Меня зовут Аня Карпелевич.
Сегодня мы поговорим о фронтенд-архитектуре верхнего уровня.
Я работаю в Директ. Делаем интерфейсы для рекламодателей.
Они подают объявления, настраивают их.
Это очень сложная, интересная система, в ней много взаимосвязанных компонентов, они перерастают друг в друга, имеют общий и свой функционал.
«Штаны превращаются в нарядные шорты».
Все это нужно очень тщательно контролировать.
А архитектура в наших приложениях очень сложная.
Это одна из причин, почему я читаю эту лекцию сегодня.
Мне очень нравится эта тема.
Что такое архитектура? Дело в том, что ответа на этот вопрос, вероятно, нет. Или есть, но у каждого свое.
Это очень спорная тема.
Вызывает много споров, много холиваров.
И многое из того, что я скажу вам сегодня, является моим мнением.
Что-то из этого поддерживается моей рабочей группой, что-то не очень.
И каждый, когда пишет архитектуру своего приложения, сам решает, как и что ему делать.
Вот почему архитектура, пожалуй, одно из самых творческих мест в работе программиста.
И поэтому наша сегодняшняя презентация тоже начнется с творчества.
Давайте посмотрим на левую картинку.
Буду очень рад, если кто-нибудь узнает здание, которое на нем изображено.
Это церковь Сен-Сюльпис в Париже.
Обратите внимание на башенки, именно поэтому здесь построена эта церковь.
Надеюсь, понятно, что они разные.
Совсем другое дело, и этому есть интересная причина.
Разница между ними составляет 130 лет. Левая башня была снесена и перестроена во время франко-прусской войны.
Почему она здесь? Посмотри на эту картинку.
Башни имеют одинаковую архитектуру, но вся обстановка, эти виньетки, безделушки, арочные конструкции разные.
Почему это? Потому что назначение этих башен одно и то же.
Ни одна из них, например, не была колокольней.
Это просто башни.
Что-то в них хранилось, но все остальное было другим.
Почему? Потому что архитектура этих башен одинаковая.
Оба имеют свод, окно только одно, и оно стрельчатое.
Высота окон примерно одинаковая.
Идея состоит в том, что архитектура, как здания, так и приложения, является несущей структурой.
Это не виньетки, не трюки, не реализация.
Это то, что лежит в основе.
И эта основа, как правило, зависит от окружающей среды, от почвы, если мы говорим о здании, от цели, которую ставит перед собой архитектор, но почти никогда не зависит от дизайнерских изысков.
Пример со зданием для темы про архитектуру вполне нагляден.
Но правая картинка интереснее.
«Архитектура — это немая музыка».
«Architektur ist gefrorene Musik», — сказал Иоганн Вольфганг Гете в XVIII веке.
Гете, скорее всего, ничего не знал об архитектуре зданий; он был поэтом.
И он гарантированно ничего не знал об архитектуре приложений.
Но он высказал очень ценную и интересную мысль.
Музыка существует в динамике.
Это не что-то статичное.
Это процесс.
Точно так же приложение — это процесс.
У него есть момент запуска, есть момент развития, когда мы с ним что-то делаем, работаем.
И наконец наступает момент завершения.
Архитектура приложения — это его снимок в любой момент времени.
В любой момент наше приложение, как и музыкальная тема, должно быть четким, ясным, понятным, предсказуемым и т. д. Иначе все развалится.
На этом мы заканчиваем творческое введение и переходим к вещам более приземленным, более близким к практике создания приложений.
Что такое архитектура и зачем она нужна?
Во-первых, нам приходится организовывать большой объём кодов, с чем мы в Директе — и не только в Директе — сталкиваемся постоянно.
Кода так много, что в нем можно потеряться.
Мы не хотим потеряться в коде.
Во-вторых, дублирование функционала.
Это тоже вечная проблема, с которой вы всегда будете сталкиваться, и сегодня эта тема про дублирование будет проходить через всю лекцию.
Нам может понадобиться один и тот же функционал в нескольких местах интерфейса.
Если он нужен в нескольких местах, то это должен быть физически один и тот же код, который используется в нескольких местах, а не копии.
Почему? Об этом мы поговорим дальше.
Но архитектура должна помочь нам избежать копипаста.
В-третьих, это поддержка.
Совершенно очевидно, что если у нас есть приложение, то его нужно как-то поддерживать, и желательно, чтобы на это не тратились все ресурсы команды.
Изменение состава команды.
Это тоже вещь, с которой мы сталкиваемся в реальной жизни чаще, чем хотелось бы.
Кто-то приходит, кто-то уходит, и если человек полгода пытается проникнуть в код, это плохо.
Если знания о коде хранятся только в одной голове, и он будет передавать эти знания в течение шести месяцев, если уйдет, это еще хуже.
В общем, здесь архитектура тоже помогает нам сделать все это более понятным и поддержать обмен знаниями.
Добавление и расширение функционала.
Это тоже довольно очевидная вещь.
К нам прибегает менеджер и говорит, что нам это срочно нужно.
И если для того, чтобы сделать это срочно, придется потратить много времени и сил, то это плохое архитектурное решение.
Но нам нужны хорошие вещи.
И наконец, ошибки.
Чем понятнее и предсказуемее наша архитектура, тем легче находить ошибки, тем меньше ошибок.
Как все это можно назвать? Все это можно назвать проблемами сложной системы.
Приложение — сложная система, архитектура помогает нам решить задачу.
Короче говоря, что-то в этом роде.
Справа от меня картинка лапши, и вот что происходит, если не следить за архитектурой, если не строить, не продумывать и не проектировать.
А вторая картинка — что получится, если как-то продумать архитектуру.
Это еще не Сен-Сюльпис, но, по крайней мере, это детский конструктор, он стоит твердо и не разваливается.
Сегодня мы тоже будем много играть с конструктором.
Формально обо всём этом.
Архитектура — это способ решения проблем сложной системы путем абстрагирования реализации от интерфейса и разделения полномочий между блоками кода.
Далее мы подробно разберем эту длинную фразу.
Каковы особенности архитектуры приложений как области знаний? У нее есть определенная сфера, с которой мы работаем.
То есть это не что-то абстрактное, это вполне конкретная вещь.
Вот задача, подбираем под нее архитектуру, а не типа, ух какой интересный архитектурный подход, надо попробовать.
Так что нет. Можно попробовать на чем-то маленьком, но для серьёзного проекта подбирается архитектура, иногда написанная под конкретный проект. История вопроса, когда вообще возникла эта идея, что нужно заниматься архитектурой.
Надо сказать, что в свое время весьма неординарную идею высказал в 1968 году Дсгер Дейкстра, замечательный программист. Вероятно, он наиболее известен как автор алгоритма Дейкстры, который ищет кратчайший путь в графе.
Но у него есть немало, по сути, прорывных для своего времени идей.
И одна из них - статья, ссылку на материалы дам позже, можете прочитать, всего две страницы, небольшое эссе.
Звучит это как «Оператор GOTO считается вредным», переводится как «Оператор GOTO — оператор безусловного перехода — зло».
Это была первая мысль, что давайте официально заявим, что надо писать архитектуру, а не лапшу.
В 70-е годы эту идею Дийкстра развивал совместно с Парнасом и самостоятельно, отдельно.
Первая подробная книга об архитектуре приложений в целом была написана в 1996 году Мэри Шоу и Дэвидом Гарланом.
После этого, собственно, столь подробные книги об архитектуре ПО не писались именно из-за масштаба, что в каждой области знаний есть свои архитектурные подходы, где-то более популярен один, где-то другой, что-то, вообще, в каких-то не применимо.
места.
А поскольку архитектура — это творческий процесс, то конкретных книг о том, как писать архитектуру, вы не найдете.
Возможно, после 1996 года на эту тему не было ничего особо подробного.
Каковы текущие требования к архитектуре проекта? Первое и самое важное, что ему действительно нужно, — это расширяемость, потому что, если ваш проект не расширяем, он мертв.
Повторное использование кода.
Это про тот самый копипаст. Если у вас есть два блока, которые используются в двух разных местах, нужна одна и та же функциональность, тогда один и тот же код нужно использовать повторно, а архитектура должна быть такой, чтобы любой фрагмент кода можно было взять и использовать повторно, как только он понадобится.
.
Разделение полномочий между модулями кода.
Об этом сегодня мы также поговорим подробнее, зачем это нужно.
Идея такая: каждый модуль, каждый блок, каждый фрагмент кода должен выполнять одно конкретное действие, нести ровно одну функцию.
И эту функцию нужно разместить в заголовке этого метода, класса, что бы это ни было, модуля.
Один модуль – одна функция.
И наконец, качество приложений.
Здесь много чего хотелось бы сделать, и безотказность, и обратную совместимость.
На самом деле, опять же, он подбирается под задачу.
Где-то нужна обратная совместимость, чтобы ни в коем случае ничего не сдвинулось.
Где-то нужна надежность, чтобы, не дай Бог, пароли, ПИН-коды карт или CVV никуда не утекли.
Где-то оно должно быть безотказным, будь то спутник или что-то еще.
В общем, выбирайте любые несколько.
Чем больше вы хотите поддерживать, тем с большей архитектурной сложностью вы, вероятно, столкнетесь.
Дальше мы с вами поговорим о некоторых определениях, просто таких энциклопедических вещах.
Почему это важно? Потому что терминология в архитектуре очень важна, и нам нужно говорить на одном языке.
Определения в основном взяты из парадигмы программирования, называемой ООП.
Но на самом деле они переросли в другие парадигмы, причем термины «класс, объект, интерфейс» действуют не только в рамках ООП.
Однако эти определения и понимание взяты именно из мира ООП.
Самое простое — класс.
Что такое класс? Это шаблон, это образец.
Вот, например, класс Snake. Мы определили для него три приватных поля, то есть поле, которое не доступно никому, кроме методов самого класса — количество голов, количество хвостов и длина у попугаев.
Мы определили конструктор, в который закладываем в попугаев эти самые головы, хвосты и длины.
Получил класс Змеи.
Это просто.
Давайте двигаться дальше.
Объект. А объект — это экземпляр определенной структуры.
Более того, опять же в классическом ООП предполагается, что объект является объектом класса.
В современном мире в JavaScript, который не всегда был языком ООП, да и сейчас не всегда и не всегда ООП, мы знаем, что могут быть абстрактные объекты.
То есть мы можем создать объект, литерал, который не будет объектом класса.
Но вот пример того, как мы создаем объект класса Snake. Вот перед нами двухвостая змея длиной 38 попугаев – удав.
Модуль.
Модуль — это смысловая единица.
Это не всегда класс.
Это может быть набор классов, набор объектов, набор методов, не объединенных в классы.
Обычно вы можете думать о модуле как о чем-то, что вы записали в один файл.
Но в принципе модуль — это еще и папка, в которой они находятся, например файл и тесты для этого модуля — это тоже модуль.
Здесь важно то, что модуль — это то, что вы называете модулем, то, что вы считаете единицей семантики.
В данном случае модуль о том, как мы едим змей.
Результатом работы этого модуля является последний метод eatSnake, с помощью которого мы едим змей.
Я не знаю, почему мы едим змей, но мы знаем, как это сделать, потому что именно так мы написали этот модуль.
Это было тривиально; тогда начнется что-то более интересное.
Интерфейс класса.
Интерфейс класса — это, проще говоря, его публичные методы, то, что из него выпирает, что мы можем получить от объекта этого класса из объекта извне.
Этот класс реализует интерфейс getSnakeLength. Он может вернуть нам длину змеи.
Обратите внимание, что внешний доступ к приватным полям отсутствует. Внешний доступ доступен только общедоступному методу getSnakeLength.
Здесь происходит очень интересная вещь.
Мы долго спорили, как назвать эту штуку, ведь термин «абстрактный интерфейс» я придумал, когда писал эту лекцию.
И, честно говоря, я нигде не видел нормального определения этого подхода и метода.
Однако многие языки программирования позволяют создавать абстрактные интерфейсы и называть их если не абстрактными классами, то и абстрактные интерфейсы тоже просто интерфейсами.
Оказывается, это омоним интерфейса класса.
Идея состоит в том, что абстрактный интерфейс — это набор методов, которые что-то делают. Когда мы создаем класс, мы исходим из вопроса «что этоЭ» Это змея, и она может что-то делать, а может и нет. Она может просто выдать свою длину.
И когда мы создаем интерфейс, мы исходим из того, что он делает, что он должен уметь.
И это оказывается очень мощным способом расширения классов.
Мы можем присвоить классам некоторые возможности, расширив их интерфейсами.
Например, фреймворк I-BEM может сделать такое; такая история с абстрактными интерфейсами встроена во фреймворк.
Многие фреймворки, к сожалению, не могут этого сделать, но это мощная вещь.
В качестве примера мы создали звуковой интерфейс, который может звучать.
И его определением является абстрактный пустой метод getNoise. Мы расширили нашу змею классом audiable, реализовали ее метод getNoise, и наша змея зашипела.
Вдохновением для создания этого набора примеров меня вдохновила замечательная книга Рика Фримена и компании Design Patterns. Теперь мы попробуем рассмотреть эти примеры немного более конкретно.
Но сначала давайте поговорим о том, зачем нужны были эти примеры.
Но они были нужны для этого большого слайда.
То, что здесь написано, настолько важно, что я даже поместил это на желтом титульном листе.
Это, можно сказать, мантра.
Это очень важный принцип, о котором вы всегда должны думать, когда проектируете архитектуру.
Высокая связность, низкая связанность — сильная связность, слабая связь.
Есть определенная проблема в том, что и слово связность, и слово связность переводятся на русский язык как «связность»; слово «сцепление» было придумано специально для этого принципа.
Вот идея.
Ваши блоки должны быть очень компактными и очень плотно сцепленными между собой.
Они должны реализовывать ровно одну функцию.
Причем соединяться между собой они должны очень легко, чтобы их можно было легко комбинировать и собирать, как конструктор.
И тогда ваша архитектура будет достаточно гибкой и достаточно надежной.
А еще легко проверить.
Давайте посмотрим, как мы можем добиться сильной связи и слабой связи, как говорится, точка за точкой.
Специализация.
Каждый блок решает только одну задачу.
Вот хорошая иллюстрация – детский конструктор.
У нас есть каждый блок или набор блоков.
Все они имеют свою форму, свой размер.
А если нам нужно построить дом, мы возьмем длинные блоки.
Если нам нужно построить шар, мы возьмем короткие блоки.
Каждый блок имеет свою функцию.
А те, кто играл с конструкторами, знают: чем проще форма деталей, тем больше из них можно построить.
Из таких закорючек ничего не построить, либо строится только то, что описано в инструкции.
И кому это нужно? То же самое, абстракция.
Речь идет об абстракции интерфейса от реализации.
Идея в том, что интерфейс внешний, то, как выделяется наш класс, наш блок, то, как он взаимодействует с другими блоками, не должно влиять на его внутреннюю реализацию.
Напротив, такое случается.
Никогда в другую сторону.
В хорошей архитектуре.
Вот, например, образование этих пупырышек не влияет на форму самого блока.
Отдельно выбираем форму блока и приклеиваем на него пупырышки.
Инкапсуляция.
Продолжение предыдущей темы.
В приватных методах, то есть изнутри наших блоков, мы реализуем сам смысл нашего блока — реализацию.
И интерфейс, способ их подключения - в открытом доступе.
То есть в данном случае все эти крестики, тире и сама форма — реализация.
А прыщи — это интерфейс.
И хорошая архитектура выглядит именно таким конструктором.
Ох, какой страшный монстр.
Речь идет о повторном использовании кода.
Изначально этот монстр, по сути, был призван показать пример плохой архитектуры, но посмотрите на него внимательно.
Он красивый.
Более того, он явно доволен жизнью, довольно бодро бегает на своих странных ножках.
Возможно, он даже умеет летать или, по крайней мере, у него красивые крылья бабочки.
В чем идея? Если у вас есть реализация на верблюда и реализация на крокодила, и к вам приходит менеджер и говорит, что срочно нужен верблюд-крокодил.
Вы не пишите отдельно верблюда-крокодила.
Вы берете тело верблюда, отделяете его от всей реализации верблюда.
Возьмите голову крокодила, отделите ее от крокодила и используйте блоки повторно.
Почему это необходимо? Потом, когда к вам снова прибежит менеджер и скажет, что мы срочно расширяемся в Южную Америку, а там аллигаторы, нам нужно поддержать неправильную форму челюсти, или что у крокодила четвертый зуб не тот, вы не будете шарить весь проект, где вы копировали головы крокодилов.
Потому что поблизости может оказаться еще какая-нибудь зебра-буйвол-крокодил.
Вы просто берете свой класс головы крокодила, делаете его расширением серии голов аллигатора, передаете ему параметры, и он определяет, какие зубы ему следует рисовать.
Вот и все.
В одном месте, а не во всех местах, где он используется.
Здесь надежность возрастает в разы, ведь какую-нибудь скопированную голову вы гарантированно забудете в каком-нибудь очень редком проекте.
В целом, в таких трупах нет ничего страшного.
Хороший труп, полезный.
Теперь мы рассмотрим примеры плохого кода.
Обратите внимание, что это псевдокод. Псевдокод немного похож на TypeScript, но все же псевдокод. Не пытайтесь это запустить, это не сработает. Можете повторить, запускать именно этот код не стоит, так как он использует синтаксические конструкции, которые TypeScript 2.7 не поддерживает, но иллюстрации получились неплохие (теперь есть более актуальные примеры — прим.
редактора).
Итак, у нас есть класс User. У него есть имя и возраст. Всё хорошо.
У нас есть Пользователь с фамилией, прошу прощения за разные шрифты.
Пользователь с фамилией, у него есть имя, возраст и фамилия.
И у нас есть метод printLabel. Передаем ему User. Далее смотрим, есть ли у нас Пользователь класса User, рисуем имя и возраст. Если Пользователь относится к классу Пользователь с фамилией, то имя, фамилия и возраст. Давайте все же попробуем разобраться, что здесь плохого.
Дублирование кода, да? Много разного дублирования кода, это хорошо.
Да конечно.
Здесь есть два дублирования кода — одно — мы дублируем UserWithSurname, второе — мы дублируем себя в методе printLabel. Что еще там? Правильно, да, все дело в том, что у нас много дублирования кода, потенциально даже больше.
Есть ли здесь что-нибудь еще? Наследование тоже здесь есть, и это тоже один из вариантов.
Здесь две проблемы — нет повторного использования, нет специализации.
Мы говорили еще о двух вещах.
PrintLabel попадает в частные методы.
Более? В-четвертых, чего здесь не хватает? Да все верно.
Никакой специализации нет, два блока делают одно и то же.
Никакой абстракции, у нас смешаны интерфейс и реализация.
Инкапсуляции нет; действительно, доступ к частным методам.
Переиспользуя код, очень правильно сказали о бесконечных «если», которых может быть очень много.
Давайте посмотрим, как это сделать лучше, но давайте не будем делать это таким образом.
Мы создадим интерфейс printLabel, это не потому, что iPrintLabel не из-за iPhone, а потому, что это интерфейс.
И мы определим один абстрактный метод getText. Давайте создадим класс User, реализующий iPrintLabel. У него действительно будут приватные поля name и age, и единственный публичный метод, тот самый getText из iPrintLabel, в котором мы будем честно обращаться к его приватным полям из класса, это разрешено и даже поощряется.
UserWithSurname действительно будет наследником класса User, и нам нужно будет только переопределить Surname и переопределить getText. Но printLabel станет очень простым.
Он примет iPrintLabel и просто выведет getText. Прелесть здесь в том, что если и появляется абстракция, то интерфейс отдельно, реализация отдельно.
Появляется инкапсуляция.
Специализация пожалуйста, для этого мы сделали наследование.
А с повторным использованием кода вообще все хорошо, ведь мы можем напечатать что угодно, главное расширить его интерфейс iPrintLabel, и нам не придется думать о том, будет это напечатано или нет, оно будет напечатано.
Мы больше не будем касаться метода printLabel. Вот хороший и очень простой способ улучшить архитектуру с помощью нескольких дополнительных строк кода.
На этом мы заканчиваем с теорией.
С теорией всего, потому что то, что мы только что описали, справедливо не только для фронтенда, но и для всего в целом.
И переходим к архитектурным подходам и отдельно к архитектурным подходам, которые используются во фронтенде и пригодятся, используются, встречаются.
Как работает обычное веб-приложение? Есть сервер.
Внутри сервера реализована какая-то внутренняя архитектура.
Из него торчит какой-то API, например, это может быть REST API или не REST. Все вместе — клиент и сервер — тоже реализация клиент-серверного архитектурного подхода.
Потому что у нас могут быть чисто серверные приложения, чисто клиентские приложения, какой-нибудь PowerPoint, из которого все это проигрывается.
Это чисто клиент-серверное приложение.
Далее мы более подробно рассмотрим фронтенд. Интерфейс состоит из нескольких больших блоков.
Каждый блок реализован каким-то образом, и эта реализация позволяет связывать большие блоки вместе.
Внутри модуля это тоже как-то реализовано.
Внутри модуля есть метод. Этот метод также имеет архитектуру.
И поэтому архитектура – это, по сути, иерархия.
Он существует на каждом уровне, даже на уровне объявления переменных; это также может быть часть архитектуры.
Маленькие.
Сегодня мы поговорим о верхнем уровне front-end архитектуры, то есть о том, как структурированы большие модули, как данные передаются от пользователя к серверу, от сервера к пользователю и немного о реализации внутри модулей, как реализовать их так, чтобы они соответствовали архитектуре, которая была создана.
> Клиент-сервер ( Клиент-сервер ) > Компонент ( Компонентный ) > Событие ( Управляемый событиями ) > ОТДЫХ ( Изобразительное State Transfer ) > Модель-Вид-*( MVC , MVP , МВВМ ) > Однонаправленные потоки данных ( Поток )Это архитектурные подходы.
О некоторых из них мы сегодня упомянули.
Клиент-серверная архитектура; компонентная архитектура, одна из ее вариаций вам знакома по React, надеюсь, знакома.
Событийный, который, как ни странно, тоже всем знаком; на нем основаны почти все операционные системы для персональных компьютеров.
REST, то, что мы любим в сервере, и два последних, с которыми мы сегодня познакомимся подробно, — это самые фронтенды, с чем мы работаем — это model-view* и однонаправленные потоки данных.
Начнем с МВ*.
Почему звездочка? История, как говорится, полна боли и гнева.
Когда-то, ещё в 80-х годах, был придуман замечательный архитектурный подход под названием MVC. M – Модель, V – Вид, C – Контроллер.
Подход оказался очень удобным.
Его вообще придумали для консольных приложений.
Но когда веб-технологии начали развиваться, когда все стали ими пользоваться, оказалось, что иногда это необходимо, но модель MV хороша, а Контроллер реализован не так.
В результате появилось столько разных вариантов реализации Model-View — чего угодно, что возникла первоначальная путаница из-за того, что все называли это MVC. Потому что если есть модель МВ, то третья — Контроллер, что бы мы туда на самом деле не напихали.
Потом оказалось, что люди путаются и под MVC подразумевают совершенно разные вещи.
Примерно сейчас, не более года назад, эту терминологию начали активно разделять и давать каждой реализации этого подхода собственное имя.
Так или иначе, этот MV* появился.
Я также видел в Интернете термин MVW, где W означает «что угодно».
Ну а мы переходим, собственно, к технологиям MVC.
Как они построены? Идея в том, что у нас есть модель, хранящая данные.
Их обычно много.
Существует какое-то представление, которое показывает эти данные пользователю.
Их тоже, как правило, очень много.
И какой-то третий компонент, являющийся посредником между ними, соединяет данные и отображение.
Вот пользователь в правом верхнем углу со всем этим работает.
MVC, с которого все началось, появился еще в 1980 году, Smalltalk. Но именно в таком виде он до сих пор существует в некоторых рамках.
Не в некоторых, довольно многих.
В чем идея? Пользователь работает напрямую с представлением и контроллером.
Он вводит данные в некоторые поля представления, нажимает кнопку отправки и данные поступают в контроллер.
Это отправка формы.
Это честная отправка формы с помощью давно знакомой всем кнопки отправки, надеюсь.
Давайте посмотрим.
Желтая стрелка от пользователя к контроллеру означает, что пользователь отправил данные контроллеру с помощью кнопки отправки.
Зеленая стрелка – туда перешло управление.
Контроллер просматривает эти данные.
Возможно, он их как-то обрабатывает, есть тонкости реализации, и отправляет в нужную модель.
Контроллер сам выбирает, на какую модель отправлять.
Отправляет с помощью зеленой стрелки управления, отправляет данные с помощью желтой стрелки.
Модель также обрабатывает данные.
Возможно, она их подтверждает. Возможно, она помещает их в базу данных.
Короче говоря, модель знает, что с ними делать.
Обычно результатом являются новые данные.
Например, мы можем сообщить пользователю, вошел он в систему или нет, и модель сверит пароль с логином.
После этого модель снова передает управление контроллеру, чтобы контроллер сам выбрал, какое представление отображать.
И данные поступают напрямую в View. Как это можно сделать, вообще как модель может отправлять данные во представление?
Очень просто.
Если контроллер и модель находятся на серверной стороне, а шаблоны представления — на стороне сервера.
Так работают фреймворки Ruby on Rails, ASP.NET, Django, в общем, везде, где вы пишете серверную шаблонизацию, и собранный HTML отправляется клиенту, а данные тоже отправляются обратно, скорее всего, это этот подход. Какие у нас здесь проблемы? Вы не можете создать такую вещь в одностраничном приложении.
У нас постоянно данные приходят на сервер, уходят с сервера, а страница перезагружается.
Во-вторых, вообще не понятно, куда девать валидацию на стороне клиента, и вообще клиентский JavaScript, AJAX и все такое? Потому что, если мы хотим чего-то быстрого, нам некуда идти.
Такой подход просто не работает или работает не лучшим образом.
Последняя строчка вот такая интересная история, кажется, из 2008 года.
Вопрос был: где хранить бизнес-логику — на модели или в контроллере? Были и такие, кто говорил: «Мы храним бизнес-логику в контроллере, потому что это удобно, в модель сразу отправляются чистые данные.
Контроллер сам проверит, перепроверит, если что-нибудь произойдет, и отправит ошибку».
Были те, кто говорил, что «В результате получаются толстые, тупые и уродливые контроллеры».
Они действительно оказались огромными.
И сказали, что бизнес-логика должна быть в модели, а контроллер должен быть тонким, легким, передавать данные, а модель сама их обрабатывать.
И то в первой версии мода Теги: #frontend #interfaces #Промышленное программирование #flux #Perfect code #mvp #frontend архитектура #контроллер представления модели #mvvm
-
Важность Восстановления Данных На Диске
19 Oct, 24 -
Cms На Базе Codeigniter – Текущая Ситуация
19 Oct, 24 -
Радиостанция Groove Salad.
19 Oct, 24 -
Постарайся
19 Oct, 24