MAC 441/5714 - Programação Orientada
a Objetos
Aula 11 - 20/04/2004
Aumentando a Flexibilidade
- Na vida real, sistemas de software tendem a sobreviver
vários
anos.
- Mesmo sistemas desenvolvidos para ter vida curta, acabam vivendo
muito
mais tempo do que o esperado.
- No entanto,
- os requisitos tendem a variar ao longo da vida do sistema,
- os sistemas são estendidos de diferentes formas para
acrescentar
novas funcionalidades não antecipadas e
- partes de um sistema são utilizadas em outros sistemas
(reutilização).
- Portanto, os sistemas devem ter flexibilidade para que possam
ser
- adaptados a diferentes contextos e
- estendidos em diferentes direções.
- Mas é preciso cuidado. Lição de
Programação
eXtrema:
- Não antecipe necessidades, pois elas podem não
aparecer.
- Não incorpore flexibilidade desnecessária.
- Possível abordagem para enfrentar esta dicotomia:
- A arquitetura do sistema deve ser sempre o mais simples
possível.
- Less is more. Frase do famoso arquiteto
Mies van der Rohe
.
- Outra forma importante de incorporar flexibilidade sem aumentar a
complexidade:
- maximizar a coesão
- minimizar o acoplamento
Maximizando a Coesão
- Coesão é uma medida da diversidade dos
"tópicos"
abordados por uma entidade.
- Quanto menor a diversidade de assuntos abordados por uma
entidade,
maior a sua coesão.
- Uma entidade bem focada em um determinado aspecto do sistema,
é
uma entidade bem coesa.
- Sistemas onde os aspectos estão difusos são pouco
flexíveis
e dificultam extensões, modificações e
reutilizações.
- Cada classe deve ser o mais coesa quanto possível.
- Cada classe deve representar apenas uma abstração.
- Classes não coesas podem trazer, pelo menos, 3 problemas:
- a classe é mais difícil de entender
- está se supondo que as duas (ou mais)
abstrações
representadas pela classe tem sempre uma relação de 1 p/
1
entre si.
- pode ser necessário especializar a classe em
várias
dimensões baseadas nas várias abstrações
- Exemplo:
- Uma classe para uma conta bancária que inclui
informações
sobre o correntista (nome, endereço, etc.)
- Problema (2 acima): não permitirá contas
conjuntas,
se um correntista tem várias contas, os seus dados serão
duplicados
em cada conta o que gerará problemas de
atualização
e consistência.
- Probema (3): especialização na dimensão do
tipo
de conta (corrente, poupança) e no tipo de correntista (pessoa
física
ou jurídica).
- FIGURA
4.1 e
4.2
- Solução: aumentar a coesão criando
uma
classe separada para o correntista
- FIGURA
4.4
- Regrinhas simples para maximizar coesão:
- um atributo deve possuir um valor simples, não uma
estrutura
- um atributo deve descrever uma instância da classe (essa
regra
é violada pelo exemplo da figura
4.1)
- Outro exemplo:
- Representação de vôos e seus respectivos
aeroportos
- FIGURA
4.6
- Problema: se o vôo é repetido todos os dias,
estaremos
duplicando os objetos que representam o intinerário todos os
dias.
- Isso ocorre pois estamos representando tando o
intinerário
quanto uma instância do vôo na mesma classe.
- Solução: separar as duas abstrações
- FIGURA
4.7
- Flight Segment representa uma instância daquele vôo
em
um determinado dia, poderia incluir informações sobre a
tripulação,
por exemplo.
- Os designs mais coesos descritos acima eliminam a
redundância.
- Redundância desperdiça espaço e dificulta a
atualização
dos dados.
- Mas, muitas vezes, redundância pode melhorar o desempenho
do
sistema.
Minimizando o Acoplamento
- Acoplamento é
- O quão "amarrado" uma parte do sistema é
às
outras partes.
- O quão dependente uma parte do sistema é das
estruturas
internas das outras partes do sistema.
- Uma medida do quanto uma classe conhece do mundo à sua
volta.
- Se uma classe A conhece (e depende) da interface de uma classe B,
e
a interface da classe B é modificada, a classe A terá que
ser
modificada também.
- Minimizando o acoplamento entre as classes (e objetos) de um
sistema,
nós facilitamos as modificações no sistema.
- Há várias formas de acoplamento, entre elas:
- Acoplamento de Identidade
- se um objeto guarda uma referência para outro, ele
conhece
a idêntidade do outro e, portanto, está acoplado a ele.
- reduz-se acoplamento de identidade eliminando
associações
no diagrama de classes e implementando associações de
forma
uni-direcional.
- note que em linguagens dinâmicas (Smalltalk, Self,
Python, Lua) o acoplamento de identidade é mais leve do que em
linguagens fortemente tipadas (Java, C++, C#)
- Acoplamento de Representação
- ocorre quando um objeto referencia outro, i.e., acessa o outro
- quanto mais específico o acesso (e.g., mexer nas
variáveis
públicas do outro objeto) maior o acoplamento.
- usando um método "acessor" diminui um pouco o
acoplamento
(pois o método esconde a implementação do dado).
- Acoplamento de Subclasses
- quando um objeto acessa uma subclasse usando a interface da
subclasse
ao invés de usar a interface da superclasse.
- um cliente deve sempre usar uma referência para o tipo
mais
geral possível.
- exemplo: em Java usar InputStream ao invés de usar
FileInputStream.
- FIGURA
4.8
- FIGURA
4.9
- Uma regra fundamental relacionada a esta é que devemos
sempre programar para as interfaces e nunca para a
implementação
.
- Assim, nos diagramas UML, as classes deveriam, sempre que
possível,
usar as <<interface>>s e não outras
classes.
- Acoplamento de Herança
- Uma subclasse é acoplada à sua superclasse
através
de acoplamento de herança.
- É provavelmente o tipo de acoplamento mais forte.
- Se manifesta fortemente em tempo de compilação.
Mas
também em tempo de execução.
- O que uma classe herda em tempo de compilação
não
pode ser descartado em tempo de execução.
- Isso difere de agregação, quando um objeto pode
se
desfazer de seus agregados em tempo de execução.
- Exemplo: item de catálogo que é subclasse de
item
em estoque. E se a empresa decidir não guardar o item em estoque
e
encomendá-lo de terceiros toda vez que o item for encomendado?
- FIGURA
4.13
- FIGURA
4.14
Referência
Charles Richter. Designing Flexible Object-Oriented Systems with UML
. Capítulo 4: Flexibility Guidelines for Class Diagrams.
Macmillan
Technical Publishing, 1999.
Próxima Aula
Aula Anterior
Página de MAC 441/5714
Página do Fabio
Página do DCC