Você está na página 1de 56

Anlise e Projeto de Sistemas de

Informao Orientados a Objetos


Segunda Edio
(Partes selecionadas para Estudo do Tema: Especificao Formal)
(Uso exclusivo dos alunos da disicplina INE5419 2010.2)

No redistribuir!
Raul Sidnei Wazlawick
http://www.inf.ufsc.br/~raul

Prefcio
Este livro apresenta, de maneira didtica e aprofundada, elementos de anlise e projeto de
sistemas de informao orientados a objetos.
A rea de desenvolvimento de software tem se organizado nos ltimos anos em torno da
linguagem de modelagem UML (Unified Modeling Language) e do processo UP (Unified
Process), transformados em padro internacional pela OMG (Object Management
Group).
No se procura aqui realizar um trabalho enciclopdico sobre UP ou UML, mas uma
apresentao de cunho estritamente prtico, baseada em mais de vinte anos de
experincia no ensino, prtica e consultoria em anlise, projeto e programao orientada a
objetos.
Este livro diferencia-se da maioria de outros livros da rea por apresentar em detalhes as
tcnicas de construo de contratos de operao e consulta de sistema de forma que esses
contratos possam ser usados para efetiva gerao de cdigo.
Novos padres e tcnicas de modelagem conceitual so detalhadamente apresentados,
tcnicas estas tambm adequadas para uso com contratos e diagramas de comunicao,
de forma a garantir gerao automtica de cdigo; no apenas de esqueletos, mas de
cdigo final executvel.
Em relao aos casos de uso de anlise, o livro apresenta, em detalhes, tcnicas para
ajudar a decidir o que considerar efetivamente como caso de uso. Essa dificuldade tem

sido sistematicamente relatada por analistas de vrias partes do Brasil, a partir do contato
obtido em cursos ministrados pelo autor.
Ao contrrio de outros livros da rea, que se organizam em torno da apresentao dos
diagramas UML e procuram explicar todos os seus possveis usos, este livro se concentra
nas atividades com as quais o analisa e o projetista de software possivelmente vo se
deparar e sugere quais diagramas poderiam ajud-los e de que forma.
Algumas empresas brasileiras ainda tm dificuldade em conseguir exportar software
devido falta de flexibilidade e manutenibilidade dos sistemas gerados. Este livro
apresenta um conjunto de informaes e tcnicas que pode suprir essa carncia. As
tcnicas em questo foram implementadas com xito pelo autor na empresa TEClgica
Ltda., em Blumenau, no desenvolvimento de um projeto de grande porte em 2004.
Posteriormente, as tcnicas foram aplicadas e aperfeioadas nos departamentos de
tecnologia de informao do Ministrio Pblico de Santa Catarina, Tribunal Regional do
Trabalho do Mato Grosso e Justia Federal de Santa Catarina, contendo agora ainda mais
orientaes e detalhes do que na primeira edio deste livro.
O livro direcionado a profissionais de computao (analistas, projetistas e
programadores), estudantes de graduao e ps-graduao das disciplinas de Anlise e
Projeto de Sistemas e Engenharia de Software. Como conhecimentos prvios so
recomendados rudimentos sobre orientao a objetos, notao UML e fundamentos de
banco de dados.
Para que o livro pudesse aprofundar ainda mais as informaes sobre anlise e projeto
orientados a objetos sem se tornar demasiadamente longo, foram suprimidas nesta
segunda edio algumas informaes referentes ao processo de engenharia de software
que estavam presentes na primeira edio. Esses processos sero descritos de forma
detalhada pelo autor em um novo livro sobre engenharia de software a ser lanado
brevemente. Alm disso, para ganhar espao e dinamismo, os exerccios, anteriormente
includos no livro, passam a estar disponveis apenas na Internet (www.campus.com.br
ou www.inf.ufsc.br/~raul/).
Raul Sidnei Wazlawick
Florianpolis, 19 de fevereiro de 2010.

1 Introduo
2 Viso Geral do Sistema
3 Requisitos
4 Casos de Uso de Alto Nvel
5 Casos de Uso Expandidos
6 Diagramas de Sequncia de Sistema
7 Modelagem Conceitual
7.1 Atributos
7.1.1 Tipagem
7.1.2 Valores Iniciais
Um atributo pode ser declarado com um valor inicial, ou seja, sempre que uma instncia
do conceito (classe) for criada, aquele atributo receber o valor inicial definido, que
posteriormente poder ser mudado, se for o caso.
Uma venda, por exemplo, pode ser criada com um valor total que inicialmente (antes que
haja algum livro na venda) ser zero. Isso pode ser definido no prprio diagrama de
classes do modelo conceitual, como mostrado na Figura 7.4.

Figura 7.4: Um atributo com valor inicial.


Pode-se usar a linguagem OCL tambm para definir o valor inicial de um atributo de
forma textual. Para isso, necessrio primeiro declarar o contexto da expresso (no caso,
o atributo valorTotal, na classe Venda, representado por Venda::valorTotal) e usando a
expresso init para indicar que se trata de um valor inicial de atributo. A expresso OCL
seria escrita assim:
Context Venda::valorTotal:Moeda init: 0,00

Pode-se omitir o tipo Moeda, pois a OCL no obriga a declarao de tipos nas suas
expresses:
Context Venda::valorTotal init: 0,00
possvel tambm que um atributo tenha um valor inicial calculado de forma mais
complexa. Mais adiante sero apresentados exemplos de expresses complexas com OCL
que podem ser usadas para inicializar atributos com valores como somatrios, quantidade
de elementos associados, maior elemento associado etc.

7.1.3 Atributos Derivados


Atributos derivados so valores alfanumricos (novamente no se admitem objetos nem
estruturas de dados como conjuntos e listas) que no so definidos seno atravs de um
clculo. Ao contrrio dos valores iniciais, que so atribudos na criao do objeto e
depois podem ser mudados vontade, os atributos derivados no admitem qualquer
mudana diretamente neles. Em outras palavras, so atributos read-only.
Um atributo derivado deve ser definido por uma expresso. No diagrama, representa-se o
atributo derivado com uma barra (/) antes do nome do atributo seguida da expresso que
o define. Na Figura 7.5 define-se que o lucro bruto de um produto a diferena entre seu
preo de venda e seu preo de compra.

Figura 7.5: Um atributo derivado.


Em OCL, o mesmo atributo derivado poderia ser definido usando a expresso derive:
Context Produto::lucroBruto:Moeda
derive:
precoVenda precoCompra

Nessa classe, apenas os atributos precoCompra e precoVenda podem ser diretamente


alterados por um setter. O atributo lucroBruto pode apenas ser consultado. Ele o
resultado do clculo conforme definido.
Mecanismos de otimizao de fase de implementao podem definir se atributos
derivados como lucroBruto sero recalculados a cada vez que forem acessados ou se
sero mantidos em algum armazenamento oculto e recalculados apenas quando um de
seus componentes for mudado. Por exemplo, o lucroBruto poderia ser recalculado
sempre que precoCompra ou precoVenda executarem a operao set que altera seus
valores.

7.1.4 Enumeraes
7.1.5 Tipos Primitivos

7.2 Conceitos
7.3 Como Encontrar Conceitos e Atributos
7.4 Associaes
7.4.1 Como Encontrar Associaes
7.4.2 Multiplicidade de Papis
7.4.3 Direo das Associaes
7.4.4 Associao Derivada
Assim como algumas vezes pode ser interessante definir atributos derivados, que so
calculados a partir de outros valores, pode ser tambm interessante ter associaes
derivadas, ou seja, associaes que, em vez de serem representadas fisicamente, so
calculadas a partir de outras informaes que se tenha. Por exemplo, suponha que uma
venda, em vez de se associar diretamente aos livros, se associe a um conjunto de itens, e
estes, por sua vez, representam uma quantidade e um ttulo de livro especfico (Figura
7.18).

Figura 7.18: Uma venda e seus itens.


Esse tipo de modelagem necessrio quando os itens de venda no so representados
individualmente, mas como quantidades de algum produto. Alm disso, o livro enquanto
produto pode ter seu preo atualizado, mas o item que foi vendido ter sempre o mesmo
preo. Da a necessidade de representar tambm o preo do item como um atributo com
valor inicial igual ao preo do livro.
Porm, a partir da venda, no mais possvel acessar diretamente o conjunto de livros.
Seria necessrio tomar o conjunto de itens e, para cada item, verificar qual o livro
associado. Criar uma nova associao entre Venda e Livro no seria correto porque
estaria representando informao que j existe no modelo (mesmo que de forma indireta).
Alm disso, uma nova associao entre Venda e Livro poderia associar qualquer venda
com qualquer livro, no apenas aqueles que j esto presentes nos itens da venda, o que
permitiria a representao de informaes inconsistentes.

A soluo de modelagem, nesse caso, quando for relevante ter acesso a uma associao
que pode ser derivada de informaes que j existem, o uso de uma associao
derivada, como representado na Figura 7.19.

Figura 7.19: Uma associao derivada.


Uma associao derivada s tem papel e multiplicidade em uma direo (no caso, de
Venda para Livro). Na outra direo ela indefinida. Ao contrrio de associaes
comuns que podem ser criadas e destrudas, as derivadas s podem ser consultadas (assim
como os atributos derivados, elas so read-only). A forma de implementar uma
associao derivada varia, e otimizaes podem ser feitas para que ela no precise ser
recalculada a cada vez que for acessada.
Uma associao derivada pode ser definida em OCL. O exemplo da Figura 7.19 poderia
ser escrito assim:
Context Venda::livros derive: self.itens.livro
Em relao a essa expresso OCL pode observar que:
a) o contexto a prpria associao derivada a partir da classe Venda conforme
definido no diagrama;
b) usa-se derive como no caso de atributos derivados. O que define se um
atributo ou associao derivada o contexto e o tipo de informao, j que
atributos so alfanumricos e associaes definem conjuntos de objetos;
c) self denota uma instncia do contexto da expresso OCL. No caso, qualquer
instncia de Venda;
d) . uma notao que permite referenciar uma propriedade de um objeto.
Propriedades que podem ser referenciadas pela notao . so:
a) atributos;
b) associaes;
c) mtodos.
Na modelagem conceitual usualmente faz-se referncia apenas a atributos e associaes.
Assim, se o contexto Venda, ento self.total representa o atributo total de uma

instncia de Venda, e self.itens representa um conjunto de instncias de Item


associadas venda pelo papel itens.
Quando a notao . usada sobre uma coleo, ela denota a coleo das propriedades
de todos os elementos da coleo original. Assim, no contexto de Venda, a expresso
self.itens.titulo referencia o conjunto de ttulos (strings) dos itens de uma venda. J a
expresso self.itens.livro, que aparece na definio da associao derivada da Figura
7.19, representa o conjunto das instncias de Livro associados s instncias de Item
associados a uma instncia de Venda.

7.4.5 Colees
7.4.6 Agregao e Composio
7.4.7 Associaes n-rias

7.5 Organizao do Modelo Conceitual


7.6 Padres de Anlise
7.6.1 Coeso Alta
7.6.2 Classes de Especificao
7.6.3 Quantidade
7.6.4 Medida
7.6.5 Estratgia
7.6.6 Hierarquia Organizacional
7.6.7 Juno de Objetos
7.6.8 Conta/Transao
Um padro de cunho eminentemente comercial, mas de grande aplicabilidade o padro
Conta/Transao. Foi mencionado anteriormente que livros podem ser encomendados,
recebidos, estocados, vendidos, entregues, devolvidos, reenviados e descartados. Tais
movimentaes, bem como as transaes financeiras envolvidas, poderiam dar origem a
uma srie de conceitos como Pedido, Compra, Chegada, Estoque, Venda,

Remessa, Devoluo, ContasAReceber, ContasAPagar etc., cada um com seus


atributos e associaes.

Porm, possvel modelar todos esses conceitos com apenas trs classes simples e
poderosas.
Uma conta um local onde so guardadas quantidades de alguma coisa (itens de estoque
ou dinheiro, por exemplo). Uma conta tem um saldo que usualmente consiste no
somatrio de todas as retiradas e depsitos.
Por outro lado, retiradas e depsitos usualmente so apenas movimentaes de bens ou
dinheiro de uma conta para outra. Assim, uma transao consiste em duas
movimentaes, uma retirada de uma conta e um depsito de igual valor em outra. A
Figura 7.58 ilustra essas classes.

Figura 7.58: Classes do padro Conta/Transao.


Para a classe Transacao ser consistente necessrio que ela tenha exatamente dois
movimentos de mesmo valor absoluto mas sinais opostos. Ou seja, se a transao tira
cinco reais de uma conta, ela coloca cinco reais em outra conta. Ento, a classe

Transacao necessitaria de uma invariante (assunto da Seo 7.7) como a seguinte:


Context Transacao
inv:
self.movimentos.valorsum() = 0

Ou seja, para quaisquer instncias de Transacao, a soma dos dois movimentos


associados a ela tem de ser zero.
Por outro lado, o atributo derivado /saldo da classe Conta definido como o somatrio
de todos os movimentos daquela conta.
Ento, as vrias situaes relacionadas a pedidos de livros podem ser modeladas a partir
de um conjunto de instncias da classe Conta. Por exemplo:
a) para cada fornecedor (editora) corresponde uma instncia de Conta da qual
somente so retirados livros, ou seja, essa uma conta de entrada e seu saldo vai
ficando cada vez mais negativo medida que mais e mais livros so
encomendados;
b) h uma conta para saldo de pedidos, que contm os livros pedidos mas ainda no
entregues;

c) h uma conta para estoque contendo os pedidos entregues e ainda no vendidos;


d) h uma conta de remessa contendo os livros vendidos mas ainda no enviados;
e) h uma conta de envio, contendo livros enviados mas cuja entrega ainda no foi
confirmada;
f) h uma conta de venda confirmada contendo os livros vendidos e cuja entrega foi
confirmada pelo correio (possivelmente uma para cada comprador). Essa uma
conta de sada, cujo saldo vai ficando cada vez mais positivo medida que
transaes so feitas. Seu saldo representa a totalidade de livros j vendidos.
Paralelamente h contas para as transaes em dinheiro feitas concomitantemente.
Haver contas a receber, contas a pagar, contas recebidas e pagas, investimentos, dvidas,
valores separados para pagamento de impostos etc.
Assim, cada uma das possveis transaes de pedido, compra, venda, devoluo e quebra
de estoque pode ser modelada como instncias de Transacao. Por exemplo:
a) um pedido uma transao que tira de uma conta de fornecedor e repassa conta
de saldo de pedidos;
b) a chegada da mercadoria uma transao que tira da conta de saldo de pedidos e
coloca na conta de estoque;
c) uma venda uma transao que retira da conta de estoque e coloca na conta de
remessa;
d) um registro de envio uma transao que retira da conta de remessa e coloca na
conta de itens enviados;
e) uma devoluo uma transao que retira da conta de itens enviados e coloca
novamente na conta de estoque;
f) uma confirmao de entrega uma transao que retira da conta de itens enviados
e coloca em uma conta de entrega definitiva.
Esse padro comporta inmeras variaes e sofisticaes, mas muito interessante ver
como uma simples ideia poderosa pode dar conta de tantas situaes cuja modelagem
ingnua poderia ser bastante complicada.

7.6.9 Associao Histrica


7.6.10 Intervalo

7.7 Invariantes
Existem situaes em que a expressividade grfica do diagrama de classes insuficiente
para representar determinadas regras do modelo conceitual. Nesses casos necessita-se
fazer uso de invariantes.
Invariantes so restries sobre as instncias e classes do modelo. Certas restries
podem ser representadas no diagrama: por exemplo, a restrio de que uma venda no
pode ter mais do que cinco livros poderia ser representada como na Figura 7.64.

Figura 7.64: Uma restrio que pode ser representada no diagrama.


Mas nem todas as restries podem ser representadas to facilmente. Se houvesse uma
restrio que estabelecesse que nenhuma venda pode ter valor superior a mil reais, isso
no seria passvel de representao nas associaes nem nos atributos do diagrama da
Figura 7.64. Mas seria possvel estabelecer tal restrio usando invariantes de classe
como a seguir:
Context Venda
inv:
self.total <= 1000,00

Talvez a maioria dos desenvolvedores de software, quando se depara com regras desse
tipo acaba incorporando-as nos mtodos que fazem algum tipo de atualizao nas
instncias da classe. Por exemplo, no caso anterior, poderia ser colocado um teste no
mtodo que faz a adio de um novo item em uma venda para verificar se o valor total
passaria de 1.000 e, se for o caso, impedir a adio.
O problema com essa abordagem que apenas naquele mtodo seria feita a verificao,
mas no fica uma regra geral para ser observada em outros mtodos. At possvel que o
analista hoje saiba que a regra deve ser seguida, mas, e se outro analista fizer a
manuteno do sistema dentro de cinco ou 10 anos? Ele no saber necessariamente que
essa regra existe, provavelmente no vai consultar o documento de requisitos, j
desatualizado, e poder introduzir erro no sistema se permitir a implementao de
mtodos que no obedeam regra.
Ento, todas as regras gerais para o modelo conceitual devem ser explicitadas no modelo
para que instncias inconsistentes no sejam permitidas. Se for possvel, as restries
devem ser explicitadas graficamente; caso contrrio, atravs de invariantes.
Outro exemplo, que ocorre com certa frequncia a necessidade de restringir duas
associaes que a princpio so independentes. Na Figura 7.65 considera-se que cursos
tm alunos, cursos so formados por disciplinas, e alunos matriculam-se em disciplinas,
mas o modelo mostrado na figura no estabelece que alunos s podem se matricular nas
disciplinas de seu prprio curso.

Figura 7.65: Uma situao que necessita de uma invariante para que a
consistncia entre associaes se mantenha.
Para que um aluno s possa se matricular em disciplinas que pertencem ao curso ao qual
est associado necessrio estabelecer uma invariante como:
Context Aluno
inv:
self.disciplinasforAll(d|d.cursosincludes(self.curso))

A invariante diz que, para todas as disciplinas (d) cursadas por um aluno (self), o
conjunto de cursos nos quais a disciplina oferecida contm o curso no qual o aluno est
matriculado.
A mensagem forAll afirma que uma expresso lgica verdadeira para todos os
elementos de um conjunto; no caso, o conjunto dado por self.disciplina.
A varivel d entre parnteses equivale a um iterador, ou seja, d substitui na
expresso lgica cada um dos elementos do conjunto. A mensagem includes
corresponde ao smbolo matemtico de pertena invertida (), ou seja, afirma que um
determinado conjunto contm um determinado elemento.
possvel, ainda, simplificar a expresso eliminando a varivel self e o iterador d, visto
que podem ser inferidos pelo contexto em que se encontram. A expresso anterior
poderia ento ser escrita assim:
Context Aluno
inv:
disciplinasforAll(cursosincludes(curso))

7.8 Discusso
Um bom modelo conceitual produz um banco de dados organizado e normalizado. Um
bom modelo conceitual incorpora regras estruturais que impedem que a informao seja
representada de forma inconsistente. Um bom modelo conceitual vai simplificar o cdigo

gerado porque no ser necessrio fazer vrias verificaes de consistncia que a prpria
estrutura do modelo j garante.
O uso de padres corretos nos casos necessrios simplifica o modelo conceitual e torna o
sistema mais flexvel e, portanto, lhe d maior qualidade. , portanto, uma ferramenta
poderosa. Muitos outros padres existem, e os analistas podem descobrir e criar seus
prprios padres. Apenas necessrio sempre ter em mente que s vale a pena criar um
padro quando os seus benefcios compensam o esforo de registrar sua existncia.

8 Contratos
At o incio da modelagem funcional, o processo de anlise deve ter produzido dois
artefatos importantes:
a) o modelo conceitual, que representa estaticamente a informao a ser gerenciada
pelo sistema;
b) os diagramas de sequncia de sistema, que mostram como possveis usurios
trocam informaes com o sistema, sem mostrar, porm, como a informao
processada internamente.
Na fase de construo dos diagramas de sequncia de sistema foram identificadas as
operaes e consultas de sistema. Cada operao ou consulta desse tipo implica a
existncia de uma inteno por parte do usurio. Essa inteno capturada pelos
contratos de operaes de sistema e pelos contratos de consulta de sistema, que
correspondem modelagem funcional do sistema.
Um contrato de operao de sistema pode ter trs sees:
a) precondies (opcional);
b) ps-condies (obrigatria);
c) excees (opcional).
J um contrato para uma consulta de sistema pode ter duas sees:
a) precondies (opcional);
b) resultados (obrigatria).
As precondies existem nos dois tipos de contratos e devem ser cuidadosamente
estabelecidas. Elas complementam o modelo conceitual no sentido de definir o que ser
verdadeiro na estrutura da informao do sistema quando a operao ou consulta for
executada. Isso significa que elas no sero testadas durante a execuo, mas algum
mecanismo externo dever garantir sua validade antes de habilitar a execuo da
operao ou consulta de sistema correspondente.
As ps-condies tambm devem ser muito precisas. Elas estabelecem o que uma
operao de sistema muda na informao.
Deve-se tomar cuidado para no confundir as ps-condies com os resultados das
consultas. As ps-condies s existem nas operaes de sistema porque elas especificam
alguma alterao nos dados armazenados. Assim, pelo princpio de separao entre
operao e consulta, no apropriado que uma operao de sistema retorne algum
resultado (exceto no caso mencionado na Seo 8.8.1). J as consultas, por definio,
devem retornar algum resultado, mas no podem alterar os dados armazenados. Da os
contratos das consultas de sistema terem resultados mas no ps-condies.
Ao contrrio das precondies, que devem ser garantidamente verdadeiras durante a
execuo de uma operao, as excees so situaes que usualmente no podem ser
garantidas a priori, mas sero testadas durante a execuo da operao. Excees so
eventos que, se ocorrerem, impedem o prosseguimento correto da operao.

Esse tipo de exceo ocorre apenas nas operaes de sistema quando se tenta alterar
alguma informao com dados que no satisfazem alguma regra de negcio (por
exemplo, tentar cadastrar um comprador que j tem cadastro).
Apenas elementos conceituais (conceitos, atributos e associaes) podem constar nos
contratos de anlise. Esses elementos tero necessariamente relao com as regras de
negcio do sistema sendo analisado. As excees aqui referenciadas, portanto, so
excees referentes s regras de negcio e no excees referentes a problemas de
hardware ou de comunicao. As excees que podem ocorrer nos nveis de
armazenamento, comunicao ou acesso a dispositivos externos so tratadas por
mecanismos especficos nas camadas arquitetnicas correspondentes na atividade de
projeto, e o usurio normalmente nem toma conhecimento delas.
Como as consultas no alteram a informao armazenada, elas no geram esse tipo de
excees.

8.1 Precondies
As precondies estabelecem o que verdadeiro quando uma operao ou consulta de
sistema for executada. Por exemplo, considerando o modelo conceitual de referncia da
Figura 8.1, se um usurio estiver comprando um livro, poder ser assumido como
precondio que o seu CPF, passado como parmetro para a operao, corresponde a um
comprador vlido, ou seja, existe uma instncia de Pessoa no papel de comprador cujo
atributo cpf igual ao CPF passado como parmetro. Essa expresso pode ser assim
representada em OCL:
Context Livir::identificaComprador(umCpf)
pre:
compradoresselect(cpf=umCpf)notEmpty()

Figura 8.1: Modelo conceitual de referncia.


A expresso ento afirma que, no contexto do mtodo identificaComprador, que uma
operao de sistema implementada na controladora Livir, h uma precondio que
estabelece que o conjunto de compradores filtrado (select) pela condio de que o
atributo cpf do comprador seja igual ao parmetro umCpf no vazio, ou seja, h pelo
menos um comprador cujo CPF igual ao parmetro passado.

Se a associao compradores da Figura 8.1 for qualificada como na Figura 8.2, a


precondio de garantia de parmetro mencionada anteriormente poder ser escrita de
forma mais direta:
Context Livir::identificaComprador(umCpf)
pre:
compradores[umCpf]notEmpty()

Figura 8.2: Modelo conceitual de referncia com associao qualificada.


Quando a associao qualificada, como na Figura 8.2, pode-se usar um valor para
indexar diretamente o mapeamento representado pela associao. Assim, como a
operao

identificaComprador

compradores[umCpf]

tem

produz

um
mesmo

parmetro
resultado

umCpf,
que

expresso

expresso

compradoresselect(cpf=umCpf).
Para serem teis ao processo de desenvolvimento de software, as precondies no
podem ser expressas de maneira descuidada. Elas devem refletir fatos que possam ser
identificados diretamente no modelo conceitual j desenvolvido para o sistema. Isso
justifica a utilizao de linguagens formais como OCL (Warmer & Kleppe, 1998) para
escrever contratos.
Pode-se identificar duas grandes famlias de precondies:
a) garantia de parmetros: precondies que garantem que os parmetros da
operao ou consulta correspondem a elementos vlidos do sistema de
informao, como, por exemplo, que existe cadastro para o comprador cujo CPF
corresponde ao parmetro da operao ou consulta;
b) restrio complementar: precondies que restringem ainda mais o modelo
conceitual para a execuo da operao ou consulta, de forma a garantir que a
informao se encontra em uma determinada situao desejada, por exemplo, que
o endereo para entrega informado pelo comprador no esteja no estado invlido.
Sobre o segundo tipo de precondio, pode-se entender que ela pode estabelecer
restries mais fortes sobre o modelo conceitual. Assim, se o modelo conceitual
especifica que uma associao tem multiplicidade de papel 0..1, uma precondio
complementar poder especificar que durante a execuo de determinada operao de

sistema esse papel est preenchido (1) ou no (0). Por exemplo, uma Venda pode ter ou
no um Pagamento (0..1), mas a operao de efetuar o pagamento de uma venda exige
uma venda que no esteja paga ainda (0).
necessrio lembrar que uma precondio nunca poder contradizer as especificaes
do modelo conceitual, mas apenas restringi-las ainda mais. Se o modelo conceitual exige
0 ou 1, nenhuma precondio poder garantir 2.

8.1.1 Garantia de Parmetros


Em relao s precondies de garantia de parmetros, deve-se tomar cuidado para no
confundir as precondies que testam os parmetros semanticamente com as simples
verificaes sintticas. Para garantir que um parmetro seja, por exemplo, um nmero
maior do que zero, basta usar tipagem (por exemplo, x:InteiroPositivo), no sendo
necessrio escrever isso como precondio.
A tipagem deve ser definida na assinatura da operao. Por exemplo, a tipagem que vai
definir que um determinado parmetro deve ser um nmero inteiro ou um nmero maior
do que 100, ou mesmo um nmero primo. Se o tipo no existir, deve-se definir uma
classe com o esteretipo <<primitive>> para o novo tipo.
Ser considerada precondio semntica apenas uma assero para a qual a determinao
do valor verdade implica verificar os dados gerenciados pelo sistema. Assim, determinar
se um nmero de CPF est bem formado pode ser feito sintaticamente (aplicando-se uma
frmula para calcular os dgitos verificadores), mas verificar se existe um comprador
cadastrado com um dado nmero de CPF uma verificao semntica, pois exige a
consulta aos dados de compradores. Assim, a primeira verificao deve ser feita por
tipagem, e a segunda por precondio.

8.1.2 Restrio Complementar


Uma restrio complementar consiste na garantia de que certas restries mais fortes do
que aquelas estabelecidas pelo modelo conceitual so obtidas. possvel identificar
vrios tipos de restries, como por exemplo:
a) fazer uma afirmao especfica sobre uma instncia ou um conjunto de instncias;
b) fazer uma afirmao existencial sobre um conjunto de instncias;
c) fazer uma afirmao universal sobre um conjunto de instncias.
Um exemplo de afirmao especfica sobre uma instncia, considerando o modelo da
Figura 8.2 poderia ser afirmar que o comprador com o CPF 12345678910 tem saldo igual
a zero:
Context Livir::operacaoQualquer()
pre:
compradores[12345678910].saldo = 0

Um exemplo de afirmao existencial seria dizer que existe pelo menos um comprador
com saldo igual a zero (embora no se saiba necessariamente qual):
Context Livir::operacaoQualquer()
pre:
compradoresexists(c|c.saldo = 0)

Um exemplo de afirmao universal seria dizer que todos os compradores tm saldo


igual a zero.
Context Livir::operacaoQualquer()
pre:
compradoresforAll(c|c.saldo = 0)

Tanto a expresso exists quanto forAll usadas poderiam ser simplificadas para

exists(saldo=0) ou forAll(saldo=0), mantendo o mesmo significado.

8.1.3 Garantia das Precondies


Como as precondies no so testadas pela operao admite-se que algum mecanismo
externo as garanta. Pode-se, por exemplo, antes de chamar a operao, executar uma
consulta que testa a precondio e s chama a operao se o resultado for positivo. Podese, ainda, criar mecanismos restritivos de interface que garantam que a operao s
executada se a precondio for observada.
Por exemplo, em vez de digitar um CPF qualquer, o usurio ter de selecion-lo de uma
lista de CPFs vlidos. Dessa forma, o parmetro j estar garantidamente validado antes
de executar a operao.

8.1.4 Precondio Invariante


Usam-se invariantes no modelo conceitual para regras que valem sempre,
independentemente de qualquer operao. Usam-se precondies para regras que valem
apenas quando determinada operao ou consulta est sendo executada.
Quando j existir uma invariante para determinada situao no necessrio escrever
precondies para a mesma situao. Por exemplo, se j existir uma invariante na classe

Aluno afirmando que ele s pode se matricular em disciplinas do seu curso, no


necessrio escrever precondies nas operaes de matrcula para verificar isso. Assumese que o projeto deva ser efetuado de forma que tanto a invariante quanto as eventuais
precondies nunca sejam desrespeitadas.
Mecanismos de teste de projeto podero verificar as invariantes e precondies durante a
fase de teste do sistema. Caso, em algum momento, as condies sejam falsas, devem ser
sinalizadas excees. Porm, nesses casos, o projetista deve imediatamente corrigir o
sistema para que tais excees no venham mais a acontecer. Quando o sistema for
entregue ao usurio final deve-se ter garantias de que as precondies e invariantes nunca
sejam falsas.

8.2 Associaes Temporrias


Quando se utiliza a estratgia statefull, mencionada no Captulo 6, necessrio que a
controladora guarde em memria certas informaes que no so persistentes, mas que
devem ser mantidas durante a execuo de um conjunto de operaes.
Pode-se, ento, definir certas associaes ou atributos temporrios (ambos estereotipados
com <<temp>>) para indicar informaes que s so mantidas durante a execuo de um
determinado caso de uso e descartadas depois.
Por exemplo, para que a controladora guarde a informao sobre quem o comprador
correntemente sendo atendido, pode-se utilizar uma associao temporria para indicar
isso no modelo conceitual refinado, como na Figura 8.3.

Figura 8.3: Uma associao temporria.


Assim, uma precondio de uma operao, por exemplo, poderia afirmar que j existe um
comprador corrente identificado da seguinte forma:
Context Livir::operacaoQualquer()
pre:
compradorCorrentenotEmpty()

8.3 Retorno de Consulta


Conforme mencionado, operaes de sistema provocam alteraes nos dados, enquanto
consultas apenas retornam dados. Os contratos de consultas devem ter obrigatoriamente
uma clusula de retorno, representada em OCL pela expresso body.
As expresses que representam precondies vistas at aqui so todas booleanas, mas
expresses utilizadas na clusula body podem ser de qualquer tipo. Podem retornar
strings, nmeros, listas, tuplas etc. Os exemplos seguintes so baseados no modelo
conceitual da Figura 8.3.
Inicialmente define-se uma consulta de sistema que retorna o saldo do comprador
corrente:
Context Livir::saldoCompradorCorrente():Moeda

body:
compradorCorrente.saldo

As consultas de sistema sempre tm por contexto a controladora. Portanto, nessa


expresso, compradorCorrente uma propriedade da controladora; no caso, um papel
de associao.
A consulta a seguir retorna nome e telefone do comprador cujo CPF dado:
Context Livir::nomeTelefoneComprador(umCpf):Tuple
body:
Tuple{
nome = compradores[umCpf].nome,
telefone = compradores[umCpf].telefone
}

O construtor Tuple uma das formas de representar DTOs em OCL; a tupla funciona
como um registro, no caso com dois campos: nome e telefone. Os valores dos campos
so dados pelas expresses aps o sinal =.
Para no ter de repetir a expresso compradores[umCpf] ou possivelmente expresses
at mais complexas do que essa em contratos OCL, pode-se usar a clusula def para
definir um identificador para a expresso que pode ser reutilizado. Usando a clusula def,
o contrato ficaria assim:
Context Livir::nomeTelefoneComprador(cpfComprador):Tuple
def:
comprador = compradores[cpfComprador]
body:
Tuple{
nome = comprador.nome,
telefone = comprador.telefone
}

A expresso a seguir faz uma projeo, retornando um conjunto com todos os nomes de
compradores:
Context Livir::listaNomeCompradores():Set
body:
compradores.nome

A prxima expresso aplica um filtro e uma projeo, retornando os nomes de todos os


compradores que tm saldo igual a zero:
Context Livir::listaNomeCompradoresSaldoZero():Set

body:
compradoresselect(saldo=0).nome

Como ltimo exemplo, a expresso a seguir retorna CPF, nome e telefone de todos os
compradores que tm saldo igual a zero:
Context Livir::listaCpfNomeTelefoneCompradoresSaldoZero():Set
body:
compradoresselect(saldo=0)collect(c|
Tuple {
cpf = c.cpf,
nome = c.nome,
telefone = c.telefone
}
)

A expresso collect uma forma de obter um conjunto cujos elementos so propriedades


ou transformaes de outro conjunto. A prpria notao . aplicada sobre conjuntos
uma forma abreviada de collect. Por exemplo, compradores.nome equivalente a

compradorescollect(nome).
Quando for possvel, usa-se a notao ., por ser mais simples. Mas, no exemplo
anterior, a necessidade de criar uma tupla em vez de acessar uma propriedade dos
elementos do conjunto impede o uso da notao .. Assim, a expresso collect tem de
ser explicitamente usada nesse caso. Novamente, pode-se omitir o indexador, e a
expresso poder ainda ser simplificada para:
Context Livir::listaCpfNomeTelefoneCompradoresSaldoZero():Set
body:
compradoresselect(saldo=0)collect(
Tuple {
cpf = cpf,
nome = nome,
telephone = telefone
}

Nesse caso, as coincidncias de nomes de identificadores de campo e atributos podem


deixar a expresso estranha, mas os significados desses identificadores no ambguo
pelo contexto.

8.4 Ps-condies
As ps-condies estabelecem o que muda nas informaes armazenadas no sistema aps
a execuo de uma operao de sistema. As ps-condies tambm devem ser claramente
especificadas em termos que possam ter correspondncia nas definies do modelo
conceitual. Assim, uma equivalncia com as expresses usadas como ps-condio e
expresses passveis de escrita em OCL altamente desejvel para evitar que os
contratos sejam ambguos ou incompreensveis.
Uma ps-condio em OCL escrita no contexto de uma operao (de sistema) com o
uso da clusula post, conforme exemplo a seguir:
Context Livir::operacaoX()
post:
<expresso OCL>

Havendo mais de uma ps-condio que deve ser verdadeira aps a execuo da
operao de sistema, faz-se a combinao das expresses com o operador AND:
Context Livir::operacaoX()
post:
<expresso 1> AND
<expresso 2> AND
...
<expresso n>

Para se proceder a uma classificao dos tipos de ps-condies possveis e teis em


contratos de operao de sistema deve-se considerar que o modelo conceitual possui
apenas trs elementos bsicos, que so os conceitos (representados pelas classes), as
associaes e os atributos. Assim, considerando que instncias de classes e associaes
podem ser criadas ou destrudas, e que atributos apenas podem ter seus valores alterados,
chega-se a uma classificao com cinco tipos de ps-condies:
a) modificao de valor de atributo;
b) criao de instncia;
c) criao de associao;
d) destruio de instncia;
e) destruio de associao.
Para que essas ps-condies possam ser definidas de forma no ambgua necessrio
que inicialmente se proceda a uma definio de certas operaes bsicas sobre essas
estruturas conceituais e seu comportamento esperado.
As operaes consideradas bsicas so aquelas que em orientao a objetos operam
diretamente sobre os elementos bsicos do modelo conceitual. Seu significado e
comportamento so definidos por padro.

Infelizmente, as linguagens de programao no oferecem ainda um tratamento


padronizado para as operaes bsicas. Sua programao muitas vezes fonte de trabalho
braal para programadores.
As operaes conforme definidas nas subsees seguintes so efetivamente bsicas, no
sentido de que no fazem certas verificaes de consistncia. Por exemplo, uma operao
que cria uma associao no vai verificar se o limite mximo de associaes possveis j
foi atingido. Essas verificaes de consistncia devem ser feitas em relao ao conjunto
das ps-condies, ou seja, aps avaliar todas as ps-condies que se vai verificar se
os objetos ficaram ou no em um estado consistente.
Por exemplo, suponha que um objeto A tenha uma associao obrigatria com um objeto
B1, e uma operao de sistema vai trocar essa associao por outra entre A e B2.
necessrio destruir a associao original e criar uma nova. No intervalo de tempo entre
essas duas operaes, o objeto A estaria inconsistente (sem a associao obrigatria), mas
considerando o conjunto das ps-condies observa-se que o resultado final consistente,
pois uma foi destruda e outra criada em seu lugar.
A discusso sobre a manuteno de consistncia do conjunto de ps-condies de uma
operao de sistema ser feita na Seo 8.4.6.

8.4.1 Modificao de Valor de Atributo


O tipo mais simples de ps-condio aquele que indica que o valor de um atributo foi
alterado. Pode-se indicar tal condio com uma operao bsica denotada pela expresso
set seguida do nome do atributo, com o novo valor entre parnteses.
A mensagem referente a essa operao enviada a uma instncia da classe que contm o
atributo. Por exemplo, se o objeto pessoa, instncia da classe Pessoa, tem um atributo

dataNascimento e uma determinada operao de sistema vai alterar essa data de


nascimento para um valor dado por novaData, ento a ps-condio da expresso dever
conter:
pessoa^setDataNascimento(novaData)
A notao ^ usada aqui difere da notao . no seguinte aspecto: o ponto forma uma
expresso cujo valor o retorno da avaliao da expresso, ou null, se no houver
retorno; j o circunflexo apenas indica que a mensagem foi enviada ao objeto. O valor de
uma expresso com circunflexo, portanto, s pode ser booleano.
Outra coisa: a expresso s diz que a instncia de pessoa recebeu a mensagem, mas no
diz quem enviou. A deciso sobre qual objeto vai enviar a mensagem tomada na
atividade de projeto, durante a modelagem dinmica.
Quando usadas como ps-condies, tais expresses so asseres, ou seja, afirmaes.
Assim, a leitura da expresso OCL acima seria: O objeto pessoa recebeu a mensagem

setDataNascimento com o parmetro novaData.

8.4.2 Criao de Instncia


A operao de criao de instncia deve simplesmente criar uma nova instncia de uma
classe. Embora a OCL no seja uma linguagem imperativa, ela possui um construtor para
referenciar uma nova instncia de uma classe dada. Uma nova instncia de Livro,
conforme a Figura 8.4, poderia ser referenciada assim:
Livro::newInstance()

Figura 8.4: Uma classe a ser instanciada.


Assume-se que atributos com valores iniciais (clusula init) j sejam definidos
automaticamente pela operao de criao (sem necessidade de especificar novamente
ps-condies para dar valor a esses atributos). Alm disso, atributos derivados so
calculados e no podem ser modificados diretamente. Mas, o que acontece com os
demais atributos e associaes no momento da criao?
H dois padres a seguir aqui:
a) a operao bsica de criao de instncia simplesmente produz a instncia, sem
inicializar seus atributos e associaes obrigatrias. Nesse caso, a validao
feita depois e a checagem de consistncia feita no nvel da operao de sistema,
como mencionado antes, e no no nvel da operao bsica;
b) a operao bsica de criao de instncia inicializa atributos e associaes
obrigatrias de forma que a instncia no fique inconsistente em relao ao
modelo conceitual. Nesse caso, a operao bsica j produz uma instncia
consistente.
A segunda forma exigir operaes de criao mais complexas. As instncias da classe
referenciada na Figura 8.4, por exemplo, teriam de ser criadas j com todos os seus
parmetros:
Livro::newInstance(umISBN, umTitulo, umAutor)
Ento, a operao bsica no seria mais to bsica, pois seria necessrio descrever de que
forma esses parmetros so usados para inicializar os atributos da instncia. Assim, a
operao de criao de instncia teria chamadas de operaes bsicas dentro dela.
O primeiro padro mais simples: a operao bsica de criao simplesmente cria a
instncia, e outras operaes bsicas tratam da inicializao de atributos e associaes. A
consistncia dos objetos em relao ao modelo conceitual checada aps a execuo da

operao de sistema e no aps cada operao bsica (o que seria o caso, se fosse
aplicado o segundo padro). Assim, aplicando o primeiro padro, a classe da Figura 8.4
poderia ser criada e inicializada como no exemplo a seguir (onde criaLivro uma
operao de sistema):
Context Livir::criaLivro(umIsbn, umTitulo, umAutor)
def:
novoLivro = Livro::newInstance()
post:
...
novoLivro^setIsbn(umIsbn) AND
novoLivro^setTitulo(umTitulo) AND
novoLivro^setAutor(umAutor)

Uma ps-condio ficou implcita na clausula def: a criao da instncia de Livro.


Nota-se que o atributo preco, que tem valor predefinido, no precisa ser inicializado,
bem como o atributo derivado status, que calculado (por uma clausula derive na
definio da classe Livro).
H mais um porm aqui: em ps-condies de contratos de nada adianta mencionar a
criao de uma instncia se ela no for tambm imediatamente associada a alguma outra
instncia, porque a informao inacessvel em um sistema simplesmente no
informao. Ento, a criao de instncia vai ocorrer sempre em conjunto com uma
criao de associao, conforme ser visto na seo seguinte.

8.4.3 Criao de Associao


Como visto, outro tipo de operao bsica aquela que indica que uma associao foi
criada entre duas instncias. A criao de associaes pode ser limitada superiormente e
inferiormente, dependendo da multiplicidade de papel. Por exemplo, uma associao 0..5
que j tenha cinco objetos no poder aceitar um sexto objeto. Uma associao para um
no pode aceitar um segundo elemento, nem o primeiro pode ser removido. Essa
verificao, porm, conforme foi dito, ser feita para a operao de sistema como um
todo e no individualmente para cada operao bsica.
Existem vrios dialetos para nomear operaes que modificam e acessam associaes.
Aqui ser usado o prefixo add seguido do nome de papel para nomear essa operao
(outra opo seria usar set, como no caso de atributos).
Assim, considerando a associao entre as classes Automovel e Pessoa, conforme a
Figura 8.5, e considerando duas instncias, respectivamente, jipe e joao, pode-se admitir
que a associao possa ser criada do ponto de vista do automvel por:
jipe^addPassageiro(joao)

ou, do ponto de vista da pessoa, por:


joao^addAutomovel(jipe)
As duas expresses so simtricas e produzem exatamente o mesmo resultado (a criao
da associao).

Figura 8.5: Um modelo de referncia para operaes de criao de associao.


Associaes com papel obrigatrio, como na Figura 8.6, normalmente so criadas
juntamente com um dos objetos (o do lado no obrigatrio). Assim, usualmente esse tipo
de ps-condio combinada de criao de instncia e sua associao obrigatria pode ser
feita como indicado a seguir:
venda^addPagamento(Pagamento::newInstance())

Figura 8.6: Um modelo de referncia para operaes de criao de associao


com papel obrigatrio.
A situao se complica mais quando o limite inferior for maior do que 1, o que implica
que um objeto j teria de ser criado com vrios outros objetos associados. Nesse caso, o
padro utilizado neste livro, que considera a consistncia do contrato como um todo e no
de cada operao bsica, novamente mais simples: basta criar o objeto e adicionar
associaes at chegar ao limite exigido. A consistncia ser verificada ao final do
conjunto de operaes.
Complementando, ento, o exemplo da seo anterior, a expresso a seguir mostra a
criao de um novo livro e sua inicializao, inclusive com a criao de uma associao
entre a controladora e o novo livro:
Context Livir::criaLivro(umIsbn, umTitulo, umAutor)
def:
novoLivro = Livro::newInstance()
post:
self^addLivro(novoLivro) AND
novoLivro^setIsbn(umIsbn) AND
novoLivro^setTitulo(umTitulo) AND
novoLivro^setAutor(umAutor)

8.4.4 Destruio de Instncia


A destruio de objetos deve tambm ser entendida do ponto de vista declarativo da
OCL. H duas abordagens para indicar que uma instncia foi destruda:
a) explcita: declara-se que um objeto foi destrudo atravs do envio de uma
mensagem explcita de destruio;
b) implcita: removem-se todas as associaes para o objeto de forma que ele passe a
no ser mais acessvel. Em linguagens de programao possvel implementar
coletores de lixo (garbage collection) para remover da memria objetos que no
so mais acessveis.
Neste livro ser assumida a abordagem explcita, visto que ela deixa mais claro qual a
real inteno do analista. Um objeto que foi destrudo, ento, ter recebido uma
mensagem como:
objeto^destroy()
O significado dessa expresso em uma ps-condio de operao de sistema de que o
objeto referenciado foi destrudo durante a execuo da operao.
Assume-se que todas as associaes desse objeto tambm so destrudas com ele.

8.4.5 Destruio de Associao


A destruio de uma associao referenciada pela operao bsica com prefixo
remove seguida do nome de papel e tendo como parmetro o objeto a ser removido
(em alguns dialetos poderia ser unset). Por exemplo, considerando a Figura 8.5, para
remover um pagamento p1 associado venda v, pode-se escrever:
v^removePagamento(p1)
Deve-se assumir, nese caso, que, como a multiplicidade de papel de Pagamento para

Venda obrigatria (igual a 1), a remoo da associao implicar necessariamente a


destruio do pagamento ou a criao posterior de uma nova associao com outra venda.
Se a multiplicidade do papel a ser removido fosse 1 ou 0..1, seria opcional informar o
parmetro, pois haveria uma nica possvel associao a ser removida. Observando
novamente a Figura 8.5, se a remoo da associao fosse feita a partir do pagamento, a
operao poderia ser chamada sem o parmetro, pois s h uma venda possvel a ser
removida:
p1^removeVenda()
Novamente, deve-se ter em mente que a remoo dessa associao obriga criao de
uma nova associao para o pagamento p1 ou sua destruio.
Tentar remover uma associao inexistente um erro de projeto e no pode ser tentado
em ps-condies bem formadas.

8.4.6 Ps-condies bem Formadas


Considerando-se ento que as operaes bsicas que denotam as ps-condies mais
elementares no comportam checagem de consistncia nos objetos em relao ao modelo
conceitual, o conjunto de ps-condies que precisa ser verificado para se saber se ao
final da execuo das operaes os objetos esto em um estado consistente com as
definies do modelo.
Pode-se resumir assim as checagens a serem efetuadas:
a) uma instncia recm-criada deve ter ps-condies indicando que todos os seus
atributos foram inicializados, exceto: (1) atributos derivados (que so calculados),
(2) atributos com valor inicial (que j so definidos por uma clusula init no
contexto da classe e no precisam ser novamente definidos para cada operao de
sistema) e (3) atributos que possam ser nulos (nesse caso, a inicializao
opcional);
b) uma instncia recm-criada deve ter sido associada a alguma outra que, por sua
vez, possua um caminho de associaes que permita chegar controladora de
sistema. Caso contrrio, ela inacessvel, e no faz sentido criar um objeto que
no possa ser acessado por outros.
c) todas as associaes afetadas por criao ou destruio de instncia ou associao
devem estar com seus papis dentro dos limites inferior e superior;
d) todas as invariantes afetadas por alteraes em atributos, associaes ou instncias
devem continuar sendo verdadeiros.
Foge ao escopo deste livro a definio e um sistema de verificao de restries, o que
seria necessrio para implementar automaticamente a checagem de invariantes e limites
mximo e mnimo em associaes. O analista, ao preparar os contratos, deve estar ciente
de que os objetos devem ser deixados em um estado consistente aps cada operao de
sistema. Havendo a possibilidade de implementar um sistema de checagem automtica
dessas condies, seria uma grande ajuda produtividade do analista. Porm, salvo
melhor juzo, tal sistema ainda no est disponvel nas ferramentas CASE comerciais.

8.4.7 Combinaes de Ps-condies


Cada operao de sistema ter um contrato no qual as ps-condies vo estabelecer tudo
o que essa operao muda nos objetos, associaes e atributos existentes. Usualmente,
uma operao de sistema ter vrias ps-condies, que podem ser unidas por operadores
AND, como mencionado anteriormente. Mas tambm possvel usar operadores OR, que
indicam que pelo menos uma das ps-condies ocorreu, mas no necessariamente todas:
post:
<pos-condio 1> OR
<pos-condio 2>

Alm disso, possvel utilizar o operador IMPLIES, com o mesmo significado da


implicao lgica. Mas esse operador tambm pode ser substitudo pela forma if-then-

endif. Assim, a expresso:


post:
<condio> IMPLIES <pos-condio>

pode ser escrita como:


post:
if <condio> then
<pos-condio>
endIf

Muitas vezes, a condio construda com valores que os atributos tinham antes de a
operao ser executada. Esses valores anteriores devem ser anotados com a expresso

@pre. Por exemplo, uma ps-condio que estabelea que se o saldo da venda corrente
era zero ento o saldo passou a ser 1 poderia ser escrita assim:
post:
if self.vendaCorrente.saldo@pre = 0 then
self.vendaCorrente^setSaldo(1)
endIf

ou:
post:
vendaCorrente.saldo@pre = 0 IMPLIES vendaCorrente ^setSaldo(1)

8.4.8 Ps-condies sobre Colees de Objetos


possvel com uma nica expresso OCL afirmar que todo um conjunto de objetos foi
alterado. Por exemplo, para afirmar que o preo de todos os livros foi aumentado em x%,
pode-se usar a expresso forAll para indicar que todas as instncias foram alteradas:
Context Livir::reduzPrecoLivros(x)
post: self.livrosforAll(livro|
livro^setPreco(livro.preco@pre * (1-x/100))
)

8.5 Excees
As excees em contratos so estabelecidas como situaes de falha que no podem ser
evitadas ou verificadas antes de iniciar a execuo da operao propriamente dita.
J foi visto anteriormente que, muitas vezes, situaes identificadas como excees so
na verdade pr-condies sobre as quais o analista no pensou muito. Sempre que for

possvel transformar uma exceo em pr-condio conveniente faz-lo, pois


prefervel limitar a possibilidade de o usurio gerar um erro do que ficar indicando erros
em operaes que ele j tentou executar e falhou.
Nos contratos de operao de sistema basta indicar a exceo dizendo qual condio que
a gera. O tratamento da exceo ser feito necessariamente na atividade de projeto da
camada de interface do sistema. O exemplo a seguir mostra um contrato com uma
exceo indicada:
Context Livir::identificaComprador(umCpf)
def:
comprador = compradoresselect(cpf = umCpf)
post:
self^addCompradorCorrente(comprador)
exception:
compradorsize() = 0 IMPLIES self^throw(cpf invlido)

Considera-se como exceo de contrato apenas a situao que no possa ser tratada
dentro da prpria operao, exigindo possivelmente o retorno do controle da aplicao ao
usurio para tentar outras operaes.
Assume-se tambm que, quando uma exceo ocorre em uma operao de sistema, a
operao no concluda e nenhuma de suas ps-condies obtida. O sistema de
informao deve ser mantido em um estado consistente, mesmo quando ocorrer uma
exceo.
Como mencionado, algumas excees podem ser convertidas em precondies desde que
o analista vislumbre algum meio de verificar a condio antes de tentar executar a
operao. Assim, o contrato com uma exceo poderia ser transformado em:
Context Livir::identificaComprador(umCpf)
def:
comprador = compradoresselect(cpf = umCpf)
pre:
compradorsize() = 1
post:
self.addCompradorCorrente(comprador)

Nesse

caso

no

verificao

da

condio.

Quem

chamar

operao

identificaComprador deve garantir que o CPF passado como parmetro seja vlido.

8.6 Contratos Padro CRUD


O processo de criao de contratos est intimamente ligado ao caso de uso expandido e
ao modelo conceitual. Deve-se usar o modelo conceitual como referncia em todos os
momentos porque ele a fonte de informao sobre quais asseres podem ser feitas.
Os contratos devem ser sempre escritos como expresses interpretveis em termos dos
elementos do modelo conceitual. Assim, asseres como foi impresso um recibo
dificilmente sero ps-condies de um contrato, visto que no representam informao
do modelo conceitual. Tais expresses no podem sequer ser representadas em OCL.
Mesmo que o analista quisesse por algum motivo armazenar a informao de que um
recibo foi impresso aps a execuo de alguma operao, a ps-condio deveria ser
escrita de forma a poder ser interpretada como alterao de alguma informao no
modelo conceitual, como por exemplo, o atributo reciboImpresso do
emprestimoAberto foi alterado para true ou, em OCL:
post:
emprestimoAberto^setReciboImpresso(true)
As subsees seguintes apresentam modelos de contratos para as operaes tpicas
CRUD. So trs contratos de operao e sistema, e um contrato de consulta de sistema.
As operaes so executadas sobre a classe Livro, definida segundo o modelo conceitual
da Figura 8.7.

Figura 8.7: Modelo conceitual de referncia para contratos de operaes CRUD.

8.6.1 Operaes de Criao (Create)


Para as operaes e consultas ligadas manuteno de informaes (cadastros), os
contratos sero mais ou menos padronizados. Insero (create) de informao sempre vai
incluir a criao de uma instncia, alterao de seus atributos e a criao de uma
associao com a controladora do sistema ou com alguma outra classe:
Context Livir::criaLivro(umIsbn, umTitulo, umAutor)
def:
novoLivro = Livro::newInstance()
post:
self^addLivros(novoLivro) AND
novoLivro^setIsbn(umIsbn) AND
novoLivro^setTitulo(umTitulo) AND
novoLivro^setAutor(umAutor)

Como o atributo isbn j est estereotipado com <<oid>> no necessrio estabelecer


como exceo a tentativa de inserir um livro cujo isbn j exista, pois essa exceo j
prevista pelo prprio esteretipo. Mas, se ao em vez de exceo esse fato for assumido
como precondio, ela deve ficar explcita:
Context Livir criaLivro(umIsbn, umTitulo, umAutor)
def:
novoLivro = Livro::newInstance()
pre:
livrosselect(isbn=umIsbn)isEmpty()
post:
self^addLivros(novoLivro) AND
novoLivro^setIsbn(umIsbn) AND
novoLivro^setTitulo(umTitulo) AND
novoLivro^setAutor(umAutor)

8.6.2 Operaes de Alterao (Update)


As alteraes de informao vo envolver apenas a alterao de atributos ou,
possivelmente, a criao e/ou destruio de associaes:
Context Livir alteraLivro(umIsbn, novoIsbn, umTitulo, umAutor)
def:
livro = livrosselect(isbn=umIsbn)
pre:
livrosize() = 1

post:
livro^setIsbn(novoIsbn) AND
livro^setTitulo(umTitulo) AND
livro^setAutor(umAutor)

H dois padres aqui envolvendo a alterao de atributos marcados com <<oid>>:


a) no se permite que sejam alterados. O objeto deve ser destrudo e um novo objeto
criado;
b) permite-se a alterao. Nesse caso, a operao passa dois argumentos: o ISBN
anterior e o novo, como foi feito no exemplo anterior. Se o novo ISBN
corresponder a um livro j existente haver uma exceo porque esse atributo foi
marcado como oid.
Tambm h duas opes em relao a verificar se o livro com identificador umISBN
existe ou no:
a) entende-se como exceo o fato de no existir um livro com o ISBN dado;
b) define-se uma precondio que garante que o livro com umISBN existe, como foi
feito no exemplo.

8.6.3 Operaes de Excluso (Delete)


As operaes de sistema que exluem objetos tero de considerar as regras de restrio
estrutural do modelo conceitual antes de decidir se um objeto pode ou no ser destrudo e,
caso possa, verificar se outros objetos tambm devem ser destrudos junto com ele.
No caso da Figura 8.7, por exemplo, uma instncia de Livro no pode ser simplesmente
destruda sem que se verifique o que acontece com possveis instncias de Item ligadas
ao livro, j que do ponto de vista dos itens a associao com um livro obrigatria.
Para que a excluso seja feita sem ferir esse tipo de restrio estrutural pode-se escolher
uma dentre trs abordagens:
a) garantir por precondio que o livro sendo excludo no possui nenhum item
ligado a ele. A associao, do ponto de vista do livro, opcional. Por essa
abordagem, apenas livros que no tm itens associados podem ser selecionados
para excluso;
b) garantir por ps-condio que todos os itens ligados ao livro tambm sero
excludos. Usa-se essa abordagem quando se quer que a operao de excluso se
propague para todos os objetos (no caso, itens) que tm associaes obrigatrias
com o livro. Essa propagao continua atingindo outros objetos em cadeia at que
no haja mais ligaes baseadas em associaes obrigatrias;
c) utilizar uma exceo para abortar a operao caso seja tentada sobre um livro que
tenha itens associados a ele.
Um possvel contrato usando a abordagem de precondio teria esse formato:
Context Livir::excluiLivro(umIsbn)

def:
livro = livrosselect(isbn=umIsbn)
pre:
livrosize() = 1 AND
livro.itenssize() = 0
post:
livro^destroy()

Conforme indicado, a mensagem destroy elimina a instncia de Livro, bem como todas
as suas associaes que, portanto, no precisam ser removidas uma a uma.
Um possvel contrato usando a abordagem de ps-condio, que propaga a excluso a
todos os objetos ligados ao livro por associaes de multiplicidade de papel obrigatria,
teria o seguinte formato:
Context Livir::excluiLivro(umIsbn)
def:
livro = livrosselect(isbn=umIsbn)
pre:
livrosize() = 1
post:
livro.itensforAll(item|item^destroy()) AND
livro^destroy()

A ps-condio afirma ento que, alm do livro, todos os itens ligados a ele foram
destrudos. Como a classe Item no possui associaes obrigatrias vindas de outras
classes, a destruio pode parar por a, mas caso contrrio seria necessrio destruir outros
objetos.
Um possvel contrato usando a abordagem de exceo teria este formato:
Context Livir::excluiLivro(umIsbn)
def:
livro = livrosselect(isbn=umIsbn)
pre:
livrosize() = 1
post:
livro^destroy()
exception:

livro.itensnotEmpty() IMPLIES
self^throw(no possvel excluir este livro)

Escolhe-se a abordagem de ps-condio quando se quer propagar a excluso a todos os


elementos dependentes do objeto destrudo. Por exemplo, se um comprador for destrudo,
quaisquer reservas que ele tenha no sistema podem ser destrudas junto.
Mas h situaes em que no se quer essa propagao. Por exemplo, a remoo de um
livro do catlogo no deveria ser possvel se cpias dele j foram vendidas. Nesse caso,
deve-se optar pelas abordagens de precondio ou exceo. A primeira vai exigir que se
impea que um livro com itens associados possa sofrer a operao de excluso. Por
exemplo, a lista de livros disponvel para a operao de excluso poderia conter apenas
aqueles que no possuem itens associados. Caso no se queira ou no se possa dar essa
garantia, resta a abordagem de exceo. Deixa-se o usurio tentar a excluso, mas, se ela
no for possvel, uma exceo criada.
Usualmente, informaes cadastrais como essas nunca so removidas de sistemas de
informao, mas marcadas com algum atributo booleano que indica se so instncias
ativas ou no. Afinal, no se poderia ter registros histricos de vendas de livros se os
livros que saem de circulao fossem simplesmente removidos do sistema de informao.

8.6.4 Consultas (Retrieve)


A consulta simples do padro CRUD implica simplesmente a apresentao de dados
disponveis sobre uma instncia de um determinado conceito a partir de um identificador
dessa instncia. Nessas consultas no se fazem totalizaes ou filtragens, ficando essas
operaes restritas aos relatrios (esteretipo <<rep>>).
Ento, uma consulta simples para a classe Livro da Figura 8.7 seria:
Context Livir::consultaLivro(umIsbn):Tuple
def:
livro = livrosselect(isbn=umIsbn)
body:
Tuple{
isbn = livro.isbn,
titulo = livro.titulo,
preco = livro.preco,
autor = livro.autor,
status = livro.status
}

A consulta do tipo CRUD retorna sempre uma tupla com os dados constantes nos
atributos do objeto selecionado por seu identificador.

8.7 Contrato Padro Listagem


Frequentemente necessrio utilizar operaes de listagem de um ou mais atributos de
um conjunto de instncias de uma determinada classe para preencher listas ou menus em
interfaces.
Um primeiro contrato de listagem (simples) vai apenas listar os ISBN dos livros
catalogados na livraria:
Context Livir::listaIsbn():Set
body:
self.livros.isbn

Caso se deseje uma lista de mltiplas colunas como, por exemplo, ISBN e ttulo,
necessrio retornar uma coleo de tuplas, como:
Context Livir::listaIsbnTitulo():Set
body:
self.livroscollect(livro|
Tuple{
isbn = livro.isbn,
titulo = livro.titulo
}
)

Por vezes ser necessrio aplicar um filtro lista, como, por exemplo, retornando apenas
o ISBN e ttulo de livros que no tm nenhum item associado (nunca foram vendidos).
Nesse caso aplica-se um select ao conjunto antes de formar as tuplas:
Context Livir::listaIsbnTituloNaoVendidos():Set
body:
self.livrosselect(livro|
livro.itensisEmpty()
) collect(livro|
Tuple{
isbn = livro.isbn,
titulo = livro.titulo
}
)

A maioria das consultas de simples listagem ter apenas estes dois construtores: um

select (filtro) seguido de um collect (projeo dos atributos que sero retornados). Mas
algumas podero ser mais complexas. Nesses casos, elas j no se encaixam no padro
Listagem, mas no padro Relatrio (<<rep>>).

8.8 Contratos Relacionados com Casos de Uso


Para as operaes associadas com casos de uso, frequentemente haver uma cadeia de
execuo ao longo de um dos fluxos, em que duas ou mais operaes de sistema sero
executadas. Possivelmente cada operao poder deixar informaes para as demais na
forma de associaes temporrias. Para melhor construir os contratos dessas operaes,
uma abordagem possvel seguir a sequncia das operaes de sistema do caso de uso
expandido. Nesse processo, o analista deve se perguntar:
a) qual o objetivo de cada operao?
b) o que cada uma delas produz?
c) o que cada uma delas espera que tenha sido produzido pelas anteriores?
d) que excees poderiam ocorrer durante a execuo?
e) a operao segue algum padro como CRUD, Listagem ou REP?
Ao responder a essas perguntas, o analista estar construindo contratos que permitiro
que as operaes sejam executadas de forma consistente no contexto de uma transao.
Se for necessrio adicionar novas consultas no diagrama de sequncia para garantir certas
precondies, isso deve ser feito nesse momento.
As subsees seguintes vo apresentar todos os contratos para as operaes e consultas
de sistema relacionadas ao caso de uso apresentado na forma de diagrama de sequncia
nas Figuras 6.5 (stateless) e 6.6 (statefull).

8.8.1 Contratos para Estratgia Stateless


Em funo de a estratgia ser stateless, as operaes e consultas da Figura 6.5 vo enviar
as informaes ao sistema cada vez que elas forem necessrias. Informaes temporrias
no sero guardadas. Isso afeta os objetivos das operaes e consultas. A Tabela 8.1
apresenta a lista das operaes e consultas de sistema identificadas na Figura 6.5.
Tabela 8.1
criaCompra(idComprador):LongInt
listaLivrosDisponiveis():Set
adicionaCompra(idCompra, idLivro, quantidade)
consultaTotal(idCompra):Money
listaEnderecos(idComprador):Set
defineEnderecoEntrega(idCompra, idEndereco)
consultaFrete(idCompra):Money
consultaTotalGeral(idCompra):Money
listaCartoes(idComprador):Set
defineCartao(idCompra,idCartao)
solicitacaoPagto(idCompra):Tuple

registraPagto(idCompra, codigoAutorizacao)
consultaPrazoEntrega(idCompra):Date
A Figura 8.8 apresenta o modelo conceitual de referncia para essas operaes.

Figura 8.8: Modelo conceitual de referncia para as operaes da Tabela 8.1.


Na figura 8.8 conforme feito acima:
- acrescentar ligao de Cidade com Livir
- associao de Compra pra Carto para 0..1 e no para 1.
- associao de Compra para Endereco para 0..1 e no para 1.
O primeiro contrato refere-se a uma operao que cria uma nova compra para um
comprador identificado pelo seu idComprador. A operao deve retornar um idCompra
(criado automaticamente pelo sistema) para ser usado como parmetro para identificar
essa nova compra nas demais operaes. Trata-se de um contrato cuja operao encaixase na situao, j mencionada, que permite que um retorno seja enviado contendo o
identificador de um objeto criado pela operao de sistema. Excepcionalmente, essa
operao ter dentro da clausula post um comando return, para indicar que uma
operao que retorna um valor:
Context Livir::criaCompra(idComprador):LongInt
def:

novaCompra = Compra::newInstance()
def:
comprador = compradores[idComprador]
post:
novaCompra^setNumero(novoNumeroAutomatico()) AND
novaCompra^setData(dataAtual()) AND
novaCompra^addComprador(comprador) AND
return: novaCompra.numero
exception:
compradorsize() = 0 IMPLIES
self^throw(Comprador no cadastrado)

As ps-condies referenciam duas funes que a princpio seriam definidas em


bibliotecas especficas, que so novoNumeroAutomatico, para gerar um novo
identificador para uma venda, e dataAtual, que retorna a data do sistema.
A consulta de sistema listaLivrosDisponveis segue o padro listagem (com filtro) e
deve retornar as informaes sobre ISBN, ttulo, autor e preo de todos os livros que
tenham pelo menos um exemplar em estoque. necessrio aplicar um filtro ao conjunto
de livros antes de obter seus dados:
Context Livir::listaLivrosDisponiveis():Set
body:
livrosselect(
estoque>0
)collect(livro|
Tuple{
isbn = livro.isbn,
titulo = livro.titulo,
preco = livro.preco,
autor = livro.autor
}
)

A operao adicionaCompra deve adicionar uma quantidade indicada de exemplares do


livro cujo ISBN dado compra cujo idCompra dado e reduzir do estoque a mesma
quantidade. Caso a quantidade solicitada seja superior quantidade em estoque, deve
ocorrer uma exceo:

Context Livir::adicionaCompra(idCompra, idLivro, quantidade)


def:
compra = compras[idCompra]
def:
livro = livros[idLivro]
def:
item = Item::newInstance()
pre:
comprasize() = 1 AND
livrosize() = 1
post:
item^setQuantidade(quantidade) AND
item^setValor(livro.preco) AND
item^addCompra(compra) AND
item^addLivro(livro) AND
livro^setEstoque(livro.estoque@pre quantidade)
exception:
quantidade > livro.estoque IMPLIES
self^throw(quantidade insuficiente em estoque)

Seria possvel perguntar por que a exceo referencia livro.estoque e no


livro.estoque@pre. Isso se deve ao fato de que a exceo, assim como as precondies
e definies referem-se a valores existentes antes de a operao ser executada. Apenas as
ps-condies referenciam valores posteriores e, por isso, em alguns casos exigem o uso
de @pre.
Seguem os contratos das demais operaes e consultas da Tabela 8.1:
Context Livir::consultaTotal(idCompra):Money
def:
compra = compras[idCompra]
pre:
comprasize() = 1
body:
compra.total
Context Livir::listaEnderecos(idComprador):Set
def:
comprador = compradores[idComprador]

pre:
compradorsize() = 1
body:
comprador.enderecoscollect(endereco|
Tuple {
id = endereco.idEndereco,
rua = endereco.rua,
numero = endereco.numero,
cidade = endereco.cidade.nome,
uf = endereco.cidade.uf
}
)
Context Livir::defineEnderecoEntrega(idCompra, idEndereco)
def:
compra = compras[idCompra]
def:
endereco = compra.comprador.enderecos[idEndereco]1
pre:
comprasize() = 1 AND
enderecosize() = 1
post:
compra^addEnderecoEntrega(endereco)
Context Livir::consultaFrete(idCompra):Money
def:
compra = compras[idCompra]
pre:
comprasize() = 1
body:
compra.frete
1

Aqui no necessrio verificar por precondio que o comprador existe e nico porque isso j uma
condio estrutural do modelo conceitual, j que a associao de Compra para Pessoa tem multiplicidade
1.

Context Livir::consultaTotalGeral(idCompra):Money
def:
compra = compras[idCompra]
pre:
comprasize() = 1
body:
compra.totalGeral
Context Livir::listaCartoes(idComprador):Set
def:
comprador = compradores[idComprador]
pre:
compradorsize() = 1
body:
comprador.cartoescollect(cartao|
Tuple {
bandeira = cartao.bandeira.nome,
numero = cartao.numero
}
)

Context Livir::defineCartao(idCompra,idCartao)
def:
compra = compras[idCompra]
def:
cartao = compra.comprador.cartoesselect(numero=idCartao)
pre:
comprasize() = 1 AND
cartaosize() = 1
post:
compra^addCartao(cartao)
Context Livir::solicitacaoPagto(idCompra):Tuple

def:
compra = compras[idCompra]
pre:
comprasize() = 1
body:
Tuple {
numero = compra.cartao.numero,
titular = compra.cartao.titular,
validade = compra.cartao.validade,
codSeg = compra.cartao.codSeg,
valor = compra.totalGeral
}
Context Livir::registraPagto(codigoAutorizacao, idCompra)2
def:
compra = compras[idCompra]
pre:
comprasize() = 1
post:
compra.autorizacao^setCodigo(codigoAutorizacao)3

Context Livir::consultaPrazoEntrega(idCompra):Date
def:
compra = compras[idCompra]
pre:
comprasize() = 1
body:
compra.enderecoEntrega.cidade.tempoEntrega

2
3

Aqui no se considerou a possvel exceo de a compra eventualmente no ser autorizada.

Como Autorizao uma classe de associao, esta instncia foi criada no momento em que o carto foi
associado com a compra na operao defineCartao. Porm, naquele momento o cdigo de autorizao era
zero.

A situao aqui representada simplificada com o objetivo de mostrar como possveis


contratos poderiam ser feitos. No se pretende demonstrar uma situao real de compra,
que seria bem mais complexa e, portanto, fugiria dos objetivos do livro.

8.8.2 Contratos para a Estratgia Statefull


A estratgia statefull pressupe que o sistema seja capaz de lembrar determinadas
informaes temporrias, o que no possvel com a estratgia stateless. Por isso, no
necessrio tanta passagem de parmetros quando se usa a estratgia statefull, mas
necessrio estabelecer como essas informaes sero armazenadas.
Uma possibilidade seria armazenar essas informaes em variveis globais ou da classe
controladora. Mas tais solues so pouco elegantes por fugirem da estrutura usual do
modelo conceitual. Melhor seria representar essas informaes temporrias como
associaes temporrias adicionadas ao modelo conceitual, como na Figura 8.9.

Figura 8.9: Modelo conceitual de referncia para estratgia statefull.


Na figura 8.9 conforme feito acima:
- acrescentar ligao de Cidade com Livir
- associao de Compra pra Carto para 0..1 e no para 1.
- associao de Compra para Endereco para 0..1 e no para 1.
Nesse caso, basta guardar a informao da compra corrente, pois comprador, carto e
endereo j podem ser inferidos pelas associaes persistentes existentes.

Por outro lado, no mais necessria a associao derivada para encontrar a compra
corrente a partir de seu nmero, visto que a associao temporria permite acesso direto a
essa instncia.
A Tabela 8.2 apresenta as operaes e consultas de sistema para a estratgia statefull,
conforme o diagrama da Figura 6.6.
Tabela 8.2: Operaes e Consultas de Sistema da Figura 6.6
criaCompra(idComprador)
listaLivrosDisponiveis():Set
adicionaCompra(idLivro, quantidade)
consultaTotal():Money
listaEnderecos():Set
defineEnderecoEntrega(idEndereco)
consultaFrete():Money
consultaTotalGeral():Money
listaCartoes():Set
definecartao(idCartao)
solicitacaoPagto():Tuple
registraPagto(codigoAutorizacao)
consultaPrazoEntrega():Date
A primeira operao, criaCompra(idComprador), no precisa mais retornar o

idCompra, pois a compra corrente ficar registrada na associao temporria


compraCorrente. Seu contrato fica, portanto, assim:
Context Livir::criaCompra(idComprador)
def:
novaCompra = Compra::newInstance()
def:
comprador = compradores[idComprador]
post:
novaCompra^setNumero(novoNumeroAutomatico()) AND
novaCompra^setData(dataAtual()) AND
novaCompra^addComprador(comprador) AND
self^addCompraCorrente(novaCompra)

exception:
compradorsize() = 0 IMPLIES
self^throw(Comprador no cadastrado)

Os contratos da consulta listaLivrosDisponiveis so idnticos nos dois casos. Seguem


os contratos das demais consultas e operaes de sistema:
Context Livir::adicionaCompra(idLivro, quantidade)
def:
livro = livros[idLivro]
def:
item = Item::newInstance()
pre:
livrosize() = 1 AND
compraCorrentesize() = 1
post:
item^setQuantidade(quantidade) AND
item^setValor(valor) AND
item^addCompra(compraCorrente) AND
item^addLivro(livro) AND
livro^setEstoque(livro.estoque@pre quantidade)
exception:
quantidade>livro.estoque IMPLIES
self^throw(quantidade insuficiente em estoque)
Context Livir::consultaTotal():Money
pre:
compraCorrentesize() = 1
body:
compraCorrente.total
Context Livir::listaEnderecos():Set
pre:
compraCorrentesize() = 1

body:
compraCorrente.comprador.enderecoscollect(endereco|
Tuple {
id = endereco.idEndereco,
rua = endereco.rua,
numero = endereco.numero,
cidade = endereco.cidade.nome,
uf = endereco.cidade.uf
}
)

Context Livir::defineEnderecoEntrega(idEndereco)
def:
endereco = compraCorrente.comprador.enderecos[idEndereco]
pre:
enderecosize() = 1 AND
compraCorrentesize() = 1
post:
compraCorrente^addEnderecoEntrega(endereco)

Context Livir::consultaFrete():Money
pre:
compraCorrentesize() = 1
body:
compraCorrente.frete
Context Livir::consultaTotalGeral():Money
pre:
compraCorrentesize() = 1
body:
compraCorrente.totalGeral
Context Livir::listaCartoes():Set
pre:
compraCorrentesize() = 1

body:
compraCorrente.comprador.cartoescollect(cartao|
Tuple {
bandeira = cartao.bandeira.nome,
numero = cartao.numero
}
)
Context Livir::definecartao(idCartao)
def:
cartao = compraCorrente.comprador.cartoes
select(numero=idCartao)
pre:
cartaosize() = 1 AND
compraCorrentesize() = 1
post:
compraCorrente^addCartao(cartao)
Context Livir::solicitacaoPagto():Tuple
pre:
compraCorrentesize() = 1 AND
compraCorrente.cartao->size() = 1
body:
Tuple {
numero = compraCorrente.cartao.numero,
titular = compraCorrente.cartao.titular,
validade = compraCorrente.cartao.validade,
codSeg = compraCorrente.cartao.codSeg
}

Context Livir::registraPagto(codigoAutorizacao)
pre:
compraCorrentesize() = 1 AND
compraCorrente.cartao->size()=1

post:
compraCorrente.autorizacao^setCodigo(codigoAutorizacao)

Context Livir::consultaPrazoEntrega():Date
pre:
compraCorrentesize() = 1
body:
compraCorrente.enderecoEntrega.cidade.tempoEntrega

Observa-se que, na maioria das operaes e consultas, a principal alterao entre as


estratgias stateless e statefull foi a troca da expresso, que era definida como

compras[idCompra] na estratgia stateless, por self.compraCorrente na estratgia


statefull.

9 Projeto da Camada de Domnio


10 Projeto da Camada de Interface (Web)
11 Persistncia
12 Gerao de Cdigo e Testes
13 Bibliografia
Adams, D.N. O guia do mochileiro das galxias. Sextante, 2004. (Traduo de The
hitchhickers guide to the galaxy, Completely Unexpected Productions Ltd., 1979.)
Adams, D.N. Vida, universo e tudo o mais. Sextante, 2005. (Traduo de Life, universe
and everything, Completely Unexpected Productions Ltd., 1982.)
Alford, M. Requirements-driven software design. McGraw Hill, 1991.
Ambler, S. Process patterns. Cambridge University Press, 1998.
Ambler, S., Constantine, L., Smith, R. The Unified Process elaboration phase: best
practices in implementing the UP. CMP Books, 2000.
Arlow, J., Neustadt, I. UML and the Unified Process: practical object-oriented analysis
and design. Pearson Education, 2001.
Beck, K. Programao extrema XP explicada: acolha as mudanas. Porto Alegre:
Bookman, 2004. (Traduo de Extreme programming explained: embrace change.)

Bezerra, E. Princpios de anlise e projeto de sistemas com UML. CampusElsevier,


2003.
Boehm, B.W. Software engineering. IEEE. Transactions on Computers, vol. 25, n. 12,
1976.
Booch, G.
1993.

Object-oriented analysis and design with applications. Addison-Wesley,

Booch, G. Object solutions managing the object-oriented project. Addison-Wesley,


1996.
Brown, A.W. Large-scale component-based development. Prentice-Hall, 2000.
Ceri, S., Fraternali, P., Bongio, A., Brambilla, M., Comai, S., Matera, M. Designing
data-intensive Web applications. Morgan Kaufmann Publishers, 2003.
Cox, B. Object-oriented programming: an evolutionary approach. Addison-Wesley,
1986.
DSouza, D.F., Wils A.C. Objects, components, and frameworks with UML. AddisonWesley, 1999.
Date, C.J. An introduction to database systems. Addison-Wesley, 1982.
Emam, K., Drouin, J.N., Melo, W. Spice: the theory and practice of software process
improvement and capability determination. IEEE Computer Society, 1998.
Embley, D.W., Kurtz, B.D., Woodfield, S.N. Object-oriented systems analysis: a modeldriven approach. Prentice-Hall, 1992.
Erickson, H.E., Penker, M. UML toolkit. John Wiley and Sons Inc., 1998.
Fayad, M.E., Schmidt, D.C., Johnson, R.E. Implementing application frameworks. John
Wiley & Sons, Inc., 1999.
Fowler, M., Scott, K. UML distilled. Addison-Wesley, 1997.
Fowler, M. Patterns of enterprise application architecture. Addison-Wesley, 2003.
Gamma, E., Helm, R., Johnson, R., Vlissides, J. Design patterns. Elements of reusable
object-oriented software. Addison-Wesley, 1995.
Garmus, D., Herron, D. Function point analysis: measurement practices for successful
software projects. Addison-Wesley Information Technology Series, 2000.
Goldberg, A., Robson, D. Smalltalk 80: the language. Addison-Wesley Pub Co., 1989.
Jacobson, I., Christerson, M., Jonsson, P., vergaard, G. Object-oriented software
enginneering- a use CASE driven approach. Addison-Wesley, 1992.
Jacobson, I. The object advantage- business process reengineering with object
technology. Addison-Wesley, 1994.
Jacobson, I., Booch, G., Rumbaugh, J. The unified software development process.
Addison-Wesley, 1999.

Kehoe, R., Jarvis, A., Shah-Jarvis, A. Iso 9000-3: a tool for software product and process
improvement. Springer Verlag, 1996.
Larman, C. Applying UML and patterns: an introduction to object-oriented analysis and
design and the unified process. Prentice Hall, 2001.
Lieberherr, Karl, Holland, I. Assuring good style for object-oriented programs. IEEE
Software: 3848, September 1989.
Karner, G. Use CASE points resource estimation for objectory projects. Objective
Systems, 1993.
Kruchten, P. The rational unified process: an introduction. Addison-Wesley, 2000.
Kruchten, P. The rational unified process made easy: a practitioners guide to rational
unified process. Addison-Wesley, 2003.
Maldonado, J.C., Delamaro, M.E., Jino, M. Introduo ao teste de software. CampusElsevier, 2007.
Martin, R.C. Agile software development, principles, patterns, and practices. PrenticeHall, 2002.
Meyer, B. Object-oriented software construction. Prentice Hall, 1988.
Meyer, B. Eiffel: the language. Prentice-Hall, 1992.
Mitchel, R., McKim, J. Design by contract by example. Addison-Wesley, 2001.
Object Management Group (OMG) Object Constraint Language OMG available
specification
version
2.0.
Disponvel
em
http://www.omg.org/technology/documents/formal/ocl.htm. Consultado em 26 de agosto
de 2009.
Object Management Group, OMG Unified Modeling Language UML. Disponvel em
http://www.omg.org/technology/documents/modeling_spec_catalog.htm#UML.
Consultado em 23 de setembro de 2009.
Page-Jones, M. Fundamentos do desenho orientado a objeto com UML. Makron Books,
2001. (Traduo de Fundamentals of object-oriented design in UML.)
Paula Filho, W.P. Engenharia de software: fundamentos, mtodos e padres. LTC,
2003).
Pereira e Silva, R. UML 2 Modelagem orientada a objetos. Visual Books, 2007.
Pereira e Silva, R. Como modelar com UML 2. Visual Books, 2009.
Pressman, R.S. Software engineering: a practitioners approach. McGraw Hill, 2010.
Riel, A. J. Object-oriented design heuristics. Addison-Wesley, 1996.
Rocha, A.R.C., Maldonado, J.C., Weber, K.C. Qualidade de software: teoria e prtica.
PearsonPrentice-Hall, 2001.
Royce, W. Managing the development of large software Systems. Proceedings of IEEE
WESCON, 1970.

Rumbaugh, J., Blaha, M.R., Lorensen, W., Eddy, F., Premerlani, W. Object-oriented
modeling and design. Prentice Hall, 1990.
Rumbaugh, J., Jacobson, I., Booch, G. The Unified Modeling Language reference
manual. Addison-Wesley, 1999.
Santos, C.C. Gerao automtica de diagramas de comunicao a partir de contratos
OCL. Dissertao de Mestrado, UFSC-PPGCC, 2007.
Scott, K. The Unified Process explained. Addison-Wesley Pub Co., 2001 (O processo
unificado explicado. Bookman, 2003.)
Shalloway, A., Trott, J.R. Explicando padres de projeto: uma nova perspectiva em
projeto orientado a objeto. Bookman. (Traduo de Design patterns explained: a new
perspective on object-oriented design.)
Silva, A.A., Gomide, C.F., Petrillo, F. Metodologia e projeto de software orientados a
objetos: modelando, projetando e desenvolvendo sistemas com UML e componentes
distribudos. rica, 2003.
Warmer, J., Keppe, A. The Object Constraint Language: precise modeling with UML.
Addison-Wesley Pub Co., 1998.
Wirfs-Brock, R., McKean, A. Object design: roles, responsibilities, and collaborations.
Addison-Wesley, 2002.

Apndice: Sumrio OCL


Apenas expresses e comandos usados neste livro so apresentados. Para uma definio
mais completa de OCL sugere-se consultar Warmer e Keppe (1998) ou OMG (2009). H
tambm
um
bom
guia
de
referncia
rpida
em
http://www.eoinwoods.info/doc/ocl_quick_reference.pdf.
.

1. Referencia um atributo ( direita) de um objeto ( esquerda).


2. Referencia uma coleo de objetos associados por um papel (
direita) a outro objeto.
3. Referencia o retorno de um mtodo ( direita) enviado a um objeto (
esquerda).
Obs. Quando aplicado a uma coleo de objetos ( esquerda) referencia
uma coleo da aplicao do mesmo operador a cada um dos objetos.
Exemplos:
pessoa.idade --atributo
pessoa.automoveis --associao
pessoa.getEndereco() --mtodo
compradores.nome --aplicado a uma coleo

::

1. Indica que um mtodo ( direita) est implementado em uma classe


( esquerda).
2. Indica que um valor ( direita) pertence a uma enumerao (
esquerda).
3. Indica envio de uma mensagem a uma classe.
Exemplo:
Venda::getValorTotal():Moeda -- mtodo
EstadoPagto::pendente - enumerao
Livro::newInstance() - mtodo de classe

Indica que a mensagem ( direita) enviada a uma coleo (


esquerda). Exemplo:
clientessize()

A expresso verdadeira se a mensagem indicada direita com seus


parmetros foi enviada ao objeto ou coleo denotado pela expresso
esquerda. Usada especialmente em ps-condies para indicar que uma
mensagem foi enviada a um objeto. Exemplo:
pessoa^setData(novaData)

[ ]

Notao para acessar um elemento diretamente em uma associao

qualificada. Exemplo:
compradores[cpf]

@pre

Usada em ps-condies de operaes para indicar o valor de um


atributo, objeto ou associao antes de a operao ter sido executada
porque por default qualquer valor referenciado em uma ps-condio
posterior execuo da operao. Exemplo:
post:
if self.saldo@pre = 0 then
self^setSaldo(1)
endIf

AND

Conector de duas expresses lgicas. A expresso resultante


verdadeira se as expresses direita e esquerda so verdadeiras.
Exemplo:
x=1 AND y<3

body:

Indica que a expresso direita a definio (retorno) de uma consulta


(mtodo) do contexto definido esquerda. Exemplo:
Context Livir::saldoCompradorCorrente():Moeda
body: compradorCorrente.saldo

collect:

Retorna uma coleo cujos elementos consistem na avaliao da


expresso entre parnteses aplicada a cada elemento da coleo original
( esquerda). Em algumas situaes pode ser substituda pela notao
.. Exemplo:
compradorescollect(c|
Tuple {
cpf = c.cpf,
nome = c.nome,
telefone = c.telefone
}

Context

Indica o contexto de uma expresso: classe, mtodo, associao ou


atributo. Exemplos:
Context Venda -- classe
Context Venda::getValorTotal():Moeda -- mtodo
Context Pessoa::nome -- atributo
Context Venda::itens - associao

def:

Usado para definir um termo que passa a valer como resultado de uma
expresso. Exemplo:
def: comprador = compradores[cpfComprador]

derive:

Usado para definir um atributo derivado. esquerda deve constar o


atributo como contexto e direita uma expresso. Exemplo:
Context Produto::lucroBruto:Moeda

derive: precoVenda precoCompra

exception:

Indica que a expresso a seguir avaliada se ocorrer uma exceo


durante a execuo de um mtodo definido no contexto esquerda:
Context Livir::identificaComprador(umCpf)
def:
comprador = compradoresselect(cpf = umCpf)
post:
self^addCompradorCorrente(comprador)
exception:
compradorsize() = 0 IMPLIES
self^throw(cpf invlido)

exists()

Retorna true se a coleo ( esquerda) possuir pelo menos um elemento


para o qual a expresso entre parnteses verdadeira. Exemplo:
compradoresexists(saldo = 0)

forAll()

No contexto de uma invariante ou ps-condio indica que a expresso


entre parnteses verdadeira para todos os elementos da coleo
esquerda. Exemplo:
Context Aluno
inv:
self.disciplinasforAll(d|
d.cursosincludes(self.curso)
)

if then
else endIf

Se a condio aps o if for verdadeira, a expresso como um todo vale


a expresso entre o then e o else. Caso contrrio, a expresso como
um todo consiste na avaliao da expresso entre o else e o endIf.

IMPLIES

Conector de duas expresses lgicas. A expresso resultante


verdadeira se a primeira for falsa ou ambas verdadeiras. Pode ser
substitudo por uma estrutura if...then...endif. Exemplo:
x=1 IMPLIES y<3

includes()

Mensagem enviada a uma coleo. Retorna true se o parmetro


pertence ao conjunto e false caso contrrio. Exemplo:
clientesincludes(joao)

init:

Usado para definir um valor inicial para um atributo. esquerda deve


constar o atributo como contexto e direita uma expresso. Exemplo:
Context Venda::valorTotal:Moeda init: 0.0

inv:

Indica que a expresso direita uma invariante para a classe que


aparece como contexto ( esquerda). Exemplo:
Context Transacao inv:
self.movimentos.valorsum() = 0

isEmpty()

Retorna true se a coleo esquerda vazia e false caso contrrio.


Exemplo:
clientesisEmpty()

isNull()

Retorna true se a expresso esquerda indefinida e false caso


contrrio. Exemplo:
self.liquidacao.isNull()

notEmpty()

Retorna true se a coleo ( esquerda) for vazia e false caso contrrio.


Exemplo:
compradoresnotEmpty()

OR

Conector de duas expresses lgicas. A expresso resultante


verdadeira se pelo menos uma das expresses direita ou esquerda
verdadeira. Exemplo:
x=1 OR y<3

post:

Indica que a expresso direita uma ps-condio para o mtodo


indicado no contexto esquerda. Exemplo:
Context
Livir::criaLivro(umIsbn, umTitulo, umAutor)
def:
novoLivro = Livro::newInstance()
post:
self^addLivro(novoLivro) AND
novoLivro^setIsbn(umIsbn) AND
novoLivro^setTitulo(umTitulo) AND
novoLivro^setAutor(umAutor)

pre:

Indica que a expresso direita uma precondio para o mtodo


indicado no contexto esquerda. Exemplo:
Context Livir::operacaoQualquer()
pre:
compradorCorrentenotEmpty()

return:

Pode ser usado em operaes de sistema quando se deseja que retornem


algum valor. Exemplo:
Context Livir::criaCompra(idComprador):LongInt
def:
novaCompra = Compra::newInstance()
def:
comprador = compradores[idComprador]
post:
novaCompra^setNumero(novoNumeroAutomatico()) AND
novaCompra^setData(dataAtual()) AND
novaCompra^addComprador(comprador) AND
return: novaCompra.numero()

select()

Mensagem enviada a uma coleo ( esquerda). Retorna uma coleo

com os elementos para os quais a expresso entre parnteses


verdadeira. Exemplo:
pessoasselect(idade>18)

self

Denota uma instncia da classe do contexto. Se o contexto for uma


associao, mtodo ou atributo, ento a instncia da classe qual a
associao, mtodo ou atributo pertencem.

size()

Retorna o nmero de elementos da coleo esquerda. Exemplo:


livrossize()

sum()

Mensagem aplicvel apenas a colees de valores numricos. Retorna o


somatrio dos elementos. Pode ser aplicada diretamente a uma coleo
de nmeros (sem parmetros) ou a uma coleo de objetos (com um
parmetro que indica como obter valores numricos a partir da coleo
de objetos). Exemplos:
self.movimentos.valorsum()
self.movimentossum(valor)

Tuple{}

Construtor de tuplas. Entre as chaves devem aparecer as definies de


campos separadas por vrgula. Cada definio de campo tem um nome,
um sinal de igual e um valor. Exemplo:
Tuple{
nome = compradores[cpfComprador].nome,
telefone = compradores[cpfComprador].telefone
}