Módulo 09 — Estudo de Caso aplicado a Requisitos

Onde estamos. Nos módulos anteriores destrinchamos a engenharia de requisitos peça por peça: o que é análise, como separar requisitos funcionais de não-funcionais, que técnicas usamos para levantar necessidades, como escrever casos de uso e histórias de usuário. Agora chegou a hora de juntar tudo. Neste módulo não introduzo nenhum conceito novo; em vez disso, conduzo você por um estudo de caso completo, do problema em bruto até um esboço de modelo de domínio, para que você veja como essas ferramentas conversam entre si quando aplicadas a um sistema concreto.

Deixe-me começar com uma confissão sobre como esse conteúdo costuma ser mal aprendido. É comum o estudante sair de um módulo de requisitos sabendo definir cada artefato de cor e mesmo assim travar diante de um problema real, porque cada conceito foi apresentado isolado, como peça de museu, e ninguém mostrou o fluxo que liga uma peça à seguinte. Vamos corrigir isso. Escolhi um sistema pequeno o bastante para caber num módulo e grande o bastante para exercitar todas as técnicas: um sistema de reserva de salas de estudo de uma biblioteca universitária. Todos os dados que vou usar são fictícios e servem apenas de ilustração didática; o que quero que você observe não são os números, mas o encadeamento das decisões.

O problema em bruto e os stakeholders

Todo trabalho de requisitos nasce de uma frustração vaga, quase nunca de uma especificação limpa. No nosso caso, a biblioteca possui algumas salas de estudo em grupo que vivem sendo disputadas, e a gestão atual é uma folha de papel presa na porta de cada sala, onde os alunos escrevem nome e horário. O resultado é o previsível — rasuras, reservas fantasma, brigas por sala, salas vazias que constam como ocupadas e nenhum dado sobre uso real. Alguém da coordenação diz: “precisamos de um sistema para isso”. Essa frase é o ponto de partida, e o trabalho do analista é transformá-la em algo que se possa efetivamente construir.

O primeiro movimento, antes de qualquer técnica sofisticada, é identificar quem tem interesse legítimo no sistema. Bezerra insiste que a análise começa por entender o contexto organizacional, e stakeholder é justamente qualquer pessoa ou grupo afetado pelo sistema ou capaz de afetá-lo. Se você pular essa etapa, corre o risco de projetar para um usuário imaginário e descobrir tarde demais que esqueceu de alguém decisivo.

NotaOs stakeholders do nosso estudo de caso

Aluno: reserva salas, é o usuário mais numeroso e o menos treinado. Bibliotecário/atendente: administra reservas, resolve conflitos no balcão, precisa de visão geral das salas. Coordenação da biblioteca: não usa o sistema no dia a dia, mas quer relatórios de uso para justificar investimentos. Equipe de TI: vai manter o sistema, portanto se importa com manutenibilidade e integração com o cadastro de alunos existente. Cada um desses grupos enxerga o sistema por uma janela diferente, e requisitos contraditórios entre eles são a regra, não a exceção.

Repare que já nessa lista aparece uma tensão: o aluno quer reservar em três cliques, a coordenação quer dados detalhados de cada reserva, e mais dados geralmente significam mais cliques. Guardar essa tensão desde o início evita que ela apareça como surpresa no fim.

Escolhendo e aplicando técnicas de elicitação

Com os stakeholders mapeados, o passo seguinte é decidir como extrair deles o que o sistema precisa fazer. Não existe técnica universalmente melhor; existe a técnica adequada a cada fonte. Sommerville organiza a elicitação como um processo de descoberta cuja escolha de técnicas depende de quem você tem à frente e de quanto o domínio já está estruturado.

Para o nosso caso, combinei três abordagens. Fiz entrevistas com o bibliotecário-chefe, porque ele detém o conhecimento tácito sobre os conflitos reais que a folha de papel gera — o tipo de informação que só emerge numa conversa aberta. Apliquei observação direta no balcão, porque o que as pessoas dizem que fazem quase nunca coincide com o que de fato fazem, e observar revelou que muitos alunos reservam sala e não aparecem. E usei um pequeno questionário com os alunos, adequado para alcançar muita gente com perguntas fechadas — nele descobri que a maior queixa não era falta de sala, mas incerteza sobre disponibilidade.

DicaPor que triangular técnicas

Nenhuma técnica isolada dá o quadro completo. A entrevista capta profundidade mas sofre de viés de quem fala; a observação revela o comportamento real mas não explica intenções; o questionário alcança escala mas perde nuance. Cruzar as três — o que a literatura chama de triangulação — é o que transforma impressões soltas em requisitos defensáveis.

Dessa fase saiu um caderno de anotações desorganizado, cheio de desejos, reclamações e ideias contraditórias. O próximo trabalho é dar ordem a esse material.

Da conversa aos requisitos: funcionais e não-funcionais

Organizar as descobertas significa, antes de tudo, separar o que o sistema faz daquilo que caracteriza como ele faz. Requisitos funcionais descrevem serviços e comportamentos; requisitos não-funcionais descrevem restrições e propriedades de qualidade. Essa separação, que antes pode ter soado acadêmica, agora ganha utilidade prática: ela impede que “o sistema deve ser rápido” e “o sistema deve permitir cancelar uma reserva” sejam tratados como se fossem a mesma coisa, quando exigem verificações completamente diferentes.

Abaixo estão os requisitos funcionais que emergiram da elicitação, já numerados e redigidos de forma testável. Note que cada um usa “deve” e descreve uma capacidade observável.

ID Requisito funcional Origem
RF01 O sistema deve permitir que o aluno consulte a disponibilidade das salas por data e horário. Questionário
RF02 O sistema deve permitir que o aluno reserve uma sala disponível para um intervalo de tempo. Entrevista
RF03 O sistema deve impedir reservas sobrepostas para a mesma sala. Observação
RF04 O sistema deve permitir que o aluno cancele sua própria reserva. Entrevista
RF05 O sistema deve registrar presença (check-in) e liberar a sala se não houver check-in em prazo definido. Observação
RF06 O sistema deve gerar relatório de ocupação por período para a coordenação. Entrevista

Os requisitos não-funcionais, por sua vez, não descrevem funções, mas exigências que o sistema inteiro precisa honrar. Eles costumam ser mais difíceis de arrancar dos stakeholders, porque raramente são ditos de forma explícita — ninguém entra numa entrevista dizendo “quero disponibilidade de 99%”. Cabe ao analista traduzir queixas em restrições mensuráveis.

ID Requisito não-funcional Categoria
RNF01 A consulta de disponibilidade deve responder em tempo percebido como imediato pelo aluno. Desempenho
RNF02 A interface de reserva deve ser utilizável sem treinamento por um aluno novato. Usabilidade
RNF03 O sistema deve autenticar o aluno pelo cadastro institucional já existente. Segurança/Integração
RNF04 Os dados de reserva devem ser preservados mesmo em caso de queda do serviço. Confiabilidade
RNF05 O sistema deve ser mantido pela equipe de TI sem depender do desenvolvedor original. Manutenibilidade
ImportanteUm erro que quero que você nunca cometa

Repare que o RNF01 não diz “o sistema deve ser rápido”. Requisito não-funcional que não se pode verificar é apenas um desejo. Sempre que escrever um, pergunte-se: como eu provaria, com um teste, que ele foi atendido? Se não houver resposta, o requisito ainda está vago demais. Aqui descrevi qualitativamente para não cravar um número fictício, mas num projeto real esse limiar seria negociado e fixado com o cliente.

Casos de uso: o comportamento visto de fora

Com os requisitos funcionais listados, podemos descrever o comportamento do sistema do ponto de vista de quem o usa. É exatamente para isso que servem os casos de uso: eles contam, em linguagem que o stakeholder entende, como um ator alcança um objetivo interagindo com o sistema. Bezerra trata o caso de uso como a ponte entre o requisito e o projeto, e é uma boa forma de validar com o usuário se entendemos o que ele precisa. Vou detalhar dois, com fluxo principal e alternativo, e o diagrama a seguir situa os atores e os casos.

flowchart LR
    aluno([Aluno]):::ator
    bib([Bibliotecário]):::ator
    coord([Coordenação]):::ator

    uc1[Consultar disponibilidade]
    uc2[Reservar sala]
    uc3[Cancelar reserva]
    uc4[Registrar check-in]
    uc5[Gerar relatório de ocupação]

    aluno --> uc1
    aluno --> uc2
    aluno --> uc3
    aluno --> uc4
    bib --> uc2
    bib --> uc3
    coord --> uc5

    classDef ator fill:#cfe2ff,stroke:#084298
    style uc2 fill:#d1e7dd,stroke:#0f5132
    style uc5 fill:#fff3cd,stroke:#664d03

O primeiro caso de uso é Reservar sala, o coração do sistema. Ator principal: o aluno; pré-condição: estar autenticado. O fluxo principal segue assim: o aluno informa data e horário desejados; o sistema apresenta as salas livres nesse intervalo; o aluno escolhe uma; o sistema verifica que a sala continua livre e confirma a reserva, registrando-a. A pós-condição é uma reserva ativa vinculada àquele aluno. Até aqui tudo corre bem — mas o valor de um caso de uso está justamente em pensar no que dá errado.

Fluxo alternativo do “Reservar sala”. No passo em que o sistema verifica que a sala continua livre, pode acontecer de outro aluno ter reservado a mesma sala nesse meio-tempo. O sistema então informa que a sala acabou de ficar indisponível, retorna à lista atualizada de salas livres e pede que o aluno escolha novamente. Esse fluxo alternativo é o que garante o RF03, a proibição de reservas sobrepostas, num cenário de concorrência real que a folha de papel nunca soube resolver.

O segundo caso de uso é Cancelar reserva. Ator principal: o aluno (o bibliotecário também pode cancelar em nome de um aluno, no balcão). Pré-condição: existir uma reserva ativa do aluno. O fluxo principal é curto — o aluno seleciona uma de suas reservas ativas, solicita o cancelamento, o sistema pede confirmação, o aluno confirma e o sistema libera a sala. O fluxo alternativo aparece quando o aluno tenta cancelar uma reserva cujo horário já começou ou passou: o sistema recusa o cancelamento retroativo e explica o motivo, preservando a integridade dos dados de ocupação que a coordenação vai analisar depois. Um terceiro caso de uso, Gerar relatório de ocupação, tem a coordenação como ator, roda sobre o histórico acumulado e alimenta o RF06; deixo seu detalhamento como exercício, agora que viu o padrão.

Histórias de usuário e critérios de aceitação

Casos de uso e histórias de usuário não são rivais; são lentes diferentes sobre a mesma necessidade. O caso de uso descreve o fluxo de interação em detalhe e serve bem à análise; a história é enxuta, centrada no valor para o usuário e adequada ao planejamento incremental. Muitas equipes usam as duas: a história para negociar prioridade e escopo, o caso de uso para detalhar quando chega a hora de construir. A história segue aquele formato que já conhecemos — como um papel, quero uma ação, para um benefício — e ganha rigor com critérios de aceitação, que dizem objetivamente quando ela está pronta.

História H1 — Consultar disponibilidade. Como aluno, quero ver quais salas estão livres em um horário, para escolher rapidamente onde estudar sem ir até a biblioteca. Critérios de aceitação: dado que informo uma data e um intervalo válidos, quando solicito a consulta, então vejo apenas as salas livres naquele intervalo; e se nenhuma sala estiver livre, então recebo uma mensagem clara em vez de uma lista vazia sem explicação.

História H2 — Reservar sala. Como aluno, quero reservar uma sala livre, para garantir meu lugar antes de me deslocar. Critérios de aceitação: dado que escolho uma sala livre, quando confirmo a reserva, então ela passa a constar como minha e some da lista de disponíveis; e se a sala for ocupada por outro aluno entre minha escolha e minha confirmação, então sou avisado e não fico com uma reserva inválida.

Observe que os critérios de aceitação da H2 são a mesma coisa que o fluxo alternativo do caso de uso “Reservar sala”, ditos de outra maneira. Isso não é redundância inútil: é rastreabilidade. Quando dois artefatos independentes apontam para a mesma regra, você ganha confiança de que ela é real, e não um capricho de redação.

Modelando as entidades do domínio

Requisitos bem compreendidos já contêm, em estado latente, a estrutura do domínio. Extraí-la é um exercício quase gramatical: os substantivos recorrentes costumam ser candidatos a entidades, e os verbos, a comportamentos e associações. Nas nossas listas e casos de uso, os substantivos que não param de reaparecer são aluno, sala, reserva e check-in. Bezerra recomenda exatamente essa leitura atenta do texto dos requisitos como ponto de partida da modelagem conceitual, lembrando que se trata de um modelo do domínio, e não ainda de um projeto de banco de dados ou de classes de implementação.

classDiagram
    class Aluno {
        +String matricula
        +String nome
        +List~Reserva~ reservas
    }
    class Sala {
        +String codigo
        +int capacidade
        +bool disponivelEm(intervalo)
    }
    class Reserva {
        +DateTime inicio
        +DateTime fim
        +StatusReserva status
        +bool conflitaCom(outra)
    }
    class CheckIn {
        +DateTime momento
    }
    Aluno "1" --> "*" Reserva : faz
    Sala "1" --> "*" Reserva : recebe
    Reserva "1" --> "0..1" CheckIn : registra

O diagrama comunica decisões importantes. Uma reserva não é um atributo solto do aluno nem da sala: é uma entidade própria, porque tem existência, estado e regras próprias — ela pode conflitar com outra, pode ser cancelada, pode ter ou não um check-in. Modelar a reserva como classe, em vez de espremê-la dentro de aluno ou de sala, é o que permite expressar com clareza o RF03 e o RF05. Essa é uma daquelas escolhas que separam um modelo que meramente funciona de um modelo que revela o domínio.

Do modelo ao código: entidades em Dart

Para você sentir como o modelo conceitual se traduz em estrutura verificável, vou expressá-lo em Dart. Não é ainda o sistema pronto; é o esqueleto das entidades, com a regra de negócio mais característica — a detecção de conflito de horário — codificada de forma explícita. Repare como o código apenas dá corpo ao que o diagrama já dizia.

enum StatusReserva { ativa, cancelada, concluida }

class Reserva {
  final String salaCodigo;
  final String alunoMatricula;
  final DateTime inicio;
  final DateTime fim;
  StatusReserva status;
  DateTime? checkIn;

  Reserva({
    required this.salaCodigo,
    required this.alunoMatricula,
    required this.inicio,
    required this.fim,
    this.status = StatusReserva.ativa,
  });

  // RF03: duas reservas ativas na mesma sala não podem se sobrepor no tempo.
  bool conflitaCom(Reserva outra) {
    if (salaCodigo != outra.salaCodigo) return false;
    if (status != StatusReserva.ativa) return false;
    return inicio.isBefore(outra.fim) && outra.inicio.isBefore(fim);
  }
}

O método conflitaCom é o núcleo de valor do sistema, aquele pedaço que a folha de papel na porta jamais conseguiu garantir. Ele traduz, em três linhas, o RF03 e o fluxo alternativo do caso de uso de reserva. Toda a elicitação, toda a separação de requisitos, todo o diagrama existiram para que essa regra fosse compreendida antes de ser escrita. Sem o percurso que fizemos, essa condição de sobreposição quase sempre nasce errada, porque os casos de fronteira — reservas que se encostam mas não se cruzam — passam despercebidos.

class Sala {
  final String codigo;
  final int capacidade;
  final List<Reserva> reservas;

  Sala({required this.codigo, required this.capacidade, List<Reserva>? reservas})
      : reservas = reservas ?? [];

  // RF01: uma sala está livre num intervalo se nenhuma reserva ativa conflita.
  bool disponivelPara(Reserva candidata) {
    return !reservas.any((r) => r.conflitaCom(candidata));
  }
}

Este segundo trecho mostra a associação “Sala recebe Reservas” do diagrama virando comportamento: a sala sabe responder se está livre para uma reserva candidata. A responsabilidade está no lugar certo — quem conhece as reservas de uma sala é a própria sala —, consequência direta de termos modelado o domínio antes de programar, e não durante.

Síntese

Quero que você leve três ideias deste estudo de caso. A primeira é que os artefatos de requisitos não vivem isolados: stakeholders levam a técnicas de elicitação, a elicitação produz requisitos, os requisitos funcionais viram casos de uso e histórias, e os substantivos desses textos revelam o modelo de domínio — é um fluxo, não uma coleção de gavetas. A segunda é que o valor de cada artefato aparece nos casos de exceção: o fluxo alternativo, o critério de aceitação negativo, o conflito de horário; é ali que a análise cuidadosa se paga. A terceira é que um bom modelo de domínio já contém o sistema em miniatura, e chegar a ele com clareza torna o código quase uma transcrição, e não uma descoberta arriscada. Percorra o caminho todo uma vez, com atenção, e você nunca mais vai olhar um requisito como uma peça de museu.

Para consolidar antes da aula: escolha um mini-sistema diferente do nosso — pode ser um controle de empréstimo de livros ou uma agenda de laboratório — e refaça sozinho o percurso completo: liste stakeholders, escolha técnicas de elicitação, escreva ao menos quatro requisitos funcionais e três não-funcionais, redija um caso de uso com fluxo alternativo e esboce o diagrama de classes do domínio. Se conseguir ligar cada artefato ao seguinte sem pular etapas, você dominou o objetivo deste módulo.