Prévia do material em texto
PROGRAMAÇÃO ORIENTADA A OBJETOS COM BANCO DE DADOS OBJETIVOS DE APRENDIZAGEM > Conceituar diagramas de classe e UML. > Construir diagramas de classe da UML. > Aplicar diagramas de classes da UML na programação orientada a objetos. Introdução A Linguagem de Modelagem Unificada (Unified Modeling Language — UML) é uma linguagem de propósito geral, que visa definir uma maneira-padrão de visualizar como um sistema é projetado, ajudando engenheiros de software, empresários e arquitetos de sistemas com processos de modelagem, projeto e análise. A UML oferece um conjunto de diagramas padronizados com os quais dados, processos e sistemas complexos podem ser facilmente organizados de maneira clara e intuitiva. Dentre eles, os diagramas de classes estão entres os mais utilizados e importantes na UML, pois geralmente servem de apoio para a maioria dos outros diagramas UML. Um diagrama de classes tem o objetivo de descrever de forma gráfica clas- ses e seus relacionamentos em uma modelagem de software, fornecendo uma abstração de alto nível sem a necessidade de examinar diretamente o código, pois os diagramas de classes correspondem às classes no código-fonte, sendo Diagramas de classe UML Rafael Albuquerque considerados os únicos diagramas que podem ser traduzidos diretamente para as linguagens orientadas a objetos. Dessa forma, os diagramas de classes são amplamente adotados durante o desenvolvimento de um sistema. Neste capítulo, você estudará os conceitos de diagramas de classe em UML, seu modo de construção e sua aplicação na programação orientada a objetos. Diagramas de classe e UML A UML é uma linguagem visual utilizada para modelar software desenvolvido seguindo o paradigma de orientação a objetos (GUEDES, 2011). Essa linguagem de modelagem visual de software foi desenvolvida com a união de esforços dos pesquisadores Grady Booch, Jim Rumbaugh e Ivar Jacobson na década de 1990, que combinaram um grupo de notações de modelagem concorrentes usadas pela indústria de software na época (PRES- SMAN, 2011). Pouco tempo depois, a UML se tornou a linguagem padrão de modelagem adotada internacionalmente pela indústria de engenharia de software. Em 1997, a UML 1.0 foi apresentada ao Object Management Group (OMG), uma associação sem fins lucrativos dedicada a manter especificações a serem utilizadas pela indústria de computadores. A UML 1.0 foi revisada, tornando-se a UML 1.1, adotada mais tarde naquele ano. O padrão atual é a UML 2.0, um padrão ISO que define 13 diferentes diagramas para uso na modelagem de software (PRESSMAN, 2011). Na Figura 1, é possível verificar a classificação dos diagramas do padrão UML 2.0. Diagramas de classe UML2 Figura 1. Classificação dos tipos de diagrama da UML. Fonte: Adaptada de Fowler (2005). Diagramas de classe UML 3 Dentre os diagramas apresentados na Figura 1, o diagrama de classes é o mais utilizado e um dos mais importantes da UML, pois, além de servir de apoio para o desenvolvimento de outros diagramas UML, define a estrutura das classes utilizadas pelo sistema, determinando os atributos e métodos que cada classe possui. Desse modo, estabelece como as classes se relacionam e trocam informações entre si (GUEDES, 2011). Para um melhor entendimento dos diagramas de classes, vamos definir o conceito de uma classe dentro do paradigma de programa- ção orientada a objetos. Classes são um conjunto de instruções para construir um tipo específico de objeto. Trata-se de um conceito básico de programação orientada a objetos, que gira em torno de entidades da vida real. Uma classe determina como um objeto se comportará e quais são suas características. Uma forma de representar as classes de um sistema é por meio do diagrama de classe. Esse tipo de diagrama define os tipos de objetos no sistema e os dife- rentes tipos de relacionamentos que existem entre eles, documentando os diferentes aspectos de um sistema (atributos, operações e restrições). Devido às características do diagrama de classe, ele é o único diagrama que pode ser mapeado diretamente para o código executável, pois fornece uma visão de como as classes do sistema irão interagir entre si. Para ilustrar os tipos de relacionamento entre classes, é necessário utilizar a multiplicidade, um elemento que indica as quantidades mínima e máxima de objetos envolvi- dos em cada extremidade do relacionamento, além de especificar o nível de dependência de um objeto para com os demais objetos envolvidos no relacionamento (GUEDES, 2011). O Quadro 1 mostra o significado de alguns dos vários valores de multiplicidade que podem ser utilizados em um rela- cionamento entre classes. Quadro 1. Exemplos de multiplicidade Multiplicidade Significado 0..1 No mínimo zero (nenhum) e no máximo um. Indica que os objetos das classes associadas não precisam obrigatoriamente estar relacionados, mas se houver relacionamento indica que apenas uma instância da classe relaciona-se com as instâncias da outra classe (ou da outra extremidade da associação, se for unária). (Continua) Diagramas de classe UML4 Multiplicidade Significado 1..1 Um e somente um. indica que apenas um objeto da classe relaciona-se com os objetos da outra classe. 0..* No mínimo nenhum e no máximo muitos. Indica que pode ou não haver instâncias da classe participando do relacionamento. * Muitos. Indica que muitos objetos da classe estão envolvidos na associação. 1..* No mínimo um e no máximo muitos. Indica que há pelo menos um objeto envolvido no relacionamento, podendo haver muitos objetos envolvidos. 3..5 No mínimo três e no máximo cinco. Estabelece que existem pelo menos três instâncias envolvidas no relacionamento, ou até quatro ou cinco, mas não mais do que isso. Fonte: Adaptado de Guedes (2011). Criação de diagramas de classe e seus relacionamentos associativos A diagramação de classes representa um dos componentes mais relevantes dentro do escopo de uma UML. Por meio dela, é possível descrever os tipos de objetos presentes no sistema e os vários tipos de relacionamentos asso- ciativos (FOWLER, 2005). De modo geral, o diagrama de classes possui duas características principais: as próprias classes e as associações existentes entre elas, que culminam na forma como as classes se relacionam (GUEDES, 2011). Um diagrama de classes possui uma estrutura visual dividida em nome da classe, atributos (características internas de uma classe, definidos por valores) e métodos (contêm as operações e comportamentos da classe, referindo-se ao que os objeto da classe podem fazer) (PRESSMAN, 2011). A Figura 2 apresenta um retrato dessas definições. A Figura 2a difere da Figura 2b pelo detalhamento dos parâmetros recebidos por cada método declarado na classe. A representação de uma classe em uma UML é feita por meio de um retângulo com seções mencionadas no alto (título, atributos e métodos). Além disso, conforme Guedes (2011), os símbolos de sustenido (#) e mais (+) à frente dos atributos e métodos representam a visibilidade desses componentes, (Continuação) Diagramas de classe UML 5 implicando em determinar quais atributos e métodos estarão disponíveis ao objeto de instância da classe. Nesse caso, o sustenido (#) representa que os atributos estão protegidos, determinando que além dos objetos da classe que detêm o atributo/método, também os objetos de suas subclasses poderão ter acesso ao mesmo. Em contrapartida, o símbolo de mais (+) determina que o atributo/método pode ser utilizado por qualquer objeto. Figura 2. Representação de uma classe, com título na região superior, atributos na região mediana e métodos na região inferior: (a) sem detalhes; (b) com detalhes. Fonte: Adaptada de Guedes (2011). Conta _ Comum Conta _ Comum # nro _ conta: long # dt _ abertura: Date # dt _ encerramento: Date # situacao: int # senha: int # saldo: double # nro _ conta: long # dt _ abertura: Date # dt _ encerramento: Date # situacao: int # senha: int # saldo: double + abrir_ Conta() : int + consultar _ Conta() : int + validar _ Senha() : int + saldo _ Conta() : double + extrato _ Conta() : string + sacar _ Valor() : int + depositar _ Valor() : int + encerrar _ Conta() : int + abrir _ Conta(int) : long + consultar _ Conta(long) : int + validar _ Senha(int) : int + saldo _ Conta() : double + extrato _ Conta(Date, Date) : String + sacar _ Valor(double) : int + depositar _ Valor(long, double) : int + encerrar _ Conta() : int No ramo de desenvolvimento de sistemas, é comum a utilização de muito mais que uma classe para compor a solução final. Nesse sentido, algumas classes podem se relacionar, como forma de aprimorar o fluxo de informações processadas pelo sistema. Em diagramas de classes, existem nove tipos de associações que podem ser usufruídas. A seguir, veremos qual é o compor- tamento de cada uma dessas associações. Associação unária Como o próprio nome sugere, é uma associação que ocorre quando há um único relacionamento de um objeto de uma classe com objetos da mesma classe. A Figura 3 apresenta esta abordagem. Perceba que existe apenas uma Diagramas de classe UML6 classe no exemplo, com o nome de Funcionario, que possui como atributo o respectivo nome. Um funcionário pode ser chefe de outros, mas também pode ser que não exista um funcionário que chefia outros, sendo representado pela cardinalidade 0..*. Logo, como forma de ilustrar essa relação entre funcionários, uma linha parte da classe Funcionario para a própria classe. Figura 3. Associação unária. Fonte: Adaptada de Guedes (2011). Funcionario chefia ∙ nome: String 0..* Associação binária As associações binárias, como visto na Figura 4, representam a relação entre dois objetos de duas classes diferentes. O que pode ser constatado na Figura 4 é que um objeto da classe Socio pode ou não ter algum dependente do objeto da classe Dependente. A seta representa a orientação em que se deve ler a relação de associação. Como a cardinalidade está na classe De- pendente, o fluxo de leitura seria que um sócio possui ou não dependentes; logo, somente um objeto da classe Socio pode disparar algum método para a classe Dependente. O contrário não seria o melhor caminho a se seguir, devido à cardinalidade anotada. Figura 4. Associação binária. Fonte: Adaptada de Guedes (2011). Socio Dependente ∙ nom _ socio: String ∙ end _ socio: String ∙ tel _ socio: String ∙ dat _ socio: Date ∙ nom _ dep: String ∙ dat _ socio: Date possui 0..* Diagramas de classe UML 7 Conforme Guedes (2011), a leitura da associação deve ser realizada da seguinte forma: uma instância da classe Socio possui no mínimo zero instância e no máximo muitas instâncias da classe Dependente; uma instância da classe Dependente é contida por apenas uma instância da classe Socio. Associação ternária ou N-ária Associações do tipo ternária possuem um caráter de associatividade em mais de dois objetos de classes, assinalada por um losango. A Figura 5 mostra que nesse caso podemos nos deparar com uma situação bastante corri- queira em escolas. Nesse exemplo, podemos tirar as seguintes conclusões: um professor pode lecionar para uma ou para muitas turmas; uma turma possui um ou muitos professores e pode ser alocada em pelo menos uma sala de aula; e uma sala de aula recebe pelo menos um professor, assim como pelo menos uma turma. Figura 5. Associação ternária. Fonte: Adaptada de Guedes (2011). Professor Turma Sala de Aula Leciona Possui 1..* 1..* 1..* Utiliza Agregação A agregação é um tipo especial de associação, em que se busca demons- trar que as informações de um objeto precisam ser complementadas com informações contidas em outro objeto. Seguindo a Figura 6, o objeto de classe Clube é denominado como “todo/parte”, enquanto o objeto de classe Diagramas de classe UML8 Pessoa é visto como a “parte”. Logo, entre os objetos associados é feito uma espécie de relação todo/parte. No exemplo da Figura 6, sempre que as informações de um clube forem consultadas, serão apresentadas todas as pessoas associadas àquele clube, e conforme a cardinalidade, vários clubes contêm várias pessoas associadas. Segundo Fowler (2005), a agregação é comumente confundida com outro tipo de associação, conhecida como composição, que veremos a seguir. Figura 6. Associação de agregação. Fonte: Fowler (2005, p. 79). Clube Pessoa membros ** Segundo Guedes (2011), principal função de uma associação do tipo agrega- ção é identificar a obrigatoriedade de uma complementação das informações de um objeto-todo por seus objetos-parte. Composição A composição apresenta um comportamento parecido com a agregação, exceto que, embora uma classe possa ser um componente de muitas outras classes, toda instância deve ser um componente de apenas um proprietário, em que os objetos-parte têm de estar associado a um único objeto-todo (FOWLER, 2005). Na composição, existe uma relação muito forte entre os objetos-todo e os objetos-parte. Na Figura 7, é possível notar que um objeto da classe Revista _ Cientifica refere-se a no mínimo um objeto da classe Edicao, e cada objeto da classe Edicao relaciona-se única e exclusivamente a uma instância específica da classe Revista _ Cientifica. Diagramas de classe UML 9 Figura 7. Associação de composição. Fonte: Adaptada de Guedes (2011). Revista _ Cientifica Edicao Artigo ∙ til _ rev: String ∙ issn _ rev: long ∙ periodicidade: String ∙ nro _ edi: int ∙ vol _ edi: int ∙ dat _ edi: Date ∙ tiragem _ edi: int ∙ tit _ art: String Contém 1..* 0..10 publica Generalização/especialização Este tipo de associação tem como objetivo apresentar a herança entre as classes, com a identificação de classes denominadas superclasses e classes que herdam características delas, chamadas por sua vez de subclasses. A subclasses podem apresentar diferenciações de comportamento em relação à superclasse, sendo mais específicas e, portanto, apresentando métodos polimórficos em suas classes. Na Figura 8, perceba que objetos das classes Conta _ Especial e Conta _ Poupanca são ambas Contas e herdam pro- priedades e métodos da classe Conta _ Comum. Assim, embora apresentem características de uma conta comum, possuem especificações que as distin- guem desse tipo de conta. Diagramas de classe UML10 Figura 8. Generalização/especialização no diagrama de classes. Fonte: Adaptada de Guedes (2011). Conta _ Comum Conta _ Especial Conta _ Poupanca # nro _ conta: long # /dt _ abertura: Date # /dt _ encerramento: Date [o..1] # situacao: int = 1 # senha: int # /saldo: double = 0 + abrir _ Conta(int): long + consultar _ Conta(long): int + validar _ Senha(int): int + saldo _ Conta(): String + extrato _ Conta(): String + sacar _ Valor(double): int + depositar _ Valor(long. double): int + encerrar _ Conta(): int + abrir _ Conta(int, double): long + sacar _ Valor(double): int + juros _ Conta(double): double ∙ limite _ conta: double ∙ dt _ aniversario: Date + renda _ Conta(Date, double): double Os tipos associativos examinados constituem os métodos mais usuais de associações para relacionamentos de objetos de classes diferentes. Na próxima seção, vamos analisar na programação como a associação pode ser implementada utilizando a linguagem de programação Java. Diagramas de classe UML 11 Além dos métodos citados, existem outros três tipos de associações (GUEDES, 2011), listados a seguir. � classe associativa —produzida quando há cardinalidades de muitos (*) em suas extremidades nos relacionamentos dos objetos; � dependência — identifica certo grau de dependência de uma classe A em relação a outra classe B, sendo representada por uma linha tracejada entre as duas classes contendo uma seta da classe A para a classe B, sendo a classe A dependente; � realização — mistura características dos relacionamentos de generalização e dependência, com o objetivo de identificar classes responsáveis por executar funções para outras classes. Diagramas de classe e código Java Associaçõesentre entidades são determinadas por uma conexão específica que determina quais objetos estão conectados e qual é o nível de relaciona- mento entre eles. Na situação específica de associação, conforme descrita na Figura 9, podemos observar que a classe do tipo Pessoas possui uma chamada à classe Carros, utilizando-se no seguinte sentido: uma pessoas pode ter no mínimo zero carro e no máximo vários carros. O contrário não acontece, pois não existe uma chamada a algum objeto Pessoa dentro da classe Carro. Figura 9. Utilização da associação em Java. Diagramas de classe UML12 A associação mostrada na Figura 9 é estabelecida de modo que não exija dependência alguma entre as entidades, igualando o nível conceitual de cada classe. No exemplo a seguir, veremos a situação de dependência entre entidades com a associação do tipo agregação, que utiliza o conceito de “todo/parte”. A Figura 10 apresenta um exemplo de modo de utilização da agregação. Perceba que o código do relacionamento de agregação é extremamente parecido com o que foi apresentado para a relação de associação. A diferença entre associação e agregação é inteiramente semântica, mantendo a sintaxe de ambos os códigos igual. Como a agregação possui uma característica unidi- recional, não é possível, por exemplo, formar ciclos dentro de um sistema mais complexo (KNOERNSCHILD, 2001). Figura 10. Utilização da agregação em Java. Uma forma especial de agregação é a composição com relacionamento caracterizado como parte-todo, com o “todo” sendo responsável pelo ciclo de vida da “parte”. Nesse sentido, a “parte” não existe sem o “todo”, e o exemplo da Figura 11 aborda exatamente isso, pois o motor é projetado como parte primordial de um automóvel, mas sem um automóvel não existiria a necessidade de um motor. Assim como na agregação, essa abordagem é puramente semântica, e na prática da codificação, não existe diferença na sintaxe tanto para associação quanto para agregação. Diagramas de classe UML 13 Figura 11. Utilização da composição em Java. Agregação e composição, que são relacionamentos de associação, não são relacionamentos nativos da orientação a objetos; por isso, sua sintaxe apresenta a mesma estrutura. São utilizados na UML para representar modelos estruturais codificados no software. Logo, ao implementar o código-fonte, para a maioria das linguagens de programação esse relacionamento é um tanto transparente, pois baseia-se apenas na utilização de um atributo na classe. Em se tratando de orientação de objetos em Java, uma característica explícita de relacionamento entre objetos de classes nessa linguagem pode ser vista na relação de herança, que, pelo diagrama de classe, é chamada de generalização. Perceba pela Figura 12 que no código ilustrado o objeto da subclasse Carro herda características e comportamentos gerais denotados à classe Automovel. Diagramas de classe UML14 Figura 12. Utilização de generalização em Java. Como podemos ver, diagramas de classes são essenciais para a elaboração de um plano de negócio de desenvolvimento, em que podemos atribuir tipos de relações a partir do seu grau de importância. Dessa forma, a diagramação de classes define importantes e imprescindíveis associações no controle do fluxo de informações que um objeto pode fornecer a outro. Referências FOWLER, M. UML Essencial: Um breve guia para linguagem-padrão de modelagem de objetos. 3. ed. Porto Alegre: Bookman, 2005. GUEDES, G. T. A. UML 2 — uma abordagem prática. 2. ed. São Paulo: Novatec, 2011. KNOERNSCHILD, K. Java Design: Objects, UML, and Process.1st ed. Boston: Addison Wesley, 2001. PRESSMAN, R. S. Engenharia de software: uma abordagem profissional 7. ed. Porto Alegre: AMGH, 2011. E-book. Leituras recomendadas FINEGAN, E. OCA Java SE 8 Programmer I: guia de estudos. 1. ed. Porto Alegre: Bookman, 2018. LARMAN, C. Utilizando UML e padrões: uma introdução à análise e ao projeto orientado a objetos e ao desenvolvimento iterativo. 3. ed. Porto Alegre: Bookman, 2007. Diagramas de classe UML 15 Os links para sites da web fornecidos neste capítulo foram todos testados, e seu funcionamento foi comprovado no momento da publicação do material. No entanto, a rede é extremamente dinâmica; suas páginas estão constantemente mudando de local e conteúdo. Assim, os editores declaram não ter qualquer responsabilidade sobre qualidade, precisão ou integralidade das informações referidas em tais links. Diagramas de classe UML16