Você está na página 1de 14

ARQUITETURA DE

SOFTWARE DESKTOP

DDD - Domain-Driven Design ........................................................................................................ 2


Mas afinal, o que é DDD? ......................................................................................................... 3
O Modelo .................................................................................................................................. 4
Arquitetura em Camadas ......................................................................................................... 5
Entities, Value Objects, Services e Aggregates ........................................................................ 6
Test-Driven Development ............................................................................................................. 8
Uma prévia sobre TDD ...................................................................................................... 9
Por que utilizar o TDD em nossas aplicações? ....................................................................... 10
Mais qualidade no projeto ..................................................................................................... 10
Código mais simples ............................................................................................................... 11
Redução do tempo para disponibilizar o produto................................................................. 11
SOLID na aplicação de Padrões de Projeto ........................................................................ 12
 Single Responsibility Principle: princípio da responsabilidade única; ............................. 12
 Open Closed Principle: princípio do aberto/fechado; ..................................................... 13
 Liskov Substitution Principle: princípio da substituição de Liskov; ................................. 13
 Interface Segregation Principle: princípio da segregação de Interfaces; ........................ 13
 Dependency Inversion Principle: princípio da inversão de dependência. ....................... 14
DDD - Domain-Driven Design

Uma nova metodologia de design que está presente em várias aplicações


desenvolvidas em .NET
Nota:
NET é uma plataforma de código aberto para a criação de aplicações de desktop,
Web e móveis que podem ser executadas nativamente em qualquer sistema
operacional. O sistema. NET inclui ferramentas, bibliotecas e linguagens que
oferecem suporte ao desenvolvimento de software moderno, escalável e de alta
performance. É usado fornecendo acesso às amplas funcionalidades do
Windows e do Windows Server. Também é amplamente usado para computação
em nuvem baseada no Windows.

Para quem nunca ouviu falar sobre Domain-Driven Design, é importante


ressaltar que não se trata de um novo framework nem uma nova linguagem de
programação, mas sim de uma nova disciplina ou abordagem (alguns diriam até
um novo paradigma) para o desenvolvimento de software, ou seja, uma série de
ideias e princípios que ao serem aplicados no processo de desenvolvimento de
software podem simplificar o mesmo e agregar mais valor ao produto final.
O termo Domain-Driven Design foi criado por Eric Evans em seu livro entitulado
“Domain-Driven Design: Tackling Complexity in the Heart of Software”, onde ele
fala extensivamente sobre esses princípios e como eles podem ser aplicados e
suportados em código, mostrando diversos padrões de projeto de forma
detalhada e suas ideias para um melhor desenvolvimento de software após duas
décadas percebendo os mesmos problemas.
Mas afinal, o que é DDD?
A principal ideia do DDD é a de que o mais importante em um software não é o
seu código, nem sua arquitetura, nem a tecnologia sobre a qual foi desenvolvido,
mas sim o problema que o mesmo se propõe a resolver, ou em outras palavras,
a regra de negócio. Ela é a razão do software existir, por isso deve receber o
máximo de tempo e atenção possíveis. Em praticamente todos os projetos de
software, a complexidade não está localizada nos aspectos técnicos, mas sim
no negócio, na atividade que é exercida pelo cliente ou problema que o mesmo
possui. Como já diz o título do livro de Eric Evans, esse é o “coração”, o ponto
central de qualquer aplicação, portanto todo o resto deve ser trabalhado de forma
que este “coração” seja entendido e concebido da melhor forma possível.
Vamos utilizar um exemplo para tentar clarificar essa ideia: imagine que o mais
novo cliente de sua empresa é um call center e você precisa desenvolver um
software que controle todos os processos do mesmo. Mas quem conhece os
processos de um call center? Seu gerente? Os desenvolvedores? Com certeza
não. Todos estes provavelmente já foram atendidos por um, talvez tenham ideias
vagas sobre o funcionamento, mas ninguém possui conhecimento suficiente
para guiar o desenvolvimento desse projeto. Quem realmente conhece o negócio
são os atendentes, supervisores e demais funcionários desse call center. É deles
que esse conhecimento deve ser extraído, de maneira que a equipe do projeto
possa se alinhar com seus desejos e expectativas.
Após esse exemplo, vamos fazer um paralelo com alguns conceitos do DDD. O
funcionamento e processos do call center são considerados o domínio da
aplicação. O domínio é o ponto central de qualquer aplicação, é por causa dele
que o software é criado afinal de contas. Reforçando o que já foi falado
anteriormente, é o domínio que concentra a maior parte da complexidade de
quase todos os projetos de software. O que muitas vezes acontece é um foco
excessivo em aspectos técnicos (o velho exemplo da equipe que está “ansiosa”
por aplicar a mais nova versão de determinado framework) em detrimento de um
conhecimento mais aprofundado no domínio. O grande ponto a ser destacado
aqui é que para desenvolver uma aplicação de qualidade, que atenda todas as
necessidades do cliente de forma satisfatória, não basta apenas ter muito
conhecimento técnico e utilizar os melhores frameworks e plataformas, é
necessário que a equipe do projeto tenha uma clara compreensão sobre o
problema que o software se propõe a resolver, pois é isso que realmente traz
valor ao produto final.

O Modelo
Mas nem tudo são flores. Um domínio não é algo facilmente transformável em
código, pois consiste em uma série de ideias e conceitos do mundo real. Para
que seja possível gerar código que atenda as necessidades de determinado
domínio é preciso uma camada intermediária, uma abstração entre a regra do
negócio e o código, até mesmo para auxiliar os envolvidos a ter um melhor
entendimento sobre o domínio em questão. Essa “camada” é o modelo, que tem
como principal objetivo organizar toda a informação obtida dos especialistas,
atuando como um guia para a arquitetura e o código da aplicação e, ao mesmo
tempo, representando de maneira correta os conceitos do domínio. Este é o
grande desafio dos desenvolvedores, criar um modelo que reflita os conceitos
do domínio de forma clara que também seja útil para o desenvolvimento. Se o
modelo for de difícil implementação ou se não representar a realidade, ele
fatalmente não será utilizado e perderá o seu valor.
Muito bem, já vimos as principais ideias pregadas pelo DDD, agora é hora de
baixar um pouco o nível e ver as principais práticas sugeridas para a criação do
modelo e da arquitetura de uma aplicação. A Figura 1 mostra um mapa com
esses conceitos, como mostrado no livro de Eric Evans. A Figura 1 é um
exemplo interessante de modelo. Nesse caso, o domínio sendo modelado é o do
próprio DDD.

Diagrama que mostra o relacionamento entre os principais padrões do DDD


Arquitetura em Camadas
Para que possamos atingir o principal objetivo do DDD, que é focar no domínio
da aplicação, é necessário que a arquitetura da mesma seja pensada de forma
a permitir essa distinção. Pensando nisso é que o DDD sugere uma arquitetura
padrão (Figura 2), que tem como objetivo principal separar o modelo do domínio
da tecnologia em si, facilitando assim eventuais mudanças nas regras de negócio
da aplicação.

Muitas aplicações possuem regras de negócio espalhadas por todo o código,


desde stored procedures na base de dados até JavaScripts na interface do
usuário. O grande problema é que alterar alguma dessas regras se torna um
verdadeiro pesadelo, uma vez que o desenvolvedor precisará literalmente
rastrear todos os locais onde ela deve ser modificada, efetuar as alterações
propriamente ditas, e por fim planejar a instalação de todos os componentes
modificados.
Para evitar esse tipo de problema, devemos isolar todo o código responsável por
controlar o domínio de maneira que ele tenha uma única responsabilidade:
implementar regras de negócio. Essa camada deve ser o principal local
modificado quando alguma regra da aplicação tiver que ser alterada. Vejamos
cada camada:
 Domain Layer: Como já comentado, essa camada concentra toda a regra
de negócio da aplicação. Essa deve ser a sua única preocupação,
delegando qualquer outro tipo de atividade para as demais camadas;
 Infrastructure Layer: É a camada de mais baixo nível, responsável por
prover serviços como persistência e envio de email, ou seja, dar o suporte
tecnológico para as demais camadas;
 Application Layer: Coordena as atividades da aplicação, porém, não
contém regras de negócio. Pode, por exemplo, manter um estado de
determinada transação. Essa é a camada mais discutida, pois
dependendo do domínio da aplicação, ela pode não ser necessária.
 User Interface Layer: Responsável pela interação com o usuário, seja
interpretando comandos ou exibindo informação para o mesmo.

Entities, Value Objects, Services e Aggregates


Entities são objetos identificados por sua identidade e não por seus atributos. O
exemplo mais simples é uma pessoa. A representação de uma pessoa em
software geralmente conta com atributos como nome, data de nascimento, CPF,
RG etc. Porém, como podemos distinguir cada pessoa unicamente? Pelo nome
e data de nascimento com certeza não, pois muitas pessoas nascem em um
mesmo dia e podem existir pessoas com o mesmo nome também. CPF e RG
podem ser usados, se levarmos em conta apenas cidadãos brasileiros. A
principal ideia é que cada pessoa deve ser única, não sendo possível criar uma
pessoa igual apenas “copiando” os atributos de outra.
Por outro lado, Value Objects são objetos que não possuem uma identidade
definida, eles são definidos apenas por seus atributos. Para o domínio, não é
importante que sejam identificados. O que importa é somente o valor que
“carregam”.
Já os serviços são objetos que têm como finalidade prover um comportamento
que não se adapta a nenhum Entity ou Value Object, mas que ainda assim é um
conceito importante no contexto do domínio. Um típico exemplo é o cálculo de
frete. O CEP é utilizado para efetuar esse cálculo, mas essa lógica está além do
objetivo do objeto CEP, portanto não é correto que fique no mesmo. Entretanto,
esse conceito também não está diretamente relacionado a nenhum outro objeto.
O melhor nesse caso é optar por um Service cujo único objetivo é efetuar o
cálculo.
Você notará que, devido a sua natureza, Services geralmente terão como nome
um verbo (“CalcularFrete”, por exemplo), diferente de Entities e Value Objects,
cuja descrição é geralmente um nome (no exemplo mostrado, “CEP”.)
Já um Aggregate é um grupo de objetos que devem ser tratados como um só,
cujo agrupamento representa uma unidade maior no contexto do domínio.
Muitas vezes um objeto filho não tem o menor sentido sem o seu “pai”. O
exemplo mais claro é o relacionamento de um Item de Pedido com um Pedido.
Os itens só existem em razão do pedido, pois sem pedido não é possível ter
qualquer tipo de item.
Como esse é um dos conceitos mais complicados, vejamos o exemplo da Figura
3, adaptado do livro de Eric Evans, que possui dois Aggregates, Cliente e Carro.
Test-Driven Development
O TDD (Test-Driven Development) no desenvolvimento de aplicações .NET
guiadas por testes com o Visual Studio, além de como utilizar Mock para
facilitar a simulação de dados para testes.
O TDD preza pela realização de testes no código antes mesmo de implementar
as funcionalidades propriamente ditas, reduzindo a quantidade de erros,
aumentando a qualidade do código e permitindo ao desenvolvedor conhecer
melhor as regras de negócio que estão sendo implementadas.
Veremos também como utilizar a técnica de mock no apoio ao TDD, prática
bastante útil em cenários onde é necessário realizar testes com dados fictícios,
pois facilita a geração de objetos para testes a partir de modelos do domínio da
aplicação.
Durante o ciclo de vida de um software, os requisitos inicialmente estabelecidos
geralmente mudam, novos são adicionados e outros removidos.
Claro que isso não vem de hoje, mas tornou-se muito mais constante devido às
novas possibilidades de produzirmos softwares para diversas plataformas, por
exemplo.
Sempre estamos evoluindo e os estilos tradicionais de desenvolvermos novos
produtos enfrentam desafios significativos, como a necessidade constante de
facilitar a manutenção.
Realizar alterações em uma aplicação desenvolvida e prestes a entrar para o
mercado, tradicionalmente, pode causar indisposição junto aos seus clientes de
formas difíceis de serem previstas.
Como resultado, as organizações hesitam em fazer mudanças que são
necessárias para o software, impedindo assim o seu melhor desempenho e
consequentemente seu sucesso perante as organizações que dele dependam.
Neste quesito, no que diz respeito à mudança, é que entramos no tema deste
artigo, cujo foco é trabalhar em testes com base na metodologia Test-Driven
Development (TDD).
O intuito deste artigo é apresentar de forma prática e simples como podemos
trabalhar numa aplicação baseando-se em testes para as funcionalidades que
desejamos implementar, de forma a reduzir falhas no sistema.
Com TDD podemos aumentar a nossa produtividade, pois iremos reduzir a
quantidade de depurações necessárias para detecção de erros, teremos uma
melhor visualização do nosso código, tornando mais simples a leitura dele,
dentre outras vantagens que refletem de forma direta na construção de um
software de qualidade.
Para praticar os conceitos que serão apresentados aqui, criaremos uma
aplicação simples de carrinho de compras, no qual estaremos vendo a utilização
de um “simulador de banco de dados” conhecido por Moq, que auxilia na geração
de dados fictícios para testes.

Uma prévia sobre TDD


Nos últimos anos, houve uma série de novidades em torno da metodologia de
TDD e sua real eficácia com relação ao desenvolvimento das mais diversas
aplicações. Mesmo com a desenvoltura que podemos encontrar nas técnicas do
TDD, ainda existe muita relutância na sua utilização, principalmente relacionada
aos prazos para desenvolvimento e entrega de projetos.
Ao trabalharmos com desenvolvimento baseado em testes, temos
primeiramente a mudança do nosso foco, que neste momento passa a se voltar
para tecnologias ágeis e práticas baseadas em testes como sendo as operações
primárias para o desenvolvimento de sistemas complexos e de alto
desempenho.
O Test Driven Development é uma metodologia de desenvolvimento avançado
com foco na qualidade do software orientado a objetos, amplamente utilizado
dentro da comunidade Agile. O que torna o TDD único é o seu foco na
especificação do projeto, ao invés de ser na sua validação.
A abordagem TDD leva a uma melhor arquitetura de software de qualidade,
melhorando a qualidade, simplicidade e capacidade de teste, enquanto aumenta
a confiança no código e a produtividade da equipe.
Ao implementarmos essa metodologia, os testes utilizados são compostos de
afirmações verdadeiras e falsas que indicam o comportamento correto com
relação ao teste que está sendo usado no momento.
Nesta abordagem criamos testes automatizados de unidades antes mesmo de
escrevermos o código específico. Ao escrevermos inicialmente os testes, estes
não só nos ajudam na medição dos testes propriamente ditos, mas também
forçam o desenvolvedor a se concentrar no conceito do design avançado desde
o início.
Através do desenvolvimento de um conjunto de casos de teste funcional
inicialmente, os desenvolvedores podemos ter a certeza de que terão sempre
um software com o mínimo de falha possível, além de que as características
recém-aplicadas serão aplicadas conforme o esperado.
Para o TDD, temos que uma unidade é definida basicamente como sendo uma
classe ou um grupo de funções relacionadas, muitas vezes chamado de módulo.
Com a disposição de unidades relativamente pequenas, podemos oferecer
benefícios críticos à nossa aplicação, como é o caso da redução dos esforços
no momento da depuração, além de que testes pequenos melhoram a
legibilidade e compreensão mais rápida e eficiente do que é preciso fazer.

Por que utilizar o TDD em nossas aplicações?


Como qualquer outra metodologia de desenvolvimento, o TDD exige uma
mudança de paradigmas com foco no código para uma abordagem baseada em
testes. Ao adotarmos uma abordagem de desenvolvimento orientada a testes, é
necessário um esforço significativo, podendo requerer da organização de
desenvolvimento uma mudança de cultura. Porém os benefícios referentes a
estas mudanças podem ultrapassar os custos que podem ser acarretados. Esta
mudança melhora a qualidade e a confiabilidade do sistema, maximiza a
produtividade do desenvolvedor e acelera significativamente o tempo para a
disponibilidade do projeto no mercado profissional. Vejamos a seguir alguns dos
benefícios obtidos na adoção do TDD.

Mais qualidade no projeto


Com o TDD, cada componente é obrigado a ser construído de forma constante
com capacidade a nível elevado de qualidade, de forma mais consistente com
base nos testes, onde temos o desenvolvimento em pequenos incrementos, que
exigem testes para serem aprovados.
Uma vez que o componente desenvolvido individualmente muda para a
integração, este nível elevado de qualidade nos componentes leva a uma rápida
integração e testes mais eficazes.
O esforço para construir uma ampla base de testes automatizados de forma
incremental ao longo do ciclo de desenvolvimento, produz uma base muito mais
completa e valiosa de testes do que um esforço em testes apressados, e muitas
vezes “espremidos” no final do projeto. Durante todo o ciclo de desenvolvimento
o foco maior em testes ajuda a manter um foco maior sobre a qualidade em geral.
Este investimento contínuo em qualidade rende benefícios significativos ao nível
geral do sistema.

Código mais simples


Durante a implementação de um recurso, o desenvolvedor orientado a testes
escreve o código mais simples para fazer os testes passarem. O TDD ajuda
aos desenvolvedores a evitarem o excesso de soluções engenhosas devido ao
seu microciclo de desenvolvimento. Ela também ajuda a quebrar o problema em
unidades modulares e produzir uma solução que possa ser testada, bem como
implementada. Esta abordagem para o desenvolvimento tem o efeito de
simplificação no código do projeto e alcança os benefícios associados a ela,
incluindo melhoria na legibilidade e compreensibilidade. Quanto mais complexo
o problema, mais importante é garantir que cada unidade está codificada de uma
forma simples tanto quanto possível.

Redução do tempo para disponibilizar o produto


O ciclo do TDD é mais curto que o ciclo de desenvolvimento tradicional.
Concentrando-se em desenvolver apenas o que é necessário para a aprovação
nos testes, usando esse feedback imediato para reduzir os erros de regressão,
o ciclo de desenvolvimento pode ser rapidamente reduzido ao seu núcleo
essencial.
Normalmente, os atrasos de integração para os sistemas aumentarão com o
tempo de desenvolvimento do software e estenderão o cronograma das
entregas. Ao aplicarmos o TDD, temos a maioria dos problemas de componentes
resolvidos muito mais cedo no processo, diminuindo assim o tempo de
integração e a rapidez para o produto completo estar no mercado.
SOLID na aplicação de Padrões de Projeto
Em um sistema desenvolvido através do paradigma orientado a objetos, existem
diversos padrões e metodologias que devem ser adotadas para que o software
produzido seja de fácil manutenção e possibilite sua extensão.
Através dos diversos padrões de software apresentados pelos mais diferentes
autores, percebe-se que tratam de soluções de problemas recorrentes no
desenvolvimento de sistemas.
Apesar dos padrões serem de fato uma melhoria nos sistemas, muitos analistas
e programadores ainda apresentam dificuldades na sua aprendizagem,
principalmente em uma primeira abordagem aos padrões de projeto existentes.
Como forma de facilitar este aprendizado, juntamente com a motivação de criar
um código melhor, pode-se estudar cinco princípios básicos de design
orientados a objetos, chamados de “SOLID”.
Abordados inicialmente por Robert Martin, em um artigo chamado Principles Of
Ood, o autor elabora cinco técnicas de programação orientada a objetos onde
cada técnica é uma das letras da palavra SOLID. Esses cinco princípios são:

 Single Responsibility Principle: princípio da responsabilidade única;


O princípio da responsabilidade única ( SRP ) é um princípio de programação de
computador que afirma que "Um módulo deve ser responsável por um, e apenas um,
ator." O termo ator refere-se a um grupo (composto por um ou mais stakeholders ou
usuários) que requer uma mudança no módulo.
Robert C. Martin, o criador do termo, expressa o princípio como: "Uma classe deve ter
apenas um motivo para mudar". Por causa da confusão em torno da palavra "razão", ele
também esclareceu dizendo que o "princípio é sobre pessoas". Em algumas de suas
palestras, ele também argumenta que o princípio é, em particular, sobre papéis ou
atores. Por exemplo, embora possam ser a mesma pessoa, a função de um contador é
diferente de um administrador de banco de dados. Assim, cada módulo deve ser
responsável por cada papel.
Como exemplo, considere um módulo que compila e imprime um relatório. Imagine que
tal módulo pode ser alterado por dois motivos. Primeiro, o conteúdo do relatório pode
mudar. Em segundo lugar, o formato do relatório pode mudar. Essas duas coisas mudam
por causas diferentes. O princípio da responsabilidade única diz que esses dois aspectos
do problema são realmente duas responsabilidades separadas e devem, portanto, estar
em classes ou módulos separados. Seria um design ruim juntar duas coisas que mudam
por razões diferentes em momentos diferentes.
A razão pela qual é importante manter uma classe focada em uma única preocupação é
que isso torna a classe mais robusta. Continuando com o exemplo anterior, se houver
uma alteração no processo de compilação do relatório, há um perigo maior de o código
de impressão quebrar se fizer parte da mesma classe.
 Open Closed Principle: princípio do aberto/fechado;
Na programação orientada a objeto, o princípio do aberto/fechado estabelece que
"entidades de software (classes, módulos, funções, etc.) devem ser abertas para
extensão, mas fechadas para modificação"; isto é, a entidade pode permitir que o
seu comportamento seja estendido sem modificar seu código-fonte.
O nome do princípio aberto/fechado tem sido usado de duas maneiras. Ambas as
maneiras usam generalizações (por exemplo, herança, ou delegação de funções)
para resolver o aparente dilema, mas os objetivos, as técnicas e os resultados são
diferentes.
Um módulo será dito aberto se ele ainda está disponível para extensão. Por
exemplo, se for possível adicionar campos para as estruturas de dados que ele
contém, ou novos elementos para o conjunto de funções que executa.
Um módulo será dito ser fechado se está disponível para uso por outros módulos.
Isso pressupõe que o módulo tenha sido bem-definido, isto é, que tenha uma
descrição estável, em que as interfaces de programação fornecidas abstraem as
características específicas do objeto.
Uma classe é fechada, uma vez que ela possa ser compilada, armazenada em uma
biblioteca, baselined, e utilizada pelo cliente. Por outro lado, diz-se que ela é aberta
quando qualquer nova classe pode usá-la como superclasse para a adição de novas
funcionalidades. Quando criamos uma subclasse de uma classe aberta, não há
necessidade de alterar a superclasse nem tampouco a forma com que seus clientes
se relacionam com ela.
 Liskov Substitution Principle: princípio da substituição de Liskov;
Na programação orientada a objeto, o princípio da substituição de Liskov é uma
definição particular para o conceito de subtipo. Foi introduzido em 1993 por Barbara
Liskov e Jeannette Wing através de um artigo de nome Family Values: A Behavioral
Notion of Subtyping. Para outra definição de subtipo ver tipo de dado.

O princípio foi definido de forma resumida como.


Se q(x) é uma propriedade demonstrável dos objetos (x) de tipo T.
Então q(x) deve ser verdadeiro para objetos y de tipo S onde S é um subtipo de T.

Portanto, a visão de "subtipo" defendida por Liskov e Wing é baseada na noção da


substituição; isto é, se S é um subtipo de T, então os objetos do tipo T, em um
programa, podem ser substituídos pelos objetos de tipo S sem que seja necessário
alterar as propriedades deste programa.
 Interface Segregation Principle: princípio da segregação de Interfaces;
No campo da engenharia de software, o princípio da segregação de Interface (ISP)
afirma que nenhum cliente deve ser forçado a depender de métodos que não utiliza. ISP
divide interfaces que são muito grandes em menores e mais específicas, para que os
clientes só necessitem saber sobre os métodos que são de interesse para eles. Tais
interfaces encolhidas são também chamados de papel de interfaces. ISP destina-se a
manter um sistema desacoplado e, assim, mais fácil para reestruturar, modificar. O ISP
é um dos cinco princípios do SOLID de design orientado a objeto, semelhante ao
Princípio de Alto Coesão do GRASP.
Dentro design orientado a objeto, interfaces fornecem camadas de abstração que
facilitam a explicação conceitual do código e cria uma barreira que impede o
acoplamento por dependências.
De acordo com muitos especialistas em software que assinaram o Manifesto para
Software Artesanal, escrevendo sofware bem trabalhado e auto-explicativo é quase tão
importante quanto escrever software funcional. Usando interfaces para descrever a
intenção do software é muitas vezes uma boa idéia.
Um sistema pode tornar-se tão acoplado em vários níveis, que não é mais possível fazer
uma alteração em um lugar sem a necessidade de muitas alterações adicionais. Usando
uma interface ou uma classe abstrata pode evitar este efeito colateral.
 Dependency Inversion Principle: princípio da inversão de dependência.
No paradigma de orientação a objetos, o Princípio da inversão de dependência refere-se a uma
forma específica de desacoplamento de módulos de software que determina a inversão das
relações de dependência: partem de módulos de alto nível, responsáveis pelas diretrizes, para
os de baixo nível. Assim, os módulos de alto nível tornam-se independentes dos detalhes de
implementação dos de baixo nível. O princípio estabelece que:
A. Módulos de alto nível não devem incorporar (ou incluir) nada dos módulos de baixo nível.
Ambos devem trabalhar apenas com abstrações, ou seja, interfaces.
B. Abstrações não devem depender de detalhes de implementação, mas os detalhes é que
devem depender de abstrações.
Ao definir que os objetos de alto e baixo nível devem fundamentar-se nas mesmas abstrações,
este princípio de projeto inverte a maneira como as pessoas geralmente raciocinam dentro do
paradigma de orientação a objetos.
A ideia que está por trás dos itens A e B é que, no projeto de integração de módulos de alto e
baixo nível, a sua interação deve ser feita de forma abstrata. Este princípio não acarreta
consequências apenas no desenvolvimento dos módulos de alto nível, mas também nos de baixo
nível, que precisam ser produzidos com a noção de interação e de possibilidade de mudança na
interface de uso.
Muitas vezes, quando se pensa na interação como um conceito abstrato, é possível reduzir o
acoplamento dos componentes sem introduzir novos padrões de código, o que torna o modelo
de interação mais leve e menos dependente de implementação.

Você também pode gostar