Telegram Web
emacsway-log: Software Design, Clean Architecture, DDD, Microservice Architecture, Distributed Systems, XP, Agile, etc.
Чтобы лучше вообразить то, что происходит в мозгу, когда объем единовременно рассматриваемой сложности превышает возможности краткосрочной памяти человека, посмотрите на эту картинку. Сколько точек вы видите? Ваши глаза не могут увидеть все 12 точек одновременно.…
Один из способов ввести мозг разработчика в состояние "умственного жонглирования" - это "звездная" ("божественная") модель, которая решает несколько проблем. Или, если сказать по другому, - совмещение нескольких моделей в границах одного компонента.

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

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

При попытке компонентного разделения такой "исторически сложившейся" системы, например, при выделении компонента, ответственного за платежи, перед программистом возникает вопрос: а что делать, если для функционирования одного компонента нужна сущность, которая находится в другом компоненте? Возникает то, что получило название "распределенный монолит". Модель размазывается на несколько компонентов.

Это несущественно, пока система маленькая. Но по мере роста размеры системы это приводит к кризису и препятствует дальнейшему росту системы. Никто не знает какой атрибут сущности кем и где используется. Изменение одного атрибута по одной причине может привести к тому, что в системе отвалится что-то другое, совершенно не связанное с этой причиной, только лишь потому, что один и тот же атрибут одной и той же сущности используется для решения разных проблем. Становится невозможно за всем уследить.

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

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

См. также:
- https://www.tgoop.com/emacsway_log/1152
- https://www.tgoop.com/emacsway_log/1295
👍6🔥3💯2
Вопрос от программиста из категории "я такие вопросы люблю" (предыдущий был не менее интересным).

Если Domain Event - это факт изменения состояния модели, то можно ли использовать его в качестве сообщения о нарушении инвариантов (т.е. в целях валидации), как это предлагал Udi Dahan?
https://udidahan.com/2008/08/25/domain-events-take-2/

Если используется Task-Based UI + CQRS с однонаправленным потоком изменений, и CQRS-команда не может быть обработана исполнена, потому что нарушает инварианты, то можно ли сообщение канала обратной связи (WebSocket) считать представлением Domain Event?

Нарушение инварианта - это событие предметной области?
На корпоративных тренингах на рабочем месте часто бывает ситуация, когда люди отваливаются: вчера ещё было 3 человека в команде, а сегодня, смотришь — остался только один, остальных растащили на встречи.

И часто этот оставшийся работает лучше и быстрее, чем до этого они работали втроем!

Я и сам сталкивался с таким, как участник: на одном курсе по управлению проектами мы выполняли задание сначала индивидуально, а потом то же задание в группах. По идее, результат группы должен быть лучше самого лучшего индивидуального результата, но моя группа сумела даже ухудшить мой результат :) Инициативу захватила одна участница, которая, видимо, очень хотела показать свои лидерские качества, а проще всего это сделать, если всех критиковать, подвергать сомнению и настаивать на собственной правоте. А то какой же я лидер, если просто прислушиваюсь к другим! Я в это играть не очень хотел, ну и вот. Не хотите ко мне прислушиваться — садитесь в лужу, bon voyage.

У этого явления есть название: эффект Рингельмана. В ИТ мы знаем его следствие, известное как Закон Брукса:

«Если проект не укладывается в сроки, то добавление рабочей силы задержит его ещё больше».

Эффект Рингельмана формулируется так:

«Личная продуктивность отдельных членов группы снижается по мере роста численности группы»

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

В исследованиях Рингельмана общая продуктивность группы уже на 5 участниках составляет только 3.5 (считая эталонную продуктивность каждого в отдельности за 1), а после 7 практически перестает расти, застывая на отметке 3.92.

Обычно эффект объясняют двумя причинами: "социальной ленью" и потерей координации.
Если мы видим, что над той же задачей работает кто-то ещё, мы уже не так сильно вкладываемся. Это "социальная лень" или "социальное бездействие".

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

Что тут можно сделать?

Брукс предлагал выстраивать группы вокруг признанного лидера и эксперта, по типу операционной бригады (всегда есть главный хирург, который делает операцию, остальные ему ассистируют).

Agile говорит, что команда должна быть не больше, чем можно накормить двумя пиццами (5-7 человек).

Исследования сообщают, что социальное бездействие ослабевает, если:
1. У людей есть общая разделяемая цель
2. Вклад каждого участника может быть идентифицирован и оценен
3. Люди чувствуют свою незаменимость

В целом, это вопрос мотивации.

А вот координация — вопрос технический, это "харды" организации работ. Сам Рингельман, кроме перетягивания каната, изучал ещё перетаскивание камней при помощи веревок и перемещением тележек мускульной силой (он вообще занимался организацией работ в сельском хозяйстве, и работал примерно в одно время с Тейлором и Гастевым). Измеряя силы, прикладываемые работниками к камню, он выяснил, что основная проблема в синхронизации усилий: то один начинает не вовремя, то тянут в разные стороны. Про мотивацию он как раз не писал.

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

В конечном счете это всё про разделение (объектов и выполняемых над ними работ), объединение (результатов работ в единое целое) и принятие решений.

Хм, кажется, опять получилось про анализ и архитектуру.
🔥14👍41
Наткнулся на интересный набор паттернов обмена сообщениями от Microsoft Azure. Так как это паттерны, реализовать их можно на любых технологиях.

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

Всего там 42 паттерна, они достаточно произвольно объединены в три категории:
— управление данными,
— архитектура и реализация
— обмен сообщениями.

Это "китайская классификация" по Борхесу; мне, например, сложно понять, почему CQRS — это "архитектура", а хореография — "обмен сообщениями". В любом случае, паттерны интересные, а ещё есть анти-паттерны, как делать не надо — тоже полезно знать при проектировании решения; и архитектурные принципы. Повторюсь, что это довольно общие вещи, относящиеся не только к продуктам на основе Azure — они в том или ином виде реализованы и в AWS, и в других системах.

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

Итак, паттерны:

* Асинхронный запрос-ответ.
В общем, простая идея про запросы, длительность обработки которых на сервере может занять больше, чем 100 мс, а очереди/брокера у вас нет или вы не хотите их использовать — и вы используете поллинг. Первым запросом запускаете процесс на сервере, а сервер возвращает 202 (Accepted) и ссылку, которую нужно поллить. Клиент регулярно ходит по этой ссылке и проверяет — выполнился ли запрос. Пока он не выполнен — сервер возвращает 200 (OK). Когда результат готов — 302 (Found) и переадресует на место, где лежит результат.
Как вариант, тут можно было бы использовать WebHook, но далеко не все клиенты поддерживают вызовы к ним — технически или по соображениям безопасности.

* Квитанция (claim-check).
Если вы собираетесь передавать большой объем данных, имеет смысл не загружать систему передачи (например, брокера или очередь), а выслать "квитанцию" с токеном, по которому клиент сможет забрать ответ из хранилища статических данных. Также паттерн можно использовать, когда нужна дополнительная защита, чтобы чувствительные данные не проходили через брокер/очередь/прокси и т.п. Ну и в принципе неплохо бы защищать статику каким-нибудь токеном, чтобы не было ситуаций с утечкой документов, доступных по прямым адресам без всякой проверки — про это следующий паттерн.

* Valet Key — не знаю, как перевести на русский, видел автоматический перевод "ключ камердинера", но не встречал такого употребления в живой среде. Это как раз токен из предыдущего паттерна: когда вы получаете статический ресурс, если он не должен быть общедоступным — защищайте его токеном. То есть, клиент сначала запрашивает ресурс у приложения, приложение отдает ссылку на ресурс + токен (либо токен зашит прямо в URL), и передает токен хранилищу. Хранилище обрабатывает запрос к ресурсу только с токеном — так гарантируется, что запросивший клиент — именно тот, кому выдали разрешение, а ещё можно ограничить действие токена по времени.
Этот паттерн также описан в книге O'Reilly 'Cloud Architecture Patterns' — хотя остальные паттерны в ней в основном низкоуровневые.

Где можно использовать эти паттерны? Например, при запросе большого отчета, который относительно долго формируется. "Заказать" формирование мы можем через асинхронный запрос и поллинг, либо через очередь запросов, потом получим "квитанцию" с токеном доступа, а сам сформированный отчет ляжет в файловое хранилище. Файловое хранилище отдаст готовый отчет только клиенту, предъявившему квитанцию с токеном. Про истечении времени жизни токена отчет будет удален.
👍7🔥73🤩1
emacsway-log: Software Design, Clean Architecture, DDD, Microservice Architecture, Distributed Systems, XP, Agile, etc.
Один из способов ввести мозг разработчика в состояние "умственного жонглирования" - это "звездная" ("божественная") модель, которая решает несколько проблем. Или, если сказать по другому, - совмещение нескольких моделей в границах одного компонента. В таком…
Существует модель ментальная (аналитическая) предметной области, грубо говоря, это представление (знания) стейкхолдеров о тех процессах, которые можно автоматизировать информационной системой. Это модель области проблемы (Problem Space), и существует она независимо от того, автоматизирована ли она системой или нет (например, правила рассчета процентной ставки банка, которую высчитывает клерк на калькуляторе). Она является причиной появления автоматизированной системы.

И существует модель решения, т.е. упрощенная интерпретация реальности с целью решения некой проблемы. Это модель области решения (Solution Space), которая подлежит реализации. Это то, что будет "делать" система, business logic (от англ. "business" - "дело").

Эти две модели могут отличаться. Основная идея DDD заключается в том, чтобы они не отличались, т.е. чтобы эти две модели совместить в одну. А поскольку натуральный язык - это средство моделирования, то для достижения этого используется Ubiquitous Language, т.е. использование единых терминов как специалистами области решения (разработчиками), так и специалистами области проблемы (экспертами предметной области). Таким образом, Ubiquitous Language является моделью как области проблемы, так и области решения. В этом заключается основная суть DDD. Такой подход позволяет существенно снизить информационную нагрузку на разработчиков, а значит, снизить вероятность ошибки. Любой, кто знает логику предметной области, легко разберется в том, как устроена система.

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

Основных целей у Bounded Context две:
1. Снизить когнитивную нагрузку, т.е. модель не должна содержать ничего неревантного решаемой ею проблеме, чтобы не создавать паразитную когнитивную нагрузку.
2. Снизить коммуникативную нагрузку, т.е. модель не должна быть разделена между разными командами, которые не смогут и шагу ступить без коммуникаций, не сломав при этом инвариантов модели.

Основная суть EventStorming заключается именно в том, что он позволяет моделировать решение прямо поверх ментальной модели стейкхолдеров, прямо на тех же стикерах. Результатом ES является модель решения, которая в точности отражает структуру будущего кода. Настолько точно, что по этой диаграмме можно делать автоматизированную сверку кода, или даже генерировать сам код (на Java это можно сделать используя сервис от Vaughn Vernon domorobo.to + xoom-designer).
👍13🔥3
emacsway-log: Software Design, Clean Architecture, DDD, Microservice Architecture, Distributed Systems, XP, Agile, etc.
Существует модель ментальная (аналитическая) предметной области, грубо говоря, это представление (знания) стейкхолдеров о тех процессах, которые можно автоматизировать информационной системой. Это модель области проблемы (Problem Space), и существует она независимо…
💬 "3.3. Что такое модель?
Мы уже сформулировали два определения модели.

Первое: модель есть средство осуществления любой деятельности субъекта.

Второе: модель есть форма существования знаний.

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

Выразим эту мысль в виде еще одного общего определения: модель есть системное отображение оригинала.

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

💬 "3.4. Аналитический подход к понятию модели

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

Соответственно этому модели разделяются на абстрактные и реальные (рис. 3.5)."

О моделировании посредством натурального языка:

💬 "Более определенно мы можем говорить об абстрактных моделях,
которые являются как бы конечным продуктом мышления, приготовленным для передачи другим субъектам. Это модели, воплощенные средствами языка: они поддаются регистрации (тексты, аудиозаписи) и могут изучаться как объекты, отчужденные от непосредственно мышления, но являющиеся его продуктами, содержащими информацию о нем."
👍31
emacsway-log: Software Design, Clean Architecture, DDD, Microservice Architecture, Distributed Systems, XP, Agile, etc.
💬 "3.3. Что такое модель? Мы уже сформулировали два определения модели. Первое: модель есть средство осуществления любой деятельности субъекта. Второе: модель есть форма существования знаний. Можно несколько дополнить каждое из этих определений указанием…
💬 "Главная для нас особенность — то, что язык является универсальным средством моделирования: говорить можно о чем угодно. Из многих свойств языка, обеспечивающих ему это свойство, обратим внимание на расплывчатость смысла слов.

Приведем пример словесной модели некоторой ситуации.
«В комнату вошел высокий красивый молодой человек, неся тяжелый сверток». Так и видится реальная картина. Но «высокий» — какого именно роста? «Молодой» — а сколько ему лет? Не говоря уж
о том, что такое «красивый». «Тяжелый» — какого веса? Практически ни одно слово естественного языка не имеет точного смысла. Можно привести аналогию: «смысл» конкретной ситуации — точка, «смысл» слова — облако. Описывая конкретную ситуацию, мы как бы обволакиваем точку облаками, понимая, что истина гдето в середине этого скопления. В большинстве случаев, особенно в быту, такого приблизительного, расплывчатого описания бывает достаточно для действий, часто успешных. В некоторых видах деятельности такая расплывчатость сознательно используется как важный позитивный фактор: поэзия, юмор, политика, дипломатия, мошенничество…

Однако в случаях, когда необходимо произвести конкретный продукт, достичь конкретного результата, этой конкретности начинает
мешать расплывчатость бытового языка. И тогда те, кто занимается конкретной деятельностью, изживают мешающую неопределенность,
вводя в язык более точные термины. У всякой группы с ее общими целями вырабатывается свой, специфический язык, обеспечивающий
нужной точностью эту деятельность. У скотоводческого африканского племени масаев есть сотни терминов для характеристики коров;
у северных народов — множество терминов, определяющих состояние
снега; на своих языках разговаривают физики, медики, юристы; уголовники «ботают по фене»; молодежь говорит на слэнге, не понятном для взрослых; лондонские «низы» разговаривают на «кокни».

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

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

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

Есть ли предел этому процессу уточнения? Есть, и это язык математики, в котором термины максимально точны, однозначны.

Правда, полностью изжить неопределенность невозможно, иначе было бы невозможно о бесконечности мира говорить конечными фразами. Есть несколько (и не только вспомогательных, но и базовых) понятий в математике, имеющих расплывчатый смысл: «приблизительно равно», «значительно больше (меньше)», «бесконечно мало (велико)», «неопределенно» и т.д. И все же математический язык является крайним, самым точным справа в спектре языков описания реальности (рис. 3.7)."
👍5
emacsway-log: Software Design, Clean Architecture, DDD, Microservice Architecture, Distributed Systems, XP, Agile, etc.
💬 "Главная для нас особенность — то, что язык является универсальным средством моделирования: говорить можно о чем угодно. Из многих свойств языка, обеспечивающих ему это свойство, обратим внимание на расплывчатость смысла слов. Приведем пример словесной…
💬 "То, что какая-то наука недостаточно математизирована (история, биология, медицина, психология, политология и т.п.), означает лишь то, что ее объект столь сложен, столь мало изучен, что до математической точности ей еще далеко. Но есть перспектива.

Для полноты картины отметим еще одну особенность языков.
Культура индивида (мир его моделей) образуется из взаимодействия его врожденных моделей и культуры его социальной среды, в том числе (а возможно, и в первую очередь) языков, входящих в эту культуру. Здесь проявляется свойство ингерентности, совместимости
внутренней и внешней культур. Случается, что их полного согласования достичь не удается: генетики доказали, что иногда неспособность научиться грамотно говорить и писать заложена в генах субъекта; человек, не имеющий абсолютного слуха, при всем старании не может полностью познать язык музыки; люди с преобладающим «правополушарным» мышлением испытывают своего рода аллергию к математике; люди, в зрелом возрасте попавшие в эмиграцию, испытывают чувство ностальгии и т.п. Однако языков так много, что каждый находит возможность сформировать свою культуру так, чтобы в каком-то отношении обеспечить свое посильно успешное взаимодействие с окружающей средой."

💬 "Продолжая рассмотрение отношений между моделью и оригиналом, остановимся на содержании информации в модели. Оригинал и модель — разные вещи. В оригинале есть много такого, чего нет
в модели
, по двум причинам: во-первых, не все из того, что известно об оригинале, понадобится включить в модель, предназначенную для
достижения конкретной цели
(зона А на рис. 3.13 изображает известное, но ненужное, в том числе ошибочно сочтенное ненужным и невключенное в модель); во-вторых, в оригинале есть всегда нечто непознанное, поэтому не могущее быть включенным в модель (зона В на рис.
3.13). Зона 2 на рисунке изображает информацию об оригинале, включенную в модель. Это истинная информация, то общее, что имеется у модели и оригинала, благодаря чему модель может служить его (частным, специальным) заменителем, представителем. Обратим внимание на зону 3. Она отображает тот факт, что у модели всегда есть собственные свойства, не имеющие никакого отношения к оригиналу, т.е. ложное
содержание
. Важно подчеркнуть, что это относится к любой модели, как
бы ни старался создатель модели включать в нее только истину."

Про эволюцию знаний:

💬 "К примеру, полезной бывает классификация моделей на познавательные и прагматические.

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

Познавательные модели (рис. 3.13) не претендуют на окончательность, завершенность: всегда остается что-то непознанное. В познавательной практике принято терпимо относиться к отличающимся и даже противоречивым мнениям. Научные модели подвергаются постоянному сомнению и проверке на правильность, непрерывно уточняются и развиваются."

--  "ПРИКЛАДНОЙ СИСТЕМНЫЙ АНАЛИЗ" /
Тарасенко Феликс Петрович
3👍2🤔2😐1
emacsway-log: Software Design, Clean Architecture, DDD, Microservice Architecture, Distributed Systems, XP, Agile, etc.
💬 "То, что какая-то наука недостаточно математизирована (история, биология, медицина, психология, политология и т.п.), означает лишь то, что ее объект столь сложен, столь мало изучен, что до математической точности ей еще далеко. Но есть перспектива. Для…
Остановимся на моментах, имеющих ключевое отношение к определению границ Bounded Context. Даже в языке математики:

💬 "полностью изжить неопределенность невозможно, иначе было бы невозможно о бесконечности мира говорить конечными фразами".

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

Немного справочной информации из Википедии:

💬 "В русском литературном языке около 50 тысяч корней и десятки тысяч производных от них слов[1]. «Толковый словарь живого великорусского языка» В. И. Даля насчитывает около 200 тысяч слов. Наиболее употребительными словами, согласно «Частотному словарю русского языка» под редакцией Л. Н. Засориной, являются около 30 тысяч слов, а наибольшую частоту имеют чуть более 6 тысяч слов, покрывающих более 90 % обработанных при составлении этого словаря текстов.
По данным исследования Головина Г. В.[2], пассивный словарный запас у тех, кто получил среднее или среднее специальное образование, составляет в среднем 75 тыс. слов, имеющие высшее или незаконченное высшее образование знают в среднем 81 тыс. слов, кандидаты и доктора наук — 86 тыс. слов[3]."
-- "Словарный запас", Википедия

Однако, вы можете возразить, а как же так, ведь если мы один и тот же оригинал называем разными терминами в разных Bounded Context, то причем здесь ограниченность языка? Отвечает на этот вопрос сам Ф.П.Тарасенко:

💬 "Практически ни одно слово естественного языка не имеет точного смысла."

💬 "увеличение точности смысла языковых моделей идет за счет добывания и включения в язык все новой и новой информации о предмете интереса."

Вернемся к нашему примеру с пассажиром лифта. Какого он пола? Какой его возраст? Как его зовут? Какая его должность? Где он живет? Эта информация утрачена. Нам известно о нем только то, что это одушевленная единица перевозки. Мы знаем о нем только то, "что можно с ним сделать" - перевезти с одного этажа на другой. Сколько терминов нам понадобилось бы, чтобы однословно описать пассажиров обоих полов в возрасте от момента рождения до 100 лет?

Когда покупатель купил некий "товар", который был передан в отдел доставки, то этот товар стал называться "грузом", и информация о характере товара утратилась. Произошла утрата определенности. Собственно, эта утрата (игнорирование) нерелевантных деталей называется абстракцией.

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

Абстракция - один из главных способов борьбы со сложностью реального мира. Это то, что позволяет "о бесконечности мира говорить конечными фразами".

Именно термины натурального языка приводит в качестве примера Steve McConnell в своей книге Code Complete для того, чтобы пояснить суть абстракции.

Таким образом, ключевым в определении границ Bounded Context является то, каким именно термином мы можем устранить избыточную определенность об оригинале моделирования. Важно ли курьеру знать детали содержимого посылки? Можем ли мы выразить это таким термином, который был бы абстрагирован от избыточной определенности оригинала (конкретного содержимого посылки)?
🔥9👍5
Forwarded from Евгений Козлов пишет про IT (Eugene Kozlov)
Наконец дошли руки сделать 2ю версию гайда по алгоритмическим интервью и изучению алгоритмов.

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

Поддержка в любом виде приветствуется😊 Любите алгосики и удачи на собесах😇

https://github.com/beagreatengineer/algo-interview
🔥18
emacsway-log: Software Design, Clean Architecture, DDD, Microservice Architecture, Distributed Systems, XP, Agile, etc.
Остановимся на моментах, имеющих ключевое отношение к определению границ Bounded Context. Даже в языке математики: 💬 "полностью изжить неопределенность невозможно, иначе было бы невозможно о бесконечности мира говорить конечными фразами". 💬 "снятие неопределенности…
До сего момента мы рассматривали управление Существенной Сложностью (Essential Complexity). Это наиболее существенное, хотя и не исчерпывающее, условие успешности разработки, потому что "Серебрянной пули нет".

Существенная Сложность (Essential Complexity) - сложность того, что делает система, сложность реализованных ею моделей, отражающих сложность реального мира, не зависящая от способа и деталей реализации. Сложность, порожденная решаемой проблемой, и ничто не может устранить или уменьшить её. Мы можем только управлять ею таким образом, чтобы минимизировать объем существенной сложности, рассматриваемой одновременно, до уровня, не превосходящего ограничения краткосрочной памяти человека.

Как утверждает Steve McConnell:

💬 "В философии существенными называют свойства, которыми объект должен обладать, чтобы быть именно этим объектом. Автомобиль должен иметь двигатель, колеса и двери — если объект не обладает каким-нибудь из этих существенных свойств, это не автомобиль."
-- "Code Complete" by Steve McConnell


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

Как утверждает Steve McConnell:

💬 "Несущественными (акцидентными, побочными) свойствами называют свойства, которыми объект обладает в силу случайности, — свойства, не влияющие на его суть. Так, автомобиль может иметь четырехцилиндровый двигатель с турбонаддувом, восьмицилиндровый или любой другой и все же являться автомобилем. Тип двигателя и колес, число дверей — все это несущественные свойства. Можете также думать о них как о второстепенных, произвольных, необязательных и случайных."
-- "Code Complete" by Steve McConnell


Ввел эти термины в оборот Frederick P. Brooks в своей монументальной статье "No Silver Bullets: Essence and Accidents of Software Engineering", позаимствовав идею у Аристотеля.

💬 "Following Aristotle, I divide them [difficulties] into essence - the difficulties inherent in the nature of the software - and accidents - those difficulties that today attend its production but that are not inherent.
<...>
The complexity of software is in essential property, not an accidental one. Hence descriptions of a software entity that abstract away its complexity often abstract away its essence. Mathematics and the physical sciences made great strides for three centuries by constructing simplified models of complex phenomena, deriving properties from the models, and verifying those properties experimentally. This worked because the complexities ignored in the models were not the essential properties of the phenomena. It does not work when the complexities are the essence.”
—“No Silver Bullet - Essence and Accident in Software Engineering” by Frederick P. Brooks, Jr.


Теперь мы подошли к вопросу о том, каким образом можно защитить управление существенной сложностью от несущественной сложности.
🔥11💯1
emacsway-log: Software Design, Clean Architecture, DDD, Microservice Architecture, Distributed Systems, XP, Agile, etc.
До сего момента мы рассматривали управление Существенной Сложностью (Essential Complexity). Это наиболее существенное, хотя и не исчерпывающее, условие успешности разработки, потому что "Серебрянной пули нет". Существенная Сложность (Essential Complexity)…
Если есть изменяемое состояние, значит, систему можно привести в логически бессмысленное состояние. Чтобы этого избежать и сохранить систему в логически согласованном состоянии, эти изменения должны соответствовать инвариантам (бизнес-правилам).

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

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

А поскольку инварианты выражены методами, то чем меньше дистанция между изменяемым состоянием и этими методами, тем быстрее и легче можно их осмыслить. Это способ обойти ограничение краткосрочной памяти человека (Закон Миллера).

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

💬 encapsulation, the fact that one cannot see, much less design, the inner structure of the pieces.
—"The Mythical Man-Month Essays on Software Engineering Anniversary Edition" by Frederick P. Brooks, Jr.


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

В Функциональной Парадигме нет изменяемого состояния, поэтому, нет необходимости в инкапсуляции.

Существует два способа управления сложностью:
1. Сократить дистанцию между изменяемым состоянием и его инвариантами (OOP).
2. Сократить саму изменяемость (FP).

💬 "OO makes code understandable by encapsulating moving parts. FP makes code understandable by minimizing moving parts."
Michael Feathers


Под "moving parts" подразумевается изменяемое состояние, т.е. речь идет о конкретном виде инкапсуляции - сокрытии состяния и экспонировании поведения.

Как вы поняли, этот пост о про Anemic Domain Models, которые не используют ни функционального, ни объектно-ориентированного способа управления сложностью.

David Parnas в своем письме к Frederick P. Brooks писал:

💬 "Ответ прост. Это из-за привязанности ООП к сложным языкам. Вместо объяснения людям, что ООП является видом проектирования, и вооружения их принципами проектирования, их учили, что ООП — это использование определенного инструмента. Любыми срeдствами можно писать и плохие, и хорошие программы. Если не учить людей проектированию, то языки не имеют большого значения. Результатом будут плохие разработки с помощью этих языков и малая выгода. А если выгода невелика, то ООП не войдет в моду.

The answer is simple. It is because [O-O] has been tied to a variety of complex languages. Instead of teaching people that O-O is a type of design, and giving them design principles, people have taught that O-O is the use of a particular tool. We can write good or bad programs with any tool. Unless we teach people how to design, the languages matter very little. The result is that people do bad de-signs with these languages and get very little value from them. If the value is small, it won't catch on."
—"The Mythical Man-Month Essays on Software Engineering Anniversary Edition" by Frederick P. Brooks, Jr.


Из этого письма следует, что ООП не приживается именно там, где не умеют проектировать, а значит, не умеют извлекать выгоду из проектирования.
🔥12👍3
emacsway-log: Software Design, Clean Architecture, DDD, Microservice Architecture, Distributed Systems, XP, Agile, etc.
Если есть изменяемое состояние, значит, систему можно привести в логически бессмысленное состояние. Чтобы этого избежать и сохранить систему в логически согласованном состоянии, эти изменения должны соответствовать инвариантам (бизнес-правилам). А если в…
Разумеется, дело не в самом ООП, как в инструменте, а в его способности поддерживать инкапсуляцию. Мы уже разобрали что такое абстракция.

💬 Когда абстракция нас покидает, на помощь приходит инкапсуляция. Абстракция говорит: «Вы можете рассмотреть объект с общей точки зрения». Инкапсуляция добавляет: «Более того, вы не можете рассмотреть объект с иной точки зрения».

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

Encapsulation picks up where abstraction leaves off. Abstraction says, "You're allowed to look at an object at a high level of detail." Encapsulation says, "Furthermore, you aren't allowed to look at an object at any other level of detail."

Continuing with the housing-materials analogy: encapsulation is a way of saying that you can look at the outside of the house but you can't get close enough to make out the door's details. You are allowed to know that there's a door, and you're allowed to know whether the door is open or closed, but you're not allowed to know whether the door is made of wood, fiberglass, steel, or some other material, and you're certainly not allowed to look at each individual wood fiber.
—"Code Complete" 2nd edition by Steve McConnell, перевод: Издательско-торговый дом "Русская Редакция"


И о сокрытии информации:

💬 "Впервые сокрытие информации было представлено на суд общественности в 1972 г. Дэвидом Парнасом (David Parnas) в статье «On the Criteria to Be Used in Decomposing Systems Into Modules (О критериях, используемых при декомпозиции систем на модули)». С сокрытием информации тесно связана идея «секретов» — аспектов проектирования и реализации, которые разработчик ПО решает скрыть в каком- то месте от остальной части программы.

Information hiding first came to public attention in a paper published by David Parnas in 1972 called "On the Criteria to Be Used in Decomposing Systems Into Modules." Information hiding is characterized by the idea of "secrets," design and implementation decisions that a software developer hides in one place from the rest of a program."
—"Code Complete" 2nd edition by Steve McConnell, перевод: Издательско-торговый дом "Русская Редакция"


Таким образом, в команде разработки, где хорошо понимают роль инкапсуляции в управлении сложностью, не может возникать причин, препятствующих использованию ООП в пользу процедурной парадигмы. Обратите внимание, я не говорю о том, что нельзя писать хороших программ без использования ООП, и Niklaus Wirt поясняет почему так.
🔥8
emacsway-log: Software Design, Clean Architecture, DDD, Microservice Architecture, Distributed Systems, XP, Agile, etc.
Разумеется, дело не в самом ООП, как в инструменте, а в его способности поддерживать инкапсуляцию. Мы уже разобрали что такое абстракция. 💬 Когда абстракция нас покидает, на помощь приходит инкапсуляция. Абстракция говорит: «Вы можете рассмотреть объект с…
Целью данного цикла постов является антикризиная архитектура, поэтому, сейчас мы не будем погружаться в подробности истории зарождения OOP, тем более, что на эту тему уже был цикл постов. В контексте нашей цели интересно только то, каким образом OOP может способствовать управлению существенной сложностью. Обратите внимание, что цитаты из "The Mythical Man-Month Essays on Software Engineering Anniversary Edition" by Frederick P. Brooks, Jr. взяты из главы ""No Silver Bullet" Refired", которая является продолжением известной его статьи "No Silver Bullet - Essence and Accident in Software Engineering" by Frederick P. Brooks, Jr.

Иными словами, эти цитаты имеют непосредственное отношение к управлению существенной сложностью.

Простым языком про абстракцию и инкапсуляцию писал Сергей Тепляков (который знаком лично с Bertrand Meyer) в статье "О дружбе значимых типов с ООП":

💬 Абстракция позволяет выделить существенные аспекты поведения, а инкапсуляция является тем инструментом, который позволяет спрятать ненужные подробности и детали реализации с глаз долой.


Далее я приведу формальное определение от Grady Booch, посколько именно его определения значительным образом повлияли на современное OOP.
emacsway-log: Software Design, Clean Architecture, DDD, Microservice Architecture, Distributed Systems, XP, Agile, etc.
Целью данного цикла постов является антикризиная архитектура, поэтому, сейчас мы не будем погружаться в подробности истории зарождения OOP, тем более, что на эту тему уже был цикл постов. В контексте нашей цели интересно только то, каким образом OOP может…
💬 "Abstraction and encapsulation are complementary concepts: Abstraction focuses on the observable behavior of an object, whereas encapsulation focuses on the implementation that gives rise to this behavior.

Encapsulation is most often achieved through information hiding (not just data hiding), which is the process of hiding all the secrets of an object that do not contribute to its essential characteristics; typically, the structure of an object is hidden, as well as the implementation of its methods. “No part of a complex system should depend on the internal details of any other part” [50]. Whereas abstraction “helps people to think about what they are doing,” encapsulation “allows program changes to be reliably made with limited effort” [51].
Encapsulation hides the details of the implementation of an object. Encapsulation provides explicit barriers among different abstractions and thus leads to a clear separation of concerns. For example, consider again the structure of a plant. To understand how photosynthesis works at a high level of abstraction, we can ignore details such as the responsibilities of plant roots or the chemistry of cell walls. Similarly, in designing a database application, it is standard practice to write programs so that they don’t care about the physical representation of data but depend only on a schema that denotes the data’s logical view [52]. In both of these cases, objects at one level of abstraction are shielded from implementation details at lower levels of abstraction.

“For abstraction to work, implementations must be encapsulated” [53]. In practice, this means that each class must have two parts: an interface and an implementation. The interface of a class captures only its outside view, encompassing our abstraction of the behavior common to all instances of the class. The implementation of a class comprises the representation of the abstraction as well as the mechanisms that achieve the desired behavior. The interface of a class is the one place where we assert all of the assumptions that a client may make about any instances of the class; the implementation encapsulates details about which no client may make assumptions.

To summarize, we define encapsulation as follows:

Encapsulation is the process of compartmentalizing the elements of an abstraction that constitute its structure and behavior; encapsulation serves to separate the contractual interface of an abstraction and its implementation.

Britton and Parnas call these encapsulated elements the “secrets” of an abstraction [54].

<...>

Hiding is a relative concept: What is hidden at one level of abstraction may represent the outside view at another level of abstraction. The underlying representation of an object can be revealed, but in most cases only if the creator of the abstraction explicitly exposes the implementation, and then only if the client is willing to accept the resulting additional complexity. Thus, encapsulation cannot stop a developer from doing stupid things; as Stroustrup points out, “Hiding is for the prevention of accidents, not the prevention of fraud” [56]. Of course, no programming language prevents a human from literally seeing the implementation of a class, although an operating system might deny access to a particular file that contains the implementation of a class.

-- "Object-Oriented Analysis and Design with Applications" 3rd edition by Grady Booch, Robert A. Maksimchuk, Michael W. Engle, Bobbi J. Young Ph.D., Jim Conallen, Kelli A. Houston


Смотрите так же статьи в wiki by Ward Cunningham:
- https://wiki.c2.com/?EncapsulationDefinition

- https://wiki.c2.com/?EncapsulationIsNotInformationHiding

- https://wiki.c2.com/?InformationHiding

Обратите внимание, что текст по второй ссылке прямо противоречит статье в Википедии (причем, русскоязычный вариант статьи противоречит англоязычному - в одном варианте свойством языка является инкапсуляция, а в другом - сокрытие), поэтому я стараюсь избегать ссылок на Википедию.
emacsway-log: Software Design, Clean Architecture, DDD, Microservice Architecture, Distributed Systems, XP, Agile, etc.
💬 "Abstraction and encapsulation are complementary concepts: Abstraction focuses on the observable behavior of an object, whereas encapsulation focuses on the implementation that gives rise to this behavior. Encapsulation is most often achieved through information…
Обратимся к первоисточнику термина "сокрытие информации" - к статье "On the Criteria to Be Used in Decomposing Systems Into Modules." by David Parnas:

💬 Information-hiding objects can be created in any language; my first experiments used primitive versions of FORTRAN.


Это противоречит англоязычной версии статьи Википедии о том, что сокрытие информации является свойством ЯП.

💬 When it is applied properly it is usually successful. Abstractions such as Unix pipes, postscript or X-win-dows achieve the goal of allowing several implementations of the same interface. However, although the principle was published 30 years ago, today’s software is full of places where information is not hidden, interfaces are complex, and changes are unreasonably difficult.


💬 While the basic idea is to hide information that is likely to change, one can often profit by hiding other information as well because it allows the re-use of algorithms or the use of more efficient algorithms.


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

Инкапсуляция же отделяет конструкцию от функции. Она защищает интерфейс, который экспонирует поведение, т.е. функцию.

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

💬 The terms "module" and "component" are often used interchangeably, which causes confusion. As I mentioned earlier, any system is composed of components. Therefore, a module is a component. However, not every component is a module. To design a flexible system it’s not enough to decompose a system into an arbitrary set of components. Instead, a modular design should enable you to alter the system by combining, reconfiguring, or replacing its components — its modules.
-- "Balancing Coupling in Software Design: Universal design principles for architecting modular software systems" by Vlad Khononov


В качестве примера модуля Vlad приводит кубик конструктора Lego.

О том, что всякий модуль есть компонент, можно подискутировать по поводу примера с ножницами, но выделим главное: модуль - это о конструкции, компонет - о функции.

Таким образом, отличие между инкапсуляцией и сокрытием информации такое же, как между DIP и DI - второе является способом достижения первого.

💬 Encapsulation is most often achieved through information hiding (not just data hiding).
-- "Object-Oriented Analysis and Design with Applications" 3rd edition by Grady Booch, Robert A. Maksimchuk, Michael W. Engle, Bobbi J. Young Ph.D., Jim Conallen, Kelli A. Houston


💬 InformationHiding should inform the way you encapsulate things
-- https://wiki.c2.com/?EncapsulationIsNotInformationHiding


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

💬 Encapsulation provides explicit barriers among different abstractions and thus leads to a clear separation of concerns.
-- "Object-Oriented Analysis and Design with Applications" 3rd edition by Grady Booch, Robert A. Maksimchuk, Michael W. Engle, Bobbi J. Young Ph.D., Jim Conallen, Kelli A. Houston


Определение encapsulation от автора OO-парадигмы (не путать с автором термина OOP):

💬 Encapsulation means that access to the implementation part of a module is not possible from outside the module, i.e. the implementation of a module is hidden. This means that the usage of a module cannot depend upon internal details of its implementation, and thus it is possible to change the implementation of a module without affecting its usage.
-- "Object-Oriented Programming in the BETA Programming Language" by Ole Lehrmann Madsen, Birger Møller-Pedersen, Kristen Nygaard
🔥1
emacsway-log: Software Design, Clean Architecture, DDD, Microservice Architecture, Distributed Systems, XP, Agile, etc.
Обратимся к первоисточнику термина "сокрытие информации" - к статье "On the Criteria to Be Used in Decomposing Systems Into Modules." by David Parnas: 💬 Information-hiding objects can be created in any language; my first experiments used primitive versions…
Ну и формальное определение абстракции:

💬 Abstraction is one of the fundamental ways that we as humans cope with complexity. Dahl, Dijkstra, and Hoare suggest that “abstraction arises from a recognition of similarities between certain objects, situations, or processes in the real world, and the decision to concentrate upon these similarities and to ignore for the time being the differences” [42]. Shaw defines an abstraction as “a simplified description, or specification, of a system that emphasizes some of the system’s details or properties while suppressing others. A good abstraction is one that emphasizes details that are significant to the reader or user and suppresses details that are, at least for the moment, immaterial or diversionary” [43]. Berzins, Gray, and Naumann recommend that “a concept qualifies as an abstraction only if it can be described, understood, and analyzed independently of the mechanism that will eventually be used to realize it” [44]. Combining these different viewpoints, we define an abstraction as follows:

An abstraction denotes the essential characteristics of an object that distinguish it from all other kinds of objects and thus provide crisply defined conceptual boundaries, relative to the perspective of the viewer.

An abstraction focuses on the outside view of an object and so serves to separate an object’s essential behavior from its implementation. Abelson and Sussman call this behavior/implementation division an abstraction barrier [45] achieved by applying the principle of least commitment, through which the interface of an object provides its essential behavior, and nothing more [46]. We like to use an additional principle that we call the principle of least astonishment, through which an abstraction captures the entire behavior of some object, no more and no less, and offers no surprises or side effects that go beyond the scope of the abstraction.

-- "Object-Oriented Analysis and Design with Applications" 3rd edition by Grady Booch, Robert A. Maksimchuk, Michael W. Engle, Bobbi J. Young Ph.D., Jim Conallen, Kelli A. Houston
2025/07/08 15:33:36
Back to Top
HTML Embed Code: