Комментарии 29
Показывайте настоящие примеры. Желательно, не из мира продаж, где весь процесс тривиален и всем известен.
В мире продаж, где есть слово "скидка", процесс тривиален и всем известен?
Настоящая же боль происходит в тот момент, когда часть участников не знает части слов или использует их неправильно.
Я сейчас подумал о примере… Предположим, мы делаем face recognition. Есть эксперт по нейронным сетям и линейной алгебре, есть эксперт по криминалистике, есть эксперт по программированию (хехе), DBA, сисадмина даже как devops'а притянули.
… Теперь, представим, что у нас всплывает проблема: классификационная сеть не может правильно начать работать, потому что микросервис, вычисляющий эйгенвекторы для разреженных матриц использует неправильную локаль при записи ответа в json из-за того, что переменные среды окружения на машине для автоматизированной сборки undercloud'ных image'ей запускаются из-под пользователя у которого локаль случайно была настроена в нетривиальное значение по geoip потому что при вендоринге кукбуки шефа забыли припинить версию (а в новой революция и geoip).
… Скажите, какова вероятность, что эта проблема будет правильно сформулирована (как написал выше) любым из участников процесса?
Спец по нейронным сетям: эйгенвекторы неправильные
Сисадмин (который должен догадаться, что запятая вместо точки это зло) угу, да, и?
Сисадмин: кривой пининг вендоринга кукбуки и в одном из регионов у нас по геоip прилетает локальная локаль на андерклаудный imagebuilder.
Спец по нейронным сетям (который должен догадаться, что json на входе кривой): угу, да, и?
Это я ещё не приводил пример, когда никто в команде не знает как назвать эту very very thingy thing with do things with things to make things do things.
Ретроскидка тоже знакомая (и тривиальная) вещь?
Сисадмин: кривой пининг вендоринга кукбуки и в одном из регионов у нас по геоip прилетает локальная локаль на андерклаудный imagebuilder.
Не, такого точно никогда в продажах не бывает.
- Скидка по фактуре в процентах
- Ценовое соглашение отличное от базового
- Ретробонус
- Поставки бесплатного товара
Кейсы могут комбинироваться. Поэтому вариантов того, что может скрываться под словом скидка n!(4).
(Не в плохом смысле, я даже скорее одобряю) Мне внезапно поплохело(автоматом) и появился нервный смешок от того, что я увидел код на C# на русском(точнее названия).
Так что вы правы — эти предрассудки...
Я понимаю, что доклад был больше про суть и про людей(стратегию), а не про подходы к реализации(хоть и об этом тоже говорили). Но интересны и технические подробности.
По поводу связности: (вольный перевод) вы говорили, что при работе разработчиков над архитектурой график связности объектов стремится к нулю и (очевидно) не может им быть достигнут. Говорится также с точки зрения прагматика о "минимальной связности", который достижим(в примерах это были интерфейсы).
(Я понимаю что это пример, но я сейчас говорю о примере как реальном кейсе)
В моем понимании на практике даже такой способ, когда интерфейс выносится в Layer_1, а Layer_2 его реализует(и мы общаемся с Layer_2 через интерфейс, который находится в Layer_1), ведет к сильной связности, т.к может вполне меняться Layer_2, а за ним должны поменяться интефрейсы(в том числе и интерфейс в Layer_1). А изменения интерфейса влечет изменение реализации Layer_1, ибо он использует тот самый интерфейс.
Да, есть соглашение о том, что когда такие вещи происходят, то меняется реализация, а интерфейс класса(назовем его контрактом) не менятеся(т.е публичный методы не меняются, меняются только private). Но опять же случаи бывают разные и далеко не всегда удается избежать этой цепочи.
Вопрос: какой уровень связности вы в продакшене считаете приемлемым(что работает для вас)?(пример есть пример) И я понимаю ответ то, что работает для меня, то и хорошо. Но вопрос состоит том, как именно Вы боретесь с подобным. Что считаете идеалом минимальной связности(скорее теоретический и недостижимый). Про DSL слышал, но все имеется ввиду возможно реализуемый на практике, но не достижимый по каким-либо причинам (денежным, временным и т.д), конечно в рамках адекватного.
P.S. И да, как писал amarao выше. По-моему мнению, Очень серьезную когнитивную нагрузку несет в себе объяснение архитектурный подходов на простых примерах. Я понимаю, это доклад, времени мало и донести мысль нужно. Мне всегда казалось, что необходим серьезный большой проект с вкраплением вики и ссылками на фрагменты кода для пояснения той или иной точки зрения. Не видели ли вы подобного проекта на просторах необъятного интернета?(именно по DDD) Если нет такого, не хотели бы начать разработку сложного open-source проекта, который показывал сложное на сложном? Если да, то не против к нему присоединиться.
2. Про разнесение интерфейсов по слоям: тут важно понимать, где начало графа, а где конец. И, соответственно, кто (какой слой) диктует изменения, а кто подстраивается. Если интерфейс в доменном слое, а реализация в инфраструктуре, то от изменения инфраструктуры интерфейс в домене меняться не должен. Потому что он описывает доменную логику, причина для изменения которой — бизнес-процессы. Понятно, что в реальном мире бывает по-другому (например, были все методы синхронными, а стали асинхронными), тогда да, придется по всей вертикали проводить изменения.
3. Про примеры. На самом деле есть ровно один способ посмотреть на серьезный большой проект: пойти работать на такой проект. Вариант немного хуже — читать книги. Книжный объем уже позволяет обрисовать довольно масштабную картину, хотя до реального проекта все равно будет далеко. Еще как вариант мастер-классы от мэтров типа тех же авторов книг. В интернетах нормальных примеров я не встречал. Там обычно загоняются на тактические паттерны, но без реальной предметной области и соответствующих процессов они не имеют смысла (с точки зрения ддд). С опен-сорсом (а точнее с крауд-сорсом, вы же это имеете в виду, да?) та же проблема: нету тех самых бизнес-задач и бизнес-процессов, от которых отталкивается разработка в коммерческих проектах.
Гипотетически интерфейс в layer1 предназначен не для "показать все возможности layer2", а для обслуживания интересов layer1. Поэтому он поменяется только тогда, когда изменятся потребности layer1, как бы ни менялся layer2. Нет здесь сильной связности. Не должно быть.
Практически, на этапе экспериментов, если мы ещё не поняли задачу, или если задача изменяется по ходу, или если мы определяем потребности через возможности — тогда да, слои потребностей и возможностей испытывают сильное взаимовлияние и взаимопроникновение.
Но по мере конкретизации целей границы обретают очертания, и их реализация в коде уже начинает нести больше пользы, чем боли и нелепых телодвижений. И вот тут уже надо тщательно убирать из интерфейса всё то, что определяется в layer2, оставляя в нём только задачи и определения из layer1. И аминь, всё по классике и на пользу делу.
Но надо понимать, что есть определённое предубеждение против русского языка в среде не 1С-программистов, и понимать, что это именно предубеждение.
Какое ещё предубеждение? Я ничего не имею против русского языка в коде, я имею много чего против предложения переключать язык каждый раз, как понадобилось написать ключевое слово. Я не хочу мучительно вспоминать, где у меня сейчас точка с запятой и куда жать, чтобы на экране появилась двойная кавычка. Или одинарная. Чем в первую очередь хороша работа на англоязычного заказчика? Да тем, что раскладку нужно переключать только, когда заходишь в чатик к друзьям. Ну, или на хабр.
То есть всё зависит от специфики того, с чем вы работаете: если у вас задачка тривиальная вот именно с точки зрения программирования, главное — уметь выпытать из заказчика чего он, собственно, хочет — то можно использовать русские имена: C#, Java и даже C++ (по крайней мере clang) их понимают. Но вот тот факт, что у вас после этого возникнут сложности с использованием stackoverflow… об этом не стоит забывать…
Подготовка MCVE в таких условиях окажется сложнее, чем попытки понять «что происходит» самому — и, главное, большой шанс, что поиск похожих, уже отвеченных, вопросов находить не будет.
То есть пишете «зкшмфеу», а оно само превращается в private.
А потом пишете cf[hfybnm, а обратно оно не возвращается. Или возвращается, но не всегда, или переключается в неподходящий момент. В общем проблемы с переключением никуда не денутся.
Немножко вставлю свои пять копеек.
берём какую-то часть реального мира, бизнес-процесса, и превращаем её в код, то есть строим программную модельНу, не знаю… Весьма распространённый взгляд на то, чем мы занимаемся, но это никак не уменьшает его ущербность. Чтобы понять, в чём подвох, взгляните на аналогичное рассуждение: берём доску и гвоздь, и превращаем их в молоток, то есть в натурную модель доски и гвоздя. Абсурд ведь, разве нет? Модельерский подход к проектированию систем не менее абсурден, просто его бредовость мы привыкли не замечать.
Моделирование как вспомогательный инструмент мы, конечно, все применяем. Порисовать квадратики со стрелочками в разных нотациях — святое дело. Пользуясь приведённой аналогией, нам при создании молотка полезно понимать, как гвоздь может быть загнан в доску. Но боже упаси буквально переносить модель в программную систему. Программа, предназначенная для удовлетворения каких-то нужд, не является ни самими этими нуждами (точно так же, как молоток не является гвоздём), ни ситуацией удовлетворения нужд. Это самостоятельная сущность. Инструмент. И части этого инструмента совсем не обязаны один-в-один логически мэппиться на предметную область. Что-то, конечно, естественным образом смэппится, но что-то и нет. Это абсолютно нормально.
Мне, например, неоднократно удавалось выкручиваться из сложных ситуаций при помощи дизайна, основанного на метафорах (MDD?). То есть не пытаемся «отразить» в программе сущности реального мира (это всё равно невозможно, потому что реальный мир бесконечно разнообразен, холистичен и постоянно изменчив), а задумываемся над тем, какими инструментами пользователю было бы понятно, как решать его задачи. Текстовый редактор, например, использует метафору (не модель!!!) листа бумаги, мэйл — метафору почтового ящика, файловая система — полки с папками.
И ещё маленький момент. При использовании всяких модных методик дизайна самое главное — не скатиться в Pattern Driven Design. Невозможно думать книжкой готовых рецептов. Думать можно только головой.
Давайте немножко посмотрим на примеры, приведённые в докладе. Классический модельный подход подразумевает, что мы должны построить модель предметной области и заложить её в конструкцию создаваемой системы. Допустим, при исследовании задачи у нас нарисовались понятия «Speaker», «Talk», «Event». В нашей модели это у нас классы объектов. Объект — это некая сущность, «живущая» внутри системы, имеющая некие свойства и обладающая неким поведением. То есть в реальном мире спикеры делают толки на эвентах, и внутри программы есть тоже «спикеры», «делающие» «толки» на «эвентах». Считается, что чем точнее объекты программы повторяют (обычно говорят «отражают») поведение объектов реального мира, тем полезнее программа, но это справедливо только для симуляторов. Имитационная модель — да, она как раз предназначена для того, чтобы прогнать ситуацию внутри компьютера, и для имитационной модели действительно важно, чтобы объекты в программе «отражали» объекты реального мира. Теперь ответьте честно, много ли из того, чем приходится лично Вам заниматься, является имитационными моделями в полном классическом смысле этого понятия? Вангую, что примерно 0%. Это очень узкая ниша, хоть и весьма уважаемая.
Даже если заходить на задачу со стороны структуры базы данных, гораздо полезнее оказывается не пытаться своими таблицами воспроизводить реальный мир, а озаботиться поиском ответов на вопросы типа таких:
— Какого рода факты мы желаем хранить в своей базе?
— О чём эти факты? (именно из ответов на такие вопросы у нас появляются entities)
— Как эти факты между собой логически связаны? (здесь у нас появляются constraints)
— Как должен быть организован процесс добавления фактов в базу?
— Какие производные факты мы желаем получать на основе первичных?
(Можно заметить, что здесь у нас базовым понятием странным образом является не «объект», а «факт». Впрочем, ничего удивительного, ещё со времён старика Кодда математической основой баз данных служит исчисление предикатов, которое по своей сути не про объекты, а про факты.)
Если мы занимаемся моделированием, то сразу нас выносит на то, что Speaker имеет фамилию и имя, а Talk имеет дату/время. И мы радостно запихиваем атрибуты в таблички. А потом оказывается, что спикером может быть компания, которая пока не решила, кто конкретно из её сотрудников будет докладываться. А рядом с докладом появляются такие реально отсутствующие в грешном физическом мире вещи, как «отмена», «перенос», «замена» (уведомление об отмене в реальности существует, а сама отмена — как-то не очень). И нам, оказывается, полезно вместо атрибута TalkDateTime таблицы Talks иметь отдельным потоками назначения, переносы, замены и отмены, а TalkDateTime вычислять на их основе.
Когда у нас первичны модели и их объекты, мы обречены вляпаться в не имеющую ни одного до конца нормального решения проблему ORM, об которую вся индустрия убивается уже несколько десятков лет. А если отречься от глупостей (ну или хотя бы снизить уровень догматичной упёртости в них), то можно помочь себе тем, что взглянуть на вопрос с альтернативного ракурса. Например, вместо ORM поиметь ROM. То есть база — это набор фактов, а в набор объектов она транслируется в зависимости от угла зрения. То есть факт «Алексей Мерсон далает доклад про ДДД продолжительностью 1 час» оказывается реляционно-объектно отмэппленым на объекты «Алексей Мерсон», «доклад про ДДД», и ещё на расписание эвента. С какой стороны на набор фактов посмотрели, такой набор объектов получили.
Ой, что-то я слишком много ереси написал… ;)
Можно провести параллель с функциональным стилем в программировании, где функция — это тоже объект.
Вообще, мне кажется, в своей основе DDD — не только и не столько про моделирование, сколько про учёт контекстов при работе с понятийным аппаратом. Весьма здравая, кстати, идея.
Если DDD — это моделирование, то почему оно тогда не DDM? Откуда тогда там слово «дизайн»?
Жаль, что мне так и не удалось донести светлую мысль, что моделирование и дизайн — это совсем разные вещи. Что первое может быть подпроцессом второго, а может и наоборот. Народ привык трактовать понятие «моделирование» глобально, смешивая в одну кучу вообще всё. Даже пример с гвоздём, доской и молотком не помогает, хотя казалось бы куда нагляднее :(
На мой вкус реляционный подход универсальнее, а если ещё и все связи изначально проектировать как n:n, то сломать структуру новыми бизнес-требованиями практически нереально, как и добиться достойной производительности потом, так что каждый раз компромисс.
Помимо понятия «фактов» я использую ещё и «бизнес-сущности»: всё, что в требованиях (сценариях) существительное — бизнес-сущности, глаголы — факты. У фактов кстати всегда есть timestamp — действие происходит однократно и в конкретный момент времени. Бизнес-сущности зато должны иметь версии (была госпожа Иванова, стала — Петрова, и отчётность в прошедших периодах не должна уехать).
Пример с 1С очень хороший. Сам по малолетке считал программирование на русском языке полным «зашкваром», но только после этой книги понял, насколько это правильно в русскоязычной предметной области программировать на русском. Единственная проблема — постоянное переключение раскладки. Напрягать будет.
p.s. Шутка про сиськи неудачная, я бы даже сказал глупая и пошлая. Но она и не зашла — в зале никакой реакции, несмотря на ожидание докладчика. Он даже взял паузу.
интересная статься. начинаю читать Синию книгу и вот размышления нужно ли это вообще привели меня сюда. Луковую архитектуру впервые увидела у Роберта Мартина "Чистая архитектура", он тоже топит за то, чтобы доменная логика была независима. Паттерн Separated Interface у него называется Dependency Inversion и он широко его применяет и показывает на разных уровнях от кода до архитектурных решений.
Domain-driven design: рецепт для прагматика