Escolar Documentos
Profissional Documentos
Cultura Documentos
Composicao de Software Orientado A Objetos
Composicao de Software Orientado A Objetos
Palestra I
1. Conceitos de Orientação a objetos
2. Herança
Palestra II
1. Sistemas de tipos
2. Metodologias de desenvolvimento de software
Palestra III
1. Determinando os requisitos
2. Analisando o problema
Palestra IV
1.Design da arquitetura
2.Escolhendo tecnologias
Palestra V
1.Desenhando o Subsistema
2.Design patterns overview
Palestra VI
1.Especificando as interfaces de classes overview
2.Teste contínuo
Palestra VII
Palestra VIII
Palestra IX
1.Introdução as interfaces
2.Contratos de interfaces
3.Ingredientes das interfaces
4.O que deve estar presente em uma interface
5.Herança e interfaces
6.Interfaces remotas
Palestra X
1.Interfaces e as metodologias de desenvolvimento
2.Interfaces no mundo real, estudo de casos
3.Interfaces e patterns
Palestra XI
1. Sobre patterns
2. The observer pattern
3. The decorator pattern
4. The factory pattern
5. The singleton pattern
6. The command pattern
Palestra XII
7. The adapter and facade patterns
8. The template method pattern
9. The iterator and composite patterns
Palestra XIII
10. The state pattern
11. The proxy pattern
Palestra XIV
12. Compound pattern
13. Vivendo melhor com patterns
14. Outros patterns
Palestra XV
Palestra XVI
Nota aos integrantes do grupo EvoFavo: Esse material deve abordar as questões
técnicas do projeto de software sendo que as questões de negócio devem ser abordadas
pelo gerente do projeto. Minha intenção não é precipitar o design e fazê-lo apenas
depois que a maioria estiver bastante a vontade com as principais idéias aqui
apresentadas. Não durmam ou converse nas palestras, nem finja que está entendendo,
caso algum tópico lhe pareça obscuro pergunte imediatamente, não percamos nosso
tempo. Lembrem-se que a primeira iteração não temos tempo marcado. Eu proponho
que após terminarmos a primeira iteração e termos uma noção mais sólida de projeto de
software que façamos várias atividades para verificar se todos dominam o básico de
cada área, garantindo assim que o pessoal está qualificado, antes de prosseguir.
Podemos a partir do resultado identificar áreas falhas e treinar o pessoal.
Alberto Paulo Rabelo Barcelos
Palestra I
Introdução
Nos dias atuais praticamente todos softwares são orientados a objetos. Mas nem
sempre se consegue com facilidade escrever na prática códigos orientados a objetos.
Tal atividade requer treinamento e reflexão.
Há muito mais atividades no desenvolvimento de software que escrever linhas de
código. Temos de fazer análise de negócios, requisitos do software, design da
arquitetura e o design de baixo nível, entre outras.
Portanto nada mais natural que basear o desenvolvimento em uma nova abstração
chamada objeto. Os objetos reduzem a quantidade de informação que deve ser
assimilada assim como garantem uma melhor comunicação entre os
desenvolvedores.
Tipos de Programação
Linguagem de máquina
Assembly e o uso do assembler
Linguagens de Alto Nível(Cobol, Fortran)
Programação estruturada
Programação orientada a objetos
Programação lógica
Programação funcional
Todos esses tipos de programação continuam existindo nos dias de hoje. Não
devemos encarar um estilo melhor que outro ou uma língua dentro de um tipo
melhor que outra, devemos sim analisar e escolher o tipo de programação e língua
de acordo com o problema que estamos resolvendo.
Exercício 1.2: Pesquise sobre o Assembly. Diga qual suas características e sua
aplicação. Verifique os deferentes tipos de Assembly e diga quais são mais usados.
Metodologia
Uma metodologia é uma descrição das etapas que devemos seguir para alcançar
um produto de alta qualidade.
Existem metodologias para os vários tipos de programação. As metodologias
predominantes nos padrões inustriais atuais são RUP e uma que vem ganhando
espaço, o XP.
A maioria dessa metodologias possuem muitos detalhes e práticas recomendadas
que podem confundir um iniciante, por isso adotaremos nesse material aqui presente
uma metodologia simples, que permita a criatividade em cada etapa do
desenvolvimento, metodologia ripple.
Exercício 1.3: O que é RUP? Quais são suas características e quando deve ser
usado.
Exercício 1.4: O que é XP? Quais as vantagens dessa metodologia e porque ela vem
ganhando espaço?
Encapsulando objetos
Associação e agregação
Lembrem-se da diferença entre grafos e árvores. Uma agregação se parece mais com
uma árvore e uma associação com um grafo. Uma árvore é um caso especial de
grafo onde cada nó pode ter apenas um nó parente e vários nós filhos. Observe que a
agregação deve respeitar além dessa lei a dependência entre as classes.
Navegabilidade
Mensagens
Há casos em que vale a pena termos uma mensagem dos dois tipos
É valido um objeto peguntar a si mesmo. Assim como fazemos perguntas a nós
mesmos como em “O que eu fiz ontem?”
Exemplo de Colaboração
Temos uma interação complicada entre dois tipos de objetos, programar já é
suficiente dificíl sem esse tipo de complexidade do mundo real. Temos um consumidor
que dependente da interface da balconista e um vendedor que depende da interface do
consumidor. Mudar um objeto significa mudar o outro também, um pesadelo para a
manutenção do código.
Constratemos a comunicação entre a balconista e o consumidor com a
comunicação entre um contador e a balconista. A balconista pode mandar uma
mensagem para o contador e esperar uma resposta mas o contador não pode perguntar
nada a balconista. Assim a interação é de mão unica e os mesmos objetivos continuam
sendo atingidos. Chamamos essa interação de cliente-fornecedor. Porém nesse tipo de
interação temos mais chance de reusar o código e portanto chegamos a um resultado
orientado a objetos.
Encapsulando objetos
Devemos declarar um campo como privado toda vez que ele for útil apenas para a
classe em questão, da mesma forma para os métodos. Não use um método público
exceto se ele for responsável pelas mensagens do objeto ou se você tiver um bom
motivo para tal. Garantimos assim objetos encapsulados que operamos usando apenas
sua interface(métodos) e além disso garantimos a reusabilidade e a orientação a objetos.
Já que nenhum outro objeto pode alterar as varáveis do nosso objeto sem usar sua
interface e usando a interface(métodos) nosso código pode ser mais facilmente
estendido e facilitamos sua manutenção.
Elementos de Classe
Quando queremos que uma informação não seja vinculada especificadamente a um
objeto mas sim a classe podemos declarar uma variável ou método como estáticos. Em
java isso equivale a inserir a keyword static na declaração desse método ou variável.
Esses elementos são chamados de elementos da classe. Não é tão fácil quanto parece o
uso de elementos de classe pois algumas linguagens não trata uma classe como um
objeto puro, isso quer dizer que as classes não tem as mesmas características como
herança, mesmo linguagens que possuem essa característica ficam a merce de
complicações como metaclasses( C++). Portanto sempre antes de decidir que sobre a
utilidade de um elemento de classe pense nas seguintes alterntivas:
1. Procure ou introduza um novo tipo de objeto, fique atento para não criar
objetos sem sentidos só para evitar o uso elementos de classe. Por exemplo ao
invés de inserir um novo elemento de classe taxaDeInvestimento podemos criar
ou mesmo inserir esse campo numa classe chamada Banco e ainda ganhamos
com a extensão do sistema já que o sistema pode agora conter vários tipos
diferentes de bancos.
2. Use um singleton pattern. Singleton é um pattern que garante que podemos ter
apenas uma instância de uma classe, o singleton object.
Exemplo: A pergunta “Esse é um ano bissexto?” combina perfeitamente com
esse padrão já que precisamos apenas uma instância do calendário gregoriano.
Uma instância onde todos os objetos podem perguntar datas.
Terminologia
Usaremos apenas os termos sublinhados
Reusando Código
Tipos de reusabilidade:
Exemplo:
Observe a notação em UML para declarar um o tipos da variável e tipo dos
parametros e os valores de retorno dos métodos, usa-se os dois pontos “ : “.
Outro exemplo, suponha que queiramos modelar uma coleção. Coleções são
objetos que contem outros objetos.
Tipos:
Listas: Coleção de objetos que os mantém na ordem que foram inseridos
Bag: Não mantém os objetos na ordem.
LinkedList
ArrayList
Objetivo: Colocar todas essas classes como uma herança de Collection.
Quando estivermos montando uma hierarquia quanto mais perto da base
colocarmos uma mensagem melhor. Normalmente nós tendemos a primeiro buscar as
mensagens que um objeto deve ter depois seus atributos isso é natural já que as
mensagens são sua interface com o mundo externo
Esse tipo de problema sempre surge e temos que decidir entre espaço e tempo.
Nunca podemos escolher precipitadamente uma abordagem, pois nenhuma abordagem
sempre será útil em todos os casos. No nosso exemplo preferimos usar a abordagem
número 2.
As mensagens que não possuem o método implementado estão em itálico, são os
chamados métodos abstratos. Já aquelas que efetivamente possuem a implementação
são chamados métodos concretos. Em UML voce pode representar o método abstrato
usando o itálico ou a palavra {abstract} em frente ao método.
Classes abstratas
Classes abstratas são aquelas que possuem pelo menos um método abstrato, seja
ele introduzido pela própria classe ou herdado.
As mesmas notações UML valem para as mensagens e nome das classes.
Vantagens:
Permite modelagem muito mais rica e flexível, por exemplo nossa classe
List possuem as três mensagens independente se podemos ou não
implementar o método.
Permite maior compartilhamento de código
Exemplo: Considere uma fruta e sua casca. Caso queiramos descascar a fruta
sabemos que podemos fazê-lo com qualquer fruta mas não podemos descrever como
fazer isso pois para cada fruta teremos um processo diferente. Essa operação deve ser
abstrata e o conceito de fruta também o é.
Se tivéssemos que dizer a uma fruta para ela se descascar ? Como saberia como
executar a operação se não temos sua implementação para a fruta?
A maioria das linguagens orientadas a objetos evita isso impedindo o
programador de instanciar uma classe abstrata.
Isso é natural, se te desse dinheiro para ir ao mercado comprar uma fruta, você
me perguntaria qual fruta você deseja que eu compre? Porque você precisa de um
pedido concreto.
Quando você for montar uma hierarquia de classes deve ter em mente que a
maioria das super classes são abstratas. Isso decorre do fato que a herança é uma
generalização de baixo para cima:
Quando chegamos a superclasses devemos pensar que elas são abstratos exceto
se elas representarem conceitos concretos na etapa 1.
É tão natural que uma superclasse seja abstrata que Java e UML nos permite
marcar uma classe como abstrata mesmo se não tivermos nenhum método abstrato
ainda.
Portanto se você observar uma classe concreta herdando outra classe concreta
pense nas seguintes transformações.
1.
Imagine que X fosse fruta e Y uma laranja. Esperaríamos que uma laranja
trabalhasse exatamente como uma fruta, mas com informações extras e comportamento
extra.
Motivos para se redefinir métodos
1.Implementar um método abstrato
2.Estender as funcionalidades do método herdado
Implementando um Stack
Imagine uma pilha de pratos. Uma stack é uma estrutura de dados parecida,
podemos: adcionar um elemnto a pilha(push( ) ); retornar um objeto no topo da pilha
(peek ( ) ); retornar verdadeiro se a pilha estiver vazia ( isEmpty( ) ); remover um objeto
do topo da pilha ( pop( ) );
Como escrever software orientados a objetos envolve reusabilidade do código,
pensemos em como reaproveitar uma classe que já existe, nesse caso a classe
LinkedList, para aproveitarmos o código devemos ter uma herança ou uma composição.
Uma composição é uma agregação de objetos extremamente forte.
Agregação e composição
A associação tem duas formas particulares: a agregação e a composição. As
duas são muito parecidas, elas relacionam um objeto composto com suas partes. Por
exemplo, a associação entre uma universidade e seus departamentos é uma agregação, a
associação entre um carro e suas partes é uma composição. A diferença entre os dois é
que a composição é mais ``física'', com a composição, uma parte não pode pertencer a
dois objetos compostos ao mesmo tempo (um motor não pode pertencer a dois carros ao
mesmo tempo), e uma parte não pode existir sem o objeto composto (mas o composto
pode ``sobre-viver'' às suas partes).
Agregação e composicão aceitam multiplicidade, só do lado das partes para a
composição (um carro é composto de quatro rodas) e dos dois lados com a agregação
(uma palavra pode pertencer a várias frases e uma frase possui várias palavras).
Geralmente, a composição implica uma forma de propagação de algumas
propriedades. Por exemplo, quando o objeto composto morrer, as partes morrem
também (definição da composição), ou quando um carro se mover, as partes se movem
também. Essas propagação não é a herança, ela não é automática, você tem que
especificá-la e implementá-la. Todas as propriedades não são propagadas, por exemplo,
um carro pode ser vermelho e o motor não.
Herança versus Composição
Vantagens únicas da herança
Natural/Elegante/Permite escrever código genérico
Desvantagens da herança
Difícil fazer bem/Difícil mudar quando descobrimos deficiências em
nosso design/É mais difícil para programas clientes entenderem/ Mais difícil mudá-lo
também
Composição atinge os mesmo objetivos que a herança com as vantagens:
Simples de produzir/Fácil de mudar/ Fácil de entender para os clientes/ Não
deixa a desejar no código pelo lado do cliente.
Introdução as Interfaces
Adapter
Adapta uma interface de uma classe para atender as expectativas de um cliente
Facade
Fornece uma simples interface em um coleção de classes.
Composite
Define uma interface que se aplica a objetos individuais e grupos de objetos.
Bridge
Desacopla uma abstração de sua implementação assim elas podem variar
independentemente.
Introdução as interfaces
O que é?
Conjunto de campos e métodos que uma classe permite que a outra acesse. Em
Java esse conceito é elevado no sentido de se tornar uma construção separada entre
implementação e interface. Assim várias classes podem ser atreladas a mesma interface
ou uma classe pode implementar mais de uma interface.
Muitas vezes sua intenção no design vai além do simples conceito de interface.
Nesse contexto que surgem os padrões de interface. Eles estendem além o conceito de
interface para atingir objetivos do designer.
Exemplo:
interface Act {
void act();
}
Interfaces e obrigações
Todas as classes que implementarem a interface devem respeitar o nome do
método e os comentários sobre ele. Esses dois itens estabelecem o que chamamos de
contrato.
Algumas vezes os métodos da interface não exigem em seu contrato que sejam
implementados por todos objetos assim podemos deixar seu corpo vazio na classe que o
implemente. Ou seja, esse objeto não necessariamente reagira diante determinada
chamada de outro objeto. Essa técnica é usada quando desejamos registrar para obter
notificações, nesse caso o objeto deve tomar alguma atitude quando o método é
chamado mas geralmente não está oferecendo um serviço ao objeto que chamou o
método.
Exemplo: A classe que implemente MouseMotionListener interface de java.awt.event
deverá implementar os métodos mouseDragged(MouseEvent e) e
mouseMoved(MouseEvent e). A presença desses métodos não significa que o objeto
deve tomar uma atitude quando o método for chamado. De fato seria natural reagir a um
drag and drop e não a um movimento do mouse.
Se voce planeja criar uma interface que possua muitos métodos notificadores é
interessante que crie também um stub. Um stub é uma classe que implementa uma
interface com métodos que não fazem nada. A partir do stub podemos criar uma
hierarquia de classes, sobrescrevendo apenas os métodos da interface que sejam
importantes para a nossa aplicação.
Exemplo: WindowsApadter
Adapter
Como programador escrevemos nossas classes e nossas interfaces portanto nos
escrevemos os contratos aos quais nossas classes devem obdecer. Mas nem sempre voce
poderá fazer tal.
Quando voce precisa implementar uma interface voce verá que existirá uma
classe que fornece os serviços que o cliente precisa mas com nomes dos métodos
diferentes. Voce pode usar a classe existente para atingir as necessidades dos clientes
usando o Adapter pattern.
A intenção desse padrão é fornecer uma interface que um cliente espera usando
os serviços de uma classe que implementa outra interace.
Arquitetura de software
Definição
Exemplo de arquitetura
diagrama de componentes
usando UML 2.0