O documento discute os cinco Princípios SOLID de projeto de software, que visam melhorar a qualidade e manutenibilidade do código. São eles: Single Responsibility Principle, Open-Closed Principle, Liskov Substitution Principle, Interface Segregation Principle e Dependency Inversion Principle. Cada princípio é explicado com seus benefícios e técnicas para implementação, como herança, injeção de dependência e padrões de projeto.
43. Violações Comuns em Sub-tipos:
• Lançar novas exceções
• Pré-condições mais restritivas
44. Violações Comuns em Sub-tipos:
• Lançar novas exceções
• Pré-condições mais restritivas
• Pós-condições menos restritivas
45. Violações Comuns em Sub-tipos:
• Lançar novas exceções
• Pré-condições mais restritivas
• Pós-condições menos restritivas
• Invariantes menos restritivos
Quem já conhecia os princípios antes?
Quem consegue citar e explicar os 5 princípios?
Existem várias ‘dimensões’: eficiência, testabilidade, confiabilidade, usabilidade, monitorável, manutenibilidade, clareza
Qual a mais básica?
Livros de Engenharia de software sempre dizem isto, certo?
Ligado ao relacionamento e interdependencias entre classes
Como identificar o grau de coesão e de acoplamento?
Existem métricas (complexidade ciclomática, etc), mas uma forma empírica seria: pelos sintomas da falta de qualidade!
Rigidez: dificil de mudar
Rigidez: dificil de mudar
Fragilidade: mudança em um lugar quebra ou causa bugs em vários lugares
Rigidez: dificil de mudar
Fragilidade: mudança em um lugar quebra ou causa bugs em vários lugares
Imobilidade: partes uteis que poderiam ser reaproveitadas dão muito esforço ou risco para separar do original....
Tudo isto é o famoso ‘código spaguetti’!
Uma vez identificada baixa qualidade, o que podemos fazer?
Principios SOLID podem ajudar!
Descritos por Robert C. Martin, aka “Uncle Bob” (objectmentor, cleancoders.com)
Não deve ser aplicado cegamente, sem bom senso!
Ex: TP´s, protótipos
Dica: utilize o Princípio quando “sentir as dores”!
A classe é focada em apenas uma coisa (conceito, regra, serviço, etc)
Canivete suiço: e se for preciso trocar a faca por um abridor de lata? E se a faca quebrar?
Reuso = com um unica responsabilidade é maior a chance de reaproveitar
Clareza = codigo tende a ser mais curto, sem ações inesperadas
Nomeaçao = com um unica responsabilidade fica mais facil encontrar um nome
Leitura facil = se é claro, tem bons nomes e curtos fica bem mais facil a leitura e entendimento
Reuso = com um unica responsabilidade é maior a chance de reaproveitar
Clareza = codigo tende a ser mais curto, sem ações inesperadas, ou seja, menor chance de ter bugs!
Nomeaçao = com um unica responsabilidade fica mais facil encontrar um nome
Leitura facil = se é claro, tem bons nomes e curtos fica bem mais facil a leitura e entendimento
Reuso = com um unica responsabilidade é maior a chance de reaproveitar
Clareza = codigo tende a ser mais curto, sem ações inesperadas, ou seja, menor chance de ter bugs!
Nomeaçao = com um unica responsabilidade fica mais facil encontrar um nome
Leitura facil = se é claro, tem bons nomes e curtos fica bem mais facil a leitura e entendimento
Reuso = com um unica responsabilidade é maior a chance de reaproveitar
Clareza = codigo tende a ser mais curto, sem ações inesperadas, ou seja, menor chance de ter bugs!
Nomeaçao = com um unica responsabilidade fica mais facil encontrar um nome
Leitura facil = se é claro, tem bons nomes e curtos fica bem mais facil a leitura e entendimento
Reuso = com um unica responsabilidade é maior a chance de reaproveitar
Clareza = codigo tende a ser mais curto, sem ações inesperadas, ou seja, menor chance de ter bugs!
Nomeaçao = com um unica responsabilidade fica mais facil encontrar um nome
Leitura facil = se é claro, tem bons nomes e curtos fica bem mais facil a leitura e entendimento
Granularidade: Responsabilidade pode ser tão grande ou tão pequena qto se queira! Dica: pensar em razões para mudar
Explosão: pode dificultar o entendimento; porem não existirá muito mais código do que se houvessem poucas classes – a logica geral é a mesma; e a clareza, tende a facilitar
Granularidade: Responsabilidade pode ser tão grande ou tão pequena qto se queira! Dica: pensar em razões para mudar
Explosão: pode dificultar o entendimento; porem não existirá muito mais código do que se houvessem poucas classes – a logica geral é a mesma; e a clareza, tende a facilitar
Granularidade: Responsabilidade pode ser tão grande ou tão pequena qto se queira! Dica: pensar em razões para mudar
Explosão: pode dificultar o entendimento; porem não existirá muito mais código útil do que se houvessem poucas classes – a logica geral é a mesma; e a clareza, tende a facilitar
Dúvidas antes da demo?
ETL básico: CSV para banco de dados (é incrível como isto ainda é comum...)
Depois do DEMO:
SRP é a ‘mãe’ de todos os demais princípios SOLID. Os demais princípios são como técnicas adicionais ou heurísticas para aplicar SRP
Usar ‘if’ ou ‘switches’ ou incluir código diretamente não deve ser a primeira opção!
Exceto para corrigir bugs
É necessário preparar seu código para OCP! Quais técnicas podem ajudar (das piores para as melhores)
Pode ser sofisticado ao usar delegates/lambdas
Herança: polimorfismo/sobrescrição de métodos (problema no C#: necessário marcar métodos como virtual);
Template Method Pattern;
Eventos (seja nativos – C# - ou usando frameworks): sinaliza ocorrências de interesse, expondo informaçoes e ate permitindo alterar o fluxo (ex: FormClosing) – é necessário definir quais momentos serão interessantes...
Métodos de extensão (C#): OCP por definição, já que a classe original permanece intacta (mas nao comece a criar bibliotecas de classes estáticas (testabilidade vai sofrer!)
Javascript e linguagens dinâmicas permitem extender classes também (protótipos, mixins)
Não introduz bugs em código existente, já testado, pois estes são minimamente alterados
Reduz gráfico de dependência de cada classe
Pensar em tudo que pode vir a ser necessário, no futuro, gera desperdício de tempo (a menos que vc seja um desenvolvedor de frameworks)
Dúvidas antes da demo?
Novo requisito: adicionar o total de registros processados
Parece lógico, certo? Mas quantas vezes já viram isto ->
Desconfie quando precisar usar “if (x is T)” – você pode estar violando o LSP!!
Programação por contrato – Bertrand Meyer
Exceto se forem exceções derivadas de exceções lançadas pelo tipo base
Ex: se parâmetro pode ser nulo no tipo base, o subtipo não pode recusar um parâmetro nulo
Ex: se o retorno de um método nunca era nulo no tipo base, o subtipo não pode retornar nulo no mesmo método.
Ex: propriedade readonly no tipo base passa a ser mutável no subtipo
FRÁGIL!
Auxilia nos 3 últimos problemas (pre-cond, pos-cond e invariantes)
Auxilia principalmente na ‘violação inicial’: encapsule em outra interface/classe abstrata os métodos que precisavam do teste do subtipo – agora estaremos testando se um comportamento é implementado.
Relacionado ao próximo principio (ISP)
Em vez de perguntar algo sobre o estado de um objeto, decidir o que fazer e então pedir ao objeto para fazer, peça diretamente ao objeto para fazê-lo, e deixe a decisão por conta do próprio objeto (relacionado ao SRP)
Dúvidas antes da demo?
Interfaces grandes em geral indicam violação do SRP – está fazendo coisas demais!
Interface menor = alta coesão
Facil pra quem implementa
Menos coisas para se entender, portanto o cliente tem menos chance de errar ao usar
Dúvidas antes da demo?
Demo na Web ->
7 propriedades e 17 métodos, se eu contei direito!!!
Observem: usa herança
Mistura de Façade (UserManager) com Strategy (IUserStore, IUserPasswordStore, etc) - usa composição
Utilizar uma abstração em vez de uma implementação, para facilitar a substituição de implementações
Implementações nem sempre são feitas ‘sob medida’
Uso de um ‘container’, responsável por ‘resolver’ as dependências (por construtor, por um ‘setter’, por uma interface)
Mesmos do OCP – forma especializada de OCP
Testes de unidade ficam mais fáceis: pode-se substituir uma dependência para testar uma classe em isolamento
Possibilidade de se alterar implementações (usando Decorator, Proxy, Interception, etc)
Pode comprometer desempenho, por exemplo
Encontrar as dependencias ao ler o código fica mais dificil, principalmente quando existem várias implementações da mesma abstração
Duvidas antes da demo?
(Antes de ir para próximo slide) Vale reforçar...
NÃO FIQUE OBCECADO!
Novamente: utilize o Princípio quando “sentir as dores”!
Os melhores cozinheiros sabem a ordem de preparo, as quantidades corretas, conseguem adaptar receitas e utilizar ingredientes alternativos, etc...
A analogia entre programação e cozinha é bastante útil:
-panelas e ingredientes corretos fazem bastante diferença
-pense em quem será servido
-receba feedback dos pratos servidos