- PVSM.RU - https://www.pvsm.ru -

Business Natural Languages

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

Итак, суть проблемы — поставить программный код в соответствие с бизнес-требованиями. Существуют замечательные методологии и техники, например, Behavior Driven Development (BDD) [2], которые позволяют в декларативном стиле описать требуемое поведение системы (тесты).

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

не код должен генерироваться из модели — модель должна быть кодом [3]

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

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% согласен:

  • Необходимость в ubiquitous Language – едином «стандартном» языке (терминологии) для взаимопонимания специалистов в предметной области и программистов
  • Отделение бизнес-логики от инфраструктуры (репозитории, сервисы, POCO, классы, аттрибуты, сериализация и т. д.). Атрибут [DataContract] не имеет никакого отношения к бизнес-логике, как и ВыгулМенеджер для собак [7] не соответвует терминологии бизнес-логики

Очевидная идея — это отделение бизнес-логики от инфрастуктурного уровня с помощью специализированного языка программирования (DSL) который бы содержал только термины, специфичные для бизнес-процесса (термины ubiquitous Language). Этот язык и есть Business Natural Language (BNL) – это DSL, ориентированный на конкретную проблемную область (domain) в смысле отраслевых бизнес-процессов (приготовление пищи, перекачка нефти и т.п.).

Я пришел к этой идее «независимо», просто рассуждая на тему организации кода. Обсуждения на Хабре и множество других материалов в интернете показывают, что идея, в общем то, действительно очевидна.
Собственно — сам источник термина Business Natural Languages — bnl.jayfields.com [8]

Что мы получаем:

  • UML модель, user story, реализация, behavior описание для тестов — все это теперь единое целое
  • реализация бизнес-логики предметной области надежно отделена от инфраструктурного кода
  • кодировать бизнес-логику теперь может не только программист, но и специалист в предметной области, не знакомый с программированием
  • накопленная бизнес-функциональность не теряется при переносе системы на любую платформу (ее даже не надо портировать)
  • не играет роли как именно реализован dsl «под низом» (это могут быть классы, код в функциональном стиле, expression trees и т.д.)

Видение светлого будущего

В простейшем случае BNL может быть реализован в виде набора функций (методов) с использованием fluent паттерна

см. пример ниже
или пример Как пекут хлеб программисты на Haskell [9] (В процессе его написания мы легко и непринужденно строим модель предметной области, фактически просто делая перевод с русского на Haskell. Безо всяких там наследований, рефакторингов и UML)
или Пример использования fluent interface в java для описания объектов предметной области [10]
такого рода материалов очень много

Кстати, в рамках данной парадигмы вырисовываются некоторые особенности Javascript/Java/C#/etc и CoffeeScript/Ruby/Python/etc стилей синтаксиса. Первый — более «жесткий», возможно, больше подходит для инфраструктурного кода, второй — более «человечный», больше подходит для описания бизнес-логики.

Но — это не совсем то что мы хотим, так как мы все еще привязаны к определенному языку программирования общего назначения (будь то Haskel, Java, CoffeScript etc.) в плане синтаксиса, кроме того, что важнее, нам доступен весь контекст, таким образом все еще возможно перемешивание с инфраструктурным кодом или написание некорректного с точки зрения бизнес-логики кода.

Идеальный вариант — это специализированный язык, наподобие описанного в начале этой статьи. На данный момент существует достаточно много фреймворков, позволяющих написать свой язык программирования (список, видимо, не исчерпывающий – см. ссылки в конце)

  • Ruby
  • Go
  • Boo
  • Visualization and Modeling SDK от Microsoft
  • ANTLR
  • Irony
  • XText
  • ...

Резонно, задать вопрос о целесообразности разработки языка с учетом трудозатрат. Хотя во многих случаях это не так сложно как кажется, я вижу наиболее перспективный путь в разработке отраслевых языков. Некий язык может стать стандартом для описания финансовых и бухгалтерских операций, другой — для 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]

Domain Driven Design

domaindrivendesign.org [16]
Введение в проблемно-ориентированное проектирование [17]
Учимся проектировать на основе предметной области (DDD: Domain Driven Design) [18]
Парадигмы программирования. Data Driven vs Domain Driven [19]
Введение в Rich Domain Model [20]

Behavior Driven Development (BDD)

Википедия [2]
behaviour-driven.org [21]
Specification By Example – BDD для прагматиков [22]
Создаем NUnit тесты в BDD стиле [23]
BDD наоборот [24]
Практика TDD/BDD на примере JavaScript: TDD и BDD [25]

Разработка DSL

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/