- BrainTools - https://www.braintools.ru -
Мир разработки полон соблазнов изобретать собственные решения. Один из самых ярких соблазнов — создать свой DSL (Domain-Specific Language). Это звучит красиво: язык, который идеально отражает задачи конкретной предметной области. Но где заканчивается здравый смысл и начинается велосипедостроение? В статье я попробую на примерах показать, когда DSL — это спасение, а когда лучше взять старый добрый Python, C# или даже Bash.

DSL часто сравнивают с секретным языком внутри команды. Когда задачи повторяются, а бизнес-логика становится громоздкой, хочется выразить всё в более компактной и выразительной форме. Так появляются конфигурационные языки, мини-языки для описания правил, трансформаций, пайплайнов данных.
Примеры вокруг нас: SQL для запросов, регулярные выражения, CSS. Никто не называет их «лишними велосипедами», потому что они решают огромный пласт задач. Но вот если вы пытаетесь «объяснить» бизнес-аналитику логику [1] системы через кастомный язык с непонятным синтаксисом, есть риск, что через год этим DSL будете пользоваться только вы сами.
С одной стороны, Python или JavaScript можно использовать почти везде. Но универсальные языки тянут за собой много «балласта»: синтаксический шум, огромные экосистемы и тысячи способов сделать одно и то же.
Пример: попробуйте описать бизнес-правило для тарификации на Python:
# Python
def calculate_tariff(user_type, minutes, base_rate):
if user_type == "student":
discount = 0.5
elif user_type == "corporate":
discount = 0.8
else:
discount = 1.0
cost = base_rate * minutes * discount
return round(cost, 2)
print(calculate_tariff("student", 120, 0.15))
Всё понятно для программиста, но бизнес-аналитик или тестировщик вряд ли захочет вникать в эти elif.
DSL выигрывает там, где описываются повторяющиеся декларативные конструкции.
Пример — простенький язык для тарифов:
# Mini-DSL
TARIFF student {
DISCOUNT = 0.5
}
TARIFF corporate {
DISCOUNT = 0.8
}
CALCULATE minutes * base_rate * DISCOUNT
Теперь аналитик может спокойно редактировать правила, не пугаясь def и скобочек.
Забыли про пользователей. DSL должен быть читаем не только для автора, но и для команды.
Изобретение велосипеда. Иногда DSL — это просто плохо сделанный YAML.
Отсутствие туллинга. Без подсветки синтаксиса, автодополнения и валидатора любой язык быстро превращается в боль [2].
Непродуманная эволюция [3]. Язык живёт дольше, чем проект, а поддерживать его никто не хочет.
Пусть у нас есть задача описывать рабочие смены сотрудников. Напишем маленький DSL на базе lark-parser:
# Python
from lark import Lark, Transformer
grammar = """
start: shift+
shift: "SHIFT" NAME "{" day+ "}"
day: "DAY" NAME HOURS
NAME: /[a-zA-Z]+/
HOURS: /[0-9]+/
%import common.WS
%ignore WS
"""
class ShiftTransformer(Transformer):
def shift(self, items):
return {"employee": items[0], "days": items[1:]}
def day(self, items):
return {"day": items[0], "hours": int(items[1])}
parser = Lark(grammar, parser="lalr", transformer=ShiftTransformer())
text = """
SHIFT Alice {
DAY Monday 8
DAY Tuesday 6
}
"""
print(parser.parse(text))
На выходе получаем JSON-подобную структуру. И бизнес может легко читать текстовое представление.
Если задача решается «из коробки» конфигами (например, Kubernetes YAML).
Если в компании нет ресурсов поддерживать язык и тулзы.
Если язык слишком узкий и его используют два человека.
В таких случаях лучше взять тот же Python или даже Excel с формулами.
Ключевой момент: DSL не должен быть самоцелью. Он должен быть «слоем общения» между кодом и предметной областью. Иногда выгоднее взять универсальный язык, но ограничить стиль кода линтерами и правилами. А иногда — построить лёгкий DSL, но с трансляцией в тот же Python.
Когда-то я писал DSL для описания ETL-пайплайнов. Красиво получилось: строки вроде
EXTRACT csv FROM "/data/users.csv"
TRANSFORM normalize_names
LOAD postgres TO "users"
Но через полгода понадобилось добавить сложные фильтры. И тут выяснилось, что DSL слишком узок. В итоге всё равно встроили куски Python. Урок: думать наперёд и не пытаться выразить «всё» собственным языком.
DSL — это инструмент. Иногда он делает жизнь проще, иногда — только сложнее. Правило простое: создавайте DSL только тогда, когда уверены, что:
предметная область устойчива,
пользователей много,
поддержка языка не ляжет грузом на одного разработчика.
Во всех остальных случаях универсальные языки и хорошие практики разработки могут оказаться куда эффективнее.
Автор: SergeyIgnatiev95
Источник [4]
Сайт-источник BrainTools: https://www.braintools.ru
Путь до страницы источника: https://www.braintools.ru/article/19659
URLs in this post:
[1] логику: http://www.braintools.ru/article/7640
[2] боль: http://www.braintools.ru/article/9901
[3] эволюция: http://www.braintools.ru/article/7702
[4] Источник: https://habr.com/ru/articles/948242/?utm_campaign=948242&utm_source=habrahabr&utm_medium=rss
Нажмите здесь для печати.