Programação de princípios do SOLID

43

Com o tempo, eu pude entender duas partes do SOLID - o "S" e o "O".

“O” - eu aprendi o Princípio Aberto Fechado com a ajuda de Herança e Padrão de Estratégia.

"S" - aprendi o princípio de responsabilidade única enquanto aprendia o ORM (a lógica da persistência é retirada dos objetos do domínio).

De maneira semelhante, quais são as melhores regiões / tarefas para aprender outras partes do SOLID (o "L", "I" e "D")?

Referências

  1. msdn - Perigos de violar os princípios do SOLID em C #
  2. channel9 - Aplicando princípios do SOLID no .NET / C #
  3. Princípios OOPS (princípios SOLID)
LCJ
fonte
25
tome nota de que todas essas idéias são boas e, juntas, são muito boas. mas se você aplicá-los dogmaticamente, eles causarão mais falhas do que sucesso.
3
Os OR-Mappers são bons para separar preocupações, não para um princípio de responsabilidade única. Consulte esta publicação programmers.stackexchange.com/questions/155628/… para uma discussão sobre as diferenças.
Doc Brown
Exemplos do mundo real blog.gauffin.org/2012/05/…
LCJ
1
@JarrodRoberson Sim, é por isso que eles são cuidadosamente referidos como diretrizes . Além disso, não se esqueça do restante dos princípios: adamjamesnaylor.com/2012/11/12/… (11 no total)
Adam Naylor
2
O link de @AdamNaylor agora está 404ing, foi movido para adamjamesnaylor.com/post/…
mattumotu

Respostas:

54

Eu estava no seu lugar há alguns meses, até encontrar um artigo muito útil.

Cada princípio é bem explicado com situações do mundo real que cada desenvolvedor de software pode enfrentar em seus projetos. Estou cortando aqui e apontando a referência - Desenvolvimento de Software SOLID, um passo de cada vez .

Como apontado nos comentários, há outra leitura muito boa do pdf - o SOLID Software Development de Pablo .

Além disso, existem alguns bons livros que descrevem os princípios do SOLID em mais detalhes - Bom livro sobre desenvolvimento de software do SOLID .

Edite e comentários de um breve resumo para cada princípio:

  • "S" - Princípio de Responsabilidade Única é orientado pelas necessidades da empresa para permitir mudanças. “Um único motivo para mudar” ajuda a entender quais conceitos logicamente separados devem ser agrupados considerando o conceito e o contexto de negócios, em vez do conceito técnico. In another words, aprendi que cada classe deve ter uma única responsabilidade. A responsabilidade é apenas realizar a tarefa atribuída

  • “O” - eu aprendi o Princípio Aberto Fechado e comecei a "preferir composição sobre herança" e, como tal, preferindo classes que não têm métodos virtuais e são possivelmente seladas, mas dependem de abstrações para sua extensão.

  • "L" - Aprendi o Princípio de Substituição de Liskov com a ajuda do padrão Repository para gerenciar o acesso a dados.

  • “I” - aprendi sobre o Princípio de Segregação de Interface, aprendendo que os clientes não devem ser forçados a implementar interfaces que não usam (como no Provedor de Associação no ASP.NET 2.0). Portanto, a interface não deve ter "muitas responsabilidades"
  • “D” - eu aprendi sobre o Princípio de Inversão de Dependência e comecei a codificar que é fácil de mudar . Mais fácil de mudar significa um menor custo total de propriedade e maior capacidade de manutenção.

Como um recurso útil do CodePlex foi mencionado nos comentários, é incluída referência ao SOLID por exemplo

insira a descrição da imagem aqui

EL Yusubov
fonte
3
Achei a seguinte coleção de artigos muito útil: lostechies.com/wp-content/uploads/2011/03/…
Scroog1
Eu li o artigo inteiro e não sou vendido em padrões ou no SOLID. O exemplo é muito simplista, mas quando fica complexo, a complexidade é artificial. Ainda estou para encontrar o SOLID OOP do mundo real sem melhores alternativas.
Job
3
uma vez que os artigos lostechies foram mencionados aqui existe também este solidexamples.codeplex.com (baseado em lostechies)
escuro fader
2
Eu fui um dos colaboradores do Pablos eBook. Fico feliz que as pessoas ainda acham útil. :)
Sean Chambers
1
+1000000 se eu puder, para o seu resumo do princípio Aberto-Fechado - todo mundo está errado e pensa que é sobre herança
AlexFoxGill
11

(I) a segregação da interface e (D) a inversão da dependência podem ser aprendidas através de testes de unidade e zombaria. Se as classes criarem suas próprias dependências, você não poderá criar bons testes de unidade. Se eles dependem de uma interface muito ampla (ou nenhuma interface), não é muito óbvio o que precisa ser ridicularizado para fazer seus testes de unidade.

StriplingWarrior
fonte
2
+1 isso é muito verdade. Você nem precisa aderir à regra (imo) às vezes muito rigorosa de 'um teste de unidade deve testar apenas uma coisa': se você não conseguir criar uma suíte de testes decente para uma aula em alguns minutos, viola I e D e, provavelmente, o resto do alfabet bem
stijn
8

O Princípio de Substituição de Liskov basicamente não permite que você use demais a herança da implementação: você nunca deve usar a herança apenas para reutilizar o código (existe composição para isso)! Ao aderir ao LSP, você pode ter certeza de que realmente existe um "é um relacionamento" entre sua superclasse e sua subclasse.

O que diz é que suas subclasses devem implementar todos os métodos da subclasse de maneira semelhante à implementação dos métodos na subclasse. Você nunca deve substituir um método pela implementação do NOP ou retornar nulo quando o supertipo lança uma exceção; declarado nos termos Design por contrato, você deve respeitar o contrato do método da superclasse ao substituir um método. Uma maneira de se defender contra a quebra desse princípio é nunca substituir um método implementado; em vez disso, extraia uma interface e implemente essa interface nas duas classes.

Princípio de Segregação de Interface , Princípio de Responsabilidade Única e Princípio de Alta Coesão do GRASP estão de alguma forma relacionados; eles se referem ao fato de que uma entidade deve ser responsável por apenas uma coisa, para que haja apenas um motivo para a mudança, para que a mudança seja feita com muita facilidade.

Na verdade, ele diz que se uma classe implementa uma interface, deve implementar e usar todos os métodos dessa interface. Se houver métodos que não são necessários nessa classe específica, a interface não será boa e deverá ser dividida em duas interfaces, uma que possua apenas os métodos necessários para a classe original. Isso pode ser considerado a partir de um ponto de vista, que se relaciona ao princípio anterior pelo fato de ele não permitir que você crie interfaces grandes para que sua implementação possa quebrar o LSP.

Você pode ver a inversão de dependência no padrão de fábrica; aqui, o componente de alto nível (o cliente) e o componente de baixo nível (instância individual a ser criada) dependem da abstração(a interface). Uma maneira de aplicá-lo em uma arquitetura em camadas: você não deve definir uma interface para uma camada na camada implementada, mas no módulo chamado. Por exemplo, a API para a camada de fonte de dados não deve ser gravada na camada de fonte de dados, mas na camada de lógica de negócios, onde é necessário chamar. Dessa maneira, a camada da fonte de dados herda / depende do comportamento definido na lógica de negócios (portanto, a inversão) e não vice-versa (como seria normalmente). Isso fornece flexibilidade no design, permitindo que a lógica de negócios funcione sem nenhuma alteração de código, com outra fonte de dados totalmente diferente.

m3th0dman
fonte
1
Ótima explicação sobre Liskov. :)
John Korsnes 13/03/2013