
Ваша оценкаПредметно-ориентированное проектирование (DDD). Структуризация сложных программных систем
Жанры
Рейтинг LiveLib
- 531%
- 446%
- 321%
- 22%
- 10%
Ваша оценкаРецензии
asmelik12 сентября 2025Книга разочаровала, не рекомендую.
Читать далееПеревод очень хороший.
Был бы отличный, если бы не несколько ошибок.
Но не всегда от серверов приложений удается получить то, на что надеешься. Многие программные продукты не хотят работать как следует, и все тут. (Глава 5, страница 120)"Сервер приложений" - это кривой перевод фразы "business rules engine" (движок бизнес-правил), например Drools, который позволяет изменять бизнес-правила без перекомпиляции приложения.
Создана возможность легко добавлять новые варианты процентов и сборов в виде Графиков начислений (Ассruаl Schedules). (Глава 9, страница 199)Accrual Schedules лучше было бы перевести не как график начислений, а как планировщик начислений.
в данном случае с использованием двойной отправки запроса (Глава 9, страница 212)Здесь вместо фразы "двойная отправка запроса", следует понимать двойную диспетчеризацию (double dispatch). Этот прием описан в паттерне "Посетитель" из книги "Шаблоны проектирования" Эриха Гаммы и компании.
Писать полностью настраиваемые приложения, пригодные для любой организации, не слишком практично. Даже если каждая организация готова была бы платить за "подгонку" приложения под ее нужды, все равно организационная структура имеет тенденцию изменяться. (Глава 16, страница 398)В оригинале автор пишет: "Fully customizing software for each organization is not practical because, even if each organization could pay for custom software, the organizational structure will likely change frequently". Фраза "fully customizing software" переведена как "полностью настраиваемое приложение", но в таком случае у читателя возникает когнитивный диссонанс, когда автор объясняет причину непрактичности использования такого приложения частым изменением организационной структуры. Ведь универсальные приложения, позволяющие гибко конфигурироваться под каждое изменение организационной структуры (типа "1С: Бухгалтерия"), именно для этого и предназначены. Я думаю, что фраза "fully customizing software for each organization" означает разработку специфичного приложения для каждой организации.
Книга не оправдала ожиданий.
Автор создает видимость глубокомысленных рассуждений, за которыми на самом деле скрываются банальные очевидности.
Если стараться сделать программу понятной, наглядной, информативной, предсказуемой в поведении, то абстракция и инкапсуляция станут по-настоящему эффективны. Модели следует факторизовать так, чтобы выделенные в них объекты были просты в использовании и понимании, но тем не менее имели гибкие и развитые интерфейсы. (Глава 10, страница 242)При этом автор не предлагает читателю каких-то конструктивных методов или алгоритмов для факторизации модели предметной области, а просто советует следовать своей интуиции.
Разбивайте элементы архитектуры (операции, интерфейсы, классы и АГРЕГАТЫ) на связные единицы, учитывая свое интуитивное понимание смысловых границ предметной области. Наблюдайте за направлениями изменений и осями стабильности в ходе последовательного рефакторинга, ищите КОНЦЕПТУАЛЬНЫЕ КОНТУРЫ (CONCEPTUAL CONTOURS), по которым происходит расслоение между ними. (Глава 10, страница 235)Автор бесконечно повторяет одни и те же мысли разными словами. Проблема в том, что его мысли не предлагают что-то новое, а просто констатируют очевидные вещи.
Дистилляция это не только примитивное отделение тех или иных частей предметной области от СМЫСЛОВОГО ЯДРА (CORE DOMAIN). В ходе дистилляции эти подобласти совершенствуются, особенно само СМЫСЛОВОЕ ЯДРО, посредством непрерывногo углубляющего рефакторинга. Происходит движение в сторону углубленной модели и гибкой архитектуры. Целью является такая архитектура, которая бы сделала модель очевидной, и модель, выражающая предметную область в самой простой форме. Углубленная модель сама дистиллирует наиболее существенные аспекты предметной области в простые элементы, сочетание которых дает возможность решать важные практические задачи, стоящие перед приложением. (Глава 15, страница 374)В итоге автор пишет, что разбиение предметной области на уровни может помочь, а может и навредить, но конкретных критериев, определяющих необходимость стратификации не приводит, а просто говорит - следуйте своей интуиции. Это сводит на нет всю полезность данного опуса.
Перечисленные пять уровней применимы в целом ряде систем управления предприятиями. Но не во всех предметных областях они способны моделировать ключевые обязанности объектов. В некоторых случаях принудительное приведение архитектуры к этому образцу может сделать только хуже. Но и тогда еще может существовать естественный набор УРОВНЕЙ РАЗДЕЛЕНИЯ ОБЯЗАННОСТЕЙ, соответствующий задаче. Если же предметная область совсем далека от тех, которые мы рассмотрели, то, возможно, придется выбрать совершенно другие уровни. В общем, следуйте своей интуиции, выберите стартовую точку и дайте архитектуре эволюционировать. (Глава 16, страница 394)На протяжении всего повествования автор определяет огромное количество новых терминов, большая часть которых представляют собой либо переименованные чужие идеи, как, например информативные интерфейсы вместо информативных селекторов Кента Бека или фабрики вместо фабричных методов и абстрактных фабрик Эриха Гаммы, либо бесполезные концепции, типа крупномасштабных структур.
Кент Бек уже писал о том, как через имена методов передавать их назначение с помощью ИНФОРМАТИВНОГО СЕЛЕКТОРА (INTENTION-REVEALING SELECTOR) (Глава 10, страница 224)
УРОВЕНЬ ЗНАНИЙ (KNOWLEDGE LEVEL), как и другие крупномасштабные структуры, строго говоря, не является обязательным для применения (Глава 16, страница 401)Вводя все новые и новые термины, автор пытается придать им материальную значимость, используя примеры из реальной практики. Однако, близость примеров к реальности сыграло с автором злую шутку, примеры не столько подтверждают идеи автора, сколько показывают его непрофессионализм. Сюжет всех историй, рассказанных автором, сводится примерно к одному сценарию.
- Группа новых разработчиков приходит в проект, но вместо того, чтобы поинтересоваться у заказчика, а что ему, собственно, надо и зачем ему оно надо, начинает изучать предметную область, рефакторя унаследованный код или читая стороннюю литературу.
- Проходят месяцы работы, появляется какая-то более менее работоспособная версия приложения, но что-то идет не так: разработчикам постоянно приходят какие-то странные запросы от заказчика, которые не вписываются в их представление о реальности.
- В какой-то момент, кто-то из разработчиков решает всё-таки интенсивно пообщаться с носителем знаний о предметной области со стороны заказчика и выясняет, что их представления о том, как должна работать программа, сильно различаются.
- В течение следующей недели разработчики на пределе своих возможностей переписывают всю наработанную за предыдущие месяцы кодовую базу и у них случается "качественный скачек".
Поэтому единственный урок, который можно извлечь из всех этих примеров, только один: поднимите свою задницу из-за компьютера и идите общаться с заказчиком!Если бы автор просто ограничился вводом новой терминологии, то я бы поставил оценку 3. Однако, в процессе описания своего представления об объектно-ориентированном проектировании автор допустил ряд непростительных ошибок, которые привели к снижению оценки до 2 баллов.
Автор навязывает читателю негативное отношение к суррогатным идентификаторам.
Легко пометить каждый объект идентификатором или написать операцию сравнения двух экземпляров, но если эти идентификаторы или операции не соответствуют никакому смысловому аспекту в модели, они только приведут к путанице. (Глава 5, страница 101)
Искусственно же сконструированная идентификация только вводит в заблуждение, портит модель, перемешивает все объекты в одну хаотическую "кашу". (Глава 5, страница 102)Автор вводит читателя в заблуждение относительно невозможности измерения степени внутренней связности и внешней зависимости модулей.
Определения зависимости и связности rрешат уклоном в чисто технические, количественные критерии, по которым их якобы можно измерить, подсчитав количество ассоциаций и взаимодействий. (Глава 5, страница 111)На самом деле, такие метрики существуют и вполне работоспособны, например LCOM (Lack of Cohesion of Methods), Ca (Afferent Coupling), Ce (Efferent Coupling), I (Instability), A (Abstractness), D (Distance from the main sequence).
Автор навязывает читателю ошибочное представление о причинах стремления разработчиков к увеличению внутренней связности в модулях и уменьшению внешней зависимости между модулями.
Человек не может одновременно удерживать в уме слишком мноro предметов (отсюда низкая внешняя зависимость). А плохо связанные между собой фраrменты информации так же трудно понять, как неструктурированную "кашу" из идей (отсюда высокая внутренняя связность). (Глава 5, страница 111)Причина стремления к уменьшению внешней зависимости между модулями в том, чтобы уменьшить и в идеале вообще исключить потребность в изменении одного модуля, при необходимости внесения изменений в другой модуль, что позволяет сократить стоимость разработки и сопровождения программного обеспечения. Возможность человека удерживать в уме слишком много предметов с этим не связана. Уменьшение внешней зависимости кода между модулями происходит путем объединения этого кода в одном модуле, что автоматически увеличивает внутреннюю связность соответствующего модуля. На понимание кода это мало влияет, да и от неструктурированной "каши" тоже не избавит.
Автор использует читателя для рефлексии своих психологических проблем.
В главе 6 на странице 116 автор заявляет, что расскажет про парадигмы моделирования. Вместо этого автор много ноет про сложности использования объектно-ориентированной базы данных и жалуется про трудности применения движка бизнес-правил.
В главе 10 на странице 231 автор много ноет про сложность понимания побочных эффектов функций и расхваливает контрактное проектирования, как средство уменьшения этой сложности, и утверждения, как способ реализации контрактного проектирования, но не показывает как это сделать. Казалось бы в Java же есть ассерты (assert), и вот они те самые утверждения, но не тут то было: автор опять ноет, что во многих современных языках программирования утверждения не поддерживаются и предлагает использовать вместо них модульные тесты.Автор вызывает у читателя неадекватное восприятие агрегации.
СУЩНОСТИ, отличные от корневого объекта, локально индивидуальны, но различаться они должны только в пределах АГРЕГАТА, поскольку никакие внешние объекты все равно не могут их видеть вне контекста корневой СУЩНОСТИ. (Глава 6, страница 120)Автор использует слово "АГРЕГАТ", которое хотя и является производным от слова "агрегация", но совершенно отличается от него по тому смыслу, который вкладывает в него автор. Агрегация описывает слабую связь между сущностями. Жизненные циклы сущностей, связанных отношением агрегации, не зависят друг от друга, в отличие от жизненного цикла объектов в АГРЕГАТЕ, когда удаление корневой сущности означает удаление всех вложенных в него объектов. Такая связь между корневой сущностью АГРЕГАТА и вложенными в него объектами называется композицией.
Автор проявляет некомпетентность при моделировании агрегата в базе данных.
Клиентское приложение нуждается в удобных средствах получения ссылок на существующие объекты предметной области. Если инфраструктура позволяет это делать относительно леrко, разработчики клиента добавляют в модель больше прослеживаемых ассоциаций, загромождая ее. С друrой стороны, они могyт с помощью запросов извлекать из базы данных в точности ту информацию, которая им нужна - например, достать несколько конкретных подобъектов, не обращаясь к корневому объекту АГРЕГАТА. Таким образом операционная лоrика предметной области переносится в запросы и клиентский код, а роль СУЩНОСТЕЙ и ОБЪЕКТОВ-ЗНАЧЕНИЙ сводится к простым контейнерам данных. Техническая сложность реализации всей инфраструктуры доступа к базе данных быстро загромождает код клиента, вынуждая разработчиков урезать и упрощать уровень предметной области. В итоrе модель становится бесполезной. (Глава 6, страница 143)Автор ноет, что база данных позволяет получать подобъекты агрегата не обращаясь к корневому объекту, что естественно сводит на нет все усилия по инкапсуляции бизнес-логики в предметной области перемещая её на уровень запросов и транзакций. Понимает ли автор, что причина этого нытья кроется в несогласованном представлении объекта в модели приложения и в модели базы данных? Недостаточно чтобы объект был агрегатом в приложении, необходимо чтобы он был агрегатом и в базе данных тоже.
В примере "Целостность товарного заказа" главы 6 на странице 128 автор сталкивается с аномалией перекоса записи (write skew) только потому, что он недостаточно точно транслировал Purchase Order из объектной модели в реляционную. В объектной модели автор заявил, что Purchase Order является агрегатом, содержащим объекты Purchase Order Line Item. Это означает, что доступ к объектам Purchase Order Line Item должен осуществляется только через объект Purchase Order. А в реляционной модели автор поместил Purchase Order Line Item в отдельную таблицу, допустив тем самым возможность манипуляций без участия Purchase Order. Если бы автор разместил все объекты Purchase Order Line Item конкретного Purchase Order в одном из столбцов той записи, которая соответствует вышеупомянутому Purchase Order, то он бы получил агрегат в реляционной модели. Это позволило бы автору контролировать соблюдение инварианта Approved Limit, так как объекты Purchase Order Line Item определяли бы состояние объекта Purchase Order не только в объектной модели приложения, но и в реляционной модели базы данных.Автор создает у читателя ошибочное представление о шаблонах проектирования "Фабричный метод" и "Абстрактная фабрика".
Хотя автор и заявляет, что его ФАБРИКА есть реализация шаблонов "Фабричный метод" и "Абстрактная фабрика". Но как выяснится позже, это совершенно не так.
ФАБРИКИ можно проектировать по-разному. В [Паттерны объектно-ориентированного проектирования. Гамма Э., Хелм Р., Джонсон Р., Влиссидес Дж.] подробно разобрано несколько специальных архитектурных шаблонов для создания объектов - FACTORY METHOD (МЕТОД-ФАБРИКА), ABSTRACT FACTORY (АБСТРАКТНАЯ ФАБРИКА) и BUILDER (КОМПОНОВЩИК). Изложение в упомянутой книге касается в основном самых трудных вопросов создания объектов. (Глава 6, страница 135)Для создания экземпляров класса МАНИПУЛЯЦИЯ автор добавляет в этот класс статический метод, который используется просто как обертка над конструктором.
public class HandlingEvent {
public static HandlingEvent newLoading(Cargo с, CarrierMovernent loadedOnto, Date timeStamp) {
HandlingEvent result = new HandlingEvent(c, LOADING_EVENT, timeStamp);
result.setCarrierMovement(loadedOnto);
return result;
}
}
Добавляя МЕТОДЫ-ФАБРИКИ в базовый класс МАНИПУЛЯЦИЯ для каждого типа манипуляций с грузами, мы абстрагируем создание экземпляров и освобождаем клиентский код от необходимости знать внутреннее устройство класса. (Глава 7, страница 163)Это не правда, автор не абстрагирует создание экземпляров класса, добавив в него статические методы, которые создают экземпляры этого класса. Чтобы абстрагировать создание объекта нужно использовать абстрактный метод фабрики объектов, а не статический метод этого объекта. Автор просто инкапсулирует логику создания экземпляра класса в статическом методе этого класса, но к шаблону "Фабричный метод" или "Абстрактная фабрика" это действие никакого отношения не имеет.
Автор вкладывает в сознание читателя крайне вредный совет по организации доступа к связанным сущностям, сохраненным в базе данных.
Что касается постоянных объектов, то для работы с ними не надо использовать запросы к базе данных, если их удобнее находить по цепочке ассоциаций. Например, адрес человека можно узнать из объекта Человек (Person). (Глава 6, страница 143)Это вредный совет, потому что обращения по цепочке ассоциаций между персистентными объектами может породить серию запросов к базе данных. Лучше сразу запросить у базы нужную информацию одним запросом, чем неявно делать несколько запросов, двигаясь по ассоциациям. Лучше запросить у базы данных конкретный объект простым запросом, чем делать сложный запрос с несколькими соединениями по внешнему ключу, чтобы, собрав комплексный объект предметной области, затем выкинуть в мусор большую часть загруженных данных, просто потому, что на самом деле нужна была только небольшая их часть.
Автор порождает у читателя пагубное стремление к объединению объектного и реляционного хранилищ в одном интерфейсе.
В идеале было бы хорошо спрятать от приложения-клиента (но не от разработчика этого клиента) все детали операций, чтобы код клиента оставался одним и тем же независимо от того, хранятся ли данные в объектной базе, реляционной базе или просто в оперативной памяти. (Глава 6, страница 147)Такое стремление к унификации наказуемо урезанием возможностей хранилища до наименьшего общего функционала между объектным и реляционным способом хранения информации.
Автор провоцирует читателя выполнять фильтрацию сущностей на стороне приложения.
При описании шаблона СПЕЦИФИКАЦИЯ в главе 9 на странице 213 автор приводит пример кода, в котором он загружает из базы данных все объекты, перебирает их в цикле и применяет на каждом СПЕЦИФИКАЦИЮ, чтобы определить, будет ли он включен в результат.
public Set satisfyingElementsFrom(InvoiceRepository repository) {
Collection pastDue lnvoices = repository.selectWhereDueDateIsBefore(currentDate);
Set delinquentInvoices = new HashSet();
Iterator it = pastDuelnvoices.iterator();
while(it.hasNext()) {
Invoice anInvoice = (Invoice) it.next();
if (this.isSatisfiedBy(anInvoice))
delinquentInvoices.add(anlnvoice);
}
return delinquentInvoices;
}
Это очень вредный пример не только из-за накладных расходов на передачу лишних объектов между базой данных и приложением, которые можно было фильтровать на стороне базы данных, но и потому, что у автора нет ограничений на количество объектов, которые он загружает в память одним запросом. Со временем при росте количества объектов это приведет к переполнению памяти приложения во время выполнения запроса к базе данных. Автор должен был использовать курсор для последовательного перебора записей в таблице или загружать и обрабатывать объекты пакетами, ограничив количество записей в одном пакете и освобождая память после его обработки.4 понравилось
265
AtNovember1 июня 2023Банда Четырех. Сиквел и приквел :)
Сначала начала читать это книгу, как дополнение к Рефакторингу Фаулера, однако, чем больше продвигалась, глава за главой, тем больше понимала, что лучше эту книгу использовать как дополнение к «Паттернам проектирования» коллектива авторов Э. Гамма, Р. Хелма , Р. Джонсона, Д. Влиссидес (в простонародье GoF).Читать далее
и читать лучше не как учебник, а итеративно, сначала обзорно, а потом отдельно по каждому вопросу. Если кто-то скажет что прочитал книгу от корки до корки и у него не взорвалась голова, значит он просто врет! )))2 понравилось
734
militska1 мая 2022Ещё одна книжка в списке любимых
Читать далееНужная книга для разработчиков крупных систем с большим количеством бизнес логики. Не стоит думать о ней, как о "справочнике по (ненужному)DDD и папочки". Эванс поднимает темы про грамотное разделение бизнес логики, про важность взаимодействия с закзачиками илюдтми из предметной области, объясняет, что методология DDD и тесное сотрудничество разработчиков с бизнесом, помогает строить системы, которые будут легче и более предсказуемо развиваться.
Ведь именно глубокое понимание процессов и тонкостей бизнес процессов, может помочь посмотреть в будущее, и строить систему, готовую к наиболее вероятным изменениям.
К этой книге я подбиралась года 3. И как в ситуации с "паттерны проектирования" Гаммы (GoF), понадобился опыт, что бы осилить, и она показалась интересной, наталкивающей на размышления. Не все главы показались интересными, но большая часть была прочитана не отрываясь.
2 понравилось
943
Цитаты
asmelik2 сентября 20251 понравилось
82
Подборки с этой книгой
Личная библиотека
FANAT1242
- 225 книг
Архитектура программного обеспечения
militska
- 13 книг
Разработка
cijic
- 94 книги
Книги по программированию, которые я когда-нибудь прочитаю
imooncake
- 19 книг
Ящик 103 программирование
oshemkov
- 18 книг
Другие издания




































