Комментарии 22
Кхм. Вы предлагаете во втором совете писать абстракции от всех используемых фреймворков? Например (условно) возьмём Qt в качестве фреймворка. Так ведь чисто из-за того, что мы будем его использовать он быстро полезет изо всех щелей! И хрен мы его просто заменим. Либо придётся ваять абстракции чуть ли не на каждый чих.
Или я что-то неверно понял?
Или я что-то неверно понял?
Идея в том, что хорошо иметь четкие уровни в архитектуре. И если вы используете что-то на UI, то это не значит, что доступ к базе данных или какая-то логика ядра системы должны зависить и вообще знать о существовании UI. Разрабатывая каждый уровень, все остальные компоненты системы, на других уровнях должны представляться абстракциями, почти черными ящиками с моделью «с этого уровня я буду дергать DAO за эти методы и получать вот такие данные».
Конечно, это все в идеале. Иногда проще, и к этому идут многие фреймворки для rapid development, довольно сильно сделать coupling уровней, примерно как в одном месте мы и из базы почитали и там же и view сгенерировали. Но стоит понимать намечающюся задницу, когда требования поменяются с «зеленых крокодилов» на «синие холодильники»
Конечно, это все в идеале. Иногда проще, и к этому идут многие фреймворки для rapid development, довольно сильно сделать coupling уровней, примерно как в одном месте мы и из базы почитали и там же и view сгенерировали. Но стоит понимать намечающюся задницу, когда требования поменяются с «зеленых крокодилов» на «синие холодильники»
минимизация связей между компонентами (низкая связанность, low cohesion).
Наверное, loose coupling, имелось ввиду.
На мой взгляд:
Наиболее плохо поддаются проектированию приложения, где главными компонентами выступают GUI и БД. Приложения баз данных трудно спроектировать так, чтобы их конечная архитектура была достаточно гибкой, — на это потребуется не одна мажорная версия кода. Тут проблема в изменчивости (БД), трудности тестирования (GUI) и местечковости (Business Logic + GUI + БД).
Наиболее хорошо проектируются приложения преобразования данных, у которых вообще может не быть интерфейса. Также хорошо проектируются приложения с минимальным числом разнородных компонентов (что очевидно). Сюда можно отнести огромное количество всяческих утилит, да хоть те же системы контроля версий.
Хорошо проектируются приложения, в которых много компонентов, но все они достаточно равноправны. Это, например, компьютерные игры, какие-нибудь редакторы. И хотя на архитектуру придется потратить достаточно много усилий, но так как один ни компонент не будет перетягивать одеяло на себя, риски перекосов ощутимо сглаживаются.
Наиболее плохо поддаются проектированию приложения, где главными компонентами выступают GUI и БД. Приложения баз данных трудно спроектировать так, чтобы их конечная архитектура была достаточно гибкой, — на это потребуется не одна мажорная версия кода. Тут проблема в изменчивости (БД), трудности тестирования (GUI) и местечковости (Business Logic + GUI + БД).
Наиболее хорошо проектируются приложения преобразования данных, у которых вообще может не быть интерфейса. Также хорошо проектируются приложения с минимальным числом разнородных компонентов (что очевидно). Сюда можно отнести огромное количество всяческих утилит, да хоть те же системы контроля версий.
Хорошо проектируются приложения, в которых много компонентов, но все они достаточно равноправны. Это, например, компьютерные игры, какие-нибудь редакторы. И хотя на архитектуру придется потратить достаточно много усилий, но так как один ни компонент не будет перетягивать одеяло на себя, риски перекосов ощутимо сглаживаются.
Есть два подхода к проектированию ПО. Один из них называется «outside-in approach», описанный в частности в книге “Growing Object Oriented Software”. В нем предлагается начать разработку с UI и двигаться в сторону бизнес-логики. Есть и другой подход, который называется «inside-out», в котором проектирование начинается с бизнес-логики и уже от нее двигаться в сторону UI и базы данных.
Возможно есть приложения, в которых второй подход не работает, что-то типа сверх тонких клиентов, но в большинстве случаев, подход inside-out будет прекрасно работать. Да, проектированием UI приложения двигает именно UI, но даже если брать разработку сложного UI-приложения, то подход inside-out все еще возможен: бизнес-аналитик, архитектор, заказчик определяет желаемое поведение UI-й части. Затем, с помощью MVXXX паттернов дербанится на части представление и логика представления; после чего разрабатывается именно логика представления на которую уже натягивается сама вьюха.
В общем, большинство приложений нормально проектируются, хотя, конечно, некоторые типы приложений могут сопротивляться этому сильнее остальных
Возможно есть приложения, в которых второй подход не работает, что-то типа сверх тонких клиентов, но в большинстве случаев, подход inside-out будет прекрасно работать. Да, проектированием UI приложения двигает именно UI, но даже если брать разработку сложного UI-приложения, то подход inside-out все еще возможен: бизнес-аналитик, архитектор, заказчик определяет желаемое поведение UI-й части. Затем, с помощью MVXXX паттернов дербанится на части представление и логика представления; после чего разрабатывается именно логика представления на которую уже натягивается сама вьюха.
В общем, большинство приложений нормально проектируются, хотя, конечно, некоторые типы приложений могут сопротивляться этому сильнее остальных
Есть два подхода к проектированию ПО. Один из них называется «outside-in approach», описанный в частности в книге “Growing
Object Oriented Software”. В нем предлагается начать разработку с UI и двигаться в сторону бизнес-логики. Есть и другой подход, который называется «inside-out», в котором проектирование начинается с бизнес-логики и уже от нее двигаться в сторону UI и базы данных.
___
Т.е. все то у чего нету UI ПО не является чтоли?
Object Oriented Software”. В нем предлагается начать разработку с UI и двигаться в сторону бизнес-логики. Есть и другой подход, который называется «inside-out», в котором проектирование начинается с бизнес-логики и уже от нее двигаться в сторону UI и базы данных.
___
Т.е. все то у чего нету UI ПО не является чтоли?
Смотря что под UI понимать. Иногда это набор опций командной строки, формат конфигурационного файла, или даже формат ввода/вывода. Не могу вспомнить какое-либо прикладное ПО вообще без интерфейса.
Рано или поздно UI на каком ни будь из концов всплывает, другое дело, что это может быть за пределами разрабатываемой системы, тогда речь идет о программных интерфейсах.
Это разновидность функционального подхода — определяем что на входе и на выходе как более или менее данность, выводим из этого то, что в центре.
Это разновидность функционального подхода — определяем что на входе и на выходе как более или менее данность, выводим из этого то, что в центре.
Вариант «outside-in approach» хорошо описан в Getting Real от 37signals и он отлично работает для проектов с тонкой моделью. Но для продуктов со сложной бизнес-логикой его использовать затруднительно.
«где главными компонентами выступают GUI и БД» — это справедливо почти для любого веб-приложения. А они вполне хорошо проектируется и покрываются тестами (как модульными, так и функциональными), особенно если используют MVC.
В каком-то софтварном журнале читал такое определение архитектуры: это то, что мы хотим сделать правильно с самого начала.
Т.е. по идее это такие вещи, которые после начала кодирования изменить сложно.
Итого, чтобы получить близкую к идеальной систему, надо хорошо продумать базовые компоненты (используемые фреймворки, интернализацию, логирования, слои) и на базе этих компонентов с помощью TDD строить оставшееся. Таким образом сложно изменяемые части скорее всего будут сделаны правильно от начала, а остальное через TDD с большей вероятностью будет сделано также качественно.
Т.е. по идее это такие вещи, которые после начала кодирования изменить сложно.
Итого, чтобы получить близкую к идеальной систему, надо хорошо продумать базовые компоненты (используемые фреймворки, интернализацию, логирования, слои) и на базе этих компонентов с помощью TDD строить оставшееся. Таким образом сложно изменяемые части скорее всего будут сделаны правильно от начала, а остальное через TDD с большей вероятностью будет сделано также качественно.
Полностью согласен с применением тестов в качестве «лакмусовой бумажки». Это прямой путь к защите слоев архитектуры от взаимопроникновения и к минимизации связности компонентов системы.
Лично мне досталась в наследство некая система с интегрированным скриптовым языком. Так вот, она была настолько монолитна, что бизнес-логика, которая по задумке должна была быть реализована скриптами, дублировалась. Фактически, было написано две параллельные системы, в скриптах и в бинарнике, именно из-за жесткой связки бизнес-логики, логики работы с БД и GUI. За три года поддержки я смог «расцепить» UI и бизнес лишь частично, и то благодаря тем самым бесконечным тестам.
В то же время новый функционал подмешивался в виде автономных (ну, почти) модулей, которые безо всяких изменений могли работать и как отдельное тестовое приложение, и как часть системы. При разработке тестируемость была основными критерием.
Итог: подход работает. В новой части изменения проходят легко и непринужденно, в старой — каждый раз кровавое месиво. Конечно, в моем случае имеет место постепенное перепроектирование системы, а не разработка с нуля, но не думаю, что это принципиально.
А по поводу разработки архитектуры имею удовольствие доложить: очень многое, чуть ли не всё, зависит от хорошо продуманных программных интерфейсов. Даже самую мерзкую пакость можно обернуть приятным API и жить спокойно, при условии автономности оной пакости, разумеется.
Лично мне досталась в наследство некая система с интегрированным скриптовым языком. Так вот, она была настолько монолитна, что бизнес-логика, которая по задумке должна была быть реализована скриптами, дублировалась. Фактически, было написано две параллельные системы, в скриптах и в бинарнике, именно из-за жесткой связки бизнес-логики, логики работы с БД и GUI. За три года поддержки я смог «расцепить» UI и бизнес лишь частично, и то благодаря тем самым бесконечным тестам.
В то же время новый функционал подмешивался в виде автономных (ну, почти) модулей, которые безо всяких изменений могли работать и как отдельное тестовое приложение, и как часть системы. При разработке тестируемость была основными критерием.
Итог: подход работает. В новой части изменения проходят легко и непринужденно, в старой — каждый раз кровавое месиво. Конечно, в моем случае имеет место постепенное перепроектирование системы, а не разработка с нуля, но не думаю, что это принципиально.
А по поводу разработки архитектуры имею удовольствие доложить: очень многое, чуть ли не всё, зависит от хорошо продуманных программных интерфейсов. Даже самую мерзкую пакость можно обернуть приятным API и жить спокойно, при условии автономности оной пакости, разумеется.
Ещё бы добавил, что «правильный подход к проектированию» даёт ещё один значимый бонус, о котором часто забывают: масштабируемость процесса разработки. Т.е. грубо говоря — возможность сократить срок разработки за счёт добавления к нему людей. Это происходит за счёт простой вещи: наше ПО это 100500 микро-ситуаций «клиент»->«сервис». И если «сервис» будет не конкретным классом а интерфейсом, то разделить работу между 2 сотрудниками: одному разрабатывать «клиент»и тестироваться с помощью мока сервиса, а другому — разрабатывать реализацию сервиса и тестировать его тестом на основ контракта. Ясно что скорость увеличится не в 2 раза из-за необходимости дополнительно создать 2 комплекта для тестирования, но если в команде и так пишутся автотесты — то не так важно. Так же очевидно, что эффективность такого подхода тем выше, чем ближе наш клиент->сервис к ситуации взаимодействия 2х крупных компонент.
Вставлю свои 5 копеек. Основанные на личных фантазиях в меру далекого от программирования человека.
При проектировке приложений, да и вообще любых систем, стараться делить их на максимально автономные модули.
Потому что сложные системы, состоят из элементов. Каждый связанный элемент может быть дефективным. И если он связан неразрывно со всей системой, то это может привести к краху все системы.
Тоесть, если риск ошибки (человеческой, программной etc) в одном модуле равен 0.1% (мало, правда),
то в случае если у нас 100 таких модулей, то риск всей системы возрастет до 10%.
Чем сложней система, тем большая вероятность катастрофы.
При проектировке приложений, да и вообще любых систем, стараться делить их на максимально автономные модули.
Потому что сложные системы, состоят из элементов. Каждый связанный элемент может быть дефективным. И если он связан неразрывно со всей системой, то это может привести к краху все системы.
Тоесть, если риск ошибки (человеческой, программной etc) в одном модуле равен 0.1% (мало, правда),
то в случае если у нас 100 таких модулей, то риск всей системы возрастет до 10%.
Чем сложней система, тем большая вероятность катастрофы.
У МакКоннела вся книга Code Complete, которая, на мой взгляд, является наиболее практически ценной из всех книг по программированию, строится вокруг изоляции и снижения сложности, и это выносится как основной принцип и императив.
Вот, умные идеи они витают в воздухе. И распространяются на все сферы жизни.
Я к этому пришел через абсолютно экономические науки. Даже напишу статью об этом, так как оно затрагивает очень много чего в мире IT. Такое проектирование систем это частное применение одной большей современной эконом. теории.
И вот, гуру программирования подтверждает что это работает на практике и так должно быть. Только пришел к этому с другой стороны
* философски *
Как-то объясняет порядок законов во вселенной. Так же как много физических явления завязаны на логарифмическую константу е, так же и другие вещи абсолютно казалось бы не связанные между собой, абсолютно связаны.
Я к этому пришел через абсолютно экономические науки. Даже напишу статью об этом, так как оно затрагивает очень много чего в мире IT. Такое проектирование систем это частное применение одной большей современной эконом. теории.
И вот, гуру программирования подтверждает что это работает на практике и так должно быть. Только пришел к этому с другой стороны
* философски *
Как-то объясняет порядок законов во вселенной. Так же как много физических явления завязаны на логарифмическую константу е, так же и другие вещи абсолютно казалось бы не связанные между собой, абсолютно связаны.
Ну, я социолог по образованию, так что тоже не могу отделаться от профессионального взгляда на разработку, во всяком случае социология науки и деятельности объясняют очень многое из получающихся результатов.
Достаточно много авторов уже писали в этом ключе: Дейкстра, Брукс, Грэм и т.д., но, слава богу, еще много неохваченных тем и есть что сказать.
Достаточно много авторов уже писали в этом ключе: Дейкстра, Брукс, Грэм и т.д., но, слава богу, еще много неохваченных тем и есть что сказать.
В свое время я писал достаточно обширную заметку по типам связанности, и всяких тонких нюансах, например в нетипизованных языках любой параметр при вызове метода стоит воспринимать как более широкий канал для образования связанности. Отдельная тема — мониторинг связанности через глобалы и god-классы. В таком случае все, например, может прекрасно тестироваться пока не был затронут god-класс или глобалсы, а после их изменения вылететь в трубу.
Работа над заметкой, правда, зависла, и у меня самого появились сомнения, насколько эту теорию нужно углублять и раскладывать по полочкам.
Тем более сейчас большая часть задач, которые решает программист носит интеграционный характер, это готовые библиотеки, фреймворки и т.д. И архитектура, которую они навязывают, это почти данность, которую очень трудоемко изолировать.
Cohension я перевожу как «сопряженность», больше смысловой нагрузки, как бы все части класса или подсистемы работают в одной упряжи. А сцепленность и связанность без шпаргалки и при размышлениях просто перепутать.
Работа над заметкой, правда, зависла, и у меня самого появились сомнения, насколько эту теорию нужно углублять и раскладывать по полочкам.
Тем более сейчас большая часть задач, которые решает программист носит интеграционный характер, это готовые библиотеки, фреймворки и т.д. И архитектура, которую они навязывают, это почти данность, которую очень трудоемко изолировать.
Cohension я перевожу как «сопряженность», больше смысловой нагрузки, как бы все части класса или подсистемы работают в одной упряжи. А сцепленность и связанность без шпаргалки и при размышлениях просто перепутать.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Идеальная архитектура