Created
December 13, 2020 21:56
-
-
Save rafaelfelipesantos/22a87031275b0bb405df03db764c9e7a to your computer and use it in GitHub Desktop.
Alternativa elegante ao Enum em PHP sem usar constants
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// Vamos ao cenário hipotético: | |
interface PaymentStatus | |
{ | |
const PAID = 1; | |
const CANCELED = 2; | |
// Isso soa familiar? | |
} | |
// Tudo bem, você não pode reescrever o valor de constants que pertencem à interfaces no PHP, | |
// mas você realmente quer um valor INTEGER ou um STATUS VÁLIDO que possa CONFIAR? | |
// Nem quero entrar no mérito do Pattern State, mas nesse gist quero apenas mostrar que existe vida além | |
// das constants. Ah, se você pensou em Reflection, pode ir tirando o seu cavalinho da chuva rs. | |
// INTEGER, STATUS VÁLIDO, CONFIAR, CONFIANÇA, OOP... | |
// Ooooh, temos um Sherlock Holmes aqui. | |
// Sigam-me os bons: | |
interface PaymentStatuses | |
{ | |
public function equals(PaymentStatuses $other): bool; | |
} | |
trait Compare | |
{ | |
public function equals(PaymentStatuses $other): bool | |
{ | |
return $other instanceof $this; | |
} | |
} | |
final class Paid implements PaymentStatuses | |
{ | |
use Compare; | |
} | |
final class Canceled implements PaymentStatuses | |
{ | |
use Compare; | |
} | |
final class PaymentStatus | |
{ | |
private function __construct() {} | |
public static function PAID(): PaymentStatuses | |
{ | |
return new Paid(); | |
} | |
public static function CANCELED(): PaymentStatuses | |
{ | |
return new Canceled(); | |
} | |
// ... | |
} | |
// Agora vamos ao que interessa: | |
class PaymentStatusTest extends TestCase | |
{ | |
public function testShouldCreateAValidStatus() | |
{ | |
$paid = PaymentStatus::PAID(); | |
$this->assertInstanceOf(PaymentStatuses::class, $paid); | |
// Por um segundo, esqueça o instanceOf e imagine que usou constants do tipo INTEGER. | |
// Sim, você compararia dois números. Não é esse o valor da constant? | |
} | |
public function testShouldValidadeEqualityBetweenStatuses() | |
{ | |
$paid = PaymentStatus::PAID(); | |
$this->assertTrue($paid->equals(clone $paid)); | |
// Tudo bem, 1 poder até ser igual à 1, mas a classe Client espera um status válido ou um integer? | |
} | |
public function testShouldValidadeDiffBetweenStatuses() | |
{ | |
$paid = PaymentStatus::PAID(); | |
$this->assertFalse($paid->equals(PaymentStatus::CANCELED())); | |
// Novamente, 1 !== 2. | |
// Imagine usar Reclection só pra GARANTIR um status válido dentre os status da sua aplicação. | |
// Outro ponto, o que me impede de chamar PaymentStatus::AQUI_EH_BR; Entendeu? | |
} | |
} | |
// Quando eu digo um Client que espere um status válido, estou falando sobre confiança: | |
final class Bill | |
{ | |
private PaymentStatuses $status; | |
public function __construct(PaymentStatuses $status) | |
{ | |
$this->status = $status; | |
// O que é que eu vou fazer com um INT aqui? | |
// E quando o status for alterado, só que antes disso você precisa garantir o fluxo padrão | |
// para que seja alterado. E sim, nesse caso o pattern state é muito bem vindo. | |
} | |
} | |
// Bom, espero que tenha entendido a problemática das constants para guardar valores referentes à estados da aplicação. | |
// O Rafael do futuro tem o hábito de esquecer as coisas que ele aprende no passado. Então, quando esse dia chegar e | |
// for pesquisar no Google, talvez caia aqui! | |
// Forte abraço :) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment