checkExist()
je jedna ze “standardizovaných” statických metod na tabulkách v Dynamics AX. Doplňuje metodu exist()
tak, že navíc zobrazuje chybovou zprávu v infologu (znění chyby bývá implementováno v samostatné metodě txtNotExist()
). Hodně týmů vytváří jen medody find()
a exist()
, což je škoda, protože vypsání chybové zprávy v případě nenalezeného záznamu je běžný scénář a je zbytečné takovou logiku duplikovat na různých místech kódu volajících exist()
, nemluvě o nemožnosti změnit text chyby na jediném centrálním místě.
Trochu překvapivě se i v takto jednoduché metodě dá chybovat. Dnes jsem takovou chybu objevil v průběhu revize kódu a bohužel jsem ji našel i na mnoha jiných místech, včetně standardního kódu AX.
Mějme následující kus kódu, který validuje existenci _bomId
v BOMTable
a provede nějakou akci, pokud validace uspěje:
if (BOMTable::checkExist(_bomId)) { BOMTable::setCheckBOM(_bomId, false); }
Logický předpoklad je, že pokud je tento kód zavolán s prázdným _bomId
(což se může snadno stát), setCheckBOM()
se neprovede a zobrazí se nějaká informace o neexistenci BOMu. Skutečný výstup ale je:
“Cannot edit a record in Bills of materials (BOMTable). The record has never been selected.”
Validace zřejmě uspěla, přestože žádný záznam s prázdným BOMId
neexistuje (a ani nemůže, protože jde o povinné pole). Neplatná hodnota se tak dostala do dalšího zpracování a způsobila tam vyhození výjimky.
Důvod je dobře patrný z kódu metody checkExist()
:
static boolean checkExist(BOMId bomNum) { if (bomNum && ! BOMTable::exist(bomNum)) return checkFailed(strfmt(BOMTable::txtNotExist(),bomNum)); return true; }
Je-li bomNum
prázné, hned první podmínka v if
není splněna a metoda checkExist()
vrátí true! Neočekávaná prázdná hodnota je tak úspěšně zvalidována a celá validace ztratila smysl.
Jak to má správně vypadat?
Stačí odebrat první část podmínky a nechat celou validační logiku na metodě exist()
. Od toho metoda exist()
také je.
static boolean checkExist(BOMId bomNum) { if (!BOMTable::exist(bomNum)) return checkFailed(strfmt(BOMTable::txtNotExist(),bomNum)); return true; }
Protože ani metoda exist()
na BOMTable
není implementována nejlépe, správně vrací false pro prázdnou hodnotu bomNum
. Podmínka v checkExist()
je tedy splněna, metoda vrátí false a do infologu vypíše “Bill of materials does not exist”.