Вы находитесь на странице: 1из 110

1

LtIiJML Essencial

F787u Fowler, Martin


UML essencial: um breve guia para a linguagem
padrão de modelagem de objetos/Martin Fowler e
Kendal Scott; trad. Vera Pezerico e ChristianThomas
Price. -2. ed. - Porto Alegre: Bookman, 2000.
1. Computação - Programação de computador- UMI. 1. Scott, Kendal. fI.Título.
CDU 681 .3(UML)
Catalogação na publicação: Mônica Bailejo Canto - CRB 10/1023
ISBN 85-7307-729-8

MARTIN FOWLER
e KENDALL SCOTT
L Essencial Um breve guia para a linguagem-padrão
de modelagem de objetos
2’Edição
Tradução:
Vera Pezerico e Christian Thomas Price
Consultoria, Supervisão e Revisão Técnica desta edição:
Roberto Tom Price
Professor do Instituto de Informática da UFRGS
Reimpressão 2003
Li4
Boonan
Porto Alegre, 2000

Obra originalmente publicada sob o título


UML Distilled - A BriefGuide to the Standard Object
Modeling Language
© Addison Wesley Longman, mc., 2000
ISBN 0-201-65783-X
Publicado conforme acordo com Addison Wesley Longman, mc.
Capa:Mário Ri) hnelt
Preparação de originais: Luís Augusto Junges Lopes
Supervisão editorial: Arysinha Jacques Affonso
Editoração eletrônica: Liser House - in. q. o.f
ívcÂ
‘-, ‘.. ),..J
- . p,l
UN1VERSíAri £STÁCI• DI sA
11(3 TCAS
[_
_______-____ çj
Reservados todos os direitos de publicação, em língua portuguesa, à
ARTMED® EDITORA S.A.
(BOOKMAN® COMPANhIA EDITORA é uma divisão da ARTMED® EDITORA S.A.)
Av. Jerônimo de Ornelas, 670 - Santana
90040-340, Porto Alegre, RS
Fone (51) 3330-3444 Fax (51) 3330-2378
É proibida a duplicação ou reprodução deste volume, no todo ou em parte, sob
quaisquer formas ou por quaisquer meios (eletrônico, mecânico, gravação, fotocópia,
distribuição na Web e outros), sem permissão expressa da Editora.
SÃO PAULO
Av. Rebouças, 1073 - Jardins
0540 1-150, São Paulo, SP
Fone (11) 3062-3757 Fax (11) 3062-2487
SAC 0800 703-3444
IMPRESSO NO BRASIL
PRINTED IN BRAZIL

Apresentação
1 1’
Quando começamos a moldar UML. (Unified Modeling LaÃguage); perávamos poder
produzir um meio-padrão de expressar projetos que não somente refletisse as
melhores práticas da indústria, mas que também ajudass a desmistificar o processo
de modelagem de sistemas de software. Acreditávamos que a disponibilidade de
uma linguagem de modelagem-padrão encorajaria mais desenvolvedores a modelar
os seus sistemas de softzvare, antes de construí-los. A adoção rápida e muito
difundida de UML demonstra que os benefícios da modelagem são, de fato, bem
conhecidos da comunidade de desenvolvedores de software.
A criação de UML foi por si só um processo iterativo e incremental muito semelhante
à modelagem de um grande sistema de software. O resultado final é um padrão
baseado nas muitas idéias e contribuições feitas por diversas pessoas e empresas da
comunidade. Começamos o trabalho de UML mas muitos outros contribuíram para
uma conclusão de sucesso; somos muito gratos pelas suas contribuições.
Criar e entrar em acordo sobre uma linguagem de modelagem-padrão por si só já é
um grande desafio. Educar a comunidade de desenvolvedores, e para ela apresentar
UML de uma forma acessível e no contexto do processo de desenvolvimento de
software, também é um grande desafio. Neste livro aparentemente curto, atualizado
para refletir as mais recentes mudanças em UML, Martin Fowler superou, certamente,
este desafio.
Com um estilo claro e acessível, Martin não somente introduz aspectos-chave de
UML, mas também demonstra claramente o papel que UML desempenha no processo
de desenvolvimento. Ao longo da leitura, recebemos grandes doses de sabedoria e
conhecimento de modelagem decorrentes dos mais de 12 anos de experiência que o
autor acumulou em projeto e em modelagem. Como resultado,

APRESENTAÇÃO
temos um livro que apresenta a linguagem a milhares de desenvolvedores, aguçando
seus interesses para melhor explorar os vários benefícios da modelagem utilizando
UML, agora um padrão. Recomendamos o livro para qualquer modelador ou
desenvolvedor interessado em conhecê-la e em obter uma visão da função-chave
que ela desempenha no processo de desenvolvimento.
Grady Booch
Ivar Jacobson
Jarnes Rurnbaugh

Prefácio
Há dois anos, Addison-Wesley entrou em contato comigo para que eu escrevesse um
livro sobre a então nova UML. Naquela época, havia muito interesse em UML, mas
existiam apenas documentos de padronização para estudo. Quebramos muitos
recordes para produzir um curto guia introdutório da nova linguagem, algo que daria
uma certa orientação até que livros mais detalhados viessem a aparecer, mais tarde
naquele ano.
Não esperávamos que este livro permanecesse depois que textos detalhados fossem
publicados. Muitas pessoas acreditam que se tendo a escolha entre uma pequena
visão geral e um livro detalhado, todos escolherão o livro detalhado. Embora esta
fosse a visão geral, eu acreditava que mesmo na presença de livros detalhados havia
ainda espaço para um resumo conciso.
Dois anos mais tarde, as minhas esperanças foram além do esperado. O LJML
Essencial é, em termos da indústria da computação, um best-seller. Mesmo que bons
livros detalhados sobre UML tenham sido publicados, o livro ainda vende bem. Melhor
do que isto, mais livros curtos surgiram, confirmando a minha crença de que, em um
mundo com tanta informação, a brevidade bem escolhida tem o seu valor.
Tudo bem, mas você deve comprar este livro?
Eu vou partir do princípio que você já ouviu algo sobre UML, pois tornou-se o modo-
padrão para desenhar diagramas de projetos orientado a objetos, e também se
espalhou em campos não-orientados a objetos. Todos os maiores métodos pré-UML já
desapareceram. UML chegou e está aqui para ficar.
Se você quer aprender sobre UML, este livro pode ajudá-lo. A maior razão para você
começar com este livro é que ele é um livro pequeno. Comprar um livro grande pode
dar a você mais informação, mas você levará mais tempo para lê-lo. Selecionei as
partes mais importantes de UML para lhe poupar trabalho. Com

\v7 PREFÁCIO
este livro, você aprenderá os elementos-chave da notação bem como seus
significados. Se você quer ir mais além, pode passar para um livro mais detalhado
mais tarde.
Se você quer um tutorial mais detalhado sobre UML, sugiro Unzfled Modeling
Language LJser Guide (Booch, Rumbaugh e Jacobson, 1999). O tJser Guide cobre mais
terreno. Ele é bem escrito e organizado, de forma que explica como aplicar UML a
vários problemas de modelagem.
Tanto este livro como o LJser Guide partem do princípio de que você já conhece algo
sobre o desenvolvimento em 00. Muitas pessoas me disseram que este livro é uma
boa introdução a objetos, mas não o escrevi tendo isto em mente. Se você está
procurando por uma introdução a objetos com UML, você deveria também considerar
o livro de Craig Larman (Larman, 1998).
Embora o ponto principal desse livro seja UML, também acrescentei materiai que
complementa UML. UML é uma parte re1ativament pequena do que você precisa
saber para ter sucesso com objetos, e acredito que é importante salientar algumas
outras coisas.
o mais importante destas outras é o processo de softzvare. UML é projetada para ser
independente de processo. Você pode desenhar tudo o que quiser; o que UML faz é
dizer o que seus diagramas significam. Entretanto, os diagramas não têm muito
sentido sem um processo que lhes dê um contexto. Também acredito que o processo
é importante e que um bom processo não precisa ser complicado.
Por isso, descrevi um esboço de um leve processo de desenvolvimento de
software 00. Ele estabelece um contexto para as técnicas e o ajudará a melhor
utilizar objetos.
Os outros tópicos incluem padrões, refatoração, código de autoteste, projetos por
contrato e cartões CRC. Nenhum deles faz parte de UML, mas são técnicas
de grande valor que utilizo regularmente.
Estrutura do Livro
o Capítulo 1 analisa o que é UML, a história do seu desenvolvimento e as razões
pelas quais você pode querer usá-la.
O Capítulo 2 discute o processo de desenvolvimento orientado a objetos. Embora
UML seja independente de processo, acho difícil discutir técnicas de modelagem sem
falar onde elas se encaixam com o desenvolvimento orientado a objetos.
Dos Capítulos 3 ao 6, as três técnicas mais importantes de UML são discutidas: casos
de uso, diagramas de classes e modelos de interação. UML é um grande monstro,
mas você não precisa dele todo. Estas três técnicas são a essência do que quase
todo mundo precisa. Comece com estas e adicione as outras à medida que for
necessitando (observe que, devido aos diagramas de classes serem tão complicados,
coloquei as partes-chave dos diagramas de classes no Capítulo 4 e os conceitos
avançados no Capítulo 6).

PREFÁCIO
Dos capítulos 7 ao 10, as técnicas remanescentes são exploradas. Todas elas são
valiosas, mas nem todo o projeto precisa de todas as técnicas. Portanto, estes
capítulos fornecem informações suficientes sobre cada técnica se você precisar dela.
Para todas essas técnicas, descrevo a notação, explico o que ela significa, e dou
dicas de como utilizá-las. A minha filosofia é esclarecer o que UML diz, e ao mesmo
tempo dar a minha opinião de como melhor utilizá-la. Também acrescentei
referências a outros livros que fornecem mais detalhes.
O Capítulo 11 dá um pequeno exemplo para mostrar como UML se encaixa em
programação, utilizando Java (é claro).
A contracapa resume a notação de UML. Você pode considerar útil usá-la
como referência, enquanto estiver lendo os capítulos, pois você pode já verificar a
notação para vários conceitos de modelagem.
Se você achar este livro interessante, pode encontrar maiores informações
sobre o meu trabalho relacionado ao uso de UML, padrões e refatoração na minha
homepage (ver página xxi).
Mudanças da Segunda Edição
À medida que UML evoluía e eu recebia feedback sobre a primeira edição desse livro,
eu o atualizava continuamente. A reimpressão do livro ocorria a cada dois ou três
meses; sendo que cada impressão continha atualizações, o que significou um
desgaste considerável para os processos da indústria gráfica.
Com a mudança de UML 1.2 para 1.3, decidimos fazer uma revisão mais detalhada
do livro, o que era suficiente para produzir uma segunda edição. Uma vez que este
livro se tornou tão popular, tentei manter o espírito essencial dele. Tentei não
adicionar muito e verificar se haveria coisas que deveriam ser retiradas.
As maiores mudanças estão no Capítulo 3, sobre casos de uso, e no Capítulo 9 sobre
diagramas de atividade, os quais foram em grande parte reescritos. Também
adicionei uma seção sobre colaborações ao Capítulo 7. Em outras partes, aproveitei
para fazer algumas pequenas modificações baseadas emfeedback de leitores e nas
minhas experiências dos dois últimos anos.
Agradecimentos da Primeira Edição
Publicar um livro com essa rapidez exigiu muita ajuda de pessoas que se superaram
em seus esforços para fazer a produção de forma bem mais rápida.
Kendall Scot teve um papel importante coletando todo material e trabalhando com os
textos e os gráficos. A medida que eu revisava o livro, ele continuava para manter
tudo em ordem, completando uma série de tarefas que surgiam de uma hora para
outra e com prazos de entrega impossíveis de serem cumpridos.

PREFÁCIO
Os três amigos, Grady Booch, Ivar Jacobson e Jim Rumbaugh, deram muito
apoio e conselhos. Investimos muitas horas com ligações internacionais, que
aprimoraram muito o livro (bem como a minha compreensão de UML).
Um grande número de revisores é essencial para se fazer um bom trabalho na
elaboração de um livro. Esses revisores não apenas me deram ofeedback necessário
mas também retornaram seus comentários em menos de uma semana para que
pudéssemos cumprir o nosso curto prazo de entrega. Meus agradecimentos a: Simmi
Kochhar Bhargava, da Netscape Communications Corporation, Eric Evans e Tom
Hadfield, da Evolve Software, mc. , Ronald E. Jeffries e Joshua Kerievsky, da Industrial
Logic, mc. , Helen Klein, da University of Michigan, James Odeli e Vivek Salgar, da
Netscape Communications Corporation. E agradecimento dobrado a Tom Hadfield,
porque ele o fez duas vezes.
Quero agradecer a Jim Odeil por duas coisas: primeiro por coordenar o esforço do
Object Management Group (OMG) para obter um padrão único para UML, o que será
um grande progresso para nossa indústria; segundo por me encorajar a entrar no
campo de análise e projeto 00.
Ah, e obrigado por revisar este livro também!
Obrigado a Cindy por ter suportado minha ausência, mesmo eu estando em
casa.
Não posso imaginar as dificuldades que o meu editor, J. Carter Shanklin e sua
assistente Angela Buenning, tiveram que enfrentar para publicar este livro tão
rapidamente. Quaisquer que tenham sido estas dificuldades, tenho certeza que
Carter e Angela merecem meus agradecimentos. A indústria editorial não é projetada
para lidar com mudanças feitas em um livro a cada dois meses, mas Carter e sua
equipe fizeram um bom trabalho escondendo este fato!
A necessidade de manter este livro atualizado me fez questionar sobre detalhes
específicos de UML. Conrad Bock, Ivar Jacobson, Cris Kobrym, Jim Odeil, Guss
Ramackers e Jim Rumbaugh fizeram o possível para me ajudar a encontrar estas
respostas.
Inúmeras pessoas me mandaram mensagens salientando vários erros e omissões;
são muitos nomes para listar aqui, mas agradeço a todos vocês.
Por fim, agradeço aos meus pais por terem me dado uma boa educação da
qual tudo mais se originou.
Martin Fowler
Melrose, Massachusetts
Fowler@acm.org
http://ourworld.compuserve.com/homepages/Martin_Fozvler

-.
1.
Sumário
Capítulo 1: Introdução 19
OqueéUML’ 19
Como Chegamos até Aqui 20
Notações e Metamodelos 22
Por que Fazer Análise e Projeto7 23
Comunicação 24
Aprendendo 00 24
Comunicação com Especialistas de Domínio 26
Procurando Mais Informação 26
Capítulo 2: Um Esboço de Processo de Desenvolvimento 29
Visão Geral do Processo 30
Concepção 31
Elaboração 31
Lidando com Riscos de Requisitos 32
Lidando com Riscos Tecnológicos 35
Lidando com Riscos de Especialização 36
Lidando com Riscos Políticos 38
Quando Termina a Elaboração’ 38
Planejando a Fase de Construção 38
Construção 40
Box: Software de Autoteste 41
Quando o Plano se Desintegra 41
Box: Refatoração 41
Utilizando UML na Construção 43
Transição 44
Box: Padrões 44

Quando Usar Desenvolvimento Iterativo 47


Onde Encontrar Mais Informação 48
Capítulo 3: Casos de Uso 49
Diagramas de Caso de Uso 51
Atores 52
Associação entre Casos de Uso 53
Casos de Uso do Negócio e Casos de Uso do Sistema 54
Quando Utilizar Casos de Uso 55
Onde Encontrar Mais Informação 56
Capítulo 4: Diagramas de Classes: Os Elementos Básicos 57
Perspectivas 59
Associações 60
Atributos 64
Operações 64
Generalização 66
Regras de Restrição 67
Box: Projeto por Contrato 67
Quando Utilizar Diagramas de Classes 69
Onde Encontrar Mais Informação 70
Capítulo 5: Diagramas de Interação 71
Diagramas de Seqüência 72
Diagramas de Colaboração 76
Comparando Diagramas de Seqüência
com Diagramas de Colaboração 77
Box: Cartões CRC 78
Quando Utilizar Diagramas de Interação 80
Capítulo 6: Diagramas de Classes: Conceitos Avançados 81
Estereótipos 81
Diagrama de Objetos 82
Operações e Atributos com Escopo de Classe 83
Classificação Múltipla e Dinâmica 84
Agregação e Composição 86
Associações e Atributos Derivados 87
Interfaces e Classes Abstratas 89
Objetos de Referência e Objetos de Valor 92
Coleções para Pontas de Associações de Valores Múltiplos 93
Frozen 93
Classificação e Generalização 94
Associações Qualificadas 94
Classes de Associação 96
Classe Parametrizada 98
Visibilidade 100
Capítulo 7: Pacotes e Colaborações 103
Pacotes 103

\i37
Colaborações 108
Quando Utilizar Diagramas de Pacotes e Colaborações 111
Onde Encontrar Mais Informação 111
Capítulo 8: Diagramas de Estados 113
Diagramas de Estados Concorrentes 117
Quando Utilizar Diagramas de Estados 119
Onde Encontrar Mais Informação 119
Capítulo 9: Diagramas de Atividades 121
Decompondo uma Atividade 125
Concorrência Dinâmica 125
Raias (Swimlanes) 125
Quando Utilizar Diagramas de Atividades 127
Onde Encontrar Mais Informação 129
Capítulo 10: Diagramas Físicos 131
Diagramas de Utilização 131
Diagramas de Componentes 131
Combinando Componentes com Diagramas de Utilização 133
Quando Utilizar Diagramas Físicos 134
Capítulo 11: UML e Programação 135
Observação de Pacientes: Modelo de Domínio 136
Observação de Pacientes: Modelo de Especificação 139
Passando para Código 142
Apêndice A: Técnicas e Suas Aplicações 151
Apêndice B: Mudanças entre Versões de UML 153
Revisões de UML 153
Cronograma de Revisões Futuras 154
Mudanças em “UML Essencial” 155
Mudanças de UML 1.0 para 1.1 155
Tipo e Classe de Implementação 155
Restrições Discriminadoras Completas e Incompletas 156
Composição 156
Imutabilidade e Congelamento 156
Retornos em Diagramas de Seqüência 157
Uso do Termo “Papel” (Role) 157
Mudanças de UML 1.2 (e 1.1) para 1.3 (e 1.4) 157
Casos de Uso 157
Diagramas de Atividades 158
Bibliografia 159
Índice 163

Figuras
Figura 1.1: Trecho do Metamodelo de UML 23
Figura 2.1: Esboço do Processo de Desenvolvimento 30
Figura 2.2: Estrutura do Padrão de Projeto Proxy 45
Figura 2.3: Padrão de Análise Cenário 46
Figura 3.1: Exemplo de Texto de Caso de Uso 50
Figura 3.2: Diagramas de Casos de Uso 51
Figura 3.3: Associação de Extensão 54
Figura 4.1: Diagrama de Classes 58
Figura 4.2: Diagrama de Classes com Navegabilidades 63
Figura 5.1: Diagrama de Seqüência 72
Figura 5.2: Processos Concorrentes e Ativações 74
Figura 5.3: Diagrama de Seqüência: Verificação de Falha 75
Figura 5.4: Diagrama de Colaboração com Numeração Simples 76
Figura 5.5: Diagrama de Colaboração com Numeração Decimal 77
Figura 5.6: Cartão Classe-Responsabilidade-Colaboração (CRC) 79
Figura 6.1: Diagrama de Classes da Estrutura
de Composição de Grupo 82
Figura 6.2: Diagrama de Objetos Mostrando Exemplo
de Instâncias de Grupo 83
Figura 6.3: Notação de Escopo de Classe 83
Figura 6.4: Classificação Múltipla 84
Figura 6.5: Classificação Dinâmica 85

Figura 6.6: Agregação e Composição 86


Figura 6.7: Notação Alternativa para Composição 87
Figura 6.8: Associações e Atributos Associados 88
Figura 6.9: Classe Período de Tempo 89
Figura 6.10: Janela como Classe Abstrata 90
Figura 6.11: Interfaces e Classes Abstratas: Um Exemplo
dejava 91
Figura 6.12: Notação Pirulito para Interfaces 91
Figura 6.13: Associação Qualificada 95
Figura 6.14: Classe de Associação 96
Figura 6.15: Promovendo uma Classe de Associação
para uma Classe Plena 96
Figura 6.16: Sutilezas de Classes de Associação 97
Figura 6.17: Estereótipo História para Associações 98
Figura 6.18: Classe Parametrizada 99
Figura 6.19: Elemento de Amarração (Versão 1) 99
Figura 6.20: Elemento de Amarração (Versão 2) 100
Figura 7.1: Diagrama de Pacotes 104
Figura 7.2: Diagrama de Pacotes Avançado 106
Figura 7.3: Diagrama de Seqüência para Registrar uma Venda 108
Figura 7.4: Diagrama de Classes para Colaboração
Registrar uma Venda 109
Figura 7.5: Colaboração Parametrizada para Venda 110
Figura 7.6: Utilizando a Colaboração de Venda 110
Figura 8.1: Diagrama de Estados 114
Figura 8.2: Diagrama de Estados sem Superestados 115
Figura 8.3: Diagrama de Estados com Superestados 116
Figura 8.4: Autorização de Pagamento 117
Figura 8.5: Diagrama de Estados Concorrentes 118
Figura 9.1: Diagrama de Atividades 122
Figura 9.2: Separações, Junções e Threads Condicionais 124
Figura 9.3: Utilizando uma Atividade Composta
para a Entrega 126
Figura 9.4: Concorrência Dinâmica 127
Figura 9.5: Raias 128
Figura 10.1: Diagrama de Utilização 132
Figura 11.1: Modelo de Domínio de Observação
de Pacientes 136
Figura 11.2: Diagrama de Objetos de Observação
de Pacientes 137
Figura 11.3: Outro Diagrama de Objetos
de Observação de Pacientes 138

Figura 11.4: Modelo de Especificação de Observação


de Pacientes 140
Figura 11.5: Operações de Observação de Pacientes 141
Figura 11.6: Diagrama de Seqüência de Observação
de Pacientes 142
Figura 11.7: Outro Modelo de Especificação de
Observação de Pacientes 148

1
Introdução
O Que é UML?
UML (Unified Modeling Language) é a sucessora da onda de métodos de análise e
projeto orientado a objetos (OOA & D) que surgiu no final dos anos oitenta e no início
dos anos noventa. Mais especificamente, ela unifica os métodos de Booch,
Rumbaugh (OMT) e Jacobson, mas o seu alcance é bem maior. UML passou por um
processo de padronização pela OMG (Object Management Group) e é agora um
padrão OMG.
UML é chamada de linguagem de modelagem; não é um método. A maioria dos
métodos consiste, pelo menos em princípio, de uma linguagem de modelagem e de
um processo. A linguagem de modelagem é a notação (principalmente gráfica)
utilizada por métodos para expressar projetos. O processo é a sugestão de quais
passos a serem seguidos na elaboração de um projeto.
A descrição dos processos em muitos livros de metodologias é um pouco incompleta.
Alem disso, acredito que a maioria das pessoas quando diz que está utilizando um
método usa a linguagem de modelagem, mas raramente segue o processo. Portanto,
em vários aspectos, a linguagem de modelagem é a parte mais importante do
método. Ela é certamente a parte-chave para a comunicação. Se você quer discutir o
seu projeto com alguém, vocês têm que compreender a linguagem de modelagem,
nao o processo que vocês utilizaram para desenvolver o projeto.
Os três amigos também desenvolveram um processo unificado, que eles chamam
RUP (Rational Unified Process). Você não precisa utilizar RUP para usar UML - eles são
distintamente separados. Entretanto, neste livro, abordo um pouco do processo, de
modo a colocar as técnicas de linguagem de modelagem em contexto. Nesta
discussão, uso os passos elementares e os termos da RUP, mas o texto nao é a
descrição de RUP. Utilizo muitos processos diferentes, dependendo

INTRODUÇÃO
do meu cliente e do tipo de software que estou construindo. Embora acredite que
uma linguagem de modelagem-padrão é valiosa, não vejo a mesma necessidade
para o processo-padrão: ainda que alguma harmonização de vocabulário poderia ser
útil.
Como Chegamos Até Aqui
Na década de oitenta, os objetos começaram a sair dos laboratórios de pesquisa e a
dar seus primeiros passos em direção ao mundo “real”. Smaiitaik estabilizou uma
plataforma que as pessoas pudessem usar, e C++ surgiu.
Como muitos desenvolvimentos em softzvare, objetos foram guiados por linguagens
de programação. Muitas pessoas se perguntavam como métodos de projeto se
encaixariam em um mundo orientado a objetos. Métodos de projeto tornaram-se
muito populares em desenvolvimentos industriais nas décadas de setenta e oitenta.
Muitos acreditavam que técnicas para auxiliar as pessoas a fazerem uma boa análise
e projeto eram também muito importantes para desenvolvimento orientado a
objetos.
Os livros essenciais sobre métodos de análise e projeto orientado a objetos
surgiram entre 1988 e 1992:
• Sally Shlaer e Steve Mellor escreveram dois livros (1989 e 1991) sobre análise e
projeto; o material desses livros gerou o seu enfoque de projeto
Recursivo (1997).
• Peter Coad e Ed Yourdon também escreveram livros que estenderam a leve
introdução de Coad orientada a protótipos para métodos. Veja Coad
e Yourdon (1991 a e 1991 b), Coad e Nicola (1993), e Coad et ai. (1995).
• Da comunidade de Smalltalk em Portland, Oregon, sugeriu CRD (Responsibility-
Driven Design) (Wirfs - Brock et ai. 1990) e cartões CRC
(Class-Responsibility-Collaboration) (Beck e Cunningham, 1989).
• Grady Booch fez muitos trabalhos para Rational Software desenvolvendo sistemas
com Ada. Seus livros apresentam vários exemplos (e os melhores cartoons no mundo
de livros de métodos). Veja Booch (1994 e 1996).
• um Rumbaugh liderou uma equipe nos laboratórios de pesquisa da General Electric,
que produziu um livro muito popular do método chamado de OMT (Object Modeling
Technique) veja Rumbaugh et ai. (1991) e Rumbaugh (1996).
• Jim OdelI baseou seus livros (escritos com James Martin) na sua longa experiência
com sistemas de informação comerciais e Engenharia da Informação. O resultado foi
o livro mais conceitual entre estes. Veja Martin e Odell (1994).
• Ivar Jacobson escreveu seus livros sobre suas experiências com sistemas de
chaveamento de telefones para Ericsson e introduziu o conceito de
casos de uso no seu primeiro livro. Veja Jacobson (1992 e 1995).
Quando me preparava para viajar para Portland para a conferência OOPSLA em 1994,
o mercado de métodos estava bastante dividido e competitivo. Cada um dos autores
mencionados acima estava, então, liderando informalmente um gru

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM-PADRÃO DE MODELAGEM DE


OBJETOS “ 21
po de praticantes que gostavam de suas idéias. Todos esses métodos são muito
semelhantes, mas eles contêm um número inoportuno de pequenas diferenças entre
eles. Os mesmos conceitos básicos apareceram em diferentes notações, o que
causava confusão para os meus clientes.
Conversas sobre padronização emergiram, mas ninguém se mostrou interessado em
fazer algo a este respeito. Alguns eram contra a idéia de padrões para metodologias.
Outros gostavam da idéia mas não se mostravam interessados em trabalhar com
isso. Uma equipe da OMG tentou analisar uma padronização, mas recebeu uma carta
aberta de protesto de todos os metodologistas-chave. Grady Booch tentou uma
aproximação informal em um café da manhã, mas também não teve sucesso. (Isso
me lembra uma velha piada. Qual é a diferença entre um metodologista e um
terrorista? Resposta: Você pode negociar com um terrorista).
Para a comunidade de metodologias 00, a grande novidade na conferência
OOPSLA 94 foi que Jim Rumbaugh havia deixado a General Electric e se unido a
Grady Brooch na Rational Software, com a intenção de unir seus métodos.
O ano seguinte foi cheio de divertimentos.
Grady e Jim proclamaram que “a guerra de métodos acabou - nós vencemos”,
declarando basicamente que eles iriam alcançar a padronização do modo Microsoft.
Um número de outros metodologistas sugeriu criar uma Coligação AntiBooch.
Para conferência de OOPSLA 95, Grady e Jim haviam preparado a sua primeira
descrição pública de seu método unificado: versão 0.8 da documentação do Método
Unificado. Mais importante ainda, eles anunciaram que a Rational Software comprara
Objectory, e que o Ivar Jacobson iria unir-se à equipe. A Rational fez uma festa para
comemorar o lançamento do rascunho 0.8, a qual foi muito concorrida. A festa
também foi muito divertida, apesar das cantorias de Jim Rumbaugh.
Durante 1996 Grady, Jim e Ivar, agora amplamente conhecidos como os três amigos,
trabalharam o seu método sob o novo nome: UML (Unified Modeling Language).
Entretanto, os outros grandes jogadores na comunidade de metodologia orientada a
objetos não estavam inclinados a deixar que UML fosse a última palavra.
Uma força de trabalho OMG foi formada para fazer a padronização na área de
metodologias. Isso representou uma tentativa mais séria para dirigir os assuntos do
que os esforços anteriores da OMG na área de metodologias. Mary Loomis assumiu a
liderança; mais tarde, Jim Odell uniu-se como co-líder e assumiu, então, a liderança
do trabalho. Odell deixou claro que estava preparado para desistir da sua
metodologia em favor de um padrão, mas ele não queria um padrão imposto pela
Rational.
Em janeiro de 1997, várias organizações submeteram propostas para um padrão de
metodologias a fim de facilitar a troca de modelos. Essas propostas focavam um
metamodelo e uma notação opcional. ARational lançou a versão 1.0 da
documentação UML como sua proposta para a OMG.
Seguiu-se, então, um pequeno período de quebra de braço, enquanto várias
propostas eram unificadas. A OMG adotou a 1.1 resultante como um padrão oficial da
OMG. Desde então, a RTF (Revision Task Force), dirigida por Cris Kobryn, fez algumas
revisões incrementais. Aversão 1.2 foi somente para melhorar as aparências, mas a
versão 1.3 tornada pública no início de 1999 foi mais significativa.

22 r INTRODUÇÃO
Notações_e Metamodelos
No seu estado atual, UML define uma notação e um metamodelo.
A notação é a coisa gráfica que você vê nos modelos; ela é a sintaxe da linguagem
de modelagem. Por exemplo, a notação de diagrama de classes define
como itens e conceitos são representados: classe, associação e multiplicidade.
Certamente, isso leva a questão do que queremos dizer exatamente com uma
associação ou multiplicidade ou mesmo uma classe. O uso comum sugere algumas
definições informais, mas algumas pessoas querem mais rigor.
A idéia de linguagem de especificação e projeto mais rigorosa prevalece mais no
campo de métodos formais. Em tais técnicas, projetos e especificações são
representados usando alguns derivativos de cálculos predicativos. Tais definições são
matematicamente rigorosas, não permitindo ambigüidade. Entretanto, o valor dessas
definições não é de forma alguma universal. Mesmo que você possa provar que um
programa satisfaz uma especificação matemática, não há maneira de provar que a
especificação matemática atinja realmente os requisitos reais do sistema.
Projetar envolve a observação de assuntos-chave no desenvolvimento. Métodos
formais freqüentemente levam a paralisação, com tantos detalhes menores Além
disso, métodos formais são difíceis de entender e manipular, freqüentemente mais
difíceis de lidar do que linguagens de programação. E você nem mesmo pode
executá-los.
A maioria das metodologias 00 tem pouco rigor; suas notações apelam para intuição
em vez de definição formal. Em geral, isso parece não ter causado muito estrago.
Estas metodologias podem ser informais, mas muitas pessoas as consideram muito
úteis - e é a utilidade que interessa.
No entanto, as pessoas que trabalham com metodologias 00 estão procurando
maneiras para melhorar o rigor das metodologias, sem sacrificar as suas utilidades.
Uma maneira de fazer isso é definir um metamodelo: um diagrama, geralmente um
diagrama de classes, que define a notação.
A Figura 1-1 é uma pequena parte de um metamodelo UML que mostra a relação
entre associações e generalização. (Este trecho aparece somente para dar uma idéia
do que são os metamodelos. Não vou nem tentar explicá-lo).
Quanto o metamodelo afeta o usuário da notação de modelagem? Bem, ele ajuda a
definir o que é um modelo bem formado - isto é, um modelo sintaticamente correto.
Como tal, um usuário em potencial de uma metodologia deve compreender o
metamodelo. Entretanto, a maioria dos usuários de metodologias não necessita de
tal compreensão para obter algum valor na utilização da notação UML.
Não sou muito rigoroso nesse livro; ao contrário, sigo o caminho das metodologias
tradicionais e apelo para a intuição do leitor. Se você quiser um maior rigor, você
deve ler com atenção o manual de referência ou a documentação oficial de UML.
Quão exigente você deve ser em relação à adesão à linguagem de modelagem? Isso
depende da razão pela qual a está utilizando. Se você tem uma ferramenta CASE que
gera código, deve aderir a interpretação da linguagem de modelagem da ferramenta
CASE para obter código aceitável. Se estiver usando os diagramas para fins de
comunicação, você tem um pouco mais de liberdade.

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM-PADRÃO DE MODELAGEM DE


OBJETOS
e voce se afastar da notação oficial, outros desenvolvedores não compreenderão
exatamente o que você está dizendo. Contudo, há vezes em que a notação oficial
pode se atravessar no caminho das suas necessidades. Devo admitir que nesses
casos não hesito em torcer a linguagem. Acredito que a linguagem deve ser
flexionada para ajudar a me comunicar, em vez do contrário. Mas não faço isso com
muita freqüência, e sou ciente de que uma flexão é uma coisa errada, pois ela causa
problemas de comunicação. Neste livro, menciono aquelas ocasiões em que me acho
inclinado a flexionar um pouco a linguagem.

Por que Fazer Análise e Projeto?

O ponto real do desenvolvimento de software é o código executável. Os diagramas


são, na verdade, apenas figuras bonitas. Nenhum usuário irá lhe agradecer pelas
suas bonitas figuras; o que o usuário quer é um software que execute.
Então, quando você estiver pensando em utilizar UML é importante que se pergunte
por que está fazendo isso e como isso irá ajudá-lo a escrever código. Não existe uma
evidência empírica real para provar se estas técnicas são boas ou más, mas as
subseções seguintes discutem as razões que encontro, freqüentemente, para utilizá-
las.
Nesta seção, abordo um pouco as técnicas que discutirei mais tarde. Se você
considera que essas referências para adiante são confusas, pule essa seção e volte
a ela mais tarde.

Figura 1-1: Trecho do Metamodelo de UML

24 ‘ INTRODUÇÃO
y
Comunicaçao
A razão fundamental para usar UML envolve comunicação. Uso UML porque ela
permite comunicar certos conceitos mais claramente do que as linguagens
alternativas. A linguagem natural é muito imprecisa e ela se complica quando se
trata de conceitos mais complexos. O código é preciso, mas muito detalhado. Então,
utilizo UML quando quero uma certa precisão, mas não quero me perder em
detalhes. Isso não significa evitar detalhes, ao contrário, utilizo UML para salientar
detalhes importantes.
Como consultor, em um projeto complexo, tenho, freqüentemente, que dar uma
olhada rápida e parecer inteligente em um curto período de tempo. Neste caso,
considero UML inestimável porque ela me ajuda a obter uma visão geral do sistema.
Uma análise do diagrama de classes pode rapidamente me dizer que tipos de
abstrações estão presentes no sistema e onde estão as partes questionáveis que
precisam ser mais bem trabalhadas. A medida que examino mais profundamente,
quero ver como as classes colaboram, então peço para ver os diagramas de
interação que ilustram comportamentos-chave do sistema.
Se isso é útil para mim como um estranho, tem a mesma utilidade para a equipe
permanente do projeto. É fácil de esquecer detalhes em um grande projeto. Com
uma pequena escolha de diagramas disponíveis, você pode achar o seu caminho no
software com muito mais facilidade.
Para construir um mapa de um grande sistema, use diagramas de pacotes (veja
Capítulo 7) que mostram as principais partes do sistema e suas interdependências.
Para cada pacote, você pode, então, desenhar um diagrama de classes. Quando você
desenha um diagrama de classes neste contexto, assuma uma perspectiva de
especificação. E importante esconder implementações neste tipo de trabalho. Você
deve também desenhar diagramas de interação para as interações-chaves do
pacote.
Use padrões (veja página 44) para descrever as idéias importantes do sistema que
aparecem em múltiplos lugares. Padrões ajudam a explicar por que o seu projeto se
apresenta da maneira como é. Também é útil descrever alternativas de projetos que
você rejeitou e porquê. Sempre acabo esquecendo por que este tipo de decisão foi
tomada.
Ao seguir estas orientações, você obtém resultados mais rapidamente. Uma parte
importante da comunicação está em salientar as coisas importantes a serem ditas.
Você não precisa mostrar cada característica de cada classe; você deve, ao contrário,
mostrar os detalhes importantes. Um documento breve comunica muito melhor que
um longo; a arte está em saber o que deixar de fora.
Aprendendo 00
Muitas pessoas falam da curva de aprendizado associada com 00 - a maldita troca de
paradigma. Em alguns aspectos, a mudança para 00 é fácil. Em outros aspectos, há
um número de obstáculos em relação ao trabalho com objetos, particularmente a sua
utilização da melhor maneira possível.

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM-PADRÃO DE MODELAGEM DE


OBJETOS

Não é o caso se é difícil aprender como programar uma linguagem 00. O problema é
que leva tempo para aprender a explorar as vantagens que as linguagens orientadas
a objetos fornecem. Tom Hadfield diz bem: Linguagens de Objeto permitem
vantagem , não as fornecem. Para utilizar estas vantagens, você tem que fazer a
maldita troca de paradigma. (Assegure-se de estar sentado nesta hora!)
As técnicas de UML foram até certo ponto projetadas para ajudar as pessoas
a fazer boa 00, mas técnicas diferentes têm vantagens diferentes.

Uma das técnicas mais valiosas para o aprendizado de 00 são os cartões CRC (veja
página 78), que não são parte da UML, embora eles possam e devam ser usados com
ela. Eles foram projetados primeiramente para ensinar as pessoas como trabalhar
com objetos. Como tal, os cartões CRC são deliberadamente diferentes das técnicas
de projeto tradicionais. Suas ênfases nas responsabilidades e suas ausências de
notações complexas tornam os cartões CRC particularmente valiosos.
Diagramas de interação (veja Capítulo 5) são muito úteis porque eles tornam a
estrutura da mensagem bastante explícita e, portanto, são úteis para salientar
projetos muito centralizados, nos quais um objeto faz todo trabalho.
Diagramas de classes (veja Capítulos 4 e 6), usados para ilustrar modelos de classe,
são bons e ruins para o aprendizado de objetos. Modelos de classe são bastante
semelhantes a modelos de dados; muitos dos princípios que fazem um bom modelo
de dados também fazem um bom modelo de classe. O maior problema na utilização
de diagrama de classes é que é fácil desenvolver um modelo de classe que seja
orientado a dados, em vez de ser orientado à responsabilidade.
o conceito de padrões (veja página 44) tornou-se vital para o aprendizado de 00
porque a utilização de padrões faz com que você se concentre em bons projetos 00 e
aprenda seguindo um exemplo. Uma vez que você tiver aprendido técnicas de
modelagem básicas, tais como simples diagrama de classes e diagramas de
interação, está na hora de começar a
observar os padrões.
• Outra técnica importante é o desenvolvimento iterativo (veja Capítulo 2). Esta
técnica não o ajuda a aprender 00 diretamente, mas ela é a chave
para uma exploração efetiva da 00. Se você faz desenvolvimento iterativo desde o
começo, você aprenderá, no contexto, o tipo certo de processo e começará a ver
porque os projetistas sugerem que as coisas sejam feitas do modo como eles o
fazem.

Quando você começa a utilizar uma técnica, tende a fazê-lo seguindo pelo livro.
Minha recomendação é começar com as notações simples as quais abordo aqui,
particularmente com diagrama de classes. À medida que se sente familiarizado, você
pode utilizar idéias mais avançadas de acordo com as suas necessidades. Você
também pode achar que quer estender a metodologia.

INTRODUÇÃO
Comunicação com Especialistas de Domínio
Um dos maiores desafios no desenvolvimento é o da construçãq do sistema certo
- um sistema que preencha as necessidades dos usuários a um preço razoável. Isso
se torna mais difícil porque, com o nosso jargão, temos que nos comunicar com
nossos usuários que têm o seu próprio, e ainda mais secreto, jargão. (Fiz muito
trabalho na área de saúde, e nesta área o jargão nem mesmo é em inglês!). Atingir
boa comunicação, com boa compreensão do mundo dos usuários, é a chave para
desenvolver um bom software.
A técnica óbvia a ser utilizada para fazer isso são casos de uso (veja Capítulo 3). Um
caso de uso é um instantâneo de um aspecto do nosso sistema. A soma de todos
esses casos de uso é a imagem externa do nosso sistema, que segue um longo
caminho para explicar o que o sistema fará.
Uma boa coleção de casos de uso é central para compreender o que seu usuário
quer. Esses casos também apresentam um bom veículo para planejamento de
projeto, porque eles controlam o desenvolvimento iterativo que é em si só uma
técnica valiosa, uma vez que fornece umfeedback regular para os usuários sobre o
que está acontecendo com o software.
Embora casos de uso ajudem na comunicação sobre coisas superficiais, também é
crucial olhar as coisas mais profundas. Isso envolve aprender como os seus
especialistas do domínio entendem o mundo deles.
Diagramas de classes (veja Capítulos 4 e 6) podem ser extremamente valiosos aqui,
desde que você os desenhe a partir de uma perspectiva conceitual. Em outras
palavras, você deve tratar cada classe como um conceito na mente de usuário. Os
diagramas de classes que você desenha não são, então, diagramas de dados ou de
classes, mas diagramas da linguagem de seus usuários.
Considero diagramas de atividades (veja Capítulo 9) muito úteis em casos nos quais
os processos de workflow são uma parte importante do mundo dos usuários. Uma
vez que suportam processos paralelos, os diagramas de atividades podem ajudar a
nos livrar de seqüências desnecessárias de processos. O modo de elaborar estes
diagramas desenfatiza as ligações com classes, o que pode ser, mais tarde, um
problema no projeto, mas torna-se uma vantagem durante este estágio mais
conceitual do processo de desenvolvimento.
Procurando Mais Informação
Este livro não é uma referência completa e definitiva para UML, muito menos para
análise e projeto 00. 1-lá muito material publicado e muitas coisas que valem a pena
ser lidas. A medida que discutir tópicos individuais, mencionarei outros livros aos
quais você deve recorrer para informações mais profundas a respeito das idéias de
UML e de OOA&D de modo geral.
Certamente, o seu primeiro passo além deste livro sobre UML deve ser os
livros dos três amigos.

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM-PADRÃO DE MODELAGEM DE


OBJETOS \27 7
• Grady Booch liderou o trabalho no guia do usuário (Booch, Rumbaugh e Jacobson,
1999). Este livro tutorial explora maneiras nas quais você pode
usar UML para fazer várias tarefas de projeto.
• Jim Rumbaugh liderou o trabalho no manual de referência (Rumbaugh, Jacobson e
Booch 1999), frequentemente acho esta referência detalhada
da UML muito útil.
• Ivar Jacobson liderou o trabalho no livro que descreve um processo que trabalha
com UML (Jacobson, Booch e Rumbaugh, 1999). Abordarei mais
sobre questões de processo no Capítulo 2.
Certamente, os livros dos três amigos não são os únicos que você deve ler sobre boa
OOA&D. Minha lista de livros recomendados muda com freqUência, dê uma olhada na
minha hornepage para maiores detalhes.
Se você é novo na área de objetos, recomendo o meu livro introdutório favorito atual,
Larman (1998). O autor tem uma forte introdução dirigida a responsabilidades para
projeto, o que vale a pena ser seguido. Se você quiser saber mais sobre objetos de
um ponto de vista conceitual; Martin e Odel (1998) encontra-se agora disponível em
uma edição UML. Os desenvolvedores de tempo real devem obter uma cópia do livro
de Douglass (1998).
Sugiro também que você leia livros sobre padrões, para material que o levará além
do conhecimento básico. Agora que a guerra dos métodos acabou, penso que a
maior parte do material interessante sobre análise e projeto que aparecerá será
sobre padrões. Inevitavelmente, entretanto, as pessoas vão propor novas técnicas de
análise e projeto, e é provável que elas falarão sobre como estas técnicas podem ser
utilizadas com UML. Este é outro benefício: UML encoraja as pessoas a
acrescentarem novas técnicas sem duplicar os trabalhos que outras já tenham feito.

2
Um Esboço de Processo
de Desenvolvimento
UML é uma linguagem de modelagem, não uma metodologia. UML não tem noções
do processo, que é uma parte importante de uma metodologia.
O título deste livro é UML Essencial, portanto eu poderia seguramente ignorar o
processo. Entretanto, não acredito que as técnicas de modelagem tenham algum
sentido sem que se saiba como elas se encaixam no processo. E por isso que eu
decidi discutir primeiro o processo, então você pode ver como um desenvolvimento
orientado a objeto funciona. Eu o chamo esboço de processo porque em vez de
tentar entrar em muitos detalhes, ofereço apenas o suficiente para dar uma noção da
maneira típica na qual um projeto que usa estas técnicas funciona.
Os três amigos desenvolveram um processo unificado chamado Rational
Unfied Process (anteriormante chamado Objectory). Este processo é descrito no
livro de processo dos amigos (Jacobson, Booch e Rumbaugh, 1999).
À medida que discutir o esboço de projeto, utilizarei a terminologia e o esboço do
esquema do Rational Unified Process. (Tenho de usar algo, e este esquema me
parece bom). Entretanto, não tentei descrever o Rational Unified Process; isto está
além do escopo deste livro. Ao invés disto, descrevo um processo leve e sem
formalidade que é consistente com o processo da Rational. Para maiores detalhes
sobre o Rational Unified Process, você deve recorrer ao livro de processo dos três
amigos ou dar uma olhada na visão geral de Kruchten (1999).
Embora o Rational Unified Process contenha detalhes sobre que tipos de modelo
devem ser desenvolvidos nos vários estágios do processo, não entrarei em tais
detalhes. Também não especificarei tarefas a serem realizadas, resultados a serem
entregues e papéis a serem desempenhados. Minha terminologia é mais solta do que
a utilizada no Rational Unified Process - este é o preço que se paga por uma leve
descrição.
Qualquer que seja a discussão do processo, não esqueça que você pode utilizar
qualquer processo com UML. UML é independente de processo. Você deve

30 UM ESBOÇO DE PROCESSO DE DESENVOLVIMLTO


escolher algo que seja adequado ao seu tipo de projeto. Qualquer que seja o
processo que utilize, você pode usar UML para registrar as decisões de análise e de
projeto resultantes.
Na verdade, não acredito que possa existir um único processo para o
desenvolvimento de software. Vários fatores associados com o desenvolvimento de
software levam a vários tipos de processos. Estes fatores incluem o tipo de software
que você está desenvolvendo (tempo real, sistema de informações, produto de
desktop), a escala (desenvolvedor único, equipe pequena, equipe com mais de 100
membros) e assim por diante.
Acredito que equipes devem criar seus próprios processos, utilizando processos
publicados como orientação e não como padrões a serem seguidos.
Visão Geral do Processo
A Figura 2-1 mostra a visão de alto nível do processo de desenvolvimento.
Construção
Concepção Elaboração 1 2 Transição
Figura 2-1: Esboço do Processo de Desenvolvimento
Este processo é um processo de desenvolvimento iterativo e incremental, no qual o
software não é implementado em um instante no fim do projeto, mas é, ao contrário,
desenvolvido e implementado em partes. A fase de construção consiste de várias
iterações, nas quais cada iteração constrói software de qualidade de produção,
testado e integrado, que satisfaz um subconjunto de requisitos de projeto. A entrega
pode ser externa, para usuários iniciais, ou puramente interna. Cada iteração contém
todas as fases usuais do ciclo de vida da análise, do projeto, da implementação e do
teste.
Teoricamente, você pode começar pelo início: escolha alguma funcionalidade e
construa-a, escolha outra funcionalidade, e assim por diante. Entretanto, vale
a pena passar algum tempo planejando.
As duas primeiras fases são a concepção e a elaboração. Durante a concepção, você
estabelece a lógica do domínio da aplicação para o projeto e decide o escopo do
projeto. E aqui que você obtém o comprometimento do patrocinador do projeto para
seguir adiante. Na elaboração, você coleta requisitos mais detalhados, faz uma
análise e um projeto de alto nível para estabelecer uma arquitetura básica, e cria um
plano para a construção do sistema.
Mesmo com este tipo de processo iterativo, algum trabalho tem que ser deixado para
ser feito no fim, na fase de transição. Este trabalho pode incluir teste
beta, ajuste de performance e treinamento de usuário.

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM-PADRÃO DE MODELAGEM DE


OBJETOS 3ï7
Os projetos variam de acordo com o volume de formalidade que eles têm. Projetos de
muita formalidade têm muitos documentos formais a serem entregues, reuniões
formais, encerramentos formais. Projetos de pouca formalidade podem ter uma fase
de concepção que consiste de um bate-papo de uma hora com o patrocinador do
projeto e um plano que cabe em uma folha de papel. Naturalmente, quanto maior o
projeto, mais formalidade você precisa. O fundamental de cada fase ainda acontece,
mas de formas bem diferentes.
Procuro manter o mínimo de formalidade possível, e a minha discussão reflete isso.
Existem vários processos de muita formalidade a serem escolhidos em outras partes.

Mostrei iterações na fase de construção, mas não nas outras fases. Na verdade, você
pode ter iterações em todas as fases, e é sempre uma boa idéia fazer isso em um
ciclo maior. A construção é a fase-chave para iteração.
Esta é a visão de alto nível. Agora, aprofundaremos os detalhes a fim de ter
informação suficiente para ver onde as técnicas discutidas mais adiante neste livro
se encaixam no esquema maior. Fazendo isso, abordarei um pouco estas técnicas e
quando usá-las. Você pode considerar isso um pouco confuso se você ainda não
estiver familiarizado com as técnicas. Se este for o caso, pule estas partes e volte a
elas mais tarde.
Concepção
A concepção pode ter várias formas. Para alguns projetos, um bate-papo na hora do
café: “Vamos colocar nosso catálogo de serviços na rede”. Para projetos maiores,
pode ser um estudo da viabilidade completo, o que leva meses.
Durante a concepção, você elabora o plano de negócio do projeto - a grosso modo
quanto custará e o quanto terá de retorno. Você também pode necessitar ter uma
idéia do escopo do projeto. Você pode necessitar fazer alguma análise inicial para ter
uma idéia do tamanho do projeto.
Não tenho a tendência de fazer a concepção muito importante. A concepção deve ser
um trabalho de poucos dias para considerar se vale a pena fazer uma investigação
mais profunda de alguns meses durante a elaboração (veja a próxima seção). A esta
altura, o patrocinador do projeto concorda apenas na realização de uma séria análise
do projeto.
Elaboração
Então, você tem o “vá em frente” para iniciar o projeto. Neste estágio, você tem
tipicamente, somente uma vaga idéia dos requisitos. Por exemplo, você pode ser
capaz de dizer:
Construiremos um sistema de próxima gera çao de suporte ao consumidor
para a Watts Galore Utility Company. Pretendemos usar tecnologia orientada
a objetos para construir um sistema mais flexível que é mais ori

E
UM IiSBOÇO DE f’ROCESSo DE DESENVOLVIMENTO
entado ao consumidor - especificamente, uni sistema que suportard o
faturamento integrado do cliente.
Evidentemente, nosso documento de requisitos será mais extenso do que isso, mas
na verdade, ele não pode dizer muito mais.
A esta altura, você quer ter uma melhor compreensão do problema.
• O que é que você realmente irá construir?
• Como você irá construí-lo?
Quando decidir quais itens examinar nesta fase, você precisa levar em consideração,
acima de tudo, os riscos do seu projeto. Que coisas poderiam descarrilhá-lo? Quanto
maior o risco, mais atenção você tem que dar a ele.
Na minha experiência, os riscos podem ser utilmente classificados em quatro
categorias:
1. Riscos de requisitos. Quais são os requisitos do sistema? O grande perigo é você
construir um outro sistema, um sistema que não faz o que o cliente
necessita.
2. Riscos tecnológicos. Quais são os riscos tecnológicos que você tem que enfrentar?
Você está selecionando a tecnologia que realmente fará o serviço
por você? As várias partes se encaixarão?
3. Riscos de habilidades. Você pode encontrar o pessoal e especialistas de que
necessita?
4. Riscos políticos. Existem forças políticas que podem interferir e afetar seriamente
o seu projeto?
O seu caso pode ter mais riscos, mas os riscos que se encaixam nestas quatros
categorias estão quase sempre presentes.
Lidando com Riscos de Requisitos
Requisitos são importantes e são onde as técnicas de LJML podem ser postas mais
obviamente em uso. O ponto inicial são os casos de uso. Casos de uso dirigem todo o
processo de desenvolvimento.
Abordarei em detalhes casos de uso no Capítulo 3; aqui simplesmente farei uma
breve descrição do que são casos de uso.
Um caso de uso é uma interação típica que o usuário tem com o sistema a fim de
atingir um objetivo. Imagine um processador de palavras típico. Um caso de uso seria
“faça a verificação ortográfica”; outro caso seria “crie um índice para o documento”.
O elemento-chave para casos de uso é que cada um indica uma função que o usuário
pode entender e que tem valor para o usuário. Conversando sobre casos de uso, um
desenvolvedor pode responder com detalhes específicos. Por exemplo:
Levarei dois meses para fazer afunção de índice para você. Também tenho um caso
de uso para dar suporte à verificação gramatical; acredito

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM-PADRÃO DE MODELAGEM DE


OBJETOS
que isso levará três meses. Temos apenas três meses até a data do lançainento - o
que você prefere?
Casos de uso fornecem a base da comunicação entre clientes e desenvolvedores
no planejamento do projeto.
Uma das coisas mais importantes a ser feita na fase de elaboração é descobrir todos
os casos de uso potenciais para o sistema que você está construindo. Na prática,
certamente, você não descobrirá todos. Entretanto, você quer descobrir a maioria,
particularmente os mais importantes e os mais arriscados. É por esta razão que,
durante a fase de elaboração, você deve planejar entrevistas com usuários a fim de
identificar casos de uso.
Casos de uso não precisam ser detalhados. Acredito, geralmente, que de um a três
parágrafos de texto descritivo sejam suficientes. Este texto deve ser suficientemente
específico para que os usuários entendam a idéia básica e para que os
desenvolvedores tenham uma visão mais ampla do que está escondido por dentro.
No entanto, casos de uso não são tudo. Outra tarefa importante é esboçar um
esqueleto do modelo conceitual do domínio. Na mente de um ou mais usuários
está a idéia de como o negócio funciona. Por exemplo:
Nossos clientes têm muitos endereços, efornecemos diversos serviços para estes
endereços. No momento, um cliente recebe uma fatura para todos os serviços em
um dado endereço. Queremos que este cliente seja cobrado por todos os serviços em
todos os endereços. Chamamos isso defaturamento consolidado.
Esta passagem contém as palavras “cliente”, “endereço” e “serviço”. O que estes
termos significam? Como eles se encaixam? Um modelo de domínio conceitual
começa a responder estas questões, e ao mesmo tempo dá um embasamento para o
modelo de objetos que será utilizado para representar os objetos do sistema mais
adiante no processo. Uso o termo modelo de domínio para descrever qualquer
modelo, cujo sujeito primário seja o mundo que o sistema de computação está
suportando, qualquer que seja o estado do processo de desenvolvimento em que se
esteja.
Observe que o processo unificado da Rational define o termo “modelo de domínio”
mais estreitamente; veja Jacobson, Booch e Rumbaugh (1999) para detalhes. O meu
uso é o mesmo que a maioria das pessoas que conheço na comunidade de objeto
utiliza.
Considero duas técnicas de UML valiosas na construção de modelos de domínio
conceitual.
A técnica principal que uso para os modelos de domínio é o diagrama de classes,
feito a partir de uma perspectiva conceitual (veja Capítulo 4). Você pode utilizar estes
diagramas para esquematizar os conceitos que os especialistas em negócios usam
quando eles pensam sobre o negócio e para esquematizar as maneiras como estes
especialistas ligam os conceitos entre si. De várias maneiras, os diagramas de
classes formam a definição de um vocabulário rigoroso para falar sobre o domínio.
Se o domínio também tem um forte elemento de workflow, gosto de descrevêlo com
diagramas de atividades (veja Capítulo 9). O aspecto-chave de diagramas

UM ESBOÇO DE PROCESSO DE DESENVOIVIMENTO


de atividades é que eles encorajam a procura de processos paralelos, que é
importante na eliminação de seqüências desnecessárias em processos de negócio.
Algumas pessoas gostam de usar diagramas de interação (veja Capítulo 5) para
explorar como vários papéis interagem no negócio. Elas consideram mais fácil obter
uma compreensão do processo, pensando ao mesmo tempo em trabalhadores e
atividades. Prefiro utilizar diagramas de atividades para estabelecer primeiro o que
precisa ser feito e determinar mais tarde quem faz o quê.
Modelagem de domínio pode ser um grande apoio para os casos de uso. Quando
coleto casos de uso, gosto de trazer um especialista no domínio e explorar como esta
pessoa pensa sobre o negócio, com auxílio de diagramas conceituais de classe e
diagramas de atividades.
Nesta situação, uso notação mínima, não me preocupo com rigor e precisão
e faço várias anotações informativas no diagrama. Não tento captar cada detalhe.
Ao contrário, focalizo em aspectos importantes e em áreas que implicam risco.
Desenho muitos diagramas desconectados sem me preocupar com a consistência
e as inter-relações entre os diagramas.
Considero que esse processo pode rapidamente fornecer muita compreensão. Munido
desta compreensão, acredito que posso identificar mais facilmente
os casos de uso para os vários usuários.
Depois de cobrir a maior parte das áreas relevantes, gosto de consolidar os vários
diagramas em um único modelo consistente de domínio. Para tanto, utilizo um ou
dois especialistas de domínio que gostam de se aprofundar na modelagem.
Mantenho a perspectiva conceitual, mas, ao mesmo tempo, me torno mais rigoroso.
Este modelo pode, então, agir como um ponto inicial para construção de classes na
fase de construção. Se este modelo é grande, uso pacotes para dividir o modelo em
pedaços. Consolidarei as informações dos diagramas de classes e de atividades e,
talvez, desenharei alguns diagramas de estados para classes que têm ciclos de vida
interessantes.
Você deve considerar este modelo inicial de domínio como um esqueleto, não como
um modelo de alto nível, O termo “modelo de alto nível” implica na falta de muitos
detalhes. Já vi este erro ser cometido em várias situações, expresso como, por
exemplo, “Não mostre atributos destes modelos”. Os resultados são modelos sem
substância. E fácil ver por que os desenvolvedores ridicularizam tais esforços.
Você não pode, entretanto, utilizar um enfoque contrário e construir um modelo
detalhado. Se você fizer isso, levará muito tempo e você morrerá de paralisia de
andlise, O truque é encontrar os detalhes importantes e se concentrar neles. A
maioria dos detalhes será tratada durante o desenvolvimento iterativo. É por isso
que prefiro pensar neste modelo como um esqueleto. O esqueleto é a base para o
resto do modelo. Ele é detalhado, mas é somente uma parte da história.
Naturalmente, isso não lhe diz como diferenciar a água do vinho; esta é a
arte do analista experiente, eu ainda não consegui elaborar como definir isso!
Modelagem de domínio também é dirigida por casos de uso, à medida que eles se
tornam conhecidos. Quando casos de uso aparecem à equipe de modelagem, deve-
se analisá-los para avaliar se eles contêm algo que possa ter um forte impacto no
modelo de domínio. Se este for o caso, eles devem explorar mais; caso contrário, os
casos de uso devem ser deixados de lado por enquanto.

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM-PADRÃO DE MODELAGEM DE


OBJETOS
A equipe que constrói um modelo de domínio deveria ser um grupo pequeno (2 a 4
pessoas) que incluem desenvolvedores e especialistas do domínio. A menor equipe
viável seria um desenvolvedor e um especialista de domínio.
A equipe deve trabalhar intensamente no período de elaboração até que o modelo
esteja fechado. Durante este período, a liderança deve assegurar que a equipe não
se emaranhe em detalhes nem opere em um nível tão alto que perca contato com a
realidade. Uma vez que eles entendem o que estão fazendo, ficar trancado nos
detalhes é o maior perigo. Uma data de entrega inflexível funciona bem como
estímulo para total concentração.
Como parte da compreensão dos requisitos do sistema, você deve construir um
protótipo de todas as partes difíceis dos casos de uso. A criação de protótipos é uma
técnica valiosa para obter uma melhor compreensão de como situações mais
dinâmicas funcionam.
Uso protótipos sempre que me sinto desconfortável sobre como uma parte de risco
do sistema realmente funcionará. Construo protótipos suficientes para compreender
bastante a fim de avaliar o risco e estimar o quanto de trabalho será necessário.
Normalmente, não faço protótipos de todo o quadro; ao contrário, uso o modelo de
domínio completo para enfatizar áreas que precisam de prototipação.
Acredito que pessoas não familiarizadas com UML precisam criar mais protótipos.
Isso as ajuda a se familiarizar com o modo pelo qual diagramas UML correspondem à
programação real.
Quando você utiliza um protótipo, não fique limitado ao ambiente no qual você
realmente desenvolverá o sistema. Por exemplo, geralmente ganho muito dos
protótipos de análise em Snialtalk, mesmo quando estou construindo um sistema C+
+.
Um dos elementos mais importantes no manejo de risco de requisitos é obter acesso
a uma especialidade de domínio. Falta de acesso a pessoas que, realmente,
conhecem o domínio é uma das causas mais ..omuns para que os projetos falhem.
Vale a pena investir tempo e dinheiro consideráveis para trazer para sua equipe
pessoas, de fato, conheçam o domínio - a qualidade do software será diretamente
proporcional ao seu conteúdo. Estas pessoas não precisam trabalhar tempo integral,
elas devem ser abertas, ter bastante conhecimento prático e estar disponíveis para
perguntas.
Lidando com Riscos Tecnológicos
A coisa mais importante a fazer em relação a riscos tecnológicos é construir um
protótipo que experimente as partes da tecnologia que você está pensando em
utilizar.
Por exemplo, digamos que você esteja utilizando C++ e um banco de dados
relacional. Você deve construir uma aplicação simples utilizando C++ e o banco de
dados juntos. Experimente várias ferramentas e veja quais funcionam melhor. Perca
algum tempo para se sentir à vontade com as ferramentas que você utilizará.
Não esqueça que os maiores riscos tecnológicos são inerentes a como os
componentes do projeto se encaixam. Você pode conhecer bem C++ e pode
conhecer também bancos de dados relacionais, mas utilizá-los juntos pode ser
surpreen

UM ESBOÇO DE PROCESSO DE DESENVOLVIMENTO


dentemente difícil. É por isso que é tão importante obter todos os componentes
que você pretende utilizar e encaixá-los nesta fase inicial do processo.
Você também deve tratar das decisões de projeto arquitetônico durante este estágio.
Estes assumem, geralmente, formas de idéias sobre quais são os maiores
componentes e como eles serão construídos. Isso é particularmente importante se
você está considerando um sistema distribuído.
Como parte deste exercício, concentre-se em quaisquer áreas que parecem
difíceis de serem modificadas mais tarde. Tente fazer o seu projeto de modo que
ele permita trocar elementos do projeto com relativa facilidade. Questione-se:
• O que acontecerá se uma peça de tecnologia não funcionar?
• O que acontecerá se não conseguirmos conectar as duas partes do quebra-cabeça?

• Qual é a probabilidade de algo dar errado? O que faremos se isso acontecer?


Como no caso do modelo do domínio, você deve observar os casos de uso à medida
que eles apareçam a fim de avaliar se contêm algo que possa prejudicar o seu
projeto. Se você teme que eles possam conter uma bomba escondida, investigue
mais detalhadamente.
Durante este processo, você utilizará tipicamente um número de técnicas UML para
esboçar suas idéias e documentar as coisas que você experimentar. Não tente ser
amplo a esta altura; esboços breves são tudo o que você precisa e, portanto, são
tudo o que você deve utilizar.
• Diagramas de classes (veja os Capítulos 4 e 6) e diagramas de interação (veja o
Capítulo 5) são úteis para mosfrar como os componentes se comi.micam.
• Diagramas de pacotes (veja o Capítulo 7) podem mostrar uma figura de alto nível
dos componentes, neste estágio.
• Diagramas de utilização (veja o Capítulo 10) podem dar uma visão geral de como
as peças são distribuídas.
Lidando com Riscos de Especialização
Freqüentemente, vou a conferências e assisto a palestras sobre estudos de caso
ministradas por pessoas que recém terminaram um projeto orientado a objetos. Elas,
geralmente, respondem a pergunta: “Quais foram seus maiores erros?” com
respostas que, normalmente, incluem: “Deveríamos ter tido mais treinamento”.
Sempre me surpreendo como empresas iniciam importantes projetos 00 com pouca
experiência e sem considerar como obter mais experiência. As pessoas se
preocupam com custos de treinamentos, mas eles pagam cada centavo à medida
que o projeto se estende.
Treinamento é um modo de evitar erros, porque os instrutores já cometeram
aqueles erros. Errar toma tempo, e tempo custa dinheiro. Então, você paga de
qualquer maneira, mas a falta de treinamento faz com que o projeto se estenda.
Não sou um grande fã de cursos de treinamentos formais. Ensinei e projetei
muitos deles. Continuo não convencido de que eles sejam eficazes no ensinamento
de habilidades orientadas a objetos. Eles dão às pessoas uma visão geral do que

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM-PADRÃO DE MODELAGEM DE


OBJETOS
elas devem saber, mas realmente não passam as habilidades essenciais necessárias
para fazer um projeto sério. Um curto curso de treinamento pode ser útil, mas é
apenas o início.
Se você fizer um curto curso de treinamento, preste muita atenção no instrutor. Vale
a pena pagar muito mais por alguém com bastante conhecimento e que seja
esfuziante, porque você aprenderá muito mais durante o processo. Além disso, faça o
seu treinamento em pequenas porções, à medida do necessário (just in time). Se
você não aplicar imediatamente o que aprendeu em um curso de treinamento, você
esquecerá.
A melhor maneira de obter especialização 00 é por consultoria, na qual você tem um
desenvolvedor especializado trabalhando no seu projeto por um longo período de
tempo. O consultor mostra como fazer as coisas, observa o que você faz, dá dicas e
um pouco de treinamento.
Um consultor trabalhará com os detalhes específicos do seu projeto e saberá que tipo
de conhecimento deve utilizar e quando. Nos estágios iniciais, o consultor é um
membro da equipe, ajudando a encontrar uma solução. A medida que o tempo passa,
você se torna mais capaz, e o consultor passa mais a revisar do que propriamente
fazer algo. Meu objetivo como consultor é me tornar desnecessário.
Você pode encontrar consultores para áreas específicas ou para todo o projeto. Os
consultores podem trabalhar meio-turno ou tempo integral. Muitos consultores
gostam de trabalhar uma semana de cada mês em cada projeto; outros consideram
isso muito pouco. Procure um consultor com conhecimento e que tenha a habilidade
de transmitir este conhecimento. O seu consultor pode ser o fator mais importante
para o sucesso do seu projeto; vale a pena pagar pela qualidade.
Se você não puder conseguir um consultor, faça uma revisão no projeto a cada dois
meses. Neste tipo de estrutura, um consultor experiente pode passar alguns dias
revisando vários aspectos do seu projeto. Durante este tempo, o revisor pode
salientar várias áreas que estão preocupando, sugerir idéias adicionais e
esquematizar quaisquer técnicas úteis que a equipe possa estar ignorando. Embora
isso não lhe dê todas as vantagens de um bom consultor, pode ser útil para
identificar aspectos-chave que você pode fazer melhor.
Você também pode enriquecer suas habilidades através da leitura. Tente ler um bom
livro técnico, no mínimo, uma vez a cada dois meses. Melhor ainda, leia- o como
parte de um grupo de leitura. Encontre algumas pessoas que queiram ler o mesmo
livro. Combinem de ler alguns capítulos a cada semana, e passem uma ou duas horas
discutindo os capítulos lidos. Fazendo isso, você pode obter um conhecimento maior
do que lendo sozinho. Se você for o gerente, incentive este tipo de atividade. Consiga
uma sala para o grupo; dê ao seu pessoal dinheiro para comprar material técnico;
determine tempo para o grupo do livro.
A comunidade de padrões de objeto descobriu que os grupos de leitura têm um
grande valor. Vários grupos de leitura de padrões surgiram. Consulte a hoíne page de
padrões (http://www.hillside.net/patterns) para maiores informações sohre estes
grupos.
A medida que você trabalhar na elaboração, preste atenção às áreas nas quais você
não tem muita experiência nem habilidade. Planeje obter a experiência no momento
em que você precisar dela.

UM EsBoço DE PROCESSO DE DESENVOLVIMENTO

Lidando com Riscos Políticos

Não POSSO oferecer conselhos sérios nesta área, porque não sou um político
corporativo experiente. Recomendo que você encontre alguém habilitado para lhe
aconselhar.

Quando Termina a Elaboração?

Meu princípio básico é que a elaboração leve em torno de um quinto do tempo total
do projeto. Dois fatores são indicadores-chave de que a elaboração foi completada.

• Os desenvolvedores podem se sentir à vontade dando estimativas, em


pessoas/semana de trabalho, de quanto tempo levará para construir cada caso de
uso.
• Todos os riscos significativos foram identificados, e os maiores são compreendidos
até o ponto que você sabe como pretende lidar com eles.

Planejando_a Fase de Construção

Há várias maneiras de planejar um projeto iterativo. É importante que você


desenvolva um plano de modo a estar ciente do progresso e para indicar o progresso
para a equipe. O método para o planejamento que uso é baseado em técnicas do
Extrenie Programming Explained (Beck 2000).
A essência da construção de um plano envolve estabelecer uma série de iterações
para construção e definir a funcionalidade a entregar em cada iteração. Algumas
pessoas gostam de utilizar pequenos casos de uso e completar um deles dentro de
uma iteração; outras gostam de usar casos de uso maiores, fazendo algum cenário
em uma iteração e outros mais tarde. O processo básico é o mesmo. Eu o descreverei
com casos de uso menores.
Durante o planejamento, gosto de considerar dois grupos de pessoas: clientes e
desenvolvedores.
Clientes são as pessoas que utilizarão o sistema no caso de um desenvolvimento
interno. Para um sistema ser vendido em prateleira, o pessoal de marketing,
geralmente, representa o cliente. O aspecto-chave é que os clientes são as pessoas
que podem avaliar o valor de negócio de um caso de uso sendo implementado.
Desenvolvedores são as pessoas que construirão o sistema. Eles devem entender os
custos e o trabalho envolvido na construção de um caso de uso. Portanto, devem
estar familiarizados com o ambiente do desenvolvimento. Geralmente, a gerência
não pode desempenhar esta função, porque é necessária experiência técnica
atualizada para fazê-lo.
O primeiro passo é categorizar os casos de uso. Faço isso de duas maneiras.
l’rimeiro, o cliente divide os casos de uso, de acordo com o valor do seu negócio, em
três pilhas de prioridade: alta, média e baixa. (Observe que é considerada má
conduta colocar tudo na pilha “alta”). Depois, o cliente registra os conteúdos de cada
categoria.

1
UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM-PADRÃO DE MODELAGEM DE
OBJETOS
Os desenvolvedores dividem, então, os casos de uso de acordo com o risco
de desenvolvimento. Por exemplo, “alto risco” seria usado para algo que fosse
muito difícil de ser feito, poderia ter um grande impacto no projeto do sistema, ou
é simplesmente mal compreendido.
Depois que isso é feito, os desenvolvedores devem estimar o tempo que cada
caso de uso necessitará, em pessoas/semana. Na realização desta estimativa,
considere
que você necessita fazer análise, projeto, codificação, teste de unidade,
integração e documentação. Também admita que você tenha um desenvolvedor
altamente comprometido, sem outras tarefas ou distrações (acrescentaremos um
fator de carga mais tarde).
Uma vez que suas estimativas estejam prontas, você pode avaliar se está
pronto para fazer o plano. Observe os casos de uso de alto risco. Se muito tempo
do projeto estiver vinculado a estes casos de uso, você deve fazer mais elaboração.
O próximo passo é determinar a duração de suas iterações. Você quer iterações
de duração fixa para todo o projeto, de modo que possa ter um ritmo regular para
o resultado de cada iteração. Uma iteração deve ser longa o suficiente, para você
fazer um punhado de casos de uso. Para Smalltalk, isso pode ser umas duas ou
três semanas; para C++, pode ser algo como seis ou oito semanas.
Agora, você pode considerar o quanto de trabalho você tem para cada iteração.
Observe que você terá feito estas estimativas, considerando um desenvolvedor
que não se distraia. Obviamente, isso nunca é o caso, portanto levo em conta o
coeficiente de carga que é a diferença entre o tempo ideal e o tempo real. Você
deve medir este fator comparando estimativas com os fatos reais.
Agora, você pode calcular com que rapidez pode prosseguir, o que chamo de
velocidade do projeto. Isso é o quanto de desenvolvimento você pode fazer em
uma iteração. Você calcula isso tomando o seu número de desenvolvedores,
multiplicando
pela duração da iteração e, então, dividindo o resultado pelo coeficiente
de carga. Por exemplo, dados 8 desenvolvedores, uma iteração de três semanas
de duração, e um coeficiente de carga de 2, você teria um ideal de 12 semanas de
desenvolvimento (8*3*1/2) de trabalho por iteração.
Some o tempo para todos os casos de uso, divida-o pelo trabalho por iteração,
e acrescente um para sorte. O resultado é a sua primeira estimativa de quantas
iterações você necessitará para o seu projeto.
O próximo passo é assinalar casos de uso para iterações.
Os casos de uso que têm alta prioridade e/ou riscos de desenvolviment
devem ser tratados na fase inicial. Não adie o risco até o final! Você poderá neces
sitar dividir casos de uso grandes e, provavelmente, revisará as estimativas dE
casos de uso devido à ordem em que você estiver fazendo as coisas. Você pode tei
menos trabalho para fazer do que o possível na iteração, mas não deve programai
mais do que o seu esforço permitir.
Para a transição, determine de 10% a 35% do tempo de construção para ajus
te e empacotamento para a entrega final (use um número alto se você foi
inexperiente com ajuste e empacotamento no seu ambiente atual).
Adicione, então, um fator de contingência: de 10% a 20% do tempo de cons
trução, dependendo de quão arriscadas as coisas possam parecer. Acrescente este
fator no final da fase de transição. Você deve planejar a entrega sem usar temp

UM EsBoço DE PROCESSO DE DESENVOLVIMENTO


de contingência - ou seja, sua data-alvo interna - mas comprometa-se em entregar
ao final do tempo de contingência.
Depois de seguir estas orientações, você deve ter um plano de implementação que
mostra os casos de uso que serão feitos durante cada iteração. Este plano simboliza
comprometimento entre os desenvolvedores e os usuários. Este plano não é imutável
- na verdade, todos devem esperar que o plano mude à medida que o projeto
progride. Uma vez que existe um compromisso entre os desenvolvedores e os
usuários, as mudanças devem ser feitas de comum acordo.
Como você pode ver pelo que está sendo exposto, casos de uso servem como
base para o planejamento do projeto, e é por isso que UML põe muita ênfase neles.
Construção
A construção elabora o sistema em uma série de iterações. Cada iteração é um
miniprojeto. Você faz análise, projeto, codificação, teste e integração para os casos
de uso designados para cada iteração. Você termina a iteração com uma
demonstração para o usuário e realiza testes de sistema para confirmar que os casos
de uso foram construídos corretamente.
O objetivo deste processo é reduzir o risco. O risco, geralmente, aparece porque
casos difíceis são deixados para o fim do projeto. Vejo projetos onde os testes
e a integração são deixados para o final. Teste e integração são tarefas extensas, e
elas sempre demoram mais do que as pessoas imaginam. Deixadas para o fim,
elas são difíceis e desanimadoras. É por isso que sempre encorajo os meus clientes
a desenvolverem software de autoteste (veja box).
As iterações dentro da construção são tanto incrementais quanto iterativas.
• As iterações são incrernen tais na função. Cada iteração é construída sobre os
casos de uso desenvolvidos nas iterações prévias.
• As iterações são iterativas em termos da base de código. Cada iteração implicará
que alguns trechos de código existentes sejam reescritos, para
os tornar mais flexíveis.
Refatoração (veja box) é uma técnica extremamente útil na iteração de código. É
uma boa idéia observar a quantidade de código que é jogada fora em cada iteração.
Desconfie se menos de 10% do código anterior é descartado a cada vez.
A integração deve ser um processo contínuo. Para iniciantes, a integração total é
parte do final de cada iteração. Entretanto, a integração pode e deve ocorrer com
mais freqüência. Uma boa prática é fazer uma construção completa e uma
integração a cada dia. Fazendo isso diariamente, as coisas não saem tanto de
sincronia que se tornam um problema integrá-las mais tarde.
Um desenvolvedor deve integrar depois de cada trabalho significativo. Além
disso, o conjunto completo de testes de unidade deve ser rodado a cada integração,
de forma a assegurar teste de regressão completo.

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM-PADRÃO DE MODELAGEM DE


OEJETOS
Software de Autoteste
Quanto mais velho eu fico, mais agressivo me torno em relação a testes. Teste
deveria ser um processo contínuo. Nenhum código deveria ser escrito até que você
saiba como testá-lo. Uma vez que você escreva um código, escreva os testes para
ele. Até que os testes funcionem, você não pode anunciar que terminou de escrever
o código.
Código de teste, uma vez escrito, deve ser guardado para sempre. Estabeleça o seu
código de teste de modo que possa executar um teste com uma simples linha de
comando ou com um botão GUI. O código deve responder com “0K” ou com uma lista
de falhas. Todos os testes devem também verificar os seus próprios resultados. Não
há nada que desperdice mais tempo do que ter um teste emissor de número, e você
ter que pesquisar o significado do mesmo.
Faço testes funcionais e de unidade. Os testes de unidade devem ser escritos pelos
desenvolvedores, organizados em pacotes e codificados para testar as interfaces de
todas as classes. Acredito que escrever testes de unidade, realmente, aumenta a
velocidade da minha programação.
Testes funcionais ou testes de sistema devem ser desenvolvidos por uma pequena
equipe separada, encarregada somente de fazer testes. Esta equipe deve ter uma
visão de caixa preta do sistema e ter especial prazer em encontrar erros e falhas
(bugs). (Bigodes sinistros e gargalhadas tétricas são opcionais mas desejáveis).
Há um frarnework de código aberto, simples mas poderoso, para testes
de unidade: a famflia xUnit. Para detalhes, veja o link na minha homepage.
Quando o Plano se Desintegra
A única coisa que você pode saber com certeza sobre um plano é que as coisas não
vão acontecer de acordo com ele. O gerenciamento de um plano tem tudo a ver com
a maneira como você lida efetivamente com as mudanças.
Uma característica-chave para o desenvolvimento iterativo é que ele é congelado nas
datas - você não pode deixar passar nenhuma data. Ao contrário, casos de uso
podem ser movidos para uma iteração posterior através de negociação
Refatoraçao
Você já se deparou com o princípio da entropia de software? Ele sugere que
programas iniciam de uma maneira bem projetada, mas à medida que novas porções
de funcionalidade são agregadas, programas gradualmente perdem sua estrutura,
transformando-se finalmente, numa maçaroca de espaguete.
Parte disso é devido à escala. Você escreve um pequeno programa que
executa bem um trabalho específico. As pessoas pedem que você aumente o

‘ 42 r UM EsBoço DE PROCESSO DE DESENVOLVIMENTO


v ___________
programa, e ele se torna mais complexo. Mesmo que você tente ficar de olho
no projeto, isso ainda pode acontecer.
Uma das razões por que a entropia do software ocorre é que, quando você adiciona
uma nova função ao programa, você constrói em cima de um programa existente,
geralmente de uma maneira que o programa não estava projetado para suportar. Em
tal situação, você pode reprojetar o programa existente para melhor suportar as suas
mudanças, ou pode trabalhar ao redor dessas mudanças nos seus acréscimos.
Embora na teoria seja melhor reprojetar seu programa, isso geralmente resulta em
trabalho extra porque qualquer reescrita no seu programa existente introduzirá
novos erros e problemas. Lembre-se do velho provérbio de engenharia: “Se não está
quebrado, não conserte!” Entretanto, se você não reprojetar seu programa, os
acréscimos serão mais complexos do que deveriam.
Gradualmente, esta complexidade extra exigirá uma dura pena. Portanto, há um
custo/benefício: O reprojeto causa um incômodo no curto prazo para um ganho no
longo prazo. Sendo a pressão de agenda como ela é, a maioria das pessoas prefere
adiar o inconveniente para o futuro.
A refatoração é um termo utilizado para descrever técnicas que reduzem o
inconveniente de curto prazo do reprojeto. Ao refatorar, você não muda a
funcionalidade do seu programa; ao invés disso, você muda sua estrutura interna a
fim de facilitar sua compreensão e seu manuseio.
As mudanças da refatoração são, geralmente, em pequenos passos:
renomear um método, mover um campo de uma classe a outra, consolidar dois
métodos semelhantes em uma superclasse. Cada passo é pequeno, no entanto,
algumas horas gastas realizando estes pequenos passos podem trazer inúmeros
benefícios ao programa.
A refatoração se toma mais fácil se você seguir os seguintes princípios.
• Não refatore e adicione funcionalidades a um programa ao mesmo tempo. Imponha
uma separação clara entre eles quando você trabalha. Você pode passar de um para
o outro em pequenos passos - por exemplo, meia-hora de refatoração, uma hora
adicionando uma nova função e meia-hora refatorando o código que você recém
adicionou.
• Certifique-se que você tem bons testes antes de iniciar a refatoração.
• De passos curtos, deliberados. Troque um campo de uma classe para outra. Una
duas metodologias semelhantes em uma superclasse. Teste depois de cada passo.
Isso pode parecer lento, mas evita depuração e, portanto, acelera o trabalho.
Você deve refatorar quando está acrescentando uma nova função ou
corrigindo um erro. Não reserve um tempo específico para refatoração; em
vez disto, faça um pouco a cada dia.
Para maiores informações sobre refatoração, veja Fowler (1999).
e de acordo com o cliente, O motivo disso é manter um hábito regular de cumprir
as datas e evitar o mau hábito de atrasar compromissos.

UIVIL ESSENCIAL: UM BREVE (.U1A PARA A LINGUAGEM-i’ADRÃO DE MODELAGEM DE


OBJETOS
Se você se achar protelando muitos casos de uso, é hora de refazer o plano, incluindo
uma re-estimativa dos níveis de esforços dos casos de uso. A essa altura, os
desenvolvedores devem ter uma idéia melhor de quanto tempo as coisas levarão.
Você deve esperar fazer uma alteração no plano a cada duas ou três iterações.
Utilizando UML na Construção
Todas as técnicas de UML são úteis neste estágio. Uma vez que farei referências a
técnicas as quais não tive oportunidade de abordar ainda, sinta-se à vontade para
pular esta seção e retornar a ela mais tarde.
Quando você considera adicionar um dado caso de uso, você, primeiro, o examina
para determinar qual é seu escopo. Um diagrama conceitual de classes (veja o
Capítulo 4) pode ser útil para delinear alguns conceitos para o caso de uso e para ver
como estes conceitos se encaixam com o software que já foi construído.
A vantagem destas técnicas a esta altura é que elas podem ser utilizadas em
conjunto com especialistas do domínio. Como Brad Kain diz: a análise acontece
somente quando o especialista de domínio está na sala (senão é uma
pseudoanálise).
Para fazer a mudança para projeto, examine como as classes colaborarão para
implementar a funcionalidade requerida para cada caso de uso. Considero que
cartões CRC e diagramas de interação são úteis na exploração destas interações.
Estes vão expor responsabilidades e operações que você pode registrar no diagrama
de classe.
Trate estes desenhos como um esboço inicial e como uma ferramenta com a
qual você pode discutir os enfoques do projeto com seus colegas. Uma vez que
você se sinta à vontade, está na hora de passar para código.
Inevitavelmente, o imperdoável código vai expor fraquezas no projeto. Não
tenha medo de mudar o projeto em resposta a esta aprendizagem. Se a mudança
for séria, use as notações para discutir idéias com seus colegas.
Uma vez construído o software, você pode usar UML para ajudar a documentar o que
fez. Acredito que diagramas UML são úteis para obter-se uma compreensão geral de
um sistema. Fazendo isso, entretanto, devo salientar que não acredito na produção
de diagramas detalhados de todo o sistema. Citando Ward Cunningham (1996):
Memos bem escritos e cuidadosamente selecionados podem facilmente substituir
uma abran gente documentação de projeto tradicional. O priineiro raramente brilha,
exceto em pontos isolados. Eleve estes pontos
e esqueça o resto.
Acredito que uma documentação detalhada deveria ser gerada de um código (como,
por exemplo, JavaDoc). Você deve escrever documentação adicional para salientar
conceitos importantes. Pense neles como sendo um primeiro passo para o leitor,
antes que ele vá para detalhes de código. Gosto de estruturá-los como textos curtos
o suficiente para serem lidos durante um café, utilizando diagramas UML para ajudar
a ilustrar a discussão.

‘\44 r UM ESBOÇO DE PROCESSO DE DESENVOLVIMENTO


Uso diagramas de pacote como o meu mapa lógico do sistema. Este diagrama me
ajuda a compreender as partes lógicas do sistema e ver as dependências (e mantê-
las sob controle). Um diagrama de utilização (veja o Capítulo 10) que mostra o
quadro físico de alto nível, também pode se mostrar útil neste estágio.
Dentro de cada pacote, gosto de ver um diagrama de classes na perspectiva de
especificação. Não mostro cada operação em cada classe. Mostro apenas as
associações e os atributos-chave e operações que me ajudam a entender o que
existe lá dentro. Este diagrama de classes funciona como um índice gráfico dos
conteúdos.
Se uma classe tem um comportamento de ciclo de vida complexo, desenho um
diagrama de estados (veja o Capítulo 8) para descrevê-lo. Faço isso se o
comportamento é suficientemente complexo, o que não acontece com muita
freqüência. Interações complicadas entre classes são mais comuns, para as quais eu
projeto diagramas de interação.
Incluo, freqüentemente, algum código importante escrito em um estilo de
programação. Se um algoritmo particularmente complexo estiver envolvido, eu
considerarei a utilização de um diagrama de atividades (veja o Capítulo 9), mas
somente se ele der maior compreensão do que o próprio código.
Se encontro conceitos que estão aparecendo repetidamente, uso padrões (veja
o box abaixo) para capturar as idéias básicas.
Transição
O ponto do desenvolvimento iterativo é fazer todo o processo de desenvolvimento
regularmente, de modo que a equipe de desenvolvimento se acostume a entregar
código acabado. Mas algumas coisas não devem ser feitas cedo. Um exemplo
importante disto é otimização.
A otimização reduz a claridade e a capacidade de extensão do sistema, de modo a
melhorar o desempenho. Este é um compromisso que você necessita fazer - apesar
de tudo, um sistema tem que ser suficientemente rápido para satisfazer os requisitos
dos usuários. Mas a otimização precoce torna o desenvolvimento mais difícil,
portanto isso é algo que precisa ser deixado para o fim.
Durante a transição, não há desenvolvimento para acrescentar funcionalidade, a não
ser que seja pequena e absolutamente essencial. Existe desenvolvimento para
corrigir erros (bugs). Um bom exemplo da fase de transição é o período entre a
versão beta e a versão final do produto.
Padrões
UML diz como expressar um projeto orientado a objetos. Os Padrões focam,
ao contrário, nos resultados do processo: oferecem modelos-exemplo.
Muitas pessoas comentaram que projetos de desenvolvimento têm problemas porque
as pessoas envolvidas não estavam cientes de projetos (designs)
bem conhecidos por pessoas com mais experiência. Os padrões descrevem

UML. ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM-PADRÃO DE MODELAGEM DE


OBJETOS
maneiras comuns de fazer as coisas. Elas são coletadas por pessoas que
identificaram temas repetitivos em projetos (designs). Estas pessoas examinam cada
tema e o descrevem de modo que outras pessoas possam ler o padrão e ver como
aplicá-lo.
Vamos examinar um exemplo. Digamos que você tem alguns objetos rodando em um
processo no seu desktop e eles necessitam comunicar-se com outros objetos rodando
em outro processo. Talvez, este processo também esteja no seu desktop; talvez, ele
esteja em outro lugar. Você não quer que os objetos do seu sistema tenham que se
preocupar em encontrar outros objetos na rede ou executar chamadas de
procedimentos remotos.
O que você pode fazer é criar um objeto proxy dentro do seu processo local para o
objeto remoto, O proxy tem a mesma interface que o objeto remoto. Os seus objetos
locais se comunicam com ele utilizando as mensagens usuais internas do processo. O
proxy, então, é responsável por passar quaisquer mensagens para o objeto real, seja
lá onde ele se localize.
A Figura 2-2 é um diagrama de classes (veja o Capítulo 4) que ilustra a
estrutura do padrão Proxy.
«método»
Sujeitoreal. solicitação()
Sujeito Real E-j / /
11/1
solicita çãoQ solicita çãoQ
Figura 2-2: Estrutura do Padrão de Projeto Proxy
Proxys são, uma técnica comum utilizada em redes e em outros sistemas. As pessoas
têm muita experiência utilizando proxies, no que diz respeito a como eles podem ser
usados, que vantagens eles podem trazer, suas limitações e como implementá-los.
Livros de metodologia como este não discutem este conhecimento, tudo que eles
discutem é como você pode diagramar um proxy. Apesar de ser útil, não é tão útil
quanto a discussão de experiência envolvendo proxys.
No início dos anos noventa, algumas pessoas começaram a capturar estas
experiências. Elas formaram uma comunidade interessada em escrever padrões.
Estas pessoas patrocinaram conferências e produziram vários livros.

UM F.SBOÇO DE £‘ROCESSO DE L)ESENVOLVIMENTO


O livro mais famoso de padrões que surgiu deste grupo é o livro da “Gangue dos
Quatro” (Gamma, Helm, Jonhson e Vlissides 1995), que discute em detalhes 23
padrões de projeto.
Se você quer saber sobre proxies, esta é a fonte. O livro da “Gangue dos Quatro”
desenvolve o assunto em dez páginas, dando detalhes sobre como os objetos
funcionam em conjunto, os benefícios e as limitações do padrão, as variações
comuns e os usos e dicas de implementação para Smalltalk e
C++.
Proxy é um padrão de projeto porque ele descreve uma técnica de projeto. Padrões
também podem existir em outras áreas. Digamos que você está projetando um
sistema para gerenciamento de risco em mercados financeiros. Você precisa
compreender como o valor de uma carteira de ações muda com o tempo. Você pode
fazer isso mantendo um preço para cada ação e marcando o tempo deste preço.
Entretanto, você também quer ser capaz de considerar o risco em situações
hipotéticas (por exemplo: “O que acontecerá se o preço do petróleo cair?”).
Para fazer isso você pode criar um Cenário que contém todo o conjunto de preços
para as ações. Então, você pode ter Cenários separados para os preços da semana
passada, seu melhor palpite para a próxima semana, seu palpite para a próxima
semana se o preço do petróleo cair e assim por diante.
Este padrão Cenário (veja Figura 2-3) é um padrão de análise porque ele
descreve uma parte da modelagem de domínio.
Padrões de análise são valiosos porque eles lhe fornecem um começo melhor quando
você trabalha com um domínio novo. Comecei a coletar padrões de análise porque
estava frustrado com domínios novos. Eu sabia que não era a primeira pessoa que os
modelava, ainda assim, cada vez eu tinha que começar com uma folha de papel em
branco.
O dado interessante sobre padrões de análise é que eles surgem em lugares pouco
comuns. Quando comecei a trabalhar em um projeto para

Figura 2-3: Padrão de Análise Cenário

UIVIL ËSSENCIAL: UM bREVE U.UIA PARA A LINGUACI \1-I’ADRÃO DE MODEIAGEM DE


OBJETOS
fazer análise financeira corporativa, fui muito ajudado por um conjunto de
padrões que eu havia anteriormente descoberto na área da saúde.
Veja Fowler (1997) para aprender mais sobre Cena’rio e outros padrões
de análise.
Um padrão é muito mais que um modelo. Um padrão deve incluir a razão pela qual
ele é do modo que é. Freqüentemente se diz que um padrão é uma solução para um
problema. Um padrão deve esclarecer o problema, explicar por que ele resolve o
problema e também explicar em que circunstâncias ele funciona ou não.
Padrões são importantes porque são o próximo estágio além da compreensão do
básico de uma linguagem ou uma técnica de modelagem. Padrões lhe dão uma série
de soluções e também lhe mostram o que faz um bom modelo e como você deve
proceder para construir um modelo. Eles ensinam através de exemplos.
Quando comecei, eu me perguntava porque tinha que inventar coisas a partir do
nada. Por que eu não possuía manuais para me mostrar como fazer coisas comuns?
A comunidade de padrões está tentando elaborar estes manuais.
Quando Usar Padrões
Sempre que você tentar desenvolver algo em análise, em projeto, em codificação ou
em gerenciamento de projeto, você deveria procurar padrões disponíveis que possam
ajudá-lo.
Onde Encontrar Mais Informação
Os livros que mencionei anteriormente são um bom ponto de partida na área de
padrões. Para ir mais adiante, dê uma olhada na hornepage de padrões:
<http://www.hillsite.net/patterns>. Ela lhe dá uma boa informação atualizada sobre a
situação do mundo de padrões.
Quando_Usar Desenvolvimento Iterativo
Você deve usar desenvolvimento iterativo somente em projetos que você quer
que tenham sucesso.
Talvez, isto não seja muito sério, mas à medida que envelheço me torno mais
agressivo sobre a utilização de desenvolvimento iterativo. Bem feita, é uma técnica
essencial, que você pode usar para expor cedo os riscos e para obter melhor controle
do desenvolvimento. Não é o mesmo do que não ter gerenciamento (embora, para
ser justo, devo salientar que algumas pessoas o usaram desta maneira).
Desenvolvimento iterativo precisa ser bem planejado. Mas é um método sólido, e
cada livro de desenvolvimento OO encoraja a sua utilização - por boas razões.

48 7 UM IiSBOÇO DE I’ROCESSO DE DESENVOLVIMENTO


Onde Encontrar Mais Informação
Existem vários livros sobre processo. Os meus dois favoritos são:
• Cockburn (1998), porque ele faz um bom trabalho focalizando os assuntos-chave
em um livro curto. Portanto, recomendo-o como um primeiro
livro de gerenciamento de projeto 00.
• McConnell (1996), pois ele dá uma visão profunda das melhores práticas.
Para saber mais sobre o Rational Unified Process:
• Kruchten (1999) é uma visão geral concisa.
• Jacobson, Booch e Rumbaugh (1999) é a fonte para maiores informações.
Se você está interessado em um enfoque mais leve, mas ainda assim disciplinado, dê
uma olhada no “Extreme Programming”, de Kent Beck. Este é um método muito
diferente que enfatiza testes fortes e projeto evolutivo. Veja : http:II
www.armaties.com/extreme.htm e o próximo livro de Kent (Beck 2000).

3
Casos de Uso
Casos de uso são um fenômeno interessante. Por muito tempo, em desenvolvimento
tradicional e orientado a objetos, as pessoas usavam interações típicas para ajudá-
las a compreender os requisitos do sistema. Entretanto, estes cenários eram tratados
muito informalmente - sempre feitos, mas raramente documentados. Ivar Jacobson é
bem conhecido por mudar isso com sua metodologia de objetos e livro associado (o
seu primeiro).
Jacobson levantou a visibilidade de casos de uso até que eles se tornaram um
elemento primário no desenvolvimento e no planejamento do projeto. Desde que
o seu livro foi publicado (1992), a comunidade de objetos adotou casos de uso de
maneira extraordinária. A minha prática certamente melhorou desde que comecei
a utilizar casos de uso desta maneira.
Então, o que é um caso de uso?
Não responderei diretamente a esta pergunta. Em vez disso, vou contornála primeiro
descrevendo cenários.
Um cenário é uma seqüência de passos que descreve uma interação entre
um usuário e um sistema. Portanto, se você tem uma loja on-line baseada na web
(loja virtual), podemos ter um cenário de Compra de um Produto que diria:
O cliente navega no catdlogo de itens e adiciona itens desejados à sua
cesta de compras. Quando o cliente deseja pagar, descreve o endereço de
entrega, fornece as informações do cartao de crédito e confirma a venda.
O sistema verifica a autoriza çao do cartão de crédito e confirma a venda
imediatamente e envia um e-mau logo a seguir.
Este cenário é uma alternativa que pode acontecer. No entanto, a autorização do
cartão de crédito pode falhar, o que seria um outro cenário.
Um caso de uso, então, é um conjunto de cenários amarrados por um objetivo
comum de um usuário. Na situação do exemplo, você teria um caso de uso de

CASOS DE Uso
Compras com uma compra bem-sucedida e uma falha na autorização de cartão de
crédito como dois cenários do caso de uso. Outros caminhos alternativos para
o caso de uso seriam cenários adicionais. Freqüentemente, casos de uso têm um
caso comum em que tudo dá certo, e muitas alternativas que podem incluir situações
de erro e também maneiras alternativas das coisas darem certo.
Um formato simples para capturar um caso de uso consiste na descrição de
seu cenário primário como uma seqüência de passos numerados e as alternativas
como variações naquela seqüência, como mostra a Figura 3-1.
Compra de um Produto
1. O cliente navega pelo catálogo e seleciona itens a serem comprados
2. O cliente vai para o check out
3. O cliente preenche o formulário da remessa (endereço de entrega; opção de
entrega imediata ou em três dias)
4. O sistema apresenta a informação total do faturamento incluindo a remessa, os
preços e os impostos
5. O cliente preenche a informação de cartão de crédito
6. O sistema autoriza a compra
7. O sistema confirma imediatamente a venda
8. O sistema manda uma confirmação para o cliente por e-mail
Alternativa: Falha na Autorização
No item 6, o sistema falha na autorização da compra por crédito
Permite ao cliente resubmeter a informação do cartão de crédito e tentar novamente
Alternativa: Cliente Regular
3a. O sistema mostra a informação atual da remessa, a informação de preço e os
quatro últimos dígitos do cartão de crédito
3b. O cliente pode aceitar ou escrever por cima destas opções por omissão Retorna
para o cenário principal no item 6
Figura 3-1: Exemplo de Texto de Caso de Uso
Existe muita variação no que diz respeito a como você pode descrever os conteúdos
de um caso de uso; UML não especifica padrão algum. Você também pode
acrescentar seções adicionais. Por exemplo, você pode acrescentar uma linha par2
pré-condições, que são coisas que devem ser verdadeiras quando o caso de pode
iniciar. Dê uma olhada nos vários livros que falam em casos de uso e acrescente os
elementos que lhe parecem razoáveis. Não inclua tudo, apenas aquilo que pareça
realmente ajudar.
Um exemplo importante disso é como você divide os casos de uso. Considere outro
cenário para uma compra on-line, uma na qual o comprador já é conhecido do
sistema como cliente regular. Algumas pessoas considerariam isso como sendo um
terceiro cenário, enquanto outras fariam disso um caso de uso separa do. Você
também pode usar uma das associações entre caso de uso, que descre rei mais
adiante.

A quantidade de detalhe que você precisa depende do risco do caso de uso:


quanto maior o risco, mais detalhes você precisa. Geralmente, acredito que entro em
detalhes somente para poucos casos de uso durante a elaboração, e o resto contém
não mais do que o caso de uso da Figura 3-1. Durante as iterações, você acrescenta
mais detalhes à medida do necessário, para implementar o caso de uso. Você não
tem que escrever todos os detalhes; a comunicação verbal é freqüentemente eficaz.
Diagramas de Casos de Uso
Em acréscimo à introdução de casos de uso como elementos básicos no
desenvolvimento do software, Jacobson (1994) também introduziu um diagrama para
a visualização de casos de uso. Esse diagrama é parte da UML.
Muitas pessoas consideram útil este tipo de diagrama. Entretanto, devo salientar que
você não necessita projetar um diagrama para utilizar casos de uso. Um dos projetos
mais eficazes que conheço que utilizou casos de uso registrava cada caso de uso em
um cartão de indexação, classificando os cartões em pilhas, para mostrar o que
precisava ser construído em cada iteração.
\ Figura 3-2 mostra alguns casos de uso para um sistema de comércio.
/
(erente Comercial
to
Caso de Uso

UIVIL IiSSENCIAL: UM IREVE LUIA PARA A LINGUAGEM-1-’ADRAO DE MODELAGEM DE


OBJETOS

Nza3
Sistema de Contabilidade

«include»

Comercial
Generalização

include

Vendedor

Figura 3-2: Diagramas de Casos de Uso

CASOS DE Uso
Atores
Um ator é um papel que um usuário desempenha em relação ao sistema. Existe
quatro atores na Figura 3-2:0 Gerente Comercial, O Analista Comercial, O Vend dor, e
O Sistema de Contabilidade. (Sim, eu sei que seria melhor usar a palav “papel”, mas,
aparentemente, houve um erro na tradução do sueco).
Certamente, existirão muitos analistas comerciais na dada organização, m no que diz
respeito ao sistema, todos desempenham o mesmo papel. Um usuár também pode
desempenhar mais de um papel. Por exemplo, um analista comc cial mais experiente
pode desempenhar o papel de Gerente de Negócio e també ser um analista
comercial regular; um Analista Comercial também pode ser u Vendedor. Quando você
lidar com atores, é importante pensar nos papéis em v de pensar nas pessoas ou em
cargos.
Os atores desempenham os casos de uso. Um único ator pode desempenh
muitos casos de uso; um caso de uso pode ter reciprocamente vários atores d
sempenhando-o. -
Na prática, considero que os atores são mais úteis quando se está proponc os casos
de uso. Em face de um grande sistema, freqüentemente pode ser difí propor uma
lista de casos de uso. Nestas situações, é mais fácil chegar primeiro lista de atores, e,
então, tentar estabelecer os casos de uso para cada ator.
Os atores não precisam ser humanos, embora sejam representados como b necos
humanos nos diagramas de caso de uso. Um ator também pode ser u sistema
externo que necessita de alguma informação do sistema atual. Na Figu 3-2, podemos
ver a necessidade de atualizar as contas para o Sistema de Contal lidade.
Existem diversas variações no que as pessoas mostram como atores. Alg mas
pessoas mostram cada sistema externo ou agente humano no diagrama caso de uso;
outras preferem mostrar o ativador do caso de uso. Prefiro expor agente que obtém
valor do caso de uso, o qual algumas pessoas chamam de at básico.
Entretanto, não levo isso muito longe. Contento-me em ver o sistema de coi
tabilidade obtendo valor, sem tentar identificar o agente humano que obtém valor do
sistema de contabilidade - isso transmitiria modelagem ao próprio sist ma de
contabilidade. Dito isto, você deve sempre contrapor casos de uso co:
atores do sistema, descubra quais são os objetivos reais do usuário e conside
maneiras alternativas para atingir stes objetivos.
Quando estou trabalhando com atores e casos de uso, não me preocupo mui sobre
qual é a associação exata entre eles. Na maioria das vezes, estou realmen
interessado nos casos de uso; os agentes são simplesmente um meio de chegar 1 A
medida que tenho todos os casos de uso, não me preocupo com os detalhes
d( agentes.
Existem algumas situações nas quais vale a pena descobrir os agentes ma
tarde.
• O sistema pode precisar configuração para vários tipos de usuários. Ne te caso,
cada tipo de usuário é um ator e os casos de uso lhe mostram
que cada ator precisa fazer.

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM-PADRÃO DE MODELAGEM DE


OBJETOS 53/
Identificar quem deseja casos de uso pode ajudá-lo a negociar prioridades entre
vários atores.
Alguns casos de uso não têm ligações claras com atores específicos. Considere uma
empresa de serviço público. Evidentemente, um dos seus casos de uso é Enviar
Contas. Entretanto, não é fácil identificar um ator associado. Nenhum papel de
usuário em especial necessita uma conta. A conta é enviada para o cliente, mas elU
não se importaria se isso não acontecesse. O melhor palpite para ator aqui é o
Departamento de Cobrança, no sentido que este obtém valor deste caso de uso. Mas
o Departamento de Cobrança, não está, geralmente, envolvido neste caso de uso.
Esteja ciente de que alguns casos de uso não aparecem como resultado do processo
de considerá-los para cada ator. Se isso acontecer, não se preocupe muito. O
importante é compreender casos de uso e os objetivos dos usuários que eles
atingem.
Uma boa fonte para identificar os casos de uso são os eventos externos. Considere
todos os eventos do mundo externo para os quais você quer reagir. Um dado evento
pode causar uma reação no sistema que não envolve usuários, ou pode causar
principalmente reação dos usuários. A identificação dos acontecimentos para os
quais o sistema necessita reagir vai lhe ajudar a identificar os casos de uso.
Associação entre Casos de Uso
Além das ligações entre atores e casos de uso, você pode mostrar vários tipos de
associações entre os casos de uso.
A associação de inclusão ocorre quando há uma parte do comportamento que é
semelhante em mais de um caso de uso e você não quer ficar copiando a descrição
deste comportamento. Por exemplo, tanto Analisar Riscos quanto Fechar Preço
requerem que você avalie o negócio. Descrever Avaliar Negócio envolve uma boa
quantidade de trabalho escrito, e odeio copiar e colar. Então, crio um caso de uso de
Avaliar Negócio separado para esta situação e me refiro a ele a partir dos casos de
uso originais.
Você utiliza generalização de caso de uso quando tem um que é semelhante
a outro, mas faz um pouco mais. Isso nos dá uma outra maneira de capturar cenários
alternativos.
No nosso exemplo, o caso de uso básico é Contrato Simples. Este é o caso no qual
tudo funciona bem. No entanto, algumas coisas podem atrapalhar o contrato simples
de um negócio. Uma delas é quando o limite é excedido - por exemplo, a quantidade
máxima que a organização comercial estabeleceu para um cliente particular. Aqui
não será desempenhado o comportamento usual associado com o dado caso de uso;
será utilizado um caso de uso alternativo.
Poderíamos colocar esta variação dentro do caso de uso de Registrar Negócio como
uma alternativa, como no caso Compra de Produtos descrito anteriormente.
Entretanto, podemos sentir que esta alternativa é diferente o suficiente para merecer
um caso de uso separado. Neste caso, colocamos a trilha alternativa em um caso de
uso especializado, Negócio com Limites Excedidos, que se refere ao caso de uso-

CASOS DE Uso
base, O caso de uso especializado pode sobre-escrever qualquer parte do caso de
uso-base, embora deva ainda satisfazer o mesmo objetivo essencial do usuário.
Uma terceira associação, que não mostrei na Figura 3-2, é chamada de extensão.
Essencialmente, ela é semelhante à generalização mas possui mais regras. Com esta
construção, o caso de uso estendido pode acrescentar comportamento para o caso
de uso-base, mas este tipo de caso deve declarar certos “pontos de extensão”, e o
caso de uso de extensão pode acrescentar comportamento adicional somente
naqueles pontos de extensão. (Veja Figura 3-3).
Comprar um Produto\ ponto de extensão
(info. de pagamento, info. de entrega)
Figura 3-3: Associação de Extensão
Um caso de uso pode ter vários pontos de extensão, e um caso de uso de extensão
pode aumentar um ou mais destes pontos de extensão. Você indica quais deles são
estendidos na linha entre os casos de uso no diagrama.
Tanto a generalização como a extensão permitem que você divida um caso de uso.
Durante a elaboração, geralmente divido um caso de uso que esteja ficando muito
complicado. Faço a divisão durante o estágio de construção se eu achar que não
posso construir todo um caso de uso em uma iteração. Quando divido, gosto de
fazer, primeiro, o caso normal e, posteriormente, as variações.
Aplique as seguintes regras:
• Use inclusão quando você estiver se repetindo em dois ou mais casos de uso
separados e você deseja evitar a repetição.
• Use generalização quando você estiver descrevendo uma variação em
comportamento normal e você deseja descrevê-la sem muito rigor.
• Use extensão quando você çstiver descrevendo uma variação em comportamento
normal e deseja utilizar a forma mais controlada, explicando os
pontos de extensão no caso de uso-base.
Casos de Uso do Negócio e Casos de Uso do Sistema
Um problema comum que pode acontecer com casos de uso é que, concentrandose
na interação entre um usuário e o sistema, você pode negligenciar situações nas
quais uma mudança no processo de negócio pode ser a melhor maneira de lidar com
o problema.

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM-PADRÃO DE MODELAGEM DE


OBJETOS

Freqüentemente, as pessoas falam sobre casos de uso de sistema e casos de uso de


negócio. Os termos não são precisos, mas o uso geral é que um caso de uso de
sistema é uma interação com o software, enquanto um caso de uso de negócio
examina como a aplicação responde ao cliente ou a um evento externo.
Não gosto de me deter muito neste assunto. Em estágios iniciais da elaboração,
inclino-me mais em relação a casos de uso de negócio, mas acredito que casos de
uso de sistema são mais úteis para o planejamento. Considero útil pensar em casos
de uso de negócio, particularmente para considerar outras maneiras de atingir os
objetivos de um ator.
No meu trabalho, concentro-me primeiro em casos de uso de negócio, e, então,
proponho casos de uso de sistema para satisfazê-los. No final do período de
elaboração, espero ter no mínimo um conjunto de casos de uso de sistema para cada
caso de uso de negócio que eu tenha identificado - no mínimo, para os casos de uso
de negócio que pretendo sustentar na primeira versão a ser entregue.
Quando Utilizar Casos de Uso
Não consigo imaginar, no momento, uma situação na qual não utilizaria casos de uso.
Eles são uma ferramenta essencial na captura de requisitos e no planejamento e
controle de um projeto iterativo. A captura de casos de uso é uma das tarefas básicas
na fase de elaboração.
A maioria dos seus casos de uso será gerada durante esta fase do projeto, mas você
descobrirá mais à medida que avança. Fique alerta a eles o tempo todo. Cada caso
de uso é um requisito em potencial, e até que você tenha capturado um requisito,
você não pode planejar como lidar com ele.
Algumas pessoas, primeiro, listam e discutem os casos de uso, então fazem um
pouco de modelagem. Também descobri que, fazendo modelagem conceitual com os
usuários, ajuda a revelar casos de uso. Portanto, tendo a fazer casos de uso e
modelagem conceitual ao mesmo tempo.
E importante lembrar que casos de uso representam uma visão externa do sistema.
Como tal, não espere nenhuma correlação entre eles e classes dentro do sistema.
Quantos casos de uso você deve ter? Durante um recente painel de discussão da
OOPSLA, vários especialistas em casos de uso disseram que, para um projeto de 10-
pessoas-ano, elas estimam aproximadamente 12 casos de uso. Estes são os casos de
uso-base; cada caso de uso tem muitos cenários e muitas variantes de casos de
usos. Já vi também projetos de tamanho semelhante com mais de uma centena de
casos de uso separados. Se você contar os casos de uso variantes para uma dúzia de
casos de uso, no final os números serão quase os mesmos. Como sempre, use o que
é bom para você.

CASOS DE Uso
Onde Encontrar Mais Informação
Um bom livro curto sobre casos de uso é o de Schneider e Winters (1998). A sua
edição atual usa as associações de UML 1.1 -inclusão e extensão- mas ele permanece
sendo o melhor livro que já vi no que diz respeito à aplicação de casos de uso. Minha
outra recomendação favorita éo conjunto de ensaios de Alistair Cockburn no
endereço da Web: <http://members.aol.com/acockburn>.
O primeiro livro de Ivar Jacobson (1994) é o que deu início a tudo, mas ele está um
pouco ultrapassado hoje em dia, O livro seguinte de Jacobson (1995) ainda é útil pela
sua ênfase em casos de uso de negócio.

4
Diagramas de Classes:
Os Elementos Básicos
A técnica de diagrama de classes tornou-se realmente central nas metodologias
orientadas a objetos. Praticamente, cada metodologia incluiu algumas variações
nesta técnica.
O diagrama de classes não é somente amplamente usado, mas também o
receptáculo para o maior escopo de conceitos de modelagem. Embora os elementos
básicos sejam necessários para todos, os conceitos avançados são utilizados com
menos freqüência. Portanto, dividi a minha exposição sobre diagrama de classes em
duas partes: a básica (este capítulo) e a avançada (veja Capítulo 6).
Um diagrama de classes descreve os tipos de objetos no sistema e os vários
tipos de relacionamento estático que existem entre eles. Há dois tipos principais
de relacionamento estático:
• associações (por exemplo, um cliente pode alugar vários vídeos)
• subtipos (uma enfermeira é um tipo de pessoa)
Diagramas de classes também mostram atributos e operações de uma classe e as
restrições à maneira com que os objetos são conectados.
A Figura 4-1 mostra um diagrama de classes típico.
J

DIAGRAMAS DE CLASSES: Os ELEMENTOS BÁSICOS


Multiplicidade: obrigatória

{classedeCrédito()
==‘ruim”}
Multiplicidade:
opcional

Figura 4-1: Diagrama de Classes

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM-PADRÃO DE MODELAGEM DE


OBJETOS
Perspectivas
Antes de começar a descrever diagrama de classes, gostaria de mencionar uma
sutileza importante no modo com que as pessoas os utilizam. Esta sutileza não é
comumente documentada, mas tem um impacto na maneira que você deve
interpretar um diagrama, pois se refere muito ao que você está descrevendo com o
modelo.
Seguindo a direção de Steve Cook e Jonh Daniels (1994), eu diria que existem três
perspectivas que você pode usar quando projetar diagramas de classes ou, de fato,
qualquer modelo, mas esta classificação é mais perceptível em conexão com
diagramas de classes.
• Conceitual. Se tomar a perspectiva conceitual, você projeta um diagrama que
representa os conceitos no domínio que está sendo estudado. Estes conceitos serão
naturalmente relacionados às classes que vão executá-los, mas freqüentemente não
existe um mapeamento direto. Na verdade, um modelo conceitual deve ser projetado
com pouca ou nenhuma preocupação com o software que poderá implementá-lo,
portanto ele pode ser considerado independente de linguagem. (Cook e Daniels
chamam isso de perspectiva essencial).
• Especificação. Agora estamos examinando o software, mas estamos analisando as
suas interfaces, não a sua implementação. O desenvolvimento orientado a objeto
põe muita ênfase na diferença entre interface e implementação, mas isto é
freqüentemente negligenciado na prática porque a noção de classe em uma
linguagem 00 combina interface com implementação. E uma pena, porque a chave
para uma programação 00 eficaz é programar para uma interface de classe em vez
de fazê-lo para sua implementação. Há uma boa exposição sobre isso no primeiro
capítulo de Gamma, Helm, Jonhson e Vlissides (1995). Você ouve com freqüência a
palavra “tipo” para falar sobre uma interface de uma classe; um tipo pode ter muitas
classes que o implementam e uma classe pode implementar muitos tipos.
• Implementação. Nesta visão, realmente, temos classes e estamos pondo
a implementação às claras. Esta é, provavelmente, a perspectiva usada
com mais freqüência, mas, de várias formas, a perspectiva de especificação
é freqüentemente a melhor para ser usada.
A compreensão das diversas perspectivas é crucial tanto para desenhar como para
ler diagramas de classes. Infelizmente, as linhas entre as perspectivas não são
rígidas, e a maioria dos modeladores não se preocupa em ter suas perspectivas
classificadas quando eles estão modelando. Embora acredite que isso
freqüentemente não afeta muito a perspectiva conceitual e a perspectiva de
especificação, é muito importante separar a perspectiva de especificação e a
perspectiva de implementação.
À medida que continuar abordando diagramas de classes, enfatizarei como
cada elemento da técnica depende muito das perspectivas.
A perspectiva não é parte da UML formal, mas a considero extremamente
aliosa na modelagem e na revisão de modelos. UML pode ser usada com todas

607 DIAGRAMAS DE CLASSES: Os ELEMENTOS BÁSICOS


as três perspectivas. Ligando classes com um estereótipo (veja pág. 81), você po dar
uma indicação da perspectiva. Você marca classes como «classe implementação»
para mostrar a perspectiva de implementação, e com «tipo para as perspectivas de
especificação e conceitual.
Associações
A Figura 4-1 mostra um modelo de classe simples que não surpreenderia ni guém
que trabalha com processamento de pedidos. Descreverei cada uma d peças e
explicarei como você as interpretaria a partir das várias perspectivas.
Começarei com associações. Associações representam relações entre oco
rências de classes (uma pessoa trabalha para uma companhia; a companhia te
vários escritórios).
Da perspectiva conceitual, associações representam relações conceituais ei tre
classes. O diagrama indica que um Pedido tem que vir de um único Cliente que um
Cliente pode fazer vários Pedidos no decorrer do tempo. Cada um desta Pedidos tem
várias Linhas de Pedido, cada uma das quais refere-se a um Úni Produto.
Cada associação tem duas pontas de associação; cada ponta é ligada a un das
classes na associação. Uma ponta pode ser explicitamente rotulada. Este róti lo é
chamado de nome de papel. (As pontas de associação são freqüentemen chamadas
de papéis).
Na Figura 4-1, a ponta da Linha de Pedido da associação com Pedido é ch mada linha
de itein. Se não há rótulo, você nomeia uma ponta com o nome classe-alvo, então,
por exemplo, ponta do Cliente da associação com Pedido ser chamada cliente.
Uma ponta de associação tem multiplicidade, que é uma indicação c
quantos objetos podem participar de um dado relacionamento. Na Figura 4-1,
na ponta do Pedido da associação com o Cliente indica que um Cliente te
muitos Pedidos associados a ele, enquanto “1” na outra ponta indica que um P
lido vem somente de um Cliente.
Geralmente, a multiplicidade indica limites inferiores e superiores para o jetos
participantes. O ““ representa uma variação de O.. infinito: um Cliente n precisa ter
feito um Pedido, e não há limite superior (ao menos na teoria!) para número de
Pedidos que um Cliente pode fazer. O “1” representa 1..1: um Pedic deve ser feito
exatamente por um Cliente.
As multiplicidades mais comuns na prática são 1, * e O.. 1 (você pode ter tan um ou
nenhum). Para uma multiplicidade mais geral, você pode ter um núme:
único (tal como 11 para os jogadores em um time de cricket), uma variação (t como
2. .4 para os jogadores em um jogo de canastra), ou combinações discreti de
números e variações (tal como 2,4 para portas em um carro, antes do apare mento
das minivans).
Dentro da perspectiva de especificação, associações representam respons
bilidades.
A Figura 4-1 implica que existem um ou mais métodos associados ao Clien
que dirão quais pedidos um dado Cliente fez. Similarmente, existem métod

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM-PADRÃO DE MODELAGEM DE


OBJETOS
dentro do Pedido que permitirão saber qual Cliente fez um dado Pedido e quais
Linhas de Item estão em um Pedido.
Se existirem convenções-padrão para nomear estes métodos de consulta, posso,
provavelmente, deduzir de um diagrama como estes métodos são chamados. Po
exemplo, posso ter uma convenção que diz que relacionamentos de valor Único são
implementados com um método que retorna o objeto relacionado, e que relações de
valor múltiplo são implementadas como um iterador em uma coleção de objetos
relacionados.
Trabalhando com uma convenção como esta em lava, por exemplo, posso
inferir a interface seguinte para uma classe de Pedido:
class Pedido {
public Cliente obtemCliente O;
public Set obtemLinhasdePedido
Obviamente, convenções de programação variam de lugar para lugar e não indicarão
todos métodos, mas elas podem ser muito úteis para você se localizar.
Uma associação também implica alguma responsabilidade de atualização. Deve
haver um modo de relacionar o Pedido ao Cliente. Mais uma vez, os detalhes não são
mostrados; pode ser que você especifique o Cliente no construtor para o Pedido. Ou,
talvez, exista um método adicionarPedido associado ao Cliente. Você pode tornar isso
mais explícito acrescentando operações à caixa da classe, como veremos mais
adiante.
Entretanto, estas responsabilidades não implicam em estrutura de dados. A partir de
um diagrama no nível de especificação, não posso fazer suposições sobre a estrutura
dos dados das classes. Não posso e não devo ser capaz de dizer se uma classe de
Pedido contém um ponteiro para Cliente, ou se a classe do Pedido cumpre com sua
responsabilidade executando algum código de seleção que pergunta a cada Cliente
se ele se refere a um dado Pedido. O diagrama indica somente a interface - nada
mais.
Se isso fosse um modelo de implementação, agora implicaríamos que existem
apontadores em ambas as direções entre as classes associadas. O diagrama diria
agora que o Pedido tem um campo que é uma coleção de ponteiros para Linhas de
Pedido e também tem um ponteiro para o Cliente. Em Java, poderemos inferir algo
como o seguinte:
class Pedido {
private Cliente _cliente;
private Set _Linhasdepedido;
class Cliente {
private Set pedidos;
Neste caso, a maioria das pessoas supõe que também são fornecidas operações de
acesso, mas você só pode ter certeza observando as operações na classe.
Agora, dê uma olhada na Figura 4-2. Ela é basicamente a mesma que a Figura 4-1,
exceto que acrescentei algumas flechas nas linhas de associação. Estas flechas
indicam navegabilidade

DIAGRAMAS DE CLASSES: Os ELEMENTOS BÁSICOS


Em um modelo de especificação, isso indicaria que um Pedido tem a respc sabilidade
de lhe dizer qual é seu cliente, mas um Cliente não tem habilida correspondente para
dizer que Pedidos ele tem. Em vez de responsabilidade métrica, temos agora
responsabilidade somente em uma extremidade da linl Em um diagrama de
implementação, isso indicaria que o Pedido contém um pc teiro para o Cliente, mas o
Cliente não teria um ponteiro para o Pedido.
Como você pode ver, a navegabilidade é uma parte importante dos diagi
mas de implementação e de especificação. Entretanto, não considero qu
navegabilidade tenha algum propósito útil nos diagramas conceituais.
Você verá com freqüência um diagrama conceitual que, primeiro, apar sem
navegabilidades. Então, as navegabilidades são acrescentadas como parte mudança
para perspectivas de especificação e implementação. Observe tambÉ que as
navegabilidades serão provavelmente diferentes entre a especificação
implementação.
Se a navegabilidade existir somente em uma direção, chamamos a assoc ção de
associação unidirecional. Uma associação bidirecional cont navegabilidades nas duas
direções. UML usa as associações sem flechas para i dicar que a navegabilidade é
desconhecida ou que a associação é bidirecional. projeto deve estabelecer um ou
outro significado. Prefiro a semântica “indeterminado” para modelos de especificação
e de implementação.
Associações bidirecionais incluem uma restrição extra, qual seja, as du navegações
são inversas uma da outra, semelhante à noção das funções invers da matemática.
No contexto da Figura 4-2, isso indica que cada Linha de ItE associado com um
Pedido deve ser associado com o Pedido original. De mo semelhante, se você pegar
uma Linha de Pedido e observar as Linhas de It€ para seus Pedidos associados, você
deve ver a Linha de Pedido original na co ção. Esta propriedade é verdadeira para as
três perspectivas.
Há muitas maneiras de nomear associações. Modeladores de dados tradic:
nais gostam de nomear as associações usando uma expressão verbal, de mo que o
relacionamento possa ser usado em uma frase. A maioria dos modeladoi orientados a
objeto prefere usar substantivos para dar nome ao papel de uma outra das pontas,
urna vez que isso corresponde melhor a responsabilidade operações.
Algumas pessoas nomeiam cada associação. Prefiro nomear uma associaç somente
quando assim fazendo melhora à compreensão. Já vi demasiadas asso ações com
nomes como “tem” ou “é relacionado a”. Se não há um nome na pon considero este
nome como sendo o nome da classe ligada, como já mencionei p viamente.
Uma associação representa uma união permanente entre dois objetos. Istc a união
existe durante toda a vida dos objetos, embora as ocorrências que esteja conectadas
possam mudar no tempo (ou, em uma associação opcional, esteja zia). Portanto, uma
referência a parâmetro, ou a criação de um objeto, não impli em associação; estas,
você modela como dependências (veja Capítulos 6 e 7).

UML EssENcIAL: UM BREVE GUIA PARA A LINGUAGEM-I-’ADRÃO DE MODELAGEM DE


OBJETOS

{se Pedido.cliente.ClassedeCrédito é “ruim”, então pedido. éPré-pago deve ser


“Verdadeiro”}

{classe de crédito() ==“ruim”}

Figura 4-2: Diagrama de Classes com Navegabilidades

Pedido
dataRecebida éPré-pago número:String preço: Money
expedir()
encerrar()

Cliente
nome
endereço
classedeCrédito() :String

Navegabilidade

Cliente Pessoal

Cliente Corporativo
nomedecontato classedecrédito limitedecrédito
aviso()
faturamensal(lnterger)

#cartãodeCrédito

linha de Item

*
rep.de venda ••1 Empregado

Linha de Pedido
quantidade: integer preço: Money
estáSatisfeito: Boolean

--fduto

DIA(,RAMAS DE LLASSES: OS IiIEMENTOS I3ÁSJCOS


Atributos
Atributos são muito semelhantes a associações.
No nível conceitual, um atributo nome do Cliente indica que Clientes têm nomes. No
nível de especificação, este atributo indica que um objeto Cliente pode lhe dizer o
seu nome e tem várias maneiras de atribuir valor a nome. No nível de
implementação, o Cliente tem um campo (também chamada de variável de
instância) para armazenar seu nome.
Dependendo do detalhe do diagrama, a notação para um atributo pode mostrar o
nome do atributo, seu tipo e valor por omissão. A sintaxe de UML define: visibilidade
nome: tipo = valor-por-omissão, onde a visibilidade é a mesma para operações,
descritas na próxima seção.
Então, qual é a diferença entre um atributo e uma associação?
Não há diferença na perspectiva conceitual. Um atributo é somente outro tipo de
notação que você pode usar, se parecer conveniente. Geralmente, os atributos têm
valor único. Com freqüência, um diagrama não indica se um atributo é opcional ou
obrigatório, embora você possa fazê-lo colocando a multiplicidade depois do nome do
atributo em colchetes quadrados - por exemplo, data-de-Recebimento LO. .1]: Date;.
A diferença ocorre nos níveis de especificação e de implementação. Atributos indicam
navegabilidade somente do tipo para o atributo. Além disso, indica que o tipo contém
a sua própria cópia do objeto atributo, implicando que qualquer tipo usado como
atributo tem uma semântica de valor em vez de referência.
Abordarei os tipos de valor e de referência mais adiante. No momento, é
melhor pensar nos atributos como classes simples e pequenas, tais como string,
date, inoney e valores primitivos, tais como integer e real.
Operações
Operações são os processos que a classe sabe realizar.
Operações correspondem claramente a métodos em uma classe. No nível de
especificação, as operações correspondem a métodos públicos. Normalmente, você
não mostra as operações que simplesmente manipulam atributos, porque elas
podem ser freqüentemente inferidas. Entretanto, você poderá ter que identificar se
um dado atributo é somente para leitura ou congelado (isto é,o seu valor nunca
muda). No modelo de implementação, você também pode querer mostrar operações
privativas (private) e protegidas (protected).
A sintaxe completa da UML para as operações é
visibilidade nome (lista- de- parâmetros): expressão-de-tipo-de-retorno {string-
depropriedades)
Onde
• visibilidade é + (público), # (protegido), ou - (privado)
• nome é um string

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM-PADRÃO DE MODELAGEM DE


OBJETOS 65 r
• lista-de-parâmetros contém parâmetros separados por vírgulas cuja sintaxe é
semelhante a dos atributos: direção nome: tipo = valor-por-omissão. O único
elemento extra é direção que é utilizado para mostrar se o parâmetro é usado para
input (in), output (out) ou ambos (inout) se não houver valor de direção assume-se
que seja in.
• Expressão-de-tipo-de-retorno é uma lista de tipos de retorno separados por vírgula.
A maioria das pessoas utiliza um tipo de retorno, mas são permitidos múltiplos tipos
de retornos.
• String-de-propriedades indicam propriedades de valor que se aplicam à dada
operação.
Uma operação-exemplo de uma Conta pode ser: + saldoEm (data: Date): Money.
Com modelos conceituais, você não deve usar operações para especificar a interface
de uma classe. Em vez disso, utilize-as para indicar as responsabilidades principais
de cada classe, empregando, talvez, algumas palavras para resumir
responsabilidades no estilo CRC (veja Capítulo 5).
Geralmente, considero útil fazer a distinção entre as operações que mudam o estado
de uma classe das que não fazem. UML define query (consulta) como uma operação
que obtém um valor de uma classe, sem mudar o estado do sistema - em outras
palavras, sem efeitos colaterais. Você pode marcar uma operação como esta com a
restrição {query}. Refiro-me a operações que mudam de estado como modificadores.

Considero útil salientar as querys. As querys podem ser executadas em qualquer


ordem, mas a seqüência de modificadores é mais importante. Costumo evitar
retornar valores dos modificadores, a fim de mantê-los separados.
Outros termos que você encontra, às vezes, são métodos de leitura (getting) e
métodos de modificação (setting). Um método de leitura devolve um valor de um
campo (e não faz mais nada). Um método de modificação põe um valor em um
campo (e não faz mais nada). Do lado de fora, um cliente não deve ser capaz de
dizer se uma qury é um método de leitura ou se um modificador é um método de
modificação. O conhecimento dos métodos de leitura e de modificação é
completamente interno à classe.
Outra distinção é entre operação e método. Uma operação é algo que é executado
em um objeto (o procedimento de chamada), enquanto um método é o corpo do
procedimento. Os dois são diferentes quando você tem polimorfismo. Se você tem
um supertipo com três subtipos, cada um dos quais sobre-escreve a operaçãó “foo”
do supertipo, você tem uma operação e quatro métodos que a implementam.
As pessoas usam, normalmente, operação e método como sinônimos, mas existem
ocasiões em que é útil ser preciso sobre a diferença. Às vezes, as pessoas as
distinguem usando os termos chamada de método ou declaração de método (para a
operação) e corpo de método.
Linguagens têm as suas próprias convenções de denominação. Em C++, operações
são chamadas funções-membro (memberfunctions), enquanto Smalltalk chama
operações de métodos (methods). C++ também utiliza o termo membros de uma
classe para se referir a operações e métodos de uma classe. UML usa o termo
“feature” para se referir tanto a um atributo quanto a uma operação.

\66 7 DIAGRAMAS DE CLASSES: Os ELEMENTOS BÁsIcos


Generalizaçao
Um exemplo típico de generaliza çao envolve clientes, pessoas físicas e jurídicas.
Elas têm diferenças mas também muitas semelhanças. As semelhanças podem ser
colocadas em uma classe geral Clientes (o supertipo), com Cliente Pessoa Física e
Cliente Pessoa Jurídica como subtipos.
Este fenômeno também está sujeito a diferentes interpretações em diferentes níveis
de modelagem. Conceitualmente, podemos dizer que Cliente Pessoa Jurídica é um
subtipo de Cliente se todas as instâncias de Cliente Pessoa Jurídica também são, por
definição, instâncias de Cliente. Um Cliente Pessoa Jurídica é, então, um tipo especial
de Cliente. A idéia-chave é que tudo que dissermos sobre um Cliente - associações,
atributos, operações - também seja verdadeiro para um Cliente Pessoa Jurídica.
Em um modelo de especificação, generalização significa que a interface do
subtipo deve incluir todos os elementos da interface do supertipo. A interface do
subtipo deve seguir a interface do supertipo.
Outra maneira de pensar sobre isso envolve o princípio de substituibilidade. Eu
deveria ser capaz de substituir um Cliente por um Cliente Pessoa Jurídica dentro de
um código que requer um Cliente, e tudo deve funcionar bem. Essencialmente, isso
significa que se você escrever um código assumindo que tem um Cliente, você pode
usar livremente qualquer subtipo de Cliente. O Cliente Pessoa Jurídica deve
responder a certos comandos diferentemente de outro Cliente (usando
polimorfismo), mas o chamador não deveria se preocupar com a diferença.
Generalização na perspectiva de implementação é associada à herança nas
linguagens de programação. A subclasse herda todos os métodos e campos da
superclasse e pode sobre-escrever métodos herdados.
O ponto-chave aqui é a diferença entre a generalização na perspectiva de
especificação (subtipagem, ou herança-interface) da perspectiva de implementação
(subclasse, ou herança-implementação). Subclasse é uma maneira de implementar
subtipagem. Você pode também implementar subtipagem por delegação - de fato,
muitos dos padrões descritos em Gamma, Heim, Johnson e Vlissides (1995) são sobre
maneiras de ter duas classes com interfaces semelhantes, sem utilizar subclasse.
Você também pode dar uma olhada em Fowler (1997) para outras idéias sobre
implementação para subtipagem.
Com qualquer uma destas formas de Generalização, você deve sempre garantir que
a generalização conceitual também se aplica. Já percebi que se você não fizer isso,
você pode ter problemas porque a generalização não é estável quando você for
fazer, posteriormente, modificações.
As vezes, você se depara com casos nos quais um subtipo tem a mesma interface
que o seu supertipo, mas o subtipo implementa operações de maneira diferente. Se
isso acontecer, você pode escolher não mostrar o subtipo no diagrama da
perspectiva de especificação. Geralmente, mostro subtipos se os usuários da classe
consideram interessante que tipos devam existir, mas não mostro se os subtipos são
vários somente devido a razões internas de implementação.

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM-PADRÃO DE MODELAGEM DE


OBJETOS
Regras de Restrição
Muito do que você está fazendo quando desenha diagramas de classes é indicar
restrições.
A Figura 4-2 indica que um Pedido pode ser feito apenas por um Unico Cliente. O
diagrama também implica que cada Linha de Item é considerada separadamente:
você diz 40 troços marrons, 40 troços azuis e 40 troços vermelhos, não 40 troços
vermelhos, azuis e marrons. Mais adiante, o diagrama diz que Cliente Pessoa Jurídica
tem limite de crédito mas Cliente Pessoa Física, não.
As construções básicas de associação, de atributo e de generalização fazem muito
para especificar restrições importantes, mas elas não podem indicar cada restrição.
Estas restrições ainda precisam ser capturadas; o diagrama de classes é um bom
lugar para fazê-lo.
UML permite que você use qualquer coisa para descrever restrições. A única regra é
que você as coloque entre chaves ({). Gosto de usar um Inglês informal, enfatizando
facilidade de leitura. UML também fornece uma Linguagem Formal de Restrições de
Objetos (OCL - Object Constraint Language); ver Warmer e Kleppe (1998).
De modo ideal, regras devem ser implementadas como asserções na sua linguagem
de programação. Estas correspondem à noção de invariantes de Projeto
por Contrato (ver o box abaixo).
Projeto por Contrato (Design by Contract)
Projeto por Contrato é uma técnica de projeto desenvolvida por Bertrand Meyer. Esta
técnica é uma característica central da linguagem Eiffel que ele desenvolveu.
Entretanto, Projeto por Contrato não é específico de Fiffel; é uma técnica valiosa que
pode ser utilizada com qualquer linguagem de programação.
No centro do projeto por contrato, está a asserção. Uma asserção é uma declaração
booleana que não deveria nunca ser falsa e, portanto, só será falsa devido a um erro
(bug). Tipicamente, asserções são checadas apenas durante a depuração (debug) e
não são checadas durante a execução em produção. De fato, um programa não deve
assumir que as asserções estão sendo checadas.
Projeto por contrato usa três tipos de asserções: pós-condições, pré-condições e
invariantes.
Pré-condições e pós-condições se aplicam a operações. Uma pós-condição é uma
declaração de como o mundo deveria parecer depois da execução de uma operação.
Por exemplo, se definirmos a operação “raiz quadrada” em um número, a pós-
condição assumiria a forma input=result*result, onde resutt é a saída e input é o
valor de entrada. A pós-condição é uma forma útil de dizer o que fazemos sem dizer
como fazemos isso - em outras palavras, a maneira de separar a interface da
implementação.

DIAGRAMAS DE CLASSES: Os ELEMENTOS BÁSICOS


Uma pré-condição é uma declaração de como o mundo deveria ser antes da
execução de uma operação. Talvez, definiremos pré-condição para a operação “raiz
quadrada” de input > = O. Tal pré-condição diz que é um erro executar “raiz
quadrada” em um número negativo e que a conseqüência disso é indefinida.
Em um primeiro instante, isso parece ser uma má idéia, pois deveríamos colocar uma
verificação em algum lugar para assegurar que a “raiz quadrada” é executada
adequadamente. A importante pergunta é quem é responsável por fazer isso.
A pré-condição torna explícito que o chamador é responsável pela verificação. Sem
esta explícita declaração de responsabilidades, podemos obter ou pouca verificação
(pois ambos os grupos assumem que o outro é responsável) ou muita verificação
(ambos os grupos verificam). Muita verificação não é bom, pois ela conduz a muitos
códigos de verificação duplicados, que pode significar acréscimo da complexidade do
programa. Ser explícito a respeito de quem é responsável ajuda a reduzir a
complexidade. O perigo do chamador esquecer de verificar é reduzido pelo fato de
que asserções são normalmente verificadas durante os testes e debugging.
Das definições de pré-condição e pós-condição, podemos ter uma forte definição do
termo exceção, que ocorre quando uma operação é executada como sua pré-
condição satisfeita, no entanto, ela não pode retornar com sua pós-condição
satisfeita.
Uma invariante é uma asserção a respeito de uma classe. Por exemplo, uma classe
de Conta pode ter uma invariante que diz que balance
sum(entries.amountQ). A invariante é “sempre” verdadeira para todas as instâncias
da classe. Neste caso, “sempre” significa “qualquer hora que o objeto estiver
disponível para ter uma operação executada nele”.
Na essência, significa que a invariante é adicionada a pré-condições e pós-condições
associadas a todas as operações de determinada classe. A invariante pode se tornar
falsa durante a execução de um método, mas deveria retornar a ser verdadeira no
momento em que outro objeto possa fazer qualquer coisa para o receptor.
Asserções podem representar um papel único em subclassificação.
Um dos perigos do polimorfismo é que você pode redefinir uma operação de
subclasse tornando-a inconsistente com as operações da superclasse. Asserções não
deixam que você faça isso. As invariantes e as pós-condições de uma classe devem
se aplicar a todas as subclasses. A subclasse pode escolher em fortalecer estas
asserções, mas ela não consegue enfraquecê-las. A pré-condição, por outro lado, não
pode ser fortalecida mas pode ser enfraquecida.
Parece estranho primeiramente, mas é importante para permitir ligação (binding)
dinâmica. Você sempre deverá ser capaz de tratar um objeto de subclasse como se
ele fosse uma instância da superclasse (pelo princípio da substituibilidade). Se uma
subclasse fortalecer sua pré-condição, então uma operação de superclasse pode
falhar quando aplicada à subclasse.

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM-PADRÃO DE MODELAGEM DE


OBJETOS
Essencialmente, asserções podem apenas aumentar a responsabilidade da
subclasse. Pré-condições são expressões que passam a responsabilidade para o
chamador, você aumenta as responsabilidades de uma classe pelo enfraquecimento
de uma pré-condição. Na prática, tudo isso permite um melhor controle de
subclasses e ajuda a assegurar que as subclasses se comportem adequadamente.
Em condições ideais, asserções deveriam ser inclusas nos códigos como sendo parte
da interface de definição. Compiladores deveriam ser capazes de acionar as
verificações de asserção para debugging e removê-las para uso de produção. Vários
estágios de verificações de asserção podem ser usados. Pré-condições lhe oferecem
frequentemente, as melhores chances de encontrar erros pela menor quantidade de
overhead de processamento.
Quando Usar Projeto por Contrato
Projeto por Contrato é uma técnica valiosa na construção de interfaces.
Apenas Eiffel sustenta asserções como sendo parte de sua linguagem, mas Eiffel é,
infelizmente, uma linguagem não muito utilizada. É direto, se complicado, adicionar
mecanismos a outras linguagens para sustentar algumas asserções.
UML não fala muito sobre asserções, mas você pode utilizá-las sem problema algum.
Invariantes são equivalentes a regras de restrição nos diagramas de classes, e você
deve utilizá-las sempre que possível. Pré e pós-condições de operação devem ser
documentadas junto às definições da operação.
Onde Encontrar Mais Informação
O livro de Meyer ( 1997) é um trabalho clássico (embora agora muito grande) sobre
projeto 00 que trata de asserções. Kim Walden e Jean- Mark Nerson (1995) bem como
Steve Cook e John Daniels (1994) utilizaram extensiva- mente projeto por contrato
em seus livros.
Você pode obter maiores informações sobre ISE (a companhia de
Bertrand Meyer) em www. eiffel. com.
Quando Utilizar Diagramas de Classes
Diagramas de classes são a base de quase todas as metodologias 00, portanto você
irá utilizá-los o tempo todo. Este capítulo cobre os conceitos básicos; o Capítulo 6
discute muitos dos conceitos avançados.

DIAGRAMAS DE CLASSES: Os ELEMENTOS BÁSICOS


O problema com diagramas de classes é que eles são muito ricos e podem ser
complexos de se usar. Você tem aqui algumas dicas.
• Não tente utilizar todas as notações que você dispõe. Comece com o material
simples deste capítulo: classes, associações, atributos, generalização e restrições.
Introduza outras notações do Capítulo 6 somente quando você necessitar.
• Ajuste a perspectiva na qual você está desenhando os modelos para o
estágio do projeto.
- Se você estiver fazendo análise, desenhe modelos conceituais.
- Quando você estiver trabalhando com software, concentre-se nos modelos de
especificação.
- Desenhe modelos de implementação somente quando você estiver ilustrando uma
particular técnica de implementação.
• Não desenhe modelos para tudo; em vez disso, concentre-se nas áreas principais. E
melhor ter poucos diagramas que você usa e mantém
atualizados do que ter muitos modelos esquecidos e obsoletos.
O maior perigo com diagrama de classes é que você pode ficar detido em detalhes
de implementação muito facilmente. Para combater isso, concentre-se nas
perspectivas conceituais e de especificação. Se você se deparar com estes
problemas, verá que cartões CRC (veja página 78) podem ser extremamente úteis.
Onde Encontrar Mais Informação
Todos os livros sobre UML que mencionei no Capítulo 1 abordam mais
detalhadamente diagrama de classes.
Dos livros mais antigos, gosto de Cook e Daniels (1994) pela maneira como
eles tratam de perspectivas e pelo formalismo que introduzem.

5
Diagramas de Interação
Diagramas de interação são modelos que descrevem como grupos de objetos
colaboram em algum comportamento.
Tipicamente, um diagrama de interação captura o comportamento de um
único caso de uso. O diagrama mostra vários objetos e as mensagens que são
passadas entre estes objetos em um caso de uso.
Ilustrarei o enfoque com um simples caso de uso que exibe o seguinte
comportamento:
• Uma janela de Entrada de Pedido envia uma mensagem “preparar” para um
Pedido.
• O Pedido, então, envia “preparar” para cada Linha de Pedido do Pedido.
• Cada Linha do Pedido verifica o item de Estoque dado.
- Se esta verificação retornar “verdadeira”, a Linha de Pedido subtrai a quantidade
apropriada do estoque e cria um item de entrega.
- Se a quantidade de Estoque caiu abaixo do nível de pedido, este item de Estoque
solicita uma ordem de reposição.
Existem dois tipos de diagramas de interação: diagramas de seqüência e diagramas
de colaboração.

DIAGRAMAS DE INTERAÇÃO
Diagramas de Seqüência
Em um diagrama de seqüência, um objeto é mostrado como uma caixa na
parte superior de uma linha tracejada vertical (veja Figura 5-1).
uma Janela de P dd uma Linha um tem de
[rada de Pedido 1e 1 O de Pedido Estoque
Objeto

prepare O

* prepare O

temEstoque:= verificar o

Condição

precisaReposiçâo:
precisaRepor ()

Autochamada

Remoção

Criação

Figura 5-1: Diagrama de Seqüência

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM-PADRÃO DE MODELAGEM DE


OEJETOS
A linha vertical é chamada de linha de vida do objeto. A linha de vida representa a
vida do objeto durante a interação. Esta forma tornou-se popular inicial-
mente com Jacobson.
Cada mensagem é representada por uma flecha entre as linhas de vida de dois
objetos. A ordem na qual estas mensagens ocorrem é mostrada da parte superior à
parte inferior da página. Cada mensagem é rotulada, no mínimo, com o nome da
mensagem; você também pode incluir os argumentos e alguma informação de
controle. Você pode ainda mostrar uma autochamada, uma mensagem que um
objeto manda para si mesmo, enviando a flecha de mensagem de volta para a
mesma linha de vida.
Para mostrar quando um objeto está ativo (para uma interação procedimental,
• isso indicaria que o procedimento está na pilha do processador), você inclui uma
caixa de ativação. Você pode omitir caixas de ativação; isso facilita o desenho do
diagrama, mas o torna mais difícil de ser compreendido.
Duas informações de controle são valiosas.
Primeiro, existe a condição, que indica quando a mensagem é enviada (por
exemplo, [precisa reposição]). A mensagem é enviada somente se a condição for
• verdadeira. Condições são úteis em casos simples como este, mas para casos mais
complicados, prefiro projetar diagramas de seqüência separados para cada caso.
O segundo marcador de controle útil é o marcador de iteração, que mostra que a
mensagem é enviada várias vezes para múltiplos objetos receptores, como
aconteceria quando você estivesse fazendo iteração em uma coleção. Você pode
mostrar a base da iteração entre colchetes, tal como *[para todas as linhas de
pedido].
A Figura 5-1 inclui um retorno, que indica o retorno de uma mensagem, não uma
nova mensagem. O retorno difere das mensagens regulares pois a linha é tracejada.
Algumas pessoas desenham um retorno para cada mensagem, mas acredito que isso
torna o diagrama confuso, então os desenho somente quando sinto que eles podem
acrescentar clareza ao diagrama. Só utilizei um retorno na Figura 5-1 para
demonstrar a notação; se você remover o retorno, acredito que o diagrama continua
tão claro como antes. Isto é um bom teste.
Como você pode ver, a Figura 5-1 é muito simples e tem um apelo visual
imediato, o que é sua grande qualidade.
Uma das coisas mais difíceis de compreender em um programa orientado a objetos é
o fluxo global de controle. Um bom projeto tem muitos pequenos métodos em classes
diferentes, e, às vezes, pode ser difícil entender a seqüência global do
comportamento pretendido. Você pode terminar examinando o código tentando
encontrar o programa. Isto é particularmente verdadeiro para as pessoas sem
experiência com objetos. Os diagramas de seqüência ajudam a entender esta
seqüência.
Esses diagramas também são valiosos para processos concorrentes.
Na Figura 5-2, vemos alguns objetos que estão verificando uma transação
bancária.
Quando uma Transação é gerada, ela cria um Coordenador de Transação
para coordenar a verificação da Transação. Este coordenador cria alguns objetos
J (neste caso, dois) Verificadores de Transação, cada um dos quais é responsável

DIAGRAMAS DE INTERAÇÃO
Mensagem Assíncrona
new
Ativação
Autochamada
Figura 5-2: Processos Concorrentes e Ativações
por uma verificação particular. Este processo facilitaria acrescentar diferentes
processos de verificação, porque cada verificador é chamado de maneira assíncrona
e procede em paralelo.
Quando um Verificador de Transação termina, ele notifica o Coordenador de
Transação. O coordenador olha para ver se todos os verificadores retornaram. Se não
o fizeram, o coordenador não faz nada. Se todos eles retornaram e se todos foram
bem-sucedidos, como neste caso, o coordenador notifica a Transação que tudo está
bem.
As meias cabeças de flecha indicam uma mensagem assíncrona. Uma mensagem
assíncrona não bloqueia o chamador, de modo que ele pode continuar o
seu próprio processo. Uma mensagem assíncrona pode fazer uma de três coisas:
1. Criar um novo Thread (de execução), caso no qual ele liga-se ao topo de uma
ativação
2. Criar um novo objeto
3. Comunicar-se com um Thread que já está funcionando.

sejaVálida

tudo
realizado?

objeto se autodestrói

Remoção de objeto é mostrada com um grande X. Objetos podem se autodestruir


(mostrado na Figura 5-2), ou eles podem ser destruídos por outra mensagem (veja
Figura 5-3).
A Figura 5-2 e a Figura 5-3 mostram dois dos cenários do caso de uso de “verificação
de transação”. Projetei cada cenário separadamente. Existem técnicas para combinar
a lógica condicional para um único diagrama, mas prefiro não usálas, porque elas
tornam o diagrama muito complicado.
Na Figura 5-3, apliquei uma técnica muito útil: inseri descrições textuais do que está
acontecendo do lado esquerdo do diagrama de seqüência. Isso envolve o
alinhamento de cada bloco de texto com a mensagem apropriada dentro do
diagrama. Isso ajuda a compreensão do diagrama, embora a custo de algum trabalho
extra. Faço isso para documentos que vou guardar mas não para esboços de quadro
branco.

ela cria um coordenador para


gerenciar as

Se uma dada verificação falhar, o coordenador elimina todos os outros verificadores


que ainda estão funcionando
...e avisa a
transação que ela não é válida.

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM-PADRÃO DE MODELAGEM DE


OBJETOS

new
Quando __
uma transação uma Transação é criada...

O coordenador cria uma série de


verificadores,
um para cada tipo de verificação. Estes verificadores realizam suas verificações como
processos separados.

deletando outro objeto

Figura 5-3: Diagrama de Seqüência: Verificação de Falha

DIAC,RAMAS DE INTERAÇÃO
Diagramas de Colaboração
A segunda forma de diagrama de interação é o diagrama de colaboração.
Dentro de um diagrama de colaboração, os objetos são mostrados como ícones.
Como em um diagrama de seqüência, flechas indicam as mensagens enviadas
dentro de um dado caso de uso. Desta vez, entretanto, a seqüência é indicada pela
numeração das mensagens.
A numeração de mensagem torna mais difícil ver a seqüência do que a colocação das
linhas de mensagem de cima para baixo na página. Por outro lado, o layout espacial
permite que você mostre outras coisas mais facilmente. Você pode mostrar como os
objetos são ligados entre si e utilizar o layout de diagramas de classes ou de pacotes
para esboçar colaborações entre objetos.
Você pode usar um dos diversos esquemas de numeração para diagramas
de colaboração. O mais simples é ilustrado na Figura 5-4. Outro enfoque envolve
um esquema de numeração decimal, visto na Figura 5-5.
[:Janela rad_ Objeto
4 1: prepare() Mensagem
jfdido 1 Número de Sequência
2*[para todas as linhas 5: precisaReposição:=precisaRepo
de pedido]:prepare()
3: temEstoque := verificar() Autodelegaçao
4: [temEstoque] := remover()
linha Macallan:Linha de Pedido estoque acaan:
6: [precisaReposição]: new

1 7: [temEstoque]: new
tem de Entrega

[ : tem de Reposição

Figura 5-4: Diagrama de Colaboração com Numeração Simples


Antigamente, a maioria das pessoas utilizava o esquema de numeração simples. UML
usa o esquema decimal porque ele torna claro qual operação está chamando outra
operação, embora isso dificulte a visão da seqüência completa.

Independente do esquema de numeração a ser usado, você pode acrescentar o


mesmo tipo de informação de controle mostrado em um diagrama de seqüência.
Na Figura 5-4 e na Figura 5-5, você pode ver as várias formas do esquema de
nomeação de objetos de UML, Noineobjeto: NorneClasse, na qual tanto o nome do
objeto quanto o nome da classe podem ser omitidos. Observe que se omitir o nome
do objeto, você deve manter os dois pontos de modo que fique claro que o que
aparece é nome da classe e não o nome do objeto. Por exemplo, o nome “linha
Macalian: Linha de Pedido” indica uma ocorrência de Linha de Pedido chamada linha
Macallan* (este é um pedido que eu, particularmente, apreciaria). Tenho a tendência
de nomear objetos no estilo Smaltalk a ser usado nos diagramas de seqüência. (Este
esquema é também UML porque “umObjeto” é um bom nome para um bbjeto).

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM-PADRÃO DE MODELAGEM DE


OBJETOS

Número de Seqüência

de pedido]:prepare()

1 .1.2.1: precisaReposição precisaRepor()

Figura 5-5: Diagrama de Colaboração com Numeração Decimal

Comparando Diagramas de Seqüência com Diagramas de Colaboração

Diferentes desenvolvedores têm preferências diferentes no que diz respeito à escolha


da forma de diagrama de interação a ser usado. Geralmente, prefiro o dia-

* N. de T.: Macaliari é um uísque.

DIAGRAMAS DE INTERAÇAO
grama de seqüência porque gosto da ênfase que ele dá à seqüência; é fácil ver a
ordem que as coisas acontecem. Outros preferem diagrama de colaboração porque
podem usar o layout para indicar como os objetos são estaticamente conectados.
Uma das características principais de qualquer forma de um diagrama de interação é
sua simplicidade. Você pode ver facilmente as mensagens observando o diagrama.
Entretanto, se você tentar representar algo além de um processo seqüencial único
sem muito comportamento condicional ou iterativo, a técnica deixa de funcionar tão
bem.
Um dos problemas com diagramas de interação é que seu uso pode ser inadequado
na exploração de alternativas. Ao experimentar alternativas, você tem muito trabalho
apagando e refazendo diagramas. Como resultado, acredito que cartões CRC (veja o
box abaixo) são muito úteis para exploração de comportamento.
Cartões CRC
No final da década de oitenta, um dos maiores centros de tecnologia de objetos
estava nos laboratórios de pesquisa da Tektronix, Portland, Oregon. Estes laboratórios
tinham alguns dos mais importantes usuários de Smalltalk, e muitas idéias-chave
sobre tecnologia de objetos foram desenvolvidas lá. Dois renomados programadores
de Smalltalk que trabalhavam lá eram Ward Cunningham e Kent Beck.
Cunningham e Beck estavam e estão preocupados em como ensinar o profundo
conhecimento de Smalltalk que eles adquiriram. Da questão de como ensinar objetos
surgiu a simples técnica de cartões Class-ResponsibiityCollaboration (CRC).
Em vez de utilizar diagramas para desenvolver modelos, como a maioria dos
metodologistas fazia, Ward representava classes em cartões de índice 4” x 6”. Em
vez de indicar atributos e métodos nos cartões, ele escrevia responsabilidades.
Então, o que é uma responsabilidade? E uma descrição de alto nível do propósito de
uma classe. A idéia é tentar fugir de uma descrição de dados e processo e, em vez
disso, capturar o propósito da classe em poucas sentenças. A escolha de um cartão é
deliberada. Você não pode escrever mais do que cabe em seu exíguo espaço. (veja
Figura 5-6).
O segundo C refere-se aos colaboradores. Estes representam as outras classes com
as quais esta classe precisa trabalhar. Isto dá alguma idéia das
ligações entre classes - ainda de alto nível.
Um dos maiores benefícios dos cartões CRC é que eles encorajam animadas
discussões entre os desenvolvedores. Quando você está trabalhando com um caso
de uso para ver como as classes o implementarão, os diagramas de interação deste
capítulo podem ser lentos de se projetar. Freqüentemente, você precisa considerar
alternativas, e com diagramas, perde-se muito tempo apagando e refazendo as
alternativas. Com cartões

UIVIL DssENUAL: UM DREVE ,U1A I’ARA A LINGUAGEM-t’ADRAO DE IVIODELAGEM DE


OBJETOS
Nome de Classe

Figura 5-6: Cartão Classe-Responsabilidade-Colaboração (CRC)


CRC,você modela a interação pegando cartões e movendo-os. Isso permite
que se considere rapidamente diversas alternativas.
À medida que faz isso, você forma idéias sobre responsabilidades e as escreve nos
cartões. E importante pensar sobre responsabilidades porque você deixa de
considerar classes como simples portadores de dados e ajuda os membros da equipe
compreenderem o comportamento de cada classe em um nível mais elevado. Uma
responsabilidade pode corresponder a uma operação, a um atributo, ou (mais
provavelmente) a um aglomerado indeterminado de atributos e operações.
Um erro comuni que vejo as pessoas cometerem e gerar longas listas de
responsabilidades de baixo nível. Isto é realmente um erro. As responsabilidades
devem caber facilmente em um cartão. Eu questionaria qualquer cartão com mais de
três responsabilidades. Você deve questionar se a classe deve ser dividida ou se as
responsabilidades seriam mais bem formuladas se englobadas em declarações de
nível mais alto.
Quando Utilizar Cartões CRC
Utilize cartões CRC para explorar uma interação entre classes, tipicamente para
mostrar como um cenário é implementado. Uma vez que você elaborou como a
interação funciona, você pode documentá-la com diagramas de interação.
Use responsabilidades para ajudá-lo a sumarizar as responsabilidadeschave de uma
classe. Elas são úteis para enfatizar classes sobrecarregadas.

Responsabilidade Pedido Colaboração Verifique


se os itens estão em estoque Linha de Pedido
Determine o preço
Verifique se o pagamento é válido . Cliente
Despache para o endereço de entrega

DIAGRAMAS DE IN1EKAÇAO
Muitas pessoas salientam a importância de desempenhar papéis; cada
pessoa de uma equipe desempenha o papel de uma ou mais classes. Nunca
vi Ward ou Kent fazerem isso, e acho que isso atrapalha.
Onde Encontrar Mais Informação
Infelizmente, Cunnigham e Beck nunca escreveram um livro sobre CRC, mas você
pode encontrar seu trabalho original (Beck e Cunnigham, 1989) na web
(<http://c2.com/docloopsla89/paper.html>). No geral, o livro que melhor descreve
esta técnica - e, na verdade, a noção completa sobre o uso de responsabilidades - é
Wirfs-Brock (1990). Este é um livro relativamente antigo pelos padrões 00, mas ele
amadureceu bem.
Quando Utilizar Diagramas de Interação
Você deve utilizar diagramas de interação quando quiser observar o comportamento
de vários objetos dentro de um único caso de uso. Esses diagramas dE interação são
bons para mostrar as colaborações entre objetos; eles não são tãc bons para uma
definição precisa de comportamento.
Se você quer observar o comportamento de um simples objeto através dE muitos
casos de uso, use um diagrama de estados (veja Capítulo 8). Se você quei observar o
comportamento através de muitos casos de uso ou de muitas trilhas dc execução
(threads), considere um diagrama de atividades (veja Capítulo 9).

Diagramas de Classes:
Conceitos Avançados

Os conceitos descritos no Capítulo 4 correspondem às notações-chave nos diagramas


de classes. Estes conceitos são os primeiros com os quais você deve familiarizar-se e
compreender, porque eles abrangerão 90% do seu trabalho na construção de
diagramas de classes.
A técnica de diagrama de classes, entretanto, promoveu a criação de dezenas de
notações para conceitos adicionais. Particularmente, não as utilizo o tempo todo, mas
elas são úteis quando apropriadas. Eu as discutirei uma de cada vez e salientarei
alguns dos aspectos das suas utilizações. No entanto, lembre-se que elas são
opcionais, e muitas pessoas obtêm muito valor de diagramas de classes sem utilizar
estes itens adicionais.
Você considerará este capítulo um pouco pesado. A boa nova é que durante
sua primeira passada por este livro, você pode seguramente pular este capítulo e
retomá-lo mais tarde.

Estereótipos

Estereótipos são o núcleo do mecanismo de extensão de UML. Se você achar que


necessita de uma construção de modelagem que não existe em UML, mas é
semelhante a algo que já existe, você trata a sua construção como um estereótipo da
construção UML.
Um exemplo disso é a interface. A interface de UML é uma classe que tem somente
operações públicas sem métodos nem atributos. Isso corresponde a interfaces em
Java, COM e CORBA. Uma vez que este é um tipo especial de classe, ele é definido
como um estereótipo de classe (veja “ Interfaces e Classes Abstratas” na página 89
para maiores detalhes sobre interface.)

827 DIA(,RAMAS DE LLAssEs: LONCEITOS PVANÇADOS


Estereótipos são geralmente mostrados em texto entre «» (por exemplo «interface»),
mas você também pode mostrá-los definindo um ícone para estereotipo. Muitas
extensões para o núcleo de UML podem ser descritas com uma coleção de
estereótipos. Dentro do diagrama de classes, estes podem ser es tereótipos de
classes, associações ou generalizações. Você pode pensá-los com subtipos dos tipos
Classe, Associação e Generalização do Metamodelo.
Notei que pessoas que utilizam UML tendem a confundir restrições com es tereótipos.
Se você marca uma classe como abstrata, isso será uma restrição ou un estereótipo?
Os documentos atuais chamam de restrição, mas você deve estar ci ente de que
existe um divisor difuso no uso dos dois conceitos. Isso não é surpre endente, pois
subtipos são freqüentemente mais restritos do que supertipos.
Um esforço está em andamento na OMG para criar perfis (profiles) UML. Un perfil
toma uma parte da UML e a estende com estereótipos para um propósit particular. A
OMG começou com tais coisas como um perfil de tempo-real e un perfil de
Linguagem de Definição de Interface CORBA (IDL). Tenho certeza qui mais está por
vir.
Diagrama de Objetos
Um diagrama de objetos é um instantâneo dos objetos em um sistema num de
terminado ponto no tempo. Uma vez que ele mostra instâncias em vez de classes um
diagrama de objetos é freqüentemente chamado de diagrama de instâncias.
Você pode usar um diagrama de instâncias para mostrar uma configuraçã de objetos
(Veja Figura 6-1, que mostra um conjunto de classes, e a Figura 6-2 qu mostra um
conjunto associado de objetos). Isso é muito útil quando as conexõe possíveis entre
objetos são complicadas.

1 pai

Figura 6-1: Diagrama de Classes da Estrutura de Composição de Grupo

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM-PADRÃO DE MODELAGEM DE


OBJETOS

Você pode dizer que os elementos da Figura 6-3 são instâncias porque os nomes
estão sublinhados. Cada nome assume a forma nome de instância: nome de classe.
As duas partes do nome são opcionais, então John e :Person são nomes legais. Você
pode, então, mostrar valores para atributos e ligações, como na Figura 6-2.
Você também pode considerar um diagrama de objetos como um diagrama
de colaboração sem mensagens.
Operações e Atributos com Escopo de Classe
UML se refere a uma operação ou a um atributo que se aplica a uma classe, em vez
de uma instância, como tendo escopo de classe. Isso equivale aos membros estáticos
em C++ ou Java e às variáveis e método de classe em Smalltalk. As propriedades do
escopo de Classe são sublinhadas em um diagrama de classes (veja Figura 6-3).

83/

Escopo de
Instância

Pedido

obterNúmero
obterPróximoNúmeroNovo

Figura 6-2: Diagrama de Objetos Mostrando Exemplo de Instâncias de Grupo

Escopo de Classe
Figura 6-3: Notação de Escopo de Classe

DIAGRAMAS DE CLASSES: CONCEITOS AVANÇADOS


Classificação Múltipla e Dinâmica
A classificação se refere ao relacionamento entre um objeto e o seu tipo.
A maioria das metodologias faz certas suposições sobre este tipo de relacionamento -
suposições que também estão presentes na corrente principal nas linguagens de
programação 00. Estas suposições foram questionadas por Jim Odeil, que sentiu que
elas eram muito restritivas para modelagem conceitual. As suposições são de
classificação única e estática de objetos, enquanto OdelI sugere a utilização de
classificação dinâmjca e múltipla de objetos para modelos conceituais.
Em uma classificação única, um objeto pertence a um único tipo, que pode
herdar de supertipos. Na classificação múltipla, um objeto pode ser descrito por
vários tipos, que não estão necessariamente conectados por herança.
Observe que a classificação múltipla é diferente da herança múltipla. A herança
múltipla diz que o tipo pode ter muitos supertipos, mas que um tipo único deve ser
definido para cada objeto. A classificação múltipla permite tipos múltiplos para um
objeto, sem definir um tipo específico para este propósito.
Por exemplo, considere uma pessoa subtipada tanto como homem ou mulher, médico
ou enfermeiro, paciente ou não (veja Figura 6-4). A classificação múltipla permite que
um objeto tenha quaisquer destes tipos designados a ele err qualquer combinação
permitida, sem a necessidade de tipos serem definidos parE todas as combinações
legais.
Se você utiliza classificação múltipla, tem que ter certeza de que deixa clan quais
combinações são legais. Você faz isso rotulando a linha de generalizaçã com um
discriminador, que é uma indicação da base de uma subtipagem. Vário subtipos
podem dividir o mesmo discriminador. Todos os subtipos com o mesmi discriminador
são disjuntos; isto é, qualquer instância do supertipo pode ser um instância de
apenas um dos subtipos dentro daquele discriminador. Uma boa cor venção é ter
todas as subclasses que usam um discriminador conectados a ur triângulo, como
mostrado na Figura 6-4. Alternativamente, você pode ter vária flechas com o mesmo
rótulo textual.

Discriminador

Figura 6-4: Classificação Múltipla

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM-PADRÃO DE MODELAGEM DE


OBJETOS 857
Uma restrição útil é dizer que qualquer instância da superciasse deve ser uma
instância de um dos subtipos de um grupo. (A superciasse é, então, abstrata). Há,
atualmente, uma certa confusão sobre o padrão, mas muitas pessoas usam a
restrição {complete} para mostrar isso.
Para ilustrar, observe as seguintes combinações legais de subtipos no diagrama:
(Feminino, Paciente, Enfermeira); (Masculino, Fisioterapeuta); (Feminino, Paciente); e
(Feminino, Médico, Cirurgião). Observe também que combinações como (Paciente,
Médico) e (Masculino, Médico, Enfermeira) são ilegais. O primeiro conjunto é ilegal
porque não inclui um tipo do Icomplete) discriminador de Sexo; o segundo conjunto é
ilegal porque contém dois tipos do discriminador de papel. A classificação única, por
definição, corresponde a um discriminador único não-rotulado.
Outra questão é se um objeto pode mudar o seu tipo. Por exemplo, quando uma
conta bancária está sem fundos, ela muda substancialmente o seu comportamento.
Especificamente, várias operações (incluindo “retirar” e “fechar”) são sobre-escritas.
A Classificação dinâmica permite que objetos mudem de tipos dentro de uma
estrutura de subtipagem; classificação estática não admite isso. Na classificação
estática, uma separação é feita entre tipos e estados; a classificação dinâmica
combina estas noções.
Deve-se utilizar classificação múltipla e dinâmica? Considero-a útil para modelagem
conceitual. Você pode fazê-la com modelagem de especificação, mas tem que se
sentir à vontade com as técnicas para implementá-la. O problema é implementá-la
de tal maneira que pareça o mesmo que subclassificação da interface, de modo que
um usuário de uma classe não possa dizer qual implementação está sendo usada.
(Veja Fowler 1997 para algumas técnicas). Entretanto, como a maioria destas coisas,
a escolha depende das circunstâncias, e você deve utilizar o seu senso crítico para
fazer a avaliação. A transformação de uma interface múltipla dinâmica em uma
implementação estática simples pode ser muito mais trabalhosa, do que vale a pena.

A Figura 6-5 mostra um exemplo da utilização de classificação dinâmica para


o emprego de uma pessoa, o que, certamente, pode mudar. Isso pode ser apropriado,
mas os subtipos necessitariam de comportamento adicional, em vez de ser

Homem

compIeto}

Figura 6-5: Classificação Dinâmica

DIAGRAMAS DE CLASSES: CONCEITOS AVANÇADOS


somente rótulos. Nestes casos, vale a pena criar, freqüentemente, uma classe se
parada para o emprego e ligar pessoa ao emprego com uma associação. Escrev um
padrão sobre este assunto chamado Modelos de papéis (Role Models); você pod obter
maiores informações sobre este padrão, e outras informações qu suplementam meu
livros “Analysis Patterns”, na minha homepage.
Agregação e Composição
Uma das minhas maiores dificuldades (bêtes noires) na modelagem é a agregação
É fácil explicá-la superficialmente: Agregação é o relacionamento “parte de”. l
como dizer que o carro tem um motor e rodas como suas partes. Isso soa bem, ma
o difícil é considerar qual é a diferença entre agregação e associação.
Antes de UML, as pessoas eram, geralmente, muito vagas sobre o que era agregação
e o que era associação. Vagas ou não, elas sempre eram inconsistentes com as idéias
dos outros. Como resultado, muitos modeladores consideram a agregação
importante, embora por razões diferentes. Então, UML incluiu agregação mas com
quase nenhuma semântica. Como Jim Rumbaugh diz: “Pense nisto comc um placebo
de modelagem” (Rumbaugh, Jacobson e Booch, 1999).
Além da agregação, UML oferece uma variedade mais forte de agregação, chamada
de composição. Na composição, o objeto parte pode pertencer a somen te um todo;
além disso, espera-se que as partes, geralmente, vivam e morram cono todo.
Normalmente, qualquer remoção do todo é considerada como tendo unefeito cascata
nas partes.
Esta remoção em cascata é freqüentemente considerada como uma parte dE
definição da agregação, mas é assumida por qualquer ponta de associação conuma
multiplicidade 1..1; se você quer realmente anular um Cliente, por exemplo você
deve cascatear esta remoção para Pedidos (e, portanto, para Linhas de Pedidos).
A Figura 6-6 mostra exemplos destas construções. As composições para Ponto
indicam que qualquer instância de Ponto pode ser tanto um Polígono quanto un
Composição
1 Agregação

Figura 6-6: Agregação e Composição


UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM-PADRÃO DE MODELAGEM DE
OBJETOS
Círculo, mas não ambos. Uma instância de Estilo, entretanto, pode ser compartilhada
por vários Polígonos e Círculos. Isso implica ainda que a remoção de um Polígono
causaria a remoção de seus Pontos associados, mas não do Estilo associado.
Esta restrição - que um Ponto deve aparecer somente em um Polígono ou
Círculo a cada vez - não pode ser expressa somente com multiplicidades. Isso
também implica que o ponto é um objeto - valor (veja “Objetos de Referência e
Objetos de Valor” na página 92). Você pode adicionar uma multiplicidade 0.1
para um lado composto da associação, mas, geralmente, não ligo para isso. O
losango negro diz tudo o que precisa ser dito.
A Figura 6-7 mostra outra notação para composição. Neste caso, você põe o
Componente dentro do todo. O nome da classe docomponente não está em negrito,
e você o escreve na forma de nome de papel: nome de Classe. Além disso, você põe
a multiplicidade no canto superior direito. Você também pode usar um atributo para
um componente de valor único.

Diferentes notações de composição funcionam em diferentes situações. Existem uma


ou duas outras, embora a variedade de notações de composição oferecida pela UML
seja mais do que suficiente. Observe que estas variações podem ser usadas somente
para composição, não para agregação.
Associações e Atributos Derivados

Associações derivadas e atributos derivados podem ser calculados de outras


associações e atributos, respectivamente, no diagrama de classes. Por exemplo, um
atributo idade de Pessoa pode ser derivado se você souber a data de nascimento da
Pessoa.

Figura 6-7: Notação Alternativa para Composição

DIAGRAMAS DE CLASSES: CONCEITOS A\’ \N.Ç \I

Cada perspectiva traz a sua própria interpretação de características derivadas nos


diagramas de classes. A mais crítica delas tem a ver com a perspectiva de
especificação. Deste ângulo, é importante dar-se conta que características derivadas
indicam uma restrição entre valores, não uma asserção do que é calculado e do que
é armazenado.
A Figura 6-8 mostra uma estrutura hierárquica de contas projetadas de uma
perspectiva de especificação. O modelo utiliza o padrão Com posite (veja Gamma,
Helm, Johnson e Vlissides, 1995).

• Objetos - Lançamento são associados a Detalhes de Contas


• O saldo de uma Conta é calculado como a soma de valores dos lançamentos.
• Os Resumos de Conta são os lançamentos de seus componentes, deter minados
recursivamente.

Uma vez que a Figura 6-8 ilustra um modelo de especificação, ela não afirma qw
Contas não contêm campos para guardar saldos; tal cache pode bem estar presen te,
mas ele é escondido dos clientes da classe Conta.
Posso ilustrar como elementos derivados indicam restrições com a classt
hamada Período de Tempo (veja Figura 6-9)

componentes {hierarchy}

{Saldo = soma de quantidades de lançamentos}


Atributo Derivado

Resumo de Conta

o papel dos lançamentos


é derivado usando
os componentes.lançamentos

Nota

Observe o seguinte.

Figura 6-8: Associações e Atributos Associados

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM-PADRÃO DE MODELAGEM DE


OBJETOS

Período de Tempo
início:Data
fim:Data
/duração:Quantidade
Figura 6-9: Classe Período de Tempo
Se isso é um diagrama de especificação, embora ele sugira que início efim estejam
armazenados e que a duração seja calculada, um programador pode, na verdade,
implementar esta classe de qualquer maneira que mantenha o comportamento
externo. Por exemplo, é perfeitamente aceitável armazenar início e duração e
calcularfi n.
Em diagramas de implementação, valores derivados são valiosos para campos de
anotação que são usados como cache por razões de desempenho. Marcando-os e
registrando a derivação do cache, é mais fácil ver explicitamente o que o cache esta
fazendo. Freqüentemente reforço isso no código utilizando a palavra “cache” no
nome (por exemplo, Cachesaldo).
Em diagramas conceituais, uso marcadores derivados para lembrar-me onde
estas derivações existem e para confirmar com os especialistas do domínio que
existem. Elas podem ser associadas aos seus usos em diagramas de especificação.
Interfaces e Classes Abstratas
Uma das grandes qualidades do desenvolvimento orientado a objetos é que você
pode variar as interfaces de classes, independentemente da implantação. Muito da
força do desenvolvimento orientado a objetos vem desta propriedade. Entretanto,
poucas pessoas fazem bom uso disso.
As linguagens de programação usam uma construção única, a classe, que contém
tanto a interface quanto a implementação. Quando você faz subclassificação, você
herda as duas. Raramente, faz-se uso de interface como uma construção separada, o
que é uma pena.
Uma interface pura, como em Java, é uma classe sem implementação e, portanto,
tem declarações de operações mas não corpos de métodos e não tem campos. As
interfaces são, freqüentemente, declaradas através de classes abstratas. Tais classes
podem oferecer alguma implementacão. mas, com freqüência, elas

\90 DIAGRAMAS DE CLASSES: CONCEITOS AVANÇADOS


são usadas basicamente para declarar uma interface. O ponto é que a
subclassíficação - ou outro mecanismo- proverá a implementação, mas os clientes
nunca verão a implementação, somente a interface.
O editor de texto representado na Figura 6-10 é um exemplo típico disso. Para
permitir que o editor seja independente da plataforma, definimos uma classe Janela
abstrata independente de plataforma. Esta classe não tem corpos de métodos; ela
apenas define uma interface para utilização pelo editor de texto. Subclasses
específicas de plataforma podem ser usadas conforme o desejado.
Janela Windows
próximo()
vo!tao
Janela
{abstract}
______ Janela Xli
de Texto -- PÇOXfl1Q(’ ____________________
L____________J voltaü próx,moo
volta
Janela Macintosh
Dependencia ________________________
práximo()
voltaQ
Figura 6-10: Janela como Classe Abstrata
Se você tem uma classe ou um método abstrato, a convenção de UML é de colocar
em itálico o nome do item abstrato. Você também pode usar a restrição {abstract}.
Uso {abstract} em quadros brancos porque não posso escrever um texto em itálico.
Com uma ferramenta de diagramação, entretanto, prefiro a elegância dos itálicos. A
subclassificação não é a única forma de fazer isso. Java oferece uma construção de
interface, e o compilador certifica-se de que a classe de implementação
ofereça implementações de todas as operações da interface.
Na Figura 6-11, podemos ver InputStream, Datalnput, e DatalnputStream
(definidos no pacote-padrão lavajo). InputStream é uma classe abstrata; Datalnput
é uma interface.
Alguma classe cliente, por exemplo, OrderReader, necessita utilizar a funcionalidade
de Datalnput. A classe DatalnputStream executa tanto as interfaces de
Datalnput quanto de InputStream e é uma subclasse da primeira.

IJML iZSSIiNCIAL: UM BREVE GUIA PARA A LINGUAGEM-PADRAO DE MODELAGEM DE


OBjETOS
«interface»
InputStream Datalnput - - - OrderReader
Generalização
Dependência
DatalnputStream Realização
Figura 6-11: lnterfaces e Classes Abstratas: Um Exemplo de Java
A ligação entre DatalnputStream e Datalnput é o relacionamento de realização.
Realização é deliberadamente semelhante à generalização; ela indica que uma
classe implementa comportamentos especificados por outras. É permitido que uma
classe de implementação implante outra; isso significa que a classe realizadora deve
estar de acordo com a interface, mas não necessita utilizar herança.
Em um modelo de especificação, não há diferença entre realização e subtipagem.
Uma ligação entre Order Reader e Datalnput é uma dependência. Neste caso, a
dependência indica que se a interface de Datalnput mudar, o Order Reader também
pode ter que vir a ser mudado. Um dos objetivos do desenvolvimento é manter as
dependências ao mínimo, de modo a minimizar os efeitos de mudanças (Mais
informações sobre dependências no Capítulo 7).
A Figura 642 mostra uma notação alternativa mais compacta. Aqui, as interfaces são
representadas por pequenos círculos (freqüentemente chamadas de pirulitos -
“lolipops”) saindo das classes que os implementam.
lnterface
Datalnput - - - OrderReader
DatalnputStream
Dependência
IriputStream 6
Figura 6-12: Notação Pirulito para Interfaces

DIAGRAMAS DE CLASSES: CONCETTOS AVANÇADOS


Com pirulitos, não há distinção entre realizar uma interface e subclassificai uma
classe abstrata. Embora a notação seja mais complicada, você não pode mostrar as
operações da interface ou quaisquer relações de generalização entre a interfaces.
Classes abstratas e interfaces são semelhantes, mas existe uma diferença As duas
permitem que você defina uma interface e postergue a sua implementação.
Entretanto, a classe abstrata permite que você acrescentc implementação de algum
método; uma interface obriga a postergação da definição de todos os métodos.
Objetos de Referência e Objetos de Valor
Uma das coisas comuns dita sobre objetos é que eles têm identidade. Isso é verdade,
mas não é tão simples assim. Na prática, você percebe que a identidade importante
para objetos de referência, mas não tão importante para objetos de valor.
Objetos de referência são coisas como Clientes. Aqui, a identidade é muito
importante, porque você geralmente quer que somente um objeto de software
designe um cliente no mundo real. Um objeto que faz referência a um objeto-Clientc
fará isso através de uma referência ou ponteiro; todos os objetos que se referem a
este Cliente vão se referir ao mesmo objeto de softzvare. Desta forma, modificações
em um Cliente ficam disponíveis para todos os usuários do Cliente.
Se você tem duas referências para um Cliente e quer ver se são as mesmas, você,
normalmente, compara suas identidades. Cópias podem ser proibidas; s€ são
permitidas, elas tendem a ser feitas raramente, talvez para propósitos de
arquivamento ou para replicação na rede. Se cópias forem feitas, você necessita
decidir como sincronizar as atualizações do objeto.
Objeto de Valor são coisas como Datas. Você tem, geralmente, múltiplos objetos de
valor representando o mesmo objeto do mundo real. Por exemplo, normal ter
centenas de objetos que designam O1-Jan-99. Estas são todas cópias
intercambiáveis. Novas datas são freqüentemente criadas e destruídas.
Se você tem duas datas e quer ver se elas são a mesma, você não examina a suas
identidades, mas sim os valores que elas armazenam. Isso significa, geralmente, que
você tem que escrever um operador de teste de igualdade, que para datas fará
testes no ano, mês e dia (ou qualquer outra forma de representaçãc interna).
Normalmente, cada objeto que faz referência a 1-jan-99 tem o seu próprio objeto
data dedicado a sso, mas você também pode compartilhar datas.
Objetos de valor devem ser imutáveis (congelados; veja “Frozen” na página 93). Em
outras palavras, você não deve ser capaz de pegar um objeto data de 01. Jan-99 e
mudá-lo para ser 02-Jan-99. Em vez disso, você deve criar um novo objetc 02-Jan-99
e ligá-lo ao primeiro objeto. A razão é que se a data fosse compartilhada, você
atualizaria a data de outro objeto de um modo imprevisível.
Antigamente, a diferença entre objetos de referência e objetos de valor era
mais clara. Objetos de valor eram os valores básicos (built-in) de um sistema dE
tipos. Agora, você pode estender o sistema de tipos com suas próprias classes, poi

UIVIL eSSENCIAL: UM IIREVE ‘,UIA PARA A LINGUAGEM-1ADRAO DE MODELAGEM DE


OBJETOS 93
isso esta questão requer mais reflexão. Em UML, atributos são geralmente usados
para objetos de valor e associações são usadas para objetos de referência. Você
também pode usar composição para objetos de valor.
Não acredito que a distinção entre objetos de valor e de referência seja útil para
modelos conceituais. Isso pode causar confusão com multiplicidades. Se represento
uma ligação para um objeto de valor com uma associação, normalmente marco a
multiplicidade da ponta do usuário de um dado valor como ““, a não ser que exista
uma regra de unicidade, tal como um número de seqüência.
Coleções para Pontas de Associações
de Valores Múltiplos
Uma ponta de valor múltiplo é uma cujo limite superior de multiplicidade é maior que
1 (por exemplo, Uma convenção usual é que pontas de valores múltiplos sejam
consideradas como conjuntos. Não há ordem para os objetos-alvo, e nenhum objeto
aparece no conjunto mais de uma vez. Entretanto, você pode mudar estas
suposições anexando uma restrição.
A restrição (orderedi implica que há uma seqüência de ordem para os objetos-
alvo - isto é, objetos-alvo formam uma lista. Eles podem aparecer somente uma
vez na lista.
Uso a restrição {bag) para indicar que objetos-alvo podem aparecer mais de uma
vez, mas sem ordem. Também utilizo a restrição {hierarchy} para indicar que eles
formam uma hierarquia, e uso a restrição {dag) para indicar um grafo acíclico
orientado (directed acyclic graph).
Frozen
Frozen (Congelado) é uma restrição que UML define como aplicável a um atributo ou
a uma ponta de associação, mas considero-o útil também para classes.
Em uma ponta de associação ou atributo, Frozen indica que o valor daquela ponta de
associação ou atributo não pode mudar durante o tempo de vida do objet&fonte. O
valor deve ser estabelecido na criação do objeto e não pode mudar jamais. O valor
inicial pode ser nulo. Certamente, se isso é verdade quando o objeto for construído,
isso será verdade durante toda a vida do objeto. Isso indica que existe um argumento
para este valor em um construtor e não existe operação que atualize este valor.
Quando aplicado a uma classe, congelado indica que todas as pontas de associação
e todos os atributos associados com aquela classe são congelados.
Congelado nao é o mesmo que Read-Only (somente-de-leitura). Read-Only indica que
um valor não pode ser mudado diretamente, mas pode mudar devido a uma
mudança em algum outro valor. Por exemplo, se uma pessoa tem uma data de
nascimento e uma idade, a idade pode ser somente-de-leitura, mas não pode ser
congelada.

DIAGRAMAS DE CLASSES: LONUEITOS JWANÇADOS


Marco “congelamento” usando a restrição {frozen e eu marco valores somente-de-
leitura com {read-only}. (Observe que Read-Only não é uma propriedade-padrão
UML).
Se você está pensando em “congelar” algo, tenha em mente que as pessoas
cometem erros. Em software, modelamos o que sabemos sobre o mundo, não como
o mundo é. Se estivéssemos modelando como o mundo é, o atributo “data de
nascimento” para um objeto Pessoa seria congelado, mas para a maioria dos casos,
gostaríamos de mudar isso se descobríssemos que um registro anterior estivesse
incorreto.
Classificação e Generalização
Ouço, com freqüência, pessoas falarem sobre subtipagem como o relacionamento “é
um”. Peço que você tome cuidado com este tipo de pensamento. O problema é que a
frase “é um” pode significar coisas diferentes.
Considere as seguintes frases.
1. Shep é um Border Colhe.
2. Um Border Colhe é um Cachorro.
3. Cachorros são Animais.
4. Border Colhe é uma Raça.
5. Cachorro é uma Espécie.
Agora, tente combinar as frases. Se eu combino as frases 1 e 2, tenho “Shep é um
Cachorro”; as frases 2 e 3 juntas dão “Border Colhes são Animais”. A frase 1 mais
2 mais 3 resulta em “Shep é um Animal”. Até agora tudo bem. Agora, tente as
frases 1 e 4: “Shep é uma Raça”. A combinação das frases 2 e 5 é “Um Border
Colhe é uma Espécie”. Estas não são tão boas.
Por que posso combinar algumas destas frases e outras não? A razão é que algumas
são classificação (o objeto Shep é uma instância do tipo Border Colhe), e algumas
são generalizações (o tipo Border Colhe é um subtipo do tipo Cachorro). A
generalização é transitiva; a classificação, não. Posso combinar a classificação
seguida de uma generalização, mas não vice-versa.
Faço questão de mostrar isso para que você desconfie do “é um”. Usá-lo pode levar a
uso inapropriado de subchassificação e à confusão de responsabilidades. Testes
melhores para subtipagem neste caso seriam as frases “Cachorros são tipos de
Animais” e “Cada instância de um Border Colhe é uma instância de Cachorro”.
Associações Qualificadas
A associação qualificada é um equivalente da UML de um conceito de programação
conhecido como vetores associativos, mapeamentos ou dicionários.

A Figura 6-13 mostra uma maneira de representar a associação entre a classe Pedido
e a classe Linha de Pedido usando um qualificador. O qualificador diz que, em
conexão com um Pedido, pode haver uma Linha de Pedido para cada instância de
Produto.
Conceitualmente, este exemplo indica que você não pode ter duas Linhas de Pedido
dentro de um Pedido para o mesmo Produto. A partir de uma perspectiva de
especificação, esta associação qualificada indicaria uma interface ao longo das linhas
de

Class Pedido {
Public LinhadePedido obterLinha_de_Item
(Produto umProduto)
Public void adicionarLinha_de_Item
(Number quantidade,Produto paraProduto);

Isso significa que todo acesso para uma dada Linha de Item requer um Produto como
argumento. A multiplicidade 1 indicaria que deve haver uma Linha de Item para cada
Produto; * indicaria que você pode ter múltiplas Linhas de Pedido por Produto, mas o
acesso às Linhas de Item ainda está indexada por Produto.
A partir de uma perspectiva de implementação, isto sugere o uso de um
arranjo associativo ou uma estrutura de dados semelhante para conter as linhas
de pedido.

Class Pedido {
Private Map _Linha_de_Item;

Na modelagem conceitual, utilizo a construção qualificadora tão somente para


mostrar restrições ao longo das linhas de “Linha de Pedido única por Produto no
Pedido”. Em modelos de especificação, uso isso para mostrar uma interface de busca
por chave (keyed lookup interface). Também posso usar ao mesmo tempo uma
associação qualificada e outra não qualificada, se isso for uma interface apropria-

da.

Uso qualificadores com modelos de implementação para mostrar usos de estruturas


de mapas, dicionários, valores associativos ou estruturas de dados semelhantes.
UML IZsSIiNCIAL: UM BREVE GUIA PARA A LINGUA,EM-PAVRAO Dli IVIUUIiLA(IiM DL UJE
los

o..1

linha de tem

Figura 6-13: Associação Qualificada

967 DIAGRAMAS DE CLASSES: CONCEITOS AVANÇADOS


Classes de Associaçao
Classes de associação permitem que você acrescente atributos, operações e outras
características às associações, como mostrado na Figura 6-14.
empregador a_
Classe ae Associa çao
Emprego

[odo: escopodeDataj

Figura 6-14: Classe de Associação


Você pode ver pelo diagrama que uma Pessoa pode trabalhar para uma única
Companhia. Suponhamos que necessitamos manter informação sobre o período de
tempo que cada funcionário trabalha para cada Companhia.
Podemos fazer isso adicionando o atributo EscopodeDatas à associação. Poderíamos
acrescentar este atributo à classe Pessoa. Mas é realmente um fato sobre a relação
da Pessoa com a companhia, que mudará caso a pessoa mude de empregador.
A Figura 6-15 mostra uma outra maneira para representar esta informação:
faça de Emprego uma classe plena (observe como as multiplicidades foram movidas
correspondentemente). Neste caso, cada uma das classes na associação original tem
uma ponta de associação de valor único em relação à classe Emprego. A ponta
“Empregador” agora é derivada, embora eu não tenha que mostrá-lo.

Figura 6-15: Promovendo uma Classe de Associação para uma Classe Plena

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM—PADRÃO DE MODELAGEM DE


OHJETOS 97 7
Qual benefício você tem com a classe de associação para compensar a notação extra
que você tem que lembrar? A classe de associação acrescenta uma restrição extra,
em que pode haver somente uma instância de classe de associação entre quaisquer
dois objetos participantes. Sinto a necessidade de um exemplo.
Dê uma olhada nos dois diagramas na Figura 6-16. Estes diagramas têm forma muito
semelhante. Entretanto, poderíamos imaginar uma Pessoa trabalhando para uma
mesma Empresa em diferentes períodos de tempo — isto é, ela sai e volta mais
tarde. Isso significa que a Pessoa poderia ter mais do que uma associação de
Emprego com a mesma Empresa no decorrer do tempo. Em relação às classes Pessoa
e Habilidade, seria difícil ver por que uma Pessoa teria mais do que uma
Competência na mesma Habilidade; na verdade, você, provavelmente, consideraria
isso um erro.
Em UML, somente o último caso é válido. Você pode ter somente uma Competência
para cada combinação de Pessoa e Habilidade.
O diagrama superior na Figura 6-16 não permitiria a uma Pessoa ter mais do que um
Emprego na mesma Empresa. Se você necessita permitir isso, precisa fazer do
Emprego uma classe cheia, no estilo da Figura 6-15.
Antigamente, modeladores faziam várias suposições sobre o significado de uma
classe de associação nestas circunstâncias. Alguns supunham que poderia existir
somente combinações únicas, tal como competência, enquanto outros não
supunham tal restrição.
empregador

Emprego
período:escopodeDatas

Pessoa * * riIidade
Competência
nível
Figura 6-16: Sutilezas de Classes de Associação

DIAGRAMAS DE CLASSES: CONCEITOS AVANÇADOS


Muitas pessoas nem pensaram nisso e podem ter suposto a restrição em alguns
casos e não em outros. Então, quando você utilizar UML, lembre-se de que
esta restrição está sempre presente.
Você encontra, freqüentemente, este tipo de construção com informação histórica,
como no caso de histórico de Empregos. Um padrão útil é o padrão Historic Mapping
(Mapeamento Histórico), descrito no livro de Fowler (1997). Podemos utilizá-lo isso
definindo um estereótipo «history» (veja Figura 6-17).
Figura 6-17: Estereótipo História para Associações
Este modelo indica que uma Pessoa pode trabalhar para uma única Empresa
em um dado momento. Entretanto, com o passar do tempo, a Pessoa pode trabalhar
para várias Companhias. Isso sugere uma interface ao longo das linhas de
Class Pessoa {
II obter empregador atual
Empresa obterEmpregador O;
II empregador em dada data
Empresa obterEmpregador (Date);
Void trocaEmpregador (Empresa novoEmpregador, Date datadinissão);
Void deixaEmpregado (Date dataSaída);
O estereótipo «history» não é parte da UML, mas menciono aqui por duas razões.
Primeiro, ele é uma noção que considerei útil em várias ocasiões na minha carreira
de modelador. Segundo, ele mostra como você pode usar estereótipos para estender
UML.
Classe Parametrizada
Muitas linguagens, mais notadamente C++, têm a noção de classe parametrizada,
ou template (gabarito).
Este conceito é mais obviamente útil para trabalhar com coleções em uma
linguagem fortemente tipada. Desta forma, você pode definir comportamento para
conjuntos em geral definindo uma classe gabarito Conjunto (Set).
class Conjunto <T> {
void insert (T newElement);
void remove (T anElement);

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM—PADRÃO DE MODELAGEM DE


OBJETOS
Tendo feito isso, você pode usar a definição geral para fazer classes de conjunto para
elementos mais específicos.
Conjunto <Empregado> Conjuntodeempregados;
Você declara uma classe parametrizada em UML usando a notação mostrada na
Figura 6-18.
T
L_ 1
Conjunto
________________ Parâmetro Template
Classe Template
insira(T)
remova(T)
Figura 6-18: Classe Parametrizada
O T no diagrama é um marcador ( place holder) para o parâmetro de tipo (Você pode
ter mais de um). Em uma linguagem não-tipada, como Smalltalk, esta questão não
existe, portanto, este conceito não é útil.
Um uso de uma classe parametrizada, tal como Conjunto <Empregado>, é chamado
de elemento de amarração (bound element).
Você pode mostrar um elemento de associação de duas maneiras. A primeira,
espelha a sintaxe de C++ (veja Figura 6-19).
Conjunto <Empregados>
Figura 6-19: Elemento de Amarração (Versão 1)
A nDtação alternativa (veja Figura 6-20) reforça o elo para o gabarito e permite que
você renomeie o elemento de amarração.
O estereótipo «bind» é um estereótipo no relacionamento de refinamento. Este
relacionamento indica que Conjunto de Empregados estará de acordo com a
interface de Conjunto. Em termos de especificação, o Conjunto de Empregados é um
subtipo de Conjunto. Isso se encaixa na outra forma de implementar coleções
específicas de tipo, que é declarar todos os subtipos apropriados.
No entanto, o uso de um elemento de amarração não é o mesmo que subtipagem.
Você não pode acrescentar propriedades (features) ao elemento de amarração, que é
completamente especificado pelo seu gabarito; você está acrescentando somente
uma informação de tipo restrito. Se quer acrescentar propriedades, você deve criar
um subtipo.

DIAGRAMAS DE CLASSES: CONCEITOS AVANÇADOS


T
L
Conjunto
Classe Template insira(T)
remova(T)
«bind»
<Empregado>
Amarração de
Conjunto <Empregado> Parâmetro
Elemento de Amarração _____________________j
Figura 6-20: Elemento de Amarração (Versão 2)
As classes parametrizadas permitem que você use uma tipagem derivada. Quando
você escreve um corpo de um gabarito, pode chamar operações no parâmetro.
Quando você declarar mais tarde o elemento de amarração, o compilador tenta
assegurar que o parâmetro fornecido sustente as operações solicitadas pelo gabarito.

Isso é um mecanismo de tipagem derivado porque você não tem que definir um tipo
para o parâmetro; o compilador deriva se a amarração é viável, examinando o código
fonte do modelo. Esta propriedade é central para o uso de classes parametrizadas na
biblioteca de gabaritos-padrão de C++ (STL); estas classes também podem ser
usadas para outros truques interessantes.
O uso de classes parametrizadas tem repercussões — por exemplo, elas podem
causar um excesso considerável de código em C++. Raramente, utilizo classes
parametrizadas em modelagem conceitual, na maioria das vezes porque elas são
usadas principalmente para coleções, que são indicadas por associações (Um caso
em que as uso é no padrão range (escopo); veja Fowler 1997). Utilizo classes
parametrizadas nas perspectivas de modelagem para implementação e
especificação, somente se elas são sustentadas pela linguagem que estou usando.
Visibilidade
Devo confessar ter uma certa ansiedade sobre esta seção.
A visibilidade é um daqueles assuntos que é simples em princípio, mas tem
complexas sutilezas. A idéia básica é que qualquer classe tem elementos públicos

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM—PADRÃO DE MODELAGEM DE


OBJETOS
e elementos particulares. Os elementos públicos podem ser usados por qualquer
outra classe; os elementos particulares podem ser usados somente pela classe
proprietária. Entretanto, cada linguagem tem suas próprias regras. Embora muitas
linguagens usem termos como public (“público”), private (“particular”) e protected
(“protegido”), eles têm significados diferentes em linguagens diferentes. Estas
diferenças são pequenas, mas causam confusão, principalmente para alguns de nós
que utilizamos mais de uma linguagem.
UML tenta abordar o tema sem entrar em terrível confusão. Essencialmente, dentro
de UML, você pode rotular qualquer atributo ou operação com um indicador de
visibilidade. Você pode usar qualquer marcador que quiser, e seu significado é
dependente da linguagem. Entretanto, UML fornece três (bastante difíceis de
lembrar) abreviações para visibilidade; + (público), — (particular) e # (protegido).
Sou inclinado a deixar este assunto apenas nestes termos, mas, infelizmente, as
pessoas projetam diagramas que usam visibilidade de maneiras específicas.
Portanto, para compreender realmente algumas diferenças comuns que existem
entre modelos, você necessita compreender os enfoques que linguagens diferentes
usam em relação à visibilidade. Então, vamos respirar fundo e mergulhar nestas
águas turvas.
Vamos começar com C++, porque é a base para o uso-padrão de UML.
• Um membro público é visível em qualquer lugar no programa e pode ser acessado
por qualquer objeto no sistema.
• Um membro particular pode ser usado somente pela classe que o define.
• Um membro protegido pode ser usado somente por (a) uma classe que o define ou
(b) uma subclasse daquela classe.
Considere uma classe Cliente que tem uma subclasse Cliente Pessoa-Física.
Considere também o objeto Martin, que é uma instância de Cliente Pessoa-Física.
Martin pode usar qualquer membro público de qualquer objeto no sistema. Martin
também pode usar qualquer membro particular da classe Cliente Pessoa-Física.
Martin não pode usar membros particulares definidos dentro de Clientes; pode,
entretanto, usar membros protegidos de Cliente e membros protegidos de Cliente
Pessoa- Física.
Agora, examinemos Smalltalk. Dentro desta linguagem, todas as variáveis de
instância são particulares, e todas as operações são públicas. Entretanto, particular
não significa a mesma coisa em Smalltalk que em C++. Em um sistema Smalltalk,
Martin pode acessar qualquer variável de instância dentro do seu próprio objeto se
aquela variável de instância estiver definida dentro de Cliente ou Cliente Pessoa-
Física. Então, de certa forma, particular em Smalltalk é semelhante a protegido em
C++.
Ah, mas isso seria simples demais...
Vamos voltar para C++. Digamos que eu tenha uma outra instância de Cliente
Pessoa-Física chamada Kendall. Kendall pode acessar qualquer membro de Martin
que tenha sido definido como parte da classe Cliente Pessoa-Física, seja público,
particular ou protegido. Kendall também pode acessar qualquer membro público ou
protegido de Martin que tenha sido definido em Cliente. Entretanto, em Smalltalk,
Kendall não pode acessar as variáveis de instância particulares de Martin — somente
as operações públicas de Martin.

\102 P’ DIAGRAMAS DE CLASSES: CONCEITOS AVANÇADOS


Em C++, você pode acessar membros de outros objetos de sua própria classe
da mesma forma que acessa os seus próprios membros. Em Smalltalk, não faz
diferença se um outro objeto é da mesma classe ou não; você pode somente acessar
aspartes públicas de um outro objeto.
Java é semelhante a C++; ela oferece acesso livre a membros de outros objetos de
uma mesma classe. Ela também acrescenta um novo nível de visibilidade, chamado
pacote. Um membro com visibilidade de package (pacote) pode ser acessado
somente por instâncias de outras classes dentro do mesmo pacote.
Permanecendo em nosso tema, para garantir que as coisas não são tão simples, lava
redefine levemente visibilidade protegida. Em lava, um membro protegido pode ser
acessado por subclasses, mas também por qualquer outra classe do mesmo pacote
da classe proprietária. Isso significa que, em Java, protegido é mais público que
pacote.
lava também permite que classes sejam marcadas: como públicas ou de pacote. Os
membros públicos de uma classe pública podem ser usados por qualquer classe que
importa o pacote em que a classe pertence. Uma classe de pacote pode ser usada
somente por outras classes do mesmo pacote.
C++ acrescenta um penduricalho adicional. Um método ou classe de C++ pode se
tornar um amigo (“friend”) de uma classe. Um amigo tem acesso completo a todos
os membros de uma classe — portanto, a frase (de mau-gosto) “em C++, amigos
tocam as partes particulares dos outros”.
Quando você estiver usando visibilidade, use as regras da linguagem na qual está
trabalhando. Quando você está examinando um modelo UML de qualquer outra
origem, seja cuidadoso com o significado dos marcadores de visibilidade, e esteja
ciente de como estes significados podem mudar de linguagem para linguagem.
Descobri que as visibilidades geralmente mudam quando você começa a trabalhar
com código. Então, não fique amarrado a elas no início do projeto.

Pacotes e Colaborações

Uma das questões mais antigas nas metodologias de software é: como você quebra
um sistema grande em sistemas pequenos? Fazemos esta pergunta porque à medida
que os sistemas crescem, se torna difícil compreendê-los, bem como as mudanças
que neles fazemos.
Métodos estruturados usam decomposição funcional, no qual todo o sistema foi
mapeado como uma função e quebrado em sub-subfunções, que foram
posteriormente quebradas em sub-subfunções e assim por diante. As funções eram
como os casos de uso em um sistema orientado a objeto no qual as funções
representavam algo que o sistema fazia como um todo.
Aquela era uma época em que o processo e os dados eram separados. Então, além
da decomposição funcional, havia também a estrutura de dados. Isso assumiria um
segundo plano, embora algumas técnicas de Engenharia de Informação agrupassem
registros de dados em áreas de interesse e produzissem matrizes para mostrar como
as funções e os registros de dados interagiam.
E deste ponto de vista que vemos a maior mudança que a orientação a objetos tem
trazido. A separação entre processo e dados já era, a decomposição funcional já era,
mas a velha questão ainda continua.
Uma idéia é agrupar as classes em unidades de nível mais alto. Esta idéia,
aplicada de forma bastante livre, aparece em muitas metodologias orientadas a
objetos. Em UML, este mecanismo de agrupamento é chamado pacote (package).
Pacotes
A idéia de um pacote pode ser aplicada a qualquer elemento do modelo, não
somente a classes. Sem alguma heurística para agrupar as classes, o agrupamento
se torna arbitrário. A dependência é a heurística que considero mais útil e mais
enfatizada em UML.

PACOTES E COLABORAÇÕES

Uso o termo diagrama de pacotes para um diagrama que mostra pacotes de classes
e as dependências entre eles. De modo restrito, um diagrama de pacotes é
simplesmente um diagrama de classes que mostra apenas pacotes e dependências.
Utilizo muito estes diagramas, por isso os chamo de diagramas de pacotes, mas você
deve lembrar que este é um termo meu, não um nome oficial de diagramas da UML.
Existe dependência entre dois elementos se mudanças na definição de um elemento
possam causar mudanças ao outro. Nas classes, as dependências existem por várias
razões: uma classe manda uma mensagem para outra; uma classe tem outra como
parte de seus dados; uma classe menciona uma outra como um parâmetro para uma
operação. Se uma classe muda a sua interface, qualquer mensagem que ela mande
pode não ser mais válida.
De forma ideal, apenas mudanças na interface de uma classe devem afetar qualquer
outra. A arte de projetar em grande escala envolve minimização de dependências;
desta forma, os efeitos da mudança são reduzidos, e o sistema requer menos esforço
para mudar.
UML tem muitas variedades de dependência, cada uma com estereótipos e
semântica particulares. Considero mais fácil começar com a dependência
nãoestereotipada e usar as dependências mais particulares somente se necessário.
Na Figura 7-1, temos domínios de classe que modelam o negócio, agrupados em dois
pacotes: Pedidos e Clientes. Os dois pacotes são parte de um pacote
de domínio completo. A aplicação Processamento de Pedido tem dependências

Aplicação
Processamento de Pedido

Aplicação
L Mala Direta
/

Pacote

Dependência

Figura 7-1: Diagrama de Pacotes

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM—PADRÃO DE MODELAGEM DE


ObJETOS
com os dois pacotes de domínio. A Interface de Usuário (IU) de Processamento
de Pedido tem dependências com a aplicação Processamento de Pedido e AWT
(fava GLJI tool kit - um kit de ferramentas lava de Interface Gráfica com o Usuário).
Há dependência entre dois pacotes se houver qualquer dependência entre
quaisquer duas classes nos pacotes. Por exemplo, se qualquer classe no pacote
Malote de Correio for dependente de qualquer classe do pacote de Clientes, existe
uma dependência entre seus pacotes correspondentes.
Há uma semelhança óbvia entre estas dependências e as dependências de
compilação. Na verdade, há uma diferença vital: com pacotes, as dependências
não são transitivas.
Um exemplo de relação transitiva é uma na qual fim tem uma barba maior
do que a de Grady e Grady tem uma barba maior do que a de Ivar, então podemos
deduzir que Jim tem a barba maior do que a de Ivar.
Para ver por que isso é importante para dependências, olhe a Figura 7-1 novamente.
Se uma classe no pacote de Pedidos muda, isso não indica que o pacote
da Interface de Usuário de Processamento de Pedido deva ser mudado. Indica
simplesmente que o pacote de aplicação de Processamento de Pedido necessita
ser examinado para ver se ele muda, O pacote TU de Processamento de Pedido
necessita mudar somente se a interface do pacote de aplicação de Processamento
de Pedido é alterada. Neste caso, a aplicação de Processamento está protegendo a
lU de Processamento dos Pedidos de mudanças nos Pedidos.
Este comportamento éo propósito clássico de uma arquitetura em camadas.
Na verdade, eles são semelhantes à semântica do comportamento de “importar”
de Java, mas não ao comportamento “incluir” de C/C++. O “incluir” de C/C++ é
transitivo, o que significa que a IU de Processamento de Pedidos seria dependente
do pacote de Pedidos. Uma dependência transitiva torna difícil limitar o escopo
de mudanças em compilações. (Embora a maioria das dependências não seja
transitiva, você pode criar uma dependência estereotipada particular que o seja).
As classes dentro de pacotes podem ser públicas, particulares ou protegidas.
Então, o pacote Pedidos é dependente dos métodos públicos das classes públicas
do pacote Clientes. Se você alterar um método particular, ou um método público
em uma classe particular, no pacote Clientes, nenhuma das classes do pacote
Pedidos
necessita mudar.
Uma técnica útil, aqui, é reduzir a interface do pacote exportando apenas
um pequeno subconjunto das operações associado com as classes públicas do
pacote. Você pode fazer isso dando visibilidade particular a todas as classes, de
modo que elas possam ser vistas somente pelas classes no mesmo pacote, e
acrescentando
classes públicas extras para o comportamento público. Estas classes extras,
chamadas Fachadas (Gamma, Helm, Johnson e Vlissides, 1995), delegam, então,
operações públicas aos seus companheiros mais tímidos do pacote.
Os pacotes não oferecem respostas sobre como reduzir as dependências no
seu sistema, mas eles o ajudam a ver quais são as dependências e você trabalha
para reduzí-las somente se você as pode ver. Para mim, os diagramas de pacotes
são uma ferramenta-chave para manter o controle da estrutura global do sistema.
A Figura 7-2 é um diagrama de pacotes mais complexo que contém constru çõe
adicionais. 1

\1067 PACOTES E COLABORAÇÕES


y
fliu
Processamento
de Pedido
Aplicação
Processamento
Pedido
Domínio
Pedidos — iientesJ
«global»
Comum

Quantidade
Valo rMonetário
EscopodeDatas

Figura 7-2: Diagrama de Pacotes Avançado

LJML JiSSENCIAL: UM bREVE (.U1A PARA A LINGUAGEM—?ADRÃO DE MODELAGEM DE


OBJETOS
Primeiro, vemos que acrescentei um pacote de Domínio que contém os pacotes
de clientes e pedidos. Isso torna-se útil porque significa que você pode projetar
dependências de e para o pacote global, em vez de muitas dependências
separadas.
Quando você mostra os conteúdos do pacote, coloca o mesmo nome do pacote
no “rótulo” e os conteúdos dentro da caixa principal. Estes conteúdos podem
ser uma lista de classes, como no pacote Comum; um outro diagrama de pacotes,
como no Domínio; ou um diagrama de classes (não mostrado, mas agora a idéia
já deve ser óbvia).
Na maioria das vezes, considero suficiente listar as classes-chave, mas, às
vezes, um diagrama adicional é útil. Neste caso, mostrei que enquanto a aplicação
de Processamento de Pedido tem uma dependência com todo o pacote do Domínio,
a aplicação de Malote de Correio é dependente somente do pacote Cliente.
O que significa desenhar uma dependência para um pacote que contém sub-
pacotes? Em geral, isso significa que a dependência resume uma dependência de
nível mais baixo. Isto é, existe alguma dependência para algum elemento dentro
do pacote de nível mais alto, mas você precisa de um diagrama mais pormenorizado
para ver os detalhes. Mais uma vez, as regras precisas variam com o tipo
particular da dependência.
A Figura 7-2 mostra o pacote Comum marcado como «global». Isso significa
que todos os pacotes no sistema têm uma dependência para Comum. Obviamente,
você deve usar esta construção parcimoniosamente, mas classes comuns,
tais como Valor Monetário, são usadas em todas as partes.
Você pode usar generalização com pacotes. Isso significa que um pacote específico
deve estar de acordo com a interface do pacote geral. Isto é comparável à
subtipagem na perspectiva de especificação, dentro dos diagramas de classes (veja
Capítulo 4). Portanto, de acordo com a Figura 7-2, o Intermediário (Broker) de
Banco de Dados pode usar tanto a Interface de Oracle quanto a de Sybase. Quando
a generalização é usada desta forma, o pacote geral pode ser marcado como
{abstract) para mostrar que ele simplesmente define uma interface, que é
implementada por um pacote mais específico.
A generalização implica em uma dependência do subtipo para o supertipo
(Você não precisa mostrar a dependência extra; a própria generalização é suficiente).

Colocar classes abstratas num pacote de supertipos é uma boa forma de


quebrar ciclos na estrutura de dependência. 1
Na situação anterior, os pacotes de interface de banco de dados são respon sávei
por carregar e salvar os objetos de domínio no banco de dados. Eles preci- ,
sam, portanto, conhecer os objetos de domínio. Entretanto, esses objetos
necessi__________
tam acionar ações de carregar e salvar.
A generalização nos permite colocar as interfaces de acionamento necessárias
— várias operações de carregar e salvar — no pacote de interface de banco de .: .
dados. Estas operações são, então, implementadas por classes dentro de pacotes
de subtipo. Não existe, então, dependência entre o pacote de interface do banco de
dados e o pacote de interface de Oracle, muito embora, em tempo de execução, o
pacote de subtipo é que será chamado pelo domínio. Mas o domínio pensa que
está lidando somente com o (mais simples) pacote de interface de banco de dados.
O polimorfismo é tão útil para pacotes quanto o é com classes.
PACOTES E LOLABORAÇÕES

Como princípio básico, é uma boa idéia remover ciclos da estrutura de dependência.
Não estou convencido de que você deva remover todos os ciclos, mas deve
certamente, minimizá-los. Se você os tem, tente contê-los dentro de um pacote de
contenção maior. Na prática, tenho visto casos nos quais não fui capaz de evitar
ciclos entre pacotes de domínio, mas tento eliminá-los das interações entre o
domínio e as interfaces externas. Generalização de pacote é um elemento-chave
para isso.
Em um sistema existente, as dependências podem ser inferidas através da
observação das classes. Isto é uma tarefa muito útil de ser realizada por uma
ferramenta. Considero isso útil se estou tentando melhorar a estrutura de um
sistema existcnte. Um primeiro passo útil é dividir as classes em pacotes e analisar
as dependências entre os pacotes. Depois, refatoro para reduzir as dependências.

Colaborações

Além de conter classes, um pacote pode conter colaborações. Uma colaboração é um


nome dado à interação entre duas ou mais classes. Tipicamente, isso é uma
interação, como descrito no diagrama de interação. Então, o diagrama de seqüência
na Figura 7-3 descreve a colaboração Registrar Venda.

dedor:Grupo
Ufa propaganda
submete proposta

comprador71
L

comDrador 2:

submete proposta

Esta colaboração pode mostrar a implementação de uma operação ou a realização


de um caso de uso. Você pode modelar a colaboração antes de decidir que
operação a chama.

‘\ios / y

Aceita proposta

Figura 7-3: Diagramas de Seqüência para Registrar uma Venda

UML ESSENCIAL: UM BREvE GUIA PARA A LINGUAGEM—VADRAO DE MODELAGEM DE


OBJETOS 1’
Uma colaboração pode ser descrita com mais de um diagrama de interação, com
cada um mostrando um caminho diferente. Você também pode mostrar um diagrama
de classes para mostrar as classes que participam na colaboração (Veja Figura 7-4).
comprador 1
Grupo vendedor
_*
Em adição ao uso de colaborações dentro de um pacote, você pode usá-las para
mostrar um comportamento comum através dos pacotes. Se alguém lhe perguntar
sobre interações de banco de dados, você pode precisar indicá-las para muitos
pacotes e classes para ver como isso funciona, embora a interação de banco de
dados seja somente um aspecto destes pacotes e classes. Você pode melhorar isso
definindo uma colaboração de interação de banco de dados. Dentro desta
colaboração, você mostra aqueles aspectos das classes que são relevantes e
diagramas de interação que mostram como eles funcionam.
Você pode descobrir, com freqüência, que a mesma colaboração é usada por classes
diferentes no sistema. A cada vez, o modo básico como classes funcionam é o
mesmo, mas classes e operações são nomeadas diferentemente e pode haver
diferenças menores na implementação. Você pode ilustrar isso parametrizando a
colaboração.
Primeiro, você projeta um diagrama como na Figura 7-5, que mostra as várias
funções que vários objetos têm na colaboração. (Observe que as classes neste
diagrama não são classes reais no sistema, em vez disto, elas são papéis na
colaboração). Você acrescentaria, então, diagramas de interação para mostrar como
estes papéis interagem.
A seguir, você mostra como um conjunto de classes participa na colaboração,
desenhando um diagrama como o da Figura 7-6.
UML também usa o termo padrão (pattern) como sinônimo para colaboração
parametrizada. É uma controvérsia chamar isso de padrão, pois um padrão é mais do
que isso, mas, certamente, esta notação pode ser usada para mostrar onde padrões
comuns são utilizados em um sistema particular.
Você também pode usar este tipo de notação na modelagem baseada em
papéis, com a qual você, primeiro, modela as colaborações e papéis e, então, pro 1
Figura 7-4: Diagrama de Classes para Colaboração Registrar uma Venda

Figura 7-5: Colaboração Parametrizada para Venda

proposta

N
“ _\
— — Venda

PACOTES E LOIABORAÇOES

Venda

/
/
\
\
E1
— — — comprador, vendedor, lote, oferta
L
\
/

comprador

comprador, vendedor

lote N

Figura 7-6: Utilizando a Colaboração de Venda

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM—PADRÃO DE MODELAGEM DE


OBJETOS lfl
põe classes que implementam estes papéis. Você pode encontrar mais informação
sobre este estilo de projeto no livro de Reenskaug (1996).
Quando Utilizar Diagramas de Pacotes e Colaborações
Os pacotes são ferramentas vitais para projetos grandes. Utilize pacotes sempre que
um diagrama de classes que compreenda todo o sistema não for mais legível numa
única folha de papel tamanho A4.
Os pacotes são particularmente úteis para testes. Embora eu escreva alguns testes
em um fundamento de classe-por-classe, prefiro fazer meu teste de unidade em um
fundamento de pacote-por-pacote. Cada pacote deve ter uma ou mais classes de
teste que testem o comportamento do pacote.
Considero colaborações úteis sempre que você quer se referir a uma interação
particular. Colaborações parametrizadas são úteis quando você tem várias
colaborações semelhantes no seu sistema.
Onde Encontrar Mais Informação
A melhor descrição que conheço sobre pacotes é de Robert Martin (1995), cujo livro
dá vários exemplos utilizando Booch e C++, com muita atenção à minimização de
dependências. Você também pode achar informações valiosas no livro de Wirfs-Brock
(1990), o primeiro autor a se referir a pacotes como subsistemas.
As colaborações são um tópico bastante novo, então você encontrará mais
discussão sobre elas somente em livros mais detalhados de UML.

8
Diagramas de Estados
Diagramas de estados são uma técnica conhecida para descrever o comportamento
de um sistema. Eles descrevem todos os estados possíveis em que um objeto
particular pode estar e como o estado do objeto muda como resultado de eventos
que o atingem. Na maioria das técnicas de 00, os diagramas de estados são
projetados para uma classe única para mostrar o comportamento ao longo do tempo
de vida de um único objeto.
Existem várias formas de diagrama de estados, cada uma com uma pequena
diferença semântica. O estilo UML é baseado no statechart de David Harel (1987).
A Figura 8-1 mostra um diagrama de estados UML para um pedido no sistema de
processamento de pedidos que apresentei anteriormente neste livro. O diagrama
indica os vários estados de um pedido.
Começamos no ponto inicial e mostramos uma transição inicial para o estado de
“Verificando”. Esta transição é rotulada “/ obter primeiro item”.
A sintaxe para um rótulo de transição tem três partes, sendo todas opcionais:
Evento LGuarda] /Açí7o. Neste caso, temos somente a ação “obter primeiro item”.
Uma vez realizada esta ação, entramos no estado de “verificando”. Este estado tem
uma atividade associada a ele, indicada por um rótulo com a sintaxe do/atividade.
Neste caso, a atividade é chamada “verificar item”.
Observe que usei os termos “ação” para a transição e “atividade” para o estado.
Embora os dois sejam processos, implementados tipicamente por algum método no
Pedido, eles são tratados diferentemente. Ações são associadas com transições e são
consideradas como processos de curta duração e não podendo ser interrompidos.
Atividades são associadas a estados e podem levar mais tempo. Uma atividade pode
ser interrompida por algum evento.

DIAGRAMAS DE liS lADOS

início

Figura 8-1: Diagrama de Estados

Observe que a definição de “curta duração” depende do tipo de sistema que você
está produzindo. Dentro de um restrito sistema de tempo real, “curta duração” pode
significar dentro de poucas instruções da máquina; para sistemas de informações
regulares, “curta duração” pode significar menos que alguns segundos.
Quando a transição não tem nenhum evento dentro do seu rótulo, isso significa que a
transição ocorre logo que qualquer atividade associada a um dado estado é
completada. Neste caso, isso significa tão logo tenhamos completado o estado
verificando. Três transições surgiram do estado Verificando. Todos as três têm
somente guardas nos seus rótulos. Um guarda é uma condição lógica que retornará
somente “verdadeiro” ou “falso”. Uma transição guardada ocorre somente se o
guarda for “verdade”.
Somente uma transição pode ocorrer de um dado estado, de modo que pretendemos
que os guardas sejam mutuamente exclusivos para qualquer evento.
Na Figura 8-1, examinamos três condições:

1. Se não verificamos ainda todos os itens, tomamos o próximo item e retornamos ao


estado de Verificando para fazer a sua verificação.
2. Se tivermos verificado todos os itens e eles estiverem todos com quantidade
suficiente em estoque, fazemos a transição para o estado Entregan do.
3. Se tivermos verificado todos os itens, mas nem todos estavam em estoque,
fazemos a transição para o estado Aguardando.

/pegar próximo tem

Autotransição

Estado

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM—PADRÃO DE MODELAGEM DE


OBJE los
Examinarei o estado Esperando primeiro. Não há atividades para este estado, então
o pedido espera neste estado, aguardando por um evento. As duas transições para
fora do estado Esperando são rotuladas com o evento Item Recebido. Isso significa
que o pedido espera até que ele detecte este evento. A esta altura, ele avalia os
guardas nas transições e faz a transição apropriada, seja para o Entregando ou de
volta para o Esperando.
Dentrci do estado Entregando, temos uma atividade que inicia a entrega. Há também
uma transição não guardada acionada pelo evento Entregue. Isso indica que a
transição sempre ocorrerá quando este acontecer. Observe, entretanto que a
transição não ocorre quando a atividade se completa; em vez disso, uma vez que a
atividade de “iniciar entrega” for terminada, o dado pedido permanece no estado de
Entregando até que o evento Entregue aconteça.
A última coisa a ser examinada é a transição chamada “cancelamento”. Queremos
ser capazes de cancelar um pedido a qualquer momento antes dele ser entregue.
Poderíamos fazer isso projetando transições separadas para cada estado de
Verificando, Esperando e Entregando. Uma alternativa útil é criar um superestado de
todos os três estados e, então, projetar uma transição única dele. Os subestados
herdam simplesmente quaisquer transições de um superestado.
As Figuras 8-2 e 8-3 mostram como estes enfoques refletem o mesmo
comportamento de sistema.

‘ 115y
v

)ce
lo
Is.
tataira

[Nem todos os itens verifica. dos] /pegar próximo item


tem recebido [alguns itens não estão disponíveis]

reto.

tin Fíqii
• Dia grama d Fstados sem Superestados

DIAGRAMAS DE ESTADOS

Mesmo com apenas três transições duplicadas, a Figura 8-2 parece um tanto
carregada. A Figura 8-3 esclarece muito as coisas, e se forem necessárias mudanças
mais tarde, é mais difícil esquecer o evento cancelamento.
Nos exemplos, mostrei uma atividade dentro de um estado, indicado por
um texto na forma de do/atividade. Você também pode indicar outras coisas dentro
de um estado.
Se um estado responde a um evento com uma ação que não causa uma transição,
você pode mostrar isso colocando um texto na forma Nome-do-evento/Nomeda-a çao
na caixa de estado.
Nome do Superestado
Ativado
__________ [Todos os itens verificados && __________
. todos os itens disponíveis]
1’ Verificando f’ Expedindo ‘
do / verificar j do / iniciar 1
> tem entrega
a Ç’ ,‘
‘o
Aguardando
cancelado
CanceIado
• Um evento pode ser gerado após um dado período de tempo. Isso é indicado com a
palavra-chave after. Por exemplo, você pode dizer after (20
minutes).

[Nem todos itens verificados] / pegar próximo tem

[Todos os tens verificados && alguns itens não estão em estoque]

tem recebido [alguns tens não estão em estoque]

4
nos.

Figura 8-3: Diagrama de Estados com Superestados


Existem alguns outros tipos de eventos, além dos eventos nomeados, exter

UML. ESSENCIAL: UM BREVE GUIA PARA A LINCUAGEM—PADRAO DE IVIODELAGEM DE


OBJETOS

Um evento pode ser gerado quando uma condição se torna verdadeira. Você mostra
isso com a palavra-chave when. Por exemplo, você poderia ter when (tem perature
>100 degrees).

Existem também dois eventos especiais, entrada (entry) e saída (exit). Qualquer
ação que estiver marcada como ligada ao evento entry é executada sempre que se
chegar a um dado estado, através de uma transição. A ação associada ao evento exit
é executada sempre que o estado for deixado através de uma transição. Se você
tiver uma transição que volta ao mesmo estado (isto é chamado autotransição) com
uma ação, a ação de saída será executada primeiro, depois a ação de transição e,
finalmente, a ação de entrada. Se um estado tiver também uma atividade associada,
esta atividade é executada depois da ação de entrada.

Diagramas de Estados Concorrentes

Além dos estados de um pedido baseados na disponibilidade de itens, existem


também estados que são baseados em autorização de pagamento. Se examinarmos
estes estados, podemos ver um diagrama de estados como o da Figura 8-4.

‘ 117 r
v

[pagamento não 0k]

Figura 8-4: Autorização de PagamenE


DIAGRAMAS DE ESTADOS
Começamos fazendo aqui uma autorização. A atividade de “verificação de
pagamento” termina com a sinalização que o pagamento é aprovado. Se o
pagamento estiver ok, o dado pedido espera no estado Autorizado até que ocorra o
evento de “Entrega”. Caso contrário, o pedido entra no estado Rejeitado.
O objeto Pedido exibe uma combinação de comportamentos mostrados na Figura 8-1
e na Figura 8-2. Os estados associados e o estado Cancelado discutidos
anteriormente podem ser combinados em um diagrama de estados concorrentes
(veja Figura 8-5).
Observe que, na Figura 8-5, não incluí detalhes dos estados internos.
Cancelado
cado
__________ fim
• __
itad
Figura 8-5: Diagrama de Estados Concorrentes
As seções concorrentes do diagrama de estados são lugares nos quais, a qualquer
momento, um dado pedido está em dois estados diferentes, um de cada diagrama.
Quando o pedido deixa os estados concorrentes, ele está somente em um único
estado. Podemos ver que um pedido começa em ambos, estados de Verificado e
Autorizado. Se a atividade de “verificação de pagamento” do estado de Autorizando é
completada com sucesso em primeiro lugar, o pedido estará nos estados de
Verificado e Autorizado. Se o evento de” cancelamento “acontecer, o pedido estará
somente no estado Cancelado.
Diagramas de estados concorrentes são úteis quando um dado objeto tem
conjuntos de comportamentos independentes. Entretanto, observe que você não

LJML IiSSENCIAL: UM BREVE (,UIA PARA A LIN(,UAEM—PADRÃO DE MODELAGEM DE


OBJETOS 119
deve ter demasiados conjuntos concorrentes de comportamento ocorrendo em um
único objeto. Se você tem vários diagramas de estados concorrentes complicados
para o mesmo objeto, deve considerar dividir o objeto em objetos separados.
Quando Utilizar Diagramas de Estados
Diagramas de estados são bons para descrever o comportamento de um objeto,
através de vários casos de uso. Esses diagramas não são muito bons para descrever
um comportamento que envolve vários objetos em colaboração. Para tal, é útil
combinar diagramas de estados com outras técnicas.
Por exemplo, diagramas de interação (veja Capítulo 5) são bons para descrever o
comportamento de vários objetos em um único caso de uso, e diagramas de
atividades (veja Capítulo 9) são bons para mostrar a seqüência geral de ações para
vários objetos e casos de uso.
Nem todo mundo considera que os diagramas de estados sejam naturais. Fique
atento ao modo que as pessoas trabalham com eles. Pode ser que sua equipe não
considere diagramas de estados úteis para seu tipo de trabalho. Isso não é um
grande problema; como sempre, você deve lembrar de usar uma combinação das
técnicas que funcionam para você.
Se você utilizar diagramas de estados, não tente projetá-los para cada classe no
sistema. Embora este método seja freqüentemente usado por perfeccionistas de
muita formalidade, ele é quase sempre um desperdício de trabalho. Use diagramas
de estados somente para aquelas classes que exibem comportamento interessante,
para as quais a construção do diagrama de estados ajude a compreender o que está
acontecendo. Muitas pessoas acreditam que Interface de Usuários e objetos de
controle têm o tipo de comportamento que é útil descrever com diagramas de
estados.
Onde Encontrar Mais Informação
Tanto o ljser Guide (Booch, Rumbaugh e Jacobson, 1999) como o Reference Manual
(Rumbaugh, Jacobson e Booch, 1999) têm mais informações sobre diagramas de
estados. Projetistas de tempo real tendem a usar muito modelos de estado, portanto
não é surpreendente que Douglass (1998) tenha muito a dizer sobre diagramas de
estados, incluindo informação de como implementá-los.
Se você usar muito diagramas de estados, deve ler a discussão no livro de Cook e
Daniels (1994). Embora existam diferenças na semântica entre State Charts daquela
época e aquelas da UML, os autores entram em assuntos detalhados dos quais você
deve estar ciente se estiver usando diagramas de estados.

9
Diagramas de Atividades
Diagramas de atividades são uma das partes mais inesperadas de UML.
Ao contrário da maioria das outras técnicas da UML, diagramas de atividades não
têm origens claras nos trabalhos anteriores dos três amigos. Ao contrário,
•o diagrama de atividades combina idéias de várias técnicas: os diagramas de
eventos de Jim Odeli, técnicas de modelagem de estado SDL, modelagem de
workflow e redes de Petri. Estes diagramas são particularmente úteis em conexão
com workflow e na descrição de comportamento que tem muito processamento em
paralelo.
Descreverei diagramas de atividades com mais detalhes do que eles realmente
merecem neste pequeno livro. A razão é que eles são uma das áreas menos
compreendidas de UML, e os livros atuais sobre UML são particularmente omissos em
sua discussão.
Na Figura 9-1, o símbolo central é o estado de atividade, ou simplesmente atividade.
Uma atividade é um estado de estar fazendo algo: tanto um processo de mundo real,
tal como datilografar uma carta, ou a execução de uma rotina de software, tal como
um método em uma classe.
O diagrama de atividades descreve a seqüência de atividades, com suporte para
comportamento condicional e paralelo. Um diagrama de atividades é uma variante
de um diagrama de estados no qual a maioria, se não todos, dos estados é estado de
atividade. Portanto, muito da terminologia segue a mesma terminologia de diagrama
de estados.
Comportamento condicional é delineado por desvios (branches) e intercalações
(merges).
Um desvio (branch) é uma transição de entrada única e várias transições de saída
guardadas. Somente uma transição de saída pode ser tomada, de modo que os
guardas devem ser mutuamente exclusivos. A utilização de [else] como um guarda
indica que transição “else” deverá ser usada se todos os outros guardas do desvio
forem falsos.

\1y

DIAGRAMAS DE ATIVIDADES

Início

Separação

Atividade
Guarda
[pedido urgente]

Desvio
Intercalação

Junção

Fim

Figura 9-1: Diagrama de Atividades

UIVIL bSSENCIAL: UM DREVE ,U1A PARA A LINL,UAUEM—PADRÃO DE MODELAGEM DE


OBJETOS
Na Figura 9-1, depois que um pedido é preenchido, há um desvio. Se você tiver um
pedido de urgência (rush order), você faz uma entrega durante a noite; se não, você
faz uma entrega normal.
Uma intercalação (merge) tem múltiplas transições de entrada e uma única saída.
Um merge marca o final de um comportamento condicional iniciado por um branch.
Você não precisa mostrar explicitamente o losango para desvios e intercalações. Um
estado de atividade, como qualquer estado, pode ter múltiplas transições de saída
guardadas e múltiplas transições de entrada. Use o losango se você quiser deixar
claros os desvios e as intercalações em um diagrama.
Comportamento paralelo é indicado por Separações (Forks) e Junções (Joins).
Um Separação (Fork) tem uma transição de entrada e várias transições de saída.
Quando uma transição de entrada é acionada (triggered), todas as transições de
saída são executadas em paralelo. Então, na Figura 9-1, depois que você recebe um
pedido, você o preenche e envia a fatura em paralelo.
O diagrama diz que estas atividades podem ocorrer em paralelo. Essencial- mente,
isso significa que a seqüència entre elas é irrelevante. Eu poderia preencher o
pedido, enviar a fatura, entregar e, então, receber o pagamento; ou poderia enviar a
fatura, receber o pagamento e, então, preencher o pedido e fazer a entrega.
Essas atividades também podem ser executadas intercaladamente. Por exemplo,
você examina o primeiro item de linha de um pedido, escreve a fatura, pega o
segundo item de linha, coloca a fatura em um envelope e assim por diante. Ou você
poderia fazer alguma destas coisas simultaneamente: escrever a fatura com uma
mão enquanto você pega o próximo item com a outra. Qualquer uma das seqüências
é correta, de acordo com o diagrama.
O diagrama de atividades permite que você escolha a ordem em que faz as coisas.
Em outras palavras, ele simplesmente determina as regras essenciais de seqüência
que você deve seguir. Esta é a diferença-chave entre um diagrama de atividades e
um fluxograma: os fluxogramas são normalmente limitados a processos sequenciais,
enquanto que os diagramas de atividades podem lidar com
processos paralelos.
Isso é importante para modelagem de negócios. Os negócios têm, freqüentemente,
processos processos não necessariamente seqüencias. Uma técnica como esta que
encoraja comportamento paralelo é valiosa nestas situações porque ela encoraja as
pessoas a se afastarem de seqüências desnecessárias nos seus comportamentos e a
identificar oportunidades para fazer coisas em paralelo. Isso pode melhorar a
eficiência e o retorno de processos de negócio.
Os diagramas de atividades também são úteis para programas concorrentes, uma
vez que você pode projetar graficamente quais caminhos (threads) você tem e
quando eles precisam ser sincronizados.
Quando você tem comportamento paralelo, precisa sincronizar. Não fechamos um
pedido até que ele seja entregue e pago. Mostramos isso com a junção (join) antes
da atividade Fechar Pedido. Com o junção, a transição seguinte é efetuada somente
quando todos os estados nas transições de entrada tenham completado suas
atividades.
Separação e junção devem se completar. No caso mais simples, isso significa que
toda vez que você tiver uma separação, deve ter uma junção que una os threads

124 DIAGRAMAS DE ATIVIDADES


iniciadas por aquelas separações. (Esta regra vem do fato de que um diagrama de
atividades é, atualmente, uma forma de diagrama de estados).
Entretanto, existem várias extensões para esta regra.
• Um thread que sai de uma separação pode abrir-se em uma nova separação, com
os novos threads juntando-se antes de alcançar a junção da primeira separação.
• Se um thread saindo de uma separação vai direto para outra separação, você pode
remover a segunda separação e somente ter os threads da segunda separação
saindo da primeira separação. Portanto, na Figura 9-2, removi uma separação entre
as atividades de preparação de comida e a separação de abertura. De modo
semelhante, se uma junção vai direto para uma outra junção, você pode eliminar a
primeira junção e ter as threads indo direto para a segunda. Isso é uma estenografia
notacional para remover a confusão do diagrama; ela tem o mesmo significado
semântico como se as separações e junções extras estivessem lá.
• Uma construção avançada chamada de estado de sincronia permite que você faça
sincronia em lugares onde a regra de encaixe de separação e junção impediria que
você fizesse isso. Para detalhes sobre esta construção, veja o Reference manual
(Rumbaugh, Jacobson e Booch 1999) ou o padrão de UML.
Existe uma exceção para a regra de que todos os estados de entrada em uma junção
devem ter terminado suas atividades, antes que a junção possa ser efetuada. Você
pode acrescentar uma condição para um thread saindo de uma separação. O
resultado é um thread condicional. Durante a execução, se a condição de um thread
condicional for falsa, este thread é considerado completado no que diz respeito à
junção. Então na Figura 9-2, mesmo que eu não esteja a fim de vinho, ainda seria
capaz de comer o meu Espaguete Carbonara (devo confessar que nunca tive que
testar esta regra na execução deste diagrama!)

Figura 92; Separações, J;;rições e Threads Condicionais

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM—PADRÃO DE MODELAGEM DE


OBJETOS
de Decompondo uma Atividade
Uma atividade pode ser dividida em subatividades. Isso funciona mais ou menos
como superestados e subestados em um diagrama de estados. Você pode somente
mostrar o superestado no diagrama-pai, ou pode mostrar o superestado no seu
comportamento externo dentro dele, como fiz na Figura 9-3 (veja página 126).
Neste caso, dei um começo e um fim para a atividade de entrega. Você também
e pode projetar transições diretamente para dentro, ou para fora do diagrama sub-
2 sidiário. As vantagens dos estados de fim e início explícitos são que uma atividade
de entrega pode ser usada em outros contextos, e o diagrama-pai é desacoplado
to dos conteúdos do diagrama subsidiário.
Concorrência Dinâmica
Concorrência dinâmica permite que você mostre interações sem que tenha que
construir um ciclo (loop).
Na Figura 9-4(veja página 127), a atividade preencher linha de item é executada uma
vez para cada linha de item em um pedido. O marcador de multiplicidade (*) indica
que a atividade é executada muitas vezes. A transição para Entregar Pedido é
acionada somente quando as linhas de item tiverem sido preenchidos. Se várias
atividades precisam ser executadas juntas de alguma forma, você pode mostrar isso
fazendo do Preencher Linhas de item uma atividade composta.
Raias (Swimlanes)
Os diagramas de atividades dizem o que acontece, mas não dizem quem faz o
quê. Em programação, isso significa que o diagrama não representa qual classe é
responsável para cada atividade.
Em modelagem de domínio, isso significa que o diagrama não representa que
pessoas ou departamentos são responsáveis por cada atividade. Uma solução, aqui,
é rotular cada atividade com a classe ou pessoa responsável. Isso funciona, mas não
oferece a mesma clareza que os diagramas de interação (veja Capítulo 5) para
mostrar a comunicação entre objetos.
Raias são uma solução para isso.
Para usar raias, você deve organizar seus diagramas de atividades em zonas
verticais separadas por linhas. Cada zona representa as responsabilidades de uma
classe específica ou, no caso da Figura 9-5, um departamento específico.
As raias são úteis porque elas combinam a descrição de lógica do diagrama de
atividades com a descrição de responsabilidade do diagrama de interação.
Entretanto, elas podem ser difíceis de serem projetadas em um diagrama complexo.
Já usei zonas não-lineares, o que é melhor do que nada. (As vezes, você tem que
parar de tentar dizer muito em um só diagrama).
Algumas pessoas asseguram-se de atribuir atividades a objetos quando projetam um
diagrama de atividades. Outras gostam de trabalhar, primeiro, com

DIAGRAMAS DE ATIVIDADES

Figura 9-3: Utilizando uma Atividade Composta para a Entrega

UNIL tssENcIAL: UM DREVE L,UIA PARA A LINGUALEM—I’ADRAO DE IVIODELALEM DE


UBJL lOS
Concorrência Dinâmica
c0Pre
Figura 9-4: Concorrência Dinâmica
diagramas de atividades, para obter uma noção global do comportamento, e
atribuem as atividades para objetos mais tarde. Vi pessoas que atribuem
imediatamente ficarem sensíveis em relação àquelas que adiam a tarefa; elas fazem
acusações desagradáveis de desenhar diagramas de dataflozo, não sendo orientados
a objeto.
Confesso que, geralmente, desenho um diagrama de atividades sem assinalar
comportamento a objetos até mais tarde. Considero útil atacar uma coisa de cada
vez. Isso é particularmente verdade quando estou fazendo modelagem do negócio e
encorajando um especialista do domínio a pensar em novas maneiras de fazer as
coisas. Isso funciona para mim. Outros preferem assinalar comporta- mentos para
objetos imediatamente. Você deve fazer o que lhe deixa mais à vontade. A coisa
importante é atribuir atividades a classes antes de ter terminado. Para isso, prefiro
usar um diagrama de interação (veja Capítulo 5).
Quando Utilizar Diagramas de Atividades
Como a maioria das técnicas de modelagem comportamental, os diagramas de
atividades têm qualidades e fraquezas definidas, por isso a melhor maneira de usá-
los é em combinação com outras técnicas.
A maior qualidade dos diagramas de atividades está no fato de que eles suportam e
encorajam comportamento paralelo. Isso os torna uma grande ferramenta para
modelagem de workflozv, e, em princípio, para programação concorrente. A maior
desvantagem destes diagramas é que eles não deixam muito claras as ligações entre
ações e objetos.
Você pode definir uma ligação para um objeto rotulando uma atividade com um
nome de objeto ou usando raias que dividem um diagrama de atividades em base
em responsabilidades, mas isso não tem a clareza simples de diagramas de interação
(veja Capítulo 5). Por esta razão, algumas pessoas sentem que diagramas de
atividades não são orientados a objetos e, portanto, são maus.
Descobri que a técnica pode ser muito útil, e não jogo fora ferramentas úteis
de minha caixa de ferramentas.
Gosto de utilizar diagramas de atividades nas seguintes situações:
• Analisando um caso de uso. Neste estágio, não estou interessado em alocar ações
aos objetos; eu preciso simplesmente compreender que ações preci

DIAGI<AMAs DE P,JIVIDADES

Execução

Serviço de Atendimento ao Cliente

Setor Financeiro

Figura 9-5: Raias

UML tSSENCIAL: UM BREVE GUIA PARA A LINGUAGEM—PADRÃO DE MODELAGEM DE


OBJETOS \1297
sam acontecer e quais são as dependências comportamentais. Faço alocações de
método a objetos mais tarde e mostro estas alocações com um diagrama de
interação.
• Compreendendo workflow. Mesmo antes de iniciar os casos de uso, acredito que os
diagramas de atividades são muito úteis para compreensão de um processo de
negócio. Posso, facilmente, projetar estes diagramas junto com especialistas do
negócio para compreender como o negócio funciona e como ele pode mudar.
• Descrevendo um algoritmo seqüencial complicado. Neste caso, um diagrama de
atividades não é nada mais do que umflowchart em notação UML. Os
prós e contras comuns deflowcharts se aplicam aqui.
• Lidando com aplicações de processamento paralelo. Pessoalmente, não uso
diagrama de atividades para este propósito, mas escutei alguns relatos positivos.
Não use diagramas de atividades nas seguintes situações:
• Tentando ver como os objetos colaboram. Um diagrama de interação é mais
simples e lhe dá uma visão mais clara das colaborações.
• Tentando ver como um objeto se comporta durante o seu ciclo de vida. Use um
diagrama de estados para isso (veja Capítulo 8).
• Representando lógica condicional existente. Use uma tabela de decisão.
O trabalho em UML 1.3 acrescentou muito mais rigor e precisão para diagramas de
atividades. Entretanto, isso tem vantagens e desvantagens. O problema é que
quando você usa estes diagramas para modelagem conceitual, muito deste rigor
atrapalha. Nestas situações, você não tem como objetivo precisão total, apenas uma
visão geral de como as coisas funcionam. De qualquer modo, você, provavelmente,
não acertará, mesmo se tentar, a não ser que seja capaz de executar e testar o
diagrama. Lembre-se da frase de Bertrand Meyer: “Bolhas não quebram”.
Por outro lado, o fato de ter um padrão para diagrama de estados e diagrama de
atividades faz com que exista uma base mais estável para desenvolvedores de
ferramentas construírem as que executarão estes diagramas. Tais diagramas
permitiram que você execute e teste estes diagramas.
Onde Encontrar Mais Informação
Existe pouca informação sobre diagramas de atividades. O Reference Manual
(Rumbaugh, Jacobson e Booch, 1999) fornece muitos detalhes mas não ensina como
eles funcionam. O LJser Guide (Booch, Jacobson e Rumbaugh, 1999) não dá detalhes
suficientes para responder o tipo de questões que você terá quando tentar usar esta
técnica. Esperamos que alguém preencha esta lacuna num futuro não muito distante.
*4

34

lo
Diagramas Físicos
UML fornece dois tipos de diagramas físicos: diagramas de utilização e diagramas de
componentes.
Diagramas de Utilização
Um diagrama de utilização (deploynient diagram) mostra as relaçoes tisicas entre
componentes de software e hardzvare no sistema implementado. Um diagrama de
utilização é um bom lugar para mostrar como componentes e objetos são acessados
se movem em um sistema distribuído.
Cada nó no diagrama de utilização representa algum tipo de unidade computacional
— na maioria dos casos, uma parte do hardware. O hardzvare pode ser um simples
dispositivo ou sensor, ou poderia ser um computador de grande porte.
A Figura 10-1 mostra um PC conectado a um servidor UNIX através de TCP / IP.
Conexões entre nós mostram o caminho de comunicação sobre o qual o sistema vai
interagir.
Diagramas de Componentes
Um diagrama de componentes mostra os vários componentes em um sistema e suas
dependências.

DIAGRAMAS Físicos

Figura 10-1: Diagrama de Utilização

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM—PADRÃO DE MODELAGEM DE


OBJETOS
Um componente representa um módulo físico do código. Um componente é,
freqüentemente, o mesmo que um pacote, mas ele pode ser diferente, uma vez que
componentes representam o empacotamento físico do código. Como tal, uma classe
única pode estar presente em componentes múltiplos, mas esta classe pode ser
definida em apenas um pacote. Por exemplo, a classe string de Java é parte do
pacote java.lang, mas ela aparece em muitos componentes.
As dependências entre componentes mostram como mudanças em um componente
podem causar mudanças em outros componentes. Existe uma variedade de
dependências que você pode usar, incluindo dependências de compilação e de
comunicação. Freqüentemente, uso este tipo de dependência para mostrar que
componentes se comunicam uns com os outros.
Combinando Componentes com Diagramas de Uti1izaço
Embora possa projetar em separado o diagrama de utilização e o diagrama de
componentes, você também pode colocar o diagrama de componentes no diagrama
de utilização, como fiz na Figura 10-1. Você pode fazer isso para mostrar quais
componentes funcionam em que nós.
Então, no diagrama, a Interface de Usuário da Unidade de Fígado e a Fachada de
Cliente da Unidade de Fígado funcionam em um PC Windows. A TU da Unidade de
Fígado é dependente da Fachada do Cliente da Unidade de Fígado, uma vez que ela
aciona métodos específicos na Fachada. Embora a comunicação seja bidirecional, no
sentido de que a Fachada devolve os dados, a Fachada não está ciente de quem está
acionando e, portanto, não é dependente da IU da Unidade de Fígado. Em
contrapartida, na comunicação entre dois componentes do domínio de Saúde, os dois
estão cientes de que estão falando com outro componente de Saúde, então a
dependência de comunicação é bidirecional. Os dois componentes de domínio
funcionam em nós separados.
Um componente pode ter mais do que uma interface, neste caso você pode ver quais
componentes comunicam com cada interface. Na Figura 10-1, a aplicação do servidor
tem duas interfaces. Uma interface é usada pela fachada de aplicação rodando em
um PC; a outra interface é usada por um componente de configuração funcionando
em um servidor.
O uso de múltiplos componentes do Domínio de Saúde é escondido de seus clientes.
Cada componente de Domínio de Saúde tem um banco de dados local.
As pessoas, projetam, freqüentemente, estes tipos de diagramas com símbolos que
se parecem com os vários elementos. Por exemplo, elas usam ícones especiais para
servidores, PC e bancos de dados. Isso é válido em UML: você pode tratar cada ícone
como um estereótipo de um elemento de diagrama apropriado. Geralmente, tais
ícones facilitam a compreensão do diagrama, embora eles se tornem confusos se
você mostrar nós e componentes juntos, como fiz na Figura 10-1.

\134r DTAGRAMAS Físicos


Quando Utilizar Diagramas Físicos
A maioria das pessoas projeta este tipo de informação informalmente, mas as
pessoas estão gradualmente formalizando os diagramas para se adaptarem a UML.
Projeto estes diagramas sempre que tenho que mostrar informação física que é
diferente da informação lógica associada. Na maioria das vezes, penso que eu
desenho, no mínimo, um diagrama que mostra nós e componentes maiores, no estilo
da Figura 10-1. Uso ícones pictoriais se posso fazer isso sem que o diagrama fique
muito confuso.

11
UML e Programação
Até agora, eu abordei muito notação. Uma questão importante ainda não ficou clara:
como um programador usa realmente UML como parte de seu difícil trabalho diário
de programação? Responderei a esta pergunta abordando sobre como utilizo UML
quando estou programando, mesmo em pequena escala. Não entrarei em muitos
detalhes, mas espero poder lhe dar uma noção do que você pode fazer com UML.
Imaginemos um sistema de computador projetado para reunir informações
sobre pacientes para um hospital.
Vários profissionais da área da saúde fazem observações sobre os pacientes. Este
sistema simples permitirá que alguém obtenha informações sobre estas observações
e acrescente observações adicionais. Como este é um livro curto, passarei por cima
de ligações de bancos de dados e TU e considerarei somente as classes básicas de
domínio.
Este é um exemplo tão simples que tem apenas um caso de uso, chamado
“revisar e acrescentar informações de pacientes”. Podemos elaborar este caso com
alguns cenários.
• Pedir a última medida de batimento cardíaco de um paciente.
• Pedir o tipo sangüíneo de um paciente.
• Atualizar o nível de consciência do paciente.
• Atualizar o batimento cardíaco do paciente. O sistema marca o batimento como
lento, normal ou rápido, de acordo com os escopos definidos no
sistema.
Meu primeiro passo no processo é sugerir um modelo conceitual que descreva os
modelos neste domínio. Neste estágio, não estou pensando em como o software
trabalhará, somente em como organizar os conceitos que estão nas mentes de
médicos e enfermeiras. Iniciarei com um modelo baseado em vários pa

UML E PROGRAMÇÃO
drões de análise de Fowler (1997): Observação (Observation), Quantidade (Quantity),
Escopo (Range) e Fenômeno com Escopo (Pheno,nenon with range).
Observação de Pacientes: Modelo de Domínio
A Figura 11-1 mostra um modelo de domínio inicial para o nosso sistema.
Tipo de Fenômeno Fenômeno
_____________________________________ escopo:Escopo
o..1 *
11
**
Medição Categoria
valor:Quantidade _________________________ estáPresente:Booleano
medição [ _______ ________ _________________
*
Paciente
Quantidade Escopo
________________ Unidade ________________
valor:Número superior:Magnitude
unidade:Unidade inferior:Magnitude
Figura 11-1: Modelo de Domínio de Observação de Pacientes

UML ESSENCIAL: UM BREvE GUIA PARA A LINGUAGEM—PADRÃO DE MODELAGEM DE


OBJETOS

Como estes conceitos representam a informação do domínio?


Começarei com os conceitos simples de Quantidade, Unidade e Escopo. Quantidade
representa um valor dimensionado, tal como 6 metros — uma quantidade com valor
de 6 e unidade em metros. As unidades são simplesmente aquelas categorias de
medida com as quais queremos lidar. Escopo nos permite abordar sobre escopos
como conceito simples — por exemplo, um escopo de 4 metros para 6 metros é
representado como um objeto de escopo único com limite superior de
6 metros e um limite inferior de 4 metros. Em geral, os escopos podem ser expressos
em termos de qualquer coisa que possa ser comparada (usando os operadores
<,>,<=, > e =), portanto, os limites superiores e inferiores de escopos são ambos
grandezas (Quantidades são um tipo de grandeza).
Cada observação feita por um médico ou por uma enfermeira é uma instância do
conceito de Observação e é tanto uma Medição quanto uma Categoria (de
observação). Então, a medição de uma altura de 1,8 metro para Martin Fowler
representaria uma instância de Medição. Associada com essa medição ocorreram a
quantidade de 1,8 metro, o Tipo de Fenômeno “altura”, e o Paciente, chamado de
Martin Fowler. Tipo de Fenômeno representa as coisas que podem ser medidas:
altura, peso, batimento cardíaco e assim por diante.
Uma observação de que o tipo sangüíneo de Martin Fowler é O seria representada
como uma Categoria cujo Fenômeno associado é “grupo sangüíneo O”.
Este Fenômeno é ligado ao Tipo de Fenômeno “grupo sangüíneo”
O diagrama de objetos na Figura 11-2 deve esclarecer um pouco as coisas a esta
altura.

Figura 11-2: Diagrama de Objetos de Observação de Pacientes

UML E PROGRAMÇÃO

A Figura 11-3 mostra que podemos fazer uma Observação servir tanto para uma
Medição quanto para uma Categoria, determinando que a Medição de “90
batimentos por minuto” também pode ser uma Categoria, cujo Fenômeno associado
é “batimento cardíaco rápido”.
Neste estágio, detive-me apenas em representação de conceitos; não me concentrei
muito em comportamento. Não faço sempre isso, mas parece um bom ponto de
partida para um problema que diz respeito, principalmente, ao manuseio de
informações.
No momento, ainda estou discutindo conceitos de observação de paciente, bem
como estaria fazendo com um médico ou enfermeira. (Na verdade, isso é o que
acontece na vida real. Os modelos conceituais foram construídos por dois médicos e
por uma enfermeira, com a minha ajuda.) Para fazer a mudança para

\138 7’
v

Figura 11 -3: Outro Diagrama de Objetos de Observação de Pacientes

UML ESSENCIAL: UM BREVE GUIA PARA A LINCUAL,EM—PAVKAO DE IVIUDELA(,EM DE


LBJETOS 139/
um programa orientado a objeto, tenho que decidir como lidar com o quadro
conceitual em termos de softzvare. Para este exercício, escolhi a linguagem de
programação lava (Tinha que incluir lava de alguma forma neste livro1).
A maioria destes conceitos funcionará bem como classes Java. Paciente, Tipo de
Fenômeno, Fenômeno, Unidade e Quantidade funcionarão sem problemas. Os dois
itens difíceis são Escopo e Observação.
Escopo é um caso porque quero criar uma variação possível de quantidades para um
Fenômeno. Posso fazer isso criando uma interface de “grandeza” e estabelecendo
que Quantidade implementa esta interface, mas isso geraria excessivo mapeamento
dinâmico de superclasse para subclasse (dozvncasting). Isso não acontece com
Smalltalk, e posso usar tipos parametrizados em C++. Para este exercício, prefiro
usar uma classe de Escopo de Quantidade que utilize o padrão Escopo.
Meu problema com Observação é que uma Observação pode ser tanto uma
Observação de Categoria quanto uma Medição ao mesmo tempo (veja Figura 11- 3.
Em Java, como na maioria das linguagens de programação, temos apenas
classificação única. Decidi lidar com isso permitindo que qualquer Observação tenha
um Fenômeno associado, que permite efetivamente que a classe de Observação
implemente tanto os conceitos de Observação como de Observação de Categoria).
Estas decisões não proporcionam um resultado perfeito, mas são um tipo de
imperfeição pragmática que permitem que o trabalho seja realizado. Não tente fazer
softzvare que mapeie exatamente a perspectiva conceitual. Em vez disso, tente ser
fiel ao espírito da perspectiva conceitual, mas ainda realista considerando as
ferramentas que você estiver utilizando.
Observação de Pacientes: Modelo de Especificação
A Figura 11-4 reflete modificações que fiz no modelo de domínio para levar em
consideração alguns fatores associados à linguagem-alvo.
O modelo de observação de pacientes está agora na perspectiva de especificação.
Ele mostra as interfaces de classe, em vez de mostrar as próprias classes. Posso
manter o modelo conceitual para um outro dia, mas, mais provavelmente, trabalharei
somente com o modelo de especificação daqui por diante. Procuro não manter
muitos modelos ao meu redor. Meu princípio básico é que se eu não puder manter
um Modelo atualizado, jogo-o no lixo. (Eu sei, também sou preguiçoso!).
Agora vamos analisar o comportamento associado ao modelo de observação de
pacientes.
O primeiro cenário pede a última medida do batimento cardíaco do paciente. A
primeira pergunta é: de quem é a responsabilidade de executar este pedido? O
Paciente parece uma escolha natural. Ele precisa olhar todas as suas observações,
determinar quais são as medidas de Tipo de Fenômeno “batimento cardíaco”, e
encontrar o último valor. Para fazer isso, terei que acrescentar uma hora para a
Medida. Como isso também pode se aplicar a outras observações, a acrescentarei
também à Observação.

UML E PROGRAMÇÃO

Existe uma responsabilidade semelhante para Fenômeno: Encontre a última


Observação de Categoria que tenha um Fenômeno para um dado Tipo de Fenômeno.

A Figura 11-5 mostra operações que acrescentei ao Paciente para refletir o meu
pensamento.
Não coloque esforço demasiado em propor operações se elas não forem, neste
momento, óbvias, O mais importante a perseguir logo é uma descrição de
responsabilidade. Se você pode moldá-la na forma de uma operação, muito bem, se
não, uma frase curta é útil na descrição de uma responsabilidade.
A atualização do nível de consciência dos pacientes envolve a criação de uma nova
Observação do Fenômeno apropriado. Para fazer isso, o usuário do sistema,
normalmente, gostaria de escolher um Fenômeno de uma lista de opções (pop-up).
Podemos tratar isso acessando os objetos-fenômeno associados a um particular Tipo
de Fenômeno, uma vez que esta responsabilidade está implícita na associação entre
ambos.
Para adicionar uma medição, devemos criar uma nova Medição. Uma complicação
adicional surge do fato que a Medição necessita olhar para verificar se

Figura 11-4: Modelo de Especificação de Observação de Pacientes

UIVIL liSSENCIAL: UM tSREVE U1A PARA A LTNGUAGEM—i’ADRAO DE MODELAGEM DE


OBJETOS
Tipo de Fenômeno 1 * Medição
__________________ valor: Quantidade
o»1 ____
Observação
Fenomeno * _______________
escopo:Escopo_ hora da medida
de_Quantidade
*
1
Paciente
últimoValorde (Tipo de Fenômeno) : Quantidade
fenômenode (Tipo de Fenômeno) : Fenômeno
Figura 11-5: Operações de Observação de Pacientes
existe um fenômeno que possa lhe ser assinalado. Aqui, a Medição pode perguntar
para seus Tipos de Fenômeno associados se existe um Fenômeno para designar.
Existe, aqui, uma certa colaboração entre objetos. Isso sugere que este é um
bom espaço para um diagrama de seqüência (veja Figura 11-6).
Você tem que projetar todos estes diagramas?
Não necessariamente. Depende muito de quão bem você pode visualizar o que está
acontecendo e com que facilidade você pode trabalhar com a sua linguagem de
programação. Em Smalltalk, é quase sempre tão fácil escrever o código quanto
pensar com diagramas. Em C++, os diagramas são mais úteis.
Os diagramas não precisam ser obras de arte. Rabisco-os, geralmente, em um
caderno ou em um pequeno quadro branco. Transfiro-os para uma ferramenta de
desenho (ou ferramenta CASE) somente se acreditar que vale a pena o esforço de
mantê-los atualizados porque eles ajudam a esclarecer o comportamento das
classes. A esta altura em um projeto, posso também utilizar cartões CRC (veja página
78) em adição, ou em vez dos diagramas que estou descrevendo neste capítulo.

UML E 1ROGRAMÇAO
new 7 1
— uma Medição batimento cardíaco: batimento cardíaco: batimento cardíaco:
— de Fenomeno lento: Fenômeno normal: Fenômeno
achar Fenômeno()
inclui (Quantidade)
falso
inclui (Quantidade)
verdadeiro
E-
batimento
cardíaco normal
Figura 11 6: Diagrama de Seqüência de Observação de Pacientes
Passando para Código
Agora, podemos analisar algum código para implementação das idéias que discuti
nas seções anteriores. Começarei com Tipo de Fenômeno e fenômeno, uma vez que
eles têm muita ligação.
A primeira coisa a considerar é a associação entre eles: A interface deve permitir
navegabilidade nas duas direções? Neste caso, acredito que sim, porque as
duas direções serão valiosas e são conceitos muito ligados. Na verdade, também

UML ESSENCIAL UM GREVE (UIA PARA A LINGUAGEM—1ADRA0 DE IVIODELAGEM DE


UEJEIDS 1437
gosto de implementar a associação com ponteiros bidirecionais. Devo implementar,
entretanto, uma associação imutável porque eles são objetos que são criados e
depois deixados em paz - eles não são freqüentemente modificados, e quando os
são, podemos criá-los novamente.
Algumas pessoas têm problemas com ligações bidirecionais. Não as considero
problemáticas, se eu garantir que uma classe assume a responsabilidade global em
manter a associação atualizada, podendo ser assistida por um “friend” ou por um
método auxiliar, conforme for necessário.
Observemos algumas declarações.:*
public class TipoDeFenomeno extends ObjetoD000minio { public TipoDeFenomeno
(String nome)
super (nome);
void adicionaFenomeno(Fenomeno novoFenomeno) {
// RESTRIÇÃO: apenas usado por Fenomeno
fenomenos .addElement (novoFenomeno);
public void criaFenomenos(String[1 nomes) {
for (int i= O; i < nomes.length; i++)
new Fenomeno(nomes[i], this);
public Enumeration fenomenos() {
return _fenomenos . elements
private Vector fenomenos = new Vector
private EscopoDeQuantidade _escopoValido;
Usei a convenção de adicionar um sublinhado antes de todos os campos. Isto
ajuda a evitar que meus nomes se tornem confusos.
public class TipoDeFenomeno extends ObjetoDoDominio
public Fenomeno(String nome,TipoDeFenomeno tipo){
super (nome);
_tipo = tipo
_tipo.adicionaFenomeno (this)
public TipoDeFenomeno tipoDeFenomeno() {
return _tipO;
as ____________________________________________________
N . de T.: As linhas de código foram traduzidas do original.

UML E 1ROGRAMÇÃO
private TipoDeFenomeno _tipo;
private EscopoDeQuantidade _escopo;
package observações;
public class ObjetoDoDominio f
public ObjetoDoDominio (String nome) {
_nome = nome;
public ObjetoDoDominio ()
public String nome()
return _nome;
public String toString() {
return _nome;
protected String _nome = “sem nome”
Eu acrescentei uma classe ObjetoDoDominio, que conhece nomes e que realizará
qualquer outro comportamento que eu queira que todas as classes de domínio
tenham.
Eu agora posso criar o código destes objetos ao longo das seguintes linhas:
TipoDeFenomeno sexo =
new TipoDeFenomeno( “sexo”) .persist O;
String[] sexos = {“masculino”, “feminino”};
sexo. criaFenomenos (sexos);
A operação persistO armazena o TipoDeFenomeno em um objeto persistente de
modo que eu possa recuperá-lo mais tarde com o método estático getO. Eu vou pular
estes detalhes.
A seguir, eu prepararei o código para acrescentar observações a um paciente. Aqui
eu não quero que todas as associações sejam bidirecionais. Eu ligarei o paciente a
uma coleção de observações, uma vez que elas são usadas no contexto de um
paciente.
public class Observaçao extends ObjetoDoDominio {
public Observaçao (Fenomeno fenomenoRelevante,
Paciente paciente, Date quandoObservado) {
fenomeno= fenomenoRelevante;
Paciente . adicionaObservaçoes (this);
_quandoObservado = quandoObservado;

UML IjSSENCIAL: UM I3REVE (,UIA PARA A LINGUAGEM—PADRAO DE MODELAGEM DE


IJBIETOS

private Fenomeno _fenomeno

private Date _quandoObservado;

public class Paciente extends ObjetoDoDominio { public Paciente(String nome) {


super (nome)

void adicionaObservaçoes (Observaçao novaObservaçao) {


_observaçoes.addElement (novaObservaçao);

private Vector _observaçoes = new Vector();

Com isto nós podemos criar observações.

new Paciente(”Adams”) .persistO;


new Observaçao (TipoDeFenomeno . get ( “sexo”)
FenomenoComNome( “masculino”), Paciente.get (“Adams”),
new Date (96, 3, 1);
class TipoDeFenomeno {
public Fenomeno FenomenoComNome (String nome) {
Enumeration e = fenomenos O;
while (e.hasMoreElements()

{
}

Fenomeno each = (Fenomeno)e.nextElement() if (each.nome() .equals(nome))


return each;

return nuil;

Após criar observações, eu preciso ser capaz de achar os Fenômenos mais recen tes.
Class Paciente
public Fenomeno fenomenoDeTipo
(TipoDeFenomeno tipoDeFenomeno)

return (ultimaObservaçao (tipoDeFenomeno) == nuil ? new FenomenoNulo


ultimaObservaçao (tipoDeFenomeno) .fenomeno() );

i46 UML s PROGRAMÇÃO


private Observaçao
ultimaObservaçao (TipoDeFenomeno valor) {
return ultimaObservaçaoEm (observaçoesDe (valor) );
private Enumeration
observaçoesfle (TipoDeFenomeno valor) i.
Vector resultado = new Vector
Enumeration e = observaçoes()
while (e.hasMoreElements()
Observaçao cada (Observaçao)e.nextElementU;
if (cada.tipoDeFenomeno() == valor)
resultado. addElement (cada);
return resultado. elements O;
Private Observaçao ultimaObservaçaoEm
(Enumeration enumObservaçao) {
if (!enumObservaçao.hasMoreElements ()
return nuli;
Observaçao resultado =
(Observaçao) enumObservaçao . nextElement O;
if (!enumObservaçao.hasMoreElements()
return resultado;
do
{
Observaçao cada =
(Observaçao) enumObservaçao . nextElement O;
if (cada.quandoObservadoO.
after (resultado . quandoobservado ()
resultado = cada;
while (enumObservaçao.hasMoreElements() );
return resultado;
class Observaçao
public TipoDeFenomeno tipoDeFenomeno() {
return _fenomeno. tipoDeFenomeno O;
Vários métodos combinam para fazer isto. Você poderia projetar um diagrama para
mostrar isto, mas eu não costumo fazê-lo. A maneira como eu decomponho um
método tem mais a ver com refatoraçao (veja página 41) do que com o projeto
anterior.

w
li UML tSSENC1AL: UM bREVE U,UIA PARA A LINGUAGEM—I’ADRÃO DE MODELAGEM
DE OBJETOS
Agora nós podemos examinar o acréscimo de comportamento para medições.
Primeiro, vejamos a definição de classe Medição e o seu construtor.
public class Mediçao extends Observaçao
public Mediçao (Quantidade quantidade,
TipoDeFenomeno tipoDeFenomeno,
Paciente paciente, Date quandoObservado) {
initialize (paciente, quandoObservado);
_quantidade quantidade;
_tipoDeFenomeno = tipoDeFenomeno
public TipoDeFenomeno tipoDeFenomeno()
return _tipoDeFenomeno;
public String toString()
return _tipoDeFenomeno ÷ “: “ + _quantidade;
private Quantidade _quantidade;
private TipoDeFenomeno _tipoDeFenomeno;
class Observaçao
protected void initalize(Paciente paciente,
Date quandoObservado) {
paciente. adicionaObservaçoes (this);
_quandoObservado = quandoObservado;
Observe que um diagrama de classes nos dá um bom começo para este
desenvolvimento.
Mais uma vez necessitamos medições mais recentes.
Class Paciente
public Quantidade ultimaQuantidadeDe (TipoDeFenomeno
valor) {
Return ((ultimaMedia(valor) == nuil) ) ?
new
QuantidadeNula() :ultimaMediçao (valor) .quantidadeO;
private Mediçao
ultimaMediçao (TipoDeFenomeno valor) {
rama if (ultimaobservaçao(valor) == nuil)
)OflhO return nuli;
rojeto if (!ult±maObservaçao(valor) . isMeasurement()
return nuli;

—--,-

UML E PRU(,KAMÇAU
return (Mediçao)ultimaObservaçao (valor)
Em ambos casos, o diagrama de classes sugere a estrutura básica, e nós
acrescentamos comportamento a ele para suportar consultas mais interessantes.
Neste estágio, nós poderíamos descrever nossa posição com o diagrama de
classes na perspectiva de especificação mostrado na Figura 11-7 (ao lado).
Observe como esse diagrama salienta a interface em relação à implementação. Eu
modelei o papel do Tipo de Fenômeno para Fenômeno como um papel qualificado
porque esta é a interface primária no Tipo de Fenômeno. De maneira semelhante, eu
mostrei Observação com um ponteiro para Tipo de Fenômeno porque a interface
existe ali, embora Medição seja a única classe com um ponteiro direto para
Fenômeno.
Observando esse diagrama, nós podemos ver que a única, diferença entre Medição e
Observação é que Medição tem uma quantidade. Nós poderíamos remover
completamente a classe Medição do modelo de especificação, permitindo que
qualquer observação uma quantidade (potencialmente nula).
De outro modo nós poderíamos ter uma classe separada Medição, que teria campos
de quantidade e tipo de fenômeno, mas ninguém de fora do pacote estaria ciente da
existência destas classes. Nós precisaríamos acrescentar métodos Factory (Gamma,
Helm, Jonhson e Vlissides 1995) seja em Observação ou no Paciente para permitir
que a classe apropriada seja criada.
Eu deixarei esta mudança como um exercício para o leitor e passarei imediatamente
para a questão de atribuir um Fenômeno automaticamente para uma
Medição.
A Figura 11-7 ilustra o processo geral.
Primeiro, nós precisamos acrescentar uma chamada de metodokgia para o
construtor de Medição.
Class Mediçao
public Mediçao (Quantidade quantidade,
TipoDeFenomeno tipoDeFenomeno,
Paciente paciente, Date quandoobservado)
initialize (paciente, quandoObservado);
_quantidade = quantidade;
_tipoDeFenomeno = tipoDeFenomeno;
_fenomeno = determinaFenomenoPara(quantidade);
Isso delega a tarefa para tipo de fenômeno.
Class Mediçao
public Fenomeno determinaFenomenoPara (Quantidade arg)
return _tipoDeFenomeno. incluirFenomeno (arg),
Isto por sua vez consulta cada fenômeno.
Class TipoDeFenomeno
public Fenomeno incluirFenomeno (Quantidade arg)

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM—PADRÃO DE MODELAGEM DE


OHJETOS
Tipo de Fenômeno 1 Medição
scen- valor:Quantidade
rn de _________________
String
ação. L J
uali- 0.1
emeue
a
ireto
0.1, ____
entre __________ __________
* Observaçao
)S re- Fenômeno ________________
indo escopo:Escopo_ hora da medida
_deQuantidade
teria
t• * ______
:tory *
ente
iedi-
uma
Paciente
ra o
últimoValorde (Tipo de Fenômeno) : Quantidade
fenômenode (Tipo de Fenômeno) : Fenômeno
Figura 11-7: Outro Modelo de Especificação de Observação de Pacientes
Enumeration e = fenomenos O;
while (e.hasMoreElementsO)
Fenomeno cada = (Fenomeno) e.nextElementO;
if (cada.includes(arg))
return cada;
return nuli;
Class Fenomeno
public boolean includes (Quantidade arg)

1507 UML E PROGRAMÇÃO


return (_escopo == nuil ? false:_escopo.includes(arg));
O código flui bem a partir de um diagrama de seqüência. Na prática, uso,
geralmente, um diagrama de seqüência para esboçar a interação e, então, faço
algumas mudanças à medida que vou codificando. Se a interação for importante,
atualizarei o diagrama de seqüência como parte da minha documentação. Se achar
que o diagrama de seqüência não acrescenta muita clareza ao código, arquivo o
esboço do diagrama de seqüência no gabinete de arquivamento circular (cesta de
lixo).
Isso é um breve exemplo de como usar UML com uma linguagem de programação,
mas deve lhe dar uma boa idéia do processo. Você não tem que estar em um projeto
de muita formalidade para considerar útil algumas partes de UML. Você não tem que
usá-la toda, somente as partes que você achar necessárias.
Esboçar um projeto com um diagrama de classes e um diagrama de interação pode
ajudá-lo a pôr seus pensamentos em ordem e facilitar a codificação. Considero estes
esboços como protótipos rápidos. Você não precisa se ater aos diagramas mais tarde,
mas pode pensar que fica mais fácil para você e para os outros compreenderem o
código se você fizer isso.
Você não necessita de ferramentas CASE caras e cheias de recursos. Um quadro e
um simples editor gráfico no seu computador são suficientes. Certamente, existem
ferramentas CASE úteis e se você está envolvido com projetos maiores, pode até
pensar em obter tais ferramentas.
Se você fizer assim, compare-as com a linha-base de uma simples ferramenta de
desenho e um processador de textos. (É incrível o quanto você pode fazer com Visio
e Word, por exemplo). Se a ferramenta tem geração de código, observe atentamente
como ela gera o código. Um gerador de código força a ferramenta CASE a fazer uma
interpretação muito particular dos diagramas, que afetará a maneira com a qual você
projeta os diagramas e o que os diagramas significam.
Você pode encontrar mais sobre este exemplo no meu site na Web. A versão
do exemplo no site aprofunda algumas questões de camadas envolvidas no projeto
de uma interface de usuário para o modelo.

Apêndice A
Técnicas e suas Aplicações

Técnica Objetivo

Mostra comportamento com estrutura de controle.


Diagrama de Pode mostrar muitos objetos em muitos usos, muitos objetos em caso
Atividades de uso único ou a implementação de métodos. Encoraja
comportamento paralelo.

Mostra estrutura estática de conceitos, tipos e classes. Conceitos


Diagrama de mostram como os usuários pensam sobre o mundo; tipos mostram
Classes interfaces de componentes de software; classes mostram
implementação de componentes de software.

Ajudam a chegar à essência do objetivo de uma classe. Bons para


Cartões CRC explorar como implementar casos de uso. Use se você ficar atolado em
detalhes ou se estiver aprendendo a usar objetos.

Diagrama de
Mostra o layout físico dos componentes nos nós de hardware.
Utilização

APÊNDICE A — TÉCNICAS E SUAS APLICAÇÕES

Técnica

Projeto por Contrato

Diagrama de Interação

Diagrama de Pacotes

Padrões

Refatoração

Diagrama de Estados

Casos de Uso
Objetivo

Fornece uma definição rigorosa do objetivo


da

operação e do estado legal da classe.


Codifique

estes contratos nas classes para facilitar a


depu ração.

Mostra como vários objetos colaboram em um


caso de uso único.

Mostra grupos de classes e as


dependências en tr

elas.

Oferece porções úteis de análise, projeto


e técni ca

de codificação. Bons exemplos para


aprendi zado

ponto de partida para projetos.

Ajuda a fazer mudanças em programas em fun


cionament

para melhorar a estrutura. Use quan d

o código estiver atrapalhando a construção

de um bom projeto.

Mostra como um único objeto se


comporta através
de muitos casos de uso.

Elicitam requisitos de usuários em partes


significativas

Planejamento de construção é feito pela

implementação de alguns casos de uso em


cada

iteração. Base para testes de sistema.

Apêndice B
da
que
Mudanças entre
um Versões de UML
endi
-
Quando a primeira edição deste livro apareceu nas prateleiras, UML estava na versão
1.0. Muito de UML parecia ter se estabilizado e estava no processo de
reconhecimento pela OMG. Desde então, algumas revisões têm sido feitas. Neste
apêndice, descrevo as mudanças significativas que ocorreram desde a versão 1.0 e
como estas mudanças afetam o material deste livro.
Este apêndice resume as mudanças de modo que você possa se manter atualizado
se tiver uma edição mais antiga do livro. Fiz alterações no livro para mantêlo
atualizado com as versões UML, portanto, se você tem uma versão mais antiga do
livro, ele descreve a situação na data da publicação.
Revisões de UML
O lançamento público mais antigo do que veio a ser UML era a versão 0.8 da
Metodologia Unificada. Ela foi lançada para a OOPSLA, em outubro de 1995. Ela foi
trabalho de Booch e Rumbaugh, pois Jacobson ainda não era membro da Rational
naquela época. Em 1996, a Rational lançou as versões 0.9 e 0.91 que incluíam o
trabalho de Jacobson. Depois desta última versão, eles mudaram o nome para UML.
A Rational submeteu a versão 1.0 de UML para a Força-Tarefa de Projeto e Análise da
OMG em janeiro de 1997. Subseqüentemente, a Rational combinou aquela versão da
UML com outros itens e submeteu uma proposta única para o padrão OMG em
setembro de 1997, para a versão 1.1 da UML. Esta foi adotada

154/ APËNDICE B — MUDANÇAS ENTRE VERSOES DE LML


pela OMG no final de 1997. Entretanto, devido a uma confusão, a OMG chamou esta
versão padrão 1.0. Então, UML era tanto a versão 1.0 da OMG quanto a versão 1.1 da
Rational, para não ser confudida com a 1.0 da Rational. Na prática, todos chamam
esta versão de padrão Li.
UML 1.1 teve algumas pequenas mudanças visíveis em relação à versão 1.0.
Na adoção da UML 1.1, a OMG estabeleceu uma Força-Tarefa de Revisão (RTF),
presidida por Cris Kobryn, para amarrar várias pontas soltas associadas com UML. A
OMG lançou a versão 1.2 em julho de 1998. Este lançamento foi interno, de modo
que a versão 1.1 permaneceu o padrão UML oficial. Você poderia imaginar que a
versão 1.2 seria um segundo lançamento. Na prática, esta distinção pouco importou,
uma vez que as únicas alteraçõess no padrão foram editoriais: corrigindo tipos
ortográficos, erros gramaticais e coisas dessa ordem.
Uma mudança mais significativa ocorreu com a versão 1.3. Novamente, foi um
lançamento interno, portanto, não um padrão OMG oficial. Entretanto, as mudanças
foram mais significativas desta vez, afetando mais notadamente casos de uso e
diagramas de atividade, O User Guide e o Reference Manual dos amigos foram
publicados no final de 1998; estes livros repercutiram as mudanças da versão 1.3,
antes que os documentos oficiais 1.3 se tornassem públicos, o que causou alguma
confusão.
Cronograma de Revisões Futuras
Este livro estará, certamente, desatualizado quando você o ler. Para uma visão mais
atualizada, visite o meu endereço na Web: http://ourworld.compuserve.com/
homepages/martin_fowler.
Os documentos da versão 1.3 estão agora disponíveis para comentários públicos. Por
volta de abril de 1999, a RTF submeteu uma UML revisada a OMG, que
será chamada versão 1.4, A RTF espera que a única diferença entre as versões 1.3
e 1.4 tenha a ver com polimento. A não ser que algo muito estranho aconteça, a
OMG adotará, então, a versão 1.4 como um novo padrão oficial em algum dia de
1999.
A esta altura, a Força-Tarefa de Projeto e Análise da OMG tomará conta de
UML e de todas considerações sobre movimentos futuros.
Mudanças em “UML Essencial”
À medida que estas revisões em UML acontecem, tenho tentado revisar o livro
nas impressões subseqüentes.
UML 1.0 foi usada como base da primeira à quinta impressão. Quaisquer mudanças
na UML entre estas impressões foram mínimas. A sexta impressão levou em
consideração UML 1.1; entretanto, devido a uma pequena falha, as contra-capas
ainda mostravam a notação 1.0.

UML ESSENCIAL: UM BREVE GUIA PARA A LINGUAGEM—PADRÃO DE MODELAGEM DE


OBJETOS
ou Da sétima à décima impressão, a UML 1.2 foi usada como base; a décima ver-
impressão foi a primeira a usar UML 1.3. Edições baseadas em versões da UML ica
posteriores a 1.1 têm o número de versão UML na capa. (Infelizmente, um erro de
impressão fez com que algumas cópias da décima impressão tenham sido rotula o
das como 1.3 — lamento).
A primeira impressão da segunda edição é baseada na versão 1.3. Sem uma das bola
de cristal, não posso dizer no que as edições posteriores serão baseadas.
foi No resto deste apêndice, resumirei as duas maiores mudanças em UML, da de- LO
a 1.1 e da 1.2 a 1.3. Não discutirei todas as mudanças que acontecem, mas
somente aquelas que mudam algo que eu disse no UML Essencial, ou representam
to- características importantes que eu teria discutido no UML Essencial.
Continuo a seguir o espírito do UML Essencial: discutindo os elementos-chafoi ve da
UML à medida que eles afetam a aplicação de UML em projetos de mundo as real.
Como sempre, as seleções e os conselhos são meus. Se houver algum conflito
entre o que eu digo e os documentos UML oficiais, os documentos UML é que
devem ser seguidos. (Mas me informem, de modo que eu possa fazer correções).
‘er- Também aproveitei a oportunidade para indicar erros e omissões importantes das
edições anteriores, graças aos leitores que me mostraram estes erros.
Mudanças de UML 1.0 para 1.1
Tipo e Classe de Implementação
ao
Na primeira edição da LJML Essencial, abordei perspectivas e como elas alteravam
a maneira como as pessoas projetavam e interpretavam modelos — particularmente
diagramas de classes. UML leva isso, agora, em consideração, dizendo que todas
ue as classes em um diagrama de classes podem ser especializadas tanto como tipos

[3 quanto como classes de implementação.


a Uma classe de implementação corresponde a uma classe no ambiente de softzvare
no qual você está programando. Um tipo é um pouco mais nebuloso; ele
representa uma abstração não tão amarrada à implementação.
Poderia ser um tipo CORBA, uma perspectiva de especificação de uma classe, ou
uma perspectiva conceitual. Se necessário, você pode acrescentar estereótipo para
diferenciar ainda mais.
Você pode determinar que, para um diagrama, todas as classes sigam um
estereótipo específico.. Isso é o que você faria projetando um diagrama de uma
perspectiva particular. A perspectiva de implementação usaria classes de
implementação, enquanto as perspectivas conceituais e de especificação usariam
tipos.
Você usa o relacionamento de realização para indicar que uma classe de
implementação implementa um ou mais tipos.
Existe uma distinção entre tipo e interface. Uma interface tem como objetivo
corresponder diretamente a uma interface de estilo COM ou Java. Portanto,
interfaces só têm operações e não atributos.

APÊNDICE B — MUDANÇAS ENFRE VERSÕES DE UML


Você pode usar somente classificação estática e única com classes de
implementação, mas pode usar classificação dinâmica e múltipla com tipos (Acredito
que isso ocorre porque as linguagens 00 mais importantes seguem classificação
estática e única. Se um dia você usar uma linguagem que suporta uma classificação
dinâmica ou múltipla, aquela restrição não deveria, realmente, ser aplicada).
Restrições Discriminadoras Completas e Incompletas
Nas edições anteriores da LJML Essencial, afirmei que uma restrição {complete} em
uma generalização indicava que todas as instâncias de supertipos devem também
ser uma instância de um subtipo dentro daquela partição.
Em vez disso, UML 1.1 define que {complete} indica que todos os subtipos dentro de
uma partição foram especificados, o que não é bem a mesma coisa. Encontrei
alguma inconsistência na interpretação desta restrição, então você deve ser
cauteloso quanto a isso. Se você quer indicar que todas as instâncias de um
supertipo devem ser uma instância de um dos subtipos, sugiro o uso de uma outra
restrição para evitar confusão. Atualmente, estou usando {mandatory 1.
Composição
Em UML 1.0, o uso da composição implicava que a ligação fosse imutável (ou frozen),
pelo menos para componentes de valor único. Esta restrição não faz mais parte da
restrição.
Imutabilidade e Congelamento
UML define a restrição {frozen) para definir a imutabilidade em papéis de associação.
Como ela é atualmente definida, não parece se aplicar a atributos ou classes. No
meu trabalho, uso, agora, o termo congelado (frozen) em vez de imutabilidade, e
aplico a restrição para papéis de associações, de classes e de atributos.
Retornos em Diagramas de Seqüência
Em UML 1.0, um retorno em diagramas de seqüência era diferenciado pelo uso de
uma flecha vazada em vez de uma flecha cheia (veja edições anteriores). Isso era um
pouco doloroso, uma vez que a distinção era muito sutil e fácil de passar
despercebida. UML 1.1 usa uma flecha pontilhada para retorno, o que me agrada,
pois isso torna os retornos mais óbvios. (Uma vez que usei retornos pontilhados no
livro Analysis Patterns, isto também me faz parecer influente). Você pode nomear o
que é retornado para uso posterior, usando a forma Estoquesuficiente: = verificarO.
UIVIL Jis5ENCIAL: UM DREVE ,UIA PARA A LINL,UAGEM—PADRÃO DE MODELAGEM DE
OBJETOS
Uso do Termo “Papel” (Role)
Em UML 1.0, o termo Role (papel) indicava, principalmente, uma direção em uma
associação (veja edições anteriores). UML 1.1 se refere a este uso como um papel de
associação. Existe também um papel de colaboração, que é o papel que uma
instância de uma classe desempenha em uma colaboração.
UML 1.1 coloca muito mais ênfase nas colaborações, e parece que este uso de “role”
pode se tornar o principal.
Mudanças de UML 1.2 (e 1.1) para 1.3 (e 1.4)
Casos de uso
As mudanças para casos de uso envolvem um novo relacionamento entre eles.
UML 1.1 tem duas relações de caso de uso: «uses» e «extends», os dois
sendo estereótipos de generalização. UML 1.3 oferece três relações.
• A construção «include» é um estereótipo de dependência. Isso indica que o
caminho de um caso de uso é incluído em outro. Tipicamente, isso ocorre quando
poucos casos de uso compartilham passos em comum. O caso de uso incluído pode
fatorar o comportamento comum. Um exemplo de um Caixa Automático pode ser
que tanto Retirar Dinheiro quanto Fazer Transferência usem Validar Cliente. Isso
substitui o uso comum de «uses».
• Generalização de caso de uso indica que um caso de uso é uma variação em um
outro. Portanto, podemos ter um caso para Retirar Dinheiro (o caso de uso-base) e
um caso de uso separado para lidar com o caso quando a retirada for recusada,
devido à falta de fundos. A recusa poderia ser tratada como um caso de uso que
especializa em caso de uso de retirada (você pode também lidar com isso apenas
como um outro cenário dentro do caso de uso Retirar Dinheiro). Uma especialização
de caso de uso como esta pode mudar qualquer aspecto do caso de uso-base.
• A construção «extends» é um estereótipo de dependência. Isso fornece uma forma
mais controlada de extensão do que o relacionamento de generalização. Aqui, o caso
de uso-base declara um número de pontos de extensão. O caso de uso estendido
pode alterar o comportamento somente naqueles pontos de extensão. Então, se você
está construindo um sistema de compras on-line, pode ter um caso de uso para
comprar um produto com pontos de extensão para capturar a informação de remessa
e capturar a informação de pagamento. Este caso de uso poderia, então, ser
estendido para um cliente regular para o qual esta informação seria obtida de forma
diferente.
Existe alguma confusão sobre a relação entre os relacionamentos antigos e os novos.

1.

de
‘re jf
as)li—

te}
m )OS
sa.

ve
rna

‘ou ais

)Cies.
de,

de
ra
3ar
ia,
los
lo-

158 r PNDICE B — MUDANÇAS ENTRE VERSÕES DE UML


A maioria das pessoas usava «uses» da mesma forma que «includes» é usado na
versão 1.3, então para a maioria das pessoas, podemos dizer que «includes»
substitui «uses». E a maioria das pessoas usava «extends» da versão 1.1 tanto na
maneira controlada da «extends» da 1.3 quanto como uma sobre-escrita geral no
estilo de generalização 1.3. Então, você pode pensar que «extends» da 1.1 foi
dividida em «extends» 1.3 e generalização.
Embora esta explicação cubra a maioria dos usos da UML que já vi, esta não é a
maneira estritamente correta de usar estas velhas relações. Entretanto, a maioria
das pessoas não seguiu o uso estrito, e não quero realmente entrar neste assunto
agora.
Diagramas de Atividades
Quando a UML atingiu a versão 1.2, surgiram algumas questões abertas sobre a
semântica dos diagramas de atividades. Assim, o trabalho da 1.3 envolveu muito
ajuste nesta semântica.
Para comportamento condicional, agora você pode usar a atividade de decisão, em
forma de losango, para uma intercalação de comportamentos bem como para uma
ramificação. Embora nem ramificações nem intercalações sejam necessárias para
descrever comportamento condicional, é um estilo cada vez mais comum mostrá-las,
de modo que você possa colocar o comportamento condicional entre parênteses.
A barra de sincronização é agora referida como separação (ao dividir o controle) ou
como junção (ao sincronizar o controle). Entretanto, você não pode mais acrescentar
condições arbitrárias às junções. Você deve seguir regras de combinação para
assegurar-se que separação e junção combinam. Essencialmente, isso significa que
cada separação deve ter uma junção correspondente que una os threads iniciados
por uma separação. Você pode alinhar separação e junção, embora você possa
eliminá-los no diagrama quando threads vão diretamente de uma separação para
uma outra separação (ou de uma junção para outra junção).
Junções são acionadas somente quando todos os threads de entrada se completam.
No entanto, você pode ter uma condição em um thread saindo de uma separação. Se
esta condição é falsa, aquele thread é considerado completo para propósito da
junção.
Acionamento múltiplo (multiple trigger) não está mais presente. No seu lugar, você
pode ter concorrência dinâmica em uma atividade (mostrado com um ““ dentro de
uma caixa de atividade). Tal atividade pode ser invocada várias vezes em paralelo;
todas suas invocações devem ser completadas, antes que qualquer transição de
saída possa ser tomada. Isso é vagamente equivalente , embora menos flexível, a um
acionamento múltiplo e condições de sincronização correspondentes.
Estas regras reduzem um pouco a flexibilidade dos diagramas de atividade, mas
asseguram que os diagramas de atividades são verdadeiramente casos especiais de
máquinas de estado. O relacionamento entre diagramas de atividades e máquina de
estado foi assunto de debate no RTF. Revisões futuras de UML (posteriores à versão
1.4) podem muito bem tornar diagramas de atividades em um diagrama de forma
completamente diferente.

1ides»
zer que
ends»
o como
ensar
estanão
Bibliografia
assunobre
a
muito
e decim
como
necespais
co ‘ciona
Kent Beck: Smalltalk Best Pra ctice Patterns. Prentice Hail, 1996.
Kent Beck: Ext reme Programming Explained: Embrace Change. AddisonWesley,
2000.
ma Kent Beck e Ward Cunningham: “A Laboratory for Teaching ObjectOriented
Thinking.”
L. is Proceedings of OOPS7—A 89. SIGPLANNot1ces, Vol. 24, No. 10, pp. 1-6. Veja
Object plLL1na Oriented <http: / /c2.com/doc /oopsla89/paper.html>.
te, isso
threads Grady Booch: Object-Oriented Analysis and Design with Applications, 2” ed.
Addison-Wesley,
tavocê 1994.
ração
Grady Booch: Object Solutions: Managing the Object-Oriented Project. Addison-
Wesley, 1996.
e com um
Grady Booch, James Rumbaugh e Ivar Jacobson [three amigos]: The Llnified Modeling
o para Language User Guide. Addison-Wesley, 1999.
1 Frank Buschmann, Regine Meunier, Hans Rohnert, Peter Sommerlad e Michael Stal:
seu U Pattern-Oriented Software Architecture: A System of Patterns. John Wiley &
Sons, 1996.
m um
varias Peter Coad e JilI Nicola: Object-Oriented Programming. Yourdon, 1993.
e qual nbor
Peter Coad e Edward Yourdon: Object-Oriented Analysis. Yourdon, 1991a.
torres Pete
Coad e Edward Yourdon: Object-Oriented Design. Yourdon, 1991b.
idade,
espe- Peter Coad, David North e Mark Mayfield: Object Modeis: Strategies, Patterns
and Applications.
des e Prentice Hali, 1995.
Alistair Cockburn: Surviving Object-Oriented Projects. Addison-Wesley, 1998.
les em

\160/ I3WLLO(,KAFIA
Steve Cook e John Daniels: Designing Object Systenis: Object-Oriented Modeling zvith
Syntropy.
Prentice Hail, 1994.
James O. Coplien: “A Generative Development Process Pattern Language.” In Coplien
e
Schmidt, 1995, pp. 183-237.
James O. Coplien e Douglas C. Schmidt, eds.: Pattern Languages of Program Design
[PLoPD1].
Addison-Wesley, 1995.
Ward Cunningham: “EPISODES: A Pattern Language of Competitive Development.” In
Vlissides, Coplien e Kerth, 1996, pp. 371-388.
Bruce Powel Douglass: Real-Time UME. Addison-Wesley, 1998.
Martin Fowler: Analysis Patterns: Reusable Object Modeis. Addison-Wesley, 1997.
Martin Fowler: Refactoring: Improving the Design of Existing Programs. Addison-
Wesley, 1999.
Erich Gamma, Richard Heim, Ralph Johnson e John Vlissides [Gang of Four]: Design
Patterns:
Elements of Reusable Object-Oriented Software. Addison-Wesley, 1995.
Adele Goldberg and Kenneth S. Rubin: Succeeding with Objects: Decision Frameworks
for
Project Management. Addison-Wesley, 1995.
David Harel: “Statecharts: A Visual Formalism for Complex Systems.” In Science
ofComputer
Programming, Vol. 8, 1987.
Ivar Jacobson, Grady Booch e James Rumbaugh [three amigos]: The Unified Software
Development Process. Addison-Wesley, 1999.
Ivar Jacobson, Magnus Christerson, Patrik Jonsson e Gunnar Õvergaard: Object-
Oriented
Software Engineering: A Use Case Driven Approach. Addison-Wesley, 1992.
Ivar Jacobson, Maria Ericsson e Agneta Jacobson: The Object Advantage: Business
Process
Reengineering with Object Technology. Addison-Wesley, 1995.
Andrew Koenig e Barbara Moo: Ruminations on C++: A Decade of Programming
Insight and
Experience. Addison-Wesley, 1997.
Philippe Kruchten: The Rational Unfied Process: An Introduction. Addison-Wesley,
1999.
Craig Larman: Applying UML and Patterns. Prentice Hali, 1998.
James Martin e James J. Odell: Object-Oriented Methods: A Foundation (UML Edition).
Prentice
Hali, 1998.
Robert Cecil Martin: Designing Object-Oriented C++ Applications: Using the Booch
Method.
Prentice Hali, 1995.

t1BLIOGRAF1A
Steve McConnell: Rapid Development: Taning Wild Software Schedules. Microsoft
Press, 1996.
Steve McConnell: Software Project Survival Guide. Microsoft Press, 1998.
Bertrand Meyer: Object-Oriented Software Construction. Prentice Hail, 1997.
William F. Opdyke: “Refactoring Object-Oriented Frameworks.” tese de Ph.D.,
University
of Illinois at Urbana-Champaign, 1992. Veja <ftp:// st.cs.uiuc.edu/pub/papers/
refactoring/opdyke-thesis.ps.Z>.
Trygve Reenskaug: Working with Objects. Prentice Hail, 1996.
James Rumbaugh: OMT Insights. STGS Books, 1996.
James Rumbaugh, Ivar Jacobson e Grady Booch [three amigos]: The Unified Modeling
Language Reference Manual. Addison-Wesley, 1999.
James Rumbaugh, Michael Blaha, William Premerlani, Frederick Eddy e William
Lorenzen:
Object-Oriented Modeling and Design. Prentice Hali, 1991.
Geri Schneider e Jason 1’. Winters: Applying Use Cases: A Practical Guide. Addison-
Wesley,
1998.
Sally Shlaer e Stephen J. Mellor: Object-Oriented Systems Analysis: Modeling the
World in
‘r Data. Yourdon, 1989.
Sally Shlaer e Stephen J. Meilor: Object Lfecycles: Modeling the World in States.
Yourdon,
e 1991.
Sally Shlaer e Stephen J. Melior: “Recursive Design of an Application Independent
d Architecture.” IEEE Software, Vol. 14, No. 1, 1997.
John M. Vlissides, James O. Coplien e Norman L. Kerth, eds.: Pattern Languages
ofProgram
Design 2 [PLoPD2]. Addison-Wesley, 1996.
Kim Walden e Jean-Marc Nerson: Seamless Object-Oriented Software Architecture:
Anal ysis
and Design of Reliable Systems. Prentice Hail, 1995.
Jos Warmer e Anneke Kleppe: The Object Constraint Language: Precise Modeling with
UMA.
Addison-Wesley, 1998.
Rebecca Wirfs-Brock, Brian Wilkerson e Lauren Wiener: Designing Object-Oriented
Software.
Prentice Hali, 1990.

4
A
Indice
A
ação 114 atividade
agregação no diagrama de atividades 121
definição 86 no diagrama de estados 114
exemplo 86 ator
amigo 102 definição 51
apagamento 74 descobrir 52
asserção notação 51
definição 67 atributo
papel na subclasse 69 definição 64
associação notação 64
bidirecional 62 atributo derivado
como ligação permanente 64 definição 87
como responsabilidade 60 exemplo 88
de nome 64 autochamada
definição 60 definição 73
navegabilidade 62 exemplos 72, 74
unidirecional 62 autotransição 117
versos subtipos 57
associação derivada
definição 87 B
exemplo 88
associação qualificada
definição 94 l3eck, Kent 20, 38, 48, 77, 79, 159
exemplo 95 Booch, Grady ix, 19, 20, 21, 26, 129, 159,
associação unidirecional 62 160, 161
Buschmann, Frank 159

\164/ ÍNDICE
v
caixa de ativação 73
campo 64
característica 66
cartões CRC 20, 25, 43, 70, 142, 151
definição 62
exemplo 79
quando utilizar 79
usando com casos de uso 79
casos de uso 152
capturando 53
categorizando 39
definição 26,50
determinando para iterações 39
e risco de requisitos 32
e risco tecnológico 36
em diagramas de atividades 129
em diagramas de iteração 71
quando utilizar 55
teste-exemplo 50
utilizando cartões CRC 79
cenário 49
classe abstrata
comparada à interface 92
notação 89
classe de associação
definição 96
exemplo 96
promovendo para uma classe cheia 96
sutilezas 97
classe de implementação 155
classe parametrizada
definição 98
exemplos 99
Classe-Responsabilidade-Colaboração
cartões (CRC)
veja cartões CRC
classificação
definição 83
exemplos 94
tipos 83, 85
classificação dinâmica
definição 93
exemplo 86
classificação estática 85
classificação múltipla
definição 83
exemplo 84
classificação única 83
Coad, Peter 20, 159
Cockburn, Alistair 48, 56, 159

Colaboração
definição 108
parametrizada 109
quando utilizar 111
Colaboração de responsabilidade de classe
componente 133
composição
definição 86, 156
notação 86, 87
concorrência dinâmica
definição 125
notação 125
condição 73
conexão 131
Cook, Steve 59, 69, 70, 119, 160
Coplien, James 160, 161
cso de uso de negócio 55
Cunninghan, Ward 20, 43, 77, 79, 159, 160

Daniels, John 59, 69, 70, 119, 160


decomposição funcional 103
dependência
e componentes 133
definição 103
diagramas de classes 91
versos e associação 64
depois da palavra-chave 116
desenvolvimento iterativo 25
definição 30
quando utilizar 47
diagrama de colaboração
comparado a diagrama de objetos 83
definição 76
exemplos 76, 77
versus diagramas de seqüência 77
diagrama de componentes
definição 131
no diagrama de utilização 133
diagrama de estados concorrentes
definição 117
exemplo 118
diagrama de instância
definição 82
exemplo 82
diagrama de interação 24, 25, 33, 36, 43, 44, 79, 118, 125, 127, 129, 152
definição 71
exemplos 72, 76, 77, 142
quando utilizar 80

tipos 71
diagrama de objetos
definição 82
exemplo 82
exemplos 137, 138
diagrama de seqüência 150
definição 72
exemplos 72, 74, 76, 108, 142
versus diagramas de colaboração 77
diagramas de atividades 26, 33, 44, 80, 118, 151
definição 121
exemplos 122, 126, 128
quando utilizar 127
diagramas de classes 24,25, 26,33,36,43, 44, 45, 103, 107, 147, 148, 151
definição 57
exemplos 45, 46 ,58, 63, 82, 82, 84, 86, 88, 89, 90, 91, 95, 96, 96, 98, 99, 100, 109,
110, 136, 140, 141, 149
perspectivas 59
quando utilizar 69
diagramas de estados 44, 80, 129, 152
definição 113
e diagramas de utilidade 121
exemplos 114, 115, 116, 119
quando utilizar 119
diagramas de pacote 24, 36, 43, 152
definição 103
exemplos 104, 106
quando utilizar 111
diagramas de utilização 36, 44, 151
definição 131
exemplo 132
quando utilizar 134
diagramas e casos de uso
definição 51
exemplos 51
discriminador 84
Douglass, Bruce Powel 26, 119, 160
E
Eiffel 67, 69
elemento de ligação
definição 99
exemplos 99, 100
engenharia de informação 103
escopo de classe 83

estado de atividade 121


estereótipo
em diagramas físicos 134
notação 82
estereótipo de classe de implementação 60
estereótipo de história 97, 98
estereótipo de ligação 100
estereótipo de tipo 60, 155
estereótipo global 107
estereótipos
bind 100
global 107
history 97, 98
tipo 60
evento de entrada 117
evento de saída 117
exceção 68
exemplos de códigos (lava) 61, 95, 98, 99, 143, 144,145, 145, 146, 147, 148, 149,
150
F
fase de construção
definição 30
descrição 40
na UML 43
planejamento 38
fase de elaboração
categoria de risco 32
construindo modelo de domínio 33
definição 30
descobrindo casos de uso 33, 55
descrição 31
terminando 38
fase de início
definição 30
descrição 31
fase de transição
definição 30
descrição 44
fenômeno com padrão de variação 136
fim de valor múltiplo 93
fins de associação 60
flozvcharts 123, 129
formalidade 30
Fowler, Martin 46, 67, 85, 97, 100, 136, 160
função 60,156
função de associação 156
função de colaboração 156

classe

INDICE

ÍNDICE

Gangue dos Quatro 45, 59, 67, 88, 105, 148, 160
generalização
definição 66
exemplos 94
usando com pacotes 107
generalização de casos de uso
definição 53
exemplo 51
quando utilizar 54
Goldberg, Adele 160
guarda
em diagramas de atividades 123
em diagramas de estados 114

Harel, David 113, 160


Hatfield, Tom ix,25
herança múltipla 83

inconstante 68
interface
comparada à classe abstrata 92
comparada a estereótipo de Tipo 155
pura 89
UML 82

ISE 69
iteração
determinando casos de uso 39
determinando comprimento 39
determinando número 39
elementos 30
natureza incremental 40
natureza iterativa 40

Jacobson, Ivar ix, 19, 20, 21, 26, 48, 49, 51, 73, 159, 160, 161
Johnson, Ralph 45, 160
Junção

definição 123 exemplos 122, 125

Kain, Brad 43
Kleppe, Anneke 67, 161
Kobryn, Cris 21
Koenig, Andrew 160
Kruchten, Philippe 30, 48, 160

Larman, Craig 26, 161


linguagem de modelagem 19
linha de vida 73
Loomis, Mary 21

marcador de iteração 73
Martin, James 20, 26, 79
Martin, Robert 111, 161
McConnell, Steve 48, 161
Mellor, Steve 20, 161
mensagem assíncrona 76
merge
definição 123
exemplos 122
metamodelo
definição 22
extrato 23
método de obtenção 65
metodologia 65
metodologia de ambiente 65
metodologia de objeto 21, 29, 49
metodologia unificada 21
metodologias de fábrica 148
Meyei Bertrand 67, 69, 161
modelo de domínio
construção 33, 34
definição 33
e diagramas de atividades 125
equipe 34
linhas gerais 34
utilizando casos de uso 33
modificador 65

ÍNDICE
multiplicidade e colaborações 109
definição 60 quando utilizar 47
exemplos 58 Veja também padrões de análise
Veja também padrões de projeto
padrões de análise
Ncenário 46
definição 46
exemplo 46
navegabilidade Fenômeno com Variação 136
definição 62 Mapeamento Histórico 97
exemplos 63 Modelos de Papéis 85
tipos 62 Observação 136
Nerson, Jean-Mark 69, 161 Quantidade 136
nó 131 Variação 100, 136 e 139
nome de função 60 padrões de modelos de função 85
notação 22 padrões de projeto
notação Lollypop 91,92 Composite 88
definição 45
exemplo 45
O Fachada 105
Proxy 45
palavra-chave quando 116
objeto de referência 92 perfil 82
objeto de valor 92 perspectiva conceitual
OCL (linguagem restringida a objeto) 67 associações 60
OCL 67 associações derivadas 89
Odeil, um ix, 20, 21, 26, 83, 121, 161 associações qualificadas 95
OMG (Object Managment Group) ix, 20, atributos 64
21 atributos derivados 89
OMT definição 26, 59
veja OMT exemplo 136
OMT 19, 20 generalização 66
Opdyke, William 161 operações 65
operação quando utilizar 69
definição 64, 65 perspectiva de especificação
notação 64 associações 60
orientação 36, 37 associações derivadas 89
otimização 44 associações qualificadas 95
atributos 64, 64
atributos derivados 89
definição 59
exemplos 140, 141, 149
generalização 66
pacote 103 navegabilidade 62
padrão composite 88 operações 64
padrão de cenário 46 quando utilizar 24, 69
padrão de fachada 105 realização 91
padrão de mapeamento histórico 97 subclasse 91
padrão de observação 136 subtipagem 107
padrão de quantidade 136 perspectiva de implementação
padrão de variação 30, 136, 139 associações 61
padrão Proxy associações derivadas 89
padrões 24, 25, 27, 44, 152 associações qualificadas 95, 96
definição 45 atributos 64

INDICE
atributos derivados 89 restrição completa 85, 156
definição 59 restrição dag 93
generalização 66 restrição de bag 93
navegabilidade 62 restrição de congelamento 93, 156
operações 64 restrição de pedido 93
quando utilizar 62 restrição Hierarchy 93
perspectivas 59 restrição imutável 93
plano restrição obrigatório 156
construindo 38 restrição query 65
gerenciando 41 restrições 67
plano de implementação 39 abstrata 89, 107
pós-condição 67 bag 93
pré-condição 68 completa 85, 156
processo congelada 93, 156
definição 19 consulta 65
fases30 dag93
visão geral 30 hierarquia 93
Programação Extrema 38, 48 imutabilidade 93
projeto dirigido - responsabilidade 20 obrigatória 156
projeto por contrato 152 pedida 93
definição 67 somente leitura 93
quando utilizar 69 restrictor read only 93
projeto recursivo 20 retorno 73, 148
prototipação 35 risco
categorias 32
lidando com 32, 35, 36, 38
Q risco de habilidade
definição 32
lidando com 36
query 60, 65 risco de requisito
definição 32
lidando com 32
risco político
definição 32
lidando com 38
raia risco tecnológico
definida 125 definição 32
exemplos 128 lidando com 35
realização 90, 92 Rubin, Kenneth S. 160
redes Petry 121 Rumbaugh, Jim ix,19, 20, 21, 26, 86, 129,
Reenskaug, Traygve 109, 161 159, 160, 161
refatoração 40, 108, 146, 152 RUP (Rational unzfied process) 20, 29, 30, 33,
definição 42 48
princípios 43
relação transitiva 104
relacionamento de inclusão
definição 53 S
exemplo 51
quando utilizar 54 Scheider, eri 161
relacionamento estendido SDL 121
definição 54 seção
quando utilizar 54 definição 123
responsabilidade 60, 61, 79 exemplos 122
restrição abstrata 89, 107

Separação 123
definição 123
exemplos 122, 125
Shlaer, Sally 20, 161
sistema de caso de uso 55
softzvare de autoteste 41
software Rational 20, 21
STL 100
subclassificação 67, 69, 89, 92
substituibilidade
definição 66
e asserções 69
subtipagem 67, 100
subtipo 57
superestado 115,116

visibilidade
definição 100
dentro de C++ 101
dentro de lava 101
dentro de Smalltalk 101
visibilidade de pacotes 102
visibilidade particular
em C++ 101
- em Smalltalk 101
visibilidade protegida
em C++ 101
em Java 102
visibilidade pública 45
em C++ 101
em lava 102
em Smalltalk 101

ÍNDICE
J 33,

T
tem pia te
Veja classe parametrizada
teste 41, 111
Thread condicional 125
três amigos 20, 21, 26, 29, 121, 159, 160, 161
U
união
definição 123
exemplos 122, 125
URLs 37, 48, 69, 79, 154, 151
v
velocidade do projeto 39

w
Walden, Kim 69, 161
Warmer los 67, 161
Wirfs-Brock, Rebecca 20, 79, 111, 154
zvorkflow 26, 121, 123, 129
Y
Yourdon, Ed 20, 159

J’

Diagrama de Pacote

dependência —

Diagrama de Seqüência

eto

Diagrama de Utilização

Diagrama de Colaboração

1.1*: mensagem de iteração O


1.2: [condição] mensagem o

mensagem assíncrona

Вам также может понравиться