Páginas

sábado, 14 de julho de 2012

Princípios SOLID - parte 1

Um dos princípios ágeis é a resposta rápida a mudança, porem muitas vezes o sistema encontra-se tão acoplado que não conseguimos dar uma resposta rápida a mudança solicitada e em consequência a isso ferimos um dos quatro valores do XP, "Coragem", pois não vamos querer mexer no que esta funcionando, para garantir o que esta funcionando vamos copiar, colar e dar uma alterada no que precisamos, muito bem você conseguiu atender rápido a solicitação do teu cliente, porem acaba de criar um debito técnico no projeto, e como tal em algum momento ele será cobrado e os juros cobrados serão bastante altos pode ter certeza.

Pois bem, o que fazer então? Utilizar boas praticas de desenvolvimento de software (sei que na moiraria das vezes a pressão pela entrega é tanta, que as boas praticas que se %$%$@%$**(@#, mas garanto a vocês elas podem nos salvar de problemas muitas vezes impossíveis de resolver), o benefícios de um código limpo e organizado, com baixas dependências fara com que você abrace a mudança, e com certeza não vai te faltar coragem quando a próxima solicitação do cliente chegar (aquelas mudanças que mudam tudo que se tinha pensado). Os princípios SOLID de desenvolvimento foram introduzidos por Robert C. Martin, são cinco princípios que podem nos auxiliar a desenvolver um projeto orientado a objetos bastante robusto e faram com que possamos alcançar os benefícios sitados anteriormente. 
  
Princípios SOLID

  • S  -  Silge Responsability Principle (Responsabilidade Unica)
  • O -  Open Close Principle
  • L  -  Liskov Substitution Principle
  • I   -  Interface Segregation Principle
  • D  - Dependency Inversion Principle



Vou fazer um breve resumo de Silge Responsability Principle e Open Close Principle, e depois apresentar um exemplo onde possamos ver na pratica um pouco de cada um.

1. Silge Responsability Principle (Responsabilidade Unica)



Todas as classes do nosso sistema devem ter um unica responsabilidade, pois elas não podem ter mais de uma razão para existir. Porque cada responsabilidade a mais que a classe venha a ter pode se tornar um eixo de mudança, tornando essas responsabilidades acopladas. Muitas vezes alterações em uma das responsabilidades pode impactar ou inutilizar a outra, tornando assim nosso projeto frágil e difícil de dar manutenção. 
O princípio da responsabilidade unica é extremamente simples, porem na pratica é um dos mais difíceis de implementar, definir o principio como fiz anteriormente é algo natural e simples de fazer, porem implementa-lo vai alem de um simples projeto de software orientado a objetos, temos que entender os conceitos do domínio para podermos criar os nossos objetos com uma unica responsabilidade.

2. Open Close Principle(Aberto e Fechado)

Quando uma mudança em um sistema resulta em uma cascata de mudanças em módulos dependentes, o projeto do sistema possui características indesejáveis. A cascata de alterações torna o sistema mais frágil e torna suas partes mais difíceis de reutilizar O princípio “open-closed” sugere que se construam classes que
nunca mudem. Quando os requisitos mudarem, o comportamento das classes deve ser estendido pela adição de código novo, não pela alteração do código existente.

Estudo de Caso:(Esse exemplo foi pego de um teste que um amigo meu recebeu para entrar em um empresa)

Em um sistema de ingressos de um cinema, possuímos a classe ingresso que possui informações de sala, horário e valor do ingresso. Ela estava atendendo muito bem a responsabilidades que foram definidas a ela, porem nosso cliente fez uma alteração dos requisitos iniciais e que pode impactar em nosso projeto pois não tinha sido previsto. Ele precisava que o ingresso tivesse um valor 'X', porem dependendo do tipo de pessoa e dia da semana deveria ser dado um desconto na compra do ingresso. Abaixo estão os requisitos da nova funcionalidade que deveremos projetar e implementar usando os dois princípios SOLID descritos anteriormente.


Valor do Ingresso Normal: R$ 10.00
Crianças: R$ 5.50
Estudantes: R$ 8.00
Idosos: R$ 6.00

Descontos de acordo com o dia de semana
Segunda-Feira:
      - 10% para todos(crianças, idosos, estudantes)
Terça-Feira:
      - 15% idosos e crianças;
      - 5% estudantes;
Quarta-Feira:
      - 40% idosos
      - 30% crianças
      - 50% estudantes
Quinta-Feira
      - 30% idosos e estudantes
Sexta-Feira
      - 11% crianças
Domingo/Sábados/Feriados
      - 5% Idosos
OBS: Todo estudante mediante apresentação da carteirinha de estudante possui desconto para todos os 
dias da semana, exceto finais de semana 35% de desconto em todos os ingressos;

Solução Proposta:

Podemos criar um método que retorna o valor, passando o dia da semana e a pessoa que está comprando( duas Enum)  retornarValorComDesconto(diaSemana,Pessoa), se ele tivesse entregue assim com certeza ele estaria desempregado no momento, não sei a solução dele mas ele conseguiu a vaga, hahahaha. 

Pois bem vamos a solução que desenvolvi para esse problema, criei a classe DescontoDoDia que é abstrata onde implementei os métodos para retorno do desconto de acordo com o tipo de ingresso, para cada dia da semana criei uma classes que estende DescontoDoDia, elas fazem sua implementação do desconto dado de acordo com a pessoa. A classe ingresso eu mantive e apenas fiz extends dos novos tipos definidos e cada um com o seu valor de ingresso característico.

E onde fica o método para calcular o desconto? Em Ingresso ou nos DescontosDoDia? Não coloquei em nenhuma e sim em uma classe de serviço(padrões do DDD), que faz esse calculo para mim, pois analisando o problema achei que não era responsabilidade de nenhuma das classes criadas o calculo do desconto, em padrões GRASP vou falar o que devemos fazer quando surgir problemas semelhantes a esse, mas por enquanto basta saber que usei o padrão Pure Fabrication.

A solução achada contempla os dois princípios definidos anteriormente, uma vez que foram criadas classes com uma unica responsabilidade, e criamos classes que nunca mudaram, Ingresso e DescontoDoDia, se precisarmos de implementações futuras devido a novas categorias de desconto ou algo parecido provavelmente criando classes que estendam elas estaremos atendendo os requisitos. 

Pois bem, se os princípios passados forem entendidos e implementados, nossos projetos estarão bem menos acoplados e bem mais robustos para manutenções futuras que possam surgir. O código fonte e os  artefatos do exemplo estão no GiHub clique aqui. Obrigado e até a próxima.








Nenhum comentário:

Postar um comentário