Pull to refresh

Comments 84

Простите, а что вы понимаете под SOA? Какое определение SOA вы используете?

Но это широкий случай. В простых проектах блоки могут собираться в 1 класс или метод.
A service-oriented architecture (SOA) is an architectural pattern in computer software design in which application components provide services to other components via a communications protocol, typically over a network

Вы уверены, что ваша модель соответствует этому определению?

В простом случае сервис = обычный метод класса.
Когда программа растет куда-то нужно цеплять сложные системы и тогда в программе появляются сервисы.
И вместо простого метода получения из базы массива, появляется коммуникаторы по некоторым протоколам с внутренними сервисами или внешними. Смысл в том, что в контроллере это выглядет как подключение класса и запуск его метода подобно использованию модели в классической MVC структуре.

Эмм, а вы осознаете, что SOA — это не архитектура уровня "внутри приложения"?

Да, в теории SOA касается в основном вынесением функциональности на внешние ресурсы. Но например PHP-код и MySQL внутри 1 сервера являются разными системами и общаются на языке SQL между собой.

Тут имеется ввиду не прямое сходство с SOA, а его принципы.

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

Если использовать русское определение: Се́рвис-ориенти́рованная архитекту́ра (SOA, англ. service-oriented architecture) — модульный подход к разработке программного обеспечения, основанный на использовании распределённых, слабо связанных (англ. loose coupling) заменяемых компонентов, оснащённых стандартизированными интерфейсами для взаимодействия по стандартизированным протоколам.

То имеется в виду модульность и слабо связность на начальных стадиях, протоколы внутри дальше и вынесением в отдельные программы в будущем.

… которой (статье) вы не соответствуете.

имхо, вы путаете сервисную архитектуру приложения с сервисным слоем приложения.
Да, в теории SOA касается в основном вынесением функциональности на внешние ресурсы.

Нет, в теории — и на практике — SOA касается исключительно распределенных систем.


Но например PHP-код и MySQL внутри 1 сервера являются разными системами и общаются на языке SQL между собой.

Вот только это не SOA.


Тут имеется ввиду не прямое сходство с SOA, а его принципы.

Какие именно принципы?


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

То есть вы внутри программы сразу пишете так, как если бы у вас каждое обращение было удаленным? В чем это выражается?


Если использовать русское определение

Откуда вы взяли это определение?


Вот вам одна короткая цитата из Service-Oriented Architecture: Concepts, Technology, and Design: "Contemporary SOA is intrinsically reliant on Web services"


Многое изменилось за десять лет с выхода этой книги (включая, собственно, пересмотр ценности SOA и смещение в сторону микросервисов), но одно осталось неизменным: SOA — это распределенная архитектура. Монолитное приложение не может быть SOA.


То имеется в виду модульность и слабо связность на начальных стадиях

Чем, по-вашему, SOA-система отличается от любого другого хорошего ПО (напомню, что модульность и слабосвязность — это критерии любой хорошей архитектуры, не только SOA)?


протоколы внутри дальше

Что за протоколы внутри?

UFO just landed and posted this here
Да, прикольно описано.

«Что немаловажно — мы в любой момент можем заменить любую модель. К примеру, без особых проблем поставить более мощный генератор. Это — важно. Модели в MVC в идеале должны быть как запчасти автомобиля — иметь лишь интерфейс, своего рода API, что бы внедрение новой модели происходило максимально безболезненно для вашего кода.»

так и не понял о чем статья. Что MVC — круто? Для десктопа — возможно для него он и придуман.
Но если речь вебе то в этом большие сомнения. Для веба более естественен компонентный подход. Да и SOA (еще одна модная фишка) тут непонятно каким боком.
Впрочем это я чтобы взять огонь на себя — тут есть штатные коментаторы которым никогда ничего не нравится.

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


типичная ошибка. Контроллер передает данные модели когда данные приходят как часть команды (нажали на форме кнопку Сохранить отправили данные для апдейта).
Но если надо что то показать — контроллер должен дать команду представлению -что нужно показывать. А представление идет к модели и вытаскивает нужные данные. Потому как только представление «знает» какие данные нужны.
к примеру, контроллер говорит — покажи профиль Васи Пупкина. Представление идет к модели вытаскивает профиль -может весь профиль а может только часть — это уже зависит от того что и в каком виде надо представить, что очевидно не забота контроллера.

Что MVC — круто? Для десктопа — возможно для него он и придуман.
Но если речь вебе то в этом большие сомнения. Для веба более естественен компонентный подход.

Вот тут совершенно не соглашусь. Как раз для веба наиболее уместен MVC, т.к. зачастую приходится отдавать различные варианты представления, а уж что говорить про необходимость распределенной архитектуры?
Как раз для десктопа более уместен компонентный подход (скажем, как Swing, JavaFX и пр.)
MVC был придуман именно для десктопа. В VS5 даже шаблон был такой для приложений. Только моель там называлась archive. Классическая реализация — прилоджения типа Ворд. Документ — модель, верхнее меню контроллер, а отображение doc файла — это представление.
зачастую приходится отдавать различные варианты представления, а уж что говорить про необходимость распределенной архитектуры

в упор не вижу как их этого вытекает необходимость MVC. Представление никто не отдает — оно рендерит данные для пользователя и варианты это — логика работы представления (веб страницы в данном случае)
При чем тут распределенная архитектура — ума не приложу.
В вебе пользователь видит представление, и работает он с представлением, поэтому логичнее именно компонентная архитектура.
То есть на действия пользователя реагируют именно компоненты страницы и они же рендерятся в зависимости от того что делает на странице пользователь. Контроллер здесь — разве что адресная строка браузера.
И ктстати упомянутое вами ниже HMVC. Если MVC — логичная и самодостаточна архитектура — зачем нужны костыли в виде иерархических MVC? или всяких там контроллер --модель-представление?
На десктопе например, ничего такого не нужно, потому как MVC там к месту и не надо ничего изобретать.
Просто Sun в свое время запихнула MVC в свою реализацию веба на яве.
Zend и иже с ними тупо собезьянничали.
И майки туда же — был отличный компонентный Forms, надо было просто убрать визуальный редактор и дать возможность нормально работать с версткой и стилями. Дак нет перешли не MVC и теперь кроме прочего гемора нужно еще и заботится о персистентности элементов страницы о котором Forms заботился сам — програмер занимался реализацией бизнес логики а не возился в Razor с мешаниной HTML и кода шаблонизатора.

.

MVC был придуман именно для десктопа.

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

Необходимости нет, но это наиболее логичная организация приложения особенно для web, где нужно отдавать и html, и json, и xml, и мобильную разметку, ну и т.д. Десктоп-приложения чаще всего взаимодействуют с пользователем посредством однообразного интерфейса, т.к. там кроссплатформенности изначально не было.
При чем тут распределенная архитектура — ума не приложу.

Дело в том, что web — не изолирован (для десктопов не обязательно даже подключение к Интернету), и чаще приходится взаимодействовать с внешними системами, а потому, скажем, как раз упомянутая SOA очень даже к месту.
В вебе пользователь видит представление, и работает он с представлением, поэтому логичнее именно компонентная архитектура.

То, что видит пользователь в вебе — обычно большой динамический html, в котором о компонентах говорить не приходилось — лишь базовые контролы, предоставляемые браузером — здесь базовой единицей долгое время являлась именно страница, связанная с другими ссылками. Напротив, в десктоп-разработке мы в любом окружении, будь то С++ с Qt, .NET или Java, получаем внушительную стандартную библиотеку разнообразных компонентов, которые могут быть вложены друг в друга и при этом взаимодействовать, и тут понятия «страницы» практически нет — мы просто заменяем один компонент на другой, для достижения смены условно говоря «страниц» или «экранов».
Контроллер здесь — разве что адресная строка браузера.

Извините, Вы это сейчас серьезно? Вы правда не понимаете, что ВСЕ, что видит и с чем непосредственно взаимодействует пользователь — это представление? Что то, что инкапсулирует данные и ими управляет — модель, а то, что направляет и обеспечивает их взаимодействие — контроллер?
Если MVC — логичная и самодостаточна архитектура — зачем нужны костыли в виде иерархических MVC? или всяких там контроллер --модель-представление?

Просто потому, что HMVC, MVP, MVVM ничуть не менее логичны и самодостаточны, и вся разница между ними — какие функции берет на себя каждый из слоев и кто с кем связан непосредственно. MVC более популярен вследствие того, что он более прост и логичен, хотя и не везде годится — иногда оказываются уместными другие архитектурные шаблоны. Но тем не менее — каждый из них способен достичь того же результата.
На десктопе например, ничего такого не нужно, потому как MVC там к месту и не надо ничего изобретать.

а дураки из Майрософт совершенно излишне впихнули MVVM в свой WPF, так что ли?
Просто Sun в свое время запихнула MVC в свою реализацию веба на яве.

Простите, реализацию… веба??
Ну и Java все-таки не была создана для web изначально, она была создана для кроссплатформенности. В отличие от того же HTML, XML и даже JavaScript.
И да, взять тот же Swing. Он компонентный, и не для web. Однако, компоненты тоже реализованы в соответствии с MVC.
Zend и иже с ними тупо собезьянничали.

Как и многие другие разработчики, использующие MVC, и тем самым упростили себе жизнь.

Вы, кажется, совсем не понимаете, что такое MVC и что такое компоненты.
где нужно отдавать и html, и json, и xml, и мобильную разметку, ну и т.д.

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

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

Ну сейчас то какие проблемы с этим?
и тут понятия «страницы» практически нет — мы просто заменяем один компонент на другой, для достижения смены условно говоря «страниц» или «экранов».

это понятие условное. Можно назвать страницей, можно назвать формой, можно назвать экраном как в веьбе так и в десктопе.

а то, что направляет и обеспечивает их взаимодействие — контроллер?
задача контроллера реагировать на действия пользователя а не оьеспечивать взаиможействие представления и модели.
Просто потому, что HMVC, MVP, MVVM ничуть не менее логичны и самодостаточны,

а меня здесь в который раз убеждают что MVC — наше все. И то что не MVC вообще не веб.
а дураки из Майрософт совершенно излишне впихнули MVVM в свой WPF, так что ли?

найдите ту пару линуксоидов -они вам обьяснять что все что пишет майкрософт написано дураками.
Простите, реализацию… веба??

да, вы наверно недавно в IT.
В отличие от того же HTML, XML и даже JavaScript.
к какой платформе привязаны перечислены штуки?
Он компонентный, и не для web. Однако, компоненты тоже реализованы в соответствии с MVC.

я бы не был так категоричен.
Как и многие другие разработчики, использующие MVC, и тем самым упростили себе жизнь.

нет, это те разработчики которые пришли в веб и увидели что веб и MVC это одно и тоже. Им просто не с чем сравнивать.
И не просто усложнили а продолжают усложнять. Например решая проблеммы связаные с MVC (в частности отсутствие персистентности элементов страницы) переносят логику на клиента (ангуляры и иже с ними) продолжая усложнять себе жизнь. разумеется те кто приходит в IT сейчас будут думать что это единственно правильная реализация веба.

На соамом деле все просто — в связи с ростом объема ПО разработики, котрые хотят за единицу времени сделать больший обьем, ищут волшебную таблетку. Для кого то это MVC, для когото клиентские фреймворки, кто по потащил ява скрипт на серверную часть. И это на одной той же платформе которая по сути не изменилась за последние 20 лет со времен CGI.
Вы, кажется, совсем не понимаете, что такое MVC и что такое компоненты.

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

не вижу как формат передачи данных связан с необхоимостью MVC

Никак, просто при использовании MVC легче отдавать различные форматы — используя различные представления.
во первых была, во вторых опять же не вижу связи между кросплатформенностью, интерфейсом и MVC.

Ну да, и программы не нужно было пересобирать под конкретные платформы.
Я говорил про то, что компонентная архитектура более естественна для десктоп-приложений, а для web больше годится MVC и иже с ними.
это понятие условное. Можно назвать страницей, можно назвать формой, можно назвать экраном как в веьбе так и в десктопе.

при появлении одностраничных веб-приложений это понятие действительно стало более условным, но если брать web 1.0, то как раз по одному url отдавалась ровно одна страница html. Что важнее, эти страницы никак между собой не связаны, тогда как в десктопном интерфейсе для организации экранов достаточно заменить один компонент другим, остальные остаются точно в таком же состоянии.
задача контроллера реагировать на действия пользователя а не оьеспечивать взаиможействие представления и модели.

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

Не только MVC, но и MVP, MVVM, опять же HMVC — на любой вкус. И каждый из шаблонов может быть использован как в вебе, так и на десктопе.
да, вы наверно недавно в IT.

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

Ни к какой, но это то, из чего состоит web, как 15 лет назад, так и сейчас.
я бы не был так категоричен.

Если Вы внимательно посмотрите устройство Swing, то в каждом компоненте, будь то окно или кнопка, отыщите и контроллер, и модель, и представление.
Например решая проблеммы связаные с MVC (в частности отсутствие персистентности элементов страницы) переносят логику на клиента

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

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

слишком безапеляционное заявление

У меня сложилось такое впечатление, когда Вы говорите, что MVC — это только для десктоп-приложений, а для web годится компонентная структура. Между тем я хочу донести, что как раз наоборот.
контроллер должен дать команду представлению

Теперь у вас появилась абстракция "команда", которой нет в MVC.


Ну и да, каждый раз, когда обсуждается MVC (и в посте та же ошибка допущена), не указано, о каком именно MVC идет речь. А это, в числе прочего, влияет на порядок вызовов.


к примеру, контроллер говорит — покажи профиль Васи Пупкина.

Как именно это выраженно в коде?


Представление идет к модели вытаскивает профиль

Как именно это выраженно в коде?

что то я вас не совсем понимаю. обращаемся к профилю Васи Пупкина: метод view_user($id) класса Social контроллер обращается к модели делая выборку данных и контроллер передает данные отображению. в hmvc если мне необходимо сделать более сложные рассчеты и подключиться скажем к сторонней или своей библиотеки я из контроллера обращаюсь к библиотеки из библиотеки к модели (чисто за выборкой из базы) и возвращенные библиотекой данные передаю отображению. я пользуюсь такой логикой. я в чем то не прав? у вас какое то обратное видение или я не правильно понял?
ну подумайте сами зачем нужен посредник в виде контроллера чтобы передать данные от модели к представлению. И как контроллер знает какие данные и в каком виде надо передать. Как контроллер знает какая в данном представлении логика страницы. В контроллере не должно быть ни логики страницы ни бизнес-логики.
Теоретически, контроллер должен реагировать на внешние действия. Так он и задуман в классической модели.
hmvc — придуман потому что в обычном MVC нельзя сделать более менее сложную страницу где контент собирается из нескольких представлений.
Вообще если посмотрите на классическую схему MVC? в той же википедии к примеру. там двунаправленные стрелки между всеми составляющими. Нет никаких ни логических, ни технологических, ни архитектурных препятствий тому чтобы например модель инициировала перерисовку представления. Представьте хранилище данных которое обновляется из стороннего источника и представление которое отображает данные в реальном времени. модель как только обновились данные отсылает представлению сигнал что есть новые данные (или просто отсылает данные представлению).

Простите, а где же здесь расширенная MVC архитектура? Вы общими словами описали MVC, дали пару советов и некстати объединили модель и SOA.
Лично я ожидал прочитать о каком-то «варианте» MVC, например, прочитать упоминание о HMVC, узнать что-то новое — но нет…
Кстати да, HMVC тут более подходит чем SOA. Почему то многие этот термин понимают исключительно как архитектура для больших проектов где явно видно разделение сервисов в отдельные приложения.

Тогда изменю немного текст и получится, что модели могут состоять из MVC связки. И тогда мы подключаем к контроллеру, как модель контроллер 2 уровня MVC. Который собирает в себе уже модели 2 уровня и View.
Тогда изменю немного текст и получится, что модели могут состоять из MVC связки.

Не могут. В HMVC иерархия образована между контроллерами.


Более того, даже если отвлечься от HMVC, модель не может быть MVC, потому что модель (если мы говорим про модель в понимании оригинального MVC) — это бизнес, в то время как MVC — это уровень представления (в значении Presentation).

Ок, тогда HMVC будем подключать тоже отдельно, как библиотеки, так лучше?

Лучше для чего? Я не понимаю, как архитектурный паттерн можно "подключить отдельно".

Лучше, что бы не противоречить теории)

Так как на практике можно называть что угодно как угодно, главное что бы сделано было в сроки и потом другие программисты могли работать с кодом.

А то много теоретиков на практике 5 дней делают то, что делается за 1. Зато на мега навороченных технологиях и согласно теории.

Лучше, что бы не противоречить теории

Какой теории?


Так как на практике можно называть что угодно как угодно, главное что бы сделано было в сроки и потом другие программисты могли работать с кодом.

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

Какой теории?


Как минимум той, которой вы оперируете.

Когда вы искажаете шаблон (не берете другой, а именно искажаете существующий) — вы усложняете работу тех, кто придет работать с кодом потом.


Не искажаем, а дополняем. Так как архитектура — это совокупность шаблонов.

Есть проблема — надо ее решить. Описать структуру Веб-приложения которая на практике НЕ ограничивается MVC паттерном. Я часто работаю с Веб-кодом разных людей и по итогу туда тулят Фабрики, Адаптеры и куча шаблонов которые только усложняют все и страдает бизнес, так как амбиции умников стоят немалых денег потом.

Как минимум той, которой вы оперируете.

В рамках теории, которой я оперирую, архитектурный паттерн нельзя подключить как библиотеку.


Не искажаем, а дополняем.

Ну вот конкретно вы — по крайней мере, в том, что вы пишете в этом посте и комментариях — именно искажаете.


Есть проблема — надо ее решить

Какая проблема?


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

Неуместное применение любого шаблона приводит к проблемам, это, в общем-то, очевидный факт. И что? Это как-то делает паттерн "фабрика" или паттерн "адаптер" хуже?


Ну и да, MVC и фабрика/адаптер — это паттерны принципиально разного уровня, совершенно не вижу смысла упоминать их в одном рассуждении на равных.

Ок, тогда допишу критерии качества кода.

Один из критериев — это кол-во абстрактных объектов которые НЕ относятся к бизнес-логике.

Чем меньше кол-во объектов используется что-бы решить ту или иную задачу тем код проще.

Именно на этом критерии и строится попытка создать описание структуры веб-приложения.
Чем меньше кол-во объектов используется что-бы решить ту или иную задачу тем код проще.

Это, конечно, правда. Но "проще" — не означает автоматически "поддерживаемее". Статический вызов с прямым связыванием проще, чем инверсия зависимостей, но второе — поддерживаемее (я говорю про большинство сценариев, а не про все).


Но, что забавно, вы ратуете за уменьшение количества объектов, но при этом упоминаете SOA, где количество дополнительных абстракций как раз очень велико.


Именно на этом критерии и строится попытка создать описание структуры веб-приложения.

Структура веб-приложения — это архитектурный паттерн. На этом уровне вас не волнуют фабрики и адаптеры.

Давайте возьмем для примера ваш код: https://github.com/srogovtsev/appveyor-website

Вы считаете этот код легким и поддерживаемым?

По какой архитектуре вы программировали сайт?
Давайте возьмем для примера ваш код: https://github.com/srogovtsev/appveyor-website

Вы это, простите, серьезно сейчас?


Во-первых, это не мой код. Я его не "программировал".


Во-вторых, это сайт, это не приложение. У него нет "архитектуры", архитектура может быть у нижележащей CMS (кажется, там Jekyll).

Да, можем рассмотреть Jekyll как пример

Как пример чего? Впрочем, рассмотрите, я с интересом послушаю — я в его код ни разу не заглядывал.

Кстати, а почему веб-сайт — это НЕ приложение? [ Веб-приложение Wiki ]

Сразу видно, что кол-во не бизнес объектов зашкаливает в отличии от php решений например. Но это C# поетому часть кода нужна в принципе для работы веб-сайта в среде сервера.

Поетому можно дописать еще + Server Environment needs

Допустим как в любой CMS нам нужно ее расширить. Например сделать отдельную страницу /list/ в которую вывести из БД например таблицу товаров.

Вопрос: сколько надо сделать действий в NJekyll этом, что бы такую простое дело реализовать?

Например у нас будет так:

1) Создать контроллер list с index методом (Роутинг определяет метод контроллера для запуска)
2) Создать класс модели с методом SQL запроса или наследовать стандартный, там есть уже получение всей таблицы метод
3) Подключить класс в контроллер и положить в переменную массив
4) Создать View с циклом
5) Подключить VIew к контроллеру + прописать заголовок title странице желательно

5 действий — 5-15 минут времени.

А сколько шагов надо сделать на NJekyll ??
Кстати, а почему веб-сайт — это НЕ приложение?

Этот конкретный — не приложение, потому что у него нет, собственно, логики. Это статическая информация.


Сразу видно, что кол-во не бизнес объектов зашкаливает

Сразу видно? Приведите конкретные примеры.


Но это C# поетому часть кода нужна в принципе для работы веб-сайта в среде сервера.

Это вы о чем, например?


Вопрос: сколько надо сделать действий в NJekyll этом, что бы такую простое дело реализовать?

Нисколько, потому что Jekyll для этого не предназначен. Это статический сайт.

Казалось, что это только часть кода, а html-ки генерируются из БД где-то.

Ок, слишком простая программа для вопроса архитектуры.

Для пример если взять WordPress CMS или Java Spring MVC из коробки, то за 5 действий точно не уложится.

Иногда до 5 часов занимает такая простая 5 минутная задача на некоторых системах, которые НЕ допилены до удобной и расширяемой архитектуры.

Суть вопроса в том, что мало слова MVC, надо детализировать дальше, что бы потом за минимум шагов делать максимум функционала и одно другому не мешало.

Есть у вас какой-то пример кода Веб-сайта для рассмотрения еще?
Суть вопроса в том, что мало слова MVC, надо детализировать дальше,

Ну вот у вас в статье и нет никакой детализации.


Есть у вас какой-то пример кода Веб-сайта для рассмотрения еще?

У меня — нет. Зачем мне?

Например сделать отдельную страницу /list/ в которую вывести из БД например таблицу товаров.

Ну и так, для информации — если взять какой-нибудь банальный asp.net MVC, то решение этой задачи сведется к приблизительно тем же шагам, что и у вас: объявили бизнес-сущность, объявили контроллер/экшн, получили сущность из DAL, передали во view, во view нарисовали. Пока задача тривиальна, код тоже тривиален.

asp.net MVC — хороший пример.

Но там не совсем так быстро все происходит.

А есть пример кода на нем?
Но там не совсем так быстро все происходит.

Почему это?


А есть пример кода на нем?

Лично у меня в паблике нет. Но описанная вами задача есть в любом туториале и сводится к определению двух классов и одного представления (при условии, что само приложение уже существует и в нем построена нужная инфраструктура).

Да, необходима «нужная инфраструктура»

А как ее строить? По каким правилам и шаблонам?

Одного MVC НЕ достаточно. Поетому и цель найти какой-то удобный и оптимальный шаблон.
А как ее строить? По каким правилам и шаблонам?

Ну, люди об этом книги пишут.


Одного MVC НЕ достаточно.

Конечно, недостаточно. MVC — это шаблон презентационного слоя, он говорит, как декомпоновать презентационную логику от бизнес-логики. Как вы будете обращаться с бизнес-логикой — ваше дело.


Поетому и цель найти какой-то удобный и оптимальный шаблон.

Какие вы уже пробовали?

Пробовали разные Frameworks: PHP CodeIgniter, PHP Zend, PHP Yii, PHP Kohana, PHP Symphony, WordPress CMS, На Java пробовали Java Spring MVC, ASP.NET MVC рассматривали и при работе с Android SDK и Objective-C не нашли готовых решений для построения этой самой «нужной инфраструктуры»

По итогу пришли вот к тому, что написано выше. На счет SOA я уже понял, что многие его понимают буквально. Поетому уже изменил текст и детализировал как разновидности объектов подключаемые к контроллеру.
Пробовали разные Frameworks

Вы пробовали фреймворки. А я говорю об архитектурных шаблонах приложения.


ASP.NET MVC рассматривали и при работе с Android SDK и Objective-C не нашли готовых решений

Простите, а какая связь между asp.net MVC и Android SDK?


По итогу пришли вот к тому, что написано выше

То есть опять к MVC — то есть опять не вышли за пределы слоя представления. Нет, это никак не решает озвученную вами задачу.


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

Что такое "объекты, подключаемые к контроллеру"?

Простите, а какая связь между asp.net MVC и Android SDK?


Что бы понять связь, нужно написать программу на том и на том.

Связь в том, что и там и там нужно дописывать ту самую «нужную инфраструктуру» что бы простые задачи решались в 5 шагов за 5 минут.

Android и iOS приложения имеют ту же проблематику и там она еще более ощутима. Там тоже необходимо строить нечто подобное для удобства разработки.

Нет, это никак не решает озвученную вами задачу.


Оно уже решает задачу. К примеру мы делали проект Moow.life: http://moow.life/ и вот Android приложение: https://play.google.com/store/apps/details?id=com.moow

Мы смогли сделать быстрее и дешевле, чем многие другие разработчики нам предлагали. Так как мы изначально построили систему так как описано выше.

А некоторые наши клиенты отказались и заказали в другом месте некоторые сайты, после чего вернулись с «говноархитектурой» которую больше никто не хочет править и надо переписывать весь Back-End.

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

«объекты, подключаемые к контроллеру»


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

Связь в том, что и там и там нужно дописывать ту самую «нужную инфраструктуру» что бы простые задачи решались в 5 шагов за 5 минут.

А, окей, то есть никакой.


Так как мы изначально построили систему так как описано выше.

Но выше описан обычный MVC — хотя вы же говорите, что MVC недостаточно. Где-то противоречие.


Как переубедить тех, кто усложняет код

Зачем вам их переубеждать? Но вообще, логика в таких случаях очень простая: берем интересующие нас метрики (обычно это стоимость внесения изменения) и меряем.


Объект — это экземпляр класса. И они бывают разные по сущности. Это может быть

У вас мешанина.


библиотека, или класс для управления сервисом или адаптер какой-то.

Библиотека — это не объект, библиотека — это библиотека (и они не подключаются к контроллеру)


другой контроллер при HMVC

Тогда почему у вас HMVC написан там, где модель, а не там, где контроллер?


класс для управления сервисом

Что такое "класс для управления сервисом"? Зачем "подключать" его к контроллеру?


А еще у вас в посте там же, где контроллеры, упомянуто:


Routing

… хотя при хорошей декомпозиции в контроллере роутинга нет, он находится за его пределами и обеспечен инфраструктурой


business logic

… хотя в MVC противопоказано включать бизнес-логику в контроллеры, она сосредоточена в модели (в классическом MVC) или бизнес-слое (в Model 2). Контроллеры могут содержать только презентационную логику.


Server Environment needs

… хотя это задача инфраструктуры.

Библиотека — это не объект, библиотека — это библиотека (и они не подключаются к контроллеру)


Не соглашусь! Пример как это работает в CodeIgniter:

http://www.codeigniter.com/user_guide/libraries/loader.html

$this->load->library('calendar', NULL, 'my_calendar');
// Calendar class is now accessed using:
$this->my_calendar


MVC противопоказано включать бизнес-логику в контроллеры


Баталии на эту тему проходили тут: https://toster.ru/q/2419

И это реально проблема! Сборка ответа на запрос пользователя из частей — это уже бизнес-логика так как сами части есть предметной областью чаще всего.

Поетому все таки в контроллере будет бизнес-логика 1 уровня, а уже в моделях 2-го и далее.

Ок, тогда вынесем в отдельный элемент архитектуры Core components как вариант. (Еще редактирую)
Не соглашусь! Пример как это работает в CodeIgniter:

Пламенный привет кодеигнайтеру с его нарушением SRP.


И это реально проблема!

Да нет никакой проблемы, если вы знаете об отличиях классического MVC от Model 2.


Сборка ответа на запрос пользователя из частей — это уже бизнес-логика так как сами части есть предметной областью чаще всего.

Нет, это логика приложения (application). Бизнес не оперирует понятиями "запрос и ответ пользователя".


Ок, тогда вынесем в отдельный элемент архитектуры Core components как вариант.

… и в этот момент то, что вы описываете, перестанет быть MVC.


Но вообще, конечно, занятно: у вас уже есть готовое решение, но вы не знаете его декомпозиции на компоненты. И вы говорите об архитектуре?

CodeIgniter был приобретен Канадский институтом http://www.bcit.ca/ Я думаю там не дураки собрались.)

У людей проблемы с понятиями. Когда слишком много информации, то многие путают их.

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

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

Есть пример кода чистой MVC у вас?
CodeIgniter был приобретен Канадский институтом http://www.bcit.ca/ Я думаю там не дураки собрались

Ничего не знаю про этот институт, но могу заметить, что факт приобретения не означает согласия со всеми решениями, принятыми в продукте.


У людей проблемы с понятиями. Когда слишком много информации, то многие путают их.

Для решения этой проблемы служат книги и обзорные статьи. В частности, про группу шаблонов separated presentation (к которой относится MVC) хорошо написано у Фаулера.


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

… например?


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

Зависит от природы обработки входной информации. Например, валидация типов — это не бизнес-процесс, но валидация диапазонов — бизнес-процесс. И вот второго в контроллере быть не должно (впрочем, первого тоже лучше избежать, это cross-cutting concern).


Есть пример кода чистой MVC у вас?

Что вы понимаете под "чистой MVC"? Приложение, реализованное в этом шаблоне? Фреймворк под этот шаблон? Какой MVC вас интересует — оригинальный, или Model 2?

… и нет, добавленные вами "Core Components" не имеют никакого отношения к шаблону MVC.


А как понимать вот эту фразу: "M (Controller can connects with different objects)" — я и вовсе не понимаю.


Кстати, спешу напомнить вам, что Хабрахабр — русскоязычный сайт.

… и нет, добавленные вами «Core Components» не имеют никакого отношения к шаблону MVC.


Тема статьи: Расширенная MVC архитектура

Если мы например добавляем перед запуском контроллера роутер как отдельный класс/объект + напаковуем в абстрактный класс контроллера кучу возможностей, в том числе в контроллере уже может быть например данные о пользователе из Базы данных. То это уже не MVC, а что-то новое на основе MVC

Кроме того, контроллер например может содержать такой код:

if ($_GET['stop_mirror_server']) {
   $this->load->library('server_control');
   $this->server_control->stop();
   $this->load->model('mailer');
   $this->mailer->send_stop_server_noty();
}


server_control может быть вообще адаптером который через командную строку потом вызовет shell который остановит сервер.
А то что надо сразу письмо отправить — это уже бизнес логика.

Суть статьи — предложить расширенное определение MVС для веб приложений.

Просто MVC мало. А «нужная инфраструктура» у каждого своя и часто перегружена и не оптимальна.
То это уже не MVC, а что-то новое на основе MVC

Ну да, это какой-то очередной фреймворк, имя которым легион. Не архитектура, а именно фреймворк.


Кроме того, контроллер например может содержать такой код:

if ($_GET['stop_mirror_server']) {
$this->load->library('server_control');
$this->server_control->stop();
$this->load->model('mailer');
$this->mailer->send_stop_server_noty();
}

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


Суть статьи — предложить расширенное определение MVС для веб приложений.


А чем "MVC для веб-приложений" отличается от "просто MVC"? (кстати, я продолжаю вас спрашивать, вы говорите о классическом MVC или Model 2?)


А «нужная инфраструктура» у каждого своя

Это неправда. Инфраструктура, нужная для реализации шаблона MVC, обычно уже определена фреймворком. Вы хотите пообсуждать фреймворки?


Или вы говорите об инфраструктуре, нужной для организации приложения в целом? Ну окей, давайте поговорим, только при чем тут вообще MVC?

Кстати сама идея переноса бизнес-логики в контроллер более удобная для веб-сайтов. Так как с ростом технологии AJAX очень много простых запросов к системе и проще отдавать результат сразу прям в контроллере, что бы не усложнять систему.

И так складывается, что практика противоречит теории.
Кстати сама идея переноса бизнес-логики в контроллер более удобная для веб-сайтов.

Ага, ужасно удобная. Вот у вас есть веб-сайт и, внезапно, API к нему (для мобильного приложения). И оба должны реализовывать одну и ту же функцию. Вы будете заставлять сайт и API использовать один контроллер?


И так складывается, что практика противоречит теории.

Не противоречит. Теория как раз проста и понятна: чем проще ваша система, тем больше вы можете позволять себе нарушать SRP — потому что общая стоимость поддержки невелика. Но по мере усложнения системы правильный дизайн становится все критичнее — именно потому, что его проще поддерживать.

Вот у вас есть веб-сайт и, внезапно, API к нему (для мобильного приложения). И оба должны реализовывать одну и ту же функцию.

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

Кстати например Like используется одна во всех 3 случаях.

AJAX и API работают одинаково и Cron может GET запросом например давать данные.

Но в нашем случае выносить логику на 2 уровень имеет смысл лишь когда нужно, а не всегда. Тоесть это расширение возможностей для упрощения в большом кол-ве ситуаций.
Кстати например Like используется одна во всех 3 случаях.

Like? Вы про LIKE '%abc%'? Извините, я бизнес-функции имел в виду.


AJAX и API работают одинаково

Могут работать одинаково, но это накладывает ограничения на дизайн — что неудобно.


Cron может GET запросом например давать данные.

Угу, межпроцессное взаимодействие, как это мило, удобно и производительно.


Но предположим даже вы так сделали, и у вас есть один HTTP API, к которому вы ходите за этой функцией изо всех. Знаете, что получилось? Теперь у вас нет MVC (на этом уровне), и, как следствие, нет контроллера (в терминах MVC).


Но в нашем случае выносить логику на 2 уровень имеет смысл лишь когда нужно, а не всегда.

То есть теперь программист не знает, какая логика на каком "уровне" живет.

Like — всмысле «мне нравится» например у поста в ленте ))

ограничения на дизайн


У нас не встречалось этой проблемы

В общем основная цель — это простота.

Если вы считаете, что то что написано бесполезно — Ок!

Возможно в вашей ситуации это не нужно. Вы уже достаточно минусов поставили не так ли?

Вот только судя по просмотрам, остальным в принципе пофиг)

А значит тема не особо актуальна.
Like — всмысле «мне нравится» например у поста в ленте

И что, вы во всех случаях используете одну и ту же MVC-триаду?


А значит тема не особо актуальна.

Неактуален пост, который очередной раз повторяет (местами с ошибками) уже написанное, не добавляя ничего нового и полезного.

общая стоимость поддержки невелика


Думаю на этой точке можно остановить спор.

В вашем опыте не велика, а в нашем убытки от умников хоронят проекты и приносят огромные убытки по итогу.

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

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


думаю нет смысла обсуждать сложные детали вопроса построения приложения на базе MVC паттерна

Ну да, с простыми бы сначала разобраться...

Не вижу смысла обсуждать так как возможно вы бы НЕ сделали то, что делаем мы с той же скоростью и ценой, а было бы дольше и дороже в разы.

И как я понимаю вы специалист НЕ по Web-приложениям и скорее всего работаете с кучей сложного кода, где скорее всего проблема работы с MVC не присутствует.

Есть пример кода с хорошей архитектурой по вашему мнению? Киньте ссылку.

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

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


И как я понимаю вы специалист НЕ по Web-приложениям

Вы понимаете неправильно.


скорее всего работаете с кучей сложного кода, где скорее всего проблема работы с MVC не присутствует.

Да, я работаю с кучей сложного кода. В том числе в свое время я работал (лет пять) с приложением, где UI был сделан на MVC, и успел там съесть всех типовых проблем.


Есть пример кода с хорошей архитектурой по вашему мнению? Киньте ссылку.

Ну например Autofac. Еще мне нравится архитектура asp.net WebAPI и OWIN, но я не уверен, что понимаю, где и в каком состоянии от них выложены исходники.

.NET компоненты и веб-сервисы — это разные миры.

Ок, негатива я наслушался, но по итогу никакого конструктивного совета не было.

Будем считать этот пост негативным)
.NET компоненты и веб-сервисы — это разные миры.

Критерии хорошей архитектуры одинаковы.

Если вы пишите в контроллере что-то вроде return json_encode($model) вместо return $view->render($model) в зависимости от какого-то условия, то вы:

1. Меняете используемое представления по этому условию (самописный или предоставленный фреймворком view и глобальную функцию)

2. Никак не касаетесь бизнес-логики — это обычная обязанность контроллера, выбрать какое представление отобразить, к бизнес-логике никакого отношения не имеет.

Вообще вы правильно понимаете, что такое бизнес-логика? Вы понимаете, что она не зависит ни от приложения, ни от фреймворков, ни от языка, ни от протокола связи клиента и сервера, ни даже от наличия интернета и собственно компьютеров сервера и клиента? Бизнес-логика оперирует бизнес-сценариями и бизнес-процессами с использованием бизнес-терминов типа: «потенциальный или постоянный клиент просматривает каталог товаров, сообщает менеджеру по обработке заявок(это роль, а не человек) какие товары и в каком количестве он хочет приобрести, также сообщает другие данные, необходимые для оформления заказа (фио, адрес доставки и т. п.) непосредственно или сообщая свой идентификатор постоянного клиента, менеджер проверяет корректность данных, наличие товаров в каталоге, наличие их достаточного количества на складе, оформляет заказ в статусе „ждёт оплаты“ и выдаёт клиенту счёт для оплаты». В описаниях бизнес-процессов обычного бизнеса (не какого-нибудь провайдера) даже не упоминаются «эти ваши интернеты», это бизнес ставит нам, разработчикам (в широком смысле слова), задачу реализовать описанный с помощью бизнес-терминов бизнес-процесс в вебе, предоставляя возможность клиенту инициировать и взаимодействовать с ним (процессом) со своего браузера, путем предоставления пользовательского интерфейса, автоматизации ответственности роли «менеджер по обработке заявок» и обеспечения всей необходимой технической инфраструктуры для этого.

Бизнес описывает нам процесс в своих терминах, а мы уже реализуем с помощью компьютеров, каналов связи, протоколов, каналов связи, парадигм программирования, языков, фреймворков, архитектур и приложений и т. п. бизнес-задачу. Реализация делится (логически, технически это может быть какая-нибудь простыня спагетти) на три основные части — бизнес-логику, описывающую и реализующую бизнес-процессы в бизнес-терминах (её формирование ответственность исключительно бизнеса, мы только реализуем её техничски), пользовательские интерфейсы для инициации и дальнейшего взаимодействия с бизнес-процессами (тут может бизнес-диктовать вид и способы взаимодействия, может команда разработки), и инфраструктурную логику нужную «только» нам, в которую бизнес вникать не может и не хочет. В рамках MVC и подобных архитектур эти три части разделяются технически, на уровне сущностей используемых технологий и потоков данных между ними:

— модель инкапсулирует в себя бизнес-логику, разработчик не вправе вводить новые бизнес-сущности, бизнес-процессы и(или) изменять существующие без прямого указания бизнеса, разработчик лишь переводит задачу с языка бизнеса на язык программирования, его ответственность ограничивается качеством перевода, сами сущности и процессы ответственность исключительно бизнеса.

— представление инкапсулирует в себя пользовательский интерфейс, ответственность за его человеческое описание (тексты, макеты и т. п.) может нести как бизнес (аналогично модели), так и разработчик, в зависимости от договоренностей

— контроллер обеспечивает посредством предоставления необходимой инфраструктуры возможность пользователю через представление взаимодействовать с моделью. Ответственность за него несёт исключительно разработчик. Грубо говоря, контроллер это весь код, который не относится к модели и представлению. Слушать порт, распарсить запрос, отроутить его на конкретный метод или функцию с нужными параметрами, восстановить, если нужно, состояние модели или её части из хранилища или получить из внешних сервисов, проверить права пользователя, выполнить собственно логический запрос пользователя, сохранить, если нужно новое состояние модели или передать его во внешние сервисы, отдать пользователю результат — это всё контроллер в рамках MVC.
Хороший коммент на эту тему. Одна из проблем фреймворков — это его избыточность. Но с другой стороны там довольно много полезных компонентов.

Мы остановились на PHP CodeIgniter, отказались от части его функционала, хорошее оставили и дописали большое кол-во того, что реально нужно.

blog.kpitv.net/article/frameworks-1


Там обижают Yii. Говорят он хороший, но в нем тоже довольно много лишнего и некоторые вещи усложняются без весомых на то причин.
Ага, куча кода для банального CRUD. Да еще и SQL-инъекция, что еще раз доказывает, что экранировать данные вручную нежелательно.

Скрытый текст
http://inside.ikiev.biz/inside/table/users/

$.post('/inside_pdg_ajax/',
    'pdg_table=users&pdg_order=(CASE WHEN (SELECT ASCII(SUBSTRING(password, 1, 1)) FROM users where username = 0x726F6F74) = 0x32 THEN id ELSE email END)&pdg_asc=desc&active=1&pdg_limit=100&pdg_fsearch=&pdg_fkey=&pdg_page=1'
).success(function(data){ $('#inside_terminal').html(data); });


Первые 2 символа поля password пользователя root: 2d

Где SQL инъекция проходит? Какой файл и какая строка? (Код примера 2 летней давности если что)

Цепочка вызовов:
https://github.com/torrison/inside/blob/master/application/controllers/inside_pdg_ajax.php#L29
https://github.com/torrison/inside/blob/master/application/libraries/inside_lib.php#L93
https://github.com/torrison/inside/blob/master/application/models/inside_model.php#L90

Хотя могли бы и сами поискать) А 2 года назад не надо было избегать SQL-инъекций? PDO с параметрами уже давно появился.
Один из вариантов — это рассчитать кол-во элементов системы. Чем меньше элементов тем система проще.

Спорно. Чем меньше элементов, тем они крупнее и запутаннее.

M — модель, живёт в абстрактном вакууме, обычные PHP классы (сущности, объекты-значения, фабрики, бизнес-сервисы и т. п.), инакпсулирующие своё состояние и предоставляющие интерфейс работы с ним (методы получение срезов состояния и методы изменяющие состояние, обычные геттеры и сеттеры вырожденный случай, которого следует избегать). Не знают ничего об остальном приложении, включая подсистему хранения (часто SQL RDBMS), максимум в них из приложения инжектится диспетчер событий, чтобы класс мог сообщить о чём-то важном остальному приложению. Валидируют исполнение бизнес-требований, выбрасывая исключения в случае их нарушений. Использование внешних библиотек (включая стандартную) ограничено функциями, классами и их методами, не взаимодействующими с внешним (для модели) миром, либо абстрагирующими модель от этого взаимодействия. В частности модель может получать данные от внешних источников через инфраструктурные сервисы и даже изменять их, но ничего не должна знать о природе этих источников, в том числе о методах обеспечения персистентности данных в них, оперируя простыми атомарными операциями типа получить объект по идентификатору или коллекцию объектов по условию, добавить элемент в коллекцию и т. п.

V — представление, обеспечивает пользовательский интерфейс, генерируя HTML, XML, JSON и т. п. К нему же относятся (если есть) статические, формируемые командой разработки, файлы типа изображений, CSS, JS и т.д. Знает о модели, а конкретно о методах получения срезов состояния, изменять его не имеет права, даже если имеет техническую возможность. Знает о контроллере как о, прежде всего, наборе возможных роутов (htpp-запросов) и их параметров. Получает из контроллера как параметры по возможности все необходимые для рендеринга данные, избегая запросов к нему. Использование внешних библиотек, включая стандартную, ограничено чистыми функциями и методами, прежде всего форматирования данных модели.

C — контроллер, всё остальное, начиная со слушания портов (или конфигов для «стандартных» nginx/apache/IIS/...) до взаимодействия с внешним миром, включая СУБД. Обычно включает и разбивает по сущностям платформы: веб-сервер (в виде конфигов http и fast-fpm), фронт-контроллер, роутер, классы контроллеров, сервисы обеспечения персистентности модели, сервисы идентификации, аутентификации и авторизации пользователей, сервисы логирования, сервисы уведомлений и т. п. В ответ на запрос пользователя (http запрос) маршрутизирует его до вызова конкретного метода с нужными параметрами, который инициирует начало выполнение бизнес-сценария или его атомарного этапа, вызывая метод модели, предварительно восстанавливая модель (обычно только часть) из хранилища, выполняя инфраструктурные действия типа логирования и авторизации, а после окончания сценария или его этапа, выбирает и создаёт нужное представление, вызывает его метод рендеринга, повозможности как чистую функцию, явно передавая все необходимые ему данные как параметры, и возвращая результат рендеринга пользователю как тело http-ответа. Как вариант — представление возвращает полный http-ответ, или даже само отправляет его клиенту.
Sign up to leave a comment.

Articles

Change theme settings