Princípios SOLID - parte 1
Autor: Jorge Oleques | Publicado: 2012-07-14T10:00:00-07:00


Um dos princípios ágeis é a resposta&nbsp;rápida&nbsp;a mudança, porem muitas vezes o sistema encontra-se tão acoplado que não conseguimos dar uma resposta&nbsp;rápida&nbsp;a mudança solicitada e em&nbsp;consequência&nbsp;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&nbsp;rápido&nbsp;a solicitação do teu cliente, porem acaba de criar um debito&nbsp;técnico&nbsp;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&nbsp;desenvolvimento&nbsp;de software (sei que na&nbsp;moiraria&nbsp;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&nbsp;impossíveis&nbsp;de resolver), o&nbsp;benefícios&nbsp;de um&nbsp;código&nbsp;limpo e organizado, com baixas&nbsp;dependências fara com que você abrace a mudança, e com certeza não vai te faltar coragem quando a&nbsp;próxima&nbsp;solicitação do cliente chegar (aquelas mudanças que mudam tudo que se tinha pensado). Os&nbsp;princípios&nbsp;SOLID de&nbsp;desenvolvimento&nbsp;foram introduzidos por Robert C. Martin, são cinco&nbsp;princípios&nbsp;que podem nos auxiliar a desenvolver um projeto orientado a objetos bastante robusto e faram com que possamos alcançar os&nbsp;benefícios&nbsp;sitados&nbsp;anteriormente.&nbsp;

&nbsp;&nbsp;

Princípios SOLID


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







Vou fazer um breve resumo de&nbsp;Silge Responsability Principle e&nbsp;Open Close Principle,&nbsp;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&nbsp;frágil&nbsp;e&nbsp;difícil&nbsp;de dar manutenção.&nbsp;

O&nbsp;princípio&nbsp;da responsabilidade unica é extremamente simples, porem na pratica é um dos mais&nbsp;difíceis&nbsp;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&nbsp;domínio&nbsp;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&nbsp;mudanças em módulos dependentes, o projeto do sistema possui&nbsp;características indesejáveis.&nbsp;A cascata de alterações torna o sistema mais frágil e torna suas&nbsp;partes mais difíceis de reutilizar&nbsp;O princípio “open-closed” sugere que se construam classes que

nunca mudem.&nbsp;Quando os requisitos mudarem, o comportamento das classes deve&nbsp;ser estendido pela adição de código novo, não pela alteração do&nbsp;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,&nbsp;possuímos&nbsp;a classe ingresso que possui informações de sala,&nbsp;horário&nbsp;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&nbsp;princípios&nbsp;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:

&nbsp; &nbsp; &nbsp; - 10% para todos(crianças, idosos, estudantes)

Terça-Feira:

&nbsp; &nbsp; &nbsp; - 15% idosos e crianças;

&nbsp; &nbsp; &nbsp; - 5% estudantes;

Quarta-Feira:

&nbsp; &nbsp; &nbsp; - 40% idosos

&nbsp; &nbsp; &nbsp; - 30% crianças

&nbsp; &nbsp; &nbsp; - 50% estudantes

Quinta-Feira

&nbsp; &nbsp; &nbsp; - 30% idosos e estudantes

Sexta-Feira

&nbsp; &nbsp; &nbsp; - 11% crianças

Domingo/Sábados/Feriados

&nbsp; &nbsp; &nbsp; - 5% Idosos

OBS: Todo estudante mediante apresentação da carteirinha de estudante possui desconto para todos os&nbsp;

dias da semana, exceto finais de semana 35% de desconto em todos os ingressos;



Solução Proposta:



Podemos criar um&nbsp;método que retorna o valor, passando o dia da semana e a pessoa que está comprando( duas Enum)&nbsp;&nbsp;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.&nbsp;



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&nbsp;DescontoDoDia, elas&nbsp;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&nbsp;característico.



E onde fica o&nbsp;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&nbsp;princípios&nbsp;definidos anteriormente, uma vez que foram criadas classes com uma unica responsabilidade, e criamos classes que nunca mudaram, Ingresso e&nbsp;DescontoDoDia, se precisarmos de implementações futuras devido a novas categorias de desconto ou algo parecido provavelmente criando classes que&nbsp;estendam&nbsp;elas estaremos atendendo os requisitos.&nbsp;





Pois bem, se os&nbsp;princípios&nbsp;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 &nbsp;artefatos do exemplo estão no GiHub clique aqui. Obrigado e até a&nbsp;próxima.