Ho bisogno di creare un sistema di sponsorizzazione con requisiti aziendali complessi. Fondamentalmente, dopo che un utente effettua un pagamento, il sistema dovrebbe essere attivato. Esistono molti tipi diversi di sponsorizzazione, quindi ho trovato astrazioni per rendere la mia vita più semplice ora e in futuro.
Per usare il polimorfismo, ho creato per prima cosa una classe astratta che erediterebbe ogni sistema sponsor e implementare ogni metodo astratto necessario.
Ecco la classe:
abstract class SponsorshipService
{
/** @var UserKang */
protected $user;
/** @var UserKang */
protected $sponsor;
/** @var SponsorUser */
protected $sponsorship;
/** @var int */
protected $amount;
/** @var BillingMicroService */
protected $billingMicroService;
/** @var MailMicroService */
protected $mailMicroService;
public function __construct(BillingMicroService $billingMicroService, MailMicroService $mailMicroService)
{
$this->billingMicroService = $billingMicroService;
$this->mailMicroService = $mailMicroService;
}
public function apply(UserKang $user, int $amount): bool
{
$this->user = $user;
$this->amount = $amount;
if (!$this->user->isSponsored()) {
return false;
}
$this->sponsor = $this->user->getSponsor();
$this->sponsorship = $this->user->getSponsorship();
if (!$this->checkSponsorshipAppliance()) {
return false;
}
$offeredCash = $this->getOfferedCash();
$isCreditOffered = $this->offerCreditSponsorship($offeredCash);
if (!$isCreditOffered) {
return false;
}
$this->sendEmail();
$this->updateSponsorship();
}
abstract protected function checkSponsorshipAppliance(): bool;
abstract protected function getOfferedCash(): int;
abstract protected function offerCreditSponsorship(): bool;
abstract protected function sendEmail(): void;
abstract protected function updateSponsorship(): void;
}
Questo è tutto buono finora, ma mi piacerebbe testare ciascuno di questi metodi astratti per ogni implementazione di SponsorshipService che farò. Ma li ho resi protetti, perché non sembra che abbiano alcuna ragione per essere pubblici, e penso che i metodi meno pubblici di una classe lo siano, più è facile da usare e anche più sicuro.
Cosa c'è che non va in questo design? Chiaramente non voglio testare unitamente apply
in ogni modo possibile per ogni implementazione, dato che sarebbe un incubo tanto quanto lo sarebbe in futuro.