Prévia do material em texto
Atualizado para JAVA SE 8 (JDK 8)
Java
para iniciantes
Crie, compile e execute programas Java rapidamente
Herbert Schildt
Catalogação na publicação: Poliana Sanchez de Araujo – CRB 10/2094
S334j Schildt, Herbert.
Java para iniciantes : crie, compile e execute programas
Java rapidamente [recurso eletrônico] / Herbert Schildt ;
tradução: Aldir José Coelho Corrêa da Silva ; revisão
técnica: Maria Lúcia Blanck Lisbôa. – 6. ed. – Porto Alegre :
Bookman, 2015.
Editado como livro impresso em 2015.
ISBN 978-85-8260-337-6
1. Linguagem de programação - Java. I. Título.
CDU 004.438Java
O autor
O autor de best-sellers Herbert Schildt escreve incansavelmente sobre programação
há quase três décadas e é uma das principais autoridades na linguagem Java. Seus
livros de programação venderam milhões de cópias no mundo inteiro e foram tra-
duzidos para diversos idiomas. É autor de vários livros sobre Java, incluindo Java:
The Complete Reference, Herb Schildt’s Java Programming Cookbook e Swing: A
Beginner’s Guide. Ele também escreveu sobre C, C++ e C#. Embora tenha interesse
em todas as áreas da computação, seu foco principal são as linguagens de progra-
mação, incluindo compiladores, interpretadores e linguagens de controle robótico.
Também tem grande interesse na padronização de linguagens. Schildt tem gradua-
ção e pós-graduação pela Universidade de Illinois. Seu site é www.HerbSchildt.com.
O editor técnico
Dr. Danny Coward trabalhou em todas as edições da plataforma Java. Ele conduziu
a definição dos Java Servlets para a primeira versão da plataforma Java EE e para
além dela, os serviços web para a plataforma Java ME, e a estratégia e planejamento
de Java SE 7. Fundou a tecnologia JavaFX e, mais recentemente, projetou o maior
acréscimo feito ao padrão Java EE 7, a API Java WebSocket. Da codificação em Java
ao projeto de APIs com especialistas da indústria e ao trabalho por vários anos como
executivo do Java Community Process, ele adquiriu uma perspectiva singularmente
ampla de vários aspectos da tecnologia Java. Além disso, é autor de JavaWebSo-
cket Programming e de um livro ainda a ser publicado sobre Java EE. Dr. Coward
tem graduação, mestrado e doutorado em Matemática pela Universidade de Oxford.
Capítulo 4 Introdução a classes, objetos e métodos 101
Principais habilidades e conceitos
• Saber os fundamentos da classe
• Entender como os objetos são criados
• Entender como as variáveis de referência são atribuídas
• Criar métodos, retornar valores e usar parâmetros
• Usar a palavra-chave return
• Retornar um valor de um método
• Adicionar parâmetros a um método
• Utilizar construtores
• Criar construtores parametrizados
• Entender new
• Entender a coleta de lixo e os finalizadores
• Usar a palavra-chave this
.....................................................................................................................................
Antes de poder se adiantar mais em seu estudo de Java, você precisa conhecer a classe. Classe é a essência de Java. Ela é a fundação na qual toda a linguagem
Java se estrutura, porque define a natureza de um objeto. Como tal, ela forma a base
da programação orientada a objetos em Java. Dentro de uma classe, são definidos
dados e o código que age sobre eles. O código fica contido em métodos. Já que as
classes, objetos e métodos são fundamentais para Java, eles serão introduzidos neste
capítulo. Ter um entendimento básico desses recursos permitirá que você escreva
programas mais sofisticados e compreenda melhor certos elementos-chave de Java
descritos no próximo capítulo.
Fundamentos das classes
Já que toda a atividade dos programas Java ocorre dentro de uma classe, temos usado
classes desde o início deste livro. É claro que só classes extremamente simples foram
usadas e não nos beneficiamos da maioria de seus recursos. Como você verá, elas
são significativamente mais poderosas do que as classes limitadas apresentadas até
agora.
Comecemos examinando o básico. Uma classe é um modelo que define a for-
ma de um objeto. Ela especifica tanto os dados quanto o código que operará sobre
eles. Java usa uma especificação de classe para construir objetos. Os objetos são
instâncias de uma classe. Logo, uma classe é basicamente um conjunto de planos
102 Java para Iniciantes
que especifica como construir um objeto. É importante deixar uma coisa bem clara:
uma classe é uma abstração lógica. Só quando um objeto dessa classe é criado é que
existe uma representação física dela na memória.
Outro ponto: lembre-se de que os métodos e variáveis que compõem uma clas-
se são chamados de membros da classe. Os membros de dados também são chama-
dos de variáveis de instância.
Forma geral de uma classe
Quando definimos uma classe, declaramos sua forma e natureza exatas. Fazemos
isso especificando as variáveis de instância que ela contém e os métodos que operam
sobre elas. Embora classes muito simples possam conter apenas métodos ou apenas
variáveis de instância, a maioria das classes do mundo real contém ambos.
Uma classe é criada com o uso da palavra-chave class. Uma forma geral sim-
plificada de uma definição class é mostrada aqui:
class nome da classe {
// declara variáveis de instância
tipo var1;
tipo var2;
// ...
tipo varN;
// declara métodos
tipo método1(parâmetros) {
// corpo do método
}
tipo método2(parâmetros) {
// corpo do método
}
// ...
tipo métodoN(parâmetros) {
// corpo do método
}
}
Embora não haja essa regra sintática, uma classe bem projetada deve definir
apenas uma entidade lógica. Por exemplo, normalmente, uma classe que armazena
nomes e números de telefone não armazena também informações sobre o mercado
de ações, a média pluviométrica, os ciclos das manchas solares ou outros dados não
relacionados. Ou seja, uma classe bem projetada deve agrupar informações logi-
camente conectadas. A inserção de informações não relacionadas na mesma classe
desestruturará rapidamente seu código!
Até o momento, as classes que usamos tinham apenas um método: main( ).
Você verá como criar outros em breve. No entanto, observe que a forma geral de uma
classe não especifica um método main( ). O método main( ) só é necessário quando
a classe é o ponto de partida do programa. Alguns tipos de aplicativos Java, como os
applets, também precisam de um método main( ).
Capítulo 4 Introdução a classes, objetos e métodos 103
Definindo uma classe
Para ilustrar as classes, desenvolveremos uma classe que encapsula informações so-
bre veículos, como carros, furgões e caminhões. Essa classe se chama Vehicle e con-
terá três informações sobre um veículo: o número de passageiros que ele pode levar,
a capacidade de armazenamento de combustível e o consumo médio de combustível
(em milhas por galão).
A primeira versão de Vehicle é mostrada a seguir. Ela define três variáveis de
instância: passengers, fuelcap e mpg. Observe que Vehicle não contém método.
Logo, atualmente é uma classe só de dados. (Seções subsequentes adicionarão mé-
todos a ela.)
class Vehicle {
int passengers; // número de passageiros
int fuelcap; // capacidade de armazenamento de combustível em galões
int mpg; // consumo de combustível em milhas por galão
}
Uma definição class cria um novo tipo de dado. Nesse caso, ele se chama Vehi-
cle. Você usará esse nome para declarar objetos de tipo Vehicle. Lembre-se de que
uma declaração class é só uma descrição de tipo; ela não cria um objeto real. Logo, o
código anterior não faz nenhum objeto de tipo Vehicle passar a existir.
Para criar realmente um objeto Vehicle, você usará uma instrução como a mos-
trada abaixo:
Vehicle minivan = new Vehicle(); // cria um objeto Vehicle chamado minivan
Após essa instrução ser executada, minivan será uma instância de Vehicle. Portanto,
terá realidade “física”. Por enquanto, não se preocupe com os detalhes da instrução.
Sempre que você criar uma instância de uma classe,estará criando um objeto
contendo sua própria cópia de cada variável de instância definida pela classe. Logo,
todos os objetos Vehicle conterão suas próprias cópias das variáveis de instância
passengers, fuelcap e mpg. Para acessar essas variáveis, você usará o operador pon-
to (.). O operador ponto vincula o nome de um objeto ao nome de um membro. A
forma geral do operador ponto é mostrada aqui:
objeto.membro
Portanto, o objeto é especificado à esquerda e o membro é inserido à direita. Por
exemplo, para atribuir o valor 16 à variável fuelcap de minivan, use a instrução a
seguir:
minivan.fuelcap = 16;
Em geral, podemos usar o operador ponto para acessar tanto variáveis de instância
quanto métodos.
Este é um programa completo que usa a classe Vehicle:
/* Um programa que usa a classe Vehicle.
Chame este arquivo de VehicleDemo.java
*/
class Vehicle {
104 Java para Iniciantes
int passengers; // número de passageiros
int fuelcap; // capacidade de armazenamento de combustível em galões
int mpg; // consumo de combustível em milhas por galão
}
// Essa classe declara um objeto de tipo Vehicle.
class VehicleDemo {
public static void main(String args[]) {
Vehicle minivan = new Vehicle();
int range;
// atribui valores a campos de minivan
minivan.passengers = 7;
minivan.fuelcap = 16;
minivan.mpg = 21;
// calcula a autonomia presumindo um tanque cheio de gasolina
range = minivan.fuelcap * minivan.mpg;
System.out.println("Minivan can carry " + minivan.passengers +
" with a range of " + range);
}
}
Você deve chamar o arquivo que contém o programa de VehicleDemo.java,
porque o método main( ) está na classe chamada VehicleDemo e não na classe cha-
mada Vehicle. Quando compilar esse programa, verá que dois arquivos .class foram
criados, um para Vehicle e um para VehicleDemo. O compilador Java insere auto-
maticamente cada classe em seu próprio arquivo .class. Não é necessário as classes
Vehicle e VehicleDemo estarem no mesmo arquivo-fonte. Você pode inserir cada
classe em seu próprio arquivo, chamados Vehicle.java e VehicleDemo.java, respec-
tivamente.
Para executar o programa, você deve executar VehicleDemo.java. A saída a
seguir é exibida:
Minivan can carry 7 with a range of 336
Antes de avançar, examinemos um princípio básico: cada objeto tem suas pró-
prias cópias das variáveis de instância definidas por sua classe. Logo, o conteúdo das
variáveis de um objeto pode diferir do conteúdo das variáveis de outro. Não há co-
nexão entre os dois objetos exceto pelo fato de serem do mesmo tipo. Por exemplo,
se você tiver dois objetos Vehicle, cada um terá sua própria cópia de passengers,
fuelcap e mpg, e o conteúdo dessas variáveis será diferente entre os dois objetos. O
programa abaixo demonstra esse fato. (Observe que a classe que tem main( ) agora
se chama TwoVehicles.)
// Este programa cria dois objetos Vehicle.
class Vehicle {
int passengers; // número de passageiros
int fuelcap; // capacidade de armazenamento de combustível em galões
Observe o uso do operador ponto
para o acesso a um membro.
Capítulo 4 Introdução a classes, objetos e métodos 105
int mpg; // consumo de combustível em milhas por galão
}
// Essa classe declara um objeto de tipo Vehicle.
class TwoVehicles {
public static void main(String args[]) {
Vehicle minivan = new Vehicle();
Vehicle sportscar = new Vehicle();
int range1, range2;
// atribui valores a campos de minivan
minivan.passengers = 7;
minivan.fuelcap = 16;
minivan.mpg = 21;
// atribui valores a campos de sportscar
sportscar.passengers = 2;
sportscar.fuelcap = 14;
sportscar.mpg = 12;
// calcula a autonomia presumindo um tanque cheio de gasolina
range1 = minivan.fuelcap * minivan.mpg;
range2 = sportscar.fuelcap * sportscar.mpg;
System.out.println("Minivan can carry " + minivan.passengers +
" with a range of " + range1);
System.out.println("Sportscar can carry " + sportscar.passengers +
" with a range of " + range2);
}
}
A saída produzida por esse programa é mostrada aqui:
Minivan can carry 7 with a range of 336
Sportscar can carry 2 with a range of 168
Como você pode ver, os dados de minivan são totalmente diferentes dos contidos em
sportscar. A ilustração a seguir mostra essa situação.
minivan
passengers 7
fuelcap 16
mpg 21
passengers 2
fuelcap 14
mpg 12
sportscar
Lembre-se de que minivan
e sportscar referenciam
objetos separados.
106 Java para Iniciantes
Como os objetos são criados
Nos programas anteriores, a linha abaixo foi usada para declarar um objeto de tipo
Vehicle:
Vehicle minivan = new Vehicle();
Essa declaração faz duas coisas. Em primeiro lugar, ela declara uma variável chamada
minivan da classe Vehicle. Essa variável não define um objeto. Em vez disso, ela pode
apenas referenciar um objeto. Em segundo lugar, a declaração cria uma cópia física do
objeto e atribui à minivan uma referência a ele. Isso é feito com o uso do operador new.
O operador new aloca dinamicamente (isto é, aloca no tempo de execução)
memória para um objeto e retorna uma referência a ele. Essa referência é, mais ou
menos, o endereço do objeto na memória alocado por new. A referência é então
armazenada em uma variável. Logo, em Java, todos os objetos de uma classe devem
ser alocados dinamicamente.
As duas etapas da instrução anterior podem ser reescritas desta forma para
mostrarmos cada etapa individualmente:
Vehicle minivan; // declara uma referência ao objeto
minivan = new Vehicle(); // aloca um objeto Vehicle
A primeira linha declara minivan como referência a um objeto de tipo Vehicle. Por-
tanto, minivan é uma variável que pode referenciar um objeto, mas não é um objeto.
Por enquanto, minivan não referencia um objeto. A próxima linha cria um novo ob-
jeto Vehicle e atribui à minivan uma referência a ele. Agora, minivan está vinculada
a um objeto.
Java
C A Y H O R S T M A N N
5a E
C O N C E I T O S D E
C O M P U TA Ç Ã O C O M
C
Java 5 & 6
Sobre o autor
CAY S. HORSTMANN é professor de ciência da computação no departamento de ciên-
cia da computação da Universidade Estadual de San Jose. É experiente programador,
foi vice-presidente e gerente de tecnologia da Preview Systems, Inc. Presta consultoria
em C++, Java, Windows e programação Internet para importantes corporações, univer-
sidades e organizações. Horstmann é autor de muitos livros profi ssionais e acadêmicos
bem-sucedidos, incluindo Padrões e Projetos Orientados a Objetos, Big Java, Conceitos
de Computação com o Essencial de C++ (publicados pela Bookman Editora sob esses
títulos), Big C++ e Core Java, com Gary Cornell.
H819c Horstmann, Cay.
Conceitos de computação em Java [recurso eletrônico] / Cay
Horstmann ; tradução Edson Furmankiewicz. – 5. ed. – Dados
eletrônicos – Porto Alegre : Bookman, 2009.
Editado também como livro eletrônico em 2009.
Conteúdo: Capítulos 16, 17, 18 e apêndices de D a M
disponíveis em: www.bookman.com.br.
ISBN 978-85-7780-407-8
1. Computação – Linguagem de programação. I. Título.
CDU 004.438JAVA
Catalogação na publicação: Renata de Souza Borges CRB-10/Prov-021/08
CAPÍTULO 8 � Projetando Classes 329
8.6 Métodos estáticos
Às vezes você precisa de um método que não seja invocado a partir
de um objeto. Chamamos esse método de método estático ou de
método de classe. Por outro lado, os métodos que você escreveu
até agora são freqüentemente chamados de métodos de instância porque operam em uma
instância particular de um objeto.
Um método estático não é
invocado em um objeto.
330 Conceitos de Computação com Java
Um exemplo típico de um método estático é o método sqrt da classe Math. Quando
você chama Math.sqrt(x), você não fornece nenhum parâmetro implícito. (Lembre-se de
que Math é o nome de uma classe, não de um objeto.)Por que você iria querer escrever um método que não opera em um objeto? A razão
mais comum é encapsular algum cálculo que envolve apenas números. Como números
não são objetos, você não pode invocar métodos neles. Por exemplo, a chamada x.sqrt()
nunca será válida em Java.
Eis um exemplo típico de um método estático que realiza alguns cálculos algébricos
simples: calcular a porcentagem p da quantia a. Como os parâmetros são números, o mé-
todo não opera em absolutamente nenhum objeto, portanto nós o tornamos um método
estático:
/**
Calcula uma porcentagem de uma quantia.
@param p porcentagem a aplicar
@param a quantia à qual a porcentagem é aplicada
@return p porcentagem de a
*/
public static double percentOf(double p, double a)
{
return (p / 100) * a;
}
Você precisa encontrar um local para esse método. Vamos pensar em uma nova classe
(semelhante à classe Math da biblioteca Java padrão). Como o método percentOf tem a
ver com cálculos fi nanceiros, projetaremos uma classe Financial para armazená-lo. Eis
a classe:
public class Financial
{
public static double percentOf(double p, double a)
{
return (p / 100) * a;
}
// Outros métodos fi nanceiros podem ser adicionados aqui.
}
Ao chamar um método estático, você fornece o nome da classe que contém o método
para que o compilador possa localizá-lo. Por exemplo,
double tax = Financial.percentOf(taxRate, total);
Observe que você não fornece um objeto do tipo Financial ao chamar o método.
Agora podemos dizer por que o método main é estático. Quando o programa inicia,
não há nenhum objeto. Portanto, o primeiro método no programa deve ser um método
estático.
Talvez você esteja se perguntando por que esses métodos são chamados estáticos.
O signifi cado normal da palavra estático (“permanecer fi xo em um lugar”) não parece
estar relacionado com aquilo que os métodos estáticos fazem. Na realidade, essa palavra
foi adotada por acidente. Java usa a palavra-chave static porque C++ a usa no mesmo
contexto. C++ usa static para indicar métodos de classe porque os criadores de C++ não
queriam criar uma outra palavra-chave. Alguém observou que havia uma palavra-chave
CAPÍTULO 8 � Projetando Classes 331
raramente utilizada, static, que indica algumas variáveis que permanecem em uma loca-
lização fi xa para múltiplas chamadas de método. (Java não tem esse recurso, nem precisa
dele.) Acabou-se descobrindo que a palavra-chave poderia ser reutilizada para indicar
métodos de classe sem confundir o compilador. O fato de que ela pode confundir as
pessoas aparentemente não foi uma grande preocupação. Você simplesmente tem de con-
viver com o fato de que “método estático” signifi ca “método de classe”: um método que
não opera em um objeto e que só tem parâmetros explícitos.
AUTOVERIFICAÇÃO DA APRENDIZAGEM
12. Suponha que Java não tivesse métodos estáticos. Todos os métodos da classe
Math seriam então métodos de instância. Como você calcularia a raiz quadrada
de x?
13. Harry entrega seu dever de casa, um programa que executa o jogo-da-velha. A
solução dele consiste em uma única classe com muitos métodos estáticos. Por
que isso não é uma solução orientada a objetos?
8.7 Campos estáticos
Às vezes, você precisa armazenar valores fora de um objeto específi co. Utilize campos
estáticos para esse propósito. Eis um exemplo típico. Utilizaremos uma versão da nossa
classe BankAccount em que cada objeto conta bancária tem um saldo e um número de
conta:
public class BankAccount
{
. . .
private double balance;
private int accountNumber;
}
Queremos atribuir números de conta seqüencialmente. Isto é, queremos que o construtor
de conta bancária crie a primeira conta com o número 1001, a próxima com o número
1002 e assim por diante. Portanto, devemos armazenar o último número de conta atri-
buído em algum lugar.
Não faz sentido, porém, transformar esse valor em um campo de instância:
public class BankAccount
{
. . .
private double balance;
private int accountNumber;
private int lastAssignedNumber = 1000; // NÃO – não funcionará
}
Nesse caso, cada instância da classe BankAccount teria um valor próprio de lastAssigned-
Number.
332 Conceitos de Computação com Java
Em vez disso, precisamos ter um único valor de lastAssigned-
Number que seja o mesmo para toda a classe. Esse campo é chamado
campo estático, porque você o declara utilizando a palavra-chave
static.
public class BankAccount
{
. . .
private double balance;
private int accountNumber;
private static int lastAssignedNumber = 1000;
}
Cada objeto BankAccount tem campos de instância balance e accountNumber próprios, mas
há apenas uma única cópia da variável lastAssignedNumber (veja Figura 4). Esse campo é
armazenado em um local separado, fora de qualquer objeto BankAccount.
Um campo estático às vezes é chamado campo de classe porque há um único campo
para toda a classe.
Cada método de uma classe pode acessar seus campos estáticos. Eis o construtor da
classe BankAccount, que incrementa o último número atribuído e então o usa para inicia-
lizar o número de conta do objeto a ser construído:
public class BankAccount
{
public BankAccount()
{
// Gera o próximo número de conta a ser atribuído
lastAssignedNumber++; // Atualiza o campo estático
// Atribui o campo ao número de conta dessa conta bancária
accountNumber = lastAssignedNumber; // Confi gura o campo de instância
}
. . .
}
Como você inicializa um campo estático? Você não pode confi gurá-lo no construtor da
classe:
public BankAccount()
{
lastAssignedNumber = 1000; // NÃO – seria redefi nido para 1000 a cada novo objeto
. . .
}
Assim, a inicialização ocorreria toda vez que uma nova instância fosse construída.
Há três maneiras de inicializar um campo estático:
1. Não fazer nada. O campo estático é então inicializado com 0 (para números),
false (para valores boolean) ou null (para objetos).
2. Utilizar um inicializador explícito, como:
public class BankAccount
{
. . .
private static int lastAssignedNumber = 1000;
}
Um campo estático
pertence à classe, não a um
objeto da classe.
CAPÍTULO 8 � Projetando Classes 333
A inicialização é executada depois que a classe é carregada.
3. Utilizar um bloco de inicialização estático (ver Tópico Avançado 8.3).
Como ocorre com campos de instância, campos estáticos sempre devem ser declarados
como private para assegurar que os métodos das outras classes não alterem seus valores.
A exceção a essa regra são as constantes estáticas, que podem ser privadas ou públicas.
Por exemplo, a classe BankAccount poderia defi nir o valor de uma constante pública,
como
public class BankAccount
{
. . .
public static fi nal double OVERDRAFT_FEE = 5;
}
Métodos de qualquer classe referenciam essa constante como BankAccount.OVERDRAFT_FEE.
Faz sentido declarar constantes como static – você não iria querer que cada objeto
da classe BankAccount tivesse seu próprio conjunto de variáveis com os valores dessas
constantes. É sufi ciente ter um conjunto delas para a classe.
Por que as variáveis de classe são chamadas static? Como ocorre com os métodos
estáticos, a própria palavra-chave static é simplesmente uma remanescente sem sentido
collegeFund =
balance =
accountNumber =
BankAccount
10000
1001
momsSavings =
balance =
accountNumber =
BankAccount
8000
1002
harrysChecking =
balance =
accountNumber =
BankAccount
0
1003
Cada objeto
BankAccount
tem um campo
accountNumber
próprio
BankAccount.lastAssignedNumber = 1003
Há um único campo
lastAssignedNumber
para a classe
BankAccount
Figura 4 Um campo estático e campos de instância.
334 Conceitos de Computação com Java
de C++. Mas campos estáticos e métodos estáticos têm muito em comum: eles são apli-
cados a toda a classe, não a instâncias específi cas da classe.
Em geral, é recomendável minimizar o uso dos campos e métodos estáticos. Se en-
contrar utilizandovários métodos estáticos é uma indicação de que talvez você não tenha
encontrado as classes corretas para resolver seu problema de uma maneira orientada a
objetos.
AUTOVERIFICAÇÃO DA APRENDIZAGEM
14. Cite dois campos estáticos da classe System.
15. Harry informa que encontrou uma excelente maneira de evitar esses objetos in-
cômodos: colocar todo o código em uma única classe e declarar todos os méto-
dos e campos como static. Então main pode chamar os outros métodos estáticos
e todos eles podem acessar os campos estáticos. O plano do Harry funcionará?
Ele é uma boa idéia?
Formas alternativas de inicialização de campos
O Tópico Avançado 8.3 abrange dois mecanismos menos comuns para inicialização de
campo: especifi car os valores iniciais para os campos e usar blocos de inicialização.
TÓPICO AVANÇADO 8.3
Encerra aqui o trecho do livro disponibilizado para
esta Unidade de Aprendizagem. Na Biblioteca Virtual
da Instituição, você encontra a obra na íntegra.
PARADIGMAS DE
PROGRAMAÇÃO
Fabricio Machado da Silva
Programação orientada
a objetos: modelagem
de problemas
Objetivos de aprendizagem
Ao final deste texto, você deverá apresentar os seguintes aprendizados:
� Definir programação orientada a objetos.
� Identificar as linguagens orientadas a objetos.
� Aplicar a programação orientada a objetos.
Introdução
A programação orientada a objetos (POO) surgiu como um paradigma
que apresentava uma disciplina para novos projetos de desenvolvimento
de software. Etapas com análise e projeto de software que, em outros
paradigmas, acabavam sendo minimizados na POO, se tornam requisitos
fundamentais.
Não é difícil imaginar que a POO acabou se tornando um padrão con-
sumido pela engenharia de software e que possibilitou avanços significati-
vos na programação de computadores. Seu uso permitiu que reutilização
de código se tornasse algo praticamente comum em desenvolvimento
de software, servindo como base para novos conceitos, como os serviços.
Neste capítulo, você entenderá o conceito de POO, conhecerá al-
gumas linguagens que implementam esse paradigma e exemplos de
aplicação em projetos de programas de computador.
Programação orientada a objetos
O conceito de POO tem suas raízes na linguagem de programação Simula 67,
criada por Alan Kay, o precursor dos conceitos desse paradigma de programa-
ção. Contudo, sua grande evolução foi totalmente alcançada com a chegada
da linguagem de programação Smalltalk 80:
De fato, algumas pessoas consideram Smalltalk o modelo base para uma
linguagem de programação puramente orientada a objetos. Uma linguagem
orientada a objetos deve fornecer suporte para três recursos chave de lingua-
gem: tipos de dados abstratos, herança e vinculação dinâmica de chamadas
a métodos (SEBESTA, 2018, p. 547).
Linguagens que suportam a POO são, atualmente, muito usadas. Algumas
das linguagens de programação mais novas, projetadas para a POO, não
implementam mais conceitos de linguagens procedurais como as primei-
ras implementavam. Porém, ainda assim, empregam estruturas básicas da
programação estruturada e são imperativas, como as linguagens Java e C#,
atualmente muito utilizadas e consideradas exemplos de sucesso de POO.
Smalltalk 80 foi primeira linguagem a implementar completamente os
conceitos da POO, pois, em 1980, mesmo com a evolução dos módulos e pacotes
pelas linguagens de programação da época, os problemas ainda persistiam. Um
dos maiores problemas com os recursos atuais era que não existia mecanismo
para inicialização e finalização automática do tipo fornecido. Segundo Tucker
e Noonan (2009, p. 307) “As inicializações normalmente necessárias incluem
abertura de um arquivo, alocação de memória e inicialização de variáveis locais
ao módulo”. Já quanto às finalizações, incluem o fechamento de arquivos e
a liberação de memória.
Além disso, alguns programadores e projetistas começaram a perceber
que algumas necessidades não eram atendidas com as atuais linguagens de
programação imperativa de decomposição funcional e abstração de dados,
como os padrões de graphical user interfaces (GUI), que poderiam ser melhor
implementadas com o conceito de objetos que pudessem trocar mensagens
uns com os outros. Uma GUI poderia ser mais facilmente implementada se
considerarmos, por exemplo, que seus componentes (botões, áreas de texto,
imagens etc.) são tratados como objetos que podem interagir entre si e com
o usuário do sistema.
Programação orientada a objetos: modelagem de problemas2
Assim, a POO surge como um paradigma centrado no desenvolvimento
de objetos, no lugar da atual decomposição funcional e abstração de dados.
Na Figura 1, você pode perceber um pouco dessa diferença entre a atual
programação estruturada e o conceito de objetos.
Figura 1. Comparativo entre programação estruturada e objetos.
Fonte: Adaptada de Gasparotto (2014).
...
...
...
...
...
Dados
globais
Programação estruturada
Procedimento
Procedimento
Procedimento
Procedimento
Procedimento
Dados objeto
Dados objeto
Dados objeto
POO
Método
Método
Método
Método
Método
Método
Em uma linguagem de POO, o encapsulamento dos tipos de dados e suas
funções é alcançado por meio da implementação das classes. Uma classe é
uma declaração de um tipo de objeto que encapsula os seus tipos de dados
pelos seus atributos e funções por meio de seus métodos. É comum ouvir falar
que uma classe serve como uma matriz de objetos, pois, ao determinar os seus
atributos e métodos, serve como um modelo para que diversas instâncias de
um objeto sejam criadas a partir de sua estrutura.
Ao analisar a Figura 1, você pode perceber que um programa em progra-
mação estrutural possui um desempenho melhor que um mesmo programa
em POO, e isso ocorre pelo fato de, na programação estruturada, um código
ser executado após o outro sequencialmente, ao passo que na POO são ne-
cessários alguns desvios. Entretanto, a POO traz outros pontos que acabam
sendo mais interessantes no contexto de aplicações modernas. Como, na
maioria das aplicações, o desempenho das aplicações não é uma das grandes
preocupações (devido ao poder de processamento dos computadores atuais),
a POO se tornou muito difundida.
3Programação orientada a objetos: modelagem de problemas
Na próxima seção, vamos abordar como as linguagens Java, C# e Python
implementam os conceitos da POO. Essas linguagens serão exemplos por serem
muito utilizadas atualmente no contexto de desenvolvimento de software.
Linguagens orientadas a objetos
Agora, você entenderá um pouco sobre as linguagens Java, C# e Python,
atualmente muito utilizadas e que implementam os conceitos da POO.
Java é uma linguagem de programação que foi desenvolvida pela Sun
Microsystems no início da década de 1990. Ela se tornou um símbolo da POO,
inclusive causando certa confusão, por julgarem que a POO era um paradigma
de Java e não ao contrário (MACHADO; FRANCO; BERTAGNOLLI, 2016,
p. 54).
De fato, a característica mais marcante da linguagem de programação
Java está relacionada a sua portabilidade, pois os sistemas construídos não
são compilados em código nativo da plataforma. Programas em Java são
compilados para um bytecode, que é executado por uma máquina virtual, a
Java virtual machine, que permite que os programas escritos em Java possam
ser rodados em qualquer plataforma compatível com a sua máquina virtual.
Em Java, todo o programa usa classes e objetos, e é fundamental que o
programador compreenda esses conceitos da POO para conseguir programar
em Java. Os programas são escritos em pequenos pedaços separados, chamados
de objetos. Segundo Machado, Franco e Bertagnolli (2016, p. 78), “Objetos
são pequenos programas que guardam dentro de si os dados — em suma, as
variáveis — que precisam para executar suas tarefas”. Os objetos também
trazem em si, como sub-rotinas, as instruções para processar esses dados.
As variáveis que um objeto guarda são chamadas de atributos, e as suas sub-
-rotinassão chamadas de métodos.
Programação orientada a objetos: modelagem de problemas4
Veja o exemplo de uma classe Cachorro em Java com os atributos nome,
peso, altura e cor e o método pular().
public class Cachorro{
public String nome;
public float peso;
public float altura;
public String cor;
void pular{
if(altura>=80){
System.out.println("Seu Cachorro pula alto");
}
}
}
Como você pode observar, a programação em Java é praticamente regrada
pelos conceitos de POO, e as classes são a base de qualquer código Java.
Qualquer análise para um novo programa em Java deve partir do entendimento
do seu contexto e projeção das classes.
Agora, vamos analisar a linguagem C#. A linguagem C# (lê-se C Sharp)
é definida pela Microsoft, que a desenvolve como uma linguagem de POO
que faz parte de sua plataforma de desenvolvimento .NET. Embora a lingua-
gem C# tenha sido criada totalmente do zero pela Microsoft, foi baseada na
linguagem C++, e possui muitos elementos das linguagens Java e Pascal.
A plataforma .NET na qual teve seu desenvolvimento inicial, apresentou
algumas limitações que motivaram que, em 1999, fosse montada uma força
tarefa para o desenvolvimento de uma nova linguagem para essa plataforma.
Segundo Ledur (2018, p. 108):
A criação da linguagem C# ajudou muito no desenvolvimento do .NET, pois
a plataforma não precisou se adequar a nenhum código de alguma linguagem
já existente. O C# foi criado especificamente para .NET, sendo que muitas
outras linguagens têm suporte à C#.
5Programação orientada a objetos: modelagem de problemas
Os principais objetivos do projeto da linguagem C# são:
� Ser simples moderna e de propósito geral OO.
� Ter uma linguagem e suas implementações que forneçam suporte para
princípios de engenharia de software.
� Ser destinada à utilização no desenvolvimento de componentes de
software.
� Possibilitar a portabilidade dos programas escritos em C#, assim como
é possível na linguagem Java.
� Fornecer suporte para a escrita de programa, tanto hospedados local-
mente como incorporados.
A Figura 2 mostra um exemplo da estrutura de uma classe em C#.
Figura 2. Exemplo da estrutura de uma classe em C#.
Fonte: Rodrigues (2017, documento on-line).
Você pode perceber que, assim como em Java, C# possui uma estrutura
semelhante com a declaração dos atributos da classe logo no início e depois em
seus métodos, além de uma semelhança na sintaxe entre as duas linguagens,
o que é explicado devido ao embasamento do C# na linguagem Java.
Programação orientada a objetos: modelagem de problemas6
Para finalizar esta seção, vamos abordar a POO na linguagem de progra-
mação Python, que é uma linguagem de programação bastante utilizada por
sua facilidade de aprendizado, aliada as suas características de programação
de alto nível, de script, imperativa, OO e interpretada.
Python é uma linguagem que permite o desenvolvimento tanto no conceito
de programação estruturada como a POO. Possui suporte a tipificação dinâ-
mica, recursos de gerenciamento de uso de memória, além de oferecer uma
abrangente biblioteca padrão. Os interpretadores Python possuem suporte
para diversos sistemas operacionais, possibilitando a adaptação dos sistemas
construídos.
A origem do nome Python, apesar de confundido com o animal cobra,
na realidade é oriunda do grupo de comédia britânico que era assistido pelo
criador da linguagem, chamado Monty Python, formado por Graham Cha-
pman, John Cleese, Eric Idle, Michael Palin, Terry Jones e Terry Gilliam.
Carinhosamente, são chamados de Pythonistas os programadores Python,
e as referências aos trabalhos do grupo de comédia estão espalhadas pelos
tutoriais e sua documentação (LUTZ; ASCHER, 2007).
Python é uma linguagem muito simples, fácil de usar e aprender, apesar
disso, também é uma linguagem extremamente robusta e utilizada nas mais
diversas soluções:
� back-end de sistemas Web, customer relationship management (CRM),
ou gerenciamento de relacionamento com o cliente;
� pesadas simulações de engenharia;
� processamento pesado de efeitos especiais de filmes;
� soluções de análise de dados (data analytics);
� aprendizado de máquina, do inglês machine learning (ML).
Veja o exemplo de uma classe Pessoa em Python.
class Pessoa:
def _ init _ (self, nome, idade):
self.nome = nome
self.idade = idade
def setNome(self, nome):
self.nome = nome
7Programação orientada a objetos: modelagem de problemas
def setIdade(self, idade):
self.idade = idade
def getNome(self):
return self.nome
def getIdade(self):
return self.idade
Apesar da sintaxe do Python ser um pouco diferente da sintaxe de Java e
C#, é possível verificar a estrutura da classe com a definição de atributos e
métodos e que Python é outro exemplar de linguagem OO. Na próxima seção,
você verá alguns exemplos da aplicação da programação OO em classes de
exemplos, para fixar o entendimento.
Desenvolvendo com programação
orientada a objetos
Para ajudar a elucidar o conceito de POO, vamos começar analisando a se-
guinte situação: um exemplo em Java que demonstra a criação da classe
Pessoa com os atributos nome, dataNascimento e CPF; e o método
tirarCopias, que calcula o custo da geração de cópias em um sistema de
gestão de impressões de uma escola. Esse sistema deve calcular o valor da
cópia embasado na seguinte regra:
� para alunos da escola, o valor unitário da cópia será de R$ 0,07;
� para os demais usuários, o valor unitário será de R$ 0,10.
A diferença é que este requisito será implementado com os seguintes
conceitos da POO:
� classes;
� heranças.
Programação orientada a objetos: modelagem de problemas8
Observe na Figura 3, onde consta a classe Pessoa.
Figura 3. Classe Pessoa em Java.
Fonte: Geovane (2012, documento on-line).
Na classe Pessoa podemos observar os seguintes atributos:
� nome;
� cpf;
� data_nascimento.
Observamos, também, que essa classe possui o método tirarCopias,
que faz o cálculo do valor da cópia para pessoas em geral, ou seja, pessoas
que não são alunos. Porém, você pode estar se perguntando, onde estão os
dados do aluno e o método que faz o cálculo do valor da cópia quando se
trata de um aluno?
Esses dados estão na classe Aluno, mas, como o Aluno também é uma
pessoa e tem alguns atributos que são comuns as demais pessoas, não vamos
repetir na classe Aluno. A Figura 4 mostra como ficaria a classe Alunos
em Java.
9Programação orientada a objetos: modelagem de problemas
Figura 4. Classe Alunos em Java.
Fonte: Geovane (2012, documento on-line).
É possível, portanto, observar que no início da classe Aluno existe a
declaração extends. Essa declaração significa que a classe Aluno está
dizendo que herda a classe Pessoa, dessa forma, os atributos que são comuns
à classe Pessoa não necessitam ser repetidos. Além disso, percebe-se que a
classe Aluno possui o atributo matrícula, que é específico do Aluno.
Por fim, veja que, na classe Aluno, o método tirarCopias é alterado
de acordo com o valor específico para os Alunos, o que é possível em razão
de um outro recurso de POO: o polimorfismo. Polimorfismo é um recurso que
permite ao objeto ter um comportamento diferente, dependendo da situação.
Nesse caso, o cálculo do valor da cópia se altera por conta da situação de
desconto de aluno.
Pelos exemplos apresentados, percebe-se na prática alguns recursos e usos
da programação OO e seus benefícios para a programação, possibilitando,
principalmente, a reutilização do código.
Conceitos como os observados nos exemplos das Figuras 3 e 4 são casos
comuns em POO, por isso é importante todo programador conseguir abstrair
classes com seus atributos e métodos separados e, quando utilizar conceitos
bases da POO, como herança de classes, evitar reutilização de código.
Programação orientada a objetos: modelagem de problemas10
GASPAROTTO, H. M. Os 4 pilares da ProgramaçãoOrientada a Objetos. DevMedia,
Rio de Janeiro, 2014. Disponível em: https://www.devmedia.com.br/os-4-pilares-da-
-programacao-orientada-a-objetos/9264. Acesso em: 15 set. 2019.
GEOVANE, H. Entendendo e Aplicando Herança em Java. DevMedia, Rio de Janeiro, 2012.
Disponível em: https://www.devmedia.com.br/entendendo-e-aplicando-heranca-em-
-java/24544. Acesso em: 15 set. 2019.
LEDUR, C. L. Desenvolvimento de sistemas com C#. Porto Alegre: SAGAH, 2018. 268 p.
LUTZ, M.; ASCHER, D. Aprendendo Python. 2. ed. Porto Alegre: Bookman; O’Reilly, 2007.
566 p.
MACHADO, R. P.; FRANCO, M. H. I.; BERTAGNOLLI, S. C. Desenvolvimento de software III:
programação de sistemas web orientada a objetos em Java. Porto Alegre: Bookman,
2016. 220 p. (Série Tekne; Eixo Informação e Comunicação).
RODRIGUES, J. Como criar minha primeira classe em C#. DevMedia, Rio de Janeiro, 2017.
Disponível em: https://www.devmedia.com.br/como-criar-minha-primeira-classe-em-
-csharp/38785. Acesso em: 15 set. 2019.
SEBESTA, R. W. Conceitos de linguagem de programação. 11. ed. Porto Alegre: Bookman,
2018. 758 p.
TUCKER, A. B.; NOONAN, R. E. Linguagens de programação: princípios e paradigmas. 2.
ed. Porto Alegre: AMGH, 2009. 630 p.
Leituras recomendadas
EDELWEISS, N.; LIVI, M. A. C. Algoritmos e programação: com exemplos em Pascal e C.
Porto Alegre: Bookman, 2014. 476 p. (Série Livros Didáticos Informática UFRGS).
MILETTO, E. M.; BERTAGNOLLI, S. C. Desenvolvimento de software II: introdução ao de-
senvolvimento web com HTML, CSS, JavaScript e PHP. Porto Alegre: Bookman, 2014.
276 p. (Série Tekne; Eixo Informação e Comunicação).
NICOLETTI, M. C. A cartilha Prolog. São Carlos: Edufscar, 2003. 124 p. (Série Apontamentos).
OKUYAMA, F. Y.; MILETTO, E. M.; NICOLAO, M. Desenvolvimento de software I: conceitos bá-
sicos. Porto Alegre: Bookman, 2014. 236 p. (Série Tekne; Eixo Informação e Comunicação).
PINHEIRO, F. A. C. Elementos de programação em C: em conformidade com o padrão
ISO / IEC 9899. Porto Alegre: Bookman, 2012. 548 p.
11Programação orientada a objetos: modelagem de problemas
PARADIGMAS DE
PROGRAMAÇÃO
Fabricio Machado da Silva
Programação orientada
a objetos: interfaces
e classes abstratas
Objetivos de aprendizagem
Ao final deste texto, você deverá apresentar os seguintes aprendizados:
� Definir o que são interfaces.
� Identificar classes abstratas.
� Aplicar interfaces e classes abstratas em programação orientada a
objetos.
Introdução
O conceito de herança é fundamento básico em orientação a objetos,
sendo praticamente impossível dissociar orientação a objetos e reuso de
código do conceito de herança entre classes. A necessidade da herança
entre classes trouxe outras necessidades que poderiam facilitar o trabalho
de programadores em linguagens orientadas a objetos.
Criar um padrão que fosse utilizado e seguido pelas classes que her-
dam outra classe ou, então, garantir a implementação de determinados
métodos por classes que fazem parte de um determinado contexto, são
possibilidades alcançadas devido à utilização dos conceitos de classes
abstratas e interfaces.
Neste capítulo, abordaremos as interfaces no contexto de orientação
a objetos. Além disso, aprenderemos a identificar classes abstratas e
veremos algumas aplicações práticas.
Interfaces na programação orientada a objetos
As interfaces definem uma linha entre a especificação do que uma abstração
realiza e a implementação do modo como será realizada. Uma interface se
caracteriza por ser uma coleção de operações utilizadas para especificar uma
espécie de “contrato” com a classe que irá implementá-la.
Segundo Booch, Rumbaugh e Jacobson (2006, p. 156), “uma interface
é uma coleção de operações empregadas para especificar o serviço de uma
classe ou componente”. Ao realizarmos a declaração de uma interface em
uma linguagem de programação orientada a objetos, estamos estabelecendo
o comportamento esperado de uma classe independente que implemente esta
interface, garantindo que todos os métodos que foram definidos na interface
sejam obrigatoriamente implementados por esta classe.
Algumas linguagens de programação, como C#, Java e Python, têm suporte
para o conceito de interfaces, que são importantes não apenas por dividir a
especificação e a implementação de uma classe ou componente; à medida
que desenvolvermos sistemas de maior porte, as interfaces serão úteis para
especificar a visão externa de um pacote ou subsistema, por exemplo.
Uma interface pode ser descrita como uma classe estereotipada para expor
suas operações e outras propriedades. Para mostrar o relacionamento entre
uma classe e suas interfaces é fornecida uma notação especial (LIMA, 2014).
A Figura 1 mostra um exemplo de uma classe interface que representa o tipo
Pessoa e os métodos necessários para que classes no contexto de um sistema
de gestão de documentos implementem para diferentes tipos de pessoas que
acessam a plataforma.
Figura 1. Representação de interface em programação orientada a objetos.
<<interface>>
Pessoa
adicionar()
excluir()
pesquisar()
Programação orientada a objetos: interfaces e classes abstratas2
Para fazer uma analogia, podemos dizer que, quando uma classe implementa
uma interface, a classe “assina um contrato” com esta, se comprometendo,
assim, a implementar seus métodos. Em troca, os objetos instanciados a partir
dessa classe podem ser classificados como do tipo definido pela interface.
Uma característica interessante do uso de interfaces em programação
orientada a objetos é que uma classe pode implementar várias interfaces e,
assim, em algumas linguagens em que o conceito de herança múltipla não
existe, possibilita que este seja de certa forma alcançado.
Interfaces não podem implementar nenhum método, elas apenas definem
os métodos e suas assinaturas. A implementação destes é responsabilidade
das classes que a implementam ou “assinam contrato” com esta. Isso permite
que você obedeça a alguns dos princípios de reuso e escreva códigos pouco
acoplados e com alta coesão (DEITEL; DEITEL, 2010).
Interfaces são ferramentas importantes em linguagens de programação
orientada a objetos, melhorando a qualidade de seu código quando bem uti-
lizadas. Permitem um encapsulamento de comportamento, ocultando qual
classe está realizando uma tarefa específica, e isto só é possível porque a
classe que implementa uma interface é obrigada a seguir o protocolo definido
nesta. Dessa forma, as principais vantagens de seu uso são uma manutenção
mais simples do código e um maior reuso deste, aproveitando os benefícios
da programação orientada a objetos da melhor forma.
O desenvolvimento do código voltado para interfaces se deu a partir da necessidade de
se organizar as classes de forma mais coesa, com baixo acoplamento e funcionalidades
bem encapsuladas (fundamentos da orientação a objeto).
Se o programador implementa uma interface em uma classe e deixar de
especificar um método desta, um erro será gerado. Dessa forma, a utilização
de interfaces traz um grande benefício em casos em que é necessária a garantia
de que os métodos serão implementados.
3Programação orientada a objetos: interfaces e classes abstratas
Contudo, outro recurso utilizado em programação orientada a objetos
que, muitas vezes, gera certa confusão com o conceito de interfaces, são as
classes abstratas. Classes abstratas também são utilizadas para resolver ques-
tões em que é necessária a implementação de métodos por classes herdeiras.
No entanto, estas classes possuem diferenças em relação às interfaces. Na
próxima seção, iremos definir o que são classes abstratas no conceito de
programação orientada a objetos.
Classes abstratas
Ao criarmos uma classe, na maioria das vezes o fazemos para atender a um
determinado propósito, sem nos preocuparmos se a classe poderá ser herdada
por outras. No entanto, em alguns casos, ao criarmos uma classe já temos ideia
de que esta poderá ser herdada por outras, ouseja, já temos a certeza prévia
da necessidade de herança.
Nesse conceito, a criação de classes abstratas faz sentido, pois estas são
utilizadas para definir um tipo que será seguido pelas classes herdeiras.
Às vezes é útil declarar classes — chamadas classes abstratas — para as
quais você nunca pretende criar objetos. Como elas são usadas somente como
superclasses em hierarquias de herança, são chamadas superclasses abstratas.
Essas classes não podem ser usadas para instanciar objetos, pois são incom-
pletas. Suas subclasses devem declarar as partes ausentes para se tornarem
classes concretas, a partir das quais você pode instanciar objetos (DEITEL;
DEITEL, 2010, p. 309).
As classes que não são abstratas e herdam classes abstratas são denominadas
classes concretas. Sobre as classes abstratas, podemos destacar os seguintes
conceitos.
� Uma classe abstrata serve como modelo para uma classe concreta.
� Como são apenas modelos, não podem ser instanciadas diretamente.
� Por não ser instanciadas, devem ser herdadas por classes concretas.
� Uma classe abstrata pode, ou não, conter métodos abstratos, ou seja,
pode ou não implementar um método.
� Contudo, métodos abstratos definidos em uma classe abstrata devem,
obrigatoriamente, ser implementados em uma classe concreta.
Programação orientada a objetos: interfaces e classes abstratas4
De acordo com Lima (2014, p. 334),
[...] as classes abstratas não podem ser utilizadas nas expressões de instanciação
de classes. Apesar de não poderem participar em expressões de instanciação,
as classes abstratas podem definir construtores. Os construtores de classes
abstratas são responsáveis pelas iniciações que podem ser necessárias para
os campos que podem ser utilizados nas implementações dos métodos. Assim
uma subclasse direta ou indireta de uma classe abstrata ao ser instanciada
pode causar a execução de um construtor da classe abstrata.
A Figura 2 ilustra o exemplo de uma classe abstrata chamada BombaDe-
Succao, com a definição do método abstrato ativa e a herança pelas classes
BombaDiesel e BombaDAgua com a redefinição do método abstrato.
A forma de ligar uma bomba de sucção a diesel é bem diferente da forma
como se liga uma bomba de sucção de água.
Figura 2. Representação de uma classe abstrata.
Fonte: Dias (2007, p. 2).
BombaDeSuccao
BombaDiesel BombaDAgua
redefinição redefinição
As classes abstratas possuem similaridades com as interfaces, pois também
são utilizadas como uma espécie de “contrato” a ser implementado pelas
classes herdeiras. Todavia, é importante saber diferenciar que uma classe
abstrata, como o nome sugere, se trata de uma classe, e as interfaces são
consideradas entidades.
5Programação orientada a objetos: interfaces e classes abstratas
Classes abstratas também podem possuir outros métodos que não são
abstratos e, nesse caso, não é obrigatória sua implementação pelas classes
herdeiras. Uma classe abstrata pode ter métodos não abstratos e atributos não
estáticos, o que não pode ser feito com uma interface. Portanto, com uma classe
abstrata você pode criar todo o algoritmo da classe e deixar somente um ou
mais métodos específicos para ser implementados nas subclasses (BOOCH;
RUMBAUGH; JACOBSON, 2006). Contudo, a principal diferença é que uma
classe abstrata é uma classe como outra qualquer e, sendo assim, participa de
uma hierarquia de classes. Dessa forma, uma subclasse de uma classe abstrata
só pode estender essa classe abstrata, não podendo estender duas classes, por
exemplo, enquanto no caso das interfaces podem ser implementadas quantas
forem preciso, já que estas não participam da hierarquia de classes.
As classes abstratas podem não ter todos os seus métodos declarados como
métodos abstratos, mas uma classe, para ser considerada abstrata, necessita
ter pelo menos um método em seu escopo declarado como método abstrato.
Para entender melhor esse conceito, imaginemos uma conta bancária e que
toda a classe que representa esta conta deve ter uma forma de sacar. No entanto,
dependendo do tipo de conta do cliente, pode ser necessária a implementação
de diferentes formas de sacar.
Por exemplo, um cliente que possui uma conta especial pode realizar
saques acima do saldo disponível em sua conta, enquanto um cliente comum
não tem esse direito. Nesse contexto, podemos definir, na classe Conta, um
método abstrato sacar. Assim, toda classe que herdar de Conta deverá
sobrescrever (lembra-se do conceito de polimorfismo dinâmico) esse método,
implementando suas próprias regras de saque.
Na classe Conta, o método sacar seria definido somente com a assinatura,
sem corpo, conforme o exemplo a seguir, escrito em Java:
public abstract boolean sacar (double valor);
Esse método não define como o saque será executado, apenas pela decla-
ração de abstract, que obriga que todas as classes que herdam de Conta
implementem esse método. A Figura 3 ilustra o modelo de classes que repre-
sentam a herança da classe abstrata Conta.
Programação orientada a objetos: interfaces e classes abstratas6
Figura 3. Modelo de classes do exemplo Conta.
Conta
sacar(valor)
ContaEspecial
sacar(valor)
ContaPoupança
sacar(valor)
Uma classe abstrata é um conjunto de informações a respeito de uma coleção de
outras classes. Sozinha, ela não tem utilidade, já que não podemos instanciar um objeto
desta classe, apenas instanciar objetos de classes que estendem a classe abstrata inicial.
Ela serve somente para simplificar o sistema, juntando, em um único lugar, diversas
características que são comuns a um grupo de classes.
Portanto, como visto, jamais será possível criarmos um objeto a partir de
uma classe abstrata, pois se faz necessário a herança dessa classe por uma
classe concreta e os objetos devem ser instanciados somente a partir da classe
concreta. As classes abstratas são recursos valiosos quando não é possível
utilizar interfaces em razão de que nem todos os métodos serão implemen-
tados. Dessa forma, é possível que os métodos genéricos, aqueles que terão
um comportamento igual em todas as classes herdeiras, sejam definidos na
classe abstrata. Aqueles que podem sofrer comportamentos específicos ficam
por conta de implementações em classes herdeiras. Essa é a questão que deve
ser considerada ao se tomar a decisão de utilizar uma classe abstrata ou optar
por outro recuso. Na próxima seção, veremos alguns exemplos de aplicação
de classes abstratas e interfaces em programação orientada a objetos.
7Programação orientada a objetos: interfaces e classes abstratas
Aplicação de interfaces e classes abstratas
Nas seções anteriores, abordamos os conceitos de interface e classes abstratas
em programação orientada a objetos. Nesta seção, veremos, a aplicação prática
dos conceitos explorados neste capítulo, utilizando um exemplo criado em
outra linguagem de programação, C#.
Primeiramente, vamos criar uma classe abstrata Forma, com a criação
de um método abstrato chamado CalcularArea e mais dois métodos, que
não são declarados como abstratos.
public abstract class Forma
{
private double _ area;
public double Area
{
get
{
return _ area;
}
set
{
_ area = value;
}
}
public abstract void CalcularArea();
public string Descricao()
{
return "Sou a classe abstrata Forma.";
}
}
Agora, vamos criar a classe Quadrado, que herda a classe abstrata Forma.
Na sintaxe de C#, a herança é representada pelo nome da subclasse, seguido
por : e o nome da superclasse. Observe, no trecho de código a seguir, que
o método abstrato calcularArea é definido nesta classe. Isso ocorre em
C# pela declaração do comando override, que significa que o método
sobrescreve o método abstrato herdado.
Programação orientada a objetos: interfaces e classes abstratas8
public class Quadrado : Forma
{
private double lado;
public double Lado
{get
{
return lado;
}
set
{
lado = value;
}
}
public override void CalcularArea()
{
this.Area = lado * lado;
}
}
Agora, verificamos a declaração de duas interfaces em C#. A primeira é a
interface IAcao, que define que as classes que vão implementar essa interface
devem definir o método Desenhar, e a segunda interface é IAcabamento,
que define que as classes que a implementam necessitam definir o método
Pintar.
public interface IAcao
{
void Desenhar();
}
public interface IAcabamento
{
void Pintar();
}
9Programação orientada a objetos: interfaces e classes abstratas
Na sequência, vamos criar a classe ExemploInterface, que irá imple-
mentar as interfaces IAcao e IAcabamento. Perceba que a sintaxe em C#
é igual a de herança que utilizamos no exemplo anterior de classe abstrata.
No entanto, com interfaces é possível implementar mais de uma interface,
como no exemplo a seguir.
public class ExemploInterface : IAcao, IAcabamento
{
public void Desenhar()
{
Console.WriteLine("Implementação do metodo Desenhar
da interface Acao");
}
public void Pintar()
{
Console.WriteLine("Implementação do metodo Pintar da
interface Acabamento");
}
}
Com esses exemplos simples aplicamos, de forma didática, os conceitos
de herança de classe abstrata e a definição e a implementação de interfaces.
A sintaxe dos comandos pode variar conforme a linguagem de programação
utilizada, como vimos entre os exemplos acima, em C#, e alguns exemplos
anteriores que utilizavam a linguagem Java. O importante é perceber que
as características para cada conceito, conforme mencionado, se mantém.
Classes abstratas e interfaces são conceitos essenciais para quem trabalha
com linguagens de programação orientada a objetos.
O link a seguir mostra exemplos de polimorfismo, classes abstratas e interfaces, fun-
damentos da programação orientada a objetos em Java.
https://qrgo.page.link/X5z9a
Programação orientada a objetos: interfaces e classes abstratas10
BOOCH, G.; RUMBAUGH, J.; JACOBSON, I. UML: guia do usuário. 2. ed. Rio de Janeiro:
Elsevier; Campus, 2006. 474 p.
DEITEL, P.; DEITEL, H. Java: como programar. 8. ed. São Paulo: Pearson, 2010. 1144 p.
DIAS, Z. Classes Abstratas. Campinas: Instituto de Computação, Universidade Estadual
de Campinas, 2007. 17 p. (Notas de aula da disciplina MC336/MC346 – Paradigmas de
Programação). Disponível em: http://www.ic.unicamp.br/~zanoni/mc336/2012-2s/java/
Transparencias/1%20por%20pagina/cap04-4.pdf. Acesso em: 5 out. 2019.
LIMA, A. S. UML 2.5: do requisito à solução. São Paulo: Érica, 2014. 368 p.
Leituras recomendadas
LEDUR, C. L. Desenvolvimento de sistemas com C#. Porto Alegre: SAGAH, 2018. 268 p.
MACHADO, R. P.; FRANCO, M. H. I.; BERTAGNOLLI, S. C. Desenvolvimento de software III:
programação de sistemas web orientada a objetos em Java. Porto Alegre: Bookman,
2016. 220 p. (Série Tekne; Eixo Informação e Comunicação).
OKUYAMA, F. Y.; MILETTO, E. M.; NICOLAO, M. Desenvolvimento de software I: conceitos bá-
sicos. Porto Alegre: Bookman, 2014. 236 p. (Série Tekne; Eixo Informação e Comunicação).
SEBESTA, R. W. Conceitos de linguagem de programação. 11. ed. Porto Alegre: Bookman,
2018. 758 p.
11Programação orientada a objetos: interfaces e classes abstratas
PARADIGMAS DE
PROGRAMAÇÃO
Fabricio Machado da Silva
Programação orientada
a objetos: herança
e polimorfismo
Objetivos de aprendizagem
Ao final deste texto, você deverá apresentar os seguintes aprendizados:
� Especificar a herança na orientação a objetos.
� Discutir o polimorfismo na orientação a objetos.
� Aplicar a herança e o polimorfismo.
Introdução
O paradigma da programação orientada a objetos surgiu com o intuito
de aplicar conceitos da realidade ao contexto da programação de com-
putadores. O próprio nome, orientação a objetos, remete ao conceito
de que o foco da construção dos programas está em orientar a estrutura
para as entidades objetos, que emulam noções existentes no mundo real.
Para que o paradigma de orientação a objetos tenha maior abrangên-
cia, faz-se necessário que outros conceitos também sejam possíveis e,
nesse escopo, ocorre a herança entre objetos. Assim como na realidade,
no contexto da programação orientada a objetos, a herança está asso-
ciada à característica de possuir comportamentos de outra entidade.
Neste capítulo, iremos entender o funcionamento do conceito de
herança na programação orientada a objetos. Além disso, abordaremos
o conceito de polimorfismo, que permite que a herança entre objetos
seja possível, mesmo com alterações no comportamento herdado, para
atender a características específicas do objeto herdeiro.
O conceito de herança na orientação a objetos
O conceito de herança na programação orientada a objetos é utilizado para
se permitir a reutilização de um código. A herança possibilita que classes
compartilhem seus atributos e métodos entre si. Segundo Tucker e Noonan
(2009, p. 335),
[...] o paradigma orientado a objetos suporta reutilização de código por in-
termédio da herança. As classes existem em uma linguagem orientada a
objetos em uma hierarquia de classes. Uma classe pode ser declarada como
uma subclasse de outra classe, que é chamada de classe mãe ou superclasse.
Dentro dessa relação de hierarquia de classes é possível que a subclasse
herde atributos e comportamentos da superclasse, simplesmente pelo fato de
ser sua subordinada.
Na programação orientada a objetos, a relação de herança entre classes é
a relação em que uma classe é do tipo é uma, e não do tipo tem uma. Esta é
uma das confusões recorrentes na construção de programas em orientação
a objetos.
Para ilustrar essa diferença, observe a Figura 1 e veja que, neste exemplo,
temos um tipo de relação é uma, pois o objeto da classe Cachorro, assim
como o objeto da classe Gato, é, por herança, um tipo de objeto da classe
Animal.
Figura 1. Representação de herança
entre classes.
Animal
Cachorro Gato
Programação orientada a objetos: herança e polimorfismo2
Compare, agora, a relação apresentada na Figura 2, que representa uma
relação do tipo tem uma. Perceba que, neste caso, uma relação de herança
entre as classes Estado e Cidade não faz sentido, visto que um estado
possui cidades, mas uma cidade não é um estado.
Figura 2. Representação da relação do tipo tem uma entre
classes.
Estado Cidade
No conceito de herança, a superclasse geralmente é uma classe genérica,
que engloba os atributos e métodos que podem ser utilizados por qualquer
classe herdeira. Não faz sentido utilizar a superclasse para atribuir, por exem-
plo, um atributo ou método que seja específico de uma subclasse, pois, neste
caso, todas as demais subclasses estariam herdando este atributo ou método
desnecessariamente.
A herança pode apresentar duas formas diferentes. A mais comum e uti-
lizada pelas linguagens de programação, em geral, é a herança simples. No
entanto, algumas linguagens de programação orientada a objetos, como a
linguagem C++ e Python, possibilitam a implementação da herança múltipla
(TUCKER; NOONAN, 2009).
Na herança simples, uma hierarquia de classe forma uma árvore, com
sua raiz na classe genérica. Uma classe D é uma subclasse de outra classe
C quando ela estende ou especializa o significado da classe C e acrescenta
novas variáveis de instância ou métodos, ou quando modifica as definições
dos métodos público e protegido de C.
A herança múltipla, conforme já mencionado, é um recurso que também
pode ser implementado por algumas linguagens de programação orientada
a objetos. A linguagem Java, por exemplo, uma das linguagens orientada a
objetos mais utilizadas não permite a implementação da herança múltipla.
Em contraposição à herança simples, na herança múltipla uma classe pode
herdar atributos e métodos de mais de umasuperclasse, atribuindo a esta
comportamentos de diferentes classes.
3Programação orientada a objetos: herança e polimorfismo
Existem situações em que seu uso pode ser pertinente, mas a herança múl-
tipla também possui desvantagens, especialmente em razão de sua semântica,
que pode dificultar a manutenção do código. Conforme Lima (2014, p. 148)
observa,
[...] uma desvantagem da herança múltipla é que sua semântica se torna muito
complicada em certas circunstâncias. Por exemplo, se uma classe E tem sub-
classes B e C, e um método M é definido diferentemente em B e C, que imple-
mentação de M deveria ser herdada por E: aquela em B, aquela em C ou ambas?
Em alguns casos é necessário que a subclasse possua um comportamento
diferenciado do que foi herdado da superclasse. Na orientação a objetos, cha-
mamos esse conceito de polimorfismo. Na próxima seção, iremos abordá-lo
no contexto da orientação a objetos.
Polimorfismo
O polimorfismo na programação orientada a objetos permite que uma ou mais
classes derivadas de uma mesma superclasse possam invocar métodos que
possuam uma mesma assinatura, mas com comportamentos diferenciados
para cada classe derivada, utilizando, para isso, uma referência a um objeto
da superclasse.
A definição de polimorfismo é mais um dos recursos da orientação a
objetos que possibilita que um comportamento encontrado na realidade seja
aplicado à programação. Na natureza, existem animais que são capazes de
modificar sua forma ou comportamento para atender a determinada situação,
e é isto que o polimorfismo possibilita na programação orientada a objetos.
Segundo Tucker e Noonan (2009, p. 323), “em linguagens orientadas a ob-
jetos, polimorfismo refere-se à ligação tardia de uma chamada a uma ou várias
diferentes implementações de um método em uma hierarquia de herança”.
Para entendermos melhor este exemplo, suponhamos que uma aplicação
implementa um programa de desenho. Em um programa desses, podemos ter
diferentes formas geométricas: círculo, quadrado, retângulo etc.
Programação orientada a objetos: herança e polimorfismo4
Cada uma das formas geométricas é representada, respectivamente, por
uma das classes apontadas a seguir.
� classe circulo;
� classe quadrado;
� classe retangulo.
Todas essas classes são subclasses da classe FormaGeometrica. Temos,
na superclasse FormaGeometrica, a definição do método desenhar,
mas sabemos que desenhar um círculo é diferente de desenhar um retângulo.
Neste caso, a forma de implementar o método desenhar na subclasse
Circulo deve possuir um comportamento diferente da implementação
na subclasse Retangulo, apesar de todas herdarem e necessitarem dessa
implementação. Portanto, o conceito de polimorfismo serve justamente para
resolver questões como esta.
A Figura 3 ilustra um diagrama de classes com base nesta implementação.
Figura 3. Representação de polimorfismo entre classes.
FormaGeometrica
Circulo
desenhar()
Quadrado
Retangulo
desenhar()
desenhar()
desenhar()
5Programação orientada a objetos: herança e polimorfismo
Para Lima (2014), são dois os tipos mais recorrentes de polimorfismo na
programação orientada a objetos:
a) polimorfismo estático ou sobrecarga de método;
b) polimorfismo dinâmico ou sobrescrita de método.
O polimorfismo estático ou sobrecarga de método é a forma de implemen-
tação em que são definidos vários métodos com o mesmo nome, mas com
assinaturas diferentes. Ou seja, cada método pode receber diferentes parâmetros
ou, então, os mesmos parâmetros de tipos diferentes. A sobrecarga consiste
em permitir, dentro da mesma classe, mais de um método com o mesmo nome.
Entretanto, eles devem necessariamente possuir argumentos diferentes para
funcionar. Booch, Rumbaugh e Jacobson (2006) afirmam que a escolha de
qual método irá ser chamado pelo programa principal dependerá do seu tipo
de objeto, e esta decisão será tomada apenas no tempo de execução, por meio
de ligação tardia.
Veja o exemplo a seguir de um código em linguagem Java para uma classe
Calculadora. Perceba que o método calcula aparece três vezes: o primeiro
recebe como parâmetro dois valores int, o segundo recebe dois valores
double e o terceiro recebe dois valores String.
public class Calculadora {
public int calcula(int a, int b) {
return a+b;
}
public double calcula(double a, double b) {
return a+b;
}
public String calcula(String a, String b) {
return a+b;
}
}
O polimorfismo dinâmico ou sobrescrita de método nos permite reescrever
um método, ou seja, podemos reescrever nas subclasses os métodos criados
inicialmente na superclasse. Os métodos que serão sobrepostos, diferentemente
dos sobrecarregados, devem possuir o mesmo nome, tipo de retorno e quan-
tidade de parâmetros do método inicial. No entanto, este será implementado
Programação orientada a objetos: herança e polimorfismo6
com especificações da classe atual, podendo adicionar algo a mais ou não
(LIMA, 2014).
Para ilustrar este exemplo, vamos novamente utilizar um trecho de código
de uma classe em linguagem Java. Primeiramente, observe a escrita do método
setVelocidade na superclasse Veiculo:
public abstract class Veiculo {
public float velocidade;
public void setVelocidade(float v) {
velocidade = v;
}
}
Veja, então, como ficaria a implementação na subclasse Carro. Observe
que a assinatura do método é a mesma da superclasse, ou seja, recebe v como
parâmetro do tipo float. Porém, na subclasse, além de atribuir o valor de v
para velocidade, são feitos um tratamento e uma atribuição de valor ao atributo
marcha, dependendo da velocidade do veículo.
public abstract class Carro. {
public float velocidade;
public void setVelocidade(float v) {
velocidade=v;
if (velocidade < 20){
marcha = 1;
} else if (velocidade >= 20 && velocidade < 40) {
marcha = 2;
} else if (velocidade >= 40 && velocidade < 60){
marcha = 3;
} else if (velocidade >= 60 && velocidade < 70){
marcha = 4;
} else if (velocidade >= 70){
marcha = 5;
}
}
}
7Programação orientada a objetos: herança e polimorfismo
Na próxima seção, iremos abordar um exemplo de aplicação de herança e
polimorfismo em linguagens orientadas a objetos.
Aplicação de herança e polimorfismo
Nas seções anteriores, abordamos os conceitos de herança e polimorfismo em
programação orientada a objetos, utilizando a linguagem de programação Java.
Nesta seção, iremos apresentar a implementação destes conceitos na constru-
ção de um programa para uma escola, no qual são utilizados os exemplos de
herança entre as classes Professor e Aluno, que herdam de Pessoa, e o
polimorfismo dinâmico, para o método obterDescontoMensalidade,
que calcula o valor da mensalidade com desconto. A Figura 4 ilustra o modelo
de classes para esta situação.
Figura 4. Modelo de classes para situação proposta de um programa para uma escola.
Pessoa
nome: string
cpf: string
data_nascimento : Date
newAttr : integer
obterDescontoMensalidade(valor)
Professor
salario : double
disciplina : String
Aluno
Matricula : String
Programação orientada a objetos: herança e polimorfismo8
Primeiramente, vamos ver como ficaria a construção da superclasse
Pessoa.
public class Pessoa {
public String nome;
public String cpf;
public Date data _ nascimento;
public Pessoa (String _ nome, String _ cpf, Date _ data) {
this.nome = _ nome;
this.cpf = _ cpf;
this.data _ nascimento = _ data;
}
}
Após a criação da superclasse, vamos verificar os códigos utilizado para
a criação das subclasses Aluno e Professor. Certifique-se de que sua
declaração inclua as palavras extends Pessoa depois de Aluno. Essa
sintaxe é da linguagem Java e significa que as subclasses devem herdar da
superclasse Pessoa.
public class Aluno extends Pessoa {
public Aluno (String _ nome, String _ cpf, Date _ data) {super ( _ nome, _ cpf, _ data);
}
public String matricula;
}
public class Professor extends Pessoa {
public Professor (String _ nome, String _ cpf, Date _ data) {
super ( _ nome, _ cpf, _ data);
}
public double salario;
public String disciplina;
}
9Programação orientada a objetos: herança e polimorfismo
Podemos verificar que, tanto na subclasse Aluno, quanto na subclasse
Professor, o método construtor está utilizando os atributos que foram
declarados na superclasse Pessoa:
_ nome
_ cpf
_ data
Além disso, observe que no caso da subclasse Aluno é definido um atributo
específico matricula, que só faz sentido para Aluno. No caso da subclasse
Professor, os atributos salario e disciplina só fazem sentido no
contexto de Professor.
Estes exemplos ilustram o típico uso de herança, sem haver necessidade
de reescrever nas subclasses o que é comum a elas, escrevendo somente o
que lhes é específico.
Agora, suponhamos que a escola resolveu criar um programa de oferta
de descontos em mensalidades para Aluno e para Professor. Contudo, a
diferença de percentual seria de 20% para os professores e apenas 10% para
alunos. Vamos adotar o desconto de 10% como o desconto comum, logo, seria
criado na superclasse Pessoa o método obterDescontoMensalidade
para retornar o valor do desconto. Dessa forma, não é necessário fazer nenhuma
alteração na subclasse Aluno, pois o comportamento será automaticamente
herdado da superclasse Pessoa.
public class Pessoa {
public String nome;
public String cpf;
public Date data _ nascimento;
public Pessoa (String _ nome, String _ cpf, Date _ data) {
this.nome = _ nome;
this.cpf = _ cpf;
this.data _ nascimento = _ data;
}
public double obterDescontoMensalidade (double valor) {
//Retorna o valor do desconto na mensalidade
return 0.10 * valor;
}
}
Programação orientada a objetos: herança e polimorfismo10
Como especificado na regra de negócio, os objetos da classe Professor
devem receber um desconto diferenciado de 20%. Logo, utilizando o conceito
de polimorfismo dinâmico, em que o método possui a mesma assinatura,
apenas implementando um novo comportamento, vamos fazer um ajuste para
atender a esta necessidade.
Veja, então, como ficaria a subclasse Professor:
public class Professor extends Pessoa {
public Professor (String _ nome, String _ cpf, Date _ data) {
super ( _ nome, _ cpf, _ data);
}
public double salario;
public String disciplina;
public double obterDescontoMensalidade (double valor) {
//Retorna o valor do desconto na mensalidade
return 0.20 * valor;
}
}
Este foi um exemplo de aplicação simples da utilização em uma mesma
estrutura de classes dos conceitos apresentados neste capítulo. Por fim, é
possível verificar que herança e polimorfismo se relacionam no contexto das
linguagens de programação orientada a objetos.
Acesse o link a seguir para um exemplo de polimorfismo e herança em Python, uma
importante linguagem de programação que permite a orientação a objetos.
https://qrgo.page.link/6xYCs
11Programação orientada a objetos: herança e polimorfismo
BOOCH, G.; RUMBAUGH, J.; JACOBSON, I. UML: guia do usuário. 2. ed. Rio de Janeiro:
Elsevier; Campus, 2006. 474 p.
LIMA, A. S. UML 2.5: do requisito à solução. São Paulo: Érica, 2014. 368 p.
TUCKER, A. B.; NOONAN, R. E. Linguagens de programação: princípios e paradigmas. 2.
ed. Porto Alegre: AMGH, 2009. 630 p.
Leituras recomendadas
EDELWEISS, N.; LIVI, M. A. C. Algoritmos e programação: com exemplos em Pascal e C.
Porto Alegre: Bookman, 2014. 476 p. (Série Livros Didáticos Informática UFRGS).
LEDUR, C. L. Desenvolvimento de sistemas com C#. Porto Alegre: SAGAH, 2018. 268 p.
MACHADO, R. P.; FRANCO, M. H. I.; BERTAGNOLLI, S. C. Desenvolvimento de software III:
programação de sistemas web orientada a objetos em Java. Porto Alegre: Bookman,
2016. 220 p. (Série Tekne; Eixo Informação e Comunicação).
OKUYAMA, F. Y.; MILETTO, E. M.; NICOLAO, M. Desenvolvimento de software I: conceitos bá-
sicos. Porto Alegre: Bookman, 2014. 236 p. (Série Tekne; Eixo Informação e Comunicação).
NICOLETTI, M. C. A cartilha Prolog. São Carlos: Edufscar, 2003. 124 p. (Série Apontamentos).
PINHEIRO, F. A. C. Elementos de programação em C: em conformidade com o padrão
ISO / IEC 9899. Porto Alegre: Bookman, 2012. 548 p.
SEBESTA, R. W. Conceitos de linguagem de programação. 11. ed. Porto Alegre: Bookman,
2018. 758 p.
Programação orientada a objetos: herança e polimorfismo12
PARADIGMAS DE
PROGRAMAÇÃO
Fabricio Machado da Silva
Programação orientada
a objetos: classes,
relacionamentos e
encapsulamentos
Objetivos de aprendizagem
Ao final deste texto, você deve apresentar os seguintes aprendizados:
� Analisar as classes na perspectiva de orientação a objetos.
� Descrever os relacionamentos na perspectiva de orientação a objetos.
� Explicar o que é encapsulamento.
Introdução
Na programação orientada a objetos, as classes desempenham um papel
fundamental. Classes são estruturas que determinam a descrição de um
conjunto de objetos que a utilizam como base e, dessa forma, são nas
classes que são definidos os atributos e métodos que os objetos podem
conter. Por essa razão, as classes são denominadas matriz de um objeto
e determinam seu escopo.
Existem conceitos básicos em programação orientada a objetos, entre
eles, o conceito que determina que apenas os métodos do próprio objeto
devem manipular seus atributos, garantindo acesso direto à propriedade
do objeto, adicionando outra camada de segurança à aplicação. As classes
devem possibilitar diferentes tipos de relacionamentos e, assim sendo,
diferentes tipos de relacionamento são previstos.
Neste capítulo, você irá compreender o que são as classes na pers-
pectiva da orientação a objetos, além de aprender sobre seus relaciona-
mentos e o conceito de encapsulamento.
Classes na orientação a objetos
As classes são as estruturas de código mais importantes de qualquer sistema
orientado a objetos. Segundo Booch, Rumbaugh e Jacobson (2006, p. 45),
“uma classe é uma descrição de um conjunto de objetos que compartilham
os mesmos atributos, operações, relacionamentos e semântica”. As classes
são utilizadas para expressar todo o vocabulário e escopo do sistema a ser
desenvolvido.
É praticamente impossível falar em orientação a objetos sem relacioná-la
ao conceito de classes. Dessa forma, não é difícil imaginar a importância da
construção de classes bem estruturadas, que consigam delimitar corretamente
as fronteiras e os relacionamentos para, assim, realizar a distribuição correta
das responsabilidades dentro de um sistema orientado a objetos.
O paradigma de programação orientada a objetos envolve a identificação e
abstração de entidades, de acordo com o escopo de um sistema. Essas entidades
formam o vocabulário do sistema. Por exemplo, se estamos desenvolvendo
um sistema para um consultório médico, entidades como prontuário, paciente,
médico, etc., fazem parte do vocabulário e serão implementadas pelas classes.
As classes são representadas graficamente por um retângulo. A Figura 1 ilustra
a representação de uma classe conforme a Unified Modeling Language (UML).
Figura 1. Representação da estrutura de uma classe.
Fonte: Ricarte (2003, documento on-line).
Segundo Lima (2014, p. 49), “uma classe é uma descrição de um conjunto
de objetos que compartilham os mesmos atributos, operações, relacionamentos
e semântica”.
Programação orientada a objetos: classes, relacionamentos e encapsulamentos2
Cada classe deve possuir um nome que a diferencie das demais. O nome é
dito simples quando contém uma só sequência de caracteres, ou qualificado,
quando além do nome da classe, possui um prefixo que identifica o nome do
pacote a qual a classe pertence. Algumas representações de classes podem ser
apenas o seu nome. Por padrão, o nome da classe sempre começa com letra
maiúscula, como no exemploa seguir.
� Cliente.
� Parede.
� Sensor de temperatura.
Outra propriedade de uma classe são os atributos. Um atributo é uma
propriedade de uma classe e também são chamados de variáveis ou campo. É
pelos atributos que podemos definir o estado de um objeto, fazendo com que
esses valores possam ser alterados. Um atributo é, portanto, uma abstração do
tipo de dado ou de estados que os objetos da classe podem abranger.
Um atributo pode ser indicado por sua classe e, possivelmente, um valor
inicial padrão. O exemplo a seguir mostra um código em Java com a definição
dos atributos de uma classe Cachorro:
public class Cachorro{
public String nome;
public int peso;
public String corOlhos;
public int quantPatas;
}
Outra propriedade de uma classe são as operações ou métodos. Uma ope-
ração ou método é a implementação de um serviço que pode ser acionado
por algum objeto da classe, ou seja, são as operações que podem determinar
o comportamento dos objetos. Um método pode também ser definido como
uma abstração de algo que pode ser feito com determinado objeto e que pode
ser compartilhado por todos os objetos da classe.
Segundo Booch, Rumbaugh e Jacobson (2006, p. 53), “uma classe pode
ter qualquer quantidade de métodos ou até mesmo nenhum método definido”.
Os métodos ou operações podem ser especificados pela indicação de sua
assinatura, que contém nome, tipo e valor padrão de todos os parâmetros. O
exemplo de código a seguir mostra a definição em Java do método latir
para a mesma classe Cachorro:
3Programação orientada a objetos: classes, relacionamentos e encapsulamentos
class Cachorro {
int tamanho;
String nome;
void latir() {
if(tamanho > 60)
System.out.println("Wooof, Wooof!");
else if(tamanho > 14)
System.out.println("Ruff!, Ruff!");
else
System.out.println("Yip!, Yip!");
}
}
Além disso, as classes definem reponsabilidades. Uma reponsabilidade é
o conceito de que uma classe deve executar uma única responsabilidade no
sistema e essa responsabilidade deve ser executada por esta única classe, sem
ser repetida por outra classe do sistema.
Se temos, em um sistema, duas classes compartilhando uma determinada
responsabilidade, estamos ferindo esse conceito. Se ao se referir a uma deter-
minada classe, você diz: “minha classe tem as informações do cliente e pode
salvá-las no banco de dados”, perceba que o “e” na frase, indica mais de uma
responsabilidade. A seguir, vamos abordar os tipos de relacionamentos que
as classes podem estabelecer.
Relacionamentos
Ao trabalhar com a orientação a objetos, percebemos que, assim como no
mundo real, existe um número muito pequeno de classes que podem trabalhar
sozinhas em qualquer sistema. Ao contrário, temos a maioria das classes
colaborando com as outras, de diferentes maneiras. Dessa forma, ao traba-
lharmos com a definição e a modelagem de um sistema a ser construído em
uma linguagem orientada a objetos, não é possível ater-se somente a identificar
as classes que fazem parte do escopo desse sistema, mas também é preciso
entender e modelar, os relacionamentos, ou seja, o modo como essas classes
se relacionam entre si.
Programação orientada a objetos: classes, relacionamentos e encapsulamentos4
Segundo Tucker e Noonan (2009, p. 275), “existem três tipos de relaciona-
mento especialmente importantes”, conforme vemos a seguir.
� Dependências: representam os relacionamentos de utilização entre
classes.
� Generalizações: representam o relacionamento entre classes mães e
suas classes herdeiras.
� Associações: representam os relacionamentos estruturais entre objetos:
■ agregações: tipo de associação na qual o objeto dependente pode
existir mesmo sem o objeto pai;
■ composição: tipo de associação na qual a existência do objeto de-
pendente só faz sentido se o objeto pai existe.
Cada um desses relacionamentos fornece uma forma diferente de combina-
ções e de abstrações. A dependência é um relacionamento de utilização entre
classes e se caracteriza por um tipo de relacionamento no qual a mudança em
uma classe pode afetar o comportamento ou estado de outra classe.
As dependências podem ser usadas no contexto de classes para mostrar
que uma classe usa outra como argumento na assinatura de uma operação. Ou
seja, a dependência indica que um objeto depende da especificação de outro.
Uma dependência é representada graficamente por uma linha tracejada,
ligando duas classes, com uma seta apontando para a classe da qual a outra
depende. A Figura 2 ilustra um exemplo de dependência entre as classes
Sistema e Pessoa.
Figura 2. Relacionamento de dependência entre classes.
Fonte: Nogueira (2006, documento on-line).
5Programação orientada a objetos: classes, relacionamentos e encapsulamentos
Um relacionamento de dependência pode ter um nome, apesar de os nomes
raramente serem necessários, a menos que tenha um modelo com muitas
dependências e seja necessário fazer uma referência a elas (BOOCH; RUM-
BAUGH; JACOBSON, 2006).
A generalização é um relacionamento entre superclasses ou classes mães
e seus tipos mais específicos são também chamados de subclasses ou classes
filhas. A generalização significa que os objetos da classe filha podem ser
utilizados em qualquer local que a classe mãe ocorra, mas não vice-versa.
Em outras palavras, a generalização significa que a classe filha pode ser
substituível por uma declaração da classe mãe.
Como em um relacionamento do tipo generalização as classes filhas herdam
os atributos e métodos da classe mãe, é necessário que na classe filha sejam
então especificados somente os atributos e métodos que lhe são específicos,
sendo os demais herdados da classe mãe e, por isso, desnecessários para sua
declaração.
Os relacionamentos de generalização podem ser de uma classe mãe para
várias classes filhas, ou uma classe filha pode herdar de diferentes classes
mães (TUCKER; NOONAN, 2009).
Para entender melhor esse conceito, imagine uma classe mãe ou superclasse
chamada Veículo, na qual são definidos os atributos comuns a qualquer
veículo (cor, chassi, placa), e sua relação com as classes filhas Carro e
Moto. Como esses atributos se repetem tanto para um objeto do tipo Carro
quanto para um objeto do tipo Moto, não é necessário repetir os atributos
nessas classes. A seta vazada apontando para a superclasse identifica que
existe um relacionamento de generalização entre as classes. A Figura 3 ilustra
esse exemplo.
A associação é um tipo de relacionamento estrutural que especifica quais
objetos de uma classe estão conectados a objetos de outra. A partir de uma
associação entre objetos é possível navegar de um objeto ao outro. A associação
é o tipo mais comum de relacionamento e sinaliza que os objetos de uma classe
estão conectados a objetos de outra.
Programação orientada a objetos: classes, relacionamentos e encapsulamentos6
Figura 3. Relacionamento de generalização entre classes.
Fonte: Vasconcelos (2011, documento on-line).
Sem essa associação, nenhuma mensagem pode passar entre os objetos da
classe em tempo de execução. Existe uma associação entre duas classes se uma
instância de uma destas reconhecer a existência da outra, de modo a realizar
seu trabalho. Em um diagrama, uma associação é representada por uma linha
conectando duas classes. Podemos representar o direcionamento da associação
colocando setas abertas nas extremidades da linha. Com isso, pode-se definir
como é feita a navegação entre classes. Quando não se colocam setas, a navegação
é definida como bidirecional (BOOCH; RUMBAUGH; JACOBSON, 2006).
A Figura 4 mostra um tipo de relacionamento de associação simples entre
a classe Cliente e Consulta.
Figura 4. Associação simples entre classes.
Fonte: Leon (2009, documento on-line).
7Programação orientada a objetos: classes, relacionamentos e encapsulamentos
O relacionamento de agregação é usado sempre que queremos indicar
que o objetode uma classe pode colaborar com a existência de um objeto de
outra, mas a existência desse objeto não é obrigatória. Também é conhecida
como associação em que um objeto é parte de outro, de tal forma que pode
existir sem o outro ou pode, ainda, ser chamada de associação fraca, devido
ao conceito de que um pode existir sem o outro. Também podemos dizer que
é uma relação do tipo “todo/parte” ou “possui um”, sendo o último mais utili-
zado em casos em que uma classe representa algo grande composto por coisas
menores (classes agregadas). A Figura 5 ilustra um tipo de relacionamento de
agregação entre classes.
Figura 5. Agregação entre classes.
Fonte: Leon (2009, documento on-line).
Por fim, o relacionamento de composição simboliza um tipo de asso-
ciação mais forte entre as classes, pois neste tipo de relacionamento não faz
sentido um objeto parte continuar existindo sem a existência de um objeto
parte. Quando se tem uma classe que depende de outra para ser utilizada, e
quando se destrói essa classe a outra também deve ser apagada, temos um
Programação orientada a objetos: classes, relacionamentos e encapsulamentos8
relacionamento de composição. A Figura 6 ilustra um tipo de relacionamento
de composição entre classes.
Figura 6. Composição entre classes.
Fonte: Leon (2009, documento on-line).
Encapsulamento
O encapsulamento é um dos conceitos básicos da programação orientada a
objetos. Esse conceito está ligado à técnica de fazer com que detalhes internos
do funcionamento dos métodos de uma classe não sejam de conhecimento
dos objetos que a utilizam. Dessa forma, os objetos não têm que se preocupar
com o modo como o método executa um determinado bloco de código, pois
são apenas acionados pelo objeto e são retornados.
O encapsulamento também é aplicado aos atributos de uma classe. Isso
faz com que um objeto esconda seus dados de outros e permite que os dados
sejam manipulados e acessados somente pelos próprios métodos do objeto
(TUCKER; NOONAN, 2009). O conceito de encapsulamento possibilita os
seguintes ganhos:
9Programação orientada a objetos: classes, relacionamentos e encapsulamentos
� proteger os dados de um objeto de uso arbitrário e não intencional;
� ocultar de um usuário os detalhes da implementação;
� separar a maneira como um objeto se comporta da maneira como está
implementado;
� definir como implementar os conhecimentos ou ações de uma classe,
sem informar como isto é feito.
Um exemplo para ilustrar o conceito de encapsulamento seria um usuário
trocando um canal de televisão pelo controle remoto. Este usuário aperta o
botão e não se importa como o controle remoto se comunica com a televisão
e solicita a troca do canal: ele simplesmente sabe que, ao pressionar o botão,
o canal será selecionado.
Quando você cria um método, sabe que ele está correto e o chama em outra classe,
você está confiando no que fez. Se quiser lembrar a ordem das linhas de código, isto
seria o equivalente a encapsular a troca de mensagens entre os objetos.
Em um processo de encapsulamento, os atributos das classes são do tipo
private. Para acessar esses tipos de modificadores, é necessário criar
métodos setters e getters. Por entendimento, os métodos setters servem para
alterar a informação de uma propriedade de um objeto. Já os métodos getters
servem para retornar o valor dessa propriedade.
O encapsulamento é dividido em dois níveis, conforme vemos a seguir.
� Nível de classe: quando determinamos o acesso de uma classe inteira,
que pode ser public ou Package-Private (padrão);
� Nível de membro: quando determinamos o acesso de atributos ou mé-
todos de uma classe, que podem ser public, private, protected
ou Package-Private (padrão).
Veja, no exemplo a seguir, um código Java implementando os métodos
get e set para os atributos de uma classe.
Programação orientada a objetos: classes, relacionamentos e encapsulamentos10
public class Pessoa {
private String nome;
private String sobrenome;
private String dataNasc;
private String rg;
private String[] telefones;
public String getNome(){
return nome;
}
public void setNome(String n) {
nome = n;
}
public String getSobrenome() {
return sobrenome;
}
public void setSobrenome(String s) {
sobrenome = s;
}
public String getDataNasc() {
return dataNasc;
}
public void setDataNasc(String d) {
dataNasc = d;
}
public String getRg() {
return rg;
}
public void setRg(String r) {
r = rg;
}
public String getTelefones() {
return telefones;
}
public void setTelefones(String[] telefones) {
telefones[] = telefones;
}
}
11Programação orientada a objetos: classes, relacionamentos e encapsulamentos
Quando trabalhamos com programação orientada a objetos, devemos
começar a implementação de uma classe utilizando o nível de acesso pri-
vate, a menos que seja necessário utilizar o public. Fazemos isso porque
é desejável ter como padrão a privacidade dos dados ocultados, protegendo
seu acesso por outro objeto externo. Além disso, membros públicos tendem
a nos ligar a uma implementação em particular e limitar nossa flexibilidade
em mudar o código.
Uma grande vantagem do encapsulamento é que toda parte encapsulada
pode ser modificada sem que os usuários da classe em questão sejam afetados.
No caso de um liquidificador, por exemplo, um técnico poderia substituir o
motor do equipamento por outro totalmente diferente, sem que seu usuário
seja afetado — afinal, ele continuará somente tendo que pressionar o botão.
BOOCH, G.; RUMBAUGH, J.; JACOBSON, I. UML: guia do usuário. 2. ed. Rio de Janeiro:
Elsevier; Campus, 2006. 474 p.
LEON, P. L. Associações entre Classes de Objetos – UML. Pleon’s Blog, [S. l.], 22 fev. 2009.
Disponível em: https://plleon.wordpress.com/2009/02/22/associacoes-entre-classes-
-de-objetos-uml/. Acesso em: 27 set. 2019.
LIMA, A. S. UML 2.5: do requisito à solução. São Paulo: Érica, 2014. 368 p.
NOGUEIRA, A. UML - Unified Modeling Language - Generalização, agregação, com-
posição e dependência. Linha de Código, Rio de Janeiro, 13 fev. 2006. Disponível em:
http://www.linhadecodigo.com.br/artigo/943/uml-unified-modeling-language-ge-
neralizacao-agregacao-composicao-e-dependencia.aspx. Acesso em: 27 set. 2019.
RICARTE, I. L. M. O que é uma classe. Programação Orientada a Objetos – Uma aborda-
gem com Java, Campinas, 27 jun. 2000. Disponível em: http://www.dca.fee.unicamp.
br/cursos/PooJava/classes/conceito.html. Acesso em: 27 set. 2019.
TUCKER, A. B.; NOONAN, R. E. Linguagens de programação: princípios e paradigmas. 2.
ed. Porto Alegre: AMGH, 2009. 630 p.
VASCONCELOS, N. UML: Diagrama de Classes: Generalização. Tudo que eu gosto e outros
assuntos, [S. l.], 15 jun. 2011. Disponível em: http://tudoqueeugostoeoutrosassuntos.
blogspot.com/2011/06/uml-diagrama-de-classes-generalizacao.html. Acesso em:
27 set. 2019.
Programação orientada a objetos: classes, relacionamentos e encapsulamentos12
Leituras recomendadas
EDELWEISS, N.; LIVI, M. A. C. Algoritmos e programação: com exemplos em Pascal e C.
Porto Alegre: Bookman, 2014. 476 p. (Série Livros Didáticos Informática UFRGS).
LEDUR, C. L. Desenvolvimento de sistemas com C#. Porto Alegre: SAGAH, 2018. 268 p.
MACHADO, R. P.; FRANCO, M. H. I.; BERTAGNOLLI, S. C. Desenvolvimento de software III:
programação de sistemas web orientada a objetos em Java. Porto Alegre: Bookman,
2016. 220 p. (Série Tekne; Eixo Informação e Comunicação).
NICOLETTI, M. C. A cartilha Prolog. São Carlos: Edufscar, 2003. 124 p. (Série Apontamentos).
OKUYAMA, F. Y.; MILETTO, E. M.; NICOLAO, M. Desenvolvimento de software I: conceitos bá-
sicos. Porto Alegre: Bookman, 2014. 236 p. (Série Tekne; Eixo Informação e Comunicação).
PINHEIRO, F. A. C. Elementos de programação em C: em conformidade com o padrão
ISO / IEC 9899. Porto Alegre: Bookman, 2012. 548 p.
SEBESTA,R. W. Conceitos de linguagem de programação. 11. ed. Porto Alegre: Bookman,
2018. 758 p.
13Programação orientada a objetos: classes, relacionamentos e encapsulamentos
ENGENHARIA
DE SOFTWARE
Izabelly Soares de Morais
Modelo de análise de
software (orientada
a objetos)
Objetivos de aprendizagem
Ao final deste texto, você deve apresentar os seguintes aprendizados:
� Identificar os objetivos da análise orientada a objetos.
� Aplicar os principais elementos de modelagem (diagramas da UML).
� Avaliar as vantagens e as desvantagens deste modelo.
Introdução
A análise orientada a objetos, diferentemente do enfoque tradicional,
sugere que um sistema é uma coletânea de objetos que interagem entre
si, com características próprias, representadas por atributos e operações.
Neste tipo de análise, os atributos representam os dados de um objeto
e servem para expressar características e informações. Já as operações
são as ações que podem ser realizadas pelo objeto. O mais interessante
é a possibilidade de modelar o sistema usando objetos que representam
elementos do mundo real. Isso permite que sistemas complexos sejam
facilmente modelados e implementados, além de facilitar o seu cresci-
mento e a manutenção.
Neste capítulo, você vai adquirir conhecimentos fundamentais para
avançar no aprendizado sobre análise orientada a objetos. Explore concei-
tos básicos sobre o modelo, suas ferramentas, vantagens e desvantagens.
Engenharia de software aplicada à análise de
software orientada a objetos
A era tecnológica almeja por softwares cada vez mais complexos. Essa com-
plexidade está ligada diretamente à grande quantidade de informações que
devem ser processadas simultaneamente. Com o tempo, os recursos tecno-
lógicos passaram por diversas mudanças, tanto em seus dispositivos físicos
quanto lógicos. A Engenharia de Software surgiu devido à necessidade de
haver técnicas que norteassem o processo de desenvolvimento do software.
Diante dos diversos conceitos, métricas e ferramentas que regem a Engenha-
ria de Software, foram desenvolvidas maneiras de realizar a análise de software.
Primeiramente, o modelo mais utilizado foi o modelo de análise estruturada,
que ficou conhecido também como um modelo clássico. Por ser clássico, ele
traz conceitos de base para se realizar a análise de um software. Porém, como
citado anteriormente, vivemos em uma era em que os artefatos tecnológicos
devem ser cada vez mais robustos e compatíveis às novas tecnologias.
A OOA (análise orientada a objetos, em inglês object-oriented analysis,)
é uma técnica de análise semiformal para o paradigma de orientação a obje-
tos. A análise orientada a objetos é um componente-chave do paradigma de
orientação a objetos. Quando esse fluxo de trabalho é realizado, as classes são
extraídas. Os casos de uso e as classes são a base de um produto de software
orientado a objetos a ser desenvolvido (SCHACH, 2010, p.395). Dessa forma,
“concentra-se na definição de classes e na maneira como colaboram entre si
para atender aos requisitos dos clientes” (PRESSMAN; MAXIM, 2016, p.
172). Uma classe traz um conceito do mundo real, representa algum conceito,
um objeto, que tem comportamento e características e que executa ações.
Assim como as diversas vertentes da Engenharia de Software, a metodologia
de análise de software também requer técnicas específicas para que todos os
detalhes observados sejam documentados, seja por meio da escrita de uma
documentação específica, seja pelo uso de recursos gráficos. Veremos quais
elementos são utilizados pela análise orientada a objetos no próximo tópico.
Uma das metodologias existentes na Engenharia de Software é a meto-
dologia ágil e que pode ser aplicada na análise de software. No The Official
Agile Modeling Site, Scott Ambler (apud PRESSMAN; MAXIM, 2016, p. 81),
descreve modelagem ágil (AM) da seguinte maneira:
Modelagem ágil (AM) consiste em uma metodologia prática, voltada para a
modelagem e documentação de sistemas baseados em software. Simplificando,
modelagem ágil consiste em um conjunto de valores, princípios e práticas
voltados para a modelagem do software que podem ser aplicados a um projeto
de desenvolvimento de software de forma leve e eficiente. Os modelos ágeis
são mais eficientes do que os tradicionais pelo fato de serem simplesmente
bons, pois não têm a obrigação de ser perfeitos.
Modelo de análise de software (orientada a objetos)2
Elementos da modelagem orientada a objetos
O modelo de análise de software estruturado faz uso do diagrama de fluxo de
dados e do dicionário de dados, não se limitando a nenhum desses elementos,
até mesmo porque o uso de uma metodologia ou ferramenta irá depender do
contexto ao qual ela será inserida. Dessa forma, para a realização da análise de
software orientado a objetos, se faz comum o uso da linguagem de modelagem
unificada (do inglês UML – unified modeling language) como elemento de
representação gráfica e informacional de dados e informações de um software.
Linguagem de modelagem unificada (UML)
A UML nos permite visualizar e especificar detalhes de um software em
desenvolvimento por meio de uma linguagem específica. Ela permite que
elementos, relacionamentos e diagramas sejam modelados. Esses elementos
podem ser estruturais, comportamentais e, até, simples anotações sobre os
artefatos do software, que são compostos por classes, componente, interações,
pacotes, dentre outros. Os relacionamentos entre as classes, ou seja, entre
os objetos dentro de um contexto de orientação a objetos, ocorrem por meio
de dependências, associações, implementações e até generalizações. Cada
relacionamento é estabelecido conforme o problema a ser solucionado.
Para Larman (2007, p. 39), a palavra visual na definição é um ponto-chave.
A UML é a notação diagramática padrão, de fato, para desenhar ou apresentar
figuras (com algum texto) relacionadas a software – principalmente software
orientado a objetos (OO). Em Fowler (2003 apud Larman, 2007), três modos
pelos quais as pessoas aplicam UML são apresentados:
� UML como rascunho: diagramas incompletos e informais (frequente-
mente rascunhados à mão em quadros brancos) criados para explorar
partes difíceis do problema ou espaço de soluções, explorando o poder
das linguagens visuais.
� UML como planta de software: diagramas de projeto relativamente
detalhados, usados seja em Engenharia reversa, para visualizar e melhor
entender o código existente em diagramas UML; ou geração de código
(Engenharia avante).
■ Em Engenharia reversa: uma ferramenta UML lê o código fonte ou
o código binário e gera (tipicamente) diagramas UML de pacotes, de
3Modelo de análise de software (orientada a objetos)
classes e de sequência. Essas “plantas de software” podem ajudar o
leitor a entender os elementos, a estrutura e as colaborações globais.
■ Antes da programação, alguns diagramas detalhados podem fornecer
diretrizes para a geração de código (por exemplo, em Java), quer
manualmente, quer automaticamente, com uma ferramenta. É comum
que os diagramas sejam usados para uma parte do código e outra
parte seja preenchida por um desenvolvedor que esteja codificando
(talvez também aplicando rascunhos UML).
� UML como linguagem de programação: especificação executável com-
pleta de um sistema de software em UML. Código executável será
automaticamente gerado, mas não é normalmente visto ou modificado
por desenvolvedores; trabalha-se apenas na “linguagem de programa-
ção” UML. Esse uso da UML requer um modo prático de diagramar
todo o comportamento ou a lógica (provavelmente usando diagramas
de interação ou estado) e está ainda em desenvolvimento em termos
de teoria, ferramentas robustas e usabilidade.
Ainda sob o ponto de vista do autor, “a UML descreve tipos de esboço
de diagramas, tais como diagramas de classe e diagramas de sequência. Ela
não superpõe a eles uma perspectiva de modelagem. Por exemplo, a mesma
notação UML de diagramade classes pode ser usada para desenhar imagens
de conceitos do mundo real ou de classes de software em Java” (LARMAN,
2007, p. 40).
Diagrama de classe
O diagrama de classe
“fornece um conjunto inicial de elementos de notação que todos os outros
diagramas de estrutura usam. A representação UML de uma classe é um
retângulo contendo três compartimentos empilhados verticalmente [...]. O
compartimento superior mostra o nome da classe. O compartimento do meio
lista os atributos da classe. O compartimento inferior lista as operações
da classe. Ao projetar um elemento de classes em um diagrama de classes,
deve-se usar o compartimento superior, e os dois compartimentos inferiores
são opcionais (os dois inferiores seriam desnecessários em um diagrama que
ilustrasse um nível mais alto de detalhes, no qual o propósito fosse mostrar
somente o relacionamento entre os classificadores (BELL, 2016, p. 3).
Modelo de análise de software (orientada a objetos)4
A Figura 1 a seguir traz um exemplo da notação gráfica do diagrama de
classes.
Figura 1. Notação de um diagrama de classe.
O contexto que envolve a manipulação de objetos traz também a questão
da herança, a qual permite que uma classe herde outras funcionalidades e
até outros atributos. A representação gráfica desse conceito é realizada pela
ligação entre as classes por meio de uma ponta de seta, já que o “traço” re-
presenta apenas uma associação. Neste caso, essa ponta de seta não deve ser
preenchida e deve apontar, da classe que está disponibilizando, seus atributos
e operações. Chamamos essa classe de superclasse (Figura 2).
Figura 2. Representação de uma herança no diagrama de classe.
5Modelo de análise de software (orientada a objetos)
De acordo com Pressman e Maxim (2016, p. 895),
qualquer alteração nos atributos ou nas operações contidas dentro de uma
superclasse é imediatamente herdada por todas as subclasses. Portanto, a
hierarquia de classes torna-se um mecanismo pelo qual alterações (em altos
níveis) podem ser imediatamente propagadas em um sistema. É importante
notar que, em cada nível de hierarquia de classe, novos atributos e operações
podem ser acrescentados àqueles que foram herdados de níveis mais altos
na hierarquia.
As operações que envolvem o diagrama de classes podem ser contempladas também
com outros tipos de eventos. Para isso, Bell (2016) descreve as seguintes associações
que podem ser utilizadas com o diagrama de classes:
� Associação bidirecional (padrão): Uma associação é uma ligação entre duas classes.
As associações são sempre consideradas bidirecionais. Isso significa que ambas as
classes estão cientes de cada uma e do relacionamento que têm, a menos que
você qualifique a associação como algum outro tipo.
� Associação unidirecional: em uma associação unidirecional, duas classes são re-
lacionadas, mas somente uma classe reconhece que o relacionamento existe.
� Uso de pacotes, interfaces e outros tipos de associações.
Casos de uso
O caso de uso é outro diagrama da UML, e Alistair Cockburn (2001, apud
PRESSMAN; MAXIM, 2016, p. 149) observa que “um caso de uso captura
um contrato [...] [que] descreve o comportamento do sistema sob várias con-
dições, à medida que o sistema responde a uma solicitação de um de seus
envolvidos”. Para Pressman e Maxim (2016, p. 149), basicamente, um caso
de uso conta uma jornada estilizada sobre como um usuário (desempenhando
um de uma série de papéis possíveis) interage com o sistema sob um conjunto
de circunstâncias específicas.
De acordo com Schach (2010, p. 290), outra forma de interpretar um caso
de uso é que ele mostra a interação entre o produto de software e o ambiente
no qual ele opera, isto é, o ator é o membro do mundo externo ao produto de
software, ao passo que o retângulo no caso de uso representa o produto de
software. Normalmente, é mais fácil identificar um ator.
Modelo de análise de software (orientada a objetos)6
� Frequentemente, ator é um usuário de produto de software. No caso
de um produto de software para a área bancária, os usuários desse
produto de software são os clientes e os funcionários do banco, como
caixas e gerentes.
� Em geral, o ator desempenha um papel em relação ao produto de sof-
tware, que poderia ser como usuário deste. Entretanto, o iniciador de
um caso de uso, ou alguém que desempenhe um papel crítico em um
caso de uso, também desempenha um papel, portanto, é considerado
um ator, independentemente de essa pessoa também ser um usuário do
produto de software (Figura 3).
Figura 3. Representação do diagrama de caso de uso.
Assim como no diagrama de classe, o caso de uso também traz associações,
que relacionam os autores, os casos de uso, e até outros autores que podem
estar envolvidos no mesmo contexto. Para Jacobson (1992 apud PRESSMAN;
MAXIM, 2016, p. 150), algumas perguntas que devem ser respondidas por
um caso de uso:
� Quais são as metas do ator?
� Que precondições devem existir antes de uma jornada começar?
� Que tarefas ou funções principais são realizadas pelo ator?
� Que exceções poderiam ser consideradas à medida que uma jornada
é descrita?
� Quais são as variações possíveis na interação do ator?
� Que informações de sistema o ator adquire, produz ou modifica?
� O ator terá de informar o sistema sobre mudanças no ambiente externo?
� Que informações o ator deseja do sistema?
� O ator gostaria de ser informado sobre mudanças inesperadas?
7Modelo de análise de software (orientada a objetos)
Diversos mecanismos podem ser utilizados na concepção de um caso de
uso. Geralmente, as informações contidas nesse tipo de diagrama são oriun-
das de uma completa documentação de requisitos, os quais devem trazer os
requisitos funcionais do sistema. Dessa forma, todos devem trazer mais clareza
e consistência ao sistema, pois demonstram visualmente alguns de seus mais
importantes aspectos, que são suas funcionalidades.
A UML tem muitos tipos de diagramas e, dessa forma, apoia a criação de diferentes
modelos de sistema. No entanto, uma pesquisa em 2007 (ERICKSON; SIAU, 2007 apud
SOMMERVILLE, 2011, p. 83) mostrou que a maioria dos usuários de UML acredita que
cinco tipos de diagramas podem representar a essência de um sistema:
� diagramas de atividades, que mostram as atividades envolvidas em um processo
ou no processamento de dados;
� diagramas de casos de uso, que mostram as interações entre um sistema e seu
ambiente;
� Diagramas de sequência, que mostram as interações entre os atores e o sistema,
e entre os componentes do sistema;
� Diagramas de estado, que mostram como o sistema reage aos eventos internos
e externos.
Vantagens e desvantagens da análise orientada
a objetos
A demanda social trouxe diversas versões da UML. Dessa forma, suas co-
notações buscaram sempre acompanhar a necessidade dos desenvolvedores
de software. Com isso, uma das vantagens em utilizar a UML na análise de
software orientada a objetos é que sempre há alguma atualização nova, para
que sua usabilidade não fique obsoleta. Ela também traz facilidades que visam
à melhor compreensão das funcionalidades de um sistema, deixando todos os
detalhes mais claros, não só para os desenvolvedores, mas também para os
clientes, que na maioria das vezes são leigos no assunto.
Modelo de análise de software (orientada a objetos)8
A desvantagem se encontra no tempo, o qual deve ser dedicado ao desen-
volvimento dos diagramas e, consequentemente, de uma vasta documentação.
Dessa forma, só é indicado dar início ao processo de implementação após
todo o sistema ter sido especificado nos diagramas. Outro fator atrelado à
desvantagem do uso da UML na análise de software orientado a objetos é a
familiaridade da equipe desenvolvedora com as notações dos diagramas e com
as ferramentas utilizadas para desenvolvê-los, um fato que acaba atrelado ao
tempo – e sabemos que para obter lucro no desenvolvimento de um software
o custo-benefício deve estar ligadodiretamente ao investimento de tempo,
ferramentas e uma equipe especializada.
De qualquer forma, a Engenharia de Software traz métodos que podem ser
adaptáveis a qualquer projeto. O importante é sabermos que temos diversas
opções. Porém, para realizarmos a melhor escolha, devemos conhecer todas
as técnicas disponíveis e sabermos como elas operam em um ciclo de desen-
volvimento de software.
A UML começou como um esforço de Booch e Rumbaugh, em 1994, não apenas
com o intuito de criar uma notação comum, mas de combinar seus dois métodos:
o de Booch e o OMT. Assim, o primeiro rascunho público do que hoje é a UML foi
apresentado como o Método Unificado (Unified Method). Ivar Jacobson, o criador do
Método Objectory, se juntou a eles na Rational Corporation e, já formando um grupo,
vieram a ser conhecidos como “os três amigos”. Foi nesse ponto que eles decidiram
reduzir o escopo do seu esforço e enfocar em uma notação comum de diagramação
a UML em vez de um método comum (LARMAN, 2007, p. 43).
9Modelo de análise de software (orientada a objetos)
Veja a seguir um exemplo prático de um diagrama de caso de uso que traz o contexto
de uma empresa da área de segurança residencial. Na imagem deste diagrama de caso
de uso, podemos identificar os atores: proprietário e administrador do sistema, e os casos
de uso: arma/desarma o sistema, acessa o sistema via internet, dentre outros (Figura 4).
Figura 4. Exemplo de diagrama de casos de uso e seus atores.
Fonte: Pressman e Maxim (2016, p. 153)
Modelo de análise de software (orientada a objetos)10
BELL, D. Fundamentos básicos de UML: o diagrama de classes. Uma introdução aos
diagramas de estrutura em UML 2. IBM developerWorks, Nova York, 2016. Disponível em:
<https://www.ibm.com/developerworks/br/rational/library/content/RationalEdge/
sep04/bell/index.html>. Acesso em: 16 ago. 2017.
COCKBURN, A. Writing Effective Use-Cases. Reading: Addison-Wesley, 2001.
FOWLER, M. UML Distilled. 3. ed. Reading: Addison-Wesley.2003.
JACOBSON, I. Object-Oriented Software Engineering. Reading: Addison-Wesley, 1992.
LARMAN, C. Utilizando UML e padrões: uma introdução à análise e ao projeto orien-
tados a objetos e ao desenvolvimento iterativo.3. ed. Porto Alegre: Bookman, 2007.
PRESSMAN, R. S.; MAXIM, B. R. Engenharia de Software: uma abordagem profissional.
8. ed. Porto Alegre: AMGH, 2016.
SCHACH, S.R. Engenharia de software: os paradigmas clássicos e orientado a objetos.
7. ed. Porto Alegre: AMGH, 2010.
SOMMERVILLE, I. Engenharia de software. 9. ed. São Paulo: Pearson, 2011.
Leituras recomendadas
DEMARCO, T. Structured Analysis and System Specification. New York: Yourdon Press, 1978.
SLACK, N.; CHAMBERS, S.; JOHNSTON, R.; BETTS, A. Gerenciamento de operações e de
processos: princípios e práticas de impacto estratégico. 2. ed. Porto Alegre: Bookman, 2013.
YOURDON, E.; CONSTANTINE, L. L. Structured Design: fundamentals of a Discipline
of Computer Program and Systems Design. Englewood Cliffs: Prentice Hall, 1979.
11Modelo de análise de software (orientada a objetos)
Ken Arnold, ex-engenheiro sênior do Sun Microsystems Laboratories, é um grande especialista em
projeto e implementação orientada a objetos. Ele foi um dos arquitetos originais da tecnologia
Jini™ e engenheiro chefe da tecnologia JavaSpaces™ da Sun.
James Gosling é um Sun Fellow e CTO do Grupo de Desenvolvimento da Plataforma da Sun
Microsystems. Projetou a linguagem de programação Java original, implementou seu compilador
e a máquina virtual originais, e, mais recentemente, contribuiu para a Real-Time Specification de
Java. Um dos mais respeitados programadores da indústria, ele recebeu o prêmio de Excelência em
Programação da Software Development do ano de 1996.
David Holmes é diretor da DLTech Pty Ltd, localizada em Brisbane, Austrália. Especialista em
sincronização e concorrência, participou do grupo de especialistas JSR-166 que desenvolveu os novos
utilitários de concorrência. Ele também contribuiu para a atualização da Real-Time Specification de
Java e passou os últimos anos trabalhando em uma implementação desta especificação.
A756l Arnold, Ken
A linguagem de programação Java [recurso eletrônico] / Ken Arnold,
Jamoes Gosling, David Holmes ; tradução Maria Lúcia Blank Lisbôa. – 4. ed. –
Dados eletrônicos. – Porto Alegre : Bookman, 2007.
Editado também como livro impresso em 2007.
ISBN 978-85-60031-61-0
1. Computação – Linguagem de programação. I. Gosling, James.
II. Holmes, David. III. Título.
CDU 004.438JAVA
Catalogação na publicação: Juliana Lagôas Coelho – CRB 10/1798
Catalogação na publicação: Júlia Angst Coelho – CRB 10/1712
A unidade fundamental de programação na linguagem de programação Java é a clas-
se, mas a unidade fundamental de projeto orientado a objetos é o tipo. Enquanto clas-
ses definem tipos, é bastante útil e poderoso poder definir um tipo sem definir uma
classe. Interfaces definem tipos em uma forma abstrata como uma coleção de métodos
ou outros tipos que formam o contrato para aquele tipo. Interfaces não contêm imple-
mentações e você não pode criar instâncias de uma interface. Em vez disso, classes po-
dem expandir seus próprios tipos pela implementação de uma ou mais interfaces. Uma
interface é uma expressão de projeto puro, enquanto que uma classe é uma mistura de
projeto e implementação.
Uma classe pode implementar os métodos de uma interface de qualquer maneira que o
projetista da classe escolher. Uma interface, portanto possui muitas mais possíveis imple-
mentações do que uma classe. Cada classe principal em uma aplicação deve ser uma im-
plementação de alguma interface que captura o contrato daquela classe.
Classes podem implementar mais de uma interface. A linguagem de programação Java
permite herança múltipla de interface, mas somente herança simples de implementação –
uma classe pode estender somente uma outra classe. Classes podem usar herança de in-
terfaces para expandir seu tipo e então usar, por exemplo, composição para fornecer uma
implementação para estas interfaces. Este projeto permite a flexibilidade de tipo da he-
rança múltipla ao mesmo tempo em que evita os perigos da herança múltipla de imple-
mentação, ao custo de algum trabalho adicional para o programador.
Em uma dada classe, as classes que são estendidas e as interfaces que são implementa-
das são coletivamente chamadas de supertipos, e, do ponto de vista dos supertipos, uma
nova classe é um subtipo. A nova classe inclui todos os seus supertipos, de modo que a
referência a um objeto do subtipo pode ser usada polimorficamente em qualquer lugar
onde uma referência a um objeto de qualquer de seus supertipos (classe ou interface) é
requerida. Declarações de interfaces criam nomes de tipos assim como fazem as decla-
rações de classes; você pode usar o nome de uma interface como o nome de tipo de
uma variável, e qualquer objeto cuja classe implemente esta interface pode ser atribuí-
do a esta variável.
C A P Í T U L O 4
Interfaces
“Reger” é quando você desenha “figuras” em nenhum lugar – com sua batuta
ou com suas mãos – que são interpretadas como “mensagens instrucionais”
por rapazes vestindo gravatas borboleta que desejariam estar pescando.
– Frank Zappa
4.1 Um Exemplo de uma Interface Simples
Muitas interfaces simples definem uma propriedade que é atribuível a diversos objetos de
diferentes classes. Estas propriedades são frequentemente definidas em termos de um ob-
jeto estar “apto” a fazer algo. Por exemplo, nos pacotes padrões existem diversas interfa-
ces de “habilidade”, tais como;
• Cloneable – objetos deste tipo suportam clonagem, como você aprendeu com
detalhes na página 114.
• Comparable – objetos deste tipo possuem um ordenamento que permite que se-
jam comparados.
• Runnable – objetos deste tipo representam uma unidade de trabalho, que muitas ve-
zes podem ser executadas em um fluxo de controle independente (ver Capítulo 14).
• Serializable – objetos deste tipo podem ser escritos em um stream de bytes deobjetos para serem remetidos para uma nova máquina virtual, ou para armazena-
mento persistente e posterior reconstituição para um objeto vivo (ver “Serializa-
ção de Objetos” nas páginas 492-493).
Vamos examinar com mais detalhes a interface Comparable. Esta interface pode ser im-
plementada por qualquer classe cujos objetos podem ser comparados uns com os outros de
acordo com o “ordenamento natural” da classe. A interface contém um único método:
public interface Comparable<T> {
int compareTo(T obj);
}
Uma declaração de interface é similar a uma declaração de classe, exceto que a palavra-
chave interface é usada em lugar de class. Também existem regras especiais que go-
vernam os membros de uma interface, como em breve você vai aprender.
O método compareTo usa como argumento um único objeto do tipo T e o compara ao
objeto atual (esperado ser também do tipo T), retornando um inteiro negativo, nulo ou
positivo, se o objeto atual é menor do que, igual a ou maior do que o argumento, res-
pectivamente.
Considere uma variação da classe Point que introduzimos no Capítulo 1. O ordenamen-
to natural para pontos poderia ser a sua distância da origem. Poderíamos então tornar
Comparable objetos Point:
class Point implements Comparable<Point> {
/** Referência da origem que nunca muda */
private static final Point ORIGIN = new Point();
private int x, y;
//... definição de construtores, métodos de configuração e
de acesso
public double distance(Point p) {
int xdiff = x – p.x;
128 A LINGUAGEM DE PROGRAMAÇÃO JAVA
int ydiff = y – p.y;
return Math.sqrt(xdiff * xdiff + ydiff * ydiff);
}
public int compareTo(Point p) {
double pDist = p.distance(ORIGIN);
double dist = this.distance(ORIGIN);
if (dist > pDist)
return 1;
else if (dist == pDist)
return 0;
else
return -1;
}
}
Primeiro declaramos que Point é uma classe Comparable. A classe identifica os ti-
pos de interface que ela implementa relacionando-os após a palavra-chave imple-
ments, antes que o corpo da classe seja definido (e após a cláusula extends). Todas
estas interfaces são as superinterfaces da classe. A classe deve providenciar uma imple-
mentação para todos os métodos definidos em suas superinterfaces, ou senão a classe
deve ser declarada como abstract, e assim exigindo que qualquer subclasse não abs-
trata os implemente.
O único método que necessitamos implementar para a interface Comparable é compa-
reTo, e para realmente comparar dois pontos simplesmente comparamos as suas distân-
cias em relação à origem.
Interfaces introduzem nomes de tipos assim como fazem as classes, de modo que você
pode declarar variáveis destes tipos. Por exemplo:
Comparable<Point> p1;
De fato, muito do poder das interfaces provém da declaração e uso de variáveis somente
do tipo da interface, em vez de algum tipo específico de classe. Por exemplo, você pode
definir uma rotina sort de uso geral, que pode ordenar qualquer array de objetos Com-
parable sem se preocupar com o que a classe desses objetos é na realidade – todos os
objetos do array devem, naturalmente, ser do mesmo tipo:1
class Sorter {
static Comparable<?>[] sort(Comparable<?>[] list) {
// detalhes de implementação...
return list;
}
}
Referências do tipo interface, entretanto, podem ser usadas somente para acessar mem-
bros daquela interface. Por exemplo, o seguinte irá produzir um erro de compilação:
Comparable<Point> obj = new Point();
double dist = obj.distance(p1); // INVÁLIDO: Comparable não
// possui método distance
CAPÍTULO 4 • INTERFACES 129
1 No capítulo 11 você aprende sobre métodos genéricos, e sort realmente deveria ser definido como um desses.
Se você quiser tratar obj como um objeto Point você deve fazer uma coerção explícita pa-
ra este tipo.
Você pode invocar quaisquer dos métodos de Object usando uma referência do tipo de uma
interface porque não importa quais interfaces o objeto implemente, ele sempre será um Ob-
ject e assim possui aqueles métodos. De fato, qualquer interface que não estende outra in-
terface explicitamente possui membros que são os métodos públicos de Object (a menos
que a interface os sobrescreva explicitamente). Portanto, o seguinte é legal:
String desc = obj.toString();
como uma atribuição de uma referência de interface a uma referência de Object.
4.2 Declarações de Interfaces
Uma interface é declarada usando a palavra-chave interface, fornecendo um nome à
interface e relacionando os membros da interface entre chaves.
Uma interface pode declarar três tipos de membros:
• constantes (campos)
• métodos
• classes e interfaces aninhadas
Todos os membros da interface são implicitamente públicos, mas, por convenção, o mo-
dificador public é omitido. Ter membros não públicos em uma interface teria pouco
sentido; onde isto faz sentido você pode usar a acessibilidade da própria interface para
controlar o acesso aos membros da interface.
Vamos postergar a discussão de classes e interfaces aninhadas até o Capítulo 5.
4.2.1 Constantes de Interfaces
Uma interface pode declarar constantes denominadas. Estas constantes são definidas co-
mo campos, mas são implicitamente public, static e final – novamente, por con-
venção, os modificadores são omitidos nas declarações de campos. Estes campos devem
ter inicializadores – brancos finais não são permitidos. Anotações também podem ser
aplicadas aos campos – ver Capítulo 15.
Visto que interfaces não contêm detalhes de implementação, elas não podem definir cam-
pos normais – tal definição estaria ditando uma política de implementação para classes
que escolhessem implementar a interface. Interfaces podem definir constantes denomina-
das porque elas são úteis no projeto de tipos. Por exemplo, uma interface que possui di-
ferentes níveis de verbosidade em seu contrato pode definir o seguinte:
interface Verbose {
int SILENCIOSA = 0;
int CONCISA = 1;
int NORMAL = 2;
int PROLIXA = 3;
void setVerbosity(int level);
int getVerbosity();
}
130 A LINGUAGEM DE PROGRAMAÇÃO JAVA
SILENCIOSA, CONCISA, NORMAL e PROLIXA podem ser passadas ao método setVerbo-
sity, dando nomes a valores constantes que representam significados específicos. Nes-
te caso particular, os níveis de verbosidade podem ser representados mais efetivamente
por constantes de um tipo enumerado aninhado dentro da interface Verbose. Tipos enu-
merados são discutidos no Capítulo 6.
Se você necessita dados compartilhados e modificáveis em sua interface, você pode con-
seguir isto usando uma constante denominada que se refere a um objeto que contém o da-
do. Uma classe aninhada é boa para definir tal objeto, de modo que postergaremos um
exemplo até o Capítulo 5.
4.2.2 Métodos de Interfaces
Os métodos declarados em uma interface são implicitamente abstratos porque nenhuma
implementação é, ou pode ser, dada a eles. Por esta razão, o corpo do método é simples-
mente um ponto-e-vírgula após o cabeçalho do método. Por convenção, o modificador
abstract é omitido na declaração do método.
Nenhum outro modificado, de método é permitido em uma declaração de método de in-
terface, exceto para anotações – ver Capítulo 15. Eles são implicitamente public e as-
sim não podem ter nenhum outro modificador de acesso. Eles não podem ter modificado-
res que definem características de implementação – tais como native, synchronized
ou strictfp – porque uma interface não dita implementação e eles não podem ser fi-
nal porque ainda não foram implementados. Naturalmente, a implementação destes mé-
todos dentro de uma classe específica pode ter qualquer um destes modificadores. Méto-
dos de interfaces nunca podem ser métodos static porque métodos static não podem
ser abstract.
4.2.3 Modificadores de Interfaces
Uma declaração de interface pode ser precedida de modificadores de interface:
• anotações – anotações e tipos de anotação são discutidos no Capítulo 15.
• pública – uma interface public é publicamente acessível. Sem este modificador,
uma interface somente é acessível dentro de seu próprio pacote.
• abstratas – todas as interfaces são implicitamente abstract porque seusméto-
dos são todos abstratos – eles não possuem implementação. Novamente, por con-
venção, o modificador abstract é sempre omitido.
• ponto-flutuante estrito – uma interface declarada strictfp possui toda a
aritmética de ponto-flutuante, definida dentro da interface, avaliada estrita-
mente. Isto se aplica a expressões de inicialização para constantes e para to-
dos os tipos aninhados declarados na interface. Em contraste com classes, is-
to não implica que cada método na interface seja implicitamente strictfp,
porque este é um detalhe de implementação. Ver Seção 9.1.3 nas páginas 199-
200 para detalhes.
Quando diversos modificadores são aplicados à mesma interface, recomendamos usar
a ordem relacionada acima.
CAPÍTULO 4 • INTERFACES 131
4.3 Estendendo Interfaces
Interfaces podem ser estendidas usando a palavra-chave extends. Interfaces, diferente-
mente de classes, podem estender mais de uma interface:
public interface SerializableRunnable
extends java.io.Serializable, Runnable
{
//...
}
A interface SerializableRunnable estende java.io.Serializable e Runna-
ble ao mesmo tempo, o que significa que todos os métodos e constantes definidos nes-
tas interfaces agora fazem parte do contrato de SerializableRunnable, juntamen-
te com todos os novos métodos e constantes que ela define. As interfaces que são esten-
didas são as superinterfaces da nova interface e a nova interface é uma subinterface de
suas superinterfaces.
Visto que interfaces suportam herança múltipla, o grafo de herança pode conter diversos
caminhos para a mesma superinterface. Isto significa que constantes e métodos podem
ser acessados por diversos caminhos. Entretanto, visto que interfaces não definem imple-
mentação de métodos e não fornecem campos de objetos, não existem dificuldades con-
cernentes a esta forma de herança múltipla.
132 A LINGUAGEM DE PROGRAMAÇÃO JAVA
Encerra aqui o trecho do livro disponibilizado para
esta Unidade de Aprendizagem. Na Biblioteca Virtual
da Instituição, você encontra a obra na íntegra.
M149d Machado, Rodrigo Prestes.
Desenvolvimento de software III : programação de sistemas
web orientada a objetos em Java [recurso eletrônico] /
Rodrigo Prestes Machado, Márcia Häfele Islabão Franco,
Silvia de Castro Bertagnolli. – Porto Alegre : Bookman, 2016.
Editado como livro impresso em 2016.
ISBN 978-85-8260-371-0
1. Informática. 2. Desenvolvimento de software – Java.
I. Franco, Márcia Häfele Islabão. II. Bertagnolli, Rodrigo Prestes.
III. Título.
CDU 004.438
Catalogação na publicação: Poliana Sanchez de Araujo – CRB 10/2094
Modelagem de sistemas
orientada a objetos
A modelagem de sistemas exerce um importante papel no processo de
desenvolvimento de sistemas. Durante a modelagem, são tomadas as decisões
sobre a estrutura e o comportamento que o sistema irá apresentar. A UML é uma
linguagem de modelagem padrão, desenvolvida para o paradigma orientado
a objetos, que permite que essas definições estruturais e comportamentais
do sistema sejam documentadas no formato de diagramas. Neste capítulo,
veremos em detalhes os diagramas de casos de uso, de classes e de sequência,
e também analisaremos exemplos de aplicação.
capítulo 2
Objetivos de aprendizagem
Reconhecer os principais aspectos e elementos do diagrama de
casos de uso.
Definir os principais elementos e características do diagrama de
classes.
Identificar os principais elementos e características do diagrama
de sequência.
Analisar os exemplos de aplicação.
Márcia Häfele Islabão Franco
Carlos Tadeu Queiroz de Morais
28
Introdução
A modelagem de sistemas exerce um papel fundamental em todas as etapas do
processo de desenvolvimento de sistemas. Durante a modelagem, são tomadas
decisões sobre a estrutura e o comportamento do sistema.
A Unified Modeling Language (UML), ou Linguagem de Modelagem Unificada, desen-
volvida para o paradigma orientado a objetos e independente de processo de desen-
volvimento, permite a visualização, a especificação, a construção e a documentação dos
artefatos de um sistema. Ela possibilita que as definições estruturais e comportamentais
do sistema sejam documentadas no formato de diagramas, sendo composta por treze
diagramas, responsáveis por fornecerem diferentes visões do sistema.
Os diagramas da UML se subdividem em diagramas estruturais e diagramas compor-
tamentais. Os diagramas estruturais tratam de aspectos estáticos do sistema, per-
mitindo modelar aspectos relacionados à estrutura do sistema. Esses diagramas são
os seguintes: diagrama de classes, diagrama de objetos, diagrama de componentes,
diagrama de estrutura composta, diagrama de implantação e diagrama de pacotes.
Já os diagramas comportamentais estão relacionados com aspectos dinâmicos
do sistema, possibilitando modelar o sistema do ponto de vista comportamen-
tal. Esses diagramas são os seguintes: diagrama de casos de uso, diagrama de se-
quência, diagrama de comunicação, diagrama de máquina de estados, diagrama
de atividades, diagrama de temporização e diagrama de visão geral da interação.
Este capítulo tem por objetivo apresentar, de forma geral, os principais conceitos,
elementos e características do diagrama de classes, diagrama de casos de uso e
diagrama de sequência. Esses diagramas foram escolhidos por serem os mais utili-
zados na prática e por servirem de base para construção de outros diagramas.
Diagrama de casos de uso
O diagrama de casos de uso é um diagrama comportamental da UML, sendo o mais
utilizado entre os diagramas comportamentais. Além disso, ele serve como base
para a construção de outros diagramas da UML.
O diagrama de casos de uso é utilizado no início da modelagem do sistema,
geralmente nas fases de levantamento e análise de requisitos. Ele desempenha um
papel importante, pois possibilita a especificação, a visualização e a documentação
de funcionalidades e características do sistema.
IMPORTANTE
O diagrama de casos de
uso permite especificar,
visualizar e documentar
funcionalidades e
características do sistema.
29
Os principais elementos do diagrama de casos de uso são os atores, os casos de
uso e os relacionamentos. Os atores representam os usuários do sistema (usuá-
rios humanos, dispositivos de hardware e subsistemas), que interagem, por meio
de relacionamentos, com os casos de uso, os quais representam os requisitos fun-
cionais do sistema. Dessa forma, esse diagrama fornece uma visão da interação
entre os requisitos funcionais do sistema, os usuários e os demais componentes
externos.
IMPORTANTE
As fases do processo de desenvolvimento de software são levantamento de requisitos, análise de re-
quisitos, projeto, implementação, testes e implantação. A fase de levantamento de requisitos tem por
objetivo identificar as funcionalidades e as características que o sistema deve apresentar para que sejam
atendidas as necessidades do cliente. A fase de análise de requisitos é responsável por analisar detalha-
damente os dados levantados na fase de levantamento de requisitos. Nela, modelos são construídos
com o intuito de representar as características do sistema.
As próximas seções apresentam uma visão geral dos principais elementos e concei-
tos aplicados no diagrama de casos de uso. Os exemplos ilustrados, com o objetivo
de explicar as características do diagrama, se baseiam em partes de dois sistemas,
sendo estes: sistema de controle acadêmico e o sistema de microblog.
Atores
No diagrama de casos de uso, os atores são entidades externas, ou seja, não são
entidades componentes do sistema, mas interagem com o sistema. Eles podem ser
usuários do sistema, dispositivos de hardware ou outro sistema que realizam as
operações do sistema. São representados por um boneco-palito, que contém uma
breve descrição do papel que ele assume no sistema, conforme ilustra a Figura 2.1.
No exemplo, o ator recebe o nome de Usuário.
Usuário
Figura 2.1 Exemplo de ator no diagramade casos de uso.
Fonte: Autores.
DEFINIÇÃO
Os requisitos funcionais
são os requisitos
diretamente ligados à
funcionalidade do sistema.
30
Casos de uso
Na UML, o comportamento do sistema é modelado por meio de casos de uso que
representam os requisitos funcionais do sistema, ou seja, descrevem um conjunto
de operações que um sistema executa a fim de produzir um resultado para um ator.
Conforme ilustra a Figura 2.2, um caso de uso é representado por uma elipse que
contém seu nome. No exemplo, o caso de uso se refere à operação Cadastrar Curso.
Cadastrar Curso
Figura 2.2 Exemplo de caso de uso.
Fonte: Autores.
Casos de uso podem ser utilizados como técnica de levantamento de requisitos,
durante a fase de levantamento de requisitos, a fim de identificar o comportamen-
to esperado do sistema.
Relacionamentos
Nos diagramas de casos de uso, os relacionamentos representam as interações
entre atores e casos de uso. Os principais relacionamentos são associação, inclusão,
extensão e generalização. A seguir, abordamos cada um deles.
Associação
No diagrama de casos de uso, uma associação ocorre somente entre atores e casos
de uso. Esse tipo de relacionamento indica que um ator interage com uma funcio-
nalidade (ou operação) do sistema, que é representada por um caso de uso. Essa
interação pode se dar por meio da execução de uma operação ou por meio do rece-
bimento de algum resultado produzido por uma operação, indicando, desse modo,
uma comunicação entre atores e casos de uso.
A associação é representada por uma linha que une o ator ao caso de uso, conforme
a Figura 2.3.
Aluno
Realizar Matrícula
Disciplina
Figura 2.3 Associação entre ator e caso de uso.
Fonte: Autores.
ATENÇÃO
O nome de um caso de
uso deve ser um verbo ou
uma expressão verbal que
indique o comportamento
do caso de uso. As
palavras que compõem
o nome devem começar
com letra maiúscula, por
exemplo, Cadastrar Aluno,
Visualizar Seguidores.
DICA
As técnicas de
levantamento de requisitos
auxiliam na identificação
de funcionalidades e
características do sistema.
Algumas das técnicas
mais utilizadas são
brainstorming, entrevistas
e questionários.
IMPORTANTE
No relacionamento
de associação, ocorre
interação entre um ator
e uma funcionalidade do
sistema.
31
No exemplo, o ator é denominado Aluno, o qual interage, por meio de uma asso-
ciação, com o caso de uso Realizar Matrícula Disciplina. Isso representa que o alu-
no poderá executar no sistema a operação de realizar a matrícula nas disciplinas.
Inclusão
Outro tipo de relacionamento que ocorre somente entre casos de uso é a inclusão
(include). Ela indica que uma operação depende de outra para ser executada.
Nesse tipo de relacionamento, um caso de uso base incorpora o comportamento
de outro caso de uso, ou seja, a execução de um caso de uso base obriga a execução
de outro caso de uso.
O relacionamento de inclusão é representado por uma linha tracejada que contém
uma seta aberta e estereotipado como <<include>>.
Observa-se no exemplo da Figura 2.4 que os relacionamentos de inclusão partem
do caso de uso Registrar Aula (caso de uso base), e a seta aponta para os casos de
uso Registrar Frequência e Registrar Conteúdo (casos de uso que serão incorpora-
dos ao base). O ator Professor só poderá registrar a aula se registrar a frequência e
o conteúdo trabalhado.
Professor
Registrar Aula
<<include>>
<<include>>
Registrar
Frequência
Registrar
Conteúdo
Figura 2.4 Relacionamento de inclusão entre casos de uso.
Fonte: Autores.
Extensão
O relacionamento de extensão (extend) é um tipo de relacionamento que tam-
bém ocorre somente entre casos de uso. Ele é semelhante à inclusão, porém um
caso de uso base poderá ou não incorporar o comportamento do caso de uso es-
tendido. Nesse caso, o que determinará se o caso de uso será ou não incorporado
é o resultado de um teste (ou condição, ou validação) que está associado ao re-
lacionamento. Dessa forma, pode-se dizer que a extensão está relacionada a um
comportamento opcional.
O relacionamento de extensão é representado por uma linha tracejada com uma
seta aberta e estereotipada como <<extend>>, conforme a Figura 2.5.
IMPORTANTE
O relacionamento de
inclusão indica uma
dependência obrigatória
entre operações.
IMPORTANTE
No relacionamento
de extensão, um caso
de uso base pode
ou não incorporar o
comportamento do caso
de uso estendido.
D
e
s
e
n
v
o
lv
im
e
n
to
d
e
S
o
ft
w
a
re
I
II
32
Usuário
Autenticar
<<extend>>
{caso o usuário
não possua
cadastro}
Criar Conta
Figura 2.5 Relacionamento de extensão.
Fonte: Autores.
O ator Usuário pode realizar a operação Autenticar (caso de uso base) para acessar
o sistema. Entretanto, caso o usuário ainda não possua cadastro, ele poderá realizar
a operação de Criar Conta (caso de uso estendido).
Observa-se no exemplo da Figura 2.5 a restrição “{caso o usuário não possua cadas-
tro}” associada ao relacionamento. O uso de restrições é uma boa prática a ser ado-
tada, pois muitas vezes pode não ficar evidente a condição para que a operação,
que representa o caso de uso estendido, seja executada.
A Figura 2.6 apresenta um exemplo em que um ator Usuário poderá realizar a ope-
ração de Ler Mensagem, sendo esta o caso de uso base. O exemplo apresenta a res-
trição “{caso o usuário queira responder a mensagem}”, que auxilia na compreensão
da condição associada à relação de extensão. Observa-se que, se a condição for
satisfeita, a operação Responder Mensagem, que representa o caso de uso estendi-
do, será incorporada ao caso de uso base. O uso de pontos de extensão (extension
points) auxilia na identificação dos casos de uso que poderão ser incorporados a
outros casos de uso, se as condições forem atendidas.
Usuário
Ler Mensagem
Responder
Mensagemextension points
Responder
<<extend>>
{caso o usuário
queira responder
a mensagem}
Figura 2.6 Uso de pontos de extensão.
Fonte: Autores.
Generalização
A generalização (ou especialização) é um tipo de relacionamento utilizado entre
atores e entre casos de uso. Quando aplicada entre atores, temos um ator geral (de-
nominado pai) e um ou mais atores especializados (denominados filhos). É muito
utilizada para representar diferentes níveis de acesso ao sistema.
33
A Figura 2.7 apresenta três atores, que são Aluno, Aluno Curso Técnico e Aluno Cur-
so Superior. Os três atores do exemplo possuem características comuns. Os atores
especializados podem realizar a operação representada pelo caso de uso Cursar
Disciplina. Além disso, podem ainda realizar diferentes operações no sistema: o
ator Aluno Curso Técnico pode Realizar Estágio e o ator Aluno Curso Superior pode
Entregar Trabalho Conclusão.
Aluno Curso SuperiorAluno Curso Técnico
Aluno
Realizar
Estágio
Cursar
Disciplina
Entregar Trabalho
Conclusão
Figura 2.7 Generalização entre atores.
Fonte: Autores.
Na generalização entre atores, um caso de uso (denominado filho) herda o compor-
tamento de outro caso de uso (denominado pai). Esse relacionamento é utilizado
quando existem dois ou mais casos de uso com características semelhantes.
Na Figura 2.8, os casos de uso especializados Cadastrar Professor e Cadastrar Téc-
nico Administrativo herdam o comportamento do caso de uso geral Cadastrar
Servidor.
Cadastrar Servidor
Cadastrar
Professor
Cadastrar Técnico
Administrativo
Figura 2.8 Generalização entre casos de uso.
Fonte: Autores.
IMPORTANTE
No relacionamento
de generalização,
ocorre a herança do
comportamento de
um caso de uso em
relação a outro.
D
e
s
e
n
v
o
lv
im
e
n
to
d
e
S
o
ft
w
a
re
I
II
34
Descrição dos casos de uso
Os casos de uso representam as funcionalidades do sistema, mas não fornecem
qualquer informação acerca da sua implementação. Assim, muitas vezes informa-
ções que auxiliem na compreensão dos casos são fundamentais. Dessa forma, é
necessária a elaboraçãoda descrição dos casos de uso.
Não existe um formato único a ser aplicado na descrição dos casos de uso. Reco-único a ser aplicado na descrição dos casos de uso. Reco- a ser aplicado na descrição dos casos de uso. Reco-
menda-se apenas que a descrição contenha, no mínimo, nome, descrição, atores
envolvidos, fluxo de eventos (fluxo principal, fluxo alternativo e fluxo de exceção) e
indicação dos pontos de extensão.
O Quadro 2.1 apresenta o exemplo de descrição do caso de uso Autenticar referen-
te à Figura 2.5.
IMPORTANTE
Como os casos de uso
não fornecem qualquer
informação sobre a
implementação do
sistema, é fundamental
realizar a descrição.
Quadro 2.1 Descrição do caso de uso Autenticar
Nome do caso de uso Autenticar
Descrição Descreve os passos necessários para o usuário
acessar o sistema.
Atores envolvidos Usuário
Fluxo principal
Ações do Usuário Ações do Sistema
1. Informa o login de acesso ao sistema.
2. Verifica se existe uma conta referente a esse
login.
3. Solicita a senha.
4. Informa a senha.
5. Realiza a autenticação.
6. Exibe a página principal do sistema.
Fluxo alternativo I – Usuário não lembra a senha
Ações do Usuário Ações do Sistema
1. Aciona uma opção informando que esqueceu
sua senha.
2. Solicita o e-mail do usuário.
3. Informa seu e-mail.
4. Emite e-mail com link para redefinir a senha.
35
Fluxo de exceção I – Conta inexistente
Ações do Usuário Ações do Sistema
1. Exibe mensagem ao usuário informando que
uma conta deve ser cadastrada.
2. Executa ponto de extensão PE1.
Fluxo de exceção II – Senha inválida
Ações do Usuário Ações do Sistema
1. Informa ao usuário que a senha está
incorreta.
Ponto de extensão
PE1. Caso de uso Criar Conta
Quadro 2.1 Continuação
No exemplo, a descrição é composta por:
• Nome do caso de uso: Serve para identificar o caso de uso.
• Descrição: Descreve brevemente o objetivo do caso de uso.
• Atores envolvidos: São os atores que interagem com o caso de uso.
• Fluxo de eventos: Descreve o conjunto de ações que ocorrem no caso de
uso. Nesse exemplo, o fluxo de eventos é composto por:
– Fluxo principal: Descreve as ações que frequentemente são realizadas
quando a operação representada pelo caso de uso for solicitada.
– Fluxo alternativo: Descreve ações alternativas que podem ocorrer.
– Fluxo de exceção: Descreve as validações do caso de uso.
• Ponto de extensão: Refere-se ao relacionamento de extensão. Nesse caso,
ele referencia o caso de uso que poderá ser incorporado ao caso de uso base,
dependendo do retorno da validação.
Observa-se, no exemplo, que não é descrito o fluxo de eventos do caso de uso Criar
Conta. Apenas se faz referência a ele na descrição do caso de uso base. Assim, ela-ência a ele na descrição do caso de uso base. Assim, ela-ncia a ele na descrição do caso de uso base. Assim, ela-
bora-se uma nova descrição, conforme ilustra o Quadro 2.2.
ATENÇÃO
Na descrição de um caso
de uso que envolve uma
relação de inclusão, não
se descreve várias vezes o
mesmo fluxo de eventos.
Nesse caso, apenas se
referencia o caso de uso
e se realiza a descrição
separadamente.
D
e
s
e
n
v
o
lv
im
e
n
to
d
e
S
o
ft
w
a
re
I
II
36
Quadro 2.2 Descrição do caso de uso Criar Conta
Nome do caso de uso Criar Conta
Descrição Descreve os passos necessários para o usuário
realizar o cadastro no sistema.
Atores envolvidos Usuário
Fluxo principal
Ações do Usuário Ações do Sistema
1. Fornece os dados de cadastro.
2. Realiza o cadastro do usuário.
Fluxo de exceção I – Usuário já cadastrado
Ações do Usuário Ações do Sistema
1. Exibe uma mensagem informando que
já existe usuário cadastrado com o
mesmo CPF.
Fluxo de exceção II – Login existente
Ações do Usuário Ações do Sistema
1. Comunica ao usuário que o login informado
já existe.
2. Habilita campo para cadastro de novo
login.
Fluxo de exceção III – Senha fraca
Ações do Usuário Ações do Sistema
1. Informa ao usuário que a senha fornecida
não é segura e que deve conter ao menos
seis caracteres.
2. Habilita campo para cadastro de nova
senha.
Fluxo de exceção IV – Dados obrigatórios ausentes
Ações do Usuário Ações do Sistema
1. Informa ao usuário que os dados obrigatórios
precisam ser preenchidos.
c
a
p
ít
u
lo
2
M
o
d
e
la
g
e
m
d
e
s
is
te
m
a
s
o
ri
e
n
ta
d
a
a
o
b
je
to
s
37
A Figura 2.9 ilustra o diagrama de casos de uso referente ao exemplo do sistema de
microblog. Foram abordadas apenas algumas funcionalidades do sistema com o
intuito de o diagrama não ficar muito extenso e, assim, dificultar o entendimento.
No exemplo, o ator, responsável por realizar ou solicitar operações no sistema, é o
Usuário. O Usuário interage, por meio de associações, com os casos de uso Auten-
ticar, Criar Conta, Pesquisar Usuário, Seguir Usuário, Deixar Seguir, Retornar Segui-
dos, Retornar Seguidores, Ler Mensagem, Citar Mensagem, Responder Mensagem,
Reenviar Mensagem, Compartilhar Mensagem, Compartilhar por e-mail e Compar-
tilhar no Facebook, que representam as funcionalidades do sistema.
Observa-se um relacionamento de extensão entre os casos de uso Autenticar e
Criar Conta, indicando que o usuário, ao se autenticar no sistema, poderá ser dire-
cionado para realizar o cadastro, caso não o possua.
Notam-se também relacionamentos de extensão entre o caso de uso Ler Mensagem
e os casos de uso Citar Mensagem, Responder Mensagem, Reenviar Mensagem e
Compartilhar Mensagem, indicando que o usuário, após ler a mensagem, poderá
realizar qualquer uma dessas operações, caso desejar.
No exemplo do sistema de microblog, o relacionamento de generalização indica
que os casos de uso Compartilhar por e-mail e Compartilhar no Facebook são casos
de uso especializados do caso de uso geral Compartilhar Mensagem.
ATENÇÃO
Na descrição de um caso
de uso especializado,
também não é necessário
descrever o mesmo fluxo
de eventos do caso de uso
geral para todos os casos
de uso especializados,
pois toda estrutura
de um caso de uso
generalizado é herdada
pelos casos de uso
especializados, incluindo
os relacionamentos de
inclusão e extensão do
caso de uso generalizado.
Usuário
Pesquisar
Usuário
Citar
Mensagem
Responder
Mensagem
Ler Mensagem
Reenviar
Mensagem
Compartilhar
por e-mail
Compartilhar
no Facebook
Compartilhar
Mensagem
Seguir Usuário
Autenticar
Deixar Seguir
Criar Contaextension points
Criar conta usuário
extension points
Citar
Responder
Reenviar
Compartilhar
Retornar
Seguidores
Retornar
Seguidos
<<extend>>
<<extend>>
<<extend>> <<extend>>
<<extend>>
Figura 2.9 Diagrama de caso de uso do sistema de microblog.
Fonte: Autores.
O Quadro 2.3 apresenta a descrição do caso de uso Ler Mensagem.
D
e
s
e
n
v
o
lv
im
e
n
to
d
e
S
o
ft
w
a
re
I
II
38
Quadro 2.3 Descrição do caso de uso Ler Mensagem
Nome do caso de uso Autenticar
Descrição Descreve os passos necessários para o usuário
ler uma mensagem no sistema.
Atores envolvidos Usuário
Fluxo Principal
Ações do Usuário Ações do Sistema
1. Aciona a opção de ler mensagem.
2. Exibe a íntegra da mensagem.
3. Exibe as seguintes opções: Responder
Mensagem, Reenviar Mensagem, Citar
Mensagem, Compartilhar Mensagem.
Fluxo Alternativo I – Responder mensagem
Ações do Usuário Ações do Sistema
1. Executa ponto de extensão PE1.
Fluxo Alternativo II – Reenviar mensagem
Ações do Usuário Ações do Sistema
1. Executa ponto de extensão PE2.
Fluxo Alternativo III – Citar mensagem
Ações do Usuário Ações do Sistema
1. Executa ponto de extensão PE3.
Fluxo Alternativo IV – Compartilhar mensagem
Ações do Usuário Ações do Sistema
1. Executa ponto de extensão PE4.
Ponto de extensão
PE1. Caso de uso Responder Mensagem
PE2. Caso de uso Reenviar Mensagem
PE3. Caso de uso Citar Mensagem
PE4. Caso de uso Compartilhar Mensagem
Neste exemplo, é apresentada apenas a descrição do caso de uso Ler Mensagem.Entretanto, é importante destacar que, para cada ponto de extensão referenciado
na descrição do caso de uso Ler Mensagem, deve-se elaborar uma descrição corres-
pondente, assim como para todos os outros casos de uso do diagrama.
39
Diagrama de classes
O diagrama de classes é um diagrama estrutural da UML que tem como objetivo
apresentar uma visão estática de como as classes que irão compor o sistema se rela-
cionam, complementam-se e transmitem informações entre si. Entre os diagramas
estruturais da UML, sem dúvidas é o principal e o mais utilizado na modelagem de
sistemas orientada a objetos. Além disso, serve como base para a construção de
outros diagramas da UML.
Nesta seção, são apresentados, de forma geral, os principais conceitos e elementos
utilizados no diagrama de classes. Os exemplos que serão apresentados também
foram construídos com base em partes de um sistema de controle acadêmico e em
um sistema de microblog.
Classes
O diagrama de classes é composto pelas classes e pelos relacionamentos existentes
entre elas. Conforme apresentado no Capítulo 1, uma classe é a descrição de um
molde que especifica os atributos (ou propriedades) e o comportamento para um
conjunto de objetos. Um objeto é uma instância de uma classe. O comportamento
de uma classe é definido pelas funções que os objetos podem realizar, as quais
recebem o nome de operações. Na UML, as classes são representadas por um re-
tângulo que pode conter até três partições. Na Figura 2.10, há o exemplo de uma
classe denominada Aluno, que será explicada a seguir.
Aluno
– matricula : long
– nome : String
+ cadastrar(nome : String) : Aluno
+ pesquisar(matricula : long) : Aluno
+ pesquisar(nome : String) : Aluno
+ editar(nome : String) : boolean
Figura 2.10 Exemplo de classe.
Fonte: Autores.
A primeira partição define o nome da classe. No exemplo, a classe recebe o nome de
Aluno. O nome da classe deve estar de acordo com o domínio do problema que está
em modelagem. Geralmente o nome é um substantivo ou uma expressão breve com
o primeiro caractere maiúsculo. As palavras não devem ser acentuadas e, no caso de
uma expressão, não deve haver espaço entre elas, por exemplo, DiarioDeClasse.
DICA
O diagrama de classes
geralmente é construído
na fase de projeto, mas
também é comum ser
usado na fase de análise
de requisitos.
DICA
O nome de uma classe
deve ser um substantivo
ou uma expressão breve
sem acento, com a
primeira letra maiúscula e
sem separação entre
as palavras.
D
e
s
e
n
v
o
lv
im
e
n
to
d
e
S
o
ft
w
a
re
I
II
40
A segunda partição define os atributos da classe e seus tipos de dados. No exem-
plo, a classe Aluno possui os atributos matricula do tipo long e nome do tipo
String. Esses atributos têm visibilidade privada e são representados pelo símbolo
de menos (-) na frente dos atributos, indicando assim que não podem ser utiliza-
dos por outra classe do programa. Os tipos de dados que podem ser utilizados são
apresentados no Capítulo 3. O nome dos atributos também deve ser um substanti-
vo ou expressão breve, que deve representar as propriedades da classe. Diferente-
mente das classes, o nome dos atributos deve começar com caracteres minúsculos,
por exemplo: nome ou dataIngresso.
A terceira partição define as operações da classe. No exemplo, as operações da clas-
se Aluno com suas respectivas assinaturas e valores de retorno são:
• cadastrar(nome : String): Aluno: A operação cadastrar recebe
como parâmetro uma String e retorna um objeto do tipo Aluno.
• pesquisar(matricula : long) : Aluno: A operação pesquisar recebe
como parâmetro um long e retorna um objeto do tipo Aluno.
• pesquisar(nome : String): Aluno: A operação pesquisar recebe como
parâmetro uma String e retorna um objeto do tipo Aluno. As duas operações
pesquisar realizam a mesma função, o que difere uma da outra é o parâmetro
utilizado na pesquisa.
• editar(nome : String): boolean: A operação editar recebe como
parâmetro uma String e retorna um boolean. Nesse caso, se a execução da
operação estiver correta, retornará true; caso contrário, false.
Nesse exemplo, as operações da classe Aluno possuem visibilidade pública in-
dicada pelo símbolo de mais (+) na frente da operação. Desse modo, podem ser
utilizadas por qualquer classe do programa. Os níveis de visibilidade que podem
ser atribuídos aos atributos e às operações de uma classe são apresentados no
Quadro 2.4.
DICA
O nome de um atributo
deve ser um substantivo
ou uma expressão
breve com a primeira
letra minúscula e sem
separação entre as
palavras.
Quadro 2.4 Níveis de visibilidade de atributos e operações
+ Público
Pode ser acessado por qualquer classe do programa.
– Privado
Utilizado somente pela própria classe.
# Protegido
Utilizado somente pela própria classe e pelas suas subclasses.
~ Pacote
Pode ser acessado pela própria classe ou por qualquer outra classe do mesmo pacote.
41
DICA
Em alguns diagramas, é possível observar classes somente com a primeira partição. Isso ocorre em dia-
gramas nos quais as partições dos atributos e das operações foram ocultadas pelo analista para que o
diagrama não fique muito extenso ou poluído. Pelo mesmo motivo, é comum que as operações das
classes não apresentem parâmetros e retornos. Outra ocorrência possível é a inexistência de atributos e/ou
operações em algumas classes.
Relacionamentos entre classes
No diagrama de classes, os relacionamentos entre as classes são fundamentais,
uma vez que representam de que forma as classes compartilham informações e
como colaboram na execução das operações do sistema.
Na UML, o relacionamento entre as classes determina os diferentes vínculos entre
os objetos. Esses vínculos são determinados pelo tipo de relacionamento, que po-
dem ser por associação, generalização, dependência ou realização.
Esta seção apresenta os principais tipos de relacionamentos, com seus respectivos
conceitos, que podem ser utilizados no diagrama de classes.
Associação binária
A associação binária é um tipo de relacionamento que indica a existência de um
vínculo entre os objetos de uma classe com objetos de outra classe. A Figura 2.11
apresenta um exemplo de associação binária. Os atributos e as operações das clas-
ses foram omitidos com o intuito de focar o relacionamento entre as classes.
ProfessorDisciplina possui
0..* 1
Figura 2.11 Exemplo de associação binária.
Fonte: Autores.
A associação é representada por uma linha que relaciona as classes Disciplina
e Professor. Observa-se, no exemplo, que o relacionamento existente entre as
classes apresenta o nome “possui” e multiplicidade “0..*” e “1”.
O nome é opcional e é utilizado para auxiliar na compreensão do tipo de vínculo
existente entre os objetos. A multiplicidade indica o número mínimo e máximo de
objetos que podem estar associados.
IMPORTANTE
Na associação binária,
representa-se o
estabelecimento de um
vínculo entre os objetos de
uma classe com
os de outra.
42
Dessa forma, de acordo com nome e multiplicidade representados, um objeto da
classe Disciplina “possui” uma relação com um objeto da classe Professor.
Contudo um objeto da classe Professor pode relacionar-se ou não com outros
objetos da classe Disciplina.
Os valores de multiplicidade que podem ser utilizados no diagrama de classe são
apresentados no Quadro 2.5.
Quadro 2.5 Exemplos de multiplicidade
1..1 ou 1 Um e somente um
Um objeto da classe de origem relaciona-se com um e somente
um objeto da classe de destino. Em muitos diagramas, esse tipo
de multiplicidade é omitido nos relacionamentos.
1..* No mínimo 1 e no máximo muitos
Um objeto da classe de origem relaciona-se com um ou vários
objetos da classe destino.
0..* ou * No mínimo nenhum e no máximo muitos
Um objeto da classe de origem pode ou não se relacionar com
objetos da classe de destino.
0..1 No mínimo nenhum e no máximo um
Um objeto daclasse de origem relaciona-se com um objeto da
classe de destino ou com nenhum.
m..n Faixa de valores que pode ser estabelecida, por exemplo, 2..7.
Nesse caso, um objeto da classe de origem relaciona-se com pelo
menos dois e no máximo sete objetos da classe de destino.
Outra informação que um relacionamento pode conter é a navegabilidade. A nave-
gabilidade indica o sentido em que as informações são transmitidas entre os ob-
jetos das classes envolvidas. Observa-se, na Figura 2.11, que a associação contém
duas setas nas extremidades da linha. Uma delas aponta para a classe Mensagem
e a outra para a classe Assunto. Nesse caso, a classe Mensagem poderá execu-
tar operações da classe Assunto, assim como a classe Assunto poderá executar
operações da classe Mensagem.
O nome “é citado por” e a multiplicidade “0..*” e “1..*”, representados na associação,
indicam que um objeto da classe Assunto é citado por, no mínimo um e no máxi-
mo muitos, objetos da classe Mensagem, assim como um objeto da classe Mensa-
gem poderá citar nenhum ou muitos objetos da classe Assunto.
DICA
A navegabilidade é
opcional. Dessa forma, se
não há a representação
da seta, as informações
podem ser transmitidas
entre todos os objetos
das classes envolvidas,
ou seja, o equivalente
à navegabilidade
bidirecional.
43
Assunto
Mensagem
+ criar()
+ retornarMensagens()
+ retornarPrincipaisAssuntos()
+ responder()
+ reenviar()
+ citar()
+ compartilhar()
é citado por
0..* 1..*
Figura 2.12 Exemplo de associação com navegabilidade.
Fonte: Autores.
Associação unária
Esse tipo de relacionamento é usado quando se pretende representar a existência
de um vínculo entre objetos da mesma classe. A Figura 2.13 apresenta um exemplo
de associação unária na classe Disciplina.
Disciplina
é pré-requisito
0..*
0..*
Figura 2.13 Exemplo de associação unária.
Fonte: Autores.
Observa-se que uma linha parte da classe Disciplina e atinge ela própria. Essa
linha indica que pode existir um relacionamento, que recebe o nome de “é pré-re-é pré-re- pré-re-
quisito”, entre os objetos da classe Disciplina. A multiplicidade “0..*”, utilizada
nos dois extremos da linha, indica que uma disciplina pode ou não ser pré-requisito
de outra disciplina e que uma disciplina pode ou não possuir pré-requisitos.
Agregação
O relacionamento de agregação é um tipo especial de associação utilizado quando
se deseja representar vínculos do tipo todo/parte entre objetos. Na UML, usamos
o relacionamento de agregação quando pretendemos mostrar que as informações
de um objeto, denominado objeto-todo, precisam ser complementadas pelas in-
formações de um ou mais objetos, denominados objetos-parte.
A agregação é representada por uma linha com um losango na extremidade da
classe que contém o objeto-todo, conforme consta na Figura 2.14.
Usuário
Lista
+ nome : String
+ login : String
– senha : String
+ adicionarUsuario()
+ removerUsuario()
membro
0..* 0..*
Figura 2.14 Exemplo de agregação entre classes.
Fonte: Autores.
IMPORTANTE
Na associação unária,
representa-se o
estabelecimento de um
vínculo entre objetos de
uma mesma classe.
IMPORTANTE
Na agregação, representa-se
o estabelecimento de
vínculos do tipo todo/parte
entre objetos.
44
Os objetos da classe Lista representam o todo e os objetos da classe Usuario
representam as partes. Nesse caso, uma instância da classe Lista poderá conter
como membro nenhuma ou muitas instâncias da classe Usuario como suas par-
tes (objetos-parte). Uma instância da classe Usuario poderá pertencer a nenhuma
ou muitas instâncias da classe da Lista.
Na agregação, caso o objeto-todo deixe de existir, suas partes permanecerão exis-
tindo. Por exemplo, se um objeto da classe Lista for excluído, os objetos da classe
Usuario continuarão existindo no sistema.
A composição é um tipo especial de agregação que apresenta um vínculo mais
forte entre o objeto-todo e os objetos-parte. Diferentemente da agregação, na
composição, os objetos-parte estão associados a um objeto-todo. Dessa forma, os
objetos-parte não existem sem o objeto-todo. A composição é representada por
uma linha com um losango preenchido localizado na extremidade da classe que
contém o objeto-todo, conforme ilustra a Figura 2.15.
Curso Disciplina
– codigo : long
– nome : String
– codigo : long
– nome : String1..*
Figura 2.15 Exemplo de composição.
Fonte: Autores.
O objeto-parte da classe Disciplina só existe se estiver vinculado a um objeto-
-todo da classe Curso. Assim, se um curso deixar de existir, suas disciplinas tam-
bém deixarão. A multiplicidade indica que uma disciplina está vinculada somente a
um curso e o curso tem pelo menos uma disciplina.
Generalização
Na UML, a generalização (ou especialização) é um tipo de relacionamento utilizado
para classes de um sistema que possuem atributos e operações muito semelhantes.
Por meio da generalização, é possível definir uma ou mais classes a partir de uma
classe existente, reaproveitando seus atributos e suas operações.
Veja a seguir, na Figura 2.16, um exemplo de generalização entre classes.
Curso
Tecnico Superior
– codigo : long
– nome : String
+ cursarDisciplina()
+ realizarEstagio() + entregarTrabalhoConclusao()
Figura 2.16 Exemplo de generalização entre classes.
Fonte: Autores.
ATENÇÃO
Na agregação, se um
objeto-todo deixa de
existir, suas partes
continuam existindo.
IMPORTANTE
Na composição,
representa-se o
estabelecimento de um
vínculo mais forte entre
objeto-todo e objeto-parte.
ATENÇÃO
A composição se diferencia
da agregação devido ao
fato de o objeto-parte
estar associado a um
único objeto-todo.
c
a
p
ít
u
lo
2
M
o
d
e
la
g
e
m
d
e
s
is
te
m
a
s
o
ri
e
n
ta
d
a
a
o
b
je
to
s
45
A classe Curso é uma superclasse (classe geral) e, a partir dela, derivam-se duas
subclasses (classes especializadas), Tecnico e Superior. As classes especializa-
das herdam os atributos (codigo e nome) e a operação (cursarDisciplina())
da classe Curso. A subclasse Tecnico possui a operação realizarEstagio(),
além das operações e dos atributos herdados. Já a subclasse Superior, contém
a operação entregarTrabalhoConclusao(), além dos atributos e das ope-
rações herdados da classe Curso. A generalização é representada por uma seta
fechada localizada na extremidade da superclasse.
Classe associativa
As classes associativas derivam das associações que possuem multiplicidade “mui-
tos” (*) em todas as suas extremidades. Elas devem ser utilizadas quando existem
atributos relacionados a essa associação e quando eles não podem ser armazena-
dos em nenhuma das classes envolvidas.
Veja a seguir, na Figura 2.17, um exemplo de classe associativa.
Aluno Disciplina
Matricula
1..* 1..*
+ dataMatricula : Date
+ dataCancelamento : Date
+ ativa : boolean
+ realizarMatricula()
+ cancelarMatricula()
Figura 2.17 Exemplo de classe associativa.
Fonte: Autores.
Na Figura 2.17, uma instância da classe Aluno pode matricular-se em uma ou mais
instâncias da classe Disciplina, assim como uma instância da classe Disci-
plina pode ter muitas instâncias da classe Aluno matriculadas. Observa-se que
nesse relacionamento existem atributos e operações que não pertencem exclusi-
vamente às classes Aluno e Disciplina, sendo necessária a criação da classe
Matricula para armazená-los.
Dependência
O relacionamento de dependência é utilizado quando uma classe depende de atri-é utilizado quando uma classe depende de atri- utilizado quando uma classe depende de atri-
butos ou de operações de outra classe para poder executar suas operações.
Conforme se nota na Figura 2.18, o relacionamento de dependência é represen-
tado por uma linha tracejada que contém uma seta. A linha parte da classe que é
dependente, e a seta aponta para a classe responsável pela operação.
IMPORTANTE
A generalização possibilita
que subclasses herdem
atributos e operações deuma superclasse.
46
Observa-se que a classe JanelaUsuario depende da operação retornarSe-
guidores() : List<Usuario>, da classe ConsultaSeguidores, para exe-
cutar a operação visualizarSeguidores(), e esta depende da operação retornar-
Seguidores() : List<Usuario> da classe Usuario.
+ retornarSeguidores() : List<Usuario>
– nome : String
<<boudary>>
JanelaUsuario
<<control>>
ConsultaSeguidores
<<entity>>
Usuario
+ visualizarSeguidores() + retornarSeguidores() : List<Usuario>
Figura 2.18 Relacionamento de dependência entre classes.
Fonte: Autores.
As classes apresentam seus estereótipos, indicados acima do nome da classe, sen-
do eles <<boundary>>, <<control>> e <<entity>>. A seção “Estereótipos”
apresenta os principais estereótipos utilizados nos diagramas de classe.
O estereótipo <<boundary>> indica que a classe JanelaUsuario serve de co-
municação entre os atores externos do sistema e o sistema. O estereótipo <<con-
trol>> indica que a classe ConsultaSeguidores é responsável por interme-
diar as classes JanelaUsuario e Usuario. Os objetos instanciados na classe
ConsultaSeguidores são responsáveis por interpretar os eventos ocorridos
sobre os objetos da classe JanelaUsuario e retransmiti-los aos objetos da classe
Usuario. O estereótipo <<entity>> indica que a classe Usuario contém infor-
mações recebidas e armazenadas ou geradas pelo sistema.
Realização
O relacionamento de realização está ligado ao contexto de interface. Embora a rea-
lização apresente características dos relacionamentos de generalização e depen-
dência, ela tem um propósito bem diferente dos demais relacionamentos apresen-
tados neste capítulo.
Conforme apresentado no Capítulo 1, uma interface é uma coleção de operações
utilizadas para especificar um serviço de uma classe ou de um componente, ou
seja, especifica um contrato que define as execuções de uma classe, mas não espe-
cifica como elas serão realizadas.
O relacionamento de realização é representado por uma linha tracejada com uma
seta fechada. A linha parte de uma classe, e a seta aponta para a interface, confor-
me apresentado na Figura 2.19.
Além de se observar relacionamentos de dependência entre as classes Jane-
laLoginSenha, AutenticacaoLoginSenha e Usuario, nota-se também
o relacionamento de realização entre a classe AutenticacaoLoginSenha e a
interface IAutenticacao. Nesse caso, a classe AutenticacaoLoginSenha
implementa a operação autenticar() : boolean definida pela interface IAu-
tenticacao.
IMPORTANTE
Uma realização especifica
um relacionamento entre
uma interface e uma
classe que implementa as
suas operações.
47
<<interface>>
IAutenticacao
<<entity>>
Usuario
<<control>>
AutenticacaoLoginSenha
<<boundary>>
JanelaLoginSenha
+ autenticar() : boolean
+ autenticar() : boolean
+ autenticar(nome : String, login : String) : boolean
+ solicitaLoginSenha()
– nome : String
– login : String
– senha : String
Figura 2.19 Exemplo de realização.
Fonte: Autores.
Estereótipos
Na modelagem de sistemas, os estereótipos são utilizados para indicar que deter-
minados componentes do sistema executam funções diferentes dos demais. A UML
apresenta diversos estereótipos, além de permitir a criação de novos. Os estereó-
tipos podem ser utilizados em todos os diagramas da UML. Entretanto, são mais
utilizados nos diagramas de Classes.
Os três principais estereótipos utilizados nos diagramas de Classes são <<entity>>,
<<control>> e <<boundary>>.
O estereótipo <<entity>> é utilizado quando se deseja indicar que a classe ar-
mazena informações sobre uma entidade. A Figura 2.20 ilustra o exemplo de uma
classe Usuario com estereótipo <<entity>>.
Usuário
Figura 2.20 Estereótipo <<entity>>.
Fonte: Autores.
O estereótipo <<boundary>> é utilizado em classes que servem como meio de
comunicação entre os atores externos e o sistema. Na maior parte das vezes, esse
estereótipo é associado à própria interface do sistema. A Figura 2.20 apresenta um
exemplo desse estereótipo.
IMPORTANTE
Os estereótipos indicam
que alguns componentes do
sistema exercem funções
distintas das exercidas
pelos demais.
D
e
s
e
n
v
o
lv
im
e
n
to
d
e
S
o
ft
w
a
re
I
II
48
JanelaUsuário
Figura 2.21 Estereótipo <<boundary>>.
Fonte: Autores.
A Figura 2.21 apresenta um exemplo do estereótipo <<control>>. Esse estereóti-
po representa classes que têm a função de intermediar as classes <<boundary>>
e os demais componentes do sistema. Os objetos dessa classe são responsáveis por
interpretar os eventos ocorridos na classe <<boundary>> e retransmiti-los aos
objetos da classe <<entity>>.
ControleUsuário
Figura 2.22 Estereótipo <<control>>.
Fonte: Autores.
Nesse tipo de representação, não é possível visualizar os atributos e os métodos das
classes. Como apresentado nas seções sobre dependência e realização, o tipo de
estereótipo também pode ser indicado acima do nome da classe, conforme consta
nas Figuras 2.18 e 2.19.
A Figura 2.23 ilustra o diagrama de classes referente ao sistema de microblog. Nela,
há quatro classes com seus respectivos atributos e operações: Usuario, Lista, Men-
sagem e Assunto. O diagrama ilustra também os relacionamentos existentes entre
as classes, como associação, agregação e composição.
A classe Usuario tem como atributos nome : String, login : String, se-
nha : String e localidade : String, além das operações criar(), respon-
sável pela instanciação dos objetos da classe; autenticar(), responsável pelo
acesso do usuário ao sistema; pesquisar(), responsável por pesquisar usuários;
seguir(), indica a intenção de ser comunicado sobre as ações do usuário que
serão passadas como parâmetro; deixarSeguir(), indica a intenção de não
mais receber mensagens referente às ações do usuário passado como parâmetro;
retornarSeguidores(), retorna a lista de usuários seguidores; e retornar-
Seguidos(), retorna a lista de usuários que estão sendo seguidos. Observa-se
ainda uma associação unária na classe Usuario, indicando que um objeto da clas-
se Usuario pode seguir nenhum ou muitos objetos da classe.
A classe Lista é responsável por organizar os usuários em listas. Essa classe possui
o atributo nome : String, e suas operações são criar(), responsável pela instan-
ciação dos objetos da classe; remover(), que desativa uma lista; adicionar
Usuario(), que adiciona um usuário à lista; e removerUsuario(), que remove
um usuário da lista.
c
a
p
ít
u
lo
2
M
o
d
e
la
g
e
m
d
e
s
is
te
m
a
s
o
ri
e
n
ta
d
a
a
o
b
je
to
s
49
Nesse exemplo, um relacionamento de composição entre as classes Usuario e
Lista indica que um objeto-todo da classe Usuario pode conter ou não muitos
objetos-parte da classe Lista. Já um objeto-parte da classe Lista pertence so-
mente a um objeto-todo da classe Usuario. Nesse caso, um usuário é proprietário
de nenhuma ou muitas listas, e uma lista pertence somente a um usuário. Nota-se
ainda um relacionamento de agregação entre as classes Lista e Usuario, em
que um objeto-todo da classe Lista poderá conter nenhum ou muitos objetos-
-parte da classe Usuario. Assim, uma lista poderá ter como membros nenhum ou
muitos usuários, assim como um usuário poderá pertencer ou não a muitas listas.
<<entity>>
Usuario
<<entity>>
Usuario
<<entity>>
Mensagem
<<entity>>
Lista
+ nome : String
+ login : String
+ senha : String
+ localidade : String
– nome : String
– texto : String
proprietário
0..*
0..*
0..* 0..*
0..*
0..*
0..*
1..*
membro
mensagens
reenviada
é citado por
seguir
+ nome : String
+ localidade : String
– pontuacao : int
– posicaoLocalidade : int
– posicaoGeral : int
+ criar()
+ autenticar()
+ pesquisar()
+ seguir()
+ deixarseguir()
+ retornarSeguidores()
+ retornarSeguidos()
+ criar()
+ ler()
+ responder()
+ reenviar()
+ citar()
+ compartilhar()
+ criar()
+ remover()
+ adicionarUsuario()
+ removerUsuario()
+ criar()
+ retornarMensagens()
+ retornarPrincipaisAssuntos()Figura 2.23 Diagrama de classes referente ao sistema de microblog.
Fonte: Autores.
A classe Mensagem representa um texto inserido por um usuário. A classe pos-
sui como atributo texto : String, e suas operações são criar(), responsável
pela instanciação de um objeto da classe; ler(),possibilita que o usuário leia as
mensagens; responder(), cria uma nova mensagem, com texto próprio, relacio-
nada a outra; reenviar(), cria uma nova mensagem relacionada a outra (a nova
mensagem não possui texto próprio.); citar(), cria uma nova mensagem, com
texto próprio, e inclui um assunto à mensagem, por exemplo, “#case”; compar-
tilhar(), permite enviar a mensagem para outras redes sociais ou por e-mail.
Observa-se que existe um relacionamento de composição entre as classes Usua-
rio e Mensagem, que indica que um objeto-todo da classe Usuario poderá con-
50
ter nenhum ou vários objetos-parte da classe Mensagem. Nesse caso, se um usuá-
rio for excluído, todas as mensagens desse usuário também serão. Nota-se também
uma associação unária na classe Mensagem, indicando a existência de um vínculo
entre objetos da mesma classe, ou seja, uma mensagem pode ser reenviada por
nenhuma ou muitas mensagens.
A classe Assunto representa um assunto citado em uma ou mais mensagens. Os
objetos dessa classe correspondem ao símbolo “#”, utilizado no Twitter. Essa clas-
se possui os atributos nome : String, localidade : String, pontuacao :
int, posicaoLocalidade : int, posicaoGeral : int, e suas operações
são criar(), responsável pela instanciação de um objeto da classe Assunto;
retornarMensagens(), retorna as mensagens em que o assunto foi citado;
retornarPrincipaisAssuntos(), retorna uma lista dos assuntos mais bem
pontuados atualmente. Observa-se a associação entre as classes Assunto e Men-
sagem, que indica que um objeto da classe Assunto é citado por um ou muitos
objetos da classe Mensagem. Da mesma forma, um objeto da classe Mensagem
pode citar nenhum ou muitos objetos da classe Assunto. Desse modo, um as-
sunto (“#assunto”) pode ser referenciado em uma ou muitas mensagens, e uma
mensagem pode referenciar nenhum ou muitos assuntos.
Diagrama de sequência
O diagrama de sequência é um diagrama comportamental da UML que apresenta
a interação entre os elementos do sistema, enfatizando a sequência temporal em
que as mensagens são trocadas durante o processo.
O diagrama de sequência é construído com base no diagrama de caso de uso, sen-
do sugerida a construção de um diagrama de sequência por caso de uso. Esse dia-
grama também depende do diagrama de classes, uma vez que as classes utilizadas
nele estão descritas no diagrama de classes.
Esta seção apresenta os principais elementos do diagrama de sequência, assim
como a aplicação deles em determinados exemplos.
Ator
Os atores representam entidades externas que interagem com as funcionalidades
do sistema ou com outros atores envolvidos no processo, sendo responsáveis por
gerar eventos que darão início ao processo. Como o diagrama de sequência é cons-
truído com base no diagrama de casos de uso, os atores envolvidos são os mesmos
do diagrama de casos de uso.
IMPORTANTE
Lembre-se de que
cada objeto-parte de
Mensagem deve
pertencer apenas a um
objeto-todo de Usuario.
IMPORTANTE
O diagrama de sequência
enfatiza a sequência
temporal de troca de
mensagens durante a
interação entre elementos
do sistema.
DICA
O diagrama de sequência
é construído na fase de
projeto.
c
a
p
ít
u
lo
2
M
o
d
e
la
g
e
m
d
e
s
is
te
m
a
s
o
ri
e
n
ta
d
a
a
o
b
je
to
s
51
O ator é representado por um boneco-palito com o nome associado ao papel que
exerce no sistema, exatamente igual ao ator do diagrama de casos de uso. No
diagrama de sequência, ele vem acompanhado da linha de vida. Na Figura 2.24,
há um exemplo do ator Aluno.
Aluno
Figura 2.24 Ator no diagrama de sequência.
Fonte: Autores.
Linha de vida
linha de vida indica a existência de um objeto ao longo de um período de tempo
durante um processo. Conforme apresentado na Figura 2.22, a linha de vida é re-é re- re-
presentada por uma linha tracejada que parte do objeto e estende-se verticalmen-
te até o final do diagrama.
Objetos
Os objetos representam as instâncias das classes. Eles podem existir durante toda
a interação ou ser criados e destruídos durante a interação. Os objetos que existem
durante toda a interação são alinhados no topo, com suas linhas de vida estenden-
do-se até o final do diagrama. Já os que são criados e destruídos durante a intera-
ção têm suas linhas de vida finalizadas com um X.
A Figura 2.25 apresenta um exemplo de um objeto “disciplina1” que é uma instân-
cia da classe Disciplina. Esse é um exemplo de objeto que existe durante todo
o processo de interação.
disciplina1 : Disciplina
Figura 2.25 Exemplo de objeto que existe durante todo o processo de
interação.
Fonte: Autores.
IMPORTANTE
Os atores do diagrama de
sequência são os mesmos do
diagrama de casos de uso.
D
e
s
e
n
v
o
lv
im
e
n
to
d
e
S
o
ft
w
a
re
I
II
52
Na Figura 2.26, vemos o exemplo de um objeto “curso1” que é criado e destruído
durante o processo de interação.
cadastrarCurso(Curso)
curso1 : Curso
ControleUsuário
Figura 2.26 Exemplo de objeto que é criado e destruído durante a interação.
Fonte: Autores.
Foco de controle
O foco de controle indica um período em que um objeto está executando uma ou
mais ações durante a interação. Ele é representado por um retângulo posicionado
em cima da linha de vida, tendo a parte superior alinhada com o início da ação e a
inferior alinhada com seu término, conforme apresentado na Figura 2.27.
Aluno JanelaDisciplina
Visualiza Conceito
Figura 2.27 Exemplo de foco de controle e mensagem simples.
Fonte: Autores.
Mensagens
As mensagens representam a ocorrência de eventos que podem ou não solicitar a
chamada de um método, podendo ainda indicar a comunicação entre dois atores.
53
Na Figura 2.27, a mensagem indica a ocorrência de um evento que não solicita a
execução de um método. Ela é representada por uma linha com uma seta preen-
chida. O processo que está sendo representado é a interação entre o ator Aluno
e a classe JanelaDisciplina. Esse ator envia uma solicitação para visualizar o
conceito para a classe JanelaDisciplina.
Um exemplo de mensagem acompanhada da solicitação de execução de um méto-
do pode ser observado na Figura 2.28. No exemplo, há também uma mensagem de
retorno, representada por uma linha tracejada que contém uma seta aberta.
cadastrarDisciplina(Disciplina)
sucesso : boolean
disciplina1 : Disciplina
ControleDisciplina
Figura 2.28 Exemplo de mensagens de envio e retorno.
Fonte: Autores.
Autochamada
A autochamada é utilizada quando um objeto necessita enviar uma mensagem
para ele próprio. Observa-se, na Figura 2.29, um exemplo de autochamada em que
a mensagem parte do objeto e atinge ele próprio.
adicionarUsuario(Usuario)
lista1 : Lista
Figura 2.29 Exemplo com autochamada.
Fonte: Autores.
DICA
No diagrama de
sequência, as mensagens
de retorno representam
respostas aos eventos
ocorridos. O uso dessas
mensagens é opcional.
Encerra aqui o trecho do livro disponibilizado para
esta Unidade de Aprendizagem. Na Biblioteca Virtual
da Instituição, você encontra a obra na íntegra.
PROCESSOS DE
DESENVOLVIMENTO
DE SOFTWARE
Thiago Nascimento Rodrigues
Scrum e a modelagem
de software
Objetivos de aprendizagem
Ao final deste texto, você deve apresentar os seguintes aprendizados:
Descrever a UML e os seus principais diagramas.
Reconhecer o que são diagramas de classes e componentes.
Identificar os diagramas de casos de uso e os diagramas de sequências.
Introdução
A implementação precisa de qualquer sistema computacional e está
intrinsicamente associada ao entendimento correto e claro dos requisitos
estabelecidos por um cliente ou usuário final. Uma forma de minimizara
possibilidade de falhas na captação desses requisitos é por meio da criação
de uma documentação que seja expressiva o suficiente para descrever
o comportamento do sistema de forma não ambígua. Essa necessidade
se faz presente em qualquer que seja a metodologia de desenvolvi-
mento adotada. Até mesmo abordagens ágeis se valem do recurso de
documentar sistemas para fins de garantir a precisão da implementação.
Neste capítulo, você terá uma visão geral sobre uma linguagem am-
plamente utilizada para a documentação e modelagem de sistemas
— a UML. Vai conhecer seus principais diagramas e entender como eles
podem se relacionar com a execução do Scrum.
1 Linguagem UML
A UML (do inglês Unifi ed Modeling Language, ou linguagem de modelagem
unifi cada) é uma linguagem de modelagem visual padrão destinada a ser
usada tanto para a modelagem de negócios e processos similares como para
a análise, projeto e implementação de sistemas baseados em software. É uma
linguagem comum para analistas de negócios, arquitetos e desenvolvedores
de software com experiência em descrever, especifi car, projetar e documentar
processos de negócios existentes ou novos e a estrutura e o comportamento
de artefatos de sistemas de software (UML-DIAGRAMS, c2020).
A UML foi criada como resultado do caos que envolvia o desenvolvimento e
a documentação de software. Na década de 1990, havia várias formas diferentes
de representar e documentar sistemas. Surgiu a necessidade de uma maneira
mais unificada de representar visualmente esses sistemas e, como resultado,
em 1994-1996, a UML foi desenvolvida por três engenheiros de software
que trabalhavam na Rational Software. Mais tarde, foi adotada como padrão
em 1997, e continua sendo o padrão desde então, recebendo apenas algumas
atualizações (AMIT, [2018?]).
A versão atual da UML é a 2.5.1, tendo sido lançada em dezembro de 2017 (OBJECT
MANAGEMENT GROUP, 2017). A especificação UML (padrão) é atualizada e gerenciada
pelo OMG (do inglês Object Management Group, ou grupo de gerenciamento de obje-
tos) — um consórcio internacional que desenvolve padrões de integração corporativa
para uma ampla gama de tecnologias e setores. As primeiras versões da UML foram
criadas por três pesquisadores da área de modelagem de sistemas e engenharia de
software. Eles ficaram conhecidos como “três amigos” (SAUVÉ, [20––?]).
A UML não é completa e não é estritamente visual. Isso quer dizer que,
tendo como base apenas um diagrama UML, não é possível ter garantia do
pleno entendimento da parte representada do sistema ou do seu comportamento.
Algumas informações podem ser omitidas intencionalmente no diagrama,
algumas informações representadas no diagrama podem ter interpretações
diferentes e alguns conceitos da UML não possuem sequer uma notação
gráfica, portanto, não há como descrevê-los na forma de diagramas.
Um diagrama UML é uma representação gráfica e parcial de um modelo de
um sistema que está sendo projetado, implementado ou já existe. O diagrama
UML contém elementos gráficos (símbolos) — nós UML conectados com
arestas (também conhecidas como caminhos ou fluxos) — que representam
elementos no modelo UML do sistema projetado. O modelo UML do sistema
também pode conter documentação complementar, como casos de uso escritos
na forma de textos estruturados. O tipo do diagrama é definido pelos principais
símbolos gráficos mostrados no diagrama. Um diagrama em que os símbolos
Scrum e a modelagem de software2
primários na área de conteúdo são classes, por exemplo, é um diagrama de
classes. Um diagrama que mostra casos de uso e atores é um diagrama de
casos de uso. Um diagrama de sequência mostra a sequência de trocas de
mensagens entre linhas de vida. A especificação UML não impede a mistura
de diferentes tipos de diagramas, como por exemplo, combinar elementos
estruturais e comportamentais para mostrar uma máquina de estado aninhada
dentro de um caso de uso. Consequentemente, as fronteiras entre os vários tipos
de diagramas não são rigorosamente impostas. Ao mesmo tempo, algumas
ferramentas UML restringem o conjunto de elementos gráficos disponíveis
que podem ser usados ao se trabalhar em um tipo específico de diagrama.
O uso de diagramas possibilita que o processo de desenvolvimento seja
produtivo e focado, uma vez que podem ajudar as equipes a (LUCIDCHART,
c2020):
incorporar novos membros ou substituir desenvolvedores de maneira
rápida;
navegar pelo código-fonte;
planejar novos recursos antes de qualquer atividade de programação;
comunicar-se com o público técnico e não técnico com maior facilidade.
A especificação UML define duas categorias principais de diagrama:
diagramas de estrutura e diagramas de comportamento. Os diagramas de
estrutura mostram a estrutura estática do sistema e suas partes em diferentes
níveis de abstração e implementação e como eles estão relacionados entre
si. Os elementos em um diagrama de estrutura representam os conceitos
significativos de um sistema e podem incluir conceitos abstratos, do mundo
real e de implementação. Os diagramas de estrutura não utilizam conceitos
relacionados ao tempo e não mostram os detalhes do comportamento dinâmico.
No entanto, eles podem mostrar relacionamentos com os comportamentos
dos classificadores exibidos nos diagramas de estrutura. Em contrapartida,
os diagramas de comportamento mostram o comportamento dinâmico dos
objetos em um sistema, que pode ser descrito como uma série de alterações
no sistema ao longo do tempo (CREATELY, 2019).
3Scrum e a modelagem de software
Embora pareçam semelhantes à primeira vista, diagrama e modelo são diferentes.
Modelo é uma abstração que contém todos os elementos necessários para descrever
a intenção da coisa que está sendo modelada. Isso pode incluir todos os aspectos
relacionados aos negócios, sistemas, relacionamentos e muito mais. Diagrama é uma
visão específica do que se está tentando entender em um contexto específico. Os
diagramas são apenas uma maneira de analisar o todo ou uma parte do modelo. É
possível ter um elemento de modelagem específico apenas uma vez em um modelo,
mas o mesmo elemento pode aparecer em um ou mais diagramas (MAKSIMCHUCK;
NAIBURG, 2004).
Diagramas de estrutura
A UML defi ne sete tipos de diagramas de estrutura (SPARX SYSTEMS,
c2020).
1. Diagrama de classe: os diagramas de classes capturam a estrutura lógica
do sistema, as classes e os objetos que compõem o modelo, descrevendo
o que existe e quais atributos e comportamento ele possui.
2. Diagrama de estrutura: os diagramas de estrutura refletem a colaboração
interna de classes, interfaces e componentes (e suas propriedades) para
descrever uma funcionalidade.
3. Diagrama de componentes: os diagramas de componentes ilustram as
partes do software, controles internos e outros elementos que compõem
um sistema, sua organização e dependências.
4. Diagrama de implantação: os diagramas de implantação mostram como
e onde o sistema deve ser implantado; isto é, sua arquitetura de execução.
5. Diagrama de objeto: os diagramas de objetos descrevem instâncias de
classes ou objetos e seus relacionamentos em um determinado momento.
6. Diagrama de pacotes: os diagramas de pacotes descrevem a organização
dos elementos de um modelo em pacotes e suas interdependências.
7. Diagrama de perfil: os diagramas de perfil são aqueles criados para
estender elementos, conectores e componentes UML.
Scrum e a modelagem de software4
Diagramas de comportamento
Sete diagramas de comportamento também são defi nidos na UML (SPARX
SYSTEMS, c2020).
1. Diagramas de atividades: os diagramas de atividades modelam os com-
portamentos de um sistema e a maneira como esses comportamentos
estão relacionados em um fluxo geral de funcionamento.
2. Diagramas de casos de uso: os diagramas de casos de uso capturam
interações e relacionamentos entre os atores e o sistema; eles descrevem
os requisitos funcionais do sistema, a maneira pela qual operadoresexternos interagem nos limites do sistema e a resposta deste.
3. Diagramas de máquina de estado: ilustram como um elemento pode se
mover entre estados, classificando seu comportamento de acordo com
gatilhos de transição e restrições de proteção.
4. Diagramas de tempo: os diagramas de tempo definem o comporta-
mento de diferentes objetos em uma escala de tempo, fornecendo uma
representação visual dos objetos que mudam de estado e interagem ao
longo do tempo.
5. Diagramas de sequência: os diagramas de sequência são representações
estruturadas do comportamento como uma série de etapas sequenciais
ao longo do tempo. Eles são usados para descrever o fluxo de trabalho,
a transmissão de mensagens e como os elementos em geral cooperam
ao longo do tempo para alcançar um resultado.
6. Diagramas de comunicação: os diagramas de comunicação mostram
as interações entre os elementos no tempo de execução, visualizando
os relacionamentos entre objetos.
7. Diagramas de visão geral da interação: possibilitam a visualização da
cooperação entre os diagramas de interação (tempo, sequência, comu-
nicação e outros diagramas de visão geral da interação) para ilustrar
um fluxo de controle que serve a um objetivo abrangente.
Scrum e UML
Um verdadeiro membro de uma equipe ágil sabe que o artefato mais impor-
tante obtido em uma metodologia ágil é o código testado e funcionando. Não
há nada mais importante que o código em funcionamento. Todos os outros
artefatos ágeis (lista de histórias de usuário, histórias de usuário de iteração
e gráfi co de progresso) são apenas ferramentas secundárias para ajudar de-
5Scrum e a modelagem de software
senvolvedores a controlar o processo ágil. Com relação à documentação e aos
artefatos da UML, uma coisa é forçar a equipe de desenvolvimento a seguir
um conjunto pesado e rigoroso de documentação como parte do processo de
desenvolvimento, como acontece no processo unifi cado, e outra coisa é deixá-
-los decidir quais artefatos desejam. De acordo com Beck et al. (c2001), um
princípio importante do Manifesto Ágil diz que projetos devem ser construídos
em torno de indivíduos motivados, princípio este que pode ser aplicado ao uso
dos artefatos UML. Desde que a equipe de desenvolvimento entenda como a
UML pode ajudar a desenvolver uma solução modular e extensível, ela será
a primeira a propor o uso de um diagrama UML (GALLUD; FARDOUN,
2018). Ainda de acordo com Gallud e Fardoun (2018), o seguinte conjunto de
artefatos UML é altamente recomendado para uso em uma metodologia ágil
como o Scrum:
diagramas de classes;
diagramas de implantação.
Diagramas de sequência UML também podem ser úteis para a equipe de
desenvolvimento. No entanto, eles podem ser considerados como artefatos
opcionais. Ao fazer uso de digramas de classes na metodologia Scrum, é
importante preservar a filosofia de se projetar o mínimo necessário para se
implementar determinada funcionalidade. Logo, o Scrum recomenda que
a equipe projete apenas as entidades e os relacionamentos necessários para
implementar a história do usuário selecionada. Como a solução é construída
por incrementos definidos pelas iterações, esse artefato evolui com o mesmo
ritmo do software. As primeiras iterações mostrarão poucas entidades e rela-
cionamentos e, enquanto a solução aumentar, os diagramas de classes também
crescerão. Um dos aspectos difíceis do uso de diagramas UML para manter
a coerência entre o diagrama e o código de classe é a sincronização desses
dois artefatos. Isso não é um problema, já que esta revisão pode provocar a
equipe de desenvolvimento a repensar a solução, que pode resultar em algum
tipo de refatoração ou reprojeto. Alguns desenvolvedores encontram melhores
soluções de projeto depois de analisar o diagrama de classes.
De forma análoga, no Scrum é possível usar diagramas de implantação
UML desde a primeira iteração, uma vez que esse primeiro diagrama fornece
os elementos fundamentais da arquitetura do software. Os diagramas de im-
plantação UML vão possibilitar que a equipe de desenvolvimento tenha uma
ideia global dos importantes blocos de construção da solução.
Scrum e a modelagem de software6
Em resumo, alguns diagramas UML, como diagramas de classe e implan-
tação, podem ser úteis para uma equipe de desenvolvimento ágil que faz uso
do Scrum, pois podem contribuir para o projeto e criar uma melhor solução
orientada a objetos. Uma solução orientada a objetos fornece muitas das me-
lhores qualidades que qualquer equipe de desenvolvimento ágil, em particular
Scrum, busca, tais como: extensibilidade, modularidade, robustez e correção.
Não se pode desconsiderar, porém, que as metodologias ágeis vêm rede-
finindo a maneira como o software é desenvolvido. Em função disso, alguns
autores têm afirmado que o valor dos diagramas UML em um ambiente ágil é
limitado e que o esforço necessário para atualizar continuamente os diagramas
à medida que o projeto está em andamento pode não valer o esforço (COBB,
c2020). No entanto, há ainda a concordância de que existem algumas razões
pelas quais os diagramas UML podem ser úteis:
suporte: pode haver algum valor em ter diagramas UML como uma
ajuda para dar suporte ao sistema depois que o desenvolvimento for
concluído;
arquitetura: também pode haver algum valor no uso da UML para
definir e padronizar a arquitetura da solução.
Ambas as funções dependem muito da complexidade do sistema, da cri-
ticidade, da funcionalidade que ele fornece e da estratégia geral de suporte
ao sistema.
2 Diagramas de classes e de componentes
O diagrama de classes UML é uma notação gráfi ca usada para construir e
visualizar sistemas orientados a objetos. Um diagrama de classes na UML
é um tipo de diagrama estático que descreve a estrutura de um sistema por
meio dos seguintes elementos (GURU99, c2020):
classes;
atributos;
operações ou métodos;
relacionamentos entre os objetos.
Uma classe é o modelo de um objeto. Logo, uma classe descreve o que
um objeto será, mas não é o objeto em si; de fato, as classes descrevem o tipo
7Scrum e a modelagem de software
de objetos, enquanto objetos são instâncias utilizáveis das classes. Objetos e
classes trabalham em estreita relação. A Figura 1 apresenta uma representa-
ção de como os conceitos de classe e objeto estão interligados. Cada objeto
é construído a partir do mesmo conjunto de cachorros e, portanto, contém os
mesmos componentes (propriedades e métodos). Assim, o significado padrão
é que um objeto é uma instância de uma classe e um objeto — os objetos têm
estados e comportamentos.
Figura 1. Exemplo do conceito de classe e objeto (instância).
Fonte: Adaptada de Visual Paradigm (c2020).
A Figura 2 descreve um exemplo detalhado de como um diagrama de
classes pode ser estruturado e de como seus principais componentes podem
ser organizados para descrever um modelo.
Scrum e a modelagem de software8
Figura 2. Exemplo de diagrama de classes.
Fonte: Adaptada de Ventura (2019).
Os relacionamentos entre as classes podem ser de quatro tipos (CREA-
TELY, 2019).
1. Associação (conector sem pontas): tipo de relacionamento usado para
descrever classes que são independentes (podem existir sem dependência
umas das outras), mas que em algum momento durante a execução do
software podem vir a ter alguma relação.
2. Generalização (conector com seta em uma das pontas): tipo de rela-
cionamento onde a classe generalizada (classe para o qual a seta está
apontando) fornece recursos para a classe especializada (herdeira). Esse
tipo de relacionamento é exemplificado entre as classes Moradia e
Casa da Figura 2.
3. Composição (conector com um “diamante” preenchido na ponta): tipo
de relacionamento onde a existência da classe composta depende da
existência das outras classes que estão conectadas a ela. Por exemplo, na
Figura 2, a classe Casa possui uma composição com as classes Parede
e Telhado. Sem essas duas classes, a classe Casa não pode existir.
4. Agregação (conectorcom um “diamante” vazado na ponta): tipo de
relacionamento onde a existência da classe agregada não depende de
outras classes em relacionamento com ela, porém a classe agregada faz
uso dessas outras classes. A Figura 2 também apresenta um exemplo
deste tipo de relacionamento. A classe Casa possui uma agregação
com a classe Espelho. Sem o Espelho a classe Casa pode existir.
9Scrum e a modelagem de software
Em um diagrama de classe, a representação de uma classe é composta de
três seções: uma superior, onde o nome da classe é indicado; uma interme-
diária, onde os atributos são informados; e uma inferior, dedicada à listagem
das operações ou métodos disponibilizados pela classe. No dia a dia de um
projeto de modelagem de software, no entanto, nem sempre é necessário ou
relevante representar todas as três seções de cada classe no menor nível de
detalhe possível.
Diagrama de componentes
Durante a modelagem de grandes sistemas orientados a objetos, é comum
a necessidade de se decompor o sistema em subsistemas gerenciáveis. Os
diagramas de componentes UML são usados para modelar sistemas grandes
em subsistemas menores que podem ser gerenciados com facilidade. Um com-
ponente é uma parte substituível e executável de um sistema cujos detalhes de
implementação estão ocultos. Um componente fornece o conjunto de interfaces
que um componente realiza ou implementa. Os componentes também requerem
interfaces para executar uma função. É uma parte modular de um sistema que
encapsula seu conteúdo. Eles são os elementos lógicos de um sistema que
desempenham um papel essencial durante a sua execução. Um componente
é semelhante a uma caixa preta cujo comportamento externo é defi nido por
uma interface fornecida e por interfaces necessárias. (GURU99, c2020).
Um componente é representado com o símbolo <<Nome do Componente>>,
conhecido como estereótipos UML. Os detalhes dos componentes estão ocultos
para o mundo exterior. O nome de um componente é colocado no centro de
um retângulo. Um ícone de componente também pode ser exibido no canto
superior direito de um retângulo. Antes de desenhar um diagrama de compo-
nentes, os artefatos a seguir devem ser identificados claramente (TUTORIALS
POINT, c2020):
arquivos usados no sistema;
bibliotecas e outros artefatos relevantes para o sistema;
relacionamentos entre os artefatos.
Depois da identificação dos artefatos, é importante que um nome signifi-
cativo seja definido para cada componente para o qual o diagrama está sendo
preparado. Além disso, o uso de notas para esclarecer detalhes mais relevantes
também é visto como uma boa prática. A Figura 3 apresenta um diagrama de
componentes para um sistema de web tradicionalmente implementado com a
Scrum e a modelagem de software10
linguagem de programação Java. Neste exemplo, os artefatos são arquivos. O
diagrama mostra os arquivos no sistema e seus relacionamentos. Os compo-
nentes a seguir são alguns dos que podem ser identificados neste diagrama.
Java Server Page (JSP): componente da linguagem de programação Java
utilizado para incorporar comportamentos dinâmicos a documentos
HTML.
Formulário HMTL: página HTML gerada a partir do componente JSP.
Servlet: componente da linguagem Java responsável por tratar requi-
sições recebidas de clientes web.
Controlador: classe Java que executa a lógica de negócio do sistema.
Entidade: classe Java que representa o modelo de negócio do sistema.
Figura 3. Exemplo de diagrama de componentes.
Fonte: Ribeiro ([20––?], documento on-line).
Servelt
Formulário
HTML
Java Server
Page
<<Controlador>>
Java Bean JB
<<Entidade>>
Java Bean
<<Entidade>>
Java Bean JB E
<<Entidade>>
Java Bean EJB
3 Diagramas de casos de uso e de sequências
Veremos a seguir as características, a aplicabilidade e os principais usos dos
diagramas de casos de uso e de sequências.
Diagrama de casos de uso
Na UML, um diagrama de casos de uso pode resumir os detalhes dos usuários
do sistema (também conhecidos como atores) e suas interações com o sistema.
11Scrum e a modelagem de software
Um diagrama de casos de uso efi caz pode ajudar uma equipe de desenvolvi-
mento a discutir e a representar (LUCIDCHART, c2020):
cenários em que o sistema interage com pessoas, organizações ou
sistemas externos;
metas em que o sistema deve auxiliar as entidades (conhecidas como
atores) a alcançar;
o escopo do seu sistema.
Nesse contexto, os diagramas de casos de uso podem ser usados para des-
crever as funcionalidades de um sistema de maneira horizontal. Ou seja, em vez
de apenas representar os detalhes de recursos individuais de um sistema, esse
tipo de diagrama pode ser usado para mostrar todas as suas funcionalidades
disponíveis. É importante observar, no entanto, que os diagramas de caso de
uso são fundamentalmente diferentes dos diagramas de sequência ou fluxo-
gramas, porque eles não fazem nenhuma tentativa de representar a ordem ou
o número de vezes que as ações e subações do sistema devem ser executadas.
Diagramas de caso de uso possuem apenas quatro elementos principais
(UML-DIAGRAMS, c2020):
os atores, com os quais o sistema que está descrito interage;
o próprio sistema;
os casos de uso ou serviços que o sistema sabe executar;
as linhas que representam os relacionamentos entre esses elementos.
Logo, um diagrama de caso de uso deve representar a funcionalidade de um
sistema seguindo uma perspectiva de cima para baixo. Em outras palavras, de
relance, a funcionalidade do sistema é óbvia, mas todas as descrições estão em
um nível muito alto. Mais detalhes podem ser adicionados posteriormente ao
diagrama a fim de elucidar pontos interessantes no comportamento do sistema.
Um exemplo de cenário adequado para a construção de um diagrama de caso
de uso seria descrever todas as tarefas que podem ser feitas com um sistema
de banco de dados e por todas as pessoas que podem usá-lo (administradores,
desenvolvedores, pessoal de entrada de dados).
Scrum e a modelagem de software12
A semântica de multiplicidade de atores e de multiplicidade de casos de uso nos
diagramas de casos de uso não está definida precisamente na especificação UML. Logo,
a presença desses elementos em um diagrama pode significar tanto o uso concorrente
como o uso sucessivo de casos de uso (UML-DIAGRAMS, c2020).
Em contrapartida, este tipo de diagrama não deve ser usado para representar
o comportamento de exceção (quando ocorrem erros) ou para tentar ilustrar
a sequência de etapas que devem ser executadas para concluir uma tarefa.
Diagramas de sequência devem ser usados para mostrar esses recursos de
projeto. Um exemplo de cenário onde um diagrama de caso de uso estaria
sendo mal empregado é o de descrever algum protocolo de rede, tendo em
vista que existem muitos casos de exceção, comportamentos alternativos e
funcionalidades que são acionadas sob certas condições (SYBASE, c2006).
A Figura 4 apresenta um exemplo típico de caso de uso. Três atores são
retratados: paciente, secretária e médico. Cada ação passível de ser executada
por cada ator interagindo com o sistema é representada como um caso de uso
(elipses) no diagrama. Além disso, as comunicações entre atores e sistema são
representadas por relacionamentos (linhas). As linhas sem setas indicam que a
comunicação é bidirecional, ou seja, o ator interage com o sistema e o sistema
pode devolver alguma mensagem para o usuário. As linhas sem seta indicam
que a comunicação é apenas unidirecional. Neste exemplo, o ator aciona
alguma funcionalidade, mas nenhuma informação é retornada pelo sistema.
13Scrum e a modelagem de software
Figura 4. Exemplo de diagrama de casos de uso.
Fonte: Adaptada de Ribeiro (2012).
Marca
consulta
Solicita
consulta
Cancela
consulta
Paciente
Secretária
Médico
Realiza
consulta
Prescreve
medicamento
Solicita
exame
Solicita
cancelamento
de consulta
Diagrama de sequência
O diagrama de sequência é usado principalmente para mostraras interações
entre objetos na ordem sequencial em que essas interações ocorrem. Muito
parecido com o diagrama de classes, os desenvolvedores normalmente tendem
a considerar que os diagramas de sequência foram criados exclusivamente
para a atividade de desenvolvimento. No entanto, a equipe de negócios de uma
organização pode encontrar diagramas de sequência úteis para comunicar como
a empresa atualmente funciona, mostrando como vários objetos de negócios
interagem. Além de documentar os assuntos atuais de uma organização, um
diagrama de sequência no nível de negócios pode ser usado como um docu-
mento de requisitos para comunicar requisitos para uma futura implementação
do sistema. Durante a fase de requisitos de um projeto, os analistas podem
Scrum e a modelagem de software14
levar os casos de uso ao próximo nível, fornecendo um nível mais formal de
refi namento. Quando isso ocorre, os casos de uso geralmente são refi nados
em um ou mais diagramas de sequência (BELL, 2004).
A equipe técnica de uma organização pode considerar diagramas de se-
quência úteis para documentar como um sistema futuro deve se comportar.
Durante a fase de projeto, arquitetos e desenvolvedores podem usar o diagrama
para definir as interações entre os objetos do sistema, aprimorando, dessa
maneira, o seu projeto geral.
Um dos principais usos dos diagramas de sequência é para a transição
dos requisitos expressos como casos de uso para o próximo e mais formal
nível de refinamento. Os casos de uso são frequentemente refinados em um
ou mais diagramas de sequência. Além de serem usados no projeto de novos
sistemas, os diagramas de sequência podem ser usados para documentar
como os objetos em um sistema existente (chamado de “legado”) atualmente
interagem. Esta documentação é muito útil ao fazer a transição de um sistema
para outra pessoa ou organização.
Um diagrama de sequência é composto dos elementos principais a seguir
(GEEKS FOR GEEKS, [2019?]).
Ator: representa um tipo de papel (usuários, sistemas externos etc.)
passível de interação com o sistema e com seus objetos. É importante
observar que um ator está sempre fora do escopo do sistema que está
sendo modelado.
Linhas de vida: uma linha de vida é um elemento que representa um
participante individual em um diagrama de sequência. Logo, cada
instância em um diagrama de sequência é representada por uma linha de
vida. Os elementos da linha de vida estão localizados na parte superior
de um diagrama de sequência.
Mensagens: a comunicação entre objetos é representada usando men-
sagens. As mensagens aparecem em uma ordem sequencial na linha
de vida e são representadas graficamente por setas. Linhas de vida e
mensagens formam o núcleo de um diagrama de sequência.
15Scrum e a modelagem de software
Em um diagrama de sequência, uma linha de vida sempre retrata um objeto interno ao
sistema, enquanto os atores são usados para representar objetos externos ao sistema.
A Figura 5 apresenta um diagrama de sequência com os seus componen-
tes principais e outros adicionais. Neste exemplo, um fluxo de interações é
retratado para a funcionalidade de ser fazer login (autenticar) em um sis-
tema. Inicialmente, um usuário chama o método informaDados do objeto
telaLogin, fornecendo os dados de login e senha. Na sequência, o objeto
telaLogin envia uma mensagem com o objetivo de consultar os dados do
usuário. Para isso, ele repassa as informações de login e senha. O retorno desta
mensagem é armazenado em usuarioOk. A seguir, um teste de autenticação é
executado: se usuarioOk for igual a True (verdadeiro), a telaLogin envia
uma mensagem do tipo Create para o objeto telaPrincipal. Por fim, o
objeto telaLogin envia para si mesmo uma mensagem do tipo Destroy.
Figura 5. Exemplo de diagrama de sequência.
Fonte: Oliveira ([2013], documento on-line).
Scrum e a modelagem de software16
Conforme apresentado, diversos diagramas são disponibilizados pela
UML, oferecendo um grande poder de expressão para a documentação e para
a modelagem de sistemas. Embora o manifesto ágil tenha impulsionado uma
relevante discussão a respeito do uso da UML em processos de desenvolvimento
ágeis, a linguagem persiste como uma poderosa ferramenta para facilitar a
comunicação entre equipes técnicas e profissionais de outras áreas. Logo,
o conhecimento sobre os principais diagramas UML pode representar uma
habilidade a ser bem aproveitada no mercado de trabalho.
AMIT. All you need to know about uml diagrams: types and 5+examples. [2018?]. Dispo-
nível em: https://tallyfy.com/uml-diagram/. Acesso em: 10 jun. 2020.
BECK, K. et al. Manifesto for Agile software development. c2001. Disponível em: http://
www.agilemanifesto.org. Acesso em: 10 jun. 2020.
BELL, D. The sequence diagram. 2004. Disponível em: https://developer.ibm.com/tech-
nologies/web-development/articles/the-sequence-diagram/. Acesso em: 10 jun. 2020.
COBB, C. Is UML still relevant today?: how is it used in an Agile environment? c2020.
Disponível em: https://managedagile.com/is-uml-still-relevant-today/. Acesso em:
10 jun. 2020.
CREATELY. UML diagram types guide: learn about all types of UML diagrams with exam-
ples. 2019. Disponível em: https://creately.com/blog/diagrams/uml-diagram-types-
-examples/. Acesso em: 10 jun. 2020.
GALLUD, J. A.; FARDOUN, H. M. UML and Agile methods: looking for an agreement. In:
INTERNATIONAL CONFERENCE ON SOFTWARE TECHNOLOGIES, 13., 2018, Porto. Proce-
edings […]. Setúbal: Science and Technology Publications, 2018. p. 780–785. Disponível
em: https://www.scitepress.org/Papers/2018/69409/69409.pdf. Acesso em: 10 jun. 2020.
GEEKS FOR GEEKS. Unified Modeling Language (UML): sequence diagrams. [2019?].
Disponível em: https://www.geeksforgeeks.org/unified-modeling-language-uml-
-sequence-diagrams/. Acesso em: 10 jun. 2020.
GURU99. Component diagram: UML tutorial with example. c2020. Disponível em https://
www.guru99.com/component-diagram-uml-example.html. Acesso em: 10 jun. 2020.
LUCIDCHART. Types of UML diagrams. c2020. Disponível em: https://www.lucidchart.
com/blog/types-of-UML-diagrams. Acesso em: 10 jun. 2020.
MAKSIMCHUCK, R. A.; NAIBURG, E. J. Introduction to UML. 2004. Disponível em https://
www.informit.com/articles/article.aspx?p=347699&seqNum=3. Acesso em: 10 jun. 2020.
17Scrum e a modelagem de software
OBJECT MANAGEMENT GROUP. About the Unified Modeling Language specification ver-
sion 2.5.1. 2017. Disponível em https://www.omg.org/spec/UML/About-UML/. Acesso
em: 10 jun. 2020.
OLIVEIRA, L. V. UML: diagramas de sequência. [2013]. Disponível em: http://www.theclub.
com.br/restrito/revistas/201308/umld1308.aspx. Acesso em: 10 jun. 2020.
RIBEIRO, A. M. [Glossário UML:] diagrama de componentes. [20––?]. Disponível em:
https://homepages.dcc.ufmg.br/~amendes/GlossarioUML/glossario/conteudo/com-
ponentes/diagrama_de_componentes.htm. Acesso em: 10 jun. 2020.
RIBEIRO, L. O que é UML e diagramas de caso de uso: introdução prática à UML. 2012.
Disponível em: https://www.devmedia.com.br/o-que-e-uml-e-diagramas-de-caso-
-de-uso-introducao-pratica-a-uml/23408. Acesso em: 10 jun. 2020.
SAUVÉ, J. P. UML: Unified Modeling Language: uma breve história. [20––?]. Disponível
em http://www.dsc.ufcg.edu.br/~jacques/cursos/map/html/uml/historia_uml/histo-
ria_uml.htm. Acesso em: 10 jun. 2020.
SPARX SYSTEMS. UML structural models. c2020. Disponível em: https://sparxsystems.
com/enterprise_architect_user_guide/14.0/model_domains/structuraldiagrams.html.
Acesso em: 10 jun. 2020.
SYBASE. Chaptaer 4: building use case diagrams. c2006. Disponível em: http://infocenter-
-archive.sybase.com/help/index.jsp?topic=/com.sybase.stf.powerdesigner.docs_12.1.0/
html/clug/clugp157.htm. Acesso em: 10 jun. 2020.
TUTORIALS POINT. UML: component diagrams. c2020. Disponível em: https://www.
tutorialspoint.com/uml/uml_component_diagram.htm. Acesso em: 10 jun. 2020.
UML-DIAGRAMS. The Unified Modeling Language. c2020. Disponível em: https://www.
uml-diagrams.org/. Acesso em: 10jun. 2020.
VENTURA, P. Entendendo o diagrama de classes da UML. 2019. Disponível em: https://
www.ateomomento.com.br/uml-diagrama-de-classes/. Acesso em: 10 jun. 2020.
VISUAL PARADIGM. UML class diagram tutorial. c2020. Disponível em: https://www.
visual-paradigm.com/guide/uml-unified-modeling-language/uml-class-diagram-
-tutorial/. Acesso em: 10 jun. 2020.
Os links para sites da web fornecidos neste capítulo foram todos testados, e seu fun-
cionamento 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.
Scrum e a modelagem de software18
ENGENHARIA
DE SOFTWARE
Aline Zanin
Izabelly Soares
de Morais
Revisão técnica:
Jeferson Faleiro Leon
Desenvolvimento de Sistemas
Especialista em Formação Pedagógica de Professores
Catalogação na publicação: Karin Lorien Menoncin CRB-10/2147
M827e Morais, Izabelly Soares de.
Engenharia de software [recurso eletrônico] / Izabelly
Soares de Morais, Aline Zanin ; revisão técnica : Jeferson
Faleiro Leon. – Porto Alegre : SAGAH, 2017.
ISBN 978-85-9502-253-9
Engenharia. 2. Engenharia de software auxiliada por
computador. I. Zanin, Aline. II. Título.
CDU 004.41
Conhecer e construir
diagrama de casos de uso
Objetivos de aprendizagem
Ao final deste texto, você deve apresentar os seguintes aprendizados:
� Explicar o objetivo do diagrama de casos de uso.
� Aplicar os elementos do diagrama de casos de uso.
� Realizar a análise do diagrama de casos de uso.
Introdução
O diagrama de casos de uso descreve a funcionalidade proposta para um
novo sistema que será projetado e é uma excelente ferramenta para o
levantamento dos requisitos funcionais do sistema. Este diagrama não é
utilizado apenas para o time interno de desenvolvimento de um software,
mas também para apresentar ao cliente as funcionalidades que terão no
sistema. Sua forma de criação é bastante simples, tendo poucas formas
geométricas para representar um caso de uso.
Neste capítulo, você vai adquirir conhecimentos fundamentais para
avançar no aprendizado sobre os diagramas de casos de uso. Você vai
ver, também, os objetivos e os elementos do diagrama, as informações
importantes e os cuidados ao criar um diagrama.
Diagrama de casos de uso
A UML, Linguagem de Modelagem Unificada (do inglês Unified Modeling
Language), traz para o contexto computacional a padronização de uma lingua-
gem utilizada para representar informações referentes a um sistema, ou seja, a
sua aplicação pode estar ligada a diversas etapas que contemplam o processo
de desenvolvimento de um software. Cada diagrama traz um conjunto de
possibilidades, em que essas informações são mostradas de maneiras distintas.
Conforme Larman (2007, p. 87), casos de uso são narrativas em texto,
amplamente utilizadas para descobrir e registrar requisitos. Eles influenciam
muitos aspectos de um projeto, inclusive a POO (programação orientada a
objetos), e servem de entrada para vários artefatos subsequentes nos estudos
de caso. Metas de alto nível e diagramas de casos de uso são utilizados como
entrada para a criação do texto do caso de uso. Os casos de uso, por sua vez,
influenciam muitos outros artefatos de análise, projeto, implementação, gestão
de projeto e teste.
Este capítulo aborda o diagrama de caso de uso, o qual “identifica os atores
envolvidos em uma interação e dá o nome ao tipo de interação. Essa é, então,
suplementada por informações adicionais que descrevem a interação com o
sistema. A informação adicional pode ser uma descrição textual ou um ou mais
modelos gráficos. Os casos de uso são documentados por um diagrama de casos
de uso de alto nível. O conjunto de casos de uso representa todas as possíveis
interações que serão descritas nos requisitos de sistema” (SOMMERVILLE,
2011, p. 74). O próximo tópico traz as particularidades de um caso de uso.
Existem softwares com a finalidade de possibilitar a construção de diagramas, dentre
os diversos existentes podemos destacar o Astah, o qual pode ser gratuito, ter alguma
limitação de uso ou exigir alguma assinatura ou compra de licença para uso. Porém,
permite que os diagramas sejam construídos de forma organizada e clara.
Outras ferramentas que podem ser utilizadas para modelagem de caso de uso são:
� Omondo: Plugin para Eclipse (http://www.omondo.com/)
� Jude (https://jude.change-vision.com/jude-web/)
� Together (http://www.borland.com/products/downloads/download_together.html)
� IBM Rational Rose (http://www.ibm.com/software/rational)
Conhecer e construir diagrama de casos de uso2
http://www.omondo.com/
https://jude.change-vision.com/jude-web/
http://www.borland.com/products/downloads/download_together.html
http://www.ibm.com/software/rational
Elementos do diagrama de caso de uso
Os casos de uso trazem narrativas que englobam as funcionalidades do sistema,
mais precisamente os requisitos funcionais, em que alguns elementos são
fundamentais para a construção do diagrama. Dentre eles, Larman (2007),
destaca:
� Um ator é algo com comportamento, tal como uma pessoa (identificada
por seu papel), um sistema de computador ou uma organização; por
exemplo, um caixa. A representação do ator está exposta na Figura 1
a seguir.
Figura 1. Representação do ator, no caso
de uso.
3Conhecer e construir diagrama de casos de uso
� Um cenário é uma sequência especifica de ações e interações entre
atores e o sistema. É também chamado de instância de caso de uso. É
uma história particular de uso de um sistema ou um caminho através do
caso de uso; por exemplo, o cenário de efetuar com sucesso a compra
de itens em dinheiro, ou o cenário de não consumar a compra de itens
por causa da recusa de uma autorização de crédito (Figura 2).
Figura 2. Representação de um cenário, no caso de uso.
Conhecer e construir diagrama de casos de uso4
Os casos de uso podem ter três tipos de relacionamento: associação, ge-
neralização e dependência (inclusão ou extensão). A Figura 3 traz, além do
cenário e do ator, a representação gráfica determinada pela UML, para o
próprio caso de uso, em que o “traço” que liga o ator ao caso de uso representa
a associação entre o ator e o caso de uso.
Figura 3. Representação da associação e caso de uso.
Devemos estar cientes de que todo caso de uso deve ter um nome, o qual
deve vir descrito em seu interior, o que remete a sua funcionalidade, como
pagar, registrar, dentre outras possibilidades. O caso de uso busca expor o
que o sistema faz, e não como ele executa determinada funcionalidade. Por
este motivo, utilizamos verbos nos casos de uso, os quais indicam uma ação
a ser executada.
5Conhecer e construir diagrama de casos de uso
Na generalização, o caso de uso filho herda o comportamento e o significado
do caso de uso pai, em que o caso de uso filho pode incluir ou sobrescrever
o comportamento do caso de uso pai ou o caso de uso filho pode substituir o
caso de uso pai em qualquer lugar em que ele apareça (LABORATÓRIO DE
ENGENHARIA DE SOFTWARE, [2017]), como mostra a Figura 4 a seguir.
Figura 4. Representação de uma generalização.
Fonte: adaptada de Laboratório de Engenharia de Software [2017].
De acordo com Schach (2010, p. 542), “na UML, um estereótipo é uma
forma de estender a UML, isto é, se precisarmos definir uma construção que
não exista na UML, podemos fazê-lo. A relação include é tratada em UML
como um estereótipo, daí a notação «include», a qual é utilizada para denotar
funcionalidade comum. Outra relação é a relação extend, em que um caso
de uso é uma variação do caso de uso padrão”. A Figura 5 a seguir traz um
exemplo prático.
Conhecer e construir diagrama de casosde uso6
Figura 5. Representação de um caso de uso.
Utilizamos include para definir que um caso de uso precisa obrigatoriamente
do outro para ser executado, como mostrado na Figura 4, que traz algumas
funcionalidades de um sistema bancário, em que um cliente só poderá “sacar
dinheiro” caso o cadastro dele seja conferido. Ele também tem a opção de
retirar o extrato, essa funcionalidade pode ser executada apenas se alguma
condição for atendida, ou seja, ela não é uma funcionalidade obrigatória, por
isso traz o extend. Observe que, ao utilizar esses recursos, você deve utilizar
uma linha pontilhada e uma seta, para indicar qual caso tem dependência do
outro. Veja no Quadro 1 a seguir os detalhes e o gabarito para elaborar um
caso de uso.
7Conhecer e construir diagrama de casos de uso
Fonte: Larman (2007, p. 93).
Seção do caso de uso Comentário
Nome do caso de uso Começar com um verbo
Escopo O sistema em projeto
Nível “Objetivo do usuário” ou “subfunção”
Ator principal Chama o sistema para
fornecer os serviços
Interessados e interesses Quem se importa com este caso
de uso e o que eles desejam?
Pré-condições O que precisa ser verdade de início
e vale a pena dizer ao leitor?
Garantia de sucesso O que precisa ser verdade quando
da finalização bem sucedida e
se vale a pena dizer ao leitor
Cenário de sucesso principal Um caminho típico, incondicional
e otimista do cenário de sucesso
Extensões Cenários alternativos de sucesso
Requisitos especiais Requisitos não funcionais relacionados
Lista de variantes
tecnológicas e de dados
Métodos de entrada e saída e
formatos de dados variáveis
Frequência de ocorrência Influencia a investigação, teste e
oportunidade da implementação
Diversos Como, por exemplo,
pontos em aberto
Quadro 1. Gabarito para elaborar um diagrama de caso de uso.
Conhecer e construir diagrama de casos de uso8
Análise de um diagrama de caso de uso
Casos de uso são uma boa maneira de manter “a coisa” simples e de tornar
possível a especialistas no domínio ou a fornecedores de requisitos escrever
eles mesmos (ou participar da escrita de) casos de uso. Outro valor dos casos
de uso é que eles enfatizam os objetivos e perspectivas do usuário. Formulamos
a questão “quem está usando o sistema, quais são seus típicos cenários de uso
e quais são os seus objetivos?”. Essa é uma ênfase mais centrada no usuário,
comparada a simplesmente solicitar uma lista de características do sistema
(LARMAN, 2007, p. 91).
Para Sommerville (2011, p. 75), cenário e casos de uso são técnicas eficazes
para elicitar requisitos dos stakeholders, ou seja, dos envolvidos no processo
de desenvolvimento do software (clientes, equipe de desenvolvimento), que
vão interagir diretamente com o sistema, em que cada tipo de interação pode
ser representado como um caso de uso. No entanto, devido a seu foco nas
interações com o sistema, eles não são tão eficazes para elicitar restrições
ou requisitos de negócios nem funcionais em alto nível ou para descobrir
requisitos de domínio.
A análise de um caso de uso deve ser realizada tendo como base as especifi-
cações do sistema, ou seja, eles devem estar de acordo com as funcionalidades
estabelecidas provavelmente no documento de requisitos, tendo em vista que
ele trará os requisitos funcionais de maneira gráfica, utilizando a representação
gráfica de um caso de uso.
9Conhecer e construir diagrama de casos de uso
No exemplo a seguir, podemos visualizar um diagrama de caso de uso no qual todos
os elementos gráficos estão sendo utilizados.
Fonte: Schach (2010, p. 357).
Podemos notar que o cenário apresentado retrata um contexto escolar, no qual
os atores são: funcionário, usuário, aluno e professor, e os casos de uso são: cadastrar
exemplares, cadastrar usuários, fazer empréstimos e fazer consulta. Nota-se que, além
de fazer parte de um contexto escolar, contempla funcionalidades de um sistema de
biblioteca.
Conhecer e construir diagrama de casos de uso10
Conforme Leite (2000), para modelar os requisitos de software de um
sistema, podemos seguir as seguintes regras:
� Estabeleça o contexto do sistema identificando os atores (usuários e
sistemas externos) associados a ele.
� Para cada ator, considere o comportamento que cada um deles espera
ou requer que o sistema tenha, para que as suas metas sejam satisfeitas.
� Considere cada um destes comportamentos esperados como casos de
uso, dando nomes para cada um deles.
� Analise os casos de uso tentando identificar comportamentos comuns a
mais de um deles. Defina essa parte comum como caso de uso genérico,
estabelecendo um relacionamento de generalização. Tente identificar
outros relacionamentos, como a dependência entre casos de uso que
incluem o comportamento de outros.
� Modele esses casos de uso, atores e seus relacionamentos em diagramas
de casos de uso.
� Complemente esses casos de uso com notas que descrevam requisitos
não funcionais.
Além destas regras básicas, algumas dicas ajudam a construir diagramas
mais claros:
� Dê nomes que comuniquem o seu propósito.
� Quando existirem relacionamentos, distribua os casos de uso de maneira
a minimizar os cruzamentos de linhas.
� Organize os elementos espacialmente de maneira com que aqueles que
descrevem comportamentos associados fiquem mais próximos.
� Use notas para chamar a atenção de características importantes – as
notas não são apenas para os requisitos não funcionais.
� Não complique o diagrama, coloque apenas o que é essencial para
descrever os requisitos. O diagrama deve ser simples sem deixar de
mostrar o que é relevante.
Apesar de as regras serem elencadas para a construção de um caso de
uso, elas são úteis também para sua análise, tendo em vista que precisamos
conhecer essas etapas de desenvolvimento de um caso de uso para que pos-
samos analisá-lo.
11Conhecer e construir diagrama de casos de uso
LABORATÓRIO DE ENGENHARIA DE SOFTWARE. UML: Caso de uso.. Rio de Janeiro:
PUC Rio. s/d. Disponível em: http://www.les.inf.puc-rio.br/wiki/images/6/61/Aula01-
-diagrama_casos_uso.pdf. Acesso em: 07 set. 2017.
LARMAN, C. Utilizando UML e padrões: uma introdução à análise e ao projeto orien-
tados a objetos e ao desenvolvimento iterativo. 3.ed.Porto Alegre: Bookman, 2007.
LEITE J. C. Análise e Especificação de Requisitos. Notas de aula de Engenharia de Sof-
tware, Natal, 2000. Disponível em: <https://www.dimap.ufrn.br/~jair/ES/c4.html/>.
Acesso em: 04 set. 2017.
SCHACH, S.R. Engenharia de software: os paradigmas clássicos e orientado a objetos.
7. ed. Porto Alegre: AMGH, 2010.
SOMMERVILLE, I. Engenharia de software. 9. ed. São Paulo: Pearson, 2011.
Leituras recomendadas
PFLEEGER, S. Engenharia de Software: teoria e prática. 2. ed. Upper Saddle River:
Prentice-Hall, 2004.
PRESSMAN, R. S.; MAXIM, B. R. Engenharia de Software: uma abordagem profissional.
8. ed. Porto Alegre: AMGH, 2016.
Conhecer e construir diagrama de casos de uso12
http://www.les.inf.puc-rio.br/wiki/images/6/61/Aula01-
https://www.dimap.ufrn.br/~jair/ES/c4.html/
Encerra aqui o trecho do livro disponibilizado para
esta Unidade de Aprendizagem. Na Biblioteca Virtual
da Instituição, você encontra a obra na íntegra.
Conteúdo:
ANÁLISE E PROJETO
DE SISTEMAS
Cleverson Lopes Ledur
Revisão técnica:
Jeferson Faleiro Leon
Desenvolvedor de Sistemas
Especialista em Formação Pedagógica de Professores
Professor de curso Técnico em informática
Catalogação na publicação: Ana Paula M. Magnus – CRB 10/2052
L475a Ledur, Cleverson Lopes
Análise e projeto de sistemas [recurso eletrônico] /
Cleverson Lopes Ledur ; [revisão técnica: Jeferson Faleiro
Leon]. – Porto Alegre : SAGAH, 2017.
ISBN 978-85-9502-179-2
1. Computação. 2. Projeto de sistemas. 3. Análise de
projeto. I. Título.
CDU 004.41
Elaborar diagrama
de classes
Objetivos de aprendizagem
Ao final deste texto, você deve apresentar os seguintes aprendizados:
Reconhecer os conceitos básicossobre o diagrama.
Identifi car as relações entre as classes, seus atributos e métodos básicos.
Elaborar o diagrama de classes adequadamente.
Introdução
Os diagramas da UML são divididos em duas categorias básicas: dia-
gramas de estrutura e diagramas de comportamento. Cada um dos
diagramas da UML está dentro de uma dessas categorias. Pode-se dizer
que o objetivo dos diagramas estruturais é mostrar a estrutura estática
que o sistema terá. Esse tipo de categoria inclui os diagramas de classe, de
componente e de objetos. Já os diagramas comportamentais possuem
como objetivo mostrar o comportamento dinâmico entre os objetos.
Dentro dos diagramas estruturais, encontra-se o diagrama de classes,
que oferece um diagrama muito interessante em termos de estrutura,
devido à sua riqueza de elementos, que permite a descrição de sistemas.
Neste texto, você vai entender como e quando utilizar o diagrama de
classes, seus elementos e relações, além de alguns pontos importantes
que devem ser considerados ao criá-lo.
Diagrama de classes: conceitos básicos
Serão apresentados alguns conceitos essenciais sobre o diagrama de classes.
Segundo a UML, um diagrama de classes oferece três perspectivas diferentes,
cada uma focada em atender às necessidades de informação de diferentes
observadores (AMBLER, 2016). Essas perspectivas são classifi cadas em:
Conceitual: direcionada para a representação dos conceitos do domínio
em estudo ou destinada ao cliente.
Especificação: direcionada para as principais interfaces da arquitetura,
nos principais métodos e suas implementações. Também, é direcionada
para aqueles que não precisam saber detalhes sobre o desenvolvimento.
Implementação: esta é a representação mais utilizada que demonstra
detalhes de implementação, navegabilidade, atributos e é voltada para
o time de desenvolvimento.
Você pode ver exemplos destes três tipos de modelos
no link a seguir:
https://goo.gl/3eMdA
De forma geral, pode-se dizer que o propósito do diagrama de classes é
mostrar os tipos que estão sendo modelados no sistema (AMBLER, 2016).
Quando se fala em elementos do diagrama de classes, podem ser citados alguns
dos seguintes itens (que logo mais serão detalhados):
Classe.
Interface.
Tipo de dado.
Componente.
É dito que na engenharia de software, um diagrama de classes na Unified
Modeling Language (UML) é um tipo de diagrama de estrutura estática, que
descreve a estrutura de um sistema, que mostra as classes do sistema, seus
atributos, as operações (ou métodos) e as relações entre objetos.
Elaborar diagrama de classes88
Assim, o diagrama de classes é o bloco de construção principal da mode-
lagem orientada a objetos. É usado tanto para modelagem conceitual geral,
quanto para a sistemática da aplicação e para modelagem detalhada, na tradução
dos modelos para o código de programação. Os diagramas de classes também
podem ser usados para modelagem de dados. As classes, em um diagrama de
classes, representam os principais elementos, as interações na aplicação e as
classes a serem programadas.
Na concepção de um sistema, várias classes são identificadas e agrupadas
em um diagrama de classes, ajudando a determinar as relações estáticas entre
elas. Com a modelagem detalhada, as classes do projeto conceitual são muitas
vezes divididas em várias subclasses.
Para descrever melhor o comportamento dos sistemas, esses diagramas de
classes podem ser complementados por um diagrama de estado ou máquina
de estado UML.
Classe
Classes são uma descrição de um grupo de objetos com papéis semelhantes
no sistema. A partir das classes, podemos criar os objetos (instâncias). As
características estruturais defi nem o que os objetos de classe sabem. Já as
características comportamentais defi nem o que os objetos de classe podem
fazer (KIM; CARRINGTON, 1999).
Os objetos derivam de:
Coisas: objetos tangíveis, do mundo real etc.
Papéis/funções: classes de atores em sistemas, como por exemplo,
estudantes, gerentes, enfermeiros etc.
Eventos: admissão, inscrição, matrícula etc.
Interações: reuniões, tutoriais etc.
No diagrama de classes, se representa uma classe utilizando um retângulo.
O nome da classe fica no topo do retângulo, geralmente, em negrito. Logo
a seguir, são declarados os atributos e os métodos/operações (AMBLER,
2016). A Figura 1 apresenta um exemplo de classe representada no diagrama
de classes, em que o nome da classe é sempre obrigatório.
89Elaborar diagrama de classes
Figura 1. Representação de uma classe no diagrama
de classes.
Voo
- id : Integer
- horario_partida : Date
- duracao_voo : Integer
- aeroporto_saida: String
- aeroporto_chegada : String
+ atrasarVoo(minutos : int) : void
+ getHorarioChegada( ) : Date
É possível ver que no compartimento superior contém o nome da classe
Voo. Ele é impresso em negrito, centralizado e a primeira letra é maiúscula.
Já o compartimento do meio contém os atributos da classe. Eles são alinhados
à esquerda e a primeira letra é minúscula. Por fim, no compartimento inferior
consta as operações que a classe pode executar, também alinhadas à esquerda
e a primeira letra é minúscula.
Atributo
Atributos representam o estado de um objeto da classe. São descrições da
estrutura ou das características de uma classe. No diagrama de classes, os
atributos são listados na parte do meio do retângulo que representa uma classe.
Nele, deve-se inserir o nome do atributo, seguido por dois pontos e qual o tipo
de dado do atributo (Figura 2).
Figura 2. Representação de atributos no
diagrama de classes.
- id : Integer
- horario_partida : Date
- duracao_voo : Integer
- aeroporto_saida: String
- aeroporto_chegada : String
Elaborar diagrama de classes90
Na Figura 2, tem-se um exemplo de atributos que foi extraído da classe
Voo. Repare que os nomes (id, horário_partida, duracao_voo, aeroporto_saida,
aeroporto_chegada) estão do lado esquerdo dos pontos, e do lado direito o
tipo de dado (Integer, Date, Integer, String, String). A definição dos atributos
no diagrama de classes é opcional (AMBLER, 2016).
Operações/métodos de classe
Um método na programação orientada a objetos é um procedimento associado
a uma mensagem e a um objeto. Um objeto é composto, principalmente, de
dados e comportamentos, que formam a interface que um objeto apresenta
ao mundo exterior. Os dados são representados como propriedades do objeto
e o comportamento como métodos.
Assim como os atributos, os métodos também possuem tipos. No caso
dos métodos, o tipo associado é relacionado ao valor que será retornado ao
fim da computação.
Em um diagrama de classes, os métodos encontram-se dentro da classe.
No interior de uma classe, se tem as definições de operações/métodos na parte
inferior do retângulo que representa a classe (BELL, 2016). Cada método
deve ficar em uma linha, e assim como nos atributos, o tipo de retorno do
método é colocado após os dois pontos, do lado direito. Neste elemento, há a
adição dos argumentos que serão passados para o método. Na Figura 3, por
exemplo, é possível perceber o método atrasarVoo e o argumento minutos
sendo passado como um valor inteiro. No caso desse método em específico,
ele retorna a um valor void.
Figura 3. Representação de métodos no dia-
grama de classes.
+ atrasarVoo(minutos : int) : void
+ getHorarioChegada( ) : Date
91Elaborar diagrama de classes
Visibilidade
Uma das notações que existe no diagrama de classes é a visibilidade. A es-
pecifi cação UML não solicita que a visibilidade de atributos e operações seja
exibida no diagrama de classes, mas requer que ela seja defi nida para cada
atributo e operação. Para exibir a visibilidade no diagrama de classes, se deve
colocar a marca de visibilidade na frente do nome do atributo ou da operação
(BELL, 2016).
Embora, a UML especifique quatro tipos de visibilidade, uma linguagem
de programação real pode incluir visibilidades adicionais ou pode não suportaras visibilidades definidas pela UML. Veja na listagem abaixo, as visibilidades
que se encontram na especificação UML:
+ public (público)
- private (privado)
~ package (package)
# protected (protegido)
Pacotes
Um pacote é um espaço usado para agrupar elementos que são semanticamente
relacionados e podem ser alterados de forma unifi cada. É um mecanismo de
propósito geral para organizar elementos em grupos para fornecer uma melhor
estrutura para o modelo do sistema.
Os membros pertencentes a um pacote devem ser todos elementos de
pacotes. Se um pacote é removido de um modelo, todos os elementos perten-
centes ao pacote também serão removidos. O pacote por si só é um elemento,
portanto, qualquer pacote pode ser também um membro de outros pacotes
ou conter outros pacotes.
Como o pacote é um espaço, os elementos relacionados ou de um mesmo
tipo devem ter nomes únicos dentro do pacote envolvente. Diferentes tipos de
elementos podem ter o mesmo nome. Além disso, um pacote pode importar
membros individuais de outros pacotes ou todos os membros de outros pacotes.
Também, o pacote pode ser mesclado com outros pacotes.
Um pacote é processado como uma pasta com abas, um retângulo com uma
pequena aba anexada ao lado esquerdo da parte superior do retângulo. Se os
membros do pacote não forem mostrados dentro do retângulo da embalagem,
o nome da embalagem deve ser colocado no interior.
Elaborar diagrama de classes92
Quando se está modelando um grande sistema, é preciso modularizá-lo
de forma que seja possível desenvolvê-lo de forma adequada e permitir uma
fácil manutenção depois. No diagrama de classes, se pode contar com os
elementos do pacote para dividir o sistema em subsistemas (BELL, 2016).
Os pacotes permitem que os modeladores organizem os classificadores de
modelo em namespaces, semelhante às pastas em um sistema de arquivamento.
Dividir um sistema em vários pacotes, facilita o entendimento do sistema,
principalmente se cada pacote representar uma parte específica do sistema.
A Figura 4 apresenta o elemento pacote conforme a UML.
Figura 4. Representação de pacotes
no diagrama de classes.
Pacote
Um exemplo seria de um sistema de aeroporto, onde há um módulo de
gerenciamento de voos chamado SistemaVoos. A Figura 5 apresenta o uso do
pacote em um diagrama deste tipo.
Figura 5. Exemplo do uso de pacotes no diagrama de classes.
SistemaVoos
Voo
- id : Integer
- horario_partida : Date
- duracao_voo : Integer
- aeroporto_saida: String
- aeroporto_chegada : String
+ atrasarVoo(minutos : int) : void
+ getHorarioChegada( ) : Date
Aviao
- tipo : String
- velocidade_max : MPH
- distancia_max : Km
voos_solicitados
0..10..*
- aviaoReservado
93Elaborar diagrama de classes
O pacote pode ser usado como um modelo para outros pacotes. A especi-
ficação UML chama esse tipo de pacote de template package. O elemento do
pacote pode ser usado como um parâmetro do modelo. Com isso, um parâmetro
de modelo do pacote pode se referir a qualquer elemento de propriedade,
podendo ser usado um modelo do pacote ou modelos aninhados dentro dele.
Veja na Figura 6 um exemplo de template package.
Figura 6. Exemplo de um template package.
Fonte: UML Diagrams (2017).
ServiceProvider
template name
template
binding
package template
bound package
formal template parameters
ServiceType
«bind»
< ServiceFactory -> SchedulerFactory,
ServiceType -> Scheduler >
+lookup(name: String):
Service Factory
ServiceFactory
SchedulerService
«Singleton»
ServiceLocator
«use»
1
context InitialContext
ServiceFactory, ServiceType
Um pacote pode também estar vinculado a um ou mais pacotes de modelos.
Quando várias ligações são aplicadas, o resultado das ligações é produzido
tomando-se os resultados intermediários e incorporando-os no resultado
combinado com o uso da combinação de pacotes.
Elaborar diagrama de classes94
Nomeação de pacotes e domínio invertido
A UML não especifi ca uma forma para a nomenclatura de pacotes, no entanto,
é recomendado que os nomes sejam defi nidos de forma que o pacote seja
universalmente único dentro de um projeto. Para isso, normalmente, usa-se
um caminho de domínio invertido, como por exemplo, br.com.sagah como
pacote principal. O pacote principal é seguido do nome do projeto/aplicação.
Dentro do pacote da aplicação são criados os pacotes para as outras partes da
aplicação, conforme a arquitetura utilizada.
Os nomes dos pacotes internos da aplicação devem tentar expressar o
propósito das classes da forma mais simples possível. Por exemplo, um pacote
que se chama br.com.sagah.app.validacao deverá conter classes que auxiliam
a validação. Os nomes dos pacotes não devem ser usados para dividir entres
camadas a sua aplicação. Podem ser usados em casos especiais para separar
entre nodos como br.com.sagah.app.server e br.com.sagah.app.client.
Relações entre as classes, seus atributos e
métodos básicos
Na UML, há diversas relações que podem ser utilizadas para determinar a forma
com que as classes se relacionam. As relações determinam que as instâncias
de uma classe estão, de alguma forma, ligadas às instâncias da outra classe.
No diagrama de classes tem-se os elementos para representar as relações
de associação, herança, dependência, agregação e composição. Cada uma
possui um elemento que faz a ligação entre as classes, algumas semelhantes
a setas. Você vai ver cada uma dela em detalhes. Mas antes, será falado das
multiplicidades que agregam informações para as relações.
Multiplicidades
As multiplicidades são utilizadas no diagrama de classes para informar a
quantidade de instâncias de objetos que uma classe pode ter em relação a outra
classe. Se tem defi nido pela UML cinco tipos diferentes de multiplicidades
(SCHACH, 2009). Acompanhe a lista a seguir de diferentes multiplicidades:
95Elaborar diagrama de classes
0..1
■ No máximo um. Indica que os objetos da classe associada não pre-
cisam obrigatoriamente estar relacionados.
1..1
■ Um e somente um. Indica que apenas um objeto da classe se relaciona
com os objetos da outra classe.
0..*
■ Muitos. Indica que podem haver muitos objetos da classe envolvidos
no relacionamento.
1..*
■ Um ou muitos. Indica que há pelo menos um objeto envolvido no
relacionamento.
3..5
■ Valores específicos.
Associação
As associações são defi nidas como relacionamentos estruturais entre as ins-
tâncias das classes e permitem especifi car que objetos de uma classe são
ligados a objetos de outras classes (BELL, 2016). Essa relação signifi ca que
as instâncias das classes são conectadas, seja fi sicamente ou conceitualmente.
Veja na Figura 7, um exemplo de uma associação entre a classe Voo e a classe
Aviao. Fique atento também para o uso das multiplicidades nas extremidades,
que foi apresentado anteriormente.
Figura 7. Representação de uma associação no diagrama de classes.
- voos solicitados - aviaoReservado
0..* 0..1
Aviao
- tipo : String
- velocidade_max : MPH
- distancia_max : Km
Voo
- id : Integer
- horario_partida : Date
- duracao_voo : Integer
- aeroporto_saida: String
- aeroporto_chegada : String
+ atrasarVoo(minutos : int) : void
+ getHorarioChegada( ) : Date
Elaborar diagrama de classes96
Dependência
As relações nomeadas dependência são relacionamentos de utilização. Nesse
tipo de relacionamento, uma mudança na especifi cação de um elemento altera
a especifi cação do elemento dependente. Assim, a dependência entre classes
indica que um objeto de uma classe usa serviços de objetos de outra classe
(AMBLER, 2016). Para esta relação utilizamos a seta tracejada (Figura 8).
Figura 8. Representação de uma dependência no diagrama de classes.
SistemaVoos
Voo
- id : Integer
- horario_partida : Date
- duracao_voo : Integer
- aeroporto_saida: String
- aeroporto_chegada : String
+ atrasarVoo(minutos : int) : void
+ getHorarioChegada( ) : Date
+ inserirBagagem(Bagagem b : int) : void
Aviao
- tipo : String- velocidade_max : MPH
- distancia_max : Km
voos_solicitados
0..10..*
- aviaoReservado
Bagagem
- id : Integer
- peso : Integer
- cliente_id : Integer
- altura : Integer
- largura : Integer
- profundidade : Integer
- voo_id : Integer
Observe na Figura 8, um exemplo de dependência entre os elementos Voo
e Bagagem. No item Voo há uma operação chamada InserirBagagem. Ela é
utilizada quando o avião é carregado com as bagagens. Logo, a classe voo
possui uma relação de dependência com a classe Bagagem.
97Elaborar diagrama de classes
Generalização
A generalização é um tipo de relacionamento entre um elemento geral (mais
amplo) e outro mais específi co. Ela é utilizada para expressar a herança (simples
e composta) de um elemento genérico para outro elemento. Esse elemento
usa a seta fechada.
Veja na Figura 9, onde há um exemplo utilizando-se uma classe Piloto
(genérica), que é generalizada para as classes PilotoPrincipal e CoPiloto. As
classes PilotoPrincipal e CoPiloto herdam todos os atributos da classe Piloto,
bem como suas operações/métodos.
Figura 9. Representação de uma generalização no
diagrama de classes.
Piloto
- id : Integer
- nome : String
- registro : Integer
CoPilotoPilotoPrincipal
Agregação
As agregações são um tipo de associação em que o objeto-parte é um atributo
do todo. Para tanto, os objetos-parte somente são criados se o todo, ao qual
estão agregados, seja criado. Utilizando a mesma classe Piloto, você verá um
exemplo de agregação, com uma classe Tripulação. A Figura 10 apresenta um
exemplo do uso da agregação.
Elaborar diagrama de classes98
Figura 10. Representação de uma agregação no diagrama de classes.
Piloto
- id : Integer
- nome : String
- registro : Integer
CoPiloto
Tripulacao
PilotoPrincipal
Composição
A composição é um relacionamento entre um elemento (o todo) e outros ele-
mentos (as partes), em que as partes só podem pertencer ao todo, sendo criadas
e destruídas com ele. A composição representa um vínculo forte entre duas
classes, pois, uma classe FILHA só faz sentido, se uma classe PAI existir. Se
a classe PAI for apagada, a classe FILHA automaticamente deixará de existir.
A Figura 11 mostra um exemplo do uso da composição:
Figura 11. Representação de uma com-
posição no diagrama de classes.
Empresa
- cnpj : int
- nome : string
- endereco : string
- ramo : string
+ visualizar ( ) : void
Funcionario
- cpf : int
- nome : string
- dataNascimento: date
+ listar( ) : void
99Elaborar diagrama de classes
Criação de um diagrama de classes
Nesta seção será falado sobre alguns pontos importantes ao se criar um
diagrama de classe, e também de outros recursos que podem ser utilizados
para criar um diagrama de classes adequadamente, com solidez e de fácil
compreensão.
Tópicos importantes
O design de um diagrama de classes pode ser conduzido pelo critério de
completude, dados ou responsabilidades.
Projeto conduzido por dados: identifica todos os dados e verifica
se estão cobertos por uma coleção de objetos das classes do sistema.
Projeto conduzido por responsabilidade: identifica todas as respon-
sabilidades do sistema e verifica se estão cobertas por uma coleção de
objetos das classes do sistema.
Passos para a criação de um diagrama de classes:
Identificar frases nominais: observe os casos de uso e identifique uma
frase nominal. Faça isso de forma sistemática e não elimine nenhuma
possibilidade.
Elimine candidatos inapropriados: aqueles que são redundantes,
vagos, fora do escopo do sistema, um atributo do sistema etc.
Identifique os verbos: de forma geral, os verbos indicam os métodos
ou operações que são realizadas em uma classe.
Valide o modelo: verifique se você não selecionou alguma classe que
pode prejudicar o seu modelo.
Erros comuns de modelagem de domínio
Durante a criação de um diagrama de classes ou modelagem de domínio,
existem alguns erros comuns que são cometidos pelos profi ssionais. Esses
erros podem ocasionar modelos mal construídos, retrabalho e difi culdades
Elaborar diagrama de classes100
na implementação. Por isso, é muito importante sempre validar o modelo de
forma que não sejam cometidos estes erros. Veja alguns erros comuns que
são cometidos:
Análise excessiva da frase nominal: a etapa de análise nominal é
realizada de forma intensa, o que faz com que sejam coletados itens
que não são necessários.
Nomes de classe e associação incompreensíveis: é importante que
os nomes das classes e associações sejam claros e sem ambiguidades.
Atribuição de multiplicidades às associações prematuramente:
muitos profissionais, ao identificar as classes, já criam as associações
e inserem as multiplicidades sem antes analisar as possíveis alterações
que podem ser realizadas na estrutura. O ideal é que as multiplicidades
sejam inseridas ao final da estruturação do diagrama.
Abordagem das questões de implementação antes do tempo: a cria-
ção do diagrama de classes é realizada para representar um modelo.
O objetivo é que se for necessário realizar alterações, o modelo é fa-
cilmente modificado. Assim, o ideal é que as questões relacionadas às
implementações sejam verificadas na fase do ciclo de vida de projeto,
e não antes.
Comprometimento com as construções de implementação: como
o problema anterior, não é desejável que existam dependências com a
implementação durante a criação de um modelo.
Ferramentas para criar diagramas UML
Existem diversas ferramentas que podem ser utilizadas para a criação de
diagramas UML. Abaixo segue uma lista com algumas delas:
Umbrello - The UML Modeller https://umbrello.kde.org/
Astah http://astah.net/editions/community
Rational Rose http://www-03.ibm.com/software/products/pt/rosemod
ArgoUML http://argouml.tigris.org/
StarUML http://staruml.io/
Dia http://dia-installer.de/
101Elaborar diagrama de classes
AMBLER, S. W. UML 2 Class Diagram Guidelines. Agile Modeling, Toronto, 2016.
BELL, D. Fundamentos básicos de UML: o diagrama de classes. Uma introdução aos
diagramas de estrutura em UML 2. IBM developerWorks, Nova York, 2016.
KIM, S. K.; CARRINGTON, D. Formalizing the UML class diagram using Object-Z. In:
FRANCE, R.; RUMPE, B. (Ed.). UML’99: the unified modeling language. Berlin: Spring-
-Verlag, 1999. p. 753-753.
SCHACH, S. R. Engenharia de Software: os paradigmas clássico e orientado a objetos.
7. ed. Porto Alegre: McGraw-Hill, 2009.
UML DIAGRAMS. UML Package Diagrams, 2017. Disponível em: <http://www.uml-
-diagrams.org/package-diagrams.html>. Acesso em 7 set. 2017.
Leituras recomendadas
ANDRIYEVSKA, O. et al. Evaluating UML class diagram layout based on architectural
importance. In: IEEE INTERNATIONAL WORKSHOP ON VISUALIZING SOFTWARE FOR
UNDERSTANDING AND ANALYSIS. 3., Budpest, Sep. 2005. Proceedings… . Washington:
IEEE, 2005.
GUEDES, G. T. A. UML: uma abordagem prática. São Paulo: Novatec, 2008.
GUEDES, G. T. A. UML 2: guia prático.2. ed. São Paulo: Novatec , 2014.
PRESSMAN, R. S.; MAXIM, B. R. Engenharia de software: uma abordagem profissional.
8. ed. Porto Alegre: AMGH, 2016.
Elaborar diagrama de classes102
ANÁLISE E
PROJETO DE
SISTEMAS
Cleverson Ledur
Revisão técnica:
Jeferson Faleiro Leon
Desenvolvedor de Sistemas
Especialista em Formação Pedagógica de Professores
Professor de curso Técnico em informática
Catalogação na publicação: Ana Paula M. Magnus – CRB 10/2052
L475a Ledur, Cleverson Lopes
Análise e projeto de sistemas [recurso eletrônico] /
Cleverson Lopes Ledur ; [revisão técnica: Jeferson Faleiro
Leon]. – Porto Alegre : SAGAH, 2017.
ISBN 978-85-9502-179-2
1. Computação. 2. Projeto de sistemas. 3. Análise de
projeto. I. Título.
CDU 004.41
Elaborar o diagrama
de sequência
Objetivos de aprendizagem
Ao final deste capítulo, você deve apresentar os seguintes aprendizados:
� Compreender os conceitos básicos sobre o diagrama.
� Identificar as relações entre as camadas/objetos da solução.� Elaborar o diagrama de sequência adequadamente.
Introdução
Os diagramas de sequência descrevem as interações entre as classes em
termos de troca de mensagens ao longo do tempo. Eles também são
chamados de diagramas de eventos.
Um diagrama de sequência é uma boa maneira de visualizar e validar
vários cenários de tempo de execução. Eles podem ajudar a prever como
um sistema irá se comportar e a descobrir responsabilidades que uma
classe deve ter no processo de modelagem de um novo sistema.
Para criar um diagrama de sequência, você deve entender seus ele-
mentos. Atualmente, os elementos são criados em camadas, assim, é
muito importante saber expressar a interação de tais camadas através
do diagrama de sequência.
Neste texto, você irá compreender os conceitos básicos sobre o dia-
grama, irá estudar os passos que devem ser seguidos para a criação de
um diagrama de sequência, bem como introduzir o conceito de camadas
em uma solução.
Conceitos básicos
O diagrama de sequência é um diagrama de interação que mostra como os
objetos operam uns com os outros e em que ordem. É uma construção de
um gráfico de sequência de mensagens. Assim, um diagrama de sequência
mostra as interações dos objetos dispostos na sequência temporal. Ele retrata
os objetos e as classes envolvidas no cenário e a sequência de mensagens tro-
cadas entre os objetos necessários para executar a funcionalidade do cenário
(SARMA; KUNDU; MALL, 2008). Os diagramas de sequência, geralmente,
estão associados a realizações de casos de uso na visão lógica do sistema em
desenvolvimento. Às vezes eles são chamados de diagramas de eventos ou
cenários de eventos (FOWLER, 2003).
A forma gráfica do diagrama de sequência é composta por linhas verticais
paralelas (linhas de vida), por diferentes processos ou por objetos organizados
paralelamente e, como as setas horizontais, as mensagens trocadas entre eles,
estão na ordem em que ocorrem. Isso permite a especificação de cenários de
tempo de execução simples de forma gráfica. Veja na Figura 1 os principais
elementos de um diagrama de sequência.
Figura 1. Elementos de um diagrama de sequência.
Fonte: Laboratório de Engenharia de Software (2013).
Tempo
(top-down)
condição de guarda
mensagem síncrona
símbolo de destruição
mensagem (auto delegação)
objeto
<<destroy>>
valor de retorno
mensagem
[se novo]
<<create>>
(caixa de)ativação
linha de vida
ObjetoA
ObjetoB
Mensagens escritas com setas horizontais e o nome da mensagem acima,
exibem a interação. Cabeças de seta sólidas representam chamadas síncronas,
cabeças de seta aberta representam mensagens assíncronas e linhas tracejadas
representam mensagens de resposta. Se um chamador enviar uma mensagem
síncrona, deve aguardar até que a mensagem seja concluída, como invocar
uma sub-rotina. Se um chamador envia uma mensagem assíncrona, ele pode
Elaborar o diagrama de sequência2
continuar processando e não precisa esperar por uma resposta. Chamadas
assíncronas estão presentes em aplicativos multiprocessados e em middleware
orientado a mensagens. Caixas de ativação ou caixas de chamada de método
são retângulos opacos desenhados em cima das linhas de vida para representar
que os processos estão sendo executados em resposta à mensagem (Execu-
tionSpecifications in UML).
Os métodos de chamada de objetos em si mesmos usam mensagens e
adicionam novas caixas de ativação em cima de qualquer outro para indicar
um maior nível de processamento. Se um objeto é destruído (removido da me-
mória), um X é desenhado na parte inferior da linha de vida e a linha tracejada
deixa de ser desenhada abaixo. Deve ser o resultado de uma mensagem, seja
do próprio objeto ou de outra.
Uma mensagem enviada de fora do diagrama pode ser representada por
uma mensagem proveniente de um círculo preenchido (mensagem encontrada
em UML) ou de uma borda do diagrama de sequência (gate in UML). A
UML introduziu melhorias significativas nas capacidades dos diagramas de
sequência. A maioria dessas melhorias baseia-se na ideia de que fragmentos
de interação representam partes menores de uma interação envolvente. Múl-
tiplos fragmentos de interação são combinados para criar uma variedade de
fragmentos, que são usados para modelar interações que incluem paralelismo,
ramos condicionais e interações opcionais (FOWLER, 2003).
Você pode utilizar o software Astah ou Rational ROSE para criar os diagramas de
sequência. É possível baixá-lo neste link:
https://goo.gl/BXrVf
ou
https://goo.gl/QRrege
3Elaborar o diagrama de sequência
https://goo.gl/BXrVf
https://goo.gl/QRrege
Linhas de vida
Linha de vida ou lifeline é um elemento nomeado que representa um parti-
cipante individual na interação do diagrama de sequência. Embora, partes e
características estruturais possam ter uma multiplicidade superior a 1, as linhas
de vida representam apenas uma entidade interagindo ao longo das operações.
Se o elemento conectável referenciado for multivalorado (isto é, tem uma
multiplicidade maior do que 1), a linha de vida pode ter uma expressão (seletor)
que especifica qual parte particular é representada por esta linha de vida. Se o
seletor for omitido, isso significa que um representante arbitrário do elemento
conectivo multivaluado é escolhido. Veja na imagem a seguir um exemplo
de linha de vida:
Objeto
Uma linha de vida é mostrada com o uso de um símbolo que consiste em
um objeto, que pode ser, por exemplo, um retângulo, que forma sua cabeça
seguida de uma linha vertical, que pode ser tracejada para a representação
da vida útil do participante.
Às vezes, um diagrama de sequência terá uma linha de vida com um
símbolo de elemento de ator na sua cabeça. Isso, geralmente, será o caso, se o
diagrama de sequência for possuído por um caso de uso. Elementos de fronteira,
controle e entidade de diagramas de robustez também podem possuir linhas
de vida. Observe na imagem a seguir as linhas de vida sendo representadas
pelos diferentes tipos.
Elaborar o diagrama de sequência4
: Actor0 : Boundary0 : Control0 : Entity0
Mensagens
No diagrama de sequência, um dos principais elementos são aqueles que
permitem descrever a interação entre os objetos. E para isso, é utilizado as
mensagens. Elas são basicamente setas que representam a comunicação entre
objetos. Como podem existir diferentes tipos de mensagens, também são
descritas utilizando-se diferentes setas. Você irá ver cada tipo de mensagem,
bem como, o formato de seta utilizado a seguir.
Mensagem síncrona: uma mensagem síncrona requer uma resposta antes
que a interação possa continuar. Geralmente, é desenhado usando-se uma linha
com uma seta de flecha sólida apontando de um objeto para outro.
Objeto
1: Mensagem( )
Objeto 2
Mensagem assíncrona: as mensagens assíncronas não precisam de uma
resposta para a interação para continuar. Como as mensagens síncronas, elas
são desenhadas com uma seta conectando duas linhas de vida. No entanto,
a ponta da flecha geralmente está aberta e não há nenhuma mensagem de
retorno descrita.
5Elaborar o diagrama de sequência
Objeto
1: Mensagem( )
Objeto 2
Mensagem de resposta ou de retorno: uma mensagem de resposta é
desenhada com uma linha pontilhada e uma seta aberta apontando de volta
para a linha de vida original.
Objeto
1: Mensagem( )
Objeto 2
Mensagem Self: uma mensagem que um objeto envia a si mesmo, nor-
malmente mostrada com uma flecha em forma de U, voltada para si mesma.
Objeto
1: mensagem( )
Mensagem de criação: esta é uma mensagem que cria um novo objeto.
Semelhante a uma mensagem de retorno, é retratada com uma linha tracejada
e uma seta aberta que aponta para o retângulo, que representa o objeto criado.
Elaborar o diagrama de sequência6
Objeto
<<create>>
1: CreateMessage( )
Objeto 2
Mensagem de destruição: esta é uma mensagem que destrói um objeto.
Pode ser mostrado por meio de uma seta com um x no final.
Objeto Objeto 2
<<destroy>>
1: CreateMessage( )
Mensagemencontrada: uma mensagem enviada de um destinatário des-
conhecido, mostrada por uma seta de um ponto final para uma linha de vida.
Objeto
1: message( )
7Elaborar o diagrama de sequência
Mensagem perdida: uma mensagem enviada para um destinatário des-
conhecido. É mostrada por uma flecha que vai de uma linha de vida para um
ponto final, como um círculo preenchido.
Objeto
1 : Message( )
Focos de controle
Um foco de controle indica o período em que o objeto está participando ati-
vamente do processo. Os focos de controle são representados dentro da linha
de vida, mas, por uma linha mais grossa. Veja na imagem abaixo um exemplo
de foco de controle:
Foco de Controle
Elaborar o diagrama de sequência8
Fragmentos combinados
Em geral, os diagramas de sequência não se destinam a mostrar uma lógica
processual complexa. Quando este for necessário, há uma série de mecanismos
que permitem adicionar um grau de lógica processual aos diagramas, e que se
enquadram no título de fragmentos combinados. Um fragmento combinado
é uma ou mais sequências de processamento incluídas em uma moldura,
com execuções em circunstâncias específicas (OBJECT MANAGEMENT
GROUP, 2011).
Na Figura 2, veja um exemplo do uso de um fragmento do tipo loop para
descrever um conjunto de operações realizadas repetidamente.
Figura 2.
Interface
1: solicita_array( )
retorna(array)
retorna(item_array)
1.2: solicita_item(n)
1: solicita_tamanho_array( )
envia(tamanho_array)
Controle DataSource
loop: n [tamanho_array]
Nesse exemplo, tem-se três entidades: Interface, Controle e DataSource.
A interface solicita um array para a entidade controle. Essa, então, solicita o
tamanho do array para a base de dados. Com o tamanho do array, a entidade de
controle realiza um loop utilizando um fragmento combinado, associando na
variável n o índice do loop. Assim, é realizada a solicitação e recebimento do
item correspondente para aquela posição no array para a entidade DataSource.
Por fim, a entidade Interface recebe o array.
9Elaborar o diagrama de sequência
Existem diversos tipos de fragmentos que podem ser utilizados de acordo
com a necessidade. No diagrama, poucas alterações ocorrem de um tipo
para outro. Em geral, a maioria dos softwares altera o nome do fragmento e
os operadores. Os fragmentos disponíveis são (OBJECT MANAGEMENT
GROUP, 2011):
� [alt] Fragmentos alternativos. Utilizados em operações se ... então …
(IF-ELSE).
� [opt] Os fragmentos de opções modificam as construções.
� [break] O fragmento break é uma sequência alternativa de eventos que
é processada ao invés de todo o resto do diagrama.
� [par] O fragmento paralelo modela o processamento simultâneo.
� [seq] O fragmento de sequência inclui uma série de sequências, para
as quais todas as mensagens devem ser processadas em um segmento
anterior, antes do início do segmento seguinte, mas que não impõe
qualquer continuidade dentro de um segmento em que as mensagens
não compartilham uma linha de vida.
� [strict] O fragmento de sequência strict inclui uma série de mensagens
que devem ser processadas na ordem dada.
� [neg] O fragmento negativo inclui uma série inválida de mensagens.
� [critical] O fragmento crítico encerra uma seção crítica.
� [ignore] Ignorar fragmento declara uma mensagem para não interessar,
se aparecer no contexto atual.
� [consider] Considerar fragmento é efetivamente o oposto do fragmento
ignorar: qualquer mensagem não incluída no fragmento considerar
deve ser ignorada.
� [assert] O fragmento de afirmação designa que qualquer sequência não
mostrada como uma operação da asserção é inválida.
� [loop] O fragmento loop contém uma série de mensagens que são
repetidas.
Camadas e objetos
A arquitetura multicamadas (muitas vezes referida como arquitetura de N-
-camadas) é uma arquitetura em que a apresentação, o processamento de
aplicativos e as funções de gerenciamento de dados estão fisicamente separados.
O uso mais difundido dela é na arquitetura de três camadas.
Elaborar o diagrama de sequência10
A arquitetura de aplicativos multicamadas fornece um modelo para o
qual os desenvolvedores podem criar aplicativos flexíveis e reutilizáveis.
Ao segregar um aplicativo em níveis, os desenvolvedores adquirem a opção
de modificar ou adicionar uma camada específica, ao invés de retrabalhar o
aplicativo inteiro. Uma arquitetura de três camadas geralmente é composta
por uma camada de apresentação, uma camada de lógica de domínio e uma
camada de armazenamento de dados.
Enquanto os conceitos de camadas são frequentemente usados de forma
intercambiável, um ponto de vista bastante comum é que há realmente uma
diferença. Esta visão sustenta que uma camada é um mecanismo de estrutura-
ção lógica para os elementos que compõem a solução de software, na mesma
proporção que uma camada é um mecanismo de estruturação física para a
infraestrutura do sistema.
Em uma arquitetura lógica, de várias camadas para um sistema de infor-
mação com um design orientado a objetos, geralmente, tem-se as seguintes
camadas:
� Camada de apresentação.
� Camada de aplicação.
� Camada de negócio.
� Camada de acesso aos dados.
Arquitetura de três camadas
A arquitetura de três camadas é um padrão de arquitetura de software cliente-
-servidor, em que a interface do usuário (apresentação), a lógica do processo
funcional (regras de negócios), o armazenamento de dados do computador e
o acesso a dados são desenvolvidos e mantidos como módulos independentes,
na maioria das vezes, em plataformas separadas.
Além das vantagens usuais do software modular com interfaces bem
definidas, a arquitetura de três camadas destina-se a permitir que qualquer
uma das três camadas seja atualizada ou substituída independentemente,
em resposta a mudanças nos requisitos ou na tecnologia. Por exemplo, uma
alteração do sistema operacional na camada de apresentação afetaria apenas
o código da interface do usuário.
11Elaborar o diagrama de sequência
Neste tipo de arquitetura há os seguintes níveis:
1. Nível de apresentação: este é o nível mais alto da aplicação. O nível de
apresentação exibe informações relacionadas a serviços, como navega-
ção de mercadorias, compras e conteúdo do carrinho de compras. Ele
se comunica com outras camadas através das quais coloca os resultados
na camada navegador/cliente e em todas as outras camadas na rede. Em
termos simples, é uma camada que os usuários podem acessar direta-
mente (como uma página da web ou uma GUI do sistema operacional).
2. Nível de aplicação (lógica de negócios, camada lógica ou camada
intermediária): o nível lógico é retirado do nível de apresentação e,
como sua própria camada, ele controla a funcionalidade de um aplicativo
executando um processamento detalhado.
3. Nível de dados: a camada de dados inclui os mecanismos de persistência
de dados (servidores de banco de dados, compartilhamentos de arqui-
vos etc.) e a camada de acesso a dados que encapsula os mecanismos
de persistência e expõe os dados. A camada de acesso a dados deve
fornecer uma API para a camada de aplicativos que expõe os métodos
de gerenciamento de dados armazenados, sem expor ou criar depen-
dências nos mecanismos de armazenamento. Evitar dependências nos
mecanismos de armazenamento permite atualizações ou alterações
sem que os clientes da camada de aplicativos sejam afetados ou mesmo
estejam conscientes da mudança. Como acontece com a separação de
qualquer nível, há custos de implementação e, muitas vezes, custam
o desempenho em troca de uma melhor escalabilidade e manutenção.
Representando camadas no diagrama de sequência
Para explicar como criar camadas em um diagrama de sequência, irá ser utili-
zado um modelo MVC. O modelo MVC é composto pelas seguintes camadas:
� Model: regras e objetos do negócio. Estereótipo: entidade (entity).
� View: interação com atores e apresentação de dados. Estereótipo: fron-
teira (boundary).
� Controller: em algumas versões podeinteragir com os atores, mas,
normalmente, só controla os casos de uso, chamando objetos de camada
Model e objetos da camada View. Estereótipo: controle (control).
Elaborar o diagrama de sequência12
A figura a seguir apresenta os três tipos de linha de vida que podem ser
utilizadas para representar um model, um view e um controller no modelo
MVC.
View : Boundary0 Controller : Control0Model : Entity0
Na Figura 3, veja um exemplo que apresenta uma requisição HTTP de
determinado tipo de informação, sendo realizada com o modelo MVC e re-
presentada pelo uso do diagrama de sequência.
Figura 3.
View : Boundary0Controller : Control0 Model : Entity0Usuário : Actor0
1 : http_request( )
1.1 : request_data( )
1.2: send_data_retrieved_from_model( )
formated output
return_data
http_response
No exemplo anterior, pode-se verificar que cada linha de vida representa
uma das camadas. Obviamente, tem-se um ator chamado usuário, que faz a
requisição e recebe a resposta por intermédio da camada controller. Ao contrário
do que geralmente se imagina, as requisições são recebidas pelo controller,
e não pela view. A camada model faz o acesso aos dados e retorna para o
controller. Note que essa camada pode ser tanto para acessar a um banco de
dados, como para fazer uma chamada a API, retornando os dados. Por fim,
o usuário recebe o output formatado conforme a camada view processou.
13Elaborar o diagrama de sequência
Elaboração do diagrama
Existem alguns passos que devem ser realizados para a elaboração de um
diagrama de sequência. De forma geral, é interessante que exista um ou mais
diagramas ou especificações de casos de uso. Além disso, a pré-existência de
uma especificação/diagrama de classes facilita na hora de criar um diagrama
de sequência, já que os métodos, atributos e classes estão bem definidos.
Você verificará quais são os passos para a criação de um diagrama de
sequência:
1. Escolher um caso de uso.
2. Identificar os objetos que fazem parte da interação.
3. Identificar o objeto que começa a interação.
4. Identificar as mensagens trocadas entre os objetos.
5. Identificar a sequência destas mensagens.
Irão ser exemplificados estes passos utilizando-se um caso bastante simples
para você entender bem o significado de cada ação. Inicialmente, foi selecio-
nado um caso de uso. Supondo que se tem um sistema de gestão de RH, em que
há um analista do setor que faz o cadastro de um salário para um funcionário
já registrado no sistema. Então, será utilizado o caso de uso a seguir:
Analista RH
Cadastrar
Salário de
Funcionário
O analista RH será o ator no diagrama de sequência. Agora, se pode verificar
a seguinte especificação de classes para identificar os objetos da interação.
Para esse caso de uso, em específico, tem-se as classes Funcionário e Salário.
A classe Funcionário possui os seguintes métodos: pesquisar_funcionário,
cadastrar_funcionário, alterar_funcionário e excluir_funcionário. Já, a classe
Salário possui os métodos pesquisar_salário, cadastrar_salario, alterar_salário
e excluir_salário.
Elaborar o diagrama de sequência14
É necessário identificar, então, quais métodos serão usados. Nesse caso, é
preciso pesquisar_funcionário e cadastrar_salario. Veja a criação do diagrama
na Figura 4:
Figura 4. Criação de diagrama.
Interface Funcionário Salário
Funcionário : Actor0
1: cadastrar_salário( )
1.1: pesquisar_funcionário( )
retorna_funcionário
1.2: cadastrar_salário( )
retorna_resultado
1.3: retorna_resultado( )
Note que no diagrama foi inserido uma linha de vida para Interface, ou
seja, o local em que o usuário irá interagir para fazer as requisições ao sistema.
Preste atenção que neste caso não se está utilizando camadas. Você pode
verificar um exemplo utilizando camadas na seção anterior.
FOWLER, M. Sequence Diagrams. In: FOWLER, M. UML Distilled: a brief guide to the stan-
dard object modeling language. 3. ed. Indianapolis: Addison-Wesley Professional, 2003.
LABORATÓRIO DE ENGENHARIA DE SOFTWARE. UML: Diagrama de Seqüência. Rio de
Janeiro: PUC-Rio, 2013. Disponível em: <http://www.les.inf.puc-rio.br/wiki/images/e/
ef/Aula02-diagrama_sequencia.pdf>. Acesso em: 7 set. 2017.
OBJECT MANAGEMENT GROUP. UML Superstructure Specification 2.4.1. Needham,
2011. Disponível em: <http://www.omg.org/spec/UML/2.4.1>. Acesso em: 7 set. 2017.
SARMA, M.; KUNDU, D.; MALL, R. Automatic Test Case Generation from UML Sequence
Diagram. In: INTERNATIONAL CONFERENCE ON ADVANCED COMPUTING AND COMMU-
NICATIONS. 15., Guwahati, Dec. 2007. Proceedings… . Washington: IEEE, 2008. p. 60-67.
15Elaborar o diagrama de sequência
http://www.les.inf.puc-rio.br/wiki/images/e/
http://www.omg.org/spec/UML/2.4.1
Leituras recomendadas
PRESSMAN, R. S.; MAXIM, B. R. Engenharia de software: uma abordagem profissional.
8. ed. Porto Alegre: AMGH, 2016.
SCHACH, S. R. Engenharia de Software: os paradigmas clássico e orientado a objetos.
7. ed. Porto Alegre: McGraw-Hill, 2009.
SEQUENCE DIAGRAM. SmartDraw, San Diego, 2017. Disponível em: <https://www.
smartdraw.com/sequence-diagram/>. Acesso em: 7 set. 2017.
Elaborar o diagrama de sequência16
http://smartdraw.com/sequence-diagram/
Encerra aqui o trecho do livro disponibilizado para
esta Unidade de Aprendizagem. Na Biblioteca Virtual
da Instituição, você encontra a obra na íntegra.
Conteúdo:
ENGENHARIA
DE SOFTWARE
Aline Zanin
Conhecer e construir
diagrama de atividades
Objetivos de aprendizagem
Ao final deste texto, você deve apresentar os seguintes aprendizados:
� Explicar o objetivo do diagrama de atividades.
� Aplicar os elementos do diagrama.
� Analisar um diagrama de atividades.
Introdução
O diagrama de atividades é um diagrama comportamental que per-
mite a especificação e a modelagem do comportamento do software.
Esse diagrama ilustra, de forma gráfica, como será o funcionamento do
software e como será a sua execução, além de como será a atuação do
sistema no dia a dia do negócio no qual ele está inserido. Sua forma, se-
melhante ao fluxograma utilizado na área da Administração de Empresas,
permite que se demonstre, do ponto de vista funcional (como o software
funciona), as atividades que serão realizadas. Seus principais objetivos
são de documentar os aspectos funcionais do programa, demonstrar
aspectos específicos de alguma rotina, explicitar questões relacionadas
aos requisitos funcionais e explicar de forma macro o sistema.
Neste capítulo, você vai adquirir conhecimentos fundamentais sobre
os diagramas de atividades, vai conhecer os elementos, os seus objetivos
e como fazer a modelagem e a análise desse diagrama.
Diagrama de atividades: objetivos
O diagrama de atividades é um dos mais completos diagramas comportamen-
tais da UML. Ele permite visualizar detalhadamente os fluxos do sistema no
que diz respeito às ações que podem ser feitas e aos caminhos percorridos na
utilização deste sistema. Comumente ele pode ser utilizado como um deta-
lhamento da especificação textual dos requisitos especificados pelos casos de
uso. De acordo Silva (2001), o objetivo do diagrama é representar os fluxos
conduzidos por processamento interno de um sistema em reação a eventos
externos representados tipicamente nos diagramas de estado.
O diagrama permite ao cliente ter uma visão mais assertiva daquilo que
está solicitando para a equipe de desenvolvimento, uma vez que é por meio
da concepção do fluxo que o sistema irá ser construído. Por exemplo: um
cliente, proprietário de um serviço de autopeças que nunca teve um sistema
para controle de seu estoque, gostaria de implementar um sistema que rea-
lizasse um fluxo similar ao que ele efetua no papel, assim, se sentiria mais
confortável com a aquisição do software, ao ver esse fluxo modelado em um
fluxograma. A Figura 1 apresenta um exemplo de diagrama de atividades
para um sistema de vendas.
Figura 1. Exemplo de diagrama de atividades.
Solicitar
produto
Acessar a página
de cadastro
de produtos
Digitaro código
do produto
Produto já
cadastrado
Informar a
quantidade para
incrementar
o estoque
Imprime
etiqueta
Confirma
cadastro
Cadastrar uma
descrição
para o produto
Produto novo
Conhecer e construir diagrama de atividades2
Os diagramas de atividades podem e devem ser utilizados juntamente com diagramas
de casos de uso para complementar as informações.
Elementos que compõem o diagrama de
atividades
Um diagrama de atividades, assim como todos os diagramas da UML, é baseado
em elementos que, em conjunto, representam, neste caso, o comportamento
do sistema.
Os diagramas de atividades têm os seguintes elementos básicos: estados
iniciais e finais, atividades e transições, decisões e, ainda, alguns elementos
adicionais, como bifurcação, união e raias. Todos serão descritos a seguir
(FIGUEIREDO, 2017).
1. Estados iniciais e finais: marcam o início e o fim do diagrama.
Figura 2. Exemplo de estado inicial e estado final.
Fonte: Figueiredo (2017).
Estado Inicial
(iniciação)
Estado Final
(conclusão)
3Conhecer e construir diagrama de atividades
2. Atividades: marcam uma atividade realizada no sistema.
3. Decisões: marcam um ponto em que o sistema pode seguir dois cami-
nhos distintos.
Figura 3. Exemplo de atividades e decisões.
Fonte: Figueiredo (2017).
Solicitar
produto
Pago?
Sim
Processar pedido
Cancelar pedido
Não
4. Bifurcação e união: na bifurcação, ocorre uma divisão dos fluxos do
sistema; na união, ocorre uma união dos fluxos que outrora haviam
bifurcado.
Figura 4. Exemplo de bifurcação e união.
Fonte: Figueiredo (2017).
Processar pedido Efetuar cobrança
Conhecer e construir diagrama de atividades4
5. Raias: utilizadas para a organização do diagrama, podem estar asso-
ciadas a objetos, componentes do sistema ou atores.
Figura 5. Exemplo de raias.
Fonte: Figueiredo (2017).
Solicitar produto
Processar pedido
Cliente Vendas Estoque
Enviar pedido
Diagramas de atividades são, muitas vezes, utilizados pelas equipes que aplicam
testes baseados em modelos, sendo utilizados para realização de automação de
testes funcionais.
5Conhecer e construir diagrama de atividades
Analisando um diagrama de atividades
Vamos analisar detalhadamente o diagrama que foi utilizado como exemplo
neste capítulo para aprofundar o conhecimento. Para isso, trazemos nova-
mente o diagrama (Figura 6), contudo, agora, numerado para que possamos
analisá-lo em detalhes.
1. Marca o início do diagrama.
2. Indica uma atividade, uma ação que deverá ser feita no sistema, no
caso, efetuar login no sistema.
3. É uma transição, representa a ligação de uma atividade com outra, neste
caso, leva do login para o acesso à página de cadastro.
4. Indica a ação de acessar a página de cadastro de produtos.
5. É a transição de ligação entre o acesso à página de cadastro de produtos
e digitar o código de produto.
6. Indica a ação de digitar o código do produto.
7. Indica a ligação da ação ou da atividade de digitar código de produto
com um ponto de decisão, ou seja, com um ponto que no sistema pode
ser seguido de dois fluxos distintos.
8. Ponto de decisão em que o sistema verifica se o produto já está ca-
dastrado e, baseado nisso, define o fluxo que o sistema irá seguir:
cadastrar um novo produto ou registrar uma quantidade de um produto
já cadastrado.
9. Indica a ação ou a atividade de cadastro da descrição de um novo
produto.
10. Indica a ação ou a atividade de informar a quantidade do produto para
ser incrementado o estoque.
11. Indica a ligação entre o incremento de estoque e a impressão da etiqueta.
12. Representa a ação ou a atividade de imprimir uma etiqueta no sistema.
13. Indica a ligação entre a impressão da etiqueta e a confirmação da
inclusão do produto.
14. Indica a ação ou a atividade de confirmar o cadastro do produto.
15. Indica a ligação da confirmação do cadastro com o final do diagrama.
16. É o ponto final que marca o encerramento do diagrama.
Conhecer e construir diagrama de atividades6
Figura 6. Diagrama numerado com a sequência das etapas.
Solicitar
produto
Acessar a página
de cadastro
de produtos
Digitar o código
do produto
Produto já
cadastrado
Informar a
quantidade para
incrementar
o estoque
Imprime
etiqueta
Confirma
cadastro
Cadastrar uma
descrição
para o produto
Produto novo
1
2
3
4
5
6
7
8
11
12
13
14
15
16
10 9
Assista ao vídeo no link ou código a seguir para conhecer
mais sobre diagramas de atividades.
https://goo.gl/eixkcA
7Conhecer e construir diagrama de atividades
ESTUDO NA WEB. Entenda o Diagrama de Atividade. YouTube, 2017. Disponível em:
<https://www.youtube.com/watch?v=vReuK7_tYWc>. Acesso em: 1 out. 2017.
FIGUEIREDO E. UML Diagrama de Atividades. Belo Horizonte: UFMG, 2017. Disponível
em: <http://homepages.dcc.ufmg.br/~figueiredo/disciplinas/aulas/uml-diagrama-
-atividades_v01.pdf> Acesso em: 14 set. 2017
SILVA, A. M. R.; VIDEIRA, C. A. E. UML, metodologias e ferramentas CASE. 2. ed. Porto:
Centro Atlântico, 2001.
Os diagramas de atividades são documentações bastante detalhadas sobre o fluxo
comportamental do sistema e, por este motivo, alguns projetos não são bons cenários
para utilização desse tipo de diagrama. São exemplos de cenários em que é importante
efetuar a criação de diagramas de atividades: sistemas mais críticos, ou seja, nos quais
uma falha no sistema pode ocasionar grandes impactos; situações em que o cliente
deseja visualizar melhor o fluxo do sistema, como no exemplo do serviço de autopeças
(citado na introdução deste capítulo); e projetos que dispõem de tempo para uma
documentação mais detalhada.
Conhecer e construir diagrama de atividades8
Conteúdo:
ANÁLISE E
PROJETO DE
SISTEMAS
Cleverson Ledur
Elaborar diagrama de
máquina de estados
Objetivos de aprendizagem
Ao final deste texto, você deve apresentar os seguintes aprendizados:
� Reconhecer os conceitos básicos sobre o diagrama.
� Identificar as relações entre os estados da solução.
� Elaborar o diagrama de máquina de estados adequadamente.
Introdução
O diagrama de máquina de estados é um dos diagramas disponíveis na
UML para a modelagem dos aspectos dinâmicos de sistemas. Assim como
o diagrama de sequência, o diagrama de máquina de estados muitas
vezes baseia-se em um caso de uso descrito e apoia-se no diagrama
de classes. Nele, são definidos os estados e transições destes estados
para obter, de forma clara, os possíveis estados que um objeto pode ter
durante o seu tempo de vida.
Neste texto, você vai conhecer o diagrama de máquina de estados,
seus elementos e os principais conceitos em torno desta ferramenta
da UML. Também vai ver as transações que podem ocorrer entre os
estados, elementos de escolha e junção, barras de sincronização e, por
fim, as informações essenciais para que você consiga criar um diagrama
de forma adequada.
Conceitos básicos
O diagrama de máquina de estado UML é uma percepção melhorada do
conceito matemático de um autômato finito, conforme expresso na notação
Unified Modeling Language (UML). Os conceitos por trás disso são sobre
organizar a forma como um dispositivo, programa de computador ou outro
processo (muitas vezes técnico) funciona de forma que uma entidade ou cada
uma de suas subentidades esteja exatamente em um dos vários estados possí-
veis e onde estejam definidas entre esses estados (LILIUS; PALTOR, 1999).
A máquina de estado UML é uma variante baseada em objetos do conjunto
de estados de Harel, adaptada e estendida pela UML. O objetivo das máquinas
de estado UML é superar as principais limitações das máquinas tradicionais
de estados finitos, mantendo seus principais benefícios. Os gráficos de estados
UML introduzem os novos conceitos de estados hierarquicamente aninhados
e regiões ortogonais, ao mesmo tempo, que estendem a noção de ações. As
máquinas de estado UML têm as características das máquinas Mealy e das
máquinas Moore. Elas suportam as ações que dependem do estado do sistema
e doevento desencadeante, como em máquinas Mealy, além de ações de
entrada e saída, que estão associadas a estados em vez de transições, como
em máquinas Moore.
O termo máquina de estado UML pode se referir a dois tipos de máquinas
de estado: máquinas de estado comportamental e máquinas de estado de
protocolo. As máquinas de estado comportamental podem ser usadas para
modelar o comportamento de entidades individuais, por exemplo, instâncias
de classe. As máquinas de estado de protocolo são usadas para expressar
protocolos de uso e podem ser usadas para especificar os cenários de uso legal
de classificadores, interfaces e portas (GUEDES, 2008).
Máquina de estado
Muitos sistemas de software são conduzidos por eventos, o que significa que
eles esperam continuamente a ocorrência de algum evento externo ou interno,
como um clique do mouse, um botão pressionado, um horário ou a chegada de
um pacote de dados. Depois de reconhecer o evento, esses sistemas reagem
ao realizar a computação apropriada, que pode incluir manipular ou gerar
eventos que desencadeiam outros componentes de software internos. Uma
vez que o tratamento de eventos está completo, o sistema volta a aguardar o
próximo evento.
A resposta a um evento, geralmente, depende do tipo de evento e do estado
interno do sistema, e pode incluir uma mudança de estado que leva a uma
transição de estado. O padrão de eventos, estados e transições de estados entre
esses estados podem ser abstraídos e representados como uma máquina de
estados finitos (FSM).
A UML preserva a forma geral dos diagramas de estados tradicionais. Os
diagramas de máquina de estado UML são grafos direcionados nos quais os
Elaborar diagrama de máquina de estados2
nós indicam estados e conectores indicam transições de estado. Por exemplo,
a Figura 1 mostrará um diagrama de estado UML correspondente à máquina
de estado do teclado do computador. Em UML, os estados são representados
como retângulos arredondados rotulados com nomes de estados. As transi-
ções, representadas como setas, são rotuladas com os eventos desencadeantes
seguidos, opcionalmente, pela lista de ações executadas. A transição inicial
é originada do círculo sólido e especifica o estado padrão quando o sistema
começa pela primeira vez. Todo diagrama de estados deve ter uma transição
que não deve ser rotulada, uma vez que não é desencadeada por um evento.
A transição inicial pode ter ações associadas. Veja na Figura 1, o exemplo de
diagrama de máquina de estados para uma porta.
Figura 1. Exemplo de diagrama de máquina de estados de uma porta.
Aberta Fechada
Fechar [Entrada Vazia]
Abrir
Trancada
Destrancar Trancar
Eventos
Um evento é algo que acontece e afeta o sistema. Estritamente falando, na
especificação UML, o termo evento refere-se ao tipo de ocorrência e não a
qualquer instância concreta dessa ocorrência. Por exemplo, digitar uma tecla
CTRL no seu teclado é um evento para o teclado, mas cada pressionar da tecla
não é um evento, e sim, uma instância concreta do evento CTRL.
Um evento pode ter parâmetros associados, permitindo que a instância do
evento transmita não apenas a ocorrência de algum incidente interessante, mas,
também, informações quantitativas sobre essa ocorrência. Já uma ocorrência de
3Elaborar diagrama de máquina de estados
evento ultrapassa a ocorrência instantânea que o gerou e pode transmitir essa
ocorrência para uma ou mais máquinas de estado. Uma vez gerada, a instância
do evento passa por um ciclo de vida de processamento que pode consistir em
até três estágios. Primeiro, a instância do evento é recebida quando aceita e
aguarda o processamento, por exemplo, é colocado na fila de eventos. Mais
tarde, a instância do evento é despachada para a máquina de estado, nesse
ponto ele se torna o evento atual. Finalmente, é consumido quando a máquina
de estado finaliza o processamento da instância do evento.
Condições guard
As condições guard são expressões booleanas avaliadas dinamicamente com
base no valor das variáveis de estado estendido e dos parâmetros do evento.
As condições guard afetam o comportamento de uma máquina de estado ao
ativar ações ou transições quando elas avaliam TRUE e desativando-as quando
avaliam FALSE. A necessidade de condições guard é a consequência imediata
de adicionar variáveis de estado de memória expandida ao formalismo da
máquina de estado. Usado com moderação, variáveis de estado estendido e
condições guard constituem um poderoso mecanismo que pode simplificar
os projetos.
Ações e transições
Quando uma instância de evento é despachada, a máquina de estado responde
executando ações, como mudar uma variável, executar E / S, invocar uma
função, gerar outra instância de evento ou mudar para outro estado. Qualquer
valor de parâmetro associado ao evento atual está disponível para todas as
ações diretamente causadas por esse evento.
Alternar de um estado para outro é chamado de transição de estado, e o
evento que causa isso, é chamado de evento desencadeante ou simplesmente
o gatilho. Em máquinas de estado prolongado, uma transição pode ter uma
proteção, o que significa que a transição pode disparar somente se o controle
for verdadeiro. Um estado pode ter muitas transições em resposta ao mesmo
gatilho, desde que tenham guards que não sobrevivam. No entanto, essa
situação pode criar problemas na sequência de avaliação dos guards, quando
Elaborar diagrama de máquina de estados4
ocorre o gatilho comum. A especificação UML intencionalmente não estipula
nenhuma ordem específica. Em vez disso, a UML coloca o fardo no designer
para criar guards de forma que a ordem de sua avaliação não importe. Pra-
ticamente, isso significa que as expressões de condições guard não devem
ter efeitos colaterais, pelo menos, nenhum que altere a avaliação de outros
guards com o mesmo gatilho.
Modelo de execução run-to-completion
Todos os formalismos de máquinas de estado, incluindo máquinas de estado
UML, assumem universalmente que uma máquina de estado conclua o pro-
cessamento de cada evento antes que ele possa começar a processar o próximo
evento. Esse modelo de execução é chamado de executar até a conclusão ou
RTC.
No modelo RTC, o sistema processa eventos em etapas RTC discretas e in-
divisíveis. Novos eventos recebidos não podem interromper o processamento do
evento atual e devem ser armazenados (normalmente, em uma fila de eventos)
até que a máquina de estado fique novamente ociosa. Essas semânticas evitam
completamente problemas de concorrência interna em uma única máquina de
estado. O modelo RTC também contorna o problema conceitual de processar
ações associadas a transições, em que a máquina de estado não está em um
estado bem definido durante a duração da ação. Durante o processamento do
evento, o sistema não responde, de modo que o estado mal definido durante
esse período não tem significado prático.
No entanto, note que o RTC não significa que uma máquina de estado
tenha que monopolizar a CPU até o passo RTC estar completo. A restrição
de preempção aplica-se, apenas, ao contexto de tarefa da máquina de estado
que já está ocupada processando eventos. Em um ambiente multitarefa, outras
tarefas (não relacionadas ao contexto da tarefa da máquina de estado ocupada)
podem estar em execução, possivelmente, antecipando a máquina de estado
atualmente em execução. Enquanto outras máquinas de estado não compar-
tilharem variáveis ou outros recursos entre si, não há riscos de concorrência.
A principal vantagem do processamento RTC é a simplicidade. A maior
desvantagem é que a capacidade de resposta de uma máquina estatal é de-
terminada pelo seu passo RTC mais longo. Alcançar pequenos passos RTC
geralmente podem complicar, significativamente, os projetos em tempo real.
5Elaborar diagrama de máquina de estados
Relações entre estados e diagramação
Agora que você viu alguns conceitos sobre máquinas de estados e diagramação,
irá entender como tudo isso é representado no diagramade máquina de estados.
Inicialmente, você vai aprender os elementos do diagrama de estados e como
eles se relacionam para expressar as informações de estados de classes/objetos.
Estados
Um estado é denotado por um retângulo redondo com o nome estado escrito
dentro dele (OBJECT MANAGEMENT GROUP, 2007). Na Figura 2, há uma
imagem que mostra um estado.
Figura 2. Exemplo
de um elemento de
estado.
Estado
Estados iniciais e finais
O estado inicial é denotado por um círculo preto preenchido e pode ser rotu-
lado com um nome. Enquanto que o estado final é denotado por um círculo
com um ponto interno e também pode ser rotulado com um nome. A Figura
3 apresenta um estado inicial (OBJECT MANAGEMENT GROUP, 2007).
Já na Figura 4, pode ser notado um estado final. E na Figura 5 é mostrado o
uso dos dois elementos no diagrama.
Elaborar diagrama de máquina de estados6
Figura 3. Exemplo de
um elemento inicial.
Figura 4. Exemplo de
um elemento final.
Figura 5. Exemplo de uso de elemento inicial e final.
Vivo
/ Criar / Destruir
Transições
As transições de um estado para outro são indicadas por linhas com pontas
de seta (OBJECT MANAGEMENT GROUP, 2007). Uma transição pode ter
um gatilho, uma proteção e um efeito, conforme abaixo. A Figura 6 apresenta
o uso de uma transição. Já na Figura 7 você pode ver um pequeno exemplo
do uso de gatilhos:
7Elaborar diagrama de máquina de estados
Figura 6. Exemplo de transição.
Estado
Figura 7. Exemplo de uso de transições e gatilhos.
Gatilho (Trigger) [Guard] / Efeito
Estado DestinoEstado Origem
Trigger ou gatilho é a causa da transição, que pode ser um sinal, um
evento, uma mudança em alguma condição ou a passagem do tempo. Guard
é uma condição que deve ser verdadeira para que o gatilho cause a transição
(OBJECT MANAGEMENT GROUP, 2007). Já efeito é uma ação que será
invocada diretamente no objeto que possui a máquina de estado como resultado
da transição.
Autotransições
Um estado pode ter uma transição que retorna a si mesma, como no diagrama
a seguir. Isso é mais útil quando um efeito está associado à transição. Veja na
Figura 8 um exemplo de autotransição:
Figura 8. Exemplo de uma
autotransição.
Aguardando
após 2 segundos / input
Elaborar diagrama de máquina de estados8
Pseudo-estado de escolha
Um pseudo-estado de escolha é mostrado como um diamante em uma transição
que chega e duas ou mais transições que saem. O diagrama a seguir mostra que
o estado de cada estado, após o pseudo-estado de escolha, depende do formato
de mensagem selecionado durante a execução do estado anterior (OBJECT
MANAGEMENT GROUP, 2007). A Figura 9 apresenta um exemplo de uso
do elemento escolha.
Figura 9. Exemplo de uso de um elemento de escolha.
Selecionando
Formato de
Mensagem
Criando Mensagem de Voz
Criando Mensagem SMS
Criando Mensagem Fax
[Voz]
[SMS]
[Fax]
Pseudo-estado de junção
Os pseudo-estados de junção são usados para encadear várias transições. Uma
junção única pode ter uma ou mais transições entrantes. Um conceito guard
pode ser aplicado a cada transição. Assim, as junções são semânticas, uma
junção que divide uma transição entrante em múltiplas transições de saída
realiza um ramo condicional estático, ao contrário de um pseudo-estado de
escolha que realiza um ramo condicional dinâmico (OBJECT MANAGEMENT
GROUP, 2007). A Figura 10 apresenta o elemento de junção sendo utilizado
no diagrama de máquina de estados.
9Elaborar diagrama de máquina de estados
Figura 10. Exemplo de uso de um elemento de pseudo-estado de escolha.
State0
State1
[se condição 2 ]
[se condição 3 ]
[se condição 1 ]
Considerações importantes para criação de
diagrama
Até o momento, você viu os conceitos e principais elementos do diagrama de
estados. Mas ainda permanece a pergunta, quando realmente se precisa usar
um diagrama de estados em um projeto de software?
� Os diagramas de estado são muito bem empregados para descrever o
comportamento de um objeto por meio de vários casos de uso. Eles
permitem que os estados que um objeto em específico sejam descritos,
assim, consegue-se entender e especificar o comportamento desse
objeto conforme são realizadas diferentes ações (LARMAN, 2002).
� Os diagramas de máquina de estado não são bem empregados quando
se precisa descrever um comportamento que envolve vários objetos
em colaboração. Isso porque a descrição de apenas um objeto já torna
o diagrama moderadamente complexo quando existem diversas con-
dições e ações. Agora, imagine adicionar um conjunto de objetos no
mesmo diagrama, interagindo entre si. Possivelmente, o diagrama ficaria
bastante poluído e com muitos elementos que dificultariam a leitura.
� O diagrama de máquina de estados não deve ser descrito para todas
as classes do sistema, apenas para as quais ele ajude a compreender o
comportamento. Deste modo, não precisamos é necessário criar uma
infinidade de diagramas de máquina de estados para cada classe no
projeto. A utilização dele é interessante para descrever o comporta-
Elaborar diagrama de máquina de estados10
mento daquelas classes em específico, que são estritamente necessárias
(DRUSINSKY, 2006).
� Quando um objeto possui muitos conjuntos concorrentes de compor-
tamento, gerando vários diagramas de estado concorrentes, convém
dividir este objeto em objetos separados. Assim, é possível facilitar a
leitura desse diagrama, já que se pode fazê-la de forma particionada e
modularizada (DRUSINSKY, 2006).
Em geral, as máquinas de estado são usadas para modelar o comportamento
de objetos ao longo de sua vida útil e são necessárias quando os objetos têm
comportamento dependente de estados. Dentro do contexto de análise e pro-
jeto de software, os objetos que podem ter máquinas de estado são classes,
subsistemas, casos de uso e interfaces.
Mas, nem todo objeto exige máquinas de estado. Por exemplo, se o com-
portamento de um objeto for simples, não variando muito de estado, a máquina
de estado não será muito útil no projeto.
A modelagem da vida útil de um objeto envolve três itens:
� Especificação dos eventos aos quais o objeto pode responder.
� Resposta a esses eventos.
� Impacto do comportamento passado no presente.
A modelagem da vida útil de um objeto também envolve a definição da
ordem em que o objeto pode responder coerentemente a eventos, iniciado no
momento da criação do objeto e permanecendo até sua a destruição.
DRUSINSKY, D. Modelling and verification using UML statecharts. Atlanta: Elsevier, 2006.
GUEDES, G. T. A. UML: uma abordagem prática. São Paulo: Novatec, 2008.
LARMAN, C. Utilizando UML e padrões. Porto Alegre: Bookman, 2002.
LILIUS, J.; PALTOR, I. P. The semantics of UML state machines.Turku: Turku Centre for
Computer Science, 1999.
OBJECT MANAGEMENT GROUP. UML Infrastructure Specification 2.1. Needham, 2007.
11Elaborar diagrama de máquina de estados
Leituras recomendadas
BOOCH, G.; RUMBAUGH, J.; JACOBSON, I. UML: guia do usuário. Rio de Janeiro: Elsevier
Brasil, 2006.
DOUGLASS, B. P. UML statecharts. Embedded, New York, v. 12, n. 1, p. 22-42, 1999.
FOWLER, M. UML Essencial: um breve guia para linguagem padrão. Porto Alegre:
Bookman, 2014.
IBM. Criando Diagramas de Máquina de Estado. New York, 2017. Disponível em:
<https://www.ibm.com/support/knowledgecenter/pt-br/SS5JSH_9.1.2/com.ibm.
xtools.modeler.doc/topics/twrksmd.html>. Acesso em: 8 set. 2017.
SAMEK, M. A crash course in UML state machines. Embedded, New York, Mar. 2009.
SAMEK, M. Practical UML Statecharts in C/C ++: event-driven programming for Embe-
dded Systems. 2. ed. Oxford: Newnes, 2008.
Elaborar diagrama de máquina de estados12
ANÁLISE E PROJETO
DE SISTEMAS
Priscila Gonçalves
Diagramas de componentes
Objetivos de aprendizagem
Ao final deste texto, você deve apresentar os seguintes aprendizados:
� Reconhecer conceitos sobre o diagrama de componentes.
� Descrever os elementos de um diagrama de componentes.
� Identificar um diagrama de componentespor meio de exemplos
práticos.
Introdução
Os diagramas de componentes suportam o desenvolvimento com base
em componentes nos quais um sistema de software é dividido em com-
ponentes e interfaces que são reutilizáveis e substituíveis. Esses diagramas
são utilizados para modelar sistemas de software em alto nível ou para
apresentar componentes em nível de pacote mais baixo. Apresentam
estruturas do sistema de software, que descrevem os componentes do
software, suas interfaces e dependências.
Neste capítulo, você vai estudar conceitos sobre diagramas de com-
ponentes, saberá identificar e descrever seus componentes e aprenderá
aplicações práticas de diagramas de componentes.
Diagrama de componentes e seus conceitos
Em UML (linguagem de modelagem unificada), os diagramas de componentes
apresentam estruturas do sistema de software, que descrevem os componentes
do software, interfaces e suas dependências. Além disso, ajudam a enxergar
a estrutura geral do sistema e o comportamento de serviço que as partes
fornecem e consumi-las por meio de interfaces.
Os diagramas de componentes suportam o desenvolvimento com base em
componentes no qual um sistema de software é dividido em componentes e
interfaces que são reutilizáveis e substituíveis. Utilizam-se desses diagramas
para modelar sistemas de software em um alto nível ou para apresentar com-
ponentes em nível de pacote mais baixo.
Aplicações e utilizações dos diagramas de
componentes
Os diagramas de componentes têm diversas utilidades, algumas das quais
são apresentadas a seguir.
� Definem aspectos executáveis e reutilizáveis de um sistema de software.
� Apresentam problemas de configuração de software por meio de rela-
cionamentos de dependência.
� Apresentam uma representação precisa de um aplicativo de software
antes de fazer alterações ou aprimoramentos.
� Descrevem as seguintes peças físicas de um sistema de software:
■ Arquivos de código-fonte desenvolvidos em ambiente de desenvol-
vimento integrado.
■ Arquivos executáveis necessários para fornecer um sistema em
execução.
■ Bancos de dados físicos que armazenam informações nas tabelas de
um banco de dados relacional ou em páginas de um banco de dados
orientado a objetos.
■ Sistemas adaptáveis que possuam componentes que migrem para
equilíbrio de carga e recuperação de defeitos.
� Descrevem um design implementado em qualquer idioma ou estilo,
sendo necessário identificar partes do design que interagem com as
outras partes de um projeto por meio de um conjunto de entradas e saídas.
Ainda há mais benefícios em relação ao desenho de diagramas de com-
ponentes, entre os quais se pode citar o pensamento de design em relação a
blocos principais que ajudam a equipe de desenvolvedores a compreender de
uma melhor forma e criar um novo design.
Deve-se pensar no sistema como uma coleção de vários componentes,
com interfaces bem definidas e obrigatórias, de modo que se pode melhorar
a separação entre esses componentes, facilitando a compreensão e a alteração
de design quando requisitos sofrerem alterações. Pode-se ainda utilizar um
diagrama de componente como forma de representar o design, independen-
temente da linguagem ou plataforma que será utilizada.
Diagramas de componentes2
Um sistema de software completo pode ser considerado um componente. Este, por
sua vez, é uma unidade modular substituível dentro de seu ambiente. Possui uma ou
mais interfaces fornecidas bem definidas por meio das quais suas funções podem ser
acessadas, e pode ter interfaces obrigatórias, que definem quais funções ou serviços
são exigidos de outros componentes. Ao conectar interfaces fornecidas e obrigatórias
de vários componentes, um componente de grande proporção pode ser construído.
Elementos de um diagrama de componentes
Para melhor entender de que se trata um diagrama de componente, apresenta-se
a seguir mais a respeito de seus elementos.
Componentes
Na modelagem UML (linguagem de modelagem unificada), componentes são
elementos de um modelo que representam partes independentes e intercambi-
áveis de um sistema. Estão sempre em conformidade e realizam uma ou mais
interfaces que são fornecidas e requeridas, determinando o comportamento
desses componentes.
Instâncias de componentes
São elementos de modelo que representam entidades reais em um sistema.
Pacotes
Tem a função de agrupar elementos de modelos relacionados de todos os tipos,
incluindo outros pacotes.
Artefatos
São elementos de modelo que representam as entidades físicas em um sistema
de software. Eles representam unidades físicas de execução, podendo ser
arquivos executáveis, bibliotecas, componentes de software, documentos e
bancos de dados.
3Diagramas de componentes
Interfaces
Trata-se de elementos do modelo que servem para definir conjuntos de opera-
ções que outros elementos do modelo, como classes ou componentes, devem
implementar.
Relacionamentos em diagramas de componentes
Um relacionamento é uma conexão entre elementos de modelo, um tipo de
elemento de modelo que inclui semântica, define a estrutura e o comportamento
entre elementos de modelo.
A Figura 1, a seguir, descreve como ocorre a leitura dos diagramas de
componente, e é seguida pelo Quadro 1, que apresenta uma explicação refe-
rente à Figura 1.
Figura 1. Diagrama de componente.
Fonte: Visual Studio 2015 (c2018).
<<component>>
DinnerNow Web Service
9
9
1
1
2
2
2
3
3
3
4
5
56
7
7
<<component>>
Web Browser
HTTP
Customer Website
Sales
Customer Web Server :...
PaymentAuthorization
PaymentAuthorization
MealOrdering
MealOrdering
Kitchen Server :...
KitchenWorkQueue
Kitchen Website
Diagramas de componentes4
Forma Elemento Descrição e propriedades principais
1 Componente Um pedaço reutilizável de funcionalidade
do sistema. Um componente fornece e
consome o comportamento por meio de
interfaces e pode usar outros componentes.
Você pode ocultar ou mostrar as partes
internas de um componente usando
o controle expandir/recolher (9).
Um componente é um tipo de classe.
� é instanciado indiretamente. Se true
(padrão), o componente existe apenas
como um artefato de design. Em tempo de
execução, apenas suas partes existem.
2 Fornecida
a porta de
interface
Representa um grupo de mensagens ou
chamadas que implementa um componente
e que outros componentes ou sistemas
externos podem usar. Uma porta é uma
propriedade de um componente que
tem uma interface como seu tipo.
3 Porta de
interface
necessária
Representa um grupo de mensagens ou
chamadas que o componente envia a
outros componentes ou sistemas externos.
O componente é projetado para ser
acoplado a componentes que fornecem
pelo menos essas operações. A porta
possui uma interface como seu tipo.
4 Dependência Pode ser usado para indicar que uma interface
obrigatória em um componente pode ser
satisfeita por uma interface fornecida em outro.
Dependências também podem ser
usadas mais geral entre elementos de
modelo, para mostrar que o design de
um depende do design do outro.
Quadro 1. Quadro explicativo referente à Figura 1
(Continua)
5Diagramas de componentes
Quadro 1. Quadro explicativo referente à Figura 1
Forma Elemento Descrição e propriedades principais
5 Parte Um atributo de um componente, cujo
tipo é um componente geralmente outro.
Uma parte é usada no design interno
do componente pai. Partes são exibidas
graficamente, aninhados no componente pai.
Para criar uma parte de um tipo de
componente existente, arraste o componente
do Gerenciador de modelos UML para
o componente do proprietário.
Para criar uma parte de um novo tipo, clique
o componente ferramenta e, em seguida,
clique no componente do proprietário.
Por exemplo, um componente Car tem
partes engine:CarEngine, backLeft:Wheel,
frontRight:Wheel, e assim por diante.
Mais de uma parte pode ter o mesmo
tipo e componentes diferentes podem
ter partes do mesmo tipo.
� Tipo.O tipo de parte, que é definido em
outro lugar no modelo. Normalmente, o tipo
é outro componente.
� Multiplicidade. O padrão é 1. Você pode
defini-lo como 0 para indicar que a parte pode
ter o valor nulo, * para indicar que a parte é
uma coleção de instâncias do tipo em questão
ou com qualquer expressão que possa ser
avaliada como um intervalo de números.
6 Assembly
de Partes
Uma conexão entre as portas de
interface obrigatória de uma parte e as
portas de interface fornecida de outra.
A implementação de um assembly de
parte pode variar de um componente
para outro. As partes de conectado
devem ter o mesmo componente pai.
(Continua)
(Continuação)
Diagramas de componentes6
Fonte: Adaptado de Visual Studio 2015 (c2018).
Quadro 1. Quadro explicativo referente à Figura 1
Forma Elemento Descrição e propriedades principais
7 Delegação Vincula uma porta para uma interface
de uma das partes do componente.
Indica que as mensagens enviadas para
o componente são tratadas pela parte
ou que as mensagens enviadas da parte
são enviadas do componente pai.
(não
mostrado)
Generalização Indica que um componente herda de outro
componente. Partes e interfaces são herdadas.
9 Recolher/
expandir
controle
Use isto para ocultar ou mostrar as
partes internas do componente.
(não
mostrado)
Comentário Para obter notas adicionais. Você pode
vincular um comentário para qualquer
número de elementos no diagrama
usando o conector ferramenta.
(Continua)
No quadro apresentado, consta a explicação de como realizar a leitura de
cada um dos elementos do diagrama. Segundo Scott Ambler (2004), o principal
objetivo desse diagrama é possibilitar a construção de artefatos para o perfil
de arquitetura da solução, seja para a arquitetura técnica ou a de negócios.
O exemplo a seguir pertence ao diagrama de componente referente a um caso de
estudo de um sistema de gestão da biblioteca.
7Diagramas de componentes
Confira a seguir as portas — elemento que permite que subcomponentes de um
componente maior se comuniquem com elementos externos.
Teclado
Entrada
Calculadora
Processador
Saída
Monitor
Fonte: Adaptada de UML diagrama de componentes (2013).
Páginas web dinâmicas do SIB
Componentes de lógica
de negócio do SIB
Mostra menu que
está disponível em
qualquer página.
Para inserir
novo
login.html index.html
pesquisaRe
quisições.
html
pesquisaPu
blicações.
html
<<COM+>>
GestãoAuto
res
<<COM+>>
GestãoPubli
cações
<<dbtable
>>Publica
ções
<<dbtable
>>Requisi
ções
<<COM+>>
GestãoRe
quisições
<<COM+>>
GestãoSóci
os
pesquisaSó
cios.html
listaSócios
.asp
listaRequisi
ções.asp
listaPublica
ções.asp
listaAutores
.asp
fichaAutor.
asp
<<dbtable
>>Autores
<<dbtable
>>Sócios
fichaPubli
cação.asp
fichaRequi
sição.asp
fichaSócio.
asp
pesquisaAu
tores.html
Base de dados do SIB
Fonte: Adaptado de Gemo e Saugene (2012).
Diagramas de componentes8
Diagrama de componentes: exemplos práticos
Diagramas de componentes são conectados por meio de interfaces implemen-
tadas, geralmente utilizando notação de bola e soquete, assim como ocorre
em diagramas de classes. Há a possibilidade de decompor os componentes
utilizando diagramas de estrutura composta.
Um ponto importante sobre os componentes é que eles representam peças
que podem ser adquiridas e/ou atualizadas de forma independente. O uso de
diagramas deve ocorrer quando você precisar dividir seu sistema em compo-
nentes e necessitar mostrar relacionamentos por meio de interfaces.
Outra questão característica para o diagrama de componente que constava
em UML 1 era um símbolo característico que foi retirado em UML 2, per-
mitindo que fosse anotada uma caixa de classe com um ícone de aparência
semelhante. Assim, é possível utilizar a palavra-chave <<componente>>
apresentada na Figura 2, a seguir.
Figura 2. Notação para componentes.
Fonte: Adaptada de Fowler (2005, p.135).
Elemento de
janela
Elemento
de janela
Notação da UML 1
Notação da UML 2
A figura ilustra a retirada do ícone e a caixa de classe com o ícone de
aparência semelhante pelo qual foi substituído na notação UML 1.
9Diagramas de componentes
Na Figura 3, apresenta-se um modelo de elaboração de componente de
projeto, no qual, a partir de uma análise da classe, o serviço de impressão é
definido como componente na arquitetura de software e possui duas interfa-
ces: calcularServico e iniciarServico, representadas pelo símbolo em forma
de pirulito.
Figura 3. Elaboração de um componente de projeto.
Fonte: Pressman e Maxim (2016, p. 287).
calcularServiço
Componente
de projeto
Classe de análise
ServiçoDeImpressão
iniciarServiço
PrintJob
ServiçoDeImpressão
númeroDePáginas
númeroDeLados
tipoDePapel
ampliação
característicasDeProdução
calcularCustoDoServiço()
passarServiçoParaImpressora()
Na Figura 4, é apresentado um modelo de diagrama de componentes, no
qual uma caixa registradora conecta-se a um servidor de vendas, utilizando
uma interface de mensagens de vendas. Para tornar a rede mais segura, ocorre
a introdução de um componente de fila de mensagens a fim de que a caixa se
comunique com o servidor se a rede estiver disponível. Dessa forma, a fila
de mensagens fornece a interface de mensagens de vendas para comunicar-se
com a caixa, e a interface é exigida para comunicar-se com o servidor. Este,
por sua vez, é dividido em dois componentes principais: o processador de
transações, que implementa a interface de mensagens de vendas, e o driver
de contabilidade, que se comunica com o sistema de contabilidade.
Diagramas de componentes10
Figura 4. Exemplo de diagrama de componentes.
Fonte: Fowler (2011, p. 135).
Caixa
Fila de
Mensagens
Servidor de Vendas
Processador de
Transações
Driver de
Contabilidade
Sistema de
Contabilidade
mensagem
de vendas
Acesse o link ou código a seguir para conhecer melhor
os diagramas de componentes.
https://goo.gl/Xa62cn
AMBLER, S. W. The object primer: agile model driven development with UML 2.0. 3rd
ed. Cambridge, UK: Cambridge University Press, 2004.
FOWLER, M. UML essencial: um breve guia para a linguagem padrão de modelagem
de objetos. 3. ed. Porto Alegre: Bookman, 2005.
GEMO, E.; SAUGENE, Z. UML – diagramas de componentes e modelação da arquitectura
física. 2012. Disponível em: <https://pt.slideshare.net/Portal_do_estudante_ADS/
diagramas-de-componentes>. Acesso em: 01 jul. 2018.
11Diagramas de componentes
https://goo.gl/Xa62cn
https://pt.slideshare.net/Portal_do_estudante_ADS/
PRESSMAN, R. S.; MAXIM, B. R. Engenharia de software: uma abordagem professional.
8th ed. Porto Alegre: AMGH, 2016.
UML: diagrama de componentes. Revista Brasileira de Web: tecnologia, 2013. Disponível
em: <http://www.revistabw.com.br/revistabw/uml-diagrama-de-componentes/>.
Acesso em: 01 jul. 2018.
VISUAL STUDIO 2015. Diagramas de componente UML: referência. c2018. Disponível em:
<https://msdn.microsoft.com/pt-br/library/dd409390.aspx>. Acesso em: 01 jul. 2018.
Leituras recomendadas
AMBLER, S. W. UML 2 component diagramming guidelines. c2014. Disponível em: <http://
agilemodeling.com/style/componentDiagram.htm>. Acesso em: 01 jul. 2018.
AMBLER, S. W. UML 2 component diagrams: an agile introduction. c2014. Disponível
em: <http://agilemodeling.com/artifacts/componentDiagram.htm>. Acesso em: 01
jul. 2018.
DIAGRAMA de componentes. c2006. Disponível em: <http://mds.cultura.gov.br/core.
base_rup/guidances/guidelines/component_diagram_CC93D7B3.html>. Acesso
em: 01 jul. 2018.
OBJECT MANAGEMENT GROUP (OMG). OMG Unified Modeling Language (OMG UML),
version 2.5. March, 2015. Disponível em: <www.omg.org/spec/UML/2.5/PDF>. Acesso
em: 01 jul. 2018.
Diagramas de componentes12
http://www.revistabw.com.br/revistabw/uml-diagrama-de-componentes/
https://msdn.microsoft.com/pt-br/library/dd409390.aspx
http://agilemodeling.com/style/componentDiagram.htm
http://agilemodeling.com/artifacts/componentDiagram.htm
http://mds.cultura.gov.br/core.
http://www.omg.org/spec/UML/2.5/PDFEncerra aqui o trecho do livro disponibilizado para
esta Unidade de Aprendizagem. Na Biblioteca Virtual
da Instituição, você encontra a obra na íntegra.
Página em branco