Поскольку идея данного поста родилась у меня независимо от эпопеи с хлебопекарней, хочу вставить и свои пять копеек.
Итак, суть проблемы — поставить программный код в соответствие с бизнес-требованиями. Существуют замечательные методологии и техники, например, Behavior Driven Development (BDD), которые позволяют в декларативном стиле описать требуемое поведение системы (тесты).
Возникает вопрос — зачем описывать как должен работать код, если можно и сам код написать в этих терминах. Почему user story не может быть самой программой.
не код должен генерироваться из модели — модель должна быть кодом
Чтобы не томить читателей сразу перейду от слов к делу. Представим себе язык для программирования вот такого робота:
Warning! Данный пример служит только для иллюстрации идеи и не предназначен для приготовления пищи в реальной жизни. Автор не несет ответственности за вред здоровью нанесенный в результате употребления пищи, приготовленной с помощью данного примера.
пирожки_с_картошкой:
жаренный_лук:
взять лук 2шт
порезать
пожарить
вареная_картошка:
взять картошка 7шт
почистить
сварить
добавить в вареная_картошка
взять соль 0.5чл
взять сливочное масло 50г
начинка: смешать вареная_картошка и жаренный_лук
тесто: смешать
взять мука 500г
взять сливочное масло 50г
взять вода 200г
взять соль 0.5чл
лепешки: сформировать тесто 20шт лепешки
сырые_пирожки: добавить в лепешки начинка
пирожки: испечь сырые_пирожки 200С
Теперь серьезно
Есть замечательная методология — Domain Driven Design. Какое то время я считал что это лучшая на сегодняшний день методология разработки бизнес-приложений. Разработка сущностей, агрегатов и т. д. (классов) — увлекательный процесс, похожий скорее на интеллектуальное развлечение.
Все хорошо когда речь идет о статических вещах, но — у Эванса в книжке (если я не ошибаюсь) нет ни одной диаграммы workflow, ни одной схемы бизнес-процесса.
И действительно, есть классы, есть сервисы, репозитарии и т.д., все красиво — но куда деть саму бизнес-логику, как с ней поступить. Напомню, что бизнес-логика, это и есть то, ради чего, собственно, существует приложение. Реальность разработки сегодняшнего дня в том, что слишком много кода не имеет отношения к решаемой задаче, и, что хуже, этот инфраструктурный код жестко перемешан с бизнес-логикой (в частности, если мы используем парадигму Anemic Domain Model (Data-driven development)
Есть две вещи в методологии DDD, с которыми я на все 100% согласен:
- Необходимость в ubiquitous Language – едином «стандартном» языке (терминологии) для взаимопонимания специалистов в предметной области и программистов
- Отделение бизнес-логики от инфраструктуры (репозитории, сервисы, POCO, классы, аттрибуты, сериализация и т. д.). Атрибут [DataContract] не имеет никакого отношения к бизнес-логике, как и ВыгулМенеджер для собак не соответвует терминологии бизнес-логики
Очевидная идея — это отделение бизнес-логики от инфрастуктурного уровня с помощью специализированного языка программирования (DSL) который бы содержал только термины, специфичные для бизнес-процесса (термины ubiquitous Language). Этот язык и есть Business Natural Language (BNL) – это DSL, ориентированный на конкретную проблемную область (domain) в смысле отраслевых бизнес-процессов (приготовление пищи, перекачка нефти и т.п.).
Я пришел к этой идее «независимо», просто рассуждая на тему организации кода. Обсуждения на Хабре и множество других материалов в интернете показывают, что идея, в общем то, действительно очевидна.
Собственно — сам источник термина Business Natural Languages — bnl.jayfields.com
Что мы получаем:
- UML модель, user story, реализация, behavior описание для тестов — все это теперь единое целое
- реализация бизнес-логики предметной области надежно отделена от инфраструктурного кода
- кодировать бизнес-логику теперь может не только программист, но и специалист в предметной области, не знакомый с программированием
- накопленная бизнес-функциональность не теряется при переносе системы на любую платформу (ее даже не надо портировать)
- не играет роли как именно реализован dsl «под низом» (это могут быть классы, код в функциональном стиле, expression trees и т.д.)
Видение светлого будущего
В простейшем случае BNL может быть реализован в виде набора функций (методов) с использованием fluent паттерна
см. пример ниже
или пример Как пекут хлеб программисты на Haskell (В процессе его написания мы легко и непринужденно строим модель предметной области, фактически просто делая перевод с русского на Haskell. Безо всяких там наследований, рефакторингов и UML)
или Пример использования fluent interface в java для описания объектов предметной области
такого рода материалов очень много
Кстати, в рамках данной парадигмы вырисовываются некоторые особенности Javascript/Java/C#/etc и CoffeeScript/Ruby/Python/etc стилей синтаксиса. Первый — более «жесткий», возможно, больше подходит для инфраструктурного кода, второй — более «человечный», больше подходит для описания бизнес-логики.
Но — это не совсем то что мы хотим, так как мы все еще привязаны к определенному языку программирования общего назначения (будь то Haskel, Java, CoffeScript etc.) в плане синтаксиса, кроме того, что важнее, нам доступен весь контекст, таким образом все еще возможно перемешивание с инфраструктурным кодом или написание некорректного с точки зрения бизнес-логики кода.
Идеальный вариант — это специализированный язык, наподобие описанного в начале этой статьи. На данный момент существует достаточно много фреймворков, позволяющих написать свой язык программирования (список, видимо, не исчерпывающий – см. ссылки в конце)
- Ruby
- Go
- Boo
- Visualization and Modeling SDK от Microsoft
- ANTLR
- Irony
- XText
- ...
Резонно, задать вопрос о целесообразности разработки языка с учетом трудозатрат. Хотя во многих случаях это не так сложно как кажется, я вижу наиболее перспективный путь в разработке отраслевых языков. Некий язык может стать стандартом для описания финансовых и бухгалтерских операций, другой — для CRM функциональности и т. д. На самом деле этот процесс уже давно идет, так как во многих отраслевых программных продуктах существуют внутренние языки макросов для реализации специфичной для этой отрасли бизнес-логики.
Вот цитата с которой я, в общем то, согласен:
Общий тренд в индустрии ИТ уже много лет — исключить программиста там где это можно, за счёт большей гибкости самой системы. Просто потому что программист-профессионал стоит дорого, и занимается только программированием.
Взять тиражируемую систему, лучше даже на основе свободных компонентов, привлечь человека из предметной области, который сколько нибудь понимает или может разобраться — и не платить дорогущей команде программистов.
Итак, что еще нам может пригодится? Мощная IDE — будет огромным плюсом. Например, с помощью чего то подобного Type Providers в F# можно организовать intellisence который будет выводить, например, список существующих продуктов для приготовления. Плюс визуализация в виде диаграмм и т.д.
Хочу обратить внимание, что языки типа PowerShell, jQuery или Jetfire (язык для описания workflow) и т.д. — это хоть и dsl, но все же языки общего назначения, не специфичные для описания бизнес-процессов (для чего мы и вводим термин BNL).
Бонус
Я буквально в течении получаса набросал пример «кухонного» языка на CoffeeScript:
class root.Пирожки_с_картошкой extends Рецепт
constructor: () ->
super "Пирожки с картошкой"
Приготовить: () ->
жаренный_лук = @пожарить @порезать(
@взять "лук", "2шт"
)
вареная_картошка = @сварить @почистить @взять "картошка", "7шт"
@добавить( вареная_картошка, [
@взять "соль", "0.5ч/л"
@взять "сливочное масло", "50г"
] )
начинка = @смешать [вареная_картошка, жаренный_лук]
тесто = @смешать [
@взять "мука", "500г"
@взять "сливочное масло", "50г"
@взять "вода", "200г"
@взять "соль", "0.5с/л"
]
лепешки = @сформировать тесто, "20шт", "лепешки"
сырые_пирожки = @добавить лепешки, начинка
пирожки = @испечь сырые_пирожки, "200С"
(Если что — просьба на бить по почкам, так как это мой первый код на CoffeeScript. Исходники.).
Он почти ничего не умеет — только выводить список необходимых продуктов и инструкцию по приготовлению.
Рецепт Шаг-1: взять лук 2шт Шаг-2: порезать шаг-1 Шаг-3: пожарить шаг-2 Шаг-4: взять картошка 7шт Шаг-5: почистить шаг-4 Шаг-6: сварить шаг-5 Шаг-7: взять соль 0.5ч/л Шаг-8: взять сливочное масло 50г Шаг-9: добавить шаг-6 шаг-7,шаг-8 Шаг-10: смешать шаг-6,шаг-3 Шаг-11: взять мука 500г Шаг-12: взять сливочное масло 50г Шаг-13: взять вода 200г Шаг-14: взять соль 0.5с/л Шаг-15: смешать шаг-11,шаг-12,шаг-13,шаг-14 Шаг-16: сформировать шаг-15 20шт лепешки Шаг-17: добавить шаг-16 шаг-10 Шаг-18: испечь шаг-17 200С Ингредиенты лук 2шт картошка 7шт соль 0.5ч/л сливочное масло 50г мука 500г сливочное масло 50г вода 200г соль 0.5с/л
Очевидно, что достаточно легко можно добавить вычисление «критического пути» и т.п., не говоря уже о «счетчике калорий» и т.д.
Мы все еще не избавились от специфичного синтаксиса и грамматики языка, также это не на 100% песочница. Однако, пример показывает, что создание простого BNL — не такая уж сложная вещь.
Ссылки
Собственно — сам источник термина
Business Natural Languages — bnl.jayfields.com
Business Natural Languages Development in Ruby
Domain Driven Design
domaindrivendesign.org
Введение в проблемно-ориентированное проектирование
Учимся проектировать на основе предметной области (DDD: Domain Driven Design)
Парадигмы программирования. Data Driven vs Domain Driven
Введение в Rich Domain Model
Behavior Driven Development (BDD)
Википедия
behaviour-driven.org
Specification By Example – BDD для прагматиков
Создаем NUnit тесты в BDD стиле
BDD наоборот
Практика TDD/BDD на примере JavaScript: TDD и BDD
Разработка DSL
Ruby
Building a DSL in Ruby
Expressing Contract Terms in a DSL
Visualization and Modeling SDK
MSDN
Domain-Specific Development with Visual Studio DSL Tools
ANTLR
antlr.org
The Definitive ANTLR Reference: Building Domain-Specific Languages
Boo
DSLs in Boo: Domain-Specific Languages in .NET
Xtext
eclipse.org/Xtext
Irony
Codeplex
Writing Your First Domain Specific Language
Книга Фаулера
Domain-Specific Languages (Addison-Wesley)
Косвенно связанные с данной статьей
Как два программиста хлеб пекли
Светский разговор об управляемой тестами выпечке
Хлеб Маркуса и YAGNI
Как пекут хлеб программисты на Haskell
Почему программирование — хороший способ выражения малопонятных и туманно сформулированных идей
Автор: scrivener