Návrhový vzor na podmínky
- ondrej256
- Člen | 187
Ahoj,
dělám na komplexním systému a osvědčilo se mně vyčleňovat rozhodovací podmínky do separátní třídy.
Například mám situaci, kdy rozhoduju zda objednávka může být editována. Abych ji mohl editovat tak musí být splněny následující podmínky:
- uživatel musí být admin nebo vedoucí
- objednávka být ve stavu „nová“
- a dalších nějakých 5 podmínek
Tuto podmínku používám na několika místech v aplikaci. Proto jsem si vytvořil třídu:
<?php
class OrderValidator {
public function canEdit(Order $order) {
if ($order->getStatus() !== 'new') return FALSE
....
return TRUE;
}
}
Když je pak požadavek na změnu podmínky zda se objednávka může nebo nemůže editovat, vím že mám šáhnout do třídy OrderValidator a zároveń vím, že když to změním na tomto jednom místě tak se to projeví v celé aplikaci. Dobře se na to píšou testy, je to přehledné a čitelné.
Na toto řešení jsem si přišel sám a napadlo mně zda neexistuje nějaký návrhový vzor, který je přesně pro toto použití. Pokud nějaký návrhový vzor exituje tak bych to rád používal v jeho duchu, něco si o něm přečetl apod. Používáte něco podobného nebo znáte nějaký návhový vzor, který tomuto použití odpovídá?
Díky za odpovědi
- Jan Mikeš
- Člen | 771
Mám pocit, že to co hledáš je Specification pattern
PS. ještě ti přiložím malou ukázku jak používáme u nás, třídu zaregistruji jako service, díky tomu má autowiring (dokáže pracovat s DB) a zároveň i specifikaci dokážu injectovat tam kde ji potřebuji:
<?php declare (strict_types=1);
namespace OdbavTo\Domain\Specifications\Email;
use OdbavTo\Domain\Model\Customer\User\UserNotFoundException;
use OdbavTo\Domain\Model\Customer\User\UserRepository;
use OdbavTo\Domain\Model\Identity\Email;
class EmailIsUnique implements EmailSpecification
{
/**
* @var UserRepository
*/
private $userRepository;
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function isSatisfiedBy(Email $email): bool
{
try {
$this->userRepository->userOfEmail($email);
} catch (UserNotFoundException $e) {
return TRUE;
}
return FALSE;
}
}
Editoval Jan Mikeš (5. 5. 2017 16:54)
- Felix
- Nette Core | 1245
@JanMikeš Specification pattern je fajn. Ale asi bych ho
neregistroval jako „sluzbu“. Nybrz mel neco jako
ConditionResolver
, ktery by treba umel injectovat nejake veci,
mozna IConditionResolver
jako interface a prislusnou implementaci
(OrderConditionResolver
).
Just say`in.