Pri neexistujucom zázname má Model vrátiť false alebo vyhodiť výnimku?

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
srigi
Nette Blogger | 558
+
0
-

Ako Model používam Doctrine. Nejaká entita modelu má asi cca takúto formu (api):

<?php
class Pages extendes BasePages // BasePages extends Doctrine_Record
{

  public static function getByUrl($url, $lang)
  {
      $q = Doctrine_Query::create()
          ->from('Pages p')
          ->leftJoin('p.PagesI18n i')
          ->leftJoin('i.Languages l')
          ->where('i.url = ?', $url)
          ->andWhere('l.code = ?', $lang);

       return $q->fetchOne();
  }
}
?>

Rozmýšľam ako sa správať keď sa záznam nenájde. Horeuvedený kód vtedy vráti cca prázdny objekt Doctrine_Record, ktorý si musím „ocheckovať“ v presenteri. Tak ma napadlo, že či checkovačku nehodiť už do tej model metódy a vracať false.

V presenteri ale na základe toho overenia aj tak vyhadzujem pri prázdnom výsledku výnimku, tak rozmýšľam že nebudem vracať ani false a výnimky budem vyhadzovať v Modely.

Ktorý prístup je z hľadiska MVP najsprávnejší, poradte best practise.

THX.

_Martin_
Generous Backer | 679
+
0
-

Vzhledem k tomu, že výjimky se dají velmi dobře zpracovat, byl bych pro výjimku v modelu – a nejlíp nějakou typu ModelNotFoundException. Kterou lze kdekoliv odchytit a zpracovat (třeba v presenteru převést na BadRequestException).

jiriknesl
Člen | 56
+
0
-

Co se čistoty týká, vyjde to podle mě nastejno. Používám oba přístupy a vracení null nebo false je praktičtější než NotFoundException.

if(null === ($article = $articlesPersistence->fetchByUrl($url, $lang))
	$this->throw404;

// ... prace s clankem

vs:

try
{
	$article = $articlesPersistence->fetchByUrl($url, $lang);

	// ... prace s clankem

}
catch (PersistenceNotFoundException $e)
{
	$this->throw404;
}
_Martin_
Generous Backer | 679
+
0
-

Jednodušší kód může být výhodou. Ono zpracování výjimky taky může být o něco málo roztahanější, než uvádíš:

try {
	$article = $articlesPersistence->fetchByUrl($url, $lang);
} catch (PersistenceNotFoundException $e) {
	$this->throw404();
}

// ... prace s clankem

Ale je to spíš otázka, co komu vyhovuje. U výjimek nacházím tu výhodu, že je má potom model (z pohledu zpracování chyb) konzistentní chování – je jedno, zda volám fetchByUrl nebo předávám ID v konstruktoru ($model = new Article($id)) – zpracování chyb je vždy stejné.

P.S. Když píšeš PHP kód, použij prosím zápis /--php, aby se použil zvýrazňovač syntaxe.

Editoval _Martin_ (12. 2. 2010 12:20)

Ondřej Mirtes
Člen | 1536
+
0
-

Osobně vracím výsledek dotazu:

Metoda modelu:

return $this->db->fetch(....);

A v Presenteru kontroluji na začátku render metody existenci záznamu takto:

if ($result == NULL) {
	throw new BadRequestException('Record not found.');
}

Přijde mi to úsporné a dostačující :)

srigi
Nette Blogger | 558
+
0
-

Asi najlogickejsie je naozaj vratit NULL a v presenteri sa podla toho zariadit. Predsa len ked dotazujem model, ocakavam return hodnotu a nie exception (tu iba v pripade fatalneho zlyhania operacie). OK THX.

Patrik Votoček
Člen | 2221
+
0
-

Přesně jak říka srigi. Pokud je výsledkem 0 záznamů tak vrátit NULL. Pokud je v dotazu na model chyba tak jasně exception. Ještě teda já to řeším tak že chci aby mě v případě kdy očekávám pole a výsledek je 0 záznamů vrátím místo NULL prázdný array() kvuli foreachy…

Ondřej Mirtes
Člen | 1536
+
0
-

Takhle se dibi chová, to je dost praktický :)

Blizzy
Člen | 149
+
0
-

Pro model není nic výjiměčného, když podle určitých parametrů nenalezne žádná odpovídající data.

Pro presenter už to v určitých případech může být výjimečné, protože se aplikace snaží zpracovávat data, která neexistují, proto by se výjimky tohoto typu měly vyhazovat v presenteru.

Tímto způsobem by se mělo postupovat u všech případů, kde se rozhoduje, zda použít výjimku (teď není řeč o řídících výjimkách).

_Martin_
Generous Backer | 679
+
0
-

Blizzy napsal(a):

Pro model není nic výjiměčného, když podle určitých parametrů nenalezne žádná odpovídající data.

OK, asi bych to měl upřesnit: je rozdíl, pokud jde o vyhledávání a nebo o získání konkrétního modelu. V prvním případě je výsledek nejistý a lze čekat, že se mi může vrátit prázdné pole (nebo nějaký prázdný objekt, přes který lze iterovat,…). Ve druhém případě si žádám konkrétní model (článek s ID 5/článek se jménem/… záleží na identifikátoru). Pak očekávám výjimku, pokud model neexistuje. Je to samé, jako se soubory na disku.