Skip to Content

Језици специфични за домен

Садржај

Проблем и мотивација

Шта је језик?

  • Комуникација мисли и осећања системом знакова као што су звуци, гестови или писани симболи1.
  • Систем знакова, симбола, гестова и правила који се користе у комуникацији2.

Шта је софтверски језик?

  • Језик коришћен у комуникацији човек-рачунар или рачунар-рачунар.
  • У варијанти човек-рачунар тежимо да језик буде лак за разумевање од стране човека али ипак да може да се процесира на ефикасан начин од стране рачунара.
  • У контексту развој софтвера две су улоге језика:

    • прескриптивна - за опис будућих система
    • дескриптивна - за опис постојећих система

Шта домен?

  • Сфера деловања, интереса или функције1.
  • Област знања, утицаја, или деловања2.
  • Да би се доменско знање могло процесирати и да би могли комуницирати у одређеном домену корисно је дефинисати онтологију домена која описује концепте домена и њихове међусобне везе.
  • Пример домена: осигурање, здравство, финансије, саобраћај…
  • Домени могу садржати поддомене. На пример, ако је посматрани домен проблема осигурање, поддомени могу бити животно осигурање, осигурање возила, осигурање некретнина и сл.

Језици специфични за домен - ЈСД (Domain-Specific Languages - DSL)

  • Језици специфични за домен (ЈСД, енг. Domain-Specific Languages - DSL) су језици прилагођени и ограничени на одређени домен проблема.
  • За разлику од језика опште намене (ЈОН, енг. General Purpose Language - GPL), нуде повећање експресивности кроз употребу концепата и нотација прилагођених домену проблема и доменским експертима.
  • Називају се још и мали језици (енг. little languages).
  • Успешан ЈСД је фокусиран на узак, добро дефинисан домен и покрива га на одговарајући начин.
  • Домен често има свој језик коришћен од стране доменских експерата иако не постоји његова имплементација на рачунару.

Примери

SQL

SELECT player, stadium
    FROM game JOIN goal ON (id=matchid)

JPA мапирање

@Entity
@Table(name="COURSES")
public class Course {

  private long courseId;
  private String courseName;

  public Course() {
  }

  public Course(String courseName) {
    this.courseName = courseName;
  }

  @Id
  @GeneratedValue
  @Column(name="COURSE_ID")
  public long getCourseId() {
    return this.courseId;
  }
}

Build језици (Ant/Maven/Gradle)

./images/Ant-Maven-Gradle.png

Пословни процеси - BPMN

./images/BPMN.png

OrgMode

Белешке, креирање садржаја, агенда, писмено програмирање (literate programming).

** PROJ
*** TODO Прегледати пријаву грешке #173
SCHEDULED: <2022-12-14 Wed>
1. [x] Неко парче кода:
 #+begin_src rust
  fn main() {
      // Statements here are executed when the compiled binary is called

      // Print text to the console
      println!("Hello World!");
  }
 #+end_src

 #+RESULTS:
 : Hello World!

2. [ ] Нека друга забелешка...

*** WAIT Предати пројектни извештај

| Активност      | Завршено | Проблеми               |
|----------------+----------+------------------------|
| Прва активност |      30% | Нема                   |
| Друга актиност |      25% | Проблеми у снабдевању  |

Typst

Припрема за штампу (typesetting).

./images/typst.png

Scratch

Учење програмирања за децу.

./images/scratch.png

Inform

Информ је језик за креирање интерактивне фикције (текстуалних авантура) базиран на природном језику.

    "Cactus Will Outlive Us All"

    Death Valley is a room. Luckless Luke and Dead-Eye Pete are men in the Valley.
      A cactus is in the Valley. Persuasion rule: persuasion succeeds.

    A person has an action called death knell. The death knell of Luckless Luke is pulling the cactus.
      The death knell of Dead-Eye Pete is Luke trying dropping the cactus.

    Before an actor doing something:
        repeat with the victim running through people in the location:
            let the DK be the death knell of the victim;
            if the DK is not waiting and the current action is the DK:
                say "It looks as if [the DK] was the death knell for [the victim], who looks startled,
                    then nonexistent.";
                now the victim is nowhere.

ChucK

Језик за креирање музике и синтезу звука у реалном времену.

// this synchronizes to period
.5::second => dur T;
T - (now % T) => now;

// construct the patch
SndBuf buf => Gain g => dac;
// read in the file
"kick.wav" => buf.read;
// set the gain
.5 => g.gain;

// time loop
while( true )
{
    // set the play position to beginning
    0 => buf.pos;
    // randomize gain a bit
    Math.random2f(.8,.9) => buf.gain;

    // advance time
    1::T => now;
}

GritQL

GritQL је ЈСД за претрагу, линтинг и трансформацију кода.

`console.log($log)` => . where {
  $log <: not within `try { $_ } catch { $_ }`
}

Colobot

  • Colobot је едукативна реал-тиме стратегија.
  • Играч програмира роботе у виртуелном окружењу ЈСД-ом налик на C++ и Javu.

./images/colobot.png

Мобилне апликације

./images/MobilneAplikacije.png

Али и…

./images/MusicNotation-External.png

или…

./images/ChessNotation.png

па чак и…

./images/saobracajni-znaci.jpg

Када језик сматрамо ЈСД-ом?

  • Зависи од тога шта нам је домен.
  • Језик може бити више или мање прилагођен неком домену.
  • У екстремном случају и општи језик као што је Јава можемо сматрати ЈСД-ом ако нам је домен "развој софтвера". Наравно, иако тачно у теоријском смислу, у практичном губимо све предности ЈСД.
  • Добар ЈСД покрива узак, добро дефинисан домен (домен проблема). Користи само концепте циљног домена, ограничен је на дати домен и самим тим је исказивање решења језгровитије и јасније доменским експертима.
  • Чест је случај да језик настане као ЈСД али се временом прошири до те мере да га можемо сматрати ЈОН.

Предности

Утицај на продуктивност

  • Поједине студије показују да повећање продуктивности иде и до 1000%1.
  • Шта је основни разлог за повећање продуктивности?

Проблем менталног мапирања

./images/MentalnoMapiranje-1.svg

Решење употребом ЈСД

./images/MentalnoMapiranje-2.svg

Зашто ЈСД?

  • ЈСД су концизнији од језика опште намене што омогућава корисницима да јасније искажу своју намеру.
  • ЈСД синтакса, било текстуална или графичка, може се прилагодити и приближити доменским експертима.
  • Концепти коришћени у ЈСД су концепти проблемског (пословног) домена што под одређеним условима омогућава да доменски експерти директно користе ЈСД без посредовања програмера.
  • Употребом концепата проблемског домена избегава се ручно мапирање на концепте циљне имплементационе платформе. Тај посао се обавља аутоматски употребом ЈСД преводиоца (компајлера или генератора кода).
  • Исказивање решења концептима независним од коришћене технологије резултује дужим животним веком апликације.
  • Самодокументујући језички искази.

Утицај на квалитет софтвера

  • Коришћење концепата домена проблема доводи до смањења броја линија кода (у терминологији текстуалних нотација), што има позитиван утицај на брзину развоја и једноставност оџавања.
  • Смањење броја линија кода иде и до 50 пута у појединим доменима примене. Густина софтверских грешака (број софтверских грешака на хиљаду линија кода) не зависи значајно од језика који се користи.
  • Из тога се може закључити да ЈСД кроз смањење броја линија кода посредно утичу на смањење апсолутног броја софтверских грешака што повећава квалитет софтверског производа и смањује цену одржавања.
  • Превођење кода на циљну платформу (компајлирање) ће резултовати конзистентним кодом.

Утицај на еволуцију апликације

  • Исказивање решења концептима независним од коришћене технологије резултује дужим животним веком апликације.
  • Није потребно мењати језичке исказе (програме/моделе) када дође до промене технологије. Потребно је ажурирати генератор кода.

Архитектуре

Архитектура базирана на преводиоцима

./images/Arhitektura-kompajler.svg

Архитектура базирана на интерпретерима

./images/Arhitektura-interpreter.svg

Градивни елементи

Градивни елементи ЈСД

Као и сваки софтверски језик и ЈСД се састоји од:

  • Апстрактне синтаксе
  • Једне или више конкретних синтакси
  • Семантике

Апстрактна синтакса

  • Одређује правила валидности исказа са становишта његове структуре.
  • Дефинише концепте домена, њихове особине и међусобне релације
  • Језици за дефинисање апстрактних синтакси језика се у домену моделовања називају мета-мета-моделима1.

Пример - апстрактна синтакса језика за опис коначних аутомата

./images/StateMachine.svg

Апстрактно синтаксно стабло

  • Сваки исказ на датом језику се може на апстрактан начин описати апстрактним синтаксним стаблом (Abstract Syntax Tree).
  • Конкретна синтакса није важна у том случају (на пример, ако посматрамо програм на Јави тада кључне речи нису део апстрактног стабла).

Пример апстрактног синтаксног стабла

Конкретна синтакса

  • Да би могли да прикажемо исказ на конкретан начин потребна нам је конкретна синтакса.
  • Конкретна синтакса дефинише изглед исказа на неком језику, односно у ширем смислу дефинише и начине интеракције корисника са језичким исказима тј. представља интерфејс језик-корисник.
  • Иако нам је довољна једна конкретна синтакса за један језик, можемо их имати више.

Конкретна синтакса

Пример истог исказа употребом две различите конкретне синтаксе

./images/RazliciteSintakse.png

Семантика

  • Дефинише смисао језичких исказа.
  • Иако постоје и друге технике у пракси се најчешће семантика дефинише превођењем (компајлирањем тј. генерисањем кода) на језик који већ има дефинисану семантику путем преводиоца на ниже језике или интерпретера (нпр. виртуалне машине).
  • Најчешће су циљни језици на које се ЈСД преводи језици опште намене.
  • Пример: генерисање Јава програмског кода из ЈСД језичког исказа.
  • Језици се преводе на све "ниже" и "ниже". Где је крај превођењу? Машински језик. Дефинисан у хардверу рачунара (процесору).

Класификација

Подела ЈСД према врсти конкретне синтаксе

  • Текстуални
  • Графички
  • Табеларни
  • Базиран на екранским формама
  • Хибридни - комбинација више основних

Текстуалне синтаксе - предности и мане

  • Програмери се осећају "код куће".
  • Могу се користити регуларни текст едитори.
  • Серијализована форма је идентична са презентационом. се користити стандардни системи за контролу верзија (Git, Mercurial, Subversion …).
  • Подршка у алатима: бојење кода, допуна кода, претрага, навигација…
  • Мана: Није погодна за опис и разумевање структуре која није линеарне природе (графови, табеле итд.).

Графичке синтаксе - предности

  • Разумевање структуре. Подржано операцијама zoom, pan и сл.
  • Често разумљивије доменским експертима (најчешће је доменски језик графичке природе).
  • Интуитивнији и лакши за учење - учење кроз испробавање (палета са алатима и концептима, онемогућавање креирање невалидних конструкција итд.).

Графичке синтаксе - мане

  • Још увек сложенији за имплементацију и одржавање.
  • За серијализацију се користи формат који се разликује од презентационог.
  • Отежано или потпуно немогуће коришћење стандардних алата за контролу верзија. Потребно је развити посебан VCS алат.
  • Захтева наменске едиторе.

Подела према врсти домена

./images/HorizontalniVertikalniDSL.svg

Подела ЈСД према начину имплементације

  • Интерни - Настали су на бази већ постојећих програмских језика (најчешће ЈОН).
  • Екстерни - Израђени "он нуле" дефинисањем синтаксе и имплементацијом компајлера који преводи програме писане на овом језику на неки други језик (најчешће ЈОН) или се програм директно интерпретира.

Интерни ЈСД

  • Базирани на постојећем језику и алатима. Најчешће текстуални.
  • Користе сву инфраструктуру језика домаћина (едиторе, дебагере, компајлере/интерпретере…).
  • Брзи за имплементацију и лаки за одржавање. Популарни у појединим заједницама (Lisp, Ruby, Groovy, Scala…).
  • Добри као улазница у свет DSL/DSM/MDE приступа.
  • Најчешће на паметан начин користе могућности језика (анонимне функције, мета-програмирање итд.).
  • Ограничења конкретне синтаксе.
  • Свака наменска библиотека може се сматрати интерним ЈСД (API базирани)…
  • … али конкретна синтакса таквог језика није прилагођена домену.

Екстерни ЈСД

  • Израђени "он нуле" - скупљи развој и одржавање.
  • Пуна контрола конкретне синтаксе - боље прилагођавање доменским експертима.
  • Едитори и сви пропратни алати такође морају да се праве "од нуле"…
  • …mada данас постоје алати који нам тај посао олакшавају.

Неки од познатијих екстерних ЈСД

  • SQL: текстуални, домен - рад са релационим базама података
  • HTML: текстуални, домен - дефинисање садржаја на вебу
  • CSS: текстуални, домен - стилизовање садржаја
  • make: текстуални, домен - изградња апликације (build)
  • LaTeX/Typst: текстуални, домен: креирање штампаних материјала (typesetting)
  • Window Builder: GUI базиран, домен - изградња интерфејса
  • R: текстуални, домен - статистичка обрада података

Пример: Интерни ЈСД за дефинисање емаил-а (JavaMail API)

MimeMessage message = new MimeMessage(session);

message.setFrom(new InternetAddress(from));

message.addRecipient(Message.RecipientType.TO,
          new InternetAddress(to));

message.setSubject("Greetings from Novi Sad");
message.setText("Enjoying my stay in Novi Sad! See you soon!");

Transport.send(message);

Пример: Хипотетички екстерни ЈСД за дефинисање емаил-а

BEGIN myMail
  FROM me@myself.com
  TO myfriend@somewhere.org
  SUBJECT Greetings  from  Novi Sad

Enjoying my stay in Novi Sad! See you soon!

END
SEND myMail

Пример

Интерни ЈСД за дефинисање графички корисничких интерфејса (Сwинг)

public DSLKurs() {
    setBounds(100, 100, 450, 300);
    getContentPane().setLayout(new BorderLayout());
    contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
    getContentPane().add(contentPanel, BorderLayout.CENTER);
    contentPanel.setLayout(new FormLayout(new ColumnSpec[ {
                            FormFactory.RELATED_GAP_COLSPEC,
                            FormFactory.DEFAULT_COLSPEC,
                            FormFactory.RELATED_GAP_COLSPEC,
                            ColumnSpec.decode("default:grow"),},
                  new RowSpec[] {
                  FormFactory.RELATED_GAP_ROWSPEC,
                  FormFactory.DEFAULT_ROWSPEC,
                  FormFactory.RELATED_GAP_ROWSPEC,
                  FormFactory.DEFAULT_ROWSPEC,
                  FormFactory.RELATED_GAP_ROWSPEC,
                  FormFactory.DEFAULT_ROWSPEC,}));
    ....

Пример

Екстерни ЈСД за дефинисање графички корисничких интерфејса (WindowBuilder)

./images/GUIDSL-External.png

Пример

Интерни ЈСД за дефинисање граматике језика (Arpeggio Python)

def number():     return _(r'\d*\.\d*|\d+')
def factor():     return Optional(["+","-"]), [number,
                          ("(", expression, ")")]
def term():       return factor, ZeroOrMore(["*","/"], factor)
def expression(): return term, ZeroOrMore(["+", "-"], term)
def calc():       return OneOrMore(expression), EOF

Пример

Екстерни ЈСД за дефинисање граматике језика (Arpeggio PEG)

number = r'\d*\.\d*|\d+'
factor = ("+" / "-")?
        (number / "(" expression ")")
term = factor (( "*" / "/") factor)*
expression = term (("+" / "-") term)*
calc = expression+ EOF

Конкретна синтакса је важна!!!

Неки језици су погоднији за креирање интерних ЈСД

Језици погодни за креирање интерних ЈСД

  • Ruby
  • Groovy
  • Scala
  • Lisp

Пример интерног ЈСД (Ruby Sinatra)

get '/dogs' do
    # get a listing of all the dogs
end
get '/dog/:id' do
    # just get one dog, you might find him like this:
    @dog = Dog.find(params[:id])
    # using the params convention, you specified in your route
end
post '/dog' do
    # create a new dog listing
end
put '/dog/:id' do
    # HTTP PUT request method to update an existing dog
end
delete '/dog/:id' do
    # HTTP DELETE request method to remove a dog who's been sold!
end

Пример интерног ЈСД (Groovy Gradle)

repositories {
    mavenCentral()
}

dependencies {
    groovy fileTree(dir: new File(gradle.gradleHomeDir, 'lib'),
                    includes: ['**/groovy­all­*.jar'])
    compile gradleApi()
    compile 'eu.appsatori:gradle­fatjar­plugin:0.1.3',
    {
        ext.optional = true
    }
    testCompile 'org.spockframework:spock­core:0.6­groovy­1.8'
}

Екстерни ЈСД омогућавају потпуно прилагођавање домену.

Интерни ЈСД за музичку нотацију

Score k = new Score(Tonality.G_major);
Bar bar = new Bar(BarType.4_4);
t.addPause(Duration.1_4);
t.addNote(NoteType.A3, Duration.1_4);
t.addNote(NoteType.C2, Duration.1_4);
k.addBar(bar);

Екстерни ЈСД за музичку нотацију

У екстерној варијанти можемо у потпуности прилагодити конкретну синтаксу доменским експертима.

./images/MusicNotation-External.png

Lilypond note script

Али се дешава да и у екстерној варијанти ЈСД није прилагођен доменским експертима.

./images/Lilypond.png

Критике ЈСД

  • Скуп развој и одржавање језика.
  • Потреба за експертима у домену развоја језика који су истовремено способни да анализирају домен примене.
  • Језичка "какофонија" (Language Cacophony)1 и потреба да програмери познају велики број језика (посебан језик за сваки технички и/или пословни домен).

Low code/No Code платформе

Данас се платформе базиране на ЈСД често брендирају као Low Code или No Code платформе.

Језичке радионице (Language Workbenches)

Језичке радионице (Language Workbenches)

  • Интегрисана окружења за развој, тестирање и еволуцију језика и алата за њихово ефикасно коришћење (едитори, интерпретери, компајлери и сл.). Користе се код парадигме развоја оријентисане ка језицима (Language Oriented Programming - LOP)1.
  • Решавају проблем брзине развоја и лакоће одржавања ЈСД.
  • Примери језичких радионица:

    • Meta Programming System (MPS)
    • Xtext
    • Spoofax

Приступи

  • Пројекционе радионице - директна измена апстрактне репрезентације кроз пројекцију.

    ./images/projekcija.png
  • Базиране на парсерима - измена се врши посредно кроз текст који се парсира да би се добила апстрактна репрезентација.

    ./images/parseri.png

Пројекционе радионице

  • Предности:

    • Могуће вишеструке конкретне синтаксе (текстуалне, графичке, табеларне…) - боље прилагођавање конкретном домену.
    • Синтаксе се могу "у лету" мењати.
    • Контрола валидности израза у време измене модела.
  • Мане:

    • Сложеност алата.
    • Формат за перзистенцију није у вези са конкретним синтаксама које корисник користи. Немогуће је користити стандардне системе за контролу верзија базиране на тексту.
    • Морају се развити наменски генерички едитори за сваку класу конкретних синтакси.

Радионице базиране на парсерима

  • Предности:

    • Једноставније за израду и одржавање.
    • Теорија парсирања добро установљена. Велики број библиотека за парсирање.
    • Могуће користити обичне текстуалне едиторе.
    • Могуће користити стандардне системе за контролу верзија (нпр. git, subversion).
    • Једноставно копирање и лепљење (енг. copy/paste).
  • Мане:

    • Могућа само текстуална синтакса -> ограничено прилагођавање домену.
    • Провера валидности се одлаже до фазе парсирања.

Meta Programming System (MPS)

  • JetBrains - http://www.jetbrains.com/mps/
  • Пројекциона језичка радионица - едитори манипулишу директно апстрактном репрезентацијом (апстрактним синтаксним стаблом). Чак и у случају текстуалних нотација.
  • Подршка за различите конкретне синтаксе (нотације): табеларне, текстуалне, базирани на ћелијама, графичке.
  • Подршка за контролу верзија.

Meta Programming System - карактеристичан изглед

Xtext

  • Настао као део пројекта слободног софтвера - openArchitectureWare.
  • Иза развоја у највећој мери стоји немачка фирма Itemis.
  • Постао део Ецлипсе пројекта.
  • Текстуалне синтаксе. EBNF граматика.
  • Употреба ECore мета-метамодела1. Мета-модел се генерише из граматике а може да користи и већ постојећи мета-модел.
  • Генерисање Eclipse едитора са подршком за бојење синтаксе, навигацију, outline поглед итд.
  • Xtext базирани ЈСД се дубоко интегрише у Eclipse окружење и тешко је уочити разлику са подршком за било који други језик са Eclipse подршком (нпр. Јава).

Xtext - Little tortoise граматика

Spoofax

  • Као и Xtext базиран на парсирању и текстуалним синтаксама. Креира пуну подршку за језик у виду Eclipse прикључака.
  • Истраживачки пројекат на TU Delft у Холандији.
  • Граматика језика се дефинише мета-језиком SDF (Syntax Definition Formalism).
  • Парсер користи SGLR алгоритам (Scanerless GLR) и омогућава парсирање пуног скупа контекстно слободних граматика. У случају неодређености парсер враћа шуму парсирања (parse forest) док у случају детерминистичке граматике враћа увек стабло парсирања (parse tree).
  • За транформацију програма и преписивање стабала користи се ЈСД Stratego.

Spoofax - карактеристичан изглед

./images/Spoofax-prikaz.png

Инжењерство софтверских језика

  • Software Language Engineering - SLE.
  • Правац и поглед на развој софтверских језика који покушава да уједини све друге правце који у основи имају развој и употребу софтверских језика (MDE/MDA/DSM.., онтологије, grammarware, Language Oriented Programming…).
  • Једна од идеја је изједначавање модела и програма - као јединствен назив предложен је мограм.*

Литература