nível de acoplamento • Alto esforço cognitivo para entender o projeto • Dificuldade de onboarding • Uma pequena mudança numa funcionalidade quebra outras Big Ball of Mud
$id, public string $email ) {} } class TokenIssuer { public function issue(int $uniqueIdentifier): Token { // some magic return new Token($payload); } } $user = new App\User('Mateus', '[email protected]'); $token = (new App\Auth\TokenIssuer) -> issue($user -> id);
entre módulos • Clareza acerca das responsabilidades de um módulo • Possibilidade de implementar estratégias diferentes para módulos com desafios diferentes • Adoção gradual Estrutura Modular
isolada • Mudanças na implementação não afetam outros módulos, desde que os contratos sejam respeitados • Contratos do produtor podem ser redirecionados para outras implementações sem conhecimento do consumidor • Pode-se substituir as “bordas" de módulos upstream por implementações falsas (por exemplo, em memória) durante testes
int $id, public Money $total, /** @var OrderLine[] */ public array $lines, public OrderStatus $status, public Payment $payment, public int $userId, ) {} }
public int $id, public Money $total, public Money $net, public Money $tax, public TaxBracket $taxBracket, public Address $address, public Calculation $calculation, public TaxReceipt $receipt, public BalanceSheet $balance, public Uuid $uuid, public int $orderId, ) {} }
public int $id, public Money $total, public Money $net, public Money $tax, public TaxBracket $taxBracket, public Address $address, public Calculation $calculation, public TaxReceipt $receipt, public BalanceSheet $balance, public Uuid $uuid, public int $orderId, ) {} }
public int $id, public Money $total, public Money $net, public Money $tax, public TaxBracket $taxBracket, public Address $address, public Calculation $calculation, public TaxReceipt $receipt, public BalanceSheet $balance, public Uuid $uuid, public int $orderId, ) {} }
entre módulos. • Exponha uma API *pequena*, bem definida e estável para que outros módulos tenham acesso. • Ao se comunicar com outros módulos, sempre dependa da API pública daquele módulo, e jamais de implementações. • Um dos maiores benefícios de arquiteturas modulares, na minha opinião, é poder implementar estratégias diferentes para problemas diferentes. Use isto. • Cuidado com acoplamento à nível de banco de dados, como com chaves estrangeiras. • De forma geral, queries dentro de um módulo devem tocar apenas tabelas pertencentes aquele módulo. • Use o Deptrac! (Em PHP)
permite configurar “camadas”, e também criar regras sobre como essas camadas interagem com outras — incluindo com quais camadas elas podem ou não podem interagir • O Deptrac também gera um grafo de dependências, inclusive mostrando onde as violações das regras acontecem (caso haja alguma)