Návrhový vzor na podmínky

ondrej256
Člen | 186
+
0
-

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
+
0
-

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 | 1186
+
0
-

@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.