Изначально я планировал сделать обзор сразу двух техник разработки - TDD и BDD. Но прочитав статью Дена Норта – «Введение в BDD», я решил BDD рассмотреть подробней. В качестве словаря, предлагаю использовать глоссарий, который собрал из статей на www.wikipedia.org и www.habrahabr.ru.
Начнем с аббревиатуры «DD» (driven development). Алексей Лустин (технический директор компании «Серебряная пуля», которая специализируется на IT продуктах для бизнеса) хорошо охарактеризовал понятие «Разработка через» (driven development) в одной из своих статей на www.habrahabr.ru :
«Размышляя над проблемой тестирования, а точнее над проблемой качества решений, умные и не очень люди, в основном ломают копья над следующим противоречием “надо тестировать, но надо разрабатывать, а не тестировать”. Всё становится еще хуже, когда к этому мы добавим еще огромное количество подходов к проектированию и разработке. Например, как это классифицирую я, когда мне необходимо объяснить сущность проблемы:
Domain DD — способ разработки, когда цель заказчика сформулирована в виде базовых сущностей будущей системы: “Хочу Товары, Инвентаризацию, Акты списаний и оприходований”
Report DD — способ разработки, когда цель заказчика формулируется в виде конечных отчетов с анализом данных: “Хочу отчет о прибылях и убытках”
User Interface DD — способ разработки, когда цель заказчика сформулирована в виде конечного пользовательского интерфейса: “Хочу вот такую формочку для сотрудника на проходной по выдаче пропусков”
Behavior DD — способ разработки, когда цель заказчика сформулирована в виде конечного процесса ожидаемого в системе, или даже группы взаимосвязанных процессов: “Когда мы фиксируем отправку машины из Москвы, тогда нужно чтобы изменился статус заказа и зафиксировалось время отправки, а также надо учесть косвенные затраты на перевозку в себестоимости заказа”.
Отдельно стоит выделить еще 3 подхода, которые обычно нигде не описываются:
Sabotage DD — способ разработки, когда цель заказчика формулируется в виде ускоренных сроков требующих разработки напрямую в Production системах: “Срочно добавьте на форму реквизит Булево =Ромашка=”. Применяется при попытках заказчика построить управляемый хаос в команде разработки — используется в политических целях.
Moratorium DD — способ разработки, когда цель заказчика не в запуске функциональности, а в соблюдении регламентов и нормативов утвержденных на предприятии: “Любое изменение в системе должны быть согласовано с <ЛистСогласования>, любые работы по проектированию, разработке и прототипированию не могут быть проведены без указания проекта и его технико-экономического обоснования”.
Pain DD — переходный способ разработки, когда цель заказчика повысить качество решений, не снижая сроков выхода функциональности: “Хочу чтобы вы производили всестороннее тестирование, но кстати не забудьте первого числа запуск системы WMS, не дай бог вам сорвать сроки. Да и кстати ФОТ нам в этом году урезали — выделенных тестировщиков не получите”.
Классификация конечно топорная и очень уж приземленная, но для подготовки специалиста к чтению умных книг по этому поводу, достаточная. (Алексей Лустин)
В этом списке нет Test DD и вот почему. В TDD нам не интересно, каким образом заказчик сформулировал свои требования, важно как мы будем контролировать выполнение нашего программного кода. Разберем пример: написан программный код, который формирует определенную таблицу с данными. У каждой колонки этой таблицы есть определенный тип данных, в каждой строке заполнены конкретные значения. Если мы допустим ошибку и в момент добавления строки в таблицу вызовем метод который класс таблицы не поддерживает, то такой код не пройдет синтаксис контроль или в процессе выполнения мы получим исключительную ситуацию. Но если мы какие-то поля в строке не заполним данными, это не будет являться ошибкой синтаксиса. Это может являться ошибкой логики. Тогда мы можем дополнить наш код конструкциями типа «Если Не ЗначениеЗаполнено() Тогда ВызватьИсключение()» и тем самым реализуем контроль логики кода. А теперь представьте, что сначала вы пишете код, который проверяет наличие в конкретной переменной «объекта таблицы» (таблицы еще может и не существовать), проверяете, что в этой таблице есть строки, что в этих строках заполнены значения и только потом вы начинаете писать код, который создает таблицу, заполняет строки и тд. В общих чертах - это и есть техника TDD.
Теперь вернемся к BDD, и почему я решил подробней рассмотреть именно этот подход. Первая причина - если верить Дэну Норту, который не один год использовал TDD, то данная техника имеет серьезные недостатки, в ней нет конкретики. У тех кто начинает использовать эту технику сразу возникают вопросы: Проверять только передаваемые параметры и возвращаемые значения или весь код напичкивать конструкциями «if - then»? Сколько таких конструкций должно быть и как их классифицировать? В процессе использования данной техники Ден Норт встречался с большим количеством тупиковых ситуаций, которые разрулить не удалось до сих пор. К примеру, где гарантия того, что пройдя тесты ТDD мы получаем работоспособное приложение с точки зрения пользователя?
Вторая причина – BDD является развитием TDD и содержит все ее преимущества и практически лишена ее недостатков. Сводная таблица ниже иллюстрирует сравнение техник BDD и TDD:
TDD |
BDD |
|
Написание кода тестов до написания кода программы |
ДА |
ДА |
Прямая связь кода с требованиями с помощью Gherkin |
НЕТ |
ДА |
Сценарное тестирование через интерфейс пользователя |
НЕТ |
ДА |
Повторное использование кода тестов в других сценариях |
НЕТ |
ДА |
Эта таблица из лекции «Магия BDD» Леонид Паутов (ведущий разработчик компании «Серебряная пуля»), текст которой опубликован на www.infostart.ru . Я решил начать именно с этой таблицы, потому что в ней указаны не только отличия TDD и BDD но и основные решаемые задачи. Первый пункт «Написание кода тестов до написания кода программы» мы поверхностно рассмотрели два абзаца выше, но применительно к TDD. Как данная задача решается в BDD, мы поймем после разбора языка Gherkin.
Прямая связь кода с требованиями с помощью Gherkin
(За основу взята статья «Writing Features - Gherkin Language» с сайта www.behat.org)
Gherkin - это человеко-читаемый язык для описания поведения системы, который использует отступы чтобы задать структуру документа, (пробелы или символы табуляции). Каждая строчка начинается с одного из ключевых слов и описывает один из шагов. Основное преимущество — тесты могут быть разработаны не обязательно тестировщиками, а людьми которые вообще могут не знать программирования, например бизнес-аналитиками. Также это позволяет показать заказчику какой функционал был покрыт тестами. После получения файла со сценариями тестирования, тестировщику остается закрепить за каждой строкой необходимый код (об этом поговорим позднее).
Ключевые слова в Gherkin: Функционал(Feature), Сценарий(Scenario), Дано(Given), Когда(When), Тогда(Then), И(And), Но(But), Сценарий-Схема(Scenario-Outline), Фон(Background), Образцы(Examples).
Вспомогательные выражения в Gherkin: Чтобы(In order to), Как(As a), Хочу(I want to).
Истории выглядят примерно так:
Функционал[Краткое описание]
Чтобы [Получаемый результат]
Как [Потребитель результата]
Хочу [Функционал]
Сценарий: #1 [Описание]
Дано: [Ситуация или условие] или [Ситуация или условие]
И: [Ситуация или условие] или [Ситуация или условие]
Когда: [Событие или действие] или [Событие или действие]
И: [Событие или действие] или [Событие или действие]
Тогда: [Проверка результата] или [Проверка результата]
И: [Проверка результата] или [Проверка результата]
Сценарий: #N…
Пример:
Функционал: Распределение поступающей оплаты по документам реализации и зачет аванса контрагента.
Чтобы: Получить корректные проводки по счетам.
Как: Бухгалтер организации.
Хочу: При фиксации оплаты от контрагента, оплату отражать как аванс.
Сценарий #1: Поступает сумма оплаты от контрагента. Долг у контрагента, на момент оплаты, отсутствует (реализаций нет).
Дано: Контрагент (покупатель) «Иванов А.В.» оплачивает сумму 1000 рублей. Долг у контрагента отсутствует.
Когда: Фиксируется оплата от контрагента «Иванов А.В.» по договору «Основной» на сумму 1000 рублей.
Тогда: Формируется проводка по счету «АвансыПолученные» на сумму 1000 рублей.
Сценарий #2 Долг у контрагента, на момент оплаты, присутствует (есть реализации). Поступает сумма оплаты превышающая долг контрагента.
Дано: Контрагент (покупатель) «Иванов А.В.» оплачивает сумму 1000 рублей. Долг контрагента 500 рублей.
Когда: Фиксируется оплата от контрагента «Иванов А.В.» по договору «Основной» на сумму 1000 рублей
Тогда: Формируется проводка по счету «ВзаиморасчетыСКонтрагентами» на сумму 500 рублей (погашение долга)
И: Формируется проводка по счету «АвансыПолученные» на сумму 500 рублей (фиксируется аванс).
Хочу заметить, что в процессе написания истории (по аналогии с языком программирования) необходимо тщательно избегать использования ключевых слов и вспомогательных выражений после двоеточия. Например:
Чтобы: Получить корректные проводки по счетам.
Как: Бухгалтер организации.
Хочу: При фиксации оплаты от контрагента, чтобы оплата отражалась как аванс.
Так же можно заменить, что в языке нет ключевого слово «или», поэтому текст ниже является ошибкой:
Дано: Контрагент (покупатель) «Иванов А.В.» оплачивает сумму 1000 рублей. Долг контрагента 500 рублей.
Или: Контрагент (покупатель) «Иванов А.В.» оплачивает сумму 500 рублей. Долг контрагента отсутствует.
Вообще, слово «или» желательно избегать даже по тексту после двоеточия, так как это вносит определенную неоднозначность в сценарий. Но иногда этого избежать невозможно.
Что касается таких ключевых слов как Фон(Background), Сценарий-Схема(Scenario-Outline) и Образцы(Examples) то их используют достаточно редко, особенно если код пишет не программист, а бизнес-аналитик.
Теперь речь пойдет о связывании кода на языке Gherkin c реальным программным кодом. Это можно представить в виде таблицы:
Сценарий #2 Долг у контрагента, на момент оплаты, присутствует (есть реализации). Поступает сумма оплаты превышающая долг контрагента. |
|
Код Gherkin(Дано, Когда, Тогда, И) |
Код 1С (имена вызываемых процедур) |
Дано: Контрагент (покупатель) «Иванов А.В.» оплачивает сумму 1000 рублей. Долг контрагента 500 рублей. |
ПроверитьНаличиеДолгаКонтрагентаПоВзаиморасчетам(); |
Когда: Фиксируется оплата от контрагента «Иванов А.В.» по договору «Основной» на сумму 1000 рублей |
СоздатьПровестиДокументПКО(); |
Тогда: Формируется проводка по счету «ВзаиморасчетыСКонтрагентами» на сумму 500 рублей (погашение долга) |
ПроверитьПроводкиПоСчетамВзаиморасчетов(); |
И: Формируется проводка по счету «АвансыПолученные» на сумму 500 рублей (фиксируется аванс). |
ПроверитьПоводкиПоСчетамАвансовКонтрагентов(); |
Каждой строке кода на языке Gherkin сопоставляется одна процедура на языке 1С. Сразу должны возникнуть вопросы. Почему только одна процедура и зачем вообще, что то связывать?
Что бы ответить на этот вопрос, давайте вернемся к первому пункту таблицы сравнения BDD и TDD.
Написание кода тестов до написания кода программы в BDD.
Как я уже упоминал, концепция написания кода тестов до написания кода программы в ВDD, реализована немного иначе, чем в TDD. В Test Driven Development, для нас важно только проверить логику программного кода, а в Вehavior Driven Development важно проверить конечные процессы в системе (хотя параллельно проверять логику кода никто не мешает). Данные процессы, как уже известно, описываются с помощью Gherkin. В технике BDD это неотъемлемая часть написания теста, а так же формулирования требований, написания документации и тд.
Но тесты на языке Gherkin невозможно выполнить, это не язык программирования. Но зато их можно связать с кодом на языке программирования. Важно чтобы эта была реальная связь, то есть код на Gherkin должен полностью соответствовать коду на реальном языке программирования. Чем детальнее эта связь (чем больше строк в коде Gherkin), тем более развернутым получается тест. Теперь о том, зачем нам развернутый тест.
Основных причины две, первая: «В любом месте реального кода программы может возникнуть ошибка, и мы должны быстро понять - где и почему». Представим, что мы сделали следующую связь:
Сценарий #2 Долг у контрагента, на момент оплаты, присутствует (есть реализации). Поступает сумма оплаты превышающая долг контрагента. |
|
Код Gherkin(Дано, Когда, Тогда, И) |
Код 1С (имена вызываемых процедур) |
Дано: Контрагент (покупатель) «Иванов А.В.» оплачивает сумму 1000 рублей. Долг контрагента 500 рублей. |
ВыполнитьТест(); |
Когда: Фиксируется оплата от контрагента «Иванов А.В.» по договору «Основной» на сумму 1000 рублей |
|
Тогда: Формируется проводка по счету «ВзаиморасчетыСКонтрагентами» на сумму 500 рублей (погашение долга) |
|
И: Формируется проводка по счету «АвансыПолученные» на сумму 500 рублей (фиксируется аванс). |
Если у нас возникнет ошибка в процедуре ВыполнитьТест(), то мы как программисты найдем причину. Но нам, скорее всего, понадобится анализ кода, запуск отладчика и тд. А все это наше время. Другое дело, если ошибка возникнет в процедуре «ПроверитьПоводкиПоСчетамАвансовКонтрагентов()», которая сопоставлена в строке Gherkin «И: Формируется проводка по счету «АвансыПолученные» на сумму 500 рублей (фиксируется аванс).». Скорее всего, мы просто заглянем в движения документа и увидим там другую сумму или вообще отсутствие проводок.
Вторая причина, и самая важная: «Мы планируем писать тест до написания программы». И выглядит это следующим образом: у нас уже есть логика на Gherkin, у нас уже есть имена процедур: ПроверитьНаличиеДолгаКонтрагентаПоВзаиморасчетам(), СоздатьПровестиДокументПКО(). Нам остается только зайти в «тело» одноименных процедур и написать там код. Конечно часть процедур нам может не понадобиться в реальной программе. Например «ПроверитьПроводкиПоСчетам() будет нагружать систему, да и если с проводками будет проблема, скорее всего бухгалтер это заметит. А вот другие процедуры, которые будут создавать и проводить документы, мы реально можем использовать. Причем, мы их поместим в общие модули, эти модули отнесем к соответствующим подсистемам и будем вызывать так же, как вызываем их в тестах. Красота и порядок.
Теперь давайте разберемся какие процедуры, с какими строками связывать. В начале раздела, посвященного синтаксису языка Gherkin, указан шаблон истории. Связь реального кода осуществляется только со строками, в которых указаны ключевые слова: «Дано, Когда, Тогда» и детализируются связи с помощью ключевого слова «И».
Напротив ключевого слова «Дано» в квадратных скобках указано «[Ситуация или условие]». Это значит, что на этом этапе проверяются параметры, выполняются запросы к базе данных, сравниваются значения. Это необходимые условия, которые должны быть уже выполнены до начала расчета и создания данных в информационной системе.
Напротив ключевого слова «Когда» в квадратных скобках указано «[Событие или действие]». Это непосредственно расчет и создание данных.
И наконец, напротив ключевого слова «Тогда» в квадратных скобках указано «[Проверка результата]». Это такие же проверки, как и после слова «Дано», только проверяем мы то, что было сделано после ключевого слова «Когда».
Сценарное тестирование через интерфейс пользователя
Сценарное тестирование - это тестирование по предварительно написанному сценарию. Код на языке Gherkin это сценарий, а также отчасти документация и требования.
Но только отчасти, потому что читая такую документацию, пользователь может застрять на первом же «Когда: Фиксируется оплата от контрагента «Иванов А.В.» по договору «Основной» на сумму 1000 рублей». Конечно, эту строку можно развернуть подробнее:
Когда: Создается документ ПКО
И: заполняется реквизит контрагент
И: Заполняется реквизит договор…
Но такие сочинения могут занимать не одну страницу и не один час времени. С одной стороны мы хотим, что бы подготовка таких тестов занимала как можно меньше времени, с другой была как можно более прозрачной и всеобъемлющей. Вопрос - как этого достичь.
Приведу еще пример: В документе ПКО, в модуле формы, в обработчике «ПриИзмененииКонтрагента()» есть проверка, что данный контрагент является физлицом. Такие проверки желательно делать перед записью в модуле объекта, но реальный процесс разработки может диктовать иное. Коля и Вася в какой-то момент времени одновременно дорабатывали один и тот же документ, модуль объекта был захвачен Колей, а Васе нужно было срочно доделать работу. Или задача стояла таким образом: «Выбираемое значение должно проверяться сразу». В результате наш тест этого вообще не выявит, потому что мы создаем документ ПКО программно, не открывая его форму. Мы можем при написании теста программно открывать форму и вообще эмулировать все действия реального пользователя, но объем кода в тесте увеличится в разы. Мы подошли вплотную к проблеме «надо тестировать, но надо разрабатывать, а не тестировать».
В данной ситуации, если мы хотим проверить работу приложения, нам необходимо тестировать интерфейс. Вообще условно разделяют две категории тестирования: на уровне кода и тестирование интерфейса. Причем тестирование интерфейса, это не только пользовательский интерфейс, но и различные сервисы типа Web-сервисов, которые вообще не имеют графического интерфейса. Если говорить о тестировании графических интерфейсов, то идеальным решением было бы использовать специальные программные средства и инструменты.
Основная цель таких продуктов – это ускорить и упорядочить процесс написания тестов. Этот процесс должен стать максимально прозрачным и простым. В сфере автоматизации тестирования через графический интерфейс, можно выделить два основных вида инструментов:
- Которые взаимодействуют с интерфейсом приложения на уровне программного кода. Это выглядит примерно так же, если бы мы писали код открывающий формы и нажимающий кнопки, только у нас были бы генераторы этого кода. Мы бы нажимали на кнопку «Ок», а в модуле появлялась строка типа ТекущаяФорма.Кнопки.Ок.Нажать(). Но для того чтобы реализовать данную возможность, разработчик приложения должен заранее задуматься о предоставлении такого интерфейса.
- Которые взаимодействуют с интерфейсом через драйвера устройств ввода данных и используют механизмы распознания изображений. Это выглядит примерно так: программа ищет на экране конкретное изображение, если она его находит, то эмулирует клики мышки в конкретную область изображения и начитает ввод данных с клавиатуры. Данный подход не зависит от того, предоставил ли разработчик приложения такую возможность или нет. Но недостатком является то, что могут возникать ошибки при распознавании изображений, есть зависимость от разрешения экрана (оно должно быть неизменным) и скорость работы таких тестов ниже, так как на распознавание изображений уходит определенное время.
Первый вид инструментов, на мой взгляд, самый перспективный. И если говорить об 1С, то начиная с платформы 8.3, разработчики предоставили нам такую возможность. Описание данного механизма, можно посмотреть на сайте 1С или http:// /news/автоматизированное-тестирование-в-1с-8-3/ . Но основная проблема, на сегодняшний день, это поддержка только управляемых форм. Данное условие является серьезным камнем преткновения для тех, кто использует конфигурации на обычных формах. Но не является безвыходной проблемой.
В поисках решения я обратился ко второму виду инструментов, которые имеют общепринятое название «Image-based testing». Здесь оказался хороший выбор от навороченных и дорогих, типа «TestComplete», до простых и полностью бесплатных типа «SikuliX». Многие из этих продуктов сами имеют программный интерфейс, начиная от взаимодействия через командную строку, до встроенных интерпретаторов типа «Python». Основная идея для искателей решений данной проблемы, это обеспечить взаимодействие этих продуктов с платформой 1С, чем я уже занялся и в ближайшее время надеюсь предоставить результаты. Так же надеюсь, что возможно кто-то это уже сделал и поделится своими идеями.
Ну а если для вас управляемый интерфейс это родное или вы уже придумали как быстро взаимодействовать с обычными формами, обратите внимание на продукт под названием «Vanessa Behavior». Он бесплатный и очень быстро развивается. Есть хороший видео обзор https://www.youtube.com/watch?v=KbImzcrj_58.
Повторное использование кода тестов в других сценариях
Данный пункт – это высший пилотаж, но к нему по любому приходят все, кто всерьез занимается автоматизацией тестирования. Основная идея – использовать этапы одного теста в других тестах. То есть мы собираем некую библиотеку, в которой хранятся часто используемые действия, скажем по созданию и заполнению конкретных видов документов, формированию отчетов, проверке движений и тд.
Опять же, если говорить о готовых решениях, то в «Vanessa Behavior» это тоже реализовано. На мой взгляд, данный проект весьма перспективен и заслуживает поддержки.
Всем спасибо за внимание!
Глоссарий
Software development methodology (SDM) – Так же известны как software development life cycle, software development process, software process. Методологии деления процесса разработки программного обеспечения на отдельные фазы или этапы, каждый из которых содержит меры улучшающие планирование и управление процессом разработки в целом. В качестве примеров можно привести: «Каскадную модель» (waterfall model), Прототипное программирование (prototyping), СпираL9;льная модель (spiral model), быстрая разработка приложений(rapid application development), экстемальное программирование (extreme programming), различные agile-методы (agile methodology) и тд. (Wikipedia)
Agile software development. - Гибкая методология разработки (agile-методы)— серия подходов к разработке программного обеспечения, ориентированных на использование итеративной разработки, динамическое формирование требований и обеспечение их реализации в результате постоянного взаимодействия внутри самоорганизующихся рабочих групп, состоящих из специалистов различного профиля. Существует несколько методик, относящихся к классу гибких методологий разработки, в частности «экстремальное программирование», «DSDM», «Scrum», «FDD». (Wikipedia)
Driven Development (DD) (разработка “через” или разработка “от цели”) — один из способов организации процесса разработки в инженерии программного обеспечения. Входит в SDM (software development methodology) en.wikipedia.org/wiki/Software_development_process в виде отдельных методологий.
Domain-driven design (DDD).
Предметно - ориентированное проектирование. Это набор принципов и схем, направленных на создание оптимальных систем объектов. Сводится к созданию программных абстракций, которые называются моделями предметных областей. В эти модели входит бизнес-логика, устанавливающая связь между реальными условиями области применения продукта и кодом. Предметно-ориентированное проектирование не является какой-либо конкретной технологией или методологией. Это набор правил, которые позволяют принимать правильные проектные решения. Данный подход позволяет значительно ускорить процесс проектирования программного обеспечения в незнакомой предметной области. Есть книга - Эрик Эванс (Eric Evans) «Проблемно-ориентированное проектирование». (Wikipedia)
Способ разработки, когда цель заказчика сформулирована в виде базовых сущностей будущей системы: “Хочу Товары, Инвентаризацию, Акты списаний и оприходований”(Алексей Лустин «Habrahabr.ru»)
Feature-driven development (FDD). – Разработка управляемая функциональностью. Итеративная методология разработки программного обеспечения, одна из гибких методологий разработки (agile). FDD представляет собой попытку объединить наиболее признанные в индустрии разработки программного обеспечения методики, принимающие за основу важную для заказчика функциональность (свойства) разрабатываемого программного обеспечения. Основной целью данной методологии является разработка реального, работающего программного обеспечения систематически, в поставленные сроки. (Wikipedia)
Test-driven development (TDD). – Разработка через тестирование. Техника разработки программного обеспечения, которая основывается на повторении очень коротких циклов разработки: сначала пишется тест, покрывающий желаемое изменение, затем пишется код, который позволит пройти тест, и под конец проводится рефакторинг нового кода к соответствующим стандартам. Кент Бек, считающийся изобретателем этой техники, утверждал в 2003 году, что разработка через тестирование поощряет простой дизайн и внушает уверенность (inspires confidence). В 1999 году при своём появлении разработка через тестирование была тесно связана с концепцией «сначала тест» (test-first), применяемой в «экстремальном программировании» (agile методология), однако позже выделилась как независимая методология. (Wikipedia)
behavior-driven development (BDD). - Разработка основанная на функционировании. Процесс разработки программного обеспечения, который возник из TDD. Объединяет главные техники и принципы TDD, идеи из DDD и OOAD (техника объектно ориентированного анализа и проектирования). BDD главным образом является идеологией о том, как разработке программного обеспечения быть одновременно понятной бизнесу и техническим специалистам. В ней используются специализированные программные инструментарии для разработки программного обеспечения. И не смотря на то, что эти инструментарии используются в основном в BDD проектах, они так же могут быть использованы для поддержки TDD. (Wikipedia)
Способ разработки, когда цель заказчика сформулирована в виде конечного процесса ожидаемого в системе, или даже группы взаимосвязанных процессов: “Когда мы фиксируем отправку машины из Москвы, тогда нужно чтобы изменился статус заказа и зафиксировалось время отправки, а также надо учесть косвенные затраты на перевозку в себестоимости заказа”. (Алексей Лустин «Habrahabr.ru»)
Domain Specific language (DSL). Предметно-специфичный язык — язык программирования, специализированный для конкретной области применения, является ключевым понятием языково-ориентированного программирования. Любой новый язык в мире (будь-то PHP, ruby, python, Erlang, LISP, Closure или 1С) изначально создавался в качестве ответа на проблему. То есть если вы серьезно собираетесь изучать какой-либо язык или «фреймворк», вам необходимо вспомнить, «для чего» автор его создавал, вспомнить, что «не нравилось» автору в других платформах. (Алексей Лустин «Habrahabr.ru»)