Conheça os fundamentos da análise orientada a objeto e uma técnica para a extração de classes de textos de requisitos (substantivos e verbos...
Este texto usa como exemplo o SIGMAT — Sistema de Matrícula em Disciplinas, apresentado em uma documentação de requisitos como um sistema responsável por matrícula, cancelamento de matrícula, consulta de disciplinas ofertadas, gerenciamento de ofertas pela secretaria, emissão de comprovantes e verificação automática de pré-requisitos, vagas, créditos e conflitos de horário BRASIL ACADÊMICO (2026c).
O objetivo não é desenhar o sistema inteiro. Em projetos reais, um diagrama de classes costuma representar um recorte útil: a parte mais importante, mais difícil ou mais discutida do sistema. Essa orientação combina com o uso da UML como esboço de comunicação e projeto, e não como obrigação de transformar todo o sistema em um desenho gigantesco VALENTE (2020).
AlunoBasico, AlunoComMatriculas, AlunoUsuario e ServidorSecretariaUsuario. Isso evita a redeclaração da mesma classe em JavaScript. No exemplo final, os nomes definitivos aparecem uma única vez.
Uma classe é um molde. Ela define quais informações um objeto terá e quais ações poderá executar. Em JavaScript, uma classe pode ser escrita com a palavra-chave class.
class AlunoBasico {
constructor(nome, matricula) {
// Requisito relacionado: RF-01 — Realizar matrícula.
// Para solicitar matrícula, o sistema precisa identificar o aluno.
this.nome = nome;
this.matricula = matricula;
}
apresentar() {
// Método didático: mostra uma representação textual do aluno.
return `${this.nome} (${this.matricula})`;
}
}
No diagrama de classes UML, uma classe costuma ser representada por um retângulo com três partes: nome, atributos e métodos. Essa é uma simplificação didática bastante usada para mostrar a estrutura estática de um sistema BRASIL ACADÊMICO (2026b).
Um objeto é um exemplar criado a partir da classe. A classe define o formato; o objeto possui valores concretos.
const ana = new AlunoBasico("Ana Souza", "2026001");
const bruno = new AlunoBasico("Bruno Lima", "2026002");
console.log(ana.apresentar()); // Ana Souza (2026001)
console.log(bruno.apresentar()); // Bruno Lima (2026002)
Ana e Bruno são objetos diferentes, mas ambos foram criados a partir da classe AlunoBasico.
Antes de desenhar classes, é necessário ler os requisitos. Requisitos descrevem o que o sistema deve fazer; o modelo ajuda a transformar essa descrição em uma proposta de estrutura. A modelagem estrutural funciona como uma ponte entre linguagem natural, desenho da solução e código BRASIL ACADÊMICO (2026a).
Requisito funcional RF-01 — Realizar Matrícula:
“O sistema deve permitir que o aluno solicite matrícula em uma disciplina ofertada no semestre corrente, desde que atendidas as pré-condições de pré-requisitos, vagas, créditos e horário.” BRASIL ACADÊMICO (2026c)
Desse requisito, surgem candidatos a classes: Aluno, Matricula, Disciplina e TurmaOferta. Também surgem regras que orientarão métodos e validações: pré-requisitos, vagas, créditos e horário.
| Termo do requisito | Pode virar classe? | Justificativa didática |
|---|---|---|
| Aluno | Sim | Tem identidade, matrícula e participa da solicitação de matrícula. |
| Matrícula | Sim | Registra a ligação entre aluno e turma ofertada. |
| Disciplina ofertada | Sim | Pode ser modelada como TurmaOferta, pois inclui semestre, vagas e horário. |
| Vaga | Geralmente não | Neste recorte, é melhor como atributo numérico da turma ofertada. |
| Pré-requisito | Depende | Pode ser classe própria em um sistema completo; neste artigo ficará como TODO no validador. |
Uma associação indica que uma classe mantém relação com outra. Em JavaScript, isso aparece quando um objeto guarda referência para outro.
class DisciplinaExemplo {
constructor(codigo, nome) {
// Requisito relacionado: RF-02 — Consultar disciplinas.
this.codigo = codigo;
this.nome = nome;
}
}
class TurmaOfertaExemplo {
constructor(disciplina, semestre, vagasDisponiveis) {
// RF-04 — Gerenciar oferta: a secretaria cadastra ofertas de disciplinas.
// Associação: TurmaOfertaExemplo conhece uma DisciplinaExemplo.
this.disciplina = disciplina;
this.semestre = semestre;
this.vagasDisponiveis = vagasDisponiveis;
}
}
const disciplina = new DisciplinaExemplo("ESW101", "Engenharia de Software");
const turma = new TurmaOfertaExemplo(disciplina, "2026.1", 30);
A cardinalidade, também chamada de multiplicidade, informa quantos objetos podem participar de uma relação. Por exemplo: um aluno pode ter várias matrículas, mas cada matrícula pertence a um único aluno.
| Notação | Significado | Exemplo no SIGMAT |
|---|---|---|
1 |
Exatamente um | Uma matrícula pertence a um aluno. |
0..1 |
Nenhum ou um | Uma matrícula pode ter ou não comprovante emitido. |
0..* |
Nenhum ou muitos | Um aluno pode ter várias matrículas. |
1..* |
Um ou muitos | Um curso pode ter uma ou mais disciplinas obrigatórias. |
class AlunoComMatriculas {
constructor(nome, matricula) {
this.nome = nome;
this.matricula = matricula;
// Associação Aluno 1 —— 0..* Matricula.
// Observação: em UML, a multiplicidade aparece na ponta da associação.
// No código, ela costuma aparecer como uma coleção.
this.matriculas = [];
}
adicionarMatricula(matricula) {
// RF-01 — Realizar matrícula: registra uma matrícula para o aluno.
this.matriculas.push(matricula);
}
}
A herança representa uma relação do tipo “é um”. No SIGMAT, um aluno é um usuário do sistema. Um servidor da secretaria também é um usuário do sistema.
class UsuarioSistema {
constructor(nome, email) {
// Dados comuns a diferentes usuários do SIGMAT.
this.nome = nome;
this.email = email;
}
autenticar() {
// Requisito relacionado ao contexto do SIGMAT: autenticação institucional.
// TODO(RNF/Segurança): integrar com SSO institucional em uma versão real.
return `${this.email} autenticado`;
}
}
class AlunoUsuario extends UsuarioSistema {
constructor(nome, email, matricula) {
super(nome, email);
this.matricula = matricula;
}
}
class ServidorSecretariaUsuario extends UsuarioSistema {
constructor(nome, email, setor) {
super(nome, email);
this.setor = setor;
}
registrarOferta(disciplina, semestre, vagasDisponiveis = 30) {
// RF-04 — Gerenciar Oferta.
// A secretaria pode criar uma turma ofertada para uma disciplina.
// Neste exemplo intermediário, usamos TurmaOfertaExemplo,
// definida anteriormente, para evitar misturar todas as classes finais.
return new TurmaOfertaExemplo(disciplina, semestre, vagasDisponiveis);
}
}
A pergunta-guia é: “Aluno é um Usuário?”. Se sim, herança pode fazer sentido. Se a frase correta for “Aluno tem Matrículas”, então provavelmente é associação, não herança.
Agregação e composição são relações todo-parte. A agregação é uma relação mais fraca: as partes podem existir independentemente do todo. A composição é mais forte: a parte faz sentido como parte daquele todo.
class CursoExemplo {
constructor(nome) {
this.nome = nome;
// Agregação: o curso reúne disciplinas.
// As disciplinas podem continuar existindo no catálogo institucional.
this.disciplinas = [];
}
adicionarDisciplina(disciplina) {
this.disciplinas.push(disciplina);
}
}
class ComprovanteMatriculaExemplo {
constructor(codigo, dataEmissao) {
this.codigo = codigo;
this.dataEmissao = dataEmissao;
}
}
class MatriculaComComprovanteExemplo {
constructor(aluno, turma) {
this.aluno = aluno;
this.turma = turma;
this.comprovante = null; // Cardinalidade 0..1.
}
emitirComprovante() {
// RF-05 — Emitir comprovante.
if (this.comprovante) {
throw new Error("Comprovante já emitido para esta matrícula.");
}
this.comprovante = new ComprovanteMatriculaExemplo(
`COMP-${Date.now()}`,
new Date()
);
return this.comprovante;
}
}
Na UML, agregação e composição podem ser entendidas como formas especiais de associação. Toda agregação ou composição liga classes, mas acrescenta a ideia de relação todo-parte. Por isso, quando essa diferença não ajuda a compreender o sistema, muitas equipes preferem representar apenas uma associação comum.
A dependência é uma relação mais fraca que a associação. Ela indica que uma classe usa outra para cumprir uma tarefa, sem necessariamente possuir essa outra classe como parte permanente.
class ValidadorMatriculaExemplo {
podeMatricular(aluno, turma) {
// RF-01 — Realizar matrícula.
// RN-04 — A matrícula só é confirmada se houver vaga disponível.
const possuiVaga = turma.temVaga();
// TODO(RN-02): validar pré-requisitos cumpridos pelo aluno.
// TODO(RN-01): validar limite máximo de créditos por semestre.
// TODO(RN-03): validar conflito de horário.
// TODO(RN-05): validar período de matrícula.
return possuiVaga;
}
}
class ServicoMatriculaExemplo {
constructor(validador) {
// Dependência: este serviço usa um validador.
this.validador = validador;
}
matricular(aluno, turma) {
if (!this.validador.podeMatricular(aluno, turma)) {
return null;
}
// Encapsulamento didático: quem altera as vagas é a própria turma.
turma.ocuparVaga();
return { aluno, turma, status: "confirmada" };
}
}
A matriz de diagnóstico é uma tabela de apoio para decidir qual relação usar entre duas classes. Ela é útil porque força o aluno a escrever a relação em linguagem natural antes de desenhar linhas e setas.
Para criar a matriz:
- Liste pares de classes candidatas.
- Escreva uma frase simples sobre a relação entre elas.
- Faça a pergunta diagnóstica: “é um?”, “tem?”, “usa?”, “é parte de?”.
- Escolha a relação UML mais adequada.
| Pergunta | Relação provável | Exemplo no SIGMAT | Indício no código |
|---|---|---|---|
| “É um tipo de?” | Herança | Aluno é um Usuário. | class Aluno extends Usuario |
| “Conhece ou se liga a?” | Associação | Matrícula liga Aluno e TurmaOferta. | this.aluno = aluno |
| “Reúne partes independentes?” | Agregação | Curso reúne disciplinas. | this.disciplinas = [] |
| “A parte depende fortemente do todo?” | Composição | Matrícula gera comprovante. | new ComprovanteMatricula(...) |
| “Apenas usa para executar algo?” | Dependência | Serviço usa ValidadorMatricula. | this.validador.podeMatricular(...) |
O diagrama de classes é um diagrama estrutural da UML. A UML é uma linguagem padronizada pela Object Management Group para visualizar, especificar, construir e documentar artefatos de sistemas de software OMG (2017). Em termos práticos, o diagrama de classes mostra classes, atributos, métodos e relacionamentos VALENTE (2020).
Para criar um diagrama de classes para iniciantes:
- Escolha um recorte. Exemplo: “realizar matrícula em disciplina”.
- Leia os requisitos. No SIGMAT, o RF-01 orienta a matrícula; o RF-04 orienta a oferta; o RF-05 orienta o comprovante.
- Liste classes candidatas. Aluno, Disciplina, TurmaOferta, Matricula, ComprovanteMatricula, ValidadorMatricula.
- Defina atributos. Nome, matrícula, código, semestre, vagas, status.
- Defina métodos.
temVaga(),ocuparVaga(),adicionarMatricula(),emitirComprovante(). - Desenhe relações e cardinalidades. Um aluno pode ter muitas matrículas; uma matrícula pertence a uma turma.
- Valide contra os requisitos. Se uma classe ou método não ajuda a cumprir requisito algum, talvez esteja cedo para incluí-lo.
#, pacotes e padrões de projeto.
O diagrama abaixo representa apenas o recorte “realizar matrícula em disciplina”. Ele não tenta modelar todo o SIGMAT. Isso evita excesso de caixas e permite discutir com clareza o que será implementado.
Matricula possui composição com Comprovante porque o comprovante pertence à matrícula e só faz sentido como resultado dela. Já ServicoMatricula cria uma Matricula, mas não é “dono” dela no sentido todo-parte. Ele apenas orquestra o caso de uso. Por isso, a relação entre ServicoMatricula e Matricula aparece como dependência tracejada, não como composição.
O código abaixo corresponde ao diagrama parcial. Ele não é o SIGMAT completo, mas mostra como classes, relações e requisitos podem orientar uma implementação inicial.
class Usuario {
constructor(nome, email) {
// Base comum dos usuários do SIGMAT.
this.nome = nome;
this.email = email;
}
}
class Aluno extends Usuario {
constructor(nome, email, matricula) {
super(nome, email);
this.matricula = matricula;
// Associação Aluno 1 —— 0..* Matricula.
this.matriculas = [];
}
adicionarMatricula(matricula) {
// RF-01 — Realizar Matrícula.
// O aluno passa a possuir mais uma matrícula confirmada.
this.matriculas.push(matricula);
}
}
class ServidorSecretaria extends Usuario {
constructor(nome, email, setor) {
super(nome, email);
this.setor = setor;
}
registrarOferta(disciplina, semestre, vagasDisponiveis) {
// RF-04 — Gerenciar Oferta.
// A secretaria cadastra uma turma ofertada para o semestre.
return new TurmaOferta(disciplina, semestre, vagasDisponiveis);
}
}
class Disciplina {
constructor(codigo, nome, creditos = 4) {
// RF-02 — Consultar Disciplinas.
// A disciplina precisa ter dados exibíveis na consulta.
this.codigo = codigo;
this.nome = nome;
this.creditos = creditos;
}
}
class TurmaOferta {
constructor(disciplina, semestre, vagasDisponiveis) {
// Associação: uma turma ofertada se refere a uma disciplina.
this.disciplina = disciplina;
this.semestre = semestre;
// RN-04 — Vagas.
// Em um sistema didático, o atributo fica público para simplificar.
// Convenção de projeto: outras classes não devem alterar este valor diretamente.
// A alteração deve ocorrer pelo método ocuparVaga().
this.vagasDisponiveis = vagasDisponiveis;
}
temVaga() {
// RN-04 — A matrícula só pode ocorrer se houver vaga disponível.
return this.vagasDisponiveis > 0;
}
ocuparVaga() {
// Encapsulamento didático:
// a própria turma controla como uma vaga é ocupada.
if (!this.temVaga()) {
throw new Error("Não há vagas disponíveis para esta turma.");
}
this.vagasDisponiveis -= 1;
}
}
class Matricula {
constructor(aluno, turma) {
// Associação: matrícula liga Aluno e TurmaOferta.
this.aluno = aluno;
this.turma = turma;
// RF-01 — Realizar Matrícula.
this.status = "confirmada";
this.dataSolicitacao = new Date();
// Cardinalidade 0..1: pode ainda não existir comprovante.
this.comprovante = null;
}
emitirComprovante() {
// RF-05 — Emitir Comprovante.
// Evita sobrescrever silenciosamente um comprovante já emitido.
if (this.comprovante) {
throw new Error("Comprovante já emitido para esta matrícula.");
}
this.comprovante = new ComprovanteMatricula(
`COMP-${this.aluno.matricula}-${Date.now()}`,
new Date()
);
return this.comprovante;
}
}
class ComprovanteMatricula {
constructor(codigo, dataEmissao) {
// RF-05 — Emitir Comprovante.
this.codigo = codigo;
this.dataEmissao = dataEmissao;
}
}
class ValidadorMatricula {
podeMatricular(aluno, turma) {
// RF-01 — Realizar Matrícula.
// RN-04 — Vagas: implementado neste recorte.
const possuiVaga = turma.temVaga();
// TODO(RN-02): validar se o aluno cumpriu os pré-requisitos.
// TODO(RN-01): validar se o aluno não excede 28 créditos no semestre.
// TODO(RN-03): validar se não há conflito de horário.
// TODO(RN-05): validar se o período de matrícula está aberto.
// TODO(RNF-03): registrar auditoria da tentativa de matrícula.
return possuiVaga;
}
}
class ServicoMatricula {
constructor(validador) {
// Dependência: o serviço usa um validador.
this.validador = validador;
}
matricular(aluno, turma) {
// RF-01 — Realizar Matrícula.
if (!this.validador.podeMatricular(aluno, turma)) {
return null;
}
// Encapsulamento: o serviço não altera a vaga diretamente.
// Ele pede que a própria turma execute essa mudança.
turma.ocuparVaga();
const matricula = new Matricula(aluno, turma);
// Mantém o estado do aluno coerente com a matrícula criada.
aluno.adicionarMatricula(matricula);
return matricula;
}
}
// Uso didático do recorte
const secretaria = new ServidorSecretaria(
"Marina",
"marina@universidade.edu",
"Secretaria Acadêmica"
);
const disciplina = new Disciplina("ESW101", "Engenharia de Software", 4);
const turma = secretaria.registrarOferta(disciplina, "2026.1", 30);
const aluno = new Aluno("Ana Souza", "ana@aluno.edu", "2026001");
const servico = new ServicoMatricula(new ValidadorMatricula());
const matricula = servico.matricular(aluno, turma);
if (matricula) {
const comprovante = matricula.emitirComprovante();
console.log(matricula.status); // confirmada
console.log(comprovante.codigo); // COMP-2026001-...
console.log(turma.vagasDisponiveis); // 29
}
Entraram no diagrama as classes necessárias para explicar o recorte “realizar matrícula”: usuário, aluno, secretaria, disciplina, turma ofertada, matrícula, comprovante, validador e serviço de matrícula.
Ficaram de fora, de propósito, telas, banco de dados, autenticação real por SSO, geração de PDF, histórico escolar completo, horários detalhados, lista de espera e integração com sistemas externos. Esses elementos podem aparecer em outros diagramas ou em uma versão mais avançada do modelo.
Classe é uma ideia central da programação orientada a objetos porque permite transformar conceitos do domínio em estruturas de software. No SIGMAT, conceitos como aluno, turma ofertada e matrícula deixam de ser apenas palavras dos requisitos e passam a orientar atributos, métodos e relações.
Para quem está começando, o melhor caminho é progressivo: primeiro uma classe isolada; depois objetos; em seguida associação, cardinalidade, herança, agregação, composição e dependência. Só depois vale montar um diagrama maior. Ainda assim, maior não significa completo. Um bom diagrama de classes mostra o suficiente para compreender, discutir e implementar um recorte do sistema.
- BRASIL ACADÊMICO. Modelagem estrutural de soluções: do mapa de domínio ao C4 Model e UML. Brasil Acadêmico, 27 abr. 2026. Disponível em: https://blog.brasilacademico.com/2026/04/modelagem-estrutural-de-solucoes-do.html. Acesso em: 9 maio 2026.
- BRASIL ACADÊMICO. Introdução à UML e documentação: guia prático para engenharia de software. Brasil Acadêmico, 29 mar. 2026. Disponível em: https://blog.brasilacademico.com/2026/03/introducao-uml-e-documentacao-guia.html. Acesso em: 9 maio 2026.
- BRASIL ACADÊMICO. Documentação de requisitos: escrita estruturada de cenários. Brasil Acadêmico, 12 abr. 2026. Disponível em: https://blog.brasilacademico.com/2026/04/documentacao-de-requisitos-escrita.html. Acesso em: 9 maio 2026.
- FOWLER, Martin. UML essencial: um breve guia para a linguagem-padrão de modelagem de objetos. 3. ed. Porto Alegre: Bookman, 2005.
- OMG — OBJECT MANAGEMENT GROUP. Unified Modeling Language Specification, version 2.5.1. Needham: OMG, 2017. Disponível em: https://www.omg.org/spec/UML/2.5.1. Acesso em: 9 maio 2026.
- VALENTE, Marco Tulio. Engenharia de Software Moderna: capítulo 4 — Modelos. Disponível em: https://engsoftmoderna.info/cap4.html#diagrama-de-classes. Acesso em: 9 maio 2026.
Visto no Brasil Acadêmico








Comentários