Skip to content

Instantly share code, notes, and snippets.

@hallboav
Created November 26, 2019 04:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hallboav/94ab98cc66c46dca9a2579dd89617921 to your computer and use it in GitHub Desktop.
Save hallboav/94ab98cc66c46dca9a2579dd89617921 to your computer and use it in GitHub Desktop.
Hexagonal Architecture example
<?php
// Vendor
namespace VeryNiceLib {
class StdoutLogger
{
private $stream;
public function __construct()
{
$this->stream = @fopen('php://stdout', 'w');
}
public function log(string $message): void
{
@fwrite($this->stream, $message);
fflush($this->stream);
}
}
}
// Código escrito por nós. Não é o domínio; são apenas conectores entre os vendors e o domínio.
namespace DominioAdapter {
class VeryNiceLibAdapter implements \Dominio\AnotadorInterface
{
private $logger;
public function __construct(\VeryNiceLib\StdoutLogger $logger)
{
$this->logger = $logger;
}
public function anotar(string $mensagem): void
{
$this->logger->log($mensagem);
}
}
}
// Domínio, nunca deve mudar; é o core do negócio.
namespace Dominio {
interface AnotadorInterface
{
public function anotar(string $mensagem): void;
}
abstract class Criatura
{
protected $nome;
protected $saude;
protected $anotador;
public function __construct(string $nome, int $saude, AnotadorInterface $anotador = null)
{
$this->nome = $nome;
$this->saude = $saude;
$this->anotador = $anotador;
}
public function obterNome(): string
{
return $this->nome;
}
public function obterSaude(): int
{
return $this->saude;
}
public function determinarSaude(int $saude): self
{
$this->saude = $saude;
return $this;
}
public function atacar(Criatura $alvo): void
{
$danoMaximo = ceil(constant(get_class($alvo) . '::SAUDE_MAXIMA') / 8);
$dano = rand(0, $danoMaximo);
$saudeAtualizada = 0 < ($alvo->obterSaude() - $dano) ? $alvo->obterSaude() - $dano : 0;
$alvo->determinarSaude($saudeAtualizada);
if (null !== $this->anotador) {
$mensagem = sprintf("Criatura %s está atacando %s com dano de %d\n", $this->obterNome(), $alvo->obterNome(), $dano);
$this->anotador->anotar($mensagem);
}
}
public function estaMorto(): bool
{
return 0 === $this->obterSaude();
}
}
class Dragao extends Criatura
{
const SAUDE_MAXIMA = 500;
public function __construct(AnotadorInterface $anotador = null)
{
parent::__construct('Dragon', self::SAUDE_MAXIMA, $anotador);
}
}
class Jogador extends Criatura
{
const SAUDE_MAXIMA = 300;
public function __construct(string $nome, AnotadorInterface $anotador = null)
{
parent::__construct($nome, self::SAUDE_MAXIMA, $anotador);
}
}
}
// namespace global
namespace {
$logger = new \VeryNiceLib\StdoutLogger();
$anotador = new \DominioAdapter\VeryNiceLibAdapter($logger);
// uso da API
$dragao = new \Dominio\Dragao($anotador);
$jogador = new \Dominio\Jogador('Hallison', $anotador);
while (!$dragao->estaMorto()) {
$jogador->atacar($dragao);
if ($dragao->estaMorto()) {
echo 'Dragão morreu.', PHP_EOL;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment