Český programovací jazyk Flex a modFlex

16. června 2004

Flex je nový programovací jazyk české provenience, založený na jazyku Ada, s důrazem na vysokou spolehlivost a bezpečnost. Je to univerzální programovací jazyk, my se zde však budeme zajímat především o webové aplikace, kde Flex může být použit jako alternativa k PHP. V tomto článku budu demonstrovat filozofii Flexu na jednoduché aplikaci.

Firma A&&L soft s. r. o. se živí vývojem elektronického bankovnictví a Flex vznikl jaksi bokem, protože žádný z běžně používaných jazyků nevyhovoval jejím potřebám. Tím, že tento jazyk navrhli chlapci od bankovních systémů, je z velké části dáno, na co byl při návrhu kladen důraz – spolehlivost, bezpečnost a snadnou udržovatelnost kódu. Autoři však tvrdí, že nejde o jazyk pro úzké použití, ale o jazyk univerzální.

Flex byl do značné míry inspirován jazykem Ada. Adu vyvinulo na počátku osmdesátých let americké ministerstvo obrany a používá se v mission/safety-critical aplikacích. V Adě je například řídící software k raketoplánu. Poslední standard Ady je z roku 1995, je tedy jasné, že Ada v moderních aplikacích už ztrácí dech, zatímco Flex by měl poskytovat programátorům všechno, co má moderní jazyk mít. Flex podporuje „všechny stupně abstrakce“ a umožňuje konzervativní strukturované programování, podpořené silnou typovou kontrolou, ale i plnohodnotné OOP. Flex se tedy snaží být progresivní i konzervativní zároveň. Neobsahuje žádné nevyzkoušené postupy, vše, co v něm najdeme, známe již odjinud. Nepříjemným důsledkem tohoto přístupu je, že se jazyk začátečníkům může jevit jako komplikovaný, ačkoli je o dost jednodušší než třeba právě Ada.

Co je modFlex

Už z názvu je patrné, o co jde – modFlex je modul populárního HTTP serveru Apache, který umožňuje použít Flex pro generování dynamického webu. Pokud modFlex obdrží požadavek na nějaký flexovský skript, přeloží ho, vyrobí z něj knihovnu ve formátu DLL, tu načte do paměti a použije k obsloužení požadavku. Překlad samozřejmě neprobíhá při každém požadavku, ale jen po změně zdrojového skriptu.

Přestože tato architektura se spíše podobá architektuře JavaServletů (a jak dále uvidíme, flexovské skripty trochu připomínají JavaServlety), autoři se zatím nesnaží konkurovat webovým řešením postaveným na Javě. Flex je spíše konkurencí pro PHP, coby bezpečnější alternativa k tomuto populárnímu nástroji. Tomu odpovídá i přítomnost nativního bindingu na knihovny PHP. Jakékoli knihovní funkce, které jste zvyklí používat v PHP, můžete používat i s modFlex. Samozřejmostí je i snaha o konkurenci v cenové oblasti – modFlex je pochopitelně zdarma.

Vzhled skriptů

Určitě už jste zvědaví na nějaký ten kousek zdrojového kódu. Samozřejmě by byl hřích nezačít nějakým tím „Ahoj světe!“, vypsaným na obrazovku (do okna prohlížeče):

program ahoj_svete =
with
  mflib; — Hlavní modul modFlexu zprostředkovává spojení s vnějším světem.
begin
  modflex_request^.out_header.insert(‚Content-Type‘, ‚text/plain; charset=UTF-8‘);
 
  write_line(‚Ahoj, mnohovesmíre!‘);
 
  modflex_request^.out_result := 200;
  modflex_request^.out_result_info := ‚OK‘;
end ahoj_svete;

Zde ho máte. Podrobnější komentáře si vyšetříme na komplikovanější kód. Zde se jen pošle klientovi hlavička obsahující formát odpovědi, přidá se sama odpověď a celá akce se dokončí nastavením statutu protokolu HTTP.

Jak vidíte, Flex má pascalskou syntaxi (stejně jako Ada). Přestože výsledkem překladu bude DLL knihovna, kód je formálně označen jako program. Řetězce se vkládají do jednoduchých apostrofů, stříška slouží k dereferencování ukazatelů, komentáře se píší za dvojitou pomlčku. Za zmínku ještě stojí ono end ahoj_svete; úplně na konci – „pojmenované endy“ jsou povinné, protože toto opatření zlepšuje orientaci v delších programech.

Důležité je, že modFlex akceptuje zdrojové kódy jenom v kódování UTF-8. Vnitřně jsou všechny řetězce v UNICODE. Skripty tedy můžete psát v libovolném textovém editoru, který toto kódování zvládá, i když je lepší použít nějaký moderní editor, který zvládne i zvýraznění syntaxe. K dispozici je řada integračních balíků, která se stále rozšiřuje. Bohužel v současnosti ještě neexistuje podpora pro oblíbený PSPad.

Ukázka práce s Flexem

Seznamovací skript máme za sebou, takže je čas na rozsáhlejší příklad. Tím bude rafinovaná webová aplikace, která vydělí dvě celá nezáporná čísla a zobrazí výsledek. Komentářů přímo v kódu bude poskrovnu, zato budu komentovat každý úsek kódu v textu.

Aplikace se skládá z hlavního programu a jednoho modulu. Moduly ve Flexu více méně odpovídají jednotkám (unitům) v Pascalu – až na několik vylepšení. Moduly se mohou hierarchicky vnořovat do sebe a dokonce mohou být děděny. Při rozboru budeme postupovat stylem „shora dolů“, takže teď hlavní program:

program priklad =
with
  modulek,
  mflib; 
var
  stranka : c_stranka;
begin
  modflex_request^.out_header.insert(‚Content-Type‘, ‚text/html; charset=UTF-8‘);
  stranka.vypis_telo;
  stranka.vypis_dynamicky_obsah;
  stranka.vypis_konec;
leave
  modflex_request^.out_result := 200;
  modflex_request^.out_result_info := ‚OK‘;
end priklad;

Tento program má jen o šest řádek víc, než úvodní „Ahoj světe!“. První změnou je, že tento program používá kromě standardního modulu mflib i modul modulek, ve kterém budou „střeva“ naší aplikace. Dále deklarace instance stranka třídy c_stranka (je taktéž v modulu modulek). Flex nepoužívá referenční objektový model jako Java nebo Delphi, ale spíše systém z C++, takže tato deklarace rovnou vytvoří instanci třídy. Poslední změnou je sekce uvozená klíčovým slovem leave, které odpovídá klíčovému slovu finally z Javy – skript se pokusí dokončit HTTP požadavek, i když nastane neošetřená výjimka. Zde to vlastně ani není potřeba, protože odpověď „200 OK“ je výchozí, obecně se leave sekce hodí pro uvolňování zdrojů, které musí být uvolněny i v případě chyby.

Teď přišel čas na popis modulu modulek. Flex preferuje dvojstopé programování – moduly i třídy bývají zpravidla rozděleny na veřejnou specifikaci a privátní implementaci, každou část ve zvláštním souboru. Ovšem není to nutnou podmínkou, můžete sloučit jak soubory, tak specifikační a implementační část. V naší aplikaci jsem modul i třídu rozdělil. Specifikace modulku vypadá takto:

module public modulek =
  class public c_stranka =
    static vypis_telo;
    static vypis_dynamicky_obsah;
    static vypis_konec;
  end c_stranka;
end modulek;

Veřejná specifikace modulu modulek obsahuje jednu důležitou položku, a sice specifikaci třídy c_stranka. Tato třída obsahuje tři metody, které se budou starat o výpis HTML kódu do prohlížeče. Metody začínají klíčovým slovem static, které ale neznamená, že se jedná o statické metody jak je známe z jazyků Java, C# nebo C++, ale že tyto metody nelze v případných potomcích třídy c_stranka předefinovat. Pokud bychom o možnost předefinování stáli, byly by metody uvozeny klíčovým slovem virtual a samotného předefinování v případných potomcích bychom dosáhli přes override. Skutečné statické metody třídy se uvozují klíčovým slovem procedure.

Nyní se podíváme na implementaci modulu modulek. Jeho začátek vypadá takto:

module private modulek =
  with mflib,
       standard,
       standard.conversions;
  
  type t_delitel = t_unsigned range 1..t_unsigned:last;

Nejprve je zde výčet používaných modulů, kromě tradičního mflib obsahuje ještě standard, který definuje datové typy používané ve standardních knihovnách Flexu, a standard.conversions pro převody z řetězce na číslo a naopak. Zde je nutno poznamenat, že Flex neobsahuje žádné předdefinované typy, poskytuje pouze prostředky pro deklaraci typů. Jen tak pro zajímavost, definice šestnáctibitového znaménkového čísla z modulu standard vypadá následovně:

t_signed16 = signed 16; — šestnáct bitů

Pro účely ukázkové aplikace jsem také nadefinoval jeden nový typ, a to t_delitel. Ve skutečnosti je to potomek typu t_unsigned s omezeným rozsahem hodnot. Takto se vyhneme nebezpečí dělení nulou, protože nulu do proměnné typu t_delitel­ prostě přiřadit nebude možné.

Flex používá takzvaný silný typový systém, tedy úplný opak původní filozofie PHP. Ve Flexu je každá proměnná nějakého neměnného typu. Proměnné stejného typu lze libovolně přiřazovat, proměnné různých typů mezi sebou automaticky přiřazovat nelze. Znaménkové číslo do neznaménkového prostě nepřiřadíte, tedy pokud nepoužijete explicitní přetypování. Takováto strategie se většinou pozitivně projeví ve spolehlivosti vytvářených programů. Práce s typy je vidět v následující proceduře:

procedure dej_dynamicky_obsah(html_tag : t_char32str)
    return t_char32str =
  var
    delenec : t_unsigned;
    delitel : t_delitel;
    podil : t_unsigned;
  begin
    delenec := string_to_unsigned(modflex_request^.get_vars.find(‚delenec‘));
    delitel := string_to_unsigned(modflex_request^.get_vars.find(‚delitel‘));
    podil := delenec div delitel;
    result := ‚<‚ & html_tag & ‚>‘ & unsigned_to_string(podil) & ‚</‘ & html_tag & ‚>‘;
  catch
    when constraint_error do
      result := ‚číslo mimo povolený rozsah‘;
    when conversion_error do
      result := ‚nekorektní číslo‘;
    when others do
      result := ‚nespecifikovaná chyba‘;
  end dej_dynamicky_obsah;

Jedná se o běžnou proceduru (nikoli o metodu), která přebírá jeden parametr typu řetězec znaků a výsledek vrací též jako řetězec znaků. Zajímavostí je, že Flex má univerzální řetězce – tedy nejen znakové, klidně můžete mít řetězec celých čísel. Další specialita je, že Flex nezná klíčové slovo function, hodnotu může vrátit i procedura nebo statická či virtuální metoda.

V této konkrétní proceduře jsou nejprve deklarovány tři proměnné. V zadání jsme se omezili na kladná čísla, dělitel je typu t_delitel, což nám zaručuje, že nikdy nebudeme dělit nulou. Proměnné delenec a delitel se naplní z proměnných, předaných v HTTP požadavku metodou GET. Pak se vypočítá podíl, převede se na řetězec a obalí se HTML elementem, který procedura dostala jako parametr. (Všimněte si použití ampersandu na místě operátoru zřetězení.) Návratová hodnota procedury se uloží do proměnné result.

Za posledním řádkem „řádného“ kódu se nachází sekce pro zotavení z chyb. Klíčové slovo catch má obdobný význam jako v jazycích Java nebo C++. Kód za catch se provede, pokud v řádném kódu procedury nastane výjimka. Ta může být vyvolána například při převodu řetězce na číslo. Zjistíme tedy typ výjimky a podle toho upravíme návratovou hodnotu procedury.

Všimněte si, že tato procedura je velice robustní. Buď korektně provede to, co se od ní očekává, nebo slušně vrátí přesně diagnostikovanou chybu, což v PHP často není možné bez složitého testování parametrů.

S hlavní částí ukázkové aplikace jsme hotovi, nyní se vrátíme ke třídě c_stranka, jejíž implementace je taktéž v implementační části modulu modulek:

  class private c_stranka =
    static vypis_telo =
    begin
      write_line(‚<!DOCTYPE html PUBLIC „-//W3C//DTD XHTML 1.0 Transitional//EN“ „http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd“>‘);
      write_line(‚<html xmlns=“http://www.w3.org/1999/xhtml“ xml:lang=“cs“ lang=“cs“>‘);
      write_line(‚<head><title>Priklad v modFlexu</title></head>‘);
      write_line(‚<body>‘);
      write_line(‚  <h1>Delička</h1>‘);
      write_line(‚<form action=“priklad.src“ method=“get“>‘);
      write_line(‚  dělenec: <input type=“text“ name=“delenec“ />‘);
      write_line(‚  dělitel: <input type=“text“ name=“delitel“ />‘);
      write_line(‚  <input type=“submit“ value=“Vydělit“ />‘);
      write_line(‚</form>‘);
    end vypis_telo;

Uvedená metoda jednoduše vypíše HTML kód, který modFlex odešle prohlížeči. Na stránce bude jednoduchý webový formulář, pro zadání dělence a dělitele. Druhá a třetí metoda a konec modulu je zde:

    static vypis_dynamicky_obsah =
    begin
      if modflex_request^.get_vars.exist(‚delenec‘) and
         modflex_request^.get_vars.exist(‚delitel‘)
      then
        write_line(dej_dynamicky_obsah(‚b‘));
      else
        write_line(‚zadejte dvě kladná celá čísla‘);
      end if;
    end vypis_dynamicky_obsah;
    static vypis_konec =
    begin
      write_line(‚</body></html>‘);
    end vypis_konec;
  end c_stranka;
end modulek;

Metoda vypis_dynamicky_obsah zkontroluje, jestli byla odeslána data z webového formuláře. Pokud ano, zavolá metodu dej_dynamicky_obsah a její výsledek zobrazí, v opačném případě vypíše výzvu pro uživatele. Metoda vypis_konec za komentář opravdu nestojí.

Dojmy a shrnutí

ModFlex je docela sympatický projekt. Flex je opravdu zajímavý jazyk, moderně navržený, ale postavený na osvědčených základech. Skripty psané ve Flexu by opravdu mohly být spolehlivější než v PHP. Otázkou je, zda o to vývojáři stojí – většina nadšenců, kteří si chtějí co nejrychleji zprovoznit jednoduchý skript asi výhody tohoto jazyka neocení.

Samozřejmě všechno má své nevýhody, tou největší však je pravděpodobně novost Flexu. Překladač ještě není úplně hotový, takže pokud budete chtít použít nějaké exotičtější konstrukce, může se vám stát, že narazíte na hlášku typu „feature not implemented“. To samé platí o standardních knihovnách, které jsou zatím relativně chudé (což by ale vadit nemuselo, protože můžete používat knihovny z PHP). Na druhou stranu, samotný překladač Flexu i modFlex jsou napsány přímo ve Flexu. A takový překladač, to jsou desetitisíce řádek složitého kódu, takže nějaké nespolehlivosti se bát nemusíte.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Štítky: Články

Mohlo by vás také zajímat

Nejnovější

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *