Definičné a vývojové prostredie - skriptovanie
Tu nájdete:

Při nasazení ABRA Gen u větších klientů je mnohdy nutné dodávaný produkt upravit dle specifických potřeb, které jdou nad rámec běžných uživatelských úprav a nastavení. Okrem možnosti definovať si definovateľné číselníky, možnosti rôznym spôsobom do existujúcich objektov, agend a číselníkov dopĺňať ďalšie položky, možnosť si pomocou definovateľných SQL skriptov dopĺňať/rozširovať štruktúru databázy, je často potrebné určité správanie aj doprogramovať. Preto je v systéme k dispozícii možnosť skriptovania – teda možnosť do existujúcich objektov (Business objektov, agend a nevizuálnych číselníkov) zaradiť vlastný programový kód, ktorý sa bude vykonávať spolu s pevným kódom daným výrobcom. Týmto spôsobom je teda možné vytvoriť nové správanie, prípadne upraviť to súčasné presne na mieru užívateľovi. Ide o jednu z možností zákazníckej modifikovateľnosti systému.
Užívateľ/implementátor potrebuje upraviť alebo rozšíriť funkčnosť súčasného Business objektu Faktúra vydaná tak, aby sa pri vytvorení novej faktúry do popisu vyplnil nejaký text. Otvorí si agendu Balíčky skriptov - zadefinuje nový balíček (alebo sa rozhodne, že pridá svoje skripty do nejakého existujúceho balíčka) a v rámci tohto balíčka si vyberie typ Business objekt. V rámci typu Business objekt si vyberie triedu Business objektu Faktúra vydaná. V nej potom zadefinuje vlastný skript pre udalosť AfterPrefill. V tejto udalosti je mu k dispozícii samotný Business objekt (odovzdaný pomocou parametra) a prípadne ďalšie parametre. Zadefinovaný skript uloží – po uložení sa skript skompiluje na neskoršie použitie (kompilácia skriptu nie je časovo zanedbateľná, preto je lepšie mať ich už predkompilované).
Na balíčku, v ktorom je umiestnený popisovaný skript, nastaví programátor príznak Používať. Potom už len stačí spustiť agendu Faktúr vydaných alebo OLE aplikáciu, ktorá s Business objektom Faktúra vydaná pracuje, a implementované riešenie vyskúšať.
Skriptovanie je tiež nevyhnutné pre niektoré iné časti systému. Viz příklady Využití skriptování v jiných modulech systému ABRA Gen.
POZOR!!! Skriptovanie značne rozširuje možnosti systému, ako vyplýva o. i. aj z niekoľkých základných príkladov Príklady možností využitia skriptovania. Na druhej strane z toho môžu vyplývať i možné negatívne dôsledky:
-
Môže do značnej miery zmeniť vzhľad systému a správanie systému a to bohužiaľ aj negatívnym spôsobom - Napr.:
- Skrytie či premenovanie niektorých funkčných tlačidiel, položiek apod., čo môže viesť aj k zmäteniu užívateľa (nebude zodpovedať tejto príručke, ktorá popisuje stav dodávaný defaultne výrobcom).
- Zmena umiestnenia niektorých prvkov, ktorá môže viesť ku kolízii (napr. nechcenému prekrytiu) s inými položkami (napr. novo dodanými výrobcom v ďalších verziách a pod.).
- Neočakávané správanie (napr. ponúkanie záznamov z číselníka v závislosti od hodnoty inej položky riešenej skriptovaním) môže viesť napríklad aj k tomu, že sa neponúkne nič, pokiaľ daná položka nie je zadaná (pokiaľ to nie je v skripte poriadne ošetrené a pod.).
- Systém je navrhnutý tak, aby v prípade, že nie sú žiadne skripty definované, nedochádzalo k výraznejšiemu spomaleniu, aj keď nepatrné spomalenie je možné.
- Možný výskyt zavlečených chýb, najmä v prípade použitia neskúsených užívateľom.
Preto si v prípade pochybností o nejakej funkčnosti systému najskôr zistite, či sa vám nespúšťajú nejaké skripty, ktoré by daný stav mohli spôsobiť, viď Informácie o spúšťaných skriptoch.

Ako skriptovací engine bol na základe testov rýchlosti vybraný FastScript. Ačkoliv FastScript podporuje více skriptovacích jazyků, je ve skriptování ABRA Gen pro jednotnost použitý pouze PascalScript. Toto omezení souvisí mimo jiné i s tím, že ve skriptování jsou dostupné třídy, které jsou k dispozici pouze v Delphi/Pascalu – tudíž implementátor, který chce realizovat skriptování v ABRA Gen, musí být s Delphi/Pascalem tak jako tak obeznámen.
FastScript byl podstatně rozšířen, aby více vyhovoval potřebám ABRA Gen. Ide napr. o podporu dokumentácie na všetkých entitách, sprevádzkovanie enumeračných typov a množín, podporu dokumentácie pre udalosti, podporu štatistických (class) metód. Napriek tomu má aj určité obmedzenia, s ktorými je nutné pri tvorbe skriptov počítať. Viď Pokyny k tvorbe skriptov.

K dispozícii je agenda Balíčky skriptov, na vytváranie, ladenie a správu existujúcich skriptov.
Pojem "balíček" zavedený v agende balíčky skriptov, umožňuje rozumnú organizáciu (usporiadanie) vytvoreného programového kódu vrátane vzájomných závislostí. Neznamená jednoduchú distribúciu všetkých súčastí potrebných na implementáciu užívateľom požadovanej funkčnosti (skripty, definovateľné číselníky, definovateľné položky, definovateľné formuláre, definície reportov, definície exportov, definovateľné SQL skripty, …).
Aby bolo možné v definícii skriptov (a aj inde) vedieť, aké BO, agendy a nevizuálne číselníky podporujú skriptovanie a aké metódy (udalosti) ponúkajú na skriptovanie, je interne zaistená registrácia týchto objektov a v rámci objektu je k dispozícii zoznam podporovaných udalostí vrátane popisu (vysvetliviek). Skriptovanie je typicky dostupné pre Business objekty, ktoré majú možnosť definovať užívateľsky definovateľné položky (ale môžu nastať aj výnimky) a pre väčšinu agend a nevizuálnych číselníkov. Možnosť doplniť si vlastné skripty je len do vybraných miest (udalostí) v Business objektoch (BO), agendách a nevizuálnych číselníkoch. Aké miesta na skriptovanie, tzv. háčiky (hooks), sú pre daný objekt k dispozícii, je dané výrobcom a užívateľ to nemôže nijako meniť.
Zoznam objektov/tried a procedúr/funkcií, ktoré sú dostupné v skriptovaní, je k dispozícii v agende Balíčky skriptov v Class Exploreri.
Zoznam dostupných háčikov pre daný objekt je k dispozícii v agende Balíčky skriptov v záložke Zdrojový kód v položke Metóda.
Názvy metód (háčikov) pokiaľ možno čo najviac vystihujú miesto, kde dochádza k ich vyvolaniu. Ďalej sú zoznamy háčikov rozdelené na základné a pokročilé. Pokročilé sa líšia od základných tým, že začínajú znakom "_".
Ďalej môže byť odlíšené, či sa daný háčik vyvoláva pred alebo po určitej akcii. To je riešené pomocou sufixov PreHook a PostHook v názve. Pokiaľ to nemá význam, končí názov háčika len slovom Hook.
Existující háčky:
- _DeleteObject_PreHook
- _DeleteObject_PostHook
- AfterSiteOpen_Hook
- Validate_Hook(var AResult: Boolean)
- a. i.

Nezbytnou podmínkou pro provoz skriptování je, aby byla tato část systému licencována. Skriptovanie je licencované samostatne - viď Licencované celky (licencované moduly a vlastnosti). Licencovaná je tvorba a kompilácia skriptov. Samotné vykonávanie už skompilovaných skriptov nijako licencované nie je.
Zda je licence dostupná k zakoupení pro všechny produkty ABRA Gen, viz aktuální obchodní podmínky výrobce.
U skriptování však neplatí, že nepřítomnost licence skriptování "vypíná" jeho použití. Licencia na modul Skriptovanie je potrebná len pre operáciu Kompilácia z agendy Balíčky skriptov. Tzn., že aj v inštalácii bez licencie k tomuto modulu je možné naimportovať už skompilovaný balíček bez zdrojových textov a je možné používanie skompilovaných skriptov (napr. vytvorených na zákazku výrobcom).
Pokiaľ potrebujete skriptovanie vypnúť (myslí sa vypnúť vykonávanie skriptov), je to potrebné urobiť iným spôsobom, viď Vypnutie skriptovania.
Naopak ak nie je skriptovanie nainštalované, nie je k dispozícii agenda Balíčky skriptov a nebude tak možné v systéme plnohodnotne používať agendy a funkcie, ktoré sú na skriptovanie naviazané. Napr. Funkcie pre zaistenie v SCM, Operácie v rámci Web. služieb, Kontrolné body pri module E-maily a interné správy a pod.

Pokiaľ chcete potlačiť vykonávanie skriptov z nejakého konkrétneho balíčka skriptov, môžete v jeho položke Stav nastaviť, že sa nemá používať.
Pokud je třeba skriptování zcela vypnout (např. z důvodu, že je v nějakém skriptu chyba, která brání v provozu), můžete tak učinit spuštěním systému ABRA Gen bez skriptování. To lze provést spuštěním systému ABRA Gen s parametrem -noscripting. Toto vypnutie sa uskutoční len vtedy, pokiaľ užívateľ, ktorý sa do systému prihlási, má súčasne nastavené privilégium Obchádzať skriptovanie. (Z toho dôvodu, aby si bežný užívateľ nemohol vypínať skriptovanie bezdôvodne).
Syntaxe viz popis parametru spuštění -noscripting.
Odporúčame si preveriť, že sa skriptovanie skutočne podarilo vypnúť a že je vypnuté, napr. tak, že sa nezobrazuje voľba Skriptovanie v menu Nápoveda. Viď tiež Informácie o spúšťaných skriptoch.

Aktuálne prihlásenému užívateľovi sa budú spúšťať skripty, pokiaľ sú splnené nasledujúce podmienky:
- skript je z balíčku, který je zkompilován (nebo jen jeho část), viz příznak Zkompilováno
- skript je z balíčka, ktorý má nastavené Používať (viď príznak Stav) alebo má nastavené Ladiť a súčasne má daný užívateľ privilégium Ladiť skripty
- daný užívateľ nemá skriptovanie úplne vypnuté
Dále pozor na to, zda se nejedná-li se o tzv. zastaralý skript (s hodnotou Zastaralá), u něhož je zamezeno jejich spouštění. Dále viz hodnota u daného skriptu v položce Verze kompilace skriptu a Verzování, Deprecated prvky.
Pokud ve skriptování implementujete nějakou požadovanou dynamickou změnu chování číselníku v nějaké vlastní číselníkové položce, je třeba pro ni použít prvek Číselník objektový (nikoli Číselník neobjektový). Prvok Číselník neobjektový nie je schopný implementovať dynamickú zmenu správania danú skriptami k danému objektu.

Ako bolo povedané vyššie, skriptovanie značne rozširuje možnosti systému, no môžu z neho plynúť aj prípadné negatívne dôsledky. Preto je potrebné mať možnosť rýchlo užívateľsky (aj bez existencie práv na prístup do agendy Balíčkov skriptov) zistiť, či aktuálne prihlásenému užívateľovi môžu byť vykonané nejaké skripty.
Seznam všech skriptů, které si lze zobrazit, vytisknout, případně odeslat e-mailem (odeslání skriptů e-mailem je však již vázáno na patřičné právo):
-
v ľubovoľnej agende z menu Nápoveda voľbou Skriptovanie (kedy je k dispozícii a ako funguje, viď popis voľby v menu Nápoveda):
Príklad vyvolaného menu Nápoveda s dostupnou položkou Skriptovanie


V skripte je možné odkazovať sa na iné skripty. Na odkazovanie na skripty medzi balíčkami slúži druh skriptu Knižnica. Je teda možné odkazovať sa na skripty knižníc (nie Business objektov, agend a nevizuálnych číselníkov). Prehľad závislých balíčkov viď záložka Závislosti. Při volání funkcí nebo procedur z jiného skriptu je nutno používat frázi uses s následující konvencí:
uses
'nazev_balicku.nazev_knihovny','nazev_balicku.nazev_knihovny';
Pozor, vyvolanie cez názov balíčka a knižnice nie je citlivé na veľké/malé písmená.
Majme balíček skriptov s názvom napr. abra.sk.vyvoj.ukazka1, v ktorom je o. i. zavedený skript druhu Knižnica s názvom Knižnica1. Chceme sa na neho odkázať z iného skriptu. Potom musíme použiť syntax uses 'abra.sk.vyvoj.ukazka1.Kniznica1'.

Díky tomu, že je možné ve skriptování vytvářet vlastní instance (i vizuálních) objektů a těmto objektům nastavovat události, není možné po opravě zdrojových kódů skriptů a jejich překompilaci provést automaticky náhradu načtených skriptů v cache paměti. Tzn., že pokud editujete skript např. pro agendu a již jste ji měli alespoň jednou otevřenu v rámci daného spuštění ABRA Gen, pak se změna ve skriptu pro danou agendu projeví až po znovunačtení skriptu do paměti.
Možnosti, ako vyvolať znovunačítanie skriptov do pamäte:
- Zavřením a znovuspuštěním systému ABRA Gen.
- Pomocou funkcie Znovu načítať skripty.
- Pri uložení skriptu, ak je začiarknuté Znovu načítať skripty.

Každý háčik dostáva minimálne jeden parameter "Self", v ktorom je mu odovzdávaná inštancia objektu, na ktorom došlo k vyvolaniu háčika.

Aby bolo možné zistiť mená existujúcich vizuálnych prvkov (na jednoduchšie zakomponovanie skriptov do vybraných objektov), je možné si spustiť tzv. Show Inspector. Lze vyvolat z menu Nápověda volbou Zobrazit/Potlačit okno inspektoru nebo provést spuštěním systémuABRA Gen s parametrem -showinspector.
Syntaxe viz parametr spuštění -showinspector.
V obou případech se zobrazí speciální okno (Inspektor), které ukazuje za běhu ABRA Gen informace o komponentě/prvku, nad kterým se nachází kurzor myši. Zobrazené dáta o vybranom komponente je možné zmraziť pomocou klávesu Pause.
Príklad zobrazenia informácií v Show Inšpektore pre prvok obdobia.

FastScript neumožňuje vytváranie (v skripte) vlastných tried, typv a recordov.
Z této skutečnosti vyplývají i omezení skriptování v ABRA Gen. Na miestach, kde je nutné pracovať s existujúcimi recordmi (napr. TRect a TPoint), sa v obálkach objektov (tzn. to, čo je dostupné v skriptovaní) tieto záležitosti prevádzajú na viac hodnôt (napr. súradnice x a y).
Ďalej FastScript nepodporuje prácu s tzv. triedami tried. Takže v prípade potreby tejto funkčnosti v obálkach by to bolo potrebné implementovať konkrétne pre jednotlivé triedy.
FastScript ďalej nepodporuje Interface. Tudíž na všech místech, kde se interně v ABRA Gen pracuje s rozhraními (proměnné typu interface s odkazy na příslušné objekty), se ve skriptování toto vždy musí převést na instance objektů. Z toho ovšem vyplýva ten dôsledok, že pokiaľ si užívateľ pomocou nejakej metódy vytvorí nové inštancie objektov, musí sa postarať aj o ich zrušenie (kým pokiaľ je objekt "držaný za interface", je zrušený automaticky po zrušení všetkých odkazov na daný objekt cez nejaký interface).

Od verze ABRA Gen 23.1. je ARC ve výchozím stavu vypnuté, proto je třeba ve skriptování zajistit správné uvolňování objektů, aby nedocházelo ke vzniku memory leaků. Zároveň se však nepřistupovalo k již uvolněným objektům, což může v nepředvídatelných chvílích způsobovat výjimku typu Access violation, jejíž příčina se obvykle velmi obtížně hledá.
S vypnutým ARC je třeba uvolňovat všechny objekty, které si uživatel ve skritpování sám vytvoří. To platí pre:
- Všechny neinterfacové objekty (typicky TStringList, TNxParameteters, atd).
- Některé interfacové objekty, které jsou získány konkrétními metodami. (Jedná se o metody, které si vytváří tzv. Holdery pro udržení reference na původní interfacové objekty.)
Ve skriptování je u daných metod v nápovědě napsáno: Upozornění - takto získaná objektová proměnná se musí uvolnit voláním <proměnná>Free. Uvolní pouze objekt dočasně vytvořený v rámci skriptovacího prostředí, skutečného objektu v ABRA Gen se nedotkne.
Týká se to i řady metod, které z logiky věci nevytváří pouze nový objekt, ale například vrátí objekt, který již existuje. Pokud si tedy Holder drží referenci, ať již na vytvořený nebo existující objekt, který se bez zavolání metodyFree neuvolní, vznikne tím Memory Leak.
Současně je třeba brát na zřetel, že samotné zavolání metody Free na interface objekt uvolní pouze výše uvedený Holder, ale vlastní interface objekt zanikne až v okamžiku, kdy na něj neexistuje žádná reference (nikdo se na něj neodkazuje).
Níže je uveden kompletní seznam metod (včetně jejich třídy), které vrátí objekt, jež musí uživatel následně sám ve skriptování uvolnit prostřednictvím metody Free, aby nedošlo ke vzniku memory leaku:
- funkce NxCreateDocumentImportManager
- funkce >NxCreateDepositUsage
- funkce >NxSetCustomBusinessObjectFromBOText_1
- funkce >NxCreateRoll
- funkce >NxCreateRoll_1
- funkce >NxCreateInitializedRoll
- funkce >NxCreateContext
- funkce >NxCreateContext_1
- funkce >NxCreateNotLoggedContext
- funkce >NxCreateNotLoggedContext_1
- CFxExchangeDifferences.CreateDiff
- TNxSelectionRequest.Create
- TSiteForm.GetFakeBusinessObject
- TDynSiteForm.CurrentObject
- TNxCustomObjectSpace.CreateObject
- TNxCustomObjectSpace.Load
- TNxCustomObjectSpace.LoadWhenExists
- TNxCustomObjectSpace.CreateClassObject
- TNxCustomBusinessMonikerCollection.FirstBusinessObject
- TNxCustomBusinessMonikerCollection.LastBusinessObject
- TNxConditionLink.GetContext
- TNxCustomObjectDataSet.CurrentObject
- TNxCustomObjectDataSet.ActiveObject
- TNxCustomObjectDataSet.CreateBusinessObject
- TNxCustomBusinessObject.CreateMoniker
- TNxCustomBusinessObject.Clone
- TNxCustomBusinessObject.GetMonikerForFieldCode
- TNxFirm.MajorCorrection
- TBusRollSiteForm
Příklady správného uvolňování ve skriptování
Při psaní skriptů je třeba se řídit stejnými zásadami, jako při běžném programování v Delphi.
V případě vypnutí ARC (Automatického uvolňování objektů) je třeba dbát především na uvolňování všech objektů, které si uživatel ve skriptování sám vytvoří. To platí pro všechny neinterfacové objekty (typicky TStringList, TNxParameteters). Ale to i pro některé interfacové objekty, které jsou vyjmenovány výše.
Následující příklady je třeba chápat pouze jako demonstrační ukázky, které ukazují jednotlivé problémy v co možná nejtriviálnějších konstrukcích. V reálných situacích jsou konstrukce samozřejmě často daleko komplikovanější, ale jejich přesné uvedení by zbytečně komplikovalo vysvětlení podstaty problému.

Nepoužívejte Globální proměnné, nelze zajistit jejich správnou inicializaci, protože sekce mezi begin end na konci unit se nevolá.
Příklad chybné konstrukce:
var
GlobalFlag: Boolean;
begin
GlobalFlag := True; //Toto se nikdy nezavolá
end.
Doporučujeme použít globální úložiště GlobParams, jehož použití můžete navíc zabalit do snadno použitelných funkcí:
//Funkce pro získání hodnoty
function GlobalFlag: Boolean;
begin
Result := GlobParams.ParamAsBoolean('GlobalFlag', True);
end;
//Procedura pro nastavení hodnoty
procedure SetGlobalFlag(AValue: Boolean);
var
mPar: TNxParameter;
begin
mPar:= GlobParams.GetOrCreateParam(dtBoolean, 'GlobalFlag');
mPar.AsBoolean := AValue;
end;

Příklad chybné konstrukce:
procedure DoSomething(AOS: TNxCustomObjectSpace; AValue: Integer);
var
mBO: TNxCustomBusinessObject;
begin
try
case aValue of
1: mBO:= AOS.CreateObject(Class_Firm);
2: mBO:= AOS.CreateObject(Class_Person);
end;
finally
mBO.Free; //Není nezaručeno, že mBO bude správně inicializovaný
end;
end;
Správná konstrukce je tedy následující:
procedure DoSomething(AOS: TNxCustomObjectSpace; AValue: Integer);
var
mBO: TNxCustomBusinessObject;
begin
try
case aValue of
1: mBO:= AOS.CreateObject(Class_Firm);
2: mBO:= AOS.CreateObject(Class_Person);
else
mBO := nil;
end;
finally
mBO.Free; //Je zaručeno, že mBO bude správně inicializovaný a volat .Free nad objektem, který je nil není problém
end;
end;
Případně lze použít tuto konstrukci:
procedure DoSomething(AOS: TNxCustomObjectSpace; AValue: Integer);
var
mBO: TNxCustomBusinessObject;
begin
mBO := nil;
try
case aValue of
1: mBO:= AOS.CreateObject(Class_Firm);
2: mBO:= AOS.CreateObject(Class_Person);
end;
finally
mBO.Free; //Je zaručeno, že mBO bude správně inicializovaný a volat .Free nad objektem, který je nil není problém
end;
end;

Je třeba destruovat všechny neinterfacové objekty.
Mezi typické neinterfacové objekty patří například TStringList, TNxParameteters.
Neuvolněním vytvořených objektů vznikají memory leaky, které při častém opakování mohou po delší době znamenat pád programu způsobený vyčerpáním zdrojů (USER objektů, GDI objektů nebo operační paměti).
Příklad chybné konstrukce:
procedure DoSomething;
var
mSL: TStringlist;
begin
mSL:= TStringlist.Create;
mSL.Add('Takto vznikne memory leak');
end;
Správná konstrukce je tedy následující:
procedure DoSomething;
var
mSL: TStringlist;
begin
mSL:= TStringlist.Create;
try
mSL.Add('Takto nevznikne memory leak');
finally
mSL.Free;
end;
end;
V případě potřeby současně inicializovat více objektů najednou lze použít i konstrukci uvedenou níže.
Tou lze obejít mnohonásobné zanoření try a finally do sebe, což pak značně znepřehledňuje kód.
Předpokladem je, že:
-
Všechny objekty musí být před try nainicializované na nil.
-
Destruktory všech uvolňovaných objektů jsou napsány tak, aby v jejich průběhu nedošlo k vzniku výjimky.
procedure DoSomething;
var
mSL1, mSL2: TStringlist;
begin
mSL1:= nil;
mSL2:= nil;
try
mSL1:= TStringlist.Create;
mSL1.Add('Takto nevznikne memory leak');
mSL2:= TStringlist.Create;
mSL2.Add('Takto nevznikne memory leak');
finally
mSL1.Free;
mSL2.Free;
end;
end;
Některé metody umožní získat odkaz nově vytvořený nebo již existující interface objekt. Zároveň si však při tomto požadavku vytvoří tzv. Holder, který si drží referenci na originální interface objekt.
Jedná se o relativně komplikovanou konstrukci, kterou je zbytečné zde celou popisovat. Podstatné je, že nad získaným odkazem na instancí objektu musíme zavolat metodu Free, která automaticky zajistí destrukci Holderu, a tím nastane i uvolnění reference na originální interface objekt.
Tím se originální objekt nemusí okamžitě uvolnit, pokud na něj existuje jinde v programu nějaká další reference, ale uvolní se automaticky v okamžiku, kdy počet referencí na něj klesne na nulu.
Pokud bychom nad získaným odkazem metodu Free nezavolali, držel by si neuvolněný Holder stále referenci na originální interface objekt a ten by se nikdy neuvolnil. Tím by vznikl memory leak. Je třeba brát v úvahu, že mezi nejběžnější interface objekty patří v ABRA Gen Business objekty, jejichž struktura bývá často členitá, a vzniklý memory leak tam může být relativně velký.
Existuje i řada funkcí a property objektů, které vrací odkaz na již existující interface objekt, a tak z jejich názvu není patrné, že je nutné pro ně volat metodu Free.
Seznam všech funkcí a property objektů pro které je třeba volat následně Free, je uvedená výše.

I když property CurrentObject nevytvoří žádný Business objekt, u kterého by se uživatel mohl domnívat, že ho musí na konci uvolnit, je i přesto voláním této property vytvořen výše zmíněný Holder, který si drží referenci na Business objekt DynSite. Pokud nezavoláme mBO.Free, nedojde k uvolnění Holderu, který si tak bude stále držet referenci na Business objekt DynSite, který tímto rovněž také nikdy neuvolní. Tím vznikne memory leak, a to jak na Holder, tak i na Business objekt DynSite.
Příklad chybné konstrukce:
procedure DoSomething(ASite: TDynSiteForm);
var
mBO: TNxCustomBusinessObject;
begin
mBO := ASite.CurrentObject;
mBO.SetFieldValueAsBoolean('MyField', True);
mBO.Save;
end;
Správná konstrukce je tedy následující:
procedure DoSomething(ASite: TDynSiteForm);
var
mBO: TNxCustomBusinessObject;
begin
mBO := ASite.CurrentObject;
try
mBO.SetFieldValueAsBoolean('MyField', True);
mBO.Save;
finally
mBO.Free;
end;
end;

Volání mOS.Free nic neudělá. Jen přistoupí k danému objektu, a protože ten nemá Holder, tak nic neprovede (neuvolní ho).
Příklad chybné konstrukce:
procedure DoSomething(ASite: TDynSiteForm);
var
mOS: TNxCustomObjectSpace;
begin
mOS := ASite.BaseObjectSpace;
try
...
finally
mOS.Free; //Nic neudělá
end;
end;
Správná konstrukce je tedy následující:
procedure DoSomething(ASite: TDynSiteForm);
var
mOS: TNxCustomObjectSpace;
begin
mOS := ASite.BaseObjectSpace;
...
end;

Jedná se o situaci, kdy například metodou ObjectSpace.CreateObject vytvoříme nový hlavní Business objekt a následně si v některé z jeho kolekcí vytvoříme novou položku.
V takovém případě je třeba provést destrukci pouze na hlavní Business objekt a nikoliv na vytvořenou položku v kolekci, protože o destrukci položky se postará sám hlavní objekt, resp. jeho Moniker dané kolekce.
Příklad chybné konstrukce:
procedure DoSomething(ASite: TDynSiteForm);
var
mObjectSpace: TNxCustomObjectSpace;
mBO: TNxCustomBusinessObject;
mRows: TNxCustomBusinessMonikerCollection;
mRow: TNxCustomBusinessObject;
begin
mObjectSpace := ASite.BaseObjectSpace;
mBO:= mObjectSpace.CreateObject(Class_PLMPieceList);
try
mBO.Load('1000000101');
mRows := mBO.GetLoadedCollectionMonikerForFieldCode(mBO.GetFieldCode('ROWS'));
mRow := mRows.AddNewObject;
finally
mBO.Free;
mRow.free; //Zde to spadne na výjimku, protože se pokusíte přistoupit k již zdestruovanému objektu
end;
end;
Správná konstrukce je tedy následující:
procedure DoSomething(ASite: TDynSiteForm);
var
mObjectSpace: TNxCustomObjectSpace;
mBO: TNxCustomBusinessObject;
mRows: TNxCustomBusinessMonikerCollection;
mRow: TNxCustomBusinessObject;
begin
mObjectSpace := ASite.BaseObjectSpace;
mBO:= mObjectSpace.CreateObject(Class_PLMPieceList);
try
mBO.Load('1000000101');
mRows := mBO.GetLoadedCollectionMonikerForFieldCode(mBO.GetFieldCode('ROWS'));
mRow := mRows.AddNewObject;
finally
mBO.Free;
end;
end;
Přípustná je i následující konstrukce, ovšem volání mRow.Free nic neudělá. Jen přistoupí k danému objektu, a protože ten nemá Holder, tak nic neprovede (neuvolní ho).
procedure DoSomething(ASite: TDynSiteForm);
var
mObjectSpace: TNxCustomObjectSpace;
mBO: TNxCustomBusinessObject;
mRows: TNxCustomBusinessMonikerCollection;
mRow: TNxCustomBusinessObject;
begin
mObjectSpace := ASite.BaseObjectSpace;
mBO:= mObjectSpace.CreateObject(Class_PLMPieceList);
try
mBO.Load('1000000101');
mRows := mBO.GetLoadedCollectionMonikerForFieldCode(mBO.GetFieldCode('ROWS'));
mRow := mRows.AddNewObject;
finally
mRow.Free; //Nic neudělá
mBO.Free;
end;
end;

Vždy je třeba dbát na to, aby vytvoření objektu bylo před try a destrukce objektu je ve finally, a to samozřejmě na stejné úrovni.
Zároveň upozorňujeme na častou chybu, kdy je objekt vytvářen v cyklu, ale destruován je pouze jednou, nebo je naopak vytvořen pouze jednou a destruován je v cyklu.
Příklad chybné konstrukce: Business objekt se vytváří n-krát v cyklu, ale uvolní se pouze ten poslední. Z tohoto důvodu může dojít ke vzniku memory leaků. Navíc pokud by parametr aSL neobsahoval žádnou položku, mohlo by dojít k uvolnění neinicializované proměnné mBO.
procedure DoSomething(ASite: TDynSiteForm);
var
mOS: TNxCustomObjectSpace;
begin
mOS := ASite.BaseObjectSpace;
try
...
finally
mOS.Free; //Nic neudělá
end;
end;
Další příklad chybné konstrukce: Business objekt se vytváří pouze jednou, ale destruuje se v cyklu.
Toto velmi pravděpodobně způsobí vznik výjimky při opakovaném volání metody Load, protože ta se bude aplikovat na již zdestruovaném objektu.
procedure DoSomething(ASite: TDynSiteForm; aSL: TStringList);
var
mObjectSpace: TNxCustomObjectSpace;
mBO: TNxCustomBusinessObject;
I: Integer;
begin
mObjectSpace := ASite.BaseObjectSpace;
mBO:= mObjectSpace.CreateObject(Class_PLMPieceList); //Business objket se vytváří pouze jednou
for I:=0 to aSL.Count-1 do
begin
try
mBO.Load(SL[I]); //Zde se při opakovaném průchodu zavolá Load nad již zdestruovaným Business objektem
...
finally
mBO.Free; //Ale destruuje se v cyklu
end;
end;
end;
Správná konstrukce je tedy následující:
procedure DoSomething(ASite: TDynSiteForm; aSL: TStringList);
var
mObjectSpace: TNxCustomObjectSpace;
mBO: TNxCustomBusinessObject;
I: Integer;
begin
mObjectSpace := ASite.BaseObjectSpace;
for I:=0 to aSL.Count-1 do
begin
mBO:= mObjectSpace.CreateObject(Class_PLMPieceList); //Business objket se vytváří v cyklu
try
mBO.Load(SL[I]); //Load se zavolá vždy nad novou instancí Business objektu
...
finally
mBO.Free; //Business objekt se rovněž destruuje v cyklu
end;
end;
end;
Přípustná je i konstrukce níže, avšak pouze za předpokladu, že se v cyklu po Load nevolá Save. ABRA Gen neumožňuje jeden a ten samý objekt používat ve výchozím stavu opakovaně a nahlásí chybu.
procedure DoSomething(ASite: TDynSiteForm; aSL: TStringList);
var
mObjectSpace: TNxCustomObjectSpace;
mBO: TNxCustomBusinessObject;
I: Integer;
begin
mObjectSpace := ASite.BaseObjectSpace;
mBO:= mObjectSpace.CreateObject(Class_PLMPieceList); //Business objket se vytváří pouze jednou
try
for I:=0 to aSL.Count-1 do
begin
mBO.Load(SL[I]); //Load se zavolá stále na nd stejnou instancí Business objektu
...
end;
finally
mBO.Free; //Business objekt se rovněž destruuje pouze jednou
end;
end;

Pokud nějaká námi vytvořená funkce vrací novou instanci objektu, pak ji musíme správně pojmenovat, aby bylo zřejmé, že vrácený objekt je třeba zdestruovat.
Například pokud naše funkce bude vytvářet novou instanci formuláře, pojmenujme ji CreateForm a výsledek vracejme v Resultu a ne var parametru.
Příklad chybné konstrukce: Z názvu funkce není na první pohled zřejmé, že vrací novou instanci formuláře, kterou je třeba následně zdestruovat.
function GetMyForm: TForm;
begin
Result := TForm.Create(nil);
...
end;
Příklad chybné konstrukce: Název procedury je již lepší, ale v Delphi není obvykle zvykem, aby procedura vracela novou instanci objektu ve var parametru.
procedure CreateMyForm(var AForm: TForm);
begin
AForm := TForm.Create(nil);
...
end;
Správná konstrukce:
function CreateMyForm: TForm;
begin
Result := TForm.Create(nil);
...
end;

Preto, aby bolo možné SQL dopyty pripraviť už na verziu 22.0 a prechod na Unicode verziu sa čo najviac urýchlil, bola do ABRA Gen implementovaná technológia zástupných znakov, ktoré podľa verzie ABRA Gen doplnia nové nevyhnutné časti SQL dopytov.
Od verzie 22.0.0 ServicePack 26 respektíve 22.0.1 ServicePack 24 sú tieto zástupné znaky nahradené prázdnym znakom.
Od verzie 22.1.0 ServicePack 4 respektíve 22.1.1. ServicePack 3 a vyššie sú nahradené takto:
Firebird:
@{unicodeNvarcharCast(String what, int size, boolean withCollate)} vloží len zadané ID
Ostatné zástupné znaky, pokiaľ budú použité, sú nahradené prázdnym znakom.

Praktické příklady využití skriptování naleznete v samostatné kapitole.

Počas skriptovania môže dôjsť (vinou zlého skriptu) nielen k chybám vo vlastnom priebehu skriptovania, ale aj k chybám následným, a je preto dôležité vedieť, že prvotná príčina môže byť napr. práve v chybne napísanom užívateľskom skripte. Preto chyby, ktoré vznikli v priebehu skriptovania, sa užívateľovi zobrazujú s uvedením informácie, že k chybe došlo počas skriptovania.
K ladění lze využívat nástroj ScriptDebugger.exe.
Podpora ladění nesmí být vypnuta parametrem v konfiguračním souboru nexus.cfg. Více viz kap. Konfigurační soubor Nexus.cfg - oddíly a parametry, Sekce [ScriptDebugger].
Implementátor skriptovania môže na ladenie využiť i funkciu ShowMessage(), pomocou ktorej je možné zobrazovať hlásenia. Text chyby sa tiež posiela pomocou funkcie OutputDebugStr(). Texty odovzdané funkcii OutputDebugStr je možné "chytať" pomocou nejakého externého "zobrazovača" logov, napr. pomocou nástroja Sysinternals DebugView.

V rámci některých upgrade systému ABRA Gen může dojít k nějakým významným změnám (změny vývojového prostředí, související změny struktur, zásadní změny ve skriptování apod.), které vedou k tomu, že je třeba existující skripty upravit, příp. minimálně zkontrolovat. V takovém případě jsou takové skripty při procesu update automaticky nastaveny jako "zastaralé" (viz položka Verze kompilace skriptu na řádcích balíčků skriptů) a je zamezeno jejich spuštění.
Dále některé prvky skriptování mohou být v čase označeny atributem
Deprecated Atribút označujúci nejaký prvok ako zastaralý. Typicky ide o prvok, ktorý je v budúcnosti určený na zrušenie (bol napr. nahradený nejakým iným prvkom, inou funkcionalitou).. Takto označené prvky je zatiaľ možné v skriptovaní používať, ale v budúcnosti sa s nimi nepočíta, pretože boli nahradené alternatívnym kódom. Je možné ich skryť nastavením parametra HideDeprecated.
Současně jsou dodávány *.adc definiční soubory skriptování, vygenerované k příslušným verzím, pro porovnání dalších případných rozdílů ve skriptování pomocí nástroje DefsComp.exe. Porovnává dva *.adc soubory, např. *.adc k aktuální verzi s *.adc souborem verze předchozí. Tyto soubory nelze vytvořit uživatelsky, ale jsou dodávány výrobcem. Je možné ich nájsť v inštalačnom adresári ABRA Gen v podzložke ..\Doc\defscomp.

Pokud potřebujete logovat průběh nějaké funkcionality řešené pomocí skriptování, můžete využít k tomu určenou třídu TNxScriptingLog a její metody, především metodu WriteEvent. V konfiguračním souboru nexus.cfg v sekci logování, musí být nastaveno logování třídy Scripting.