Fundamentos e princípios do projeto orientado a objetos

Post on 11-Jun-2015

6.975 views 0 download

Transcript of Fundamentos e princípios do projeto orientado a objetos

Fundamentos e Princípios do ProjetoOrientado a Objetos

Autor: Evandro João Agnesevandroagnes@yahoo.com.br

2

Abstração

Seleção de alguns aspectos relevantes a uma determinada análise, suprimindo outros

Serviços e atributos aplicáveis a objetos dentro de um determinado contexto

3

Classes e Objetos

Classe

Descrição de um conjunto de objetos similares

Abstratas ou Concretas

Objeto

Reúnem na mesma estrutura:

Atributos (dados) que definem o estado

Operações que definem o comportamento e manipulam os dados

Identidade de objetos

Retenção de estado

4

Encapsulamento

Esconder detalhes de implementação do estado e comportamento do objeto

Objetos são acessados apenas pela interface externa definida para eles

Detalhes de implementação das classes podem ser alterados sem que as aplicações necessitem de alterações

5

Mensagem

Comunicação feita entre objetos

Chamadas a métodos

6

Herança

Permite que novas classes sejam construídas usando código e características declaradas em outras classes

Relação do tipo “é um” entre classes

Super-classes e sub-classes

Sub-classe herda todos atributos e métodos da super-classe

7

Polimorfismo

Propriedade na qual uma chamada genérica de um método pode ser executada de diferentes maneiras de acordo com o objeto que fez a chamada

Exemplo

Classe Reta: método desenhar()

Classe Círculo: método desenhar()

8

Relacionamentos

Associação

Relação do tipo “tem um” entre objetos

Agregação

Relação do tipo “todo-parte”

Dependência fraca

Composição

Relação do tipo “todo-parte”

Dependência forte

9

Interdependência

Elementos que compartilham alguma necessidade

Tipos de Interdependência

Nome

Tipo ou classe

Convenção

Algoritmo

Posição

Valor

Identidade

10

Interdependência

Princípios

Minimizar a interdependência total através do encapsulamento

Minimizar qualquer interdependência que cruze as fronteiras do encapsulamento

Maximizar a interdependência dentro das fronteiras do encapsulamento

Abusos

Função amigável

Herança sem restrição

Detalhes internos do algoritmo de uma classe relevantes para outras classes

11

Domínios

Domínio de Aplicação

Domínio de Negócio

Domínio de Arquitetura

Domínio de Base

Baixareutilização

Médiareutilização

Altareutilização

Domínio de Apresentação

12

Grau de dependência ou acoplamento

Conjunto de classes que uma classe se baseia para operar

Grau de dependência pode ser

Direto

Indireto

Classes em domínios altos tem alto grau de dependência indireto e classes em domínios baixos tem baixo grau de dependência indireto

13

Grau de dependência ou acoplamento

Acoplamento é o caminho para o Lado Negro da Força!

Conduz para complexidade

Conduz para confusão

Conduz ao sofrimento

Uma vez que você inicie o caminho para o Lado Negro, ele sempre irá dominar seu destino. “Consumir você ele irá!”

Desacoplar através de abstrações e interfaces!

14

Lei de Demeter

Cada unidade deve conhecer apenas unidades intimamente relacionadas a ela

Segundo a Lei de Demeter as mensagens devem ser enviadas apenas para:

si mesmo - métodos do objeto

seus objetos - atributos da instância

parâmetros recebidos pelo método

objetos criados pelo método

15

Coesão

Classes com alta coesão

Todas as características contribuem para a abstração de tipo implementada pela classe

Classes com baixa coesão

Apresenta um conjunto de características diferentes

16

Problemas de coesão

Coesão de instância mista

Ter algumas características que são definidas apenas para alguns objetos da classe

Coesão de domínio misto

Uma classe contém um elemento que cria dependência com uma classe de domínio diferente que não tem qualquer tipo de negócio com a classe*

Coesão de papel misto

Uma classe contém um elemento que diretamente cria dependência de uma classe de mesmo domínio que não tem qualquer tipo de negócio com a classe*

* Uma classe B não tem qualquer tipo de negócio com A se A puder ser plenamente definida sem qualquer noção de B

17

Problema: Coesão de instância mista

18

Problema: Coesão de domínio misto

19

Problema: Coesão de papel misto

20

Espaço-estado e comportamento

Espaço-estado de uma classe é a totalidade de estados permitidos para qualquer objeto da classe

Cada componente do estado (atributos) de um objeto define uma dimensão

É o conjunto de valores de dimensões válidas para um objeto

O modo como o objeto muda de estado é o seu comportamento

O comportamento permitido de uma classe é o conjunto de transições que o objeto pode fazer entre os estados do espaço-estado

21

Espaço-estado e comportamento

O espaço-estado de uma subclasse deve estar contido inteiramente dentro do espaço-estado da superclasse

O espaço-estado de uma subclasse pode ter mais dimensões que a superclasse

22

Invariante de classe

Condição que todo objeto da classe deve satisfazer em todo o seu ciclo de vida

São restrições no espaço-estado do objeto

A invariante nunca deve ser quebrada

23

Pré-condições e pós-condições

Devem garantir a invariante do objeto

Toda operação tem uma pré-condição e uma pós-condição

A pré-condição é uma condição que deve ser verdadeira quando a operação começar a executar

A pós-condição é uma condição que deve ser verdadeira quando a operação finalizar sua execução

24

Conformidade de tipo

Um sub-tipo deve se conformar a seu super-tipo

O sub-tipo pode ser utilizado em qualquer contexto em que o super-tipo seja esperado

A invariante da subclasse deve ser pelo menos tão forte quanto a invariante da super-classe

A pré-condição de qualquer operação deve ser igual ou menos restritiva que a operação correspondente da super-classe

A pós-condição de qualquer operação deve ser igual ou mais restritiva que a operação correspondente na super-classe

25

Comportamento fechado

O comportamento herdado deve respeitar a invariante da sub-classe

Nem sempre é possível, neste caso deve-se efetuar alguma ação corretiva

evitar herança dos métodos que não respeitem a invariante

suprimir os métodos de modo que ele não tenha efeito (possivelmente lançando uma exceção)

estar preparado para reclassificar o objeto

26

Projeto de Qualidade

Fácil de entender

Fácil de alterar

Fácil de reusar

27

Projeto Ruim

Rígido

Difícil de alterar

Uma alteração requer uma cascata de outras alterações

Impacto das alterações não consegue ser previsto

Frágil

A cada alteração novos erros aparecem em áreas aparentemente desconectadas

Imobilizado

Sem muita possibilidade de reuso

Partes desejadas de um componente possui muitas partes indesejadas para o reuso

28

Projeto Ruim

Pegajoso

Alterações corretas são mais difíceis de fazer que as erradas (bacalhau!)

Obscuro

Difícil de entender

Complexidade desnecessária

Repetição desnecessária

29

Princípios de Projeto

Princípio da Responsabilidade Única

The Single Responsibility Principle (SRP)

Princípio do Aberto-Fechado

The Open-Closed Principle (OCP)

Princípio de Substituição de Liskov

The Liskov Substitution Principle (LSP)

30

Princípios de Projeto

Princípio da Inversão de Dependência

Dependency Inversion Principle (DIP)

Princípio de Reuso de Composição

The Composite Reuse Principle (CRP)

Princípio de Segregação de Interface

The Interface Segregation Principle (ISP)

31

The Single Responsibility Principle

Uma classe deveria ter apenas uma razão para mudar

Responsabilidade = razão para mudança

Múltiplas responsabilidades = acoplamento alto, baixa coesão

Responsabilidades são eixos de alteração

Se uma classe faz mais de uma coisa, separe em classes diferentes

32

The Single Responsibility Principle

Podemos melhorar este projeto!!!

33

The Single Responsibility Principle

34

The Single Responsibility Principle

public class Grupo {private List servidores;

public List getServidores() {return servidores;

}

public void setServidores(List servidores) {this.servidores = servidores;

}}

public class Servidor {

private String login;private Grupo meuGrupo;

public Servidor (String login, Grupo grupo) {this.login = login;this.meuGrupo = grupo;meuGrupo.getServidores().add(this.login);

}}

Exemplo de código...

35

The Single Responsibility Principle

public class Grupo {private HashMap servidores;

public HashMap getServidores() {return servidores;

}

public void setServidores(HashMap servidores) {this.servidores = servidores;

}}

public class Servidor {

private String login;private Grupo meuGrupo;

public Servidor (String login, Grupo grupo) {this.login = login;this.meuGrupo = grupo;meuGrupo.getServidores().put("login", this.login);

}}

E se alterarmos a lista de servidores para um HashMap?

A classe Servidor precisa ser alterada também...

36

The Single Responsibility Principle

public class Grupo {private HashMap servidores;

public void incluirServidor(Servidor servidor){// Regra para inserir Servidor...

}}

public class Servidor {

private String login;private Grupo meuGrupo;

public Servidor (String login, Grupo grupo) {this.login = login;this.meuGrupo = grupo;meuGrupo.incluirServidor(this);

}}

Se a regra para incluir servidor for responsabilidade do Grupo, o código da classe Servidor não precisa ser alterado...

37

The Open-Closed Principle

Classes devem estar abertas para extensão e fechadas para modificação

Quando os requisitos mudam (e eles mudam!) o projeto deve permitir estender o comportamento adicionando novo código e não alterando o comportamento do código existente

Se a alteração de uma classe ou método resultar em uma cascata de alterações em outras classes e métodos, você tem um projeto “ruim”

38

The Open-Closed Principle

Separe o que varia

Encapsular o que varia para que não afete o resto do código

Menos conseqüências indesejadas

Mais flexibilidade

Abstração e polimorfismo são a chave para este princípio

39

The Open-Closed Principle

public class Matricula {private BigDecimal totalCred;private String tipoMatr;private Obrigacao obrigacao;

public void matricular(){// ...obrigacao.calcular(totalCred, tipoMatr);

}}

public class Obrigacao {

public BigDecimal calcular(BigDecimal creditos, String tipo){

BigDecimal valor = null;

if (tipo.equals("curricular")) {// Calcula matricula curricular

} else if (tipo.equals("extra-curricular")){// Calcula valor extra-curricular

} else {// Calcula valor padrao

}return valor;

}}

40

The Open-Closed Principle

41

The Liskov Substitution Principle

Conformidade de Tipo

Sub-tipos podem substituir super-tipos

Guia para criação de abstrações

Contratos

Violando este princípio podemos violar também o Princípio do Aberto-Fechado

42

The Liskov Substitution Principle

43

The Liskov Substitution Principle

public class Bolsa {

/** * Pre-condicao: valor não pode ultrapassar o devido * @param valor Valor do desconto lancado */public void lancarDesconto(BigDecimal valor){

}}

public class Financiamento extends Bolsa {

/** * Pre-condicao: deve ser menor que o devido * @param valor Valor do desconto lancado */public void lancarDesconto(BigDecimal valor){

}}

44

The Liskov Substitution Principle

45

Dependency Inversion Principle

Dependa de abstrações (ou interfaces) e não de classes concretas

Programe para uma interface, não para uma implementação

Explora o polimorfismo

Interface pode ser um super-tipo

Alterações em classes que implementam uma interface não quebram código cliente

46

Dependency Inversion Principle

47

The Composite Reuse Principle

Preferir a composição em relação a herança

Herança excessiva pode causar fragilidade e hierarquias complexas de classes

Herança pode quebrar o encapsulamento

Com herança podemos sobrescrever um método, às vezes indesejável. Na composição os métodos devem ser utilizados como foram definidos

Novas funcionalidades podem ser agregadas sem alteração no código existente (Princípio do Aberto-Fechado)

48

The Composite Reuse Principle

Herança

Comportamento é herdado

Não podemos alterar o comportamento sem escrever mais código

Composição

Comportamento como um atributo

Mais flexibilidade

Permite alterar o comportamento em tempo de execução

49

The Composite Reuse Principle

Exemplo de uso de herança:

50

The Composite Reuse Principle

Mesmo exemplo utilizando composição e CRP:

51

The Composite Reuse Principle

Outro exemplo com herança:

52

The Composite Reuse Principle

Cálculo do bônus passou a ser diferente para os empregados em tempo integral

O que fazer para garantir um bom reuso sem código duplicado?

Mas...

53

The Composite Reuse Principle

54

The Interface Segregation Principle

Interfaces para específicos tipos de cliente são melhores que uma interface de propósito geral

Clientes não deveriam ser forçados a depender de interfaces que eles não utilizam

Interfaces muito grandes podem introduzir acoplamentos não desejados entre os clientes

ISP não recomenda que seja criada uma interface para cada classe cliente, mas que as classes sejam classificadas por tipo

Caso 2 ou mais tipos de clientes utilizem o mesmo método, este deve estar em ambas interfaces

55

The Interface Segregation Principle

56

The Interface Segregation Principle

57

Referências

Fundamentals of Object-Oriented Design in UML - Meilir Page-Jones

Head First Design Patterns - Elisabeth Freeman, Eric Freeman, Bert Bates and Kathy Sierra

Design Principles e Design Patternshttp://www.objectmentor.com/resources/articles/Principles_and_Patterns.pdf

Domain Driven Design Quicklyhttp://www.infoq.com/minibooks/domain-driven-design-quickly

Contratos Nuloshttp://fragmental.com.br/wiki/index.php/Contratos_Nulos

58

Referências

Lei de Demeterhttp://c2.com/cgi/wiki?LawOfDemeter

Articles for Object Oriented Designhttp://www.objectmentor.com/resources/publishedArticles.html