# Подход ![Blacjack & hockers](_imgs/bender_header.jpeg) Зачем нам еще один велосипед? # Так исторически сложилось Была необходимость в рефакторинге сложного корпоративного приложения, написанного на Ruby on Rails. Была готовая команда ruby-разработчиков. Методология Domain Driven Development прекрасно подходила для этих задач, но готового решения на используемом языке не было. Не смотря на то, что выбор языка, в основном, был обусловлен нашей специализацией, он оказался достаточно удачным. Среди всех языков, что принято использовать для web-приложений, ruby, на мой взгляд, является самым выразительным. И поэтому больше других подходит для моделирования реальных объектов. Это не только мое мнение. > That is the Java world. Then you have the new-comers like Ruby. Ruby has a very expressive syntax, and at this basic level it should be a very good language for DDD (although I haven't heard of much actual use of it in those sorts of applications yet). Rails has generated a lot of excitement because it finally seems to make creation of Web UIs as easy as UIs were back in the early 1990s, before the Web. Right now, this capability has mostly been applied to building some of the vast number of Web applications which don't have much domain richness behind them, since even these have been painfully difficult in the past. But my hope is that, as the UI implementation part of the problem is reduced, that people will see this as an opportunity to focus more of their attention on the domain. If Ruby usage ever starts going in that direction, I think it could provide an excellent platform for DDD. (A few infrastructure pieces would probably have to be filled in.) > > Eric Evans 2006 К сожалению, за прошедшие 13 лет ничего особо не изменилось. В интернете можно найти попытки приспособить для этого Rails, но все они выглядят ужасно. Фреймворк Rails тяжелый, медленный и не соответствует принципам SOLID. Смотреть без слез, как кто-то пытается изобразить на основе _AсtiveRecord_ реализацию паттерна _Репозиторий_, очень тяжело. Мы решили взять на вооружение какой-нибудь микрофреймворк и доработать его до наших потребностей. Попробовали [Grape](https://github.com/ruby-grape/grape), идея с авто-документированием показалась удачной, но в остальном он был заброшенным и мы быстро отказались от идеи его использования. И почти сразу стали использовать другое решение - [Sinatra](http://sinatrarb.com). Мы до сих пор продолжаем его использовать для REST _Контроллеров_ и _Эндпоинтов_. Если вы разрабатывали web-приложения, то уже имеете представление о технологии. У нее есть свои плюсы и минусы, полное перечисление которых выходит за рамки данной статьи. Но для нас, как разработчиков корпоративных приложений, самым главным недостатком будет то, что REST (это понятно даже из названия) отражает не процесс, а его состояние. А преимуществом будет его понятность - технология ясна как back-end разработчикам, так и разработчикам front-end'a. Но может тогда не ориентироваться на REST, а реализовать свое решение http + json? Если даже вам удасться разработать свой сервисный API, то предоставляя его описание третьим лицам вы получите много вопросов. Гораздо больше, чем если вы предоставите привычный REST. Будем считать использование REST компромиссным решением. Мы используем JSON для лаконичности и [jsonapi](https://jsonapi.org) стандарт, чтобы не тратить время разработчиков на священные войны по поводу формата запросов. В дальнейшем, когда мы будем разбирать _Endpoint_, мы увидим, что для того, чтобы избавится от rest, достаточно переписать всего один класс. Так что REST не должен вообще беспокоить, если остались сомнения на его счет. В ходе написания нескольких микросервисов у нас появились наработки - набор абстрактных классов. Каждый такой класс можно написать за пол часа, его код легко понять, если знать для чего этот код предназначен. Тут и возникли основные трудности. Новые сотрудники, не имевшие дело с практиками DDD и чистой архитектурой, не могли понять код и его предназначение. Если бы я сам увидел этот код впервые до того как прочитал Эванса, я бы воспринял его как legacy, over-engineering. Чтобы побороть это препятствие было принято решение написать документацию (guideline), описывающую философию используемых подходов. Наброски этой документации показались удачными и было решено выложить их на Хабре. Абстрактные классы, которые повторялись из проекта в проект, было решено вынести в отдельный gem. # Философия ![drunk-master](_imgs/drunk_master.jpg) Если вспомнить какой-нибудь классический фильм про боевые искусства, то там будет крутой парень, который очень ловко обращается с шестом. Шест - это по сути палка, очень примитивный инструмент, один из первых, который попал человеку в руки. Но в руках мастера он становится грозным оружием. Можно потратить время на создание пистолета, который не стреляет тебе в ногу, а можно потратить время на обучение технике стрельбы. Мы выделили 4 основных принципа: - Нужно делать сложные вещи простыми. - Знания важнее технологии. Документация понятнее человеку чем код, не следует подменять одно другим. - Прагматичность важнее догматизма. Стандарты должны подсказывать путь, а не устанавливать ограничительные рамки. - Структурность в архитектуре, гибкость в выборе решений. Схожую философию можно проследить например у ОС ArchLinux - [The Arch Way](https://wiki.archlinux.org/index.php/The_Arch_Way_(Русский)). На моем ноутбуке Linux долго не приживался, рано или поздно он ломался и мне постоянно приходилось его переустанавливать. Это вызывало ряд проблем, иногда серьезных вроде срыва deadline по работе. Но потратив один раз 2-3 дня на установку Arch я разобрался с тем как моя ОС работает. После этого она стала работать стабильнее, без сбоев. Мои заметки помогли мне устанавливать ее на новые ПК за пару часов. А обильная документация помогала мне решать новые задачи. Фреймворк имеет абсолютно высокоуровневый характер. Классы, которые его описывают, отвечают за структуру приложения. Для взаимодействия с базами данных, реализации http протокола и других низкоуровневых вещей используются сторонние решения. Нам хотелось бы, чтобы программист при возникновении вопроса мог подсмотреть в код и понять как тот или иной класс работает, а документация позволила бы понять как ими управлять. Понимание устройства двигателя не позволит вам водить автомобиль. # Фреймворк Сложно назвать LunaPark фреймворком в привычном смысле. Frame - рамка, Work - работа. Мы же призываем не ограничивать себя рамками. Единственная рамка, которую мы декларируем, это та, которая подсказывает класс, в котором должна быть описана та или иная логика. Это скорее набор инструментов с объемной инструкцией к ним. Каждый класс - абстрактный и имеет три уровня: ```ruby module LunaPark # Фреймворк module Forms # Паттерн class Single # Реализация/вариант end end end ``` Если вы хотите реализовать форму, которая создает один элемент, вы наследуетесь от данного класса: ```ruby module Forms class Create < LunaPark::Forms::Single ``` Если несколько элементов, воспользуемся другой _Реализацией_. ```ruby module Forms class Create < LunaPark::Forms::Multiple ``` На данный момент не все наработки приведены в идеальный порядок и гем находится в состоянии альфа-версии. Мы будем приводить его поэтапно, согласованно с выходом статей. Т.е. если вы видите статью про `ValueObject` и `Entity`, то эти два шаблона уже реализованы. К окончанию цикла все они будут пригодны к использованию на проекте. Поскольку сам по себе фреймворк малополезен без связки с sinatra \ roda, будет сделан отдельный репозиторий, который покажет как все "прикрутить" для быстрого старта вашего проекта. Фреймворк является прежде всего приложением к документации. Не стоит воспринимать данные статьи как документацию к фреймворку.