Programação Orientada a Objetos - Pós Graduação - Aula 6 - Princípios OO

Preview:

Citation preview

Programação Orientada a Objetos

Princípios OO

Pós Graduação em Análise e Desenvolvimento de Sistemas

Aplicados à Gestão Empresarial

INSTITUTO FEDERAL DE EDUCAÇÃO, CIÊNCIA E TECNOLOGIA

TRIÂNGULO MINEIRO – Campus Uberlândia Centro

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Introdução

• Por que precisamos implementar baixo acoplamento, alta coesão, dentre tanto outros princípios e conceitos básicos em POO?

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Curva de Defeitos do Hardware

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Curva de Defeitos do Software

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Análise - Curva de Defeitos

• Hardware se desgasta com o tempo;

• Software se deteriora com o tempo;

• Boa parte dos Software legados são migrados para novas tecnologias por deterioração, e não por necessidades tecnológicas.

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Análise - Curva de Defeitos

• Um bom design de Software visa a uma arquitetura flexível que permita futuras alterações, facilitando a produção de código organizado e legível, maximizando seu reaproveitamento;

• Boas práticas OO procuram trazer os benefícios mencionados acima para o design.

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Programe voltado à Interface, não à Implementação

• Contains() de ArrayList é uma busca muito custosa em termos computacionais;

• Alternativas de coleções, como HashSet, são mais eficientes, pois usam internamente uma tabela Hash.

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Programe voltado à Interface, não à Implementação

• O problema ao efetuar esta manutenção, é que todo o código que usava o retorno do método ArrayList será quebrado, alterando todos os lugares que dependem de alguma forma desse método;

• Tarefas do tipo search/replace são um forte sinal de código ruim;

• Vincular os funcionários a uma implementação específica de Collection, caracteriza alto acoplamento.

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Programe voltado à Interface, não à Implementação

• Quanto menos específica for a interface/classe referenciada, menor o acoplamento e mais possibilidades de diferentes implementações;

• Como consequência, o código cliente terá uma gama menor de métodos que podem ser invocados.

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Programe voltado à Interface, não à Implementação

• Devemos procurar um balanço entre o desacoplamento e a necessidade do nosso código;

• Princípio de Segregação de Interfaces –clientes não devem ser forçados a depender de interfaces que não usam.

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Programe voltado à Interface, não à Implementação

• Hibernate usa uma implementação específica de List, mas sempre retorna List para evitar quebra de compatibilidade com o código-fonte da aplicação cliente.

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Programe voltado à Interface, não à Implementação

• E se quisermos receber objetos via socket (SocketInputStream), como faz?

• Utilize sempre o tipo menos específico possível.

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Programe voltado à Interface, não à Implementação

• Geralmente, para a API JDBC, utiliza-se uma Connection, ao invés de OracleConnection, MysqlConnection, dentre outros.

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Programe voltado à Interface, não à Implementação

• Interfaces irão ajudar muito para evitar instruções switch, ou mesmo um excessivo número de ifs encadeados, evitando acoplamentos no modelo, ocorrendo mudanças frequentes toda vez que uma nova entidade for adicionada no domínio.

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Programe voltado à Interface, não à Implementação

• No projeto criado nas aulas anteriores, os casos abaixo estão respeitando esse princípio

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Programe voltado à Interface, não à Implementação

• Contudo, ClienteView não está respeitando, gerando um alto acoplamento com ClienteControl.

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Programe voltado à Interface, não à Implementação

• O certo seria criar interfaces e factoriespara o Control, visando desacoplar o máximo possível;

• Contudo, neste caso, como existe uma implementação de Beans Binding entre o view e o Control, o prejuízo deste acoplamento é bastante minimizado.

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Componha Comportamentos

• Códigos são mais fáceis de entender e manter quando possuem poucas possibilidades de fluxos lógicos, ou seja, poucos caminhos de execução.

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Componha Comportamentos

• Quantas possibilidades diferentes existem para a execução deste método?

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Componha Comportamentos

• Existem diversas responsabilidades de execução para esta classe;

• Este comportamento pode ser composto por diversas partes menores, por isso refatorações podem ser executadas.

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Componha Comportamentos

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Componha Comportamentos

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Componha Comportamentos

• Observa-se que, passando de estruturado para OO, o sistema ganhou

4 novas classes e uma

Interface.

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Componha Comportamentos

• O comportamento foi quebrado em diversas partes, onde foram juntados novamente através de composição;

• O polimorfismo permite trabalhar de maneira uniforme com partes que executam tarefas distintas.

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Componha Comportamentos

• Ao implementar os métodos da Interface Processo na classe Transferência, observa-se que o Princípio de Segregação de Interfaces foi violado.

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Componha Comportamentos

• Neste caso, o ideal é quebrar as interfaces em uma hierarquia, assim como existe a hierarquia entre Collection e List/Set/Map;

• Caso o projeto não seja refatorado agora, existe uma grande chance de sofrer novo refactoring posteriormente, mesmo que a implementação deste método seja simples.

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Evite Herança, favoreça composição

• O maior problema da Herança é que acoplamos a implementação da classe mãe muito precocemente, criando a necessidade da classe filha conhecer muito bem o código interno da classe mãe, o que é visto como quebra de encapsulamento.

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Evite Herança, favoreça composição

• Exemplo: Herança entre Hashtable e Properties.

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Evite Herança, favoreça composição

• A motivação dos desenvolvedores da JDK é válida: o reaproveitamento de código já escrito na classe Hashtable;

• Usar composição permite o reaproveitamento de código sem o efeito indesejado de quebra de encapsulamento;

• No exemplo da jdk, bastaria a classe Properties fazer associação para um Hashtable privado, e o método setProperty() delegar para a invocação de hashtable.put()

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Evite Herança, favoreça composição

• Ao substituir herança por interface, as vantagens do polimorfismo permanecem, e o acoplamento é bem menor, já que nenhuma dessas classes precisam conhecer o funcionamento interno de outras, especialmente da classe mãe.

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Evite Herança, favoreça composição

• No projeto das aulas anteriores, ficou claro que PedidoDaoImpl e ClienteDaoImplficaram livres com o comportamento de Composição

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Cuidado com o modelo anêmico

• Um dos pilares de POO é que não se deve expor os detalhes de implementação;

• Encapsulando a implementação, pode-se trocar com facilidade, já que não existe outro código dependendo destes detalhes;

• O usuário poderá acessar o objeto através do contrato definido pela interface pública.

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Cuidado com o modelo anêmico

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Cuidado com o modelo anêmico

• No exemplo da classe Conta, o método setSaldo() feriu o encapsulamento, já que dificilmente o saldo de uma conta será simplesmente “substituído” por outro;

• Para alterar o saldo, faz mais sentido alguma operação como saque() e deposito();

• Nunca crie um getter/setter sem uma necessidade real;

• Códigos como conta.setSaldo(conta.getSaldo() + 100) estarão espalhados por toda a aplicação.

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Cuidado com o modelo anêmico

• Caso a aplicação precise modificar para que uma taxa seja debitada toda vez que for realizado um depósito, será necessário percorrer todo o código e modificar diversas invocações, usando search/replace.

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Cuidado com o modelo anêmico

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Cuidado com o modelo anêmico

• O código de exemplo é bem procedural, pois não possui atributos, e excesso do uso de métodos como funções;

• A classe Banco possui uma intimidade inapropriada com a classe Conta, pois conhece demais a sua implementação interna;

• Falta de uso do princípio Tell, Don´t Ask;

• Está rompendo o princípio básico de manter comportamento e estado relacionados em uma única classe.

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Cuidado com o modelo anêmico

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Cuidado com o modelo anêmico

• Enriqueça as classes com métodos de negócio, para que não se tornem apenas estruturas de dados;

• Algumas vezes getters/setters são necessários, mas cuidado no uso indiscriminado destes.

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Cuidado com o modelo anêmico

• No projeto da aula anterior, rapidamente foi percebido que para validar as entidades, nada melhor do que delegar este comportamento às mesmas.

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Cuidado com objetos mutáveis

• Objetos mutáveis são passíveis de efeitos colaterais, gerando bugs indesejáveis.

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Cuidado com objetos mutáveis

• Objetos imutáveis são muito mais simples de manipular, e possuem comportamento previsível.

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Cuidado com objetos mutáveis

• Objetos mutáveis são imprevisíveis, pois no exemplo abaixo é impossível determinar que a saída será o ano atual;

• Como solução, muitos criam cópias defensivas dos objetos, como:

Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br

Referências

• SILVEIRA, Paulo, Guilherme. LOPES, Sérgio. MOREIRA, Guilherme, SEPPAT, Nico. KUNG, Fábio. Introdução à Arquitetura e Design de Software. Editora Campus, 2012;

• PRESSMAN, Roger. Engenharia de Software –Uma abordagem Profissional – 7ª edição, 2011;

• ANICHE, Maurício. Orientação a objetos e SOLID para Ninjas. Casa do Código, 2015;

• GUERRA, Eduardo. Design Patterns com Java. Casa do Código, 2014.

Recommended