A apresentação está carregando. Por favor, espere

A apresentação está carregando. Por favor, espere

Programação Orientada a Objetos

Apresentações semelhantes


Apresentação em tema: "Programação Orientada a Objetos"— Transcrição da apresentação:

1 Programação Orientada a Objetos
Projeto de Classes

2 Agenda Projeto baseado na responsabilidade Acoplamento Coesão
Explícito Implícito Coesão Classes Métodos Refatoração

3 Projeto O que torna um projeto bom ou ruim? Bons projetos
Exigem mais esforços à curto prazo. A longo prazo, os esforços são justificados. Implementação pode realizar suas tarefas com classes mal projetadas. O fato de executar uma aplicação não indica se ela esta bem estruturada ou não.

4 Princípios Princípios que devem ser seguidos:
Projeto baseado na responsabilidade. Encapsulamento. Fraco acoplamento. Alta coesão.

5 Problemas Surgem em geral quando: Classes bem projetadas:
Programador de manutenção tenta fazer algumas alterações Corrigir uma falha. Adicionar nova funcionalidade. Classes bem projetadas: Tarefa fácil e óbvia. Classes mal projetadas: Tarefa muito difícil e envolve muito trabalho.

6 Problemas Grandes aplicações
Tais problemas ocorrem durante a implementação original. Se o projeto começa com uma estruturação ruim, terminá-lo pode ser muito complexo Programa não pode ser terminado. Pode conter falhas. Demorar muito mais do que necessário para ser construído.

7 Adaptar e estender uma aplicação
Muitos dos efeitos de um projeto ruim se tornam evidentes quando se tenta: Adaptar. Estender.

8 World-of-Zuul

9 World-of-Zuul Classes bem documentadas
Ilustra que projeto ruim envolve algo mais profundo que simplesmente a aparência da classe ou quanto é boa sua documentação.

10 Introdução a Acoplamento
Qualidade de um projeto de classe: Acoplamento (coupling) Refere-se a interconectabilidade da classe. Objetos cooperam via interfaces bem definidas. O grau de acoplamento indica a firmeza que essas classes estão conectadas. Um bom projeto de classe visa: Baixo grau de acoplamento Acoplamento fraco O grau de acoplamento indica como é difícil fazer alterações

11 Classes fortemente acopladas
Uma alteração em uma classe pode tornar necessário alterar várias outras classes Deve-se evitar isso, pois o efeito de fazer uma alteração pequena pode facilmente se propagar por toda a aplicação Além disso, localizar todos os lugares onde as alterações devem ser feitas e realmente fazer as alterações pode ser difícil e demorados

12 Classes fracamente acopladas
Pode-se alterar uma classe sem fazer nenhuma alteração em outras classes.

13 Introdução a Coesão (cohesion)
Número e diversidade de tarefas pelas quais uma unidade de uma aplicação é responsável Classes. Métodos. Ideal Uma unidade de código deve ser responsável por uma unidade coesa (uma tarefa que pode ser vista com uma entidade lógica) Um método deve implementar uma operação lógica Uma classe deve representar um tipo de entidade

14 Reutilização Coesão visa reutilização
Se um método ou uma classe é responsável por apenas uma coisa bem definida Bem mais provável que ele possa ser utilizado novamente em um contexto diferente.

15 Vantagem complementar de Coesão
Quando alguma alteração é necessária, é provável que encontre-se todas as partes relevantes localizadas na mesma unidade

16 Duplicação de Código Forte indicador de projeto ruim Problemas:
Qualquer alteração em uma parte deve ser feita na outra, caso contrário, a aplicação fica inconsistente. Aumenta o trabalho que um programador de manutenção tem de fazer e introduz perigo de bugs. O programador pode não achar cópia do código, não alterá-la e assumir que o trabalho esta concluído. Não há nada que indique que uma segunda cópia do código existe Sintoma de má coesão

17 Exemplo de duplicação de código
Métodos printWelcome() e goRoom() da classe Game System.out.println("You are " + currentRoom.getDescription()); System.out.print("Exits: "); if(currentRoom.northExit != null) System.out.print("north "); if(currentRoom.eastExit != null) System.out.print("east "); if(currentRoom.southExit != null) System.out.print("south "); if(currentRoom.westExit != null) System.out.print("west "); System.out.println();

18 Raízes do Erro Os dois métodos em questão fazem duas coisas:
printWelcome() imprime a mensagem de boas vindas e imprime as informações sobre a localização atual goRoom() altera a localização atual , e imprime as informações sobre a localização atual Os dois métodos imprimem as informações atuais de localização, mas nenhum deles pode chamar o outro, porque eles também fazem outras coisas. Isso é um projeto ruim.

19 Solução do Erro Um projeto mais aprimorado utilizaria um método mais coeso separando em um única tarefa a impressão das informações atuais de localização. Os dois métodos podem fazer chamadas a esse novo método quando precisarem imprimir essas informações. Dessa maneira, não e necessário escrever o código duas vezes, e quando uma alteração for necessária , será preciso uma única modificação.

20 Fazendo Extensões Tarefa Adicionar uma nova direção de movimento.
Atualmente: norte, leste, sul e oeste. Deve-se permitir: para cima e para baixo.

21 Localizando código relevante
Duas classes: Room e Game Room é a classe que armazena a saída de cada sala. Game utiliza as informações de saída da sala atual para imprimir as informações sobre saídas e para se mover de uma sala para outra.

22 Classe Room Adicionar dois novos campos Alterar metodos setExits(…)

23 Classe Game Mais trabalhoso localizar as modificações
Localizar todos os lugares exige paciência e cuidado Métodos que devem ser alterados: createRoom() printWelcome() goRoom() Uma possivel solução seria adicionar as novas direções em todos esses métodos É a melhor solução???????????

24 Acoplamento O fato de haver muitos lugares onde todas as saídas são enumeradas e sintomático de projeto ruim. Ao declarar variáveis de saída na classe Room setExits()há um if por saída goRoom() há um if por saída printLocationInfo() há um if por saída Essa decisão de projeto cria trabalho: localizar todos esses lugares e adicionar dois novos casos E se um novo requisito fosse adicionar as direções como noroeste, sudeste????

25 Solução mais adequada Usar HashMap<String, Room> para armazenar as saídas Obriga-se a escrever código que pode operar com qualquer número de saídas Não obriga a tanta alterações no futuro Essa e uma alteração na maneira como a sala armazena suas informações. Teoricamente essa alteraçao deve afetar somente a classe Room (como as informações de saída são armazenadas), não a interface (o que a sala armazena)

26 Solução mais adequada De maneira ideal , quando apenas a implementação muda , outras classes não deviam ser afetadas. Isso seria um caso de acoplamento fraco. Em nosso exemplo, isso não funciona. Se as saídas de Room forem substituídas por um HashMap, a classe Game não compilará mais. Sintoma de acoplamento forte.

27 Encapsulamento para reduzir acoplamento
Problema principal: Uso de campos públicos Ao tornar públicas as saídas, a classe Room expôs em sua interface não apenas o fato de que tem saídas, mas exatamente como tais informações são armazenadas. Isso quebra um dos princípios fundamentais do bom projeto, o encapsulamento.

28 Encapsulamento Diretriz Vantagem
Ocultar informações de implementação da visualização O que uma classe pode fazer deve ser visível Como a classe é, não. Vantagem Se nenhuma outra classe sabe como as informações são armazenadas, pode-se facilmente alterar como elas são armazenadas em quebrar outras classes

29 Classe Room Modificada
Impôr separação entre o que e como Tornando os campos privados Método de acesso para obtê-los A classe Game deverá ser alterada também. Reduzindo drasticamente o código.

30 Classe Room Modificada
Até agora não alteramos a representação de saída. Somente a interface foi limpa. A alteração em Game e mínima. Ao invés de acesso a campos públicos, o uso de métodos , mas o ganho é significativo. Agora pode ser alterar, como as saídas são armazenadas na classe Room sem se preocupar com a quebra de qualquer outra classe. A representação interna em Room foi completamente separada da interface.

31 Classe Room Alterada Agora que o projeto está como devia estar, a troca dos campos separados por um HashMap é fácil. Vale enfatizar que pode-se fazer a alteração sem mesmo verificar se qualquer coisa quebrará em outra parte. Pois foram alterados apenas aspectos privados da classe Room. A interface permanece inalterada. Vantagens da alteração: Classe Room mais curta. Método getExit() foi reduzido ao extremo.

32 Classe Room Alterada Objetivo: inserir duas novas saídas.
Metodo setExits ainda precisa de aperfeiçoamento Interface da Classe Room Alterações afetam outras classes Não é possível separar completamente as classes, caso contrário objetos de classe diferentes não seriam capazes de interagir entre si. Ao invés disso, manter o grau de acoplamento o mais baixo possivel.

33 Método setExit() public void setExit(String direction, Room neighbor)
Agora, as saídas da sala podem ser configuradas uma saída por vez e qualquer direção pode ser utilizada para uma saída. Remove-se assim completamente a restrição de Room. A classe Room pode armazenar as direções para cima e para baixo, bem como qualquer outra direção que possa imaginar.

34 Projeto baseado na responsabilidade
Uso de encapsulamento adequado reduz o acoplamento e pode reduzir significativamente a quantidade de trabalho necessário para fazer alterações em aplicações. Porem esse não é o único fator que influencia o grau de acoplamento. Outro aspecto é conhecido pelo termo projeto baseado na responsabilidade.

35 Projeto baseado na responsabilidade
Idéia Cada classe deve ser responsável por tratar seus próprios dados Adição de novas funcionalidades Qual classe devemos adicionar um método para implementar essa nova função? Qual classe deve ser responsável pela tarefa? A resposta é: a classe que é responsável por alguns dados também deve ser responsável por manipulá- los.

36 Responsabilidade e Acoplamento
Versão original do printLocation() com o método getExitString() As informações sobre saéda estão armazenadas somente na própria sala, e a sala que é responsável por fornecer essas informações. A sala pode fazer isso muito melhor do que qualquer outro objeto, desde que tenha todo o conhecimento sobre a estrutura de armazenamento interno dos dados.

37 Responsabilidade e Acoplamento
Objetivo Reduzir acoplamento System.out.println(“You are ” + currentRoom.getDescription()); System.out.println(currentRoom.getExitString()); Implementação ainda pode ser melhorada Se adicionarmos itens as salas? Ou monstros? Ou outros jogadores? Tal descrição deve estar contida na sala. Porém se tais alteracoes fossem necessárias, a classe Game deve ser alterada (acoplamento)

38 Responsabilidade e Acoplamento
Nova brecha para o projeto baseado em responsabilidade Room mantem informações sobre a sala Ela tambem deve produzir uma descrição para a sala public String getLongDescription() { return "You are " + description + ".\n" + getExitString(); } Na classe Game System.out.println(currentRoom.getLongDescription());

39 Minimizando as alterações
Outro aspecto da separação e de princípios de responsabilidade Procura-se criar um projeto que facilite alterações posteriores Idealmente apenas uma única classe precisa ser alterada para fazer uma modificação Ocasionalmente, várias classes precisam de alteração, mas objetivamente com o mínimo possível de classes. Além do mais, as alterações necessárias em outras classes devem ser óbvias, fáceis de detectar e fáceis de executar

40 Minimizando as alterações
Alcança-se regras de bons projetos utilizando: Projeto baseado na responsabilidade Fraco acoplamento Alta coesão Ter em mente: Modificação e extensão Importante antecipar que um aspecto do programa pode sofrer alteração, a fim de facilitar essa alteração.

41 Acoplamento Implícito
Campos públicos Pratica que talvez crie forte acoplamento Necessário alteração em mais de uma classe para o que devia ser uma simples modificação Campos públicos devem ser evitados Porém, há formas piores de acoplamento Acoplamento implícito Uma classe depende de informações internas da outra Dependência não óbvia Acoplamento Explícito Não é bom Porém é óbvio (aplicação não compila)

42 Acoplamento Implícito
Novo requisito Adicionar nova palavra de comando ao jogo look (imprimir a descrição da sala e sair novamente) Solução Introduzir uma nova palavra de comando, no array validCommands na classe CommandWords Boa coesão Ao invés de definirmos o comando no Parser Facilita encontrar onde os comandos estão definidos e acrescentar outros O autor esta pensando na frente, assumindo que outros comandos podem ser definidos, e criou uma estrutura que torna isso fácil

43 Acoplamento Implícito
Após fazer a alteração, isso não funciona. Ao digitar look nada acontece. Palavra é reconhecida Porém não há ação vinculada a ela Isso pode ser corrigido adicionando o método look na classe Game. E adicionado mais um if no método processCommand. O acoplamento entre as classes Game, Parser, e CommandWor dpara ser boa Fácil fazer a extensão

44 Acoplamento Implícito
Emitir comando help Nota-se um pequeno problema O novo comando não e listado Fácil de corrigir Editar string do método printHelp de Game Feito rapidamente e não parece um grande problema E se tal erro não tivesse sido notado? Você pensou nesse erro antes de ler aqui? Problema fundamental Novo comando Ajuda precisa ser atualiza Fácil de esquecer tal alteração O programa compila e executa O programador de manutenção pode muito bem acreditar que o trabalho esta terminado e liberar um programa que agora contem uma falha

45 Acoplamento Implícito
Comandos alterados Texto de ajuda deve ser modificado (acoplamento) Mas nada no fonte do programa indica claramente essa dependência (implícito) Classe bem projetada Evita acoplamento implícito Seguindo a regra do projeto baseado na responsabilidade

46 Acoplamento Implícito
Classe CommandWord Responsável pelas palavras de comando Deve ser responsável pelas impressão das palavras de comando Adicionar metodo showAll() Classe Game printHelp() Ao invés de imprimir texto fixo Invoca um método de um objeto CommandWord para imprimir todas as palavras de comando

47 Acoplamento Implícito
Game não tem referência a um objeto CommandWords Pode ser adicionado Diagrama de classe refletiria isso (Game teria relação com CommandWords) Setas no diagrama de classe são uma primeira boa indicação do quanto um programa é fortemente acoplado. Mais setas, mais acoplamento Bons projetos Diagramas com poucas setas

48 Acoplamento Implícito
Game não ter referência a CommandWords é uma boa coisa Isso não deve ser alterado Ponto de vista de Game CommandWords é detalhe de implementação do Parser Parser Retorna comandos Decisão de usar um CommandWords para isso ou outra coisa é detalhe de implementação

49 Acoplamento Implícito
Projeto Aprimorado Adicionar em Game parser.showCommands() showCommands() em Parse Delega responsabilidade ao objeto CommandWords

50 Pensando a frente Projeto atual é bem melhor que o original
Contudo é possível aperfeiçoa-lo ainda mais Característica de um bom projetista Capacidade de pensar a frente O que pode ser mudado? O que permanecera inalterado durante toda a vida do programa?

51 Pensando a frente Assumiu-se que o jogo será baseado em texto e um terminal de entrada e saída Mas isso será sempre assim? Seria uma extensão interessante, a adição de uma GUI com menus, botões e imagens. Nesse caso, nao imprimiria-se as informações no terminal O metodo showAll () por exemplo, imprime as informações no console. Seria mais interessante deixar a classe CommandWords produzir a saída, porém a classe Game deve decidir como ela será apresentada ao usuário.

52 Pensando a frente Observe que tais alterações não trás nenhum benefício agora, porém tal projeto aperfeiçoado pode trazer grandes benefícios no futuro.

53 Coesão Uma unidade de código deve ser sempre responsável por uma e somente uma tarefa. Princípio aplicado : Classes Métodos

54 Coesão de métodos Qualquer método deve ser responsável por somente uma tarefa bem definida Exemplo de metodo coeso printWelcome() da classe Game Ponto de vista Funcional Todas as instruções que estão em printWelcome() poderiam ser colocadas diretamente no metodo play() de Game, evitando até uma chamada de método. Métodos coesos Fácil de entender Fazer modificações Métodos devem ser Razoavelmente curtos Seus nomes devem indicar claramente seus propósitos

55 Coesão de Classes A classe deve apresentar uma unica entidade bem definida no domínio do problema. Outra extensão no projeto Adição de itens ao jogo Cada sala pode conter um item Item Descrição Peso (Determina se ele pode ser carregado ou nao)

56 Coesão de Classes Abordagem simples Projeto Aprimorado
Adicionar dois campos a classe Room itemDescription itemWeight Tal abordagem não possui um bom grau de coesão Room descreve tanto uma sala quanto um item Outro problema e que isso vincula um item a uma sala, e isso pode não ser desejável Projeto Aprimorado Criar uma classe separada para item (Item). Descrição Peso Room manteria uma referência a um objeto da classe Item

57 Coesão de Classes Benefícios reais de separar itens de salas
Novos requisitos Numero ilimitados de itens por sala Com o projeto aprimorado isso e fácil Criar multiplos objetos Item e armazenar em uma Collection na classe Room Abordagem ingênua Tal alteração seria quase impossível

58 Coesão para legibilidade
Metodo printWelcome() Classe Item Se uma alteração de alguma característica dos itens do jogo for necessária, um programador de manutenção sabe facilmente em qual classe começar examinar o código

59 Coesão para reutilização
Segunda grande vantagem de coesão é um potencial mais alto para reutilização Por exemplo criando uma classe Item separada, pode-se criar múltiplos itens e assim utilizar o mesmo código de um único item. A reutilização é um aspecto importante de coesão de método

60 Refatorando Refatorando e testando

61 Resumo dos Conceitos Acoplamento
Descreve a interconectabilidade das classes. Objetivo Acoplamento fraco Cada classe e amplamente independente e comunica-se com outras classes por uma interface pequena e bem definida

62 Resumo dos Conceitos Coesão
Como uma unidade de código mapeia para uma tarefa lógica ou entidade. Objetivo Sistema altamente coeso Cada unidade de código é responsável por uma tarefa ou entidade bem definida.

63 Resumo dos Conceitos Duplicação de Código Sinal de projeto ruim.
Deve ser evitado.

64 Resumo dos Conceitos Coesão de Método
Responsável apenas por uma tarefa bem definida.

65 Resumo dos Conceitos Coesão de Classe
Representa uma entidade bem definida.

66 Resumo dos Conceitos Encapsulamento
Reduz o acoplamento e assim leva a um projeto aprimorado.

67 Resumo dos Conceitos Projeto baseado na responsabilidade
Processo de projetar classes atribuindo responsabilidades bem definidas a cada classe. Determina qual classe deve implementar qual parte de uma função da aplicação.

68 Resumo dos Conceitos Minimizar as alterações
Objetivos principais de um bom projeto Localizar a alteração Ao fazer alterações em uma classe, deve-se provocar o mínimo de efeitos em outras classes.

69 Resumo dos Conceitos Refatoração
Atividade de reestruturar um código existente para manter um bom projeto de classe quando a aplicação for modificada ou estendida.


Carregar ppt "Programação Orientada a Objetos"

Apresentações semelhantes


Anúncios Google