What I’ve learned about DDD since the book

Не далее как на прошлых выходных побывал на тренинге Patterns and Practices of Effective Domain Modeling, который вел Dino Esposito. Тренинг понравился, хотя я и не узнал фактически ничего нового. Ну это я сам виноват, так как давно копаю эту тему и много уже всякого переслушал и перечитал. Так вот, на этом тренинге на одном из слайдов была ссылка на выступление Эрика Эванса (Eric Evanse), где тот рассуждал на тему, как бы он переписал книгу «Domain Driven Design. Tackling complexity in the heart of software». Я посмотрел это выступление и оно в целом очень интересное. Вообще мне нравятся темы, когда инициаторы каких-то идей, через несколько лет пишут или говорят о том, как они бы сейчас изменили свою книгу\концепцию. Это наверно наталкивает на мысли, что же наиболее важно оказалось. Второстепенные вещи редко поддаются сильным изменениям.

В общем, советую посмотреть тоже выступление What I’ve learned about DDD since the book

На сегодня это все =)

Hard’n’heavy!

Непрерывное тестирование с Mighty Moose

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

Обычный цикл разработки с помощью ТDD подразумевает использование подхода Red-Green-Refactor, который конечно же работает хорошо и при одного теста и знании горячих клавиш достаточно производителен. Однако, если затрагивается сложный функционал, то при рефакторинге кода могу затрагиваться самые разные тесты и тогда приходится вручную запускать все тесты, дабы убедится что ничто не сломано и все работает как планировалось. Вот это действие уже накладное и может вызывать большие потери времени разработчиков при запуске всех тестов и ожидании результатов, даже если предположить, что все тесты написаны качественно и проходят очень быстро.

В этой ситуации на помощь приходит Mighty Moose с подходом continuous testing (непрерывное тестирование). Мне логичным появление такой системы, с учетом того, что до этого набрали популярность и оправдали свое существование техники непрерывной интеграции и непрерывной доставки. Mighty Moose действительно оправдывает инсталляцию и занимаемую оперативную память.

Подробнее

Domain, Context & Integration (DCI)

Относительно недавно на хабрахабре попалась статья Data Context Interaction (DCI) — эволюция объектно-ориентированной парадигмы, которая меня весьма заинтересовала описанным подходом, но примеры в ней были тупо скопированы с оригинальных публикаций 3х годичной давности или около того. Вообще все статьи по теме оперируют одним и тем же примером, который, на мой взгляд, не до конца раскрывает тему и все плюсы использования DCI. Но это общая проблема интернетов, даже уже говорить про это не хочется.

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

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

Проблема

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

На картинке показана системная операция четырех объектов, общающихся между собой. В данном случае Message это вызов метода или функции.

Рассмотрим второй возможный сценарий работы с теми же объектами:

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

Выше были представлены две системные операции выраженные в Use Case 1 и Use Case 2. Как мы их отображаем в коде? В идеальном случае, я бы хотел иметь возможность открыть один файл и понять модель взаимодействия объектов в сценарии использования, над которым я работаю. Если я работаю над Use Case 1, я ничего не хочу знать про Use Case 2. Вот что я считаю успешным отображением сценариев использования в коде.

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

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

Подробнее

DDD & TDD. Часть III

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

  • Как пользователь будет вводить данные;
  • Как данные будут сохраняться/загружаться.

Домен по природе и задумке своей должен быть полностью независимым и работать независимо от того, как построено взаимодействие с пользователем (WPF, WinForms, Web) и как реализован слой данных (MSSQL, MySQL, Oracle и т.д.).

Слоеные пироги

В этой части мы плавно подходим к тому, что приложение должно быть многослойное. Как минимум:

  • Домен – слой бизнес-логики. В котором описано КАК работать с данными.
  • Слой данных. В этом слое осуществляется сохранение объектов во внешние ресурсы и восстановление из внешних ресурсов в доменные объекты. Выделением этих операций в отдельный слой мы делаем приложение более гибким, т.к. можно осуществлять работу с несколькими БД, меняя их, а приложение этого даже не заметит.
  • Слой представления. В этом слое мы говорим приложению ЧТО делать с данными, т.е. вызываем в нужном порядке доменные сервисы и отдаем результат вычислений на прорисовку. Таким образом, этот слой связывает Домен и Front End.
  • Пользовательское отображение (Front End). Это пользовательский интерфейс, может быть чем угодно: консолью, win forms, web, да хоть сразу в мозг! =) Этот слой должен быть максимально «тупой», тут недолжно быть никаких изменений данных, никакой логики, как и что показывать. Слой просто делает все что ему скажут без капли самодеятельности.

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

Подробнее

DDD & TDD. Часть II

Диспозиция

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

Доменные сервисы

Допустим, в условиях к программе сказано,  что вам

надо определять количество классов на заданный год обучения (сколько 5ых классов или 9ых) и сколько учеников в параллели.

Подумаем, какие классы и что у нас знают:

  • «Школа» знает сколько всего вообще классов;
  • «Класс» знает сколько в нем учеников.

Кажется больше нам и не надо. Как бы я сделал на заре своего обучения? Я бы в класс School добавил метод

Но это плохой подход по следующим причинам:

  • У класса School увеличивается ответственность что приводит к высокой связности классов;
  • Его становится труднее поддерживать и изменять;
  • Это так же может привести к дальнейшим проблемам тестирования.

Подробнее

DDD & TDD. Часть I

Disclaimer

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

Магические аббревиатуры

DDD – Domain Driven Design, если совсем вкратце, то это способ организации кода приложения. А организуется он таким образом, чтобы в единственной, независимой ни от чего в проекте сборке, лежала сама суть приложения.

TDD – Test Driven Development, проектирование приложения через тесты.

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

По DDD и TDD написано уже куча литературы различных форматов и объемов. Где-то проще, где-то запутаннее.  Исторический экскурс благополучно пропустим, кому интересно, могут погуглить книги Эрика Эванса и посетить сайт Мартина Фаулера.  Я постараюсь донести свое видение этого предмета максимально просто и доступно. Рассказать, как это помогает, работает, сопровождается и развивается.  Надеюсь, у меня все получится. =)

Но это все вкратце, теперь перейдем к более детальному рассмотрению.

Подробнее