Doménově specifický jazyk

Doménově specifický jazyk je programovací jazyk, který je prostřednictvím vhodné abstrakce a výrazového slovníku zaměřen na omezenou, konkrétní problémovou doménu.

Úvod

Doménově specifický jazyk je nový termín, který však využívá přístupů známých řadu let. Popisuje programovací jazyk, který se zaměřuje na konkrétní problémovou doménu, spíše než obecný programovací jazyk (např. Java nebo C++ ), který je zaměřený na řešení obecných problémů. Jako příklad doménově specifických jazyků uveďme mini-jazyky systému UNIX, mezi něž patří shellové nástroje awk a sed nebo nástroje pro tvorbu software make, yacc.

Doménově specifické jazyky jsou stejně jako jiné jazyky určeny ke komunikaci. Pomáhají přemostit propast mezi zúčastněnými stranami softwarového vývoje a programátory. DSL může zjednodušit porozumění komplikovaného bloku kódu, a tak zlepšit produktivitu vývojářů. DSL může zlepšit komunikaci s doménovými experty. Script napsaný v DSL je snadno čitelný pro doménové experty, kteří mohou porozumět tomu, jak jsou jejich myšlenky předkládány systému.

Doménově specifickým jazykům se dostává nemalé pozornosti zejména v souvislosti s moderními programovacími jazyky Groovy, Ruby, Clojure a Scala, které díky svým vlastnostem umožňují vytvářet DSL efektivněji, než kdy dříve.

Omezení kladená na Doménově specifické jazyky

Klíčové vlastnosti, které vymezují rozdíl mezi DSL a obecným programovacím jazykem jsou:

  • Zaměření na doménu: Limitované jazyky jsou užitečné pouze pokud jsou zaměřeny na malou část problémové domény. V DSL nemůžeme vybudovat celý systém. To co dělá DSL užitečné je úzké zaměření na konkrétní problém.
  • Limitovaná výrazovost (limited expressivity): Obecné programovací jazyky nabízejí množství vlastností umožňující řešit téměř libovolný problém, avšak na nižší úrovni abstrakce za použití často složitých konstrukcí, než by umožnil specifický přístup úzce zaměřený na úzce zaměřenou část problému. DSL disponuje pouze minimem vlastností pokrývající podporu problémové domény.
  • Povaha jazyka (language nature): DSL je programovací jazyk a jako takový by měl mít smysl pro plynulost. Specifickou povahu jazyka vyjadřuje nejen volání jednotlivých metod, ale i způsob jakým jsou tyto metody na sebe navázány. Povahou jazyka míníme celkový kontext, který vznikne spojením volání metod do větších na sebe navazujících celků. (Fowler mluví o Fluent API)

Interní DSL

Interní DSL je zvláštní použití obecného programovacího jazyka. Script v interním DSL je validní kód tohoto jazyka, ale používá pouze podmnožinu jazykových vlastností ve specifickém stylu. V mnoha případech je interní DSL implementován jako tenká vrstva nad abstrakcí obecného programovacího jazyka.

Externí DSL

Externí DSL je oddělený od jazyka použitého v aplikaci. Externí DSL má vlastní syntaxi, ale může používat syntaxi jiného jazyka (XML). Script v externím DSL je obvykle transformován do jazyka aplikace použitím kompilátoru nebo interpretu. Příkladem externích Doménově specifických jazyků jsou regulární výrazy, SQL, Awk, XML.

Hranice DSL

Interní DSL

Pro vymezení interního DSL je klíčový rozdíl mezi interním DSL a knihovním API (command-query API).

Běžný způsob dokumentace třídy s knihovním API je seznam metod. Příklad knihovního API můžeme vidět například v dokumentaci standardní knihovny Javy. Objekty mají své metody, každá metoda dává smysl sama o sobě.

Interní DSL používá knihovní API jako slovník ke kterému přidává gramatiku. Metoda v interním DSL má smysl pouze ve větším kontextu většího výrazu. V důsledku toho by měl mít interní DSL cit pro sestavování celých vět, raději než sekvencí odpojených příkazů. Takový typ API nazývá Fowler - plynulé API (fluent API).

Srdcem rozdílnosti je v tomto případě povaha jazyka.

Limitovaná výrazovost jazyka není u interního DSL klíčovou vlastností. Interní DSL je v podstatě obecný programovací jazyk. Záleží na způsobu jakým jej použijeme. Při formulaci výrazů interního DSL se omezujeme na malou podmnožinu vlastnosti obecného programovacího jazyka. Je běžné nepoužívat řídící struktury jako podmínky, cykly a proměnné.

Externí DSL

Pro vymezení externího DSL je klíčový rozdíl mezi externím DSL a obecným programovacím jazykem.

Jazyk může mít zaměření na doménu, ale stále být obecným programovacím jazykem. Příkladem je jazyk R. Jazyk R je zaměřený na doménu (statistika), ale je to obecný programovací jazyk. Proto ho nemůžeme nazývat DSL.

Více zřejmý DSL jsou regulární výrazy. Regulární výrazy slouží pro vyhledávání textu a manipulaci s textem. Zde je zaměření na doménu - vyhledávaní textu a manipulace s textem - v páru s limitovanými vlastnostmi. Běžný ukazatel DSL je to, že jazyk není Turingově kompletní. DSL obyčejně nepoužívá podmínky, cykly a proměnné.

Limitovaná výrazovost vymezuje rozdílnost mezi externím DSL a obecným programovacím jazykem. Limitovaná výrazovost dává externímu DSL odlišné charakteristiky jak v použití jazyka, tak v jeho implementaci.

Výhody Doménově specifických jazyků

Zlepšení produktivity vývojářů Programový kód v DSL je čitelnější než při použití knihovního API. Tato čitelnost není jen estetickou vlastností. Pro vývojáře je snazší porozumět programovému kódu, najít chybu a modifikovat kód.

Limitovaná výrazovost DSL dělá těžší psát špatný kód a snadnější vidět chyby.

Ze stejného důvodu jako podporujeme jasná jména proměnných, psaní dokumentace k metodám a jasné programové konstrukce, měli bychom podporovat používání DSL.

Komunikace s doménovými experty Podle Fowlera je nejčastějším zdrojem neúspěchu softwarového projektu komunikace se zákazníkem a uživateli. Poskytnutím jazyka pro jednání s doménou můžeme zlepšit komunikaci s doménovými experty.

Není to tak, že doménoví experti mají psát kód DSL (i když mohou), ale mohou ho číst a rozumět tomu co systém dělá. Schopností číst DSL, mohou doménoví experti objevit chybu. Také se mohou mnohem efektivněji bavit s programátory, kteří psali pravidla.

Zahrnutí doménových expertů do vývoje software je těžké, ale má vysokou návratnost.

Změny kontextu za běhu systému Přesunutí logiky systému z doby kompilace, kde by byla běžně načtena systémem do doby běhu systému je častým důvodem pro návrh DSL. Definováním DSL získáme možnost měnit logiku systému v různých prostředích.

Existují i jiné posuny v execution kontextu. Například napsat DSL nad SQL dotazy, které jsou pro vývojáře příliš komplikované. DSL jim usnadní psaní dotazů, čtení složitého kódu, nalezení chyby. Definováním DSL jako vrstvy nad složitými SQL dotazy se usnadní práce nejen vývojářům, ale i doménovým expertům, kterým umožní číst a rozumět dříve složitým podmínkám.

Definice DSL jako v tomto případě nám často vyrovná limity v hostitelském jazyce. Dovolí nám vyjádřit věci v pohodlném DSL a potom vygenerovat kód pro aktuální prostředí.

DSL nám dovolí spustit jeden stejný kód, který generuje pravidla v různých programovacím jazycích. Někdo může napsat business pravidla, které generují C# nebo Javu, nebo popíší validaci na serveru nebo v JavaScriptu. DSL může pomoci usnadnit porozumění takovým složitým pravidlům.

Nevýhody Doménově specifických jazyků

Cena za učení Je obtížné naučit se používat nový programovací jazyk. Používat více programovacích jazyků v projektu je mnohem komplikovanější. Když lidé mluví o tom problému, je zde několik nedorozumění. Je rozdíl naučit se obecný programovací jazyk a DSL. DSL je o mnoho jednodušší a proto o mnoho jednodušší na naučení.

I když je jednoduché naučit se jeden jazyk, mít v projektu mnoho jazyků dělá složitější porozumět tomu, jakou funkci v projektu mají. To je pravda, ale i když v projektu žádné DSL nebude, stále se programátoři musí učit knihovní API a nebo frameworky.

Náklady na DSL Základní problém u DSL je užitek z používání DSL versus cena za vystavení potřebných nástrojů pro jejich podporu. Použití interního DSL redukuje tuto cenu, ale výsledné omezení syntaxí jazyka aplikace může snížit tyto výhody. Externí DSL nám dává nejvíce možností k realizaci výhod, ale přichází z větší cenou za vystavení jazyka jako postavit translator a následně nástroje pro podporu jazyka.

DSL může mít malé náklady. To jest náklady na sestavení kódu a udržování kódu.

Udržování DSL je důležitý faktor. Dokonce i malé interní DSL může způsobovat problémy, pokud ho mnoho vývojářů z týmu považuje za těžko pochopitelné. Externí DSL používající parser je často strašák pro vývojáře.

Ačkoliv nemůžeme náklady na DSL ignorovat je důležité si uvědomit, že mohou být mnohonásobně splaceny používáním DSL v budoucnosti.

Uzavřenost jazyka Problém s DSL může být ten, že se postupně vyvine v obecný programovací jazyk. Postupným přidáváním nových vlastností se DSL stane jazykem univerzálním.

Pokud vybudujete celý systém ve vlastním jazyce, už to nebude DSL, ale obecný programovací jazyk. Pro společnost, která vytvořila mnoho systémů ve svém vlastním jazyce, který není použitý jinde, je těžké najít nové zaměstnance a držet krok s technologickými změnami.

Lepší než rozšiřovat stávající DSL o nové vlastnosti, které nespadají do původně zamýšlené úzké problémové domény, je vytvořit další jazyk a oba jazyky spolu zkombinovat místo toho, než vytvářet jeden rozsáhlý obecný programovací jazyk.

Nástroje pro definici DSL

Workbench jsou specializované jazykové nástroje pro definici, vytváření, rozšiřování a údržbu jazyků. Využívají se nejen k definování struktury nového jazyka, ale také jako vývojové prostředí pro psaní a udržování programů v definovaném jazyce. Program může být reprezentován textově i graficky.

  • ANTLR je nástroj pro konstrukci překladačů a práci s gramatikami. Od verze ANTLR v3 je k dispozici grafický nástroj ANTLRWorks(odkaz), který obsahuje editor, interpret kódu a debugger.
  • Eclipse Xtext prostředí pro tvorbu a údržbu DSL. Integrován do IDE Eclipse. Obsahuje parser generátor, grafickou reprezentaci AST (Abstract Syntax Tree) a editor kódu.
  • JetBrains Meta-Programming System prostředí pro rozšiřování jazyků. Jazyk je reprezentován modelově ve formě grafu. Editor jazyka je integrován do IDE IntelliJ IDEA.
  • Intentional Software
  • Software Factories

Závěr

DSL je nástroj s velmi omezeným zaměřením. Není to něco jako objektový přístup nebo agilní proces, který posune způsob myšlení o softwarovém vývoji. DSL je velmi specifický nástroj pro velmi konkrétní podmínky. Stejně jako podporujeme psaní dokumentace, přiléhavá jména proměnných a refaktoring kódu, měli bychom uvažovat o využití DSL při softwarovém vývoji.

Použitá literatura

  • FOWLER, Martin. Domain Specific Languages. Boston : Addison-Wesley Professional, 2010. 640 s. ISBN 978-0-13-210754-9.
  • GHOSH, Debasish. DSLs IN ACTION. Stamford : Manning Publications Co., 2011. 350 s. ISBN 9781935182450.
  • DEARLE, Fergal . Groovy for Domain-Specific Languages. Olton : Packt Publishing, 2010. 312 s. ISBN 184719690X.
  • Fowler, Martin. Introducing Domain-Specific Languages. 2009 DSL Developer’s Conference (http://msdn.microsoft.com/en-us/data/dd727707.aspx).
  • DEURSEN, Arie van ; KLINT, Paul ; VISSER, Joost . Domain-Specific Languages. ACM SIGPLAN Notices [online]. 2000, Volume 35 Issue 6, [cit. 2011-10-31]. Dostupný z WWW: <https://web.archive.org/web/20090202154259/http://homepages.cwi.nl/~arie/papers/dslbib/>.
  • König, Dierk, Paul King, Guillaume Laforge, and Jon Skeet, 2009. Groovy in Action, Second Edition. Manning Early Access Program Edition. Manning Publications.