- PVSM.RU - https://www.pvsm.ru -
Поскольку идея данного поста родилась у меня независимо от эпопеи с хлебопекарней [1], хочу вставить и свои пять копеек.
Итак, суть проблемы — поставить программный код в соответствие с бизнес-требованиями. Существуют замечательные методологии и техники, например, Behavior Driven Development (BDD) [2], которые позволяют в декларативном стиле описать требуемое поведение системы (тесты).
Возникает вопрос — зачем описывать как должен работать код, если можно и сам код написать в этих терминах. Почему user story не может быть самой программой.
не код должен генерироваться из модели — модель должна быть кодом [3]
Чтобы не томить читателей сразу перейду от слов к делу. Представим себе язык для программирования вот такого робота:
Warning! Данный пример служит только для иллюстрации идеи и не предназначен для приготовления пищи в реальной жизни. Автор не несет ответственности за вред здоровью нанесенный в результате употребления пищи, приготовленной с помощью данного примера.
пирожки_с_картошкой:
жаренный_лук:
взять лук 2шт
порезать
пожарить
вареная_картошка:
взять картошка 7шт
почистить
сварить
добавить в вареная_картошка
взять соль 0.5чл
взять сливочное масло 50г
начинка: смешать вареная_картошка и жаренный_лук
тесто: смешать
взять мука 500г
взять сливочное масло 50г
взять вода 200г
взять соль 0.5чл
лепешки: сформировать тесто 20шт лепешки
сырые_пирожки: добавить в лепешки начинка
пирожки: испечь сырые_пирожки 200С
Есть замечательная методология — Domain Driven Design [4]. Какое то время я считал что это лучшая на сегодняшний день методология разработки бизнес-приложений. Разработка сущностей, агрегатов и т. д. (классов) — увлекательный процесс, похожий скорее на интеллектуальное развлечение.
Все хорошо когда речь идет о статических вещах, но — у Эванса в книжке [5] (если я не ошибаюсь) нет ни одной диаграммы workflow, ни одной схемы бизнес-процесса.
И действительно, есть классы, есть сервисы, репозитарии и т.д., все красиво — но куда деть саму бизнес-логику, как с ней поступить. Напомню, что бизнес-логика, это и есть то, ради чего, собственно, существует приложение. Реальность разработки сегодняшнего дня в том, что слишком много кода не имеет отношения к решаемой задаче, и, что хуже, этот инфраструктурный код жестко перемешан с бизнес-логикой (в частности, если мы используем парадигму Anemic Domain Model [6] (Data-driven development)
Есть две вещи в методологии DDD, с которыми я на все 100% согласен:
Очевидная идея — это отделение бизнес-логики от инфрастуктурного уровня с помощью специализированного языка программирования (DSL) который бы содержал только термины, специфичные для бизнес-процесса (термины ubiquitous Language). Этот язык и есть Business Natural Language (BNL) – это DSL, ориентированный на конкретную проблемную область (domain) в смысле отраслевых бизнес-процессов (приготовление пищи, перекачка нефти и т.п.).
Я пришел к этой идее «независимо», просто рассуждая на тему организации кода. Обсуждения на Хабре и множество других материалов в интернете показывают, что идея, в общем то, действительно очевидна.
Собственно — сам источник термина Business Natural Languages — bnl.jayfields.com [8]
Что мы получаем:
В простейшем случае BNL может быть реализован в виде набора функций (методов) с использованием fluent паттерна
см. пример ниже
или пример Как пекут хлеб программисты на Haskell [9] (В процессе его написания мы легко и непринужденно строим модель предметной области, фактически просто делая перевод с русского на Haskell. Безо всяких там наследований, рефакторингов и UML)
или Пример использования fluent interface в java для описания объектов предметной области [10]
такого рода материалов очень много
Кстати, в рамках данной парадигмы вырисовываются некоторые особенности Javascript/Java/C#/etc и CoffeeScript/Ruby/Python/etc стилей синтаксиса. Первый — более «жесткий», возможно, больше подходит для инфраструктурного кода, второй — более «человечный», больше подходит для описания бизнес-логики.
Но — это не совсем то что мы хотим, так как мы все еще привязаны к определенному языку программирования общего назначения (будь то Haskel, Java, CoffeScript etc.) в плане синтаксиса, кроме того, что важнее, нам доступен весь контекст, таким образом все еще возможно перемешивание с инфраструктурным кодом или написание некорректного с точки зрения бизнес-логики кода.
Идеальный вариант — это специализированный язык, наподобие описанного в начале этой статьи. На данный момент существует достаточно много фреймворков, позволяющих написать свой язык программирования (список, видимо, не исчерпывающий – см. ссылки в конце)
Резонно, задать вопрос о целесообразности разработки языка с учетом трудозатрат. Хотя во многих случаях это не так сложно как кажется, я вижу наиболее перспективный путь в разработке отраслевых языков. Некий язык может стать стандартом для описания финансовых и бухгалтерских операций, другой — для CRM функциональности и т. д. На самом деле этот процесс уже давно идет, так как во многих отраслевых программных продуктах существуют внутренние языки макросов для реализации специфичной для этой отрасли бизнес-логики.
Вот цитата [11] с которой я, в общем то, согласен:
Общий тренд в индустрии ИТ уже много лет — исключить программиста там где это можно, за счёт большей гибкости самой системы. Просто потому что программист-профессионал стоит дорого, и занимается только программированием.
Взять тиражируемую систему, лучше даже на основе свободных компонентов, привлечь человека из предметной области, который сколько нибудь понимает или может разобраться — и не платить дорогущей команде программистов.
Итак, что еще нам может пригодится? Мощная IDE — будет огромным плюсом. Например, с помощью чего то подобного Type Providers в F# [12] можно организовать intellisence который будет выводить, например, список существующих продуктов для приготовления. Плюс визуализация в виде диаграмм и т.д.
Хочу обратить внимание, что языки типа PowerShell, jQuery или Jetfire [13] (язык для описания workflow) и т.д. — это хоть и dsl, но все же языки общего назначения, не специфичные для описания бизнес-процессов (для чего мы и вводим термин BNL).
Я буквально в течении получаса набросал пример «кухонного» языка на CoffeeScript:
class root.Пирожки_с_картошкой extends Рецепт
constructor: () ->
super "Пирожки с картошкой"
Приготовить: () ->
жаренный_лук = @пожарить @порезать(
@взять "лук", "2шт"
)
вареная_картошка = @сварить @почистить @взять "картошка", "7шт"
@добавить( вареная_картошка, [
@взять "соль", "0.5ч/л"
@взять "сливочное масло", "50г"
] )
начинка = @смешать [вареная_картошка, жаренный_лук]
тесто = @смешать [
@взять "мука", "500г"
@взять "сливочное масло", "50г"
@взять "вода", "200г"
@взять "соль", "0.5с/л"
]
лепешки = @сформировать тесто, "20шт", "лепешки"
сырые_пирожки = @добавить лепешки, начинка
пирожки = @испечь сырые_пирожки, "200С"
(Если что — просьба на бить по почкам, так как это мой первый код на CoffeeScript. Исходники [14].).
Он почти ничего не умеет — только выводить список необходимых продуктов и инструкцию по приготовлению.
Рецепт Шаг-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 [8]
Business Natural Languages Development in Ruby [15]
domaindrivendesign.org [16]
Введение в проблемно-ориентированное проектирование [17]
Учимся проектировать на основе предметной области (DDD: Domain Driven Design) [18]
Парадигмы программирования. Data Driven vs Domain Driven [19]
Введение в Rich Domain Model [20]
Википедия [2]
behaviour-driven.org [21]
Specification By Example – BDD для прагматиков [22]
Создаем NUnit тесты в BDD стиле [23]
BDD наоборот [24]
Практика TDD/BDD на примере JavaScript: TDD и BDD [25]
Ruby
Building a DSL in Ruby [26]
Expressing Contract Terms in a DSL [27]
Visualization and Modeling SDK
MSDN [28]
Domain-Specific Development with Visual Studio DSL Tools [29]
ANTLR
antlr.org [30]
The Definitive ANTLR Reference: Building Domain-Specific Languages [31]
Boo
DSLs in Boo: Domain-Specific Languages in .NET [32]
Xtext
eclipse.org/Xtext [33]
Irony
Codeplex [34]
Writing Your First Domain Specific Language [35]
Книга Фаулера
Domain-Specific Languages (Addison-Wesley) [36]
Как два программиста хлеб пекли [1]
Светский разговор об управляемой тестами выпечке [37]
Хлеб Маркуса и YAGNI [38]
Как пекут хлеб программисты на Haskell [9]
Почему программирование — хороший способ выражения малопонятных и туманно сформулированных идей [39]
Автор: scrivener
Источник [40]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/27335
Ссылки в тексте:
[1] эпопеи с хлебопекарней: http://habrahabr.ru/post/153225/
[2] Behavior Driven Development (BDD): http://en.wikipedia.org/wiki/Behavior-driven_development
[3] не код должен генерироваться из модели — модель должна быть кодом: http://habrahabr.ru/post/169601/
[4] Domain Driven Design: http://www.domaindrivendesign.org
[5] у Эванса в книжке: http://www.domaindrivendesign.org/books/evans_2003
[6] Anemic Domain Model: http://en.wikipedia.org/wiki/Anemic_Domain_Model
[7] ВыгулМенеджер для собак: http://habrahabr.ru/post/147927/
[8] bnl.jayfields.com: http://bnl.jayfields.com
[9] Как пекут хлеб программисты на Haskell: http://eax.me/haskell-bread-task/
[10] Пример использования fluent interface в java для описания объектов предметной области: http://habrahabr.ru/post/83372/
[11] цитата: http://habrahabr.ru/post/144729/#comment_4866623
[12] Type Providers в F#: http://www.developerfusion.com/article/145919/an-introduction-to-f-type-providers/
[13] Jetfire: http://wiki.jetfire.ca/Jetfire%20Overview.ashx
[14] Исходники: https://github.com/volkov-scrivener/Play_with_dsl
[15] Business Natural Languages Development in Ruby: http://www.infoq.com/presentations/fields-business-natural-languages-ruby
[16] domaindrivendesign.org: http://www.domaindrivendesign.org/
[17] Введение в проблемно-ориентированное проектирование: http://msdn.microsoft.com/ru-ru/magazine/dd419654.aspx
[18] Учимся проектировать на основе предметной области (DDD: Domain Driven Design): http://habrahabr.ru/post/61524/
[19] Парадигмы программирования. Data Driven vs Domain Driven: http://habrahabr.ru/post/158277/
[20] Введение в Rich Domain Model: http://habrahabr.ru/post/87812/
[21] behaviour-driven.org: http://behaviour-driven.org/
[22] Specification By Example – BDD для прагматиков: http://habrahabr.ru/company/etnasoft/blog/166747/
[23] Создаем NUnit тесты в BDD стиле: http://habrahabr.ru/post/156325/
[24] BDD наоборот: http://habrahabr.ru/company/luxoft/blog/150597/
[25] Практика TDD/BDD на примере JavaScript: TDD и BDD: http://habrahabr.ru/company/evilmartians/blog/149335/
[26] Building a DSL in Ruby : http://jroller.com/rolsen/entry/building_a_dsl_in_ruby
[27] Expressing Contract Terms in a DSL: http://www.jroller.com/obie/entry/expressing_contract_terms_in_a
[28] MSDN: http://msdn.microsoft.com/en-us/library/bb126259%28VS.100%29.aspx
[29] Domain-Specific Development with Visual Studio DSL Tools: http://www.amazon.com/dp/0321398203/?tag=stackoverfl08-20
[30] antlr.org: http://www.antlr.org/
[31] The Definitive ANTLR Reference: Building Domain-Specific Languages: http://pragprog.com/book/tpantlr/the-definitive-antlr-reference
[32] DSLs in Boo: Domain-Specific Languages in .NET : http://www.manning.com/rahien/
[33] eclipse.org/Xtext: http://www.eclipse.org/Xtext/
[34] Codeplex: http://irony.codeplex.com/
[35] Writing Your First Domain Specific Language: http://www.codeproject.com/Articles/26975/Writing-Your-First-Domain-Specific-Language-Part-1
[36] Domain-Specific Languages (Addison-Wesley): http://www.amazon.com/Domain-Specific-Languages-Addison-Wesley-Signature-Fowler/dp/0321712943
[37] Светский разговор об управляемой тестами выпечке: http://habrahabr.ru/post/168993/
[38] Хлеб Маркуса и YAGNI: http://habrahabr.ru/post/153845/
[39] Почему программирование — хороший способ выражения малопонятных и туманно сформулированных идей: http://habrahabr.ru/post/148584/
[40] Источник: http://habrahabr.ru/post/169711/
Нажмите здесь для печати.