Problematika hierarchie a použití výjimek v PHP

Zdroje

Doporučuji přečíst nejprve následující dva články a kouknout na existující výjimky, které jsou definovány v SPL v PHP.

Obecné rozdělení výjimek

  • Usage error (důležitý je text výjimky, nikoliv typ; lze mu předejít na místě, kde je metoda volána)
  • System error
    • Logical error (důležitý je typ výjimky pro přesné zachytávání; nelze jim předejít)
    • System failures (nezachytávají se)

(Podrobněji je to popsáno v prvním výše odkázaném článku.)

Výjimky v PHP

  1. Dynamic call
  2. Runtime = nelze zachytit kontrolou argumentů
  3. Logic = neplatný argument

(Podrobněji popsáno v druhém výše odkázaném článku.)

Logic

  1. DomainException (value does not adhere to a defined valid data domain)
  2. InvalidArgumentException (an argument does not match with the expected value)
  3. LengthException (length is invalid)
  4. OutOfRangeException (value does not match with a range)

Runtime

  1. OutOfBoundsException (value is not a valid key)
  2. OverflowException (adding an element into a full container)
  3. RangeException (an invalid range is given)
  4. UnderflowException (trying to remove an element of an empty container)
  5. UnexpectedValueException (value does not match with a set of values)

Ukázkový příklad

V třídě RegistrationManager existuje metoda activateUser, která slouží k aktivaci účtu uživatele pomocí odkazu, který dostane po registraci e-mailem. Metoda má dva parametry – $userId a $activationKey.

Seznam problémů, které mohou nastat

  1. Parametry mají nesprávný tvar. (Např. $userId není číslo nebo $activationKey nemá správný počet znaků.)
  2. Uživatel s daným $userId neexistuje.
  3. Uživatel s daným $userId má účet již aktivovaný.
  4. Aktivační klíč je neplatný.

Požadavky na řešení

  1. Při odchytávání chyb musí být možné od sebe jednotlivé chyby jednoznačně rozlišit.
  2. Zprávy ve výjimkách jsou pro programátora. Informační texty pro uživatele se sestavují až v presenteru a nesmí být závislé na zprávách ve výjimkách.

Rozbor jednotlivých problémů

Parametry mají nesprávný tvar

  • Usage error → Logická chyba
  • Použil bych InvalidArgumentException (SPL) s popisnou zprávou.
  • Pro nesprávný počet znaků v parametru $activationKey by šla použít i LengthException, ale vadí mi, že nedědí od InvalidArgumentException.

Uživatel s daným ID neexistuje

  • Runtime chyba
  • Nelíbí se mi žádná výjimka z SPL ani z Nette. (Pokud bych si musel vybrat, tak nejbližší mi přijde UnexpectedValueException z SPL a InvalidStateException z Nette.)
  • Vytvořil bych tedy nějakou vlastní výjimku, asi EntityNotFoundException (extends RuntimeException). Napadá vás nějaký lepší název?

Uživatel s daným ID má účet již aktivovaný

  • Runtime chyba
  • Použil bych asi InvalidStateException (Nette). UnexpectedValueException z SPL by ale asi taky šla, ale kolidovala by s výjimkou pro neplatnost aktivačního klíče.

Aktivační klíč je neplatný

  • Runtime chyba
  • Použil bych asi UnexpectedValueException (SPL), ale nejsem si moc jist, zda to odpovídá její definici (a value does not match with a set of values). Spíš by seděla definice z InvalidArgumentException (an argument does not match with the expected value), jenomže ta nedědí od RuntimeException.
  • Nebo vytvořit novou výjimku InvalidActionKeyException?

Další poznámky

  • V PHP lze kromě typu výjimky rozlišovat jednotlivé chyby i pomocí chybového kódu. To např. C# nemá. Nepodařilo se mi najít žádnou Best Practice, jak s kódy výjimek pracovat.
  • Co dělat v případě, že v metodě jsou dvě místa, kde může dojít k EntityNotFoundException a potřebujeme je rozlišit?
    1. Použít kód výjimky jako prosté číslo – fuj!
    2. Použít kód výjimky jako konstantu RegistrationManageru – asi můj favorit
    3. Použít kód výjimky jako konstantu potomka EntityNotFoundException – Jak se bude jmenovat? Stejně s rozlišením pomocí jmenných prostorů?
    4. Vytvořit dvě nové výjimky dědící od EntityNotFoundException
  • V budoucnu se mohou objevit další místa, kde bude vhodné vyhodit stejnou výjimku, jako na nějakém jiném řádku. Není lepší od začátku všude rvát kódy výjimek? S tím souvisí otázka, kam s konstantami, které tyto kódy reprezentují.

Jak řešíte problematiku použití výjimek vy? Řešili byste ukázkový příklad jinak?

Článek byl publikován 31. 12. 2010 02:33

Komentáře

paranoiq

Co dělat v případě, že v metodě jsou dvě místa, kde může dojít k EntityNotFou­ndException a potřebujeme je rozlišit?

e. pokud se liší zpracováním, tak je možné výjimku na jednom místě zachytit a transformovat na jinou

Odpovědět
Patrik Votocek (Vrtak-CZ)

Pokud si dobre pamatuju tak nenalezena data se v Doctrine vyhazuje NoResultException. Ale nemuzu overit (jsem omezen mobilem).

Odpovědět

Přidat komentář

 

Navigace


Kontakt

Jan Tvrdík
ICQ: 238-999-481
MSN: jan.tvrdik@live.com