Lembre-se da métrica de estabilidade de Martin e do que ele entende por "estabilidade":
Instability = Ce / (Ca+Ce)
Ou:
Instability = Outgoing / (Incoming+Outgoing)
Ou seja, um pacote é considerado completamente instável se todas as suas dependências forem de saída: ele usa outras coisas, mas nada o usa. Nesse caso, só faz sentido que isso seja concreto. Também será o tipo de código mais fácil de alterar, já que nada mais o usa e, portanto, nada mais pode quebrar se esse código for modificado.
Enquanto isso, quando você tem o cenário oposto de "estabilidade" completa com um pacote usado por uma ou mais coisas, mas não usa nada por si só, como um pacote central usado pelo software, é quando Martin diz que isso deve ser feito. abstrato. Isso também é reforçado pela parte DIP do SOLI (D), o Princípio de Inversão de Dependências, que basicamente afirma que as dependências devem fluir uniformemente em direção a abstrações para códigos de baixo e alto nível.
Ou seja, as dependências devem fluir uniformemente em direção à "estabilidade" e, mais precisamente, as dependências devem fluir em direção a pacotes com mais dependências de entrada do que as dependências de saída e, além disso, as dependências devem fluir em direção a abstrações. A essência da lógica por trás disso é que as abstrações fornecem espaço para substituir um subtipo por outro, oferecendo esse grau de flexibilidade para que as partes concretas que implementam a interface sejam alteradas sem interromper as dependências recebidas nessa interface abstrata.
Existem desvantagens significativas para depender de abstrações?
Bem, na verdade, eu discordo de Martin aqui pelo menos no meu domínio, e aqui preciso introduzir uma nova definição de "estabilidade", como "falta de motivos para mudar". Nesse caso, eu diria que as dependências devem fluir para a estabilidade, mas as interfaces abstratas não ajudam se as interfaces abstratas forem instáveis (pela minha definição de "instável", como propenso a ser repetidamente alterado, e não o de Martin). Se os desenvolvedores não conseguirem corrigir as abstrações e os clientes mudarem de idéia repetidamente de maneiras que tornem as tentativas abstratas de modelar o software incompletas ou ineficazes, não seremos mais beneficiados pela flexibilidade aprimorada das interfaces abstratas para proteger o sistema contra alterações em cascata que quebram a dependência . No meu caso pessoal, encontrei mecanismos ECS, como os encontrados em jogos AAA,mais concreta : em relação aos dados brutos, mas esses dados são altamente estáveis (como em "é improvável que precise ser alterado"). Eu sempre achei a probabilidade de algo que requer mudanças futuras ser uma métrica mais útil do que a proporção de acoplamentos eferentes para o total para orientar as decisões de SE.
Então, eu alteraria um pouco o DIP e apenas diria: "as dependências devem fluir para componentes com a menor probabilidade de exigir alterações adicionais", independentemente de esses componentes serem interfaces abstratas ou dados brutos. Tudo o que importa para mim é a probabilidade de que eles possam exigir mudanças diretas no design. As abstrações são úteis apenas neste contexto de estabilidade se algo, por ser abstrato, reduzir essa probabilidade.
Para muitos contextos que podem ser o caso de engenheiros e clientes decentes que antecipam as necessidades do software antecipadamente e projetam abstrações estáveis (como imutáveis), enquanto essas abstrações oferecem a eles todo o espaço necessário para trocar implementações concretas. Mas em alguns domínios, as abstrações podem ser instáveis e propensas a serem inadequadas, enquanto os dados exigidos pelo mecanismo podem ser muito mais fáceis de antecipar e estabilizar com antecedência. Portanto, nesses casos, pode ser realmente mais benéfico do ponto de vista de manutenção (a facilidade de alterar e estender o sistema) para que as dependências fluam em direção aos dados, em vez de abstrações. Em um ECS, as partes mais instáveis (como as partes mais frequentemente alteradas) são geralmente a funcionalidade que reside nos sistemas (PhysicsSystem
, por exemplo), enquanto as partes mais estáveis (como é menos provável que sejam alteradas) são os componentes que consistem apenas em dados brutos ( MotionComponent
por exemplo) que todos os sistemas usam.