Disciplina: Modelagem de Sistemas Notas de Aula 06: Diagrama de classes de domínio Objetivos da aula: Compreender um modelo de negócio pela representação das classes de uma entidade Modelar as entidades e seus relacionamentos de um domínio por meio de um diagrama de classes Discutir decisões de modelagem Recordando... Na aula passada você estudou um exemplo de descrição de um caso de uso. Ao descrever um caso de uso podemos definir uma interface homem-máquina que determina quais as informações são relevantes para uma determinada funcionalidade. Mais do que isso, foi possível perceber que as informações eram pertinentes a uma conjunto de descrições que iam além das funcionalidades e podiam ser aplicadas mais de uma vez... Introdução Os casos de uso são uma excelente forma de demonstrar o comportamento de um sistema sob o ponto de vista de uma funcionalidade ou um conjunto de tarefas. Ao descrever uma funcionalidade do sistema, estamos também relatando quais dados (variáveis) são importantes para uma interação com um determinado ator. A visão de um sistema por casos de um uso é uma visão tradicional de desenvolvimento de um sistema. Legado da abordagem procedimental, a visão simplista do sistema como um conjunto de funções traz problemas de reutilização, pois, invariavelmente, certo conjunto de dados é utilizado em mais de uma função. Por exemplo, seja o domínio de uma universidade. Para um caso de uso de “Inserir Professor”, necessitaremos de dados referentes a uma entidade do mundo real – neste caso um Professor (CPF, endereço, telefone, etc.). Para o caso de uso “Alocar Turma”, também precisaremos, ao menos, do CPF do professor a ser alocado. Não é difícil enxergar que o atributo de uma Professor: Pablo Rangel, D.Sc. Disciplina: Modelagem de Sistemas determinada entidade (neste exemplo o CPF de um professor) pode ser utilizado para duas ou mais funções diferentes. Isso não significa que os casos de uso são dispensáveis. Os casos de uso necessitam de uma complementação para que a visão sobre o sistema seja mais aderente ao real e ao mesmo tempo pragmática. Classes e objetos A Orientação a Objetos (OO) une duas características fundamentais a serem feitas em um sistema: os dados mais as funções (que operam sobre estes dados). Os diagramas de classes da UML ajudam em dois aspectos do problema: visualizar o modelo de negócio e implementar o projeto de software. Uma das grandes vantagens de se utilizar a OO é a conversão direta do modelo de negócios (diagrama de classes de domínio) para artefatos de software (diagrama de classes de projeto). A literatura correlata separa ainda os diagramas de classes em três níveis: conceitual (domínio), lógico (projeto) e de implementação (projeto estendido). É evidente, então, que o elemento fundamental da OO é a classe. Uma classe descreve uma entidade do mundo real, abstrata ou não, relevante para um domínio de sistema. Uma classe descreve os atributos e as operações que são comuns a uma entidade. Os atributos endereço, telefone e nome descrevem uma classe PessoaJuridica¸ mas também descrevem uma classe PessoaFisica. Na inexistência de diferenças entre estas classes, podemos descrevê-las genericamente como uma classe que atenda ambos os casos. Que tal uma classe Pessoa? Na UML, uma classe é representada como um retângulo. O nome da classe vem na parte superior. Na segunda parte do retângulo vêm os atributos de uma classe. A terceira parte do retângulo se destina as operações de uma classe, assunto que será visto posteriormente. A UML sugere que os nomes de classes sejam no singular e comecem com a primeira letra maiúscula. Além disso, nomes de atributos começam com letras minúsculas. Classes ou Atributos com nomes compostos tem o segundo nome subsequente, sem caractere separador, com a primeira letra maiúscula. Exemplo: PessoaJuridica, endereçoComercial. Professor: Pablo Rangel, D.Sc. Disciplina: Modelagem de Sistemas De fato, entender como uma classe deve ser descrita não possui uma receita de bolo. A descrição de uma classe por meio de seus atributos é uma solução que varia de domínio para domínio. Por exemplo, se estivéssemos criando um sistema para um estacionamento, não faria muito sentido descrever o carro com um atributo chamado financiado (indica se o carro está financiado ou não). A informação de financiamento para cadastro de um carro não tem relevância para um sistema de estacionamentos (ao contrário do atributo mensalista). No entanto, se estivéssemos fazendo um sistema para uma concessionária de carros, tal informação seria vital para o modelo de negócios. Cabe ao Analista de Sistemas decidir sobre o que é relevante. Concessionária Estacionamento A manifestação de uma classe é chamada de objeto ou instância. Os objetos são ocorrência de uma classe. Por exemplo, uma instância de um objeto da classe Pessoa é Manoel, que possui o CPF 567.987.342-20, mora na Rua dos Canudos n. 17 e possui telefone (23) 9878-7656. Da classe Carro (do domínio estacionamento), um possível objeto da classe é Pálio, cor prata, placa ERJ 1608 e não é mensalista. Outro objeto desta mesma classe é Ka, cor branca, Professor: Pablo Rangel, D.Sc. Disciplina: Modelagem de Sistemas placa XYZ 1909 e é mensalista. Depreende-se, então, que uma classe pode possui diversos objetos. Outros exemplos: CLASSE OBJETOS Carro Meu Gol Empregado João Formulários Demissão Seu Corsa Pálio dele Ana Carlos Cadastro Vendas Associação de classes No mundo real, as entidades não estão sozinhas e a sua existência está intrinsicamente relacionada com a existência de outros objetos. A descrição de domínios complexos não está limitada a criação de classes sem nenhum tipo de interação com outras classes. Além da própria existência da classe, as associações entre classes constituem um dos agente promotores da reutilização de código. Afinal, o que é uma associação de classes? A associação de classes é um relacionamento estrutural que especifica objetos de um item conectados a objetos de outro item. A associação indica que existe uma ligação entre objetos das classes associadas. Cada associação pode ter um nome que descreve a natureza do relacionamento. Herança O conceito de herança permite estabelecer uma hierarquia entre as classes. É um mecanismo que permite a uma classe herdar as operações e os atributos de outra classe. Com o uso da herança, quando se escreve uma classe é necessário especificar apenas no que ela é diferente da classe-mãe, classebase ou superclasse. O mecanismo da herança dá acesso automático às informações contidas na classe base. Através da herança, uma classe possui imediatamente toda a funcionalidade de uma classe já existente. A classe que herda características da outra é chamada subclasse ou classe-filha e a classe que fornece a herança é chamada superclasse ou classe-mãe. Quando estávamos aprendendo o conceito de classes, foi utilizado como exemplo a classe PessoaJuridica e a classe PessoaFisica. Em um determinado momento percebeu-se que as duas classes possuíam atributos em comum. O resultado foi a fusão destas classes em uma classe mais genérica chamada Professor: Pablo Rangel, D.Sc. Disciplina: Modelagem de Sistemas Pessoa. Se o nosso domínio de problema fosse bem restritivo, esta solução estaria suficiente. Ocorre que no mundo real, apesar de terem vários atributos em comum, em algum momento deveremos colocar os atributos que são específicos para cada entidade. Por exemplo, se colocarmos o atributo cnpj, que é aplicado a uma empresa na classe Pessoa, estaremos cometendo um erro no nosso modelo, pois os objetos da classe Pessoa que efetivamente são cidadãos não terão informação para preencher neste caso (isso pode acarretar problemas computacionais também). O correto então, é especificar três classes por meio de uma herança e colocar os atributos que são pertinentes a todas as classes filhas na classe mãe e especificar os atributos que são aplicáveis para cada classe: A herança é, portanto, o compartilhamento de atributos e operações entre classes, baseado em um relacionamento hierárquico do tipo pai-filho (ou mãefilho), em que a classe pai possui definições que podem ser utilizadas nas classes filhas. Estas funcionam como uma especialização da classe pai (as filhas estendem a sua utilização básica da classe pai para outras utilizações mais especializadas). A seguir uma figura ilustrativa do conceito de herança. Professor: Pablo Rangel, D.Sc. Disciplina: Modelagem de Sistemas Uma superclasse direta é a superclasse a partir da qual a subclasse herda explicitamente. Uma superclasse indireta é qualquer superclasse acima da superclasse direta. Desta forma, no exemplo acima, Mamífero é uma superclasse direta de SerHumano e Animal é uma superclasse indireta de SerHumano. Na UML, uma herança pode ser definida como múltipla, o que significa que uma classe filha pode ter mais de uma classe mãe. Além de trazer problemas conceituais severos, a herança múltipla é rejeitada por diversas linguagens de programação. Assim, verifique se a herança múltipla não pode ser convertida em outro tipo de associação. Associações simples As classes de um domínio possuem outras associações que não estão em uma estrutura hierárquica. A modelagem compreende a tarefa de identificar que classes cooperam no entendimento do problema. Na UML existe uma maneira de representar esta compressão por meio dos conectores associativos e suas multiplicidades. Seja o nosso domínio da concessionárias de carros além da classe Pessoa já definida anteriormente. Ao descrevermos o problema, percebemos que todo carro tem uma pessoa como proprietária. Uma maneira de representar a relação que existe entre o proprietário e o carro é liga-los através de uma associação simples (uma linha que liga duas classes e possui um nome opcional): Professor: Pablo Rangel, D.Sc. Disciplina: Modelagem de Sistemas Além da ligação conceitual que estas classes têm, a quantificação de ocorrências desta ligação é muito importante. É a multiplicidade que determina quantas vezes um objeto se relaciona com outro objetos da classe associada. As associações estabelecem uma multiplicidade mínima e uma multiplicidade máxima de ocorrência. Se, ao informar que uma pessoa tem ao menos um carro, então a multiplicidade deve garantir que o modelo esteja especificando que para cada objeto do tipo Pessoa existirá ao menos um objeto do tipo Carro. Da mesma forma, podemos dizer que uma pessoa terá no máximo cinco carros associados, o que significa que um objeto da classe Pessoa estará associado a um máximo de cinco objetos da classe Carro. Devemos especificar a multiplicidade nas duas vias. Se do ponto de vista de um objeto da classe Pessoa a associação já está resolvida, as condições não estão associados para os objetos da classe Carro. Se for afirmado que um carro não necessariamente possui um dono, então a multiplicidade mínima é zero. Além disso, se dissermos que um carro deverá ter exatamente um dono, então a multiplicidade máxima é um. Professor: Pablo Rangel, D.Sc. Disciplina: Modelagem de Sistemas Muitas vezes não conseguimos determinar a multiplicidade máxima ou simplesmente torna-se perigoso presumi-la. Por exemplo, poderíamos dizer que uma pessoa tem ao menos um carro e no máximo muitos (sem especificar quantos). A multiplicidade máxima pode ser definida com um * que deixa em aberto o valor máximo. A multiplicidade máxima com * é a padrão quando averiguado omissão. Pelo princípio da herança, as classes PessoaJuridica e PessoaFisica também podem ser proprietárias de um carro: Professor: Pablo Rangel, D.Sc. Disciplina: Modelagem de Sistemas Classes associativas Alguns objetos de classes do nosso modelo só fazem sentido existir quando para a ocorrência de uma certa associação. Classes associativas expressam classes cujos objetos dependem da existência de outros objetos em conjunto. Por exemplo, a classe Turma. Uma turma (que não é a atriz – isso era para ser uma piada) corresponde a uma disciplina e tem um professor alocado. Uma possível solução é esta: A leitura deste modelo corresponde a “Um professor pode estar alocado em alguma turma e uma turma tem um professor” e “Uma disciplina pode ter várias turmas e uma turma é de uma disciplina”. Apesar de não estar errada, o valor semântico do modelo é pobre, pois dá a entender a existência de um objeto que de fato não faz sentido sem um objeto da classe Professor ou da classe Disciplina. O mais adequado é modelar a classe Turma como uma classe associativa, de forma que fique explícito que a existência de um objeto desta classe está conceitualmente ligada a existência dos objetos da classe Professor e Disciplina. Assim, um professor leciona uma ou mais disciplinas e uma disciplina é lecionada por um ou mais professores. A Professor: Pablo Rangel, D.Sc. Disciplina: Modelagem de Sistemas manifestação dessa associação implica na existência de um objeto da classe Turma, que entre outras coisas, pode conter os atributos horário e sala. Contudo, uma classe associativa não está limitada as “classes de origem”. A classe Turma pode ter relacionamentos simples. Por exemplo, uma turma deve ter ao menos um aluno e no máximo 50. Professor: Pablo Rangel, D.Sc. Disciplina: Modelagem de Sistemas Agregação e composição A granularidade de uma classe varia bastante até mesmo em um único domínio. Muitas vezes queremos demonstrar que uma classe ajuda a compor o entendimento da outra, em uma relação todo-parte. O relacionamento todoparte expressa uma classe que é o todo (totalidade) e as classes que forma este todos são expressas como partes. Apenas a leitura em conjunto expressa conceitualmente a ideia. O relacionamento é dito “faz parte de” ou “tem um”. A representação é feita com um losango na extremidade do todo. As associações de todo-parte cuja parte é independente do todo são chamadas de agregação. A existência dos objetos considerados partes não estão condicionadas a existência do objeto todo. Para a agregação, a representação do losango é aberta. Seja, por exemplo, um cinema. Um combo é composto de ao menos um refrigerante e exatamente uma pipoca. Uma pipoca ou refrigerante pode ser comercializado em nenhum combo ou em vários combos. As associações de todo-parte cuja parte é dependente do todo são chamadas de composição. A existência dos objetos considerados partes estão condicionadas a existência do objeto todo. Em função da dependência, o objeto parte sempre estará associado a apenas um objeto todo. Para associação de composição, o losango é fechado. Seja, por exemplo, um sistema empresarial. Uma empresa é composta de departamentos e um departamento pertence a uma única empresa. A exclusão do objeto empresa implica, necessariamente, na exclusão do objeto departamento. Professor: Pablo Rangel, D.Sc. Disciplina: Modelagem de Sistemas Auto associação Os modelos de classes reais podem apresentar situações onde uma classe possui uma relação recursiva, isto é, quando existe associação de uma classe consigo própria. Seja, por exemplo, um funcionário de uma empresa. É dito dentro de uma cadeia de comandos de uma empresa que um funcionário supervisiona outro funcionário. Uma solução possível perfaz-se pela criação de classes diferentes para o funcionário supervisionado e outra para o funcionário supervisor. Ocorre que esta não é uma solução válida. Primeiro, estamos limitando conceitualmente um objeto. Estamos definindo, implicitamente, que uma vez sendo objeto da classe FuncionarioSupervisor não será objeto da classe FuncionarioSupervisionado. Esta assunção é errônea já que é razoável cogitar que um funcionário pode ser supervisor e ser supervisionado por outro funcionário. Professor: Pablo Rangel, D.Sc. Disciplina: Modelagem de Sistemas Uma outra possibilidade para manter este modelo é criar dois objetos como instâncias se referenciando a uma mesma entidade. Se conceitualmente já era ruim, agora computacionalmente é pior. A melhor solução reside numa auto referência. Nesta abordagem, os objetos de uma mesma classe estão associados entre si e precisam comunicar-se uns com os outros. Estas associações também são chamadas de associação reflexiva ou associação unária e diferenciam pelo papel que exercem (neste exemplo supervisor e supervisionado) Discussão: é um atributo, são vários atributos ou é uma classe? Uma questão recorrente durante o processo de modelagem é a definição da informação como um atributo, vários atributos ou uma classe. Por exemplo, seja a classe Pessoa. Na primeira definição da classe o atributo endereço engloba todas as características de um endereço, tais como CEP, tipo de logradouro (rua, avenida, beco, estrada, etc.), logradouro, bairro, cidade, estado e país. Ao adotar um atributo único para representação de uma informação composta, estamos deixando a cargo da interface homemmáquina estabelecer o critério para preenchimento do endereço. As informações do endereço estarão estabelecidas de uma maneira sequencial em um único atributo e a grande vantagem desta abordagem reside no fato de ser escalável pois não entra no mérito do padrão de formação do endereço. Nos Estados Unidos, por exemplo, o padrão de formação dos endereços é diferente. Professor: Pablo Rangel, D.Sc. Disciplina: Modelagem de Sistemas Nesta abordagem, as informações do endereço estarão estabelecidas de uma maneira sequencial em um único atributo, o que pode dificultar a decomposição futura. Por exemplo, como saber quais são as pessoas que moram na cidade do Rio de Janeiro? Será necessário fazer uma análise (parser) todas as vezes que a informação necessitar ser decomposta. Uma possibilidade, então, é criar atributos separados: Fica claro que um padrão rígido de endereço perde a aplicabilidade para outros países. Contudo, a grande vantagem é que as informações estão decompostas e permitem operações de maneira mais simplificada. Utilizar um atributo composto ou decompor em vários atributos simples tem implicação direta no modelo de negócios. O sistema será (ou pretende ser) utilizado em outros países? Você muito provavelmente está inclinado a adotar o padrão flexível, pois este não limita a expansão. No entanto, lembre-se que existe um custo em relação a isso: em algum momento, o seu código e a sua interface homem-máquina terá de lidar com o parser. Não existe uma resposta definitiva. O Analista de Sistemas deverá pesar os prós e contras de cada abordagem para cada domínio de problema. Professor: Pablo Rangel, D.Sc. Disciplina: Modelagem de Sistemas Uma outra questão recorrente é: em associações um-para-um, não existe uma real necessidade de criarmos uma classe. Se uma pessoa só possui um endereço, então não é necessário criarmos uma classe chamada endereço. De forma composta ou não, o endereço pode ser um atributo da classe Pessoa, o que facilitará a implementação (menos um objeto a ser instanciado). No entanto, esta não é uma boa prática. Em razão da legibilidade, atributos compostos tem grande potencial para virarem uma classe. Fica mais simples decompormos o atributo composto em atributos simples em um classe separada para tal. Além disso, esses atributos tendem a ser mostrar com multiplicidade crescente durante o desenvolvimento do sistema. O seu cliente pode jurar de pés juntos que a pessoa cadastrada no sistema só deverá ter um endereço. No entanto, com passar do tempo, ele poderá mudar de ideia e dizer que uma pessoa tem endereço comercial e um endereço residencial (nem pense em repetir atributos...). Se você modelou desde o início como uma classe separada, isso irá significar apenas a mudança de multiplicidade e a instanciação de mais objetos. Se a abordagem tivesse sido outra, muitas outras coisas teriam de ser mudadas: a criação de uma nova classe, a remoção do atributo na classe antiga, a adequação do modelo de dados, etc. Então, mesmo que a multiplicidade seja um-para-um, analise a possibilidade de crescimento do sistema e defina se a criação de uma classe é válida. Esta discussão não é aplicável para atributos simples, pois não dá para caracterizá-los como classes. Alguns de vocês dirão que o atributo nome pode ser uma classe com dois atributos (primeiroNome, sobrenome). Forçação de barra total! Uma pessoa não tem vários nomes de registro que justifiquem uma mudança de multiplicidade. Talvez em um domínio muito específico. Mas, no caso geral, não justifica. Professor: Pablo Rangel, D.Sc. Disciplina: Modelagem de Sistemas Exercícios 1. Como os diagramas de classes podem ajudar a compreender melhor um modelo de negócios? 2. A agregação e a composição são dois tipos de relações com objetivos conceituais claros. No entanto, a agregação tem difícil compreensão prática quando comparada a uma composição. Você concorda? Apresente seus argumentos. 3. Explique de que forma a herança aumenta a riqueza semântica da descrição do domínio. 4. Dada as seguintes afirmações, faça o diagrama de classes. “Em uma fábrica, um carro é composto por exatamente cinco rodas (quatro + um estepe). Uma roda, que possui um tamanho de aro, está associada a um carro.” “Uma fábrica de carros tem um nome e um número de carros fabricados por mês. A fábrica é montadora exclusiva de uma marca de carros que possui um nome e um país sede. Uma marca de carro tem ao menos uma fábrica.” “Uma fábrica de carros tem um nome e uma cidade de fornecimento. A fábrica não é montadora exclusiva de uma marca de carros e tem uma cota de carros fabricados por mês. Uma marca de carro tem ao menos uma fábrica.” “Um pessoa é casada com no mínimo zero ou no máximo 1 pessoa.” 5. Faça o diagrama de classes de domínio do estudo de caso 1 (disponível no site). Professor: Pablo Rangel, D.Sc.