Em uma recente entrevista de emprego, não consegui responder a uma pergunta sobre o SOLID - além de fornecer o significado básico dos vários princípios. Isso realmente me incomoda. Passei alguns dias pesquisando e ainda tenho que apresentar um resumo satisfatório.
A pergunta da entrevista foi:
Se você visse um projeto .Net que eu lhe disse que seguia estritamente os princípios do SOLID, o que você esperaria ver em termos de projeto e estrutura de código?
Andei um pouco, realmente não respondi a pergunta e depois fui bombardeada.
Como eu poderia ter lidado melhor com essa questão?
Respostas:
S = Princípio da responsabilidade única
Então, eu esperaria ver uma estrutura de pastas / arquivos bem organizada e hierarquia de objetos. Cada classe / parte da funcionalidade deve receber um nome que sua funcionalidade é muito óbvia e deve conter apenas lógica para executar essa tarefa.
Se você visse grandes classes de gerentes com milhares de linhas de código, isso seria um sinal de que uma única responsabilidade não estava sendo seguida.
O = Princípio aberto / fechado
Essa é basicamente a ideia de que novas funcionalidades devem ser adicionadas por meio de novas classes que tenham um impacto mínimo / exigem modificação da funcionalidade existente.
Eu esperaria ver muito uso de herança de objeto, sub-digitação, interfaces e classes abstratas para separar o design de uma parte da funcionalidade da implementação real, permitindo que outras pessoas venham e implementem outras versões ao lado sem afetar o original.
L = princípio de substituição de Liskov
Isso tem a ver com a capacidade de tratar subtipos como o tipo pai. Isso sai da caixa em C # se você estiver implementando uma hierarquia de objetos herdada adequada.
Eu esperaria ver o código tratando objetos comuns como seu tipo base e chamando métodos nas classes base / abstract em vez de instanciar e trabalhar nos próprios subtipos.
I = Princípio de Segregação de Interface
Isso é semelhante ao SRP. Basicamente, você define subconjuntos menores de funcionalidade como interfaces e trabalha com aqueles para manter seu sistema dissociado (por exemplo, um
FileManager
pode ter a única responsabilidade de lidar com a E / S do arquivo, mas isso poderia implementar umIFileReader
eIFileWriter
que continha as definições de método específicas para a leitura e gravação de arquivos).D = Princípio da inversão de dependência.
Novamente, isso se refere a manter um sistema desacoplado. Talvez você esteja atento ao uso de uma biblioteca do .NET Dependency Injection, sendo usada na solução como
Unity
ouNinject
ou em um sistema ServiceLocator comoAutoFacServiceLocator
.fonte
Muitas classes pequenas e interfaces com injeção de dependência em todo o lugar. Provavelmente, em um grande projeto, você também usaria uma estrutura de IoC para ajudá-lo a construir e gerenciar a vida útil de todos esses pequenos objetos. Consulte https://stackoverflow.com/questions/21288/which-net-dependency-injection-frameworks-are-worth-looking-into
Observe que um grande projeto .NET que segue estritamente os princípios do SOLID não significa necessariamente uma boa base de código para trabalhar com todos. Dependendo de quem foi o entrevistador, ele / ela pode querer que você mostre que entende o que o SOLID significa e / ou verifique como dogmaticamente você segue os princípios de design.
Veja bem, para ser SÓLIDO, você precisa seguir:
S princípio da responsabilidade ingle, assim você terá muitas pequenas aulas de cada um deles fazendo uma coisa única
O princípio de caneta fechada, que no .NET geralmente é implementado com injeção de dependência, que também requer o I e o D abaixo ...
O princípio da substituição de Iskov provavelmente é impossível de explicar em c # com uma única linha. Felizmente, existem outras perguntas para resolver, por exemplo, https://stackoverflow.com/questions/4428725/can-you-explain-liskov-substitution-principle-with-a-good-c-sharp-example
O Princípio da Segregação de Interface funciona em conjunto com o princípio Aberto-Fechado. Se seguido literalmente, significaria preferir um grande número de interfaces muito pequenas do que poucas interfaces "grandes"
D princípio de inversão ependency as classes de alto nível não deve depender em classes de baixo nível, ambos devem depender de captações.
fonte
Algumas coisas básicas que eu esperaria ver na base de código de uma loja que defendia o SOLID em seu trabalho diário:
Muitos padrões de adaptador e composto - eu esperaria o uso de muitos padrões de adaptador (uma classe que implementa uma interface "passando" para a funcionalidade de uma interface diferente) para simplificar a conexão de uma dependência desenvolvida para uma finalidade lugares diferentes onde sua funcionalidade também é necessária. Atualizações tão simples quanto substituir um registrador de console por um registrador de arquivos violarão o LSP / ISP / DIP se a interface for atualizada para expor um meio de especificar o nome do arquivo a ser usado; em vez disso, a classe do registrador de arquivos exporá os membros adicionais e, em seguida, um Adaptador fará com que o registrador de arquivos pareça um registrador de console ocultando o novo material, para que apenas o objeto que agrupa tudo isso saiba a diferença.
Da mesma forma, quando uma classe precisa adicionar uma dependência de uma interface semelhante à existente, para evitar alterar o objeto (OCP), a resposta usual é implementar um padrão Composite / Strategy (uma classe que implementa a interface de dependência e consome várias outras). implementações dessa interface, com quantidades variáveis de lógica, permitindo que a classe passe uma chamada para uma, algumas ou todas as implementações).
fonte
Distraia-os com a discussão de Jon Skeet de como o 'O' no SOLID é "inútil e mal compreendido" e faça com que falem sobre a "variação protegida" de Alistair Cockburn e o "design de herança ou proibição de Josh Bloch".
Breve resumo do artigo de Skeet (apesar de eu não recomendar o nome dele sem ler a postagem original do blog!):
O OP perguntou: "Como eu poderia lidar melhor com essa pergunta?" Como engenheiro sênior que conduz uma entrevista, eu estaria incomensuravelmente mais interessado em um candidato que possa falar de maneira inteligente sobre os prós e contras de diferentes estilos de design de código do que alguém que possa recitar uma lista de tópicos.
Outra boa resposta seria: "Bem, isso depende de quão bem eles o entenderam. Se tudo o que sabem são as palavras-chave do SOLID, eu esperaria abuso de herança, uso excessivo de estruturas de injeção de dependência, um milhão de pequenas interfaces, nenhuma das quais refletem o vocabulário do domínio usado para se comunicar com o gerenciamento de produtos .... "
fonte
Provavelmente, há várias maneiras pelas quais isso pode ser respondido com quantidades variáveis de tempo. No entanto, acho que isso é mais parecido com "Você sabe o que o SOLID significa?" Portanto, responder a essa pergunta provavelmente se resume apenas a acertar os pontos e explicá-la em termos de um projeto.
Então, você espera ver o seguinte:
fonte
Essa é uma pergunta excelente, embora eu ache que é uma pergunta difícil para uma entrevista.
Os princípios do SOLID realmente governam classes e interfaces e como eles se relacionam.
Esta questão é realmente uma que tem mais a ver com arquivos e não necessariamente com classes.
Uma breve observação ou resposta que eu daria é que geralmente você vê arquivos que contêm apenas uma interface, e geralmente a convenção é que eles começam com um I maiúsculo. Além disso, eu mencionaria que os arquivos não teriam código duplicado (especialmente dentro de um módulo, aplicativo ou biblioteca) e esse código seria compartilhado cuidadosamente através de certos limites entre módulos, aplicativos ou bibliotecas.
Robert Martin discute esse tópico no domínio do C ++ em Design de aplicativos C ++ orientados a objetos usando o método Booch (consulte as seções sobre Coesão, fechamento e reutilização) e no Código limpo .
fonte