Introdução ao Diagrama de Estrutura Funcional

Um novo diagrama para trabalho visual e estruturado de funcionalidades

Por Virgílio V. Vilela

Um diagrama para modelagem visual e estruturada de requisitos funcionais, não previsto na UML, no BDD ou RML, sem histórias de usuário e sem casos de uso, será possível? Foi onde chegamos ao buscar soluções para limites e dificuldades ao trabalhar com documentos de casos de uso. Confira neste artigo se é tudo isso mesmo.

Um novo diagrama e tudo mudou

Apertei um botão e foram gerados automaticamente um documento de caso de uso com 100% da estrutura e cerca de 50% do conteúdo, um protótipo e mais um documento da interface do caso de uso, com imagens das telas geradas a partir do protótipo.

Esse foi o ápice de uma longa jornada, cuja base foi um diagrama para modelagem estruturada e visual de requisitos, o diagrama de estrutura funcional. Este teve origem nas dificuldades que encontramos para pensar e trabalhar com casos de uso e questionamentos decorrentes. Estranhamente, por ser deduzido e não inventado, não está previsto na UML, no BDD (Behavior Driven Development), com que tem em comum a ênfase em comportamento de aplicativos, nem na RML (Requirements Modeling Language) que, além de enfatizar diagramas também adota uma perspectiva externa aos aplicativos.

Este artigo conta como surgiu esse diagrama, introduz seus principais elementos e, principalmente, mostra sua aplicabilidade, sem o que nada tem valor prático. Também mostramos as relações da estrutura funcional com histórias de usuário e casos de uso.

Origens

Quando comecei como analista de sistemas em uma grande empresa pública, em 1994, usávamos a ferramenta CASE Cool:Gen, hoje CA Gen, baseada em diagramas, que gerava código automático; nossa equipe, de quatro analistas, nem tinha programadores. Ninguém tinha experiência, mas desenvolvemos em dois anos um sistema de orçamento relativamente complexo, com reforço somente nos últimos seis meses.

Anos depois, fui trabalhar em um sistema que usava RUP; o sistema estava em desenvolvimento há 10 anos e, quando entregou o primeiro aplicativo, para a Web, ele tinha sido desenvolvido pelo arquiteto com um gestor do lado.

De onde eu vinha, modelar requisitos e comportamentos de aplicativos em texto, semiestruturado mas texto, soava como um tremendo retrocesso. Também tive dificuldades com o conceito de caso de uso; não percebia clareza, e meu pensamento não funciona bem sem clareza de ideias. Mas questionar uma metodologia amplamente usada e um conceito formalizado e estabelecido não foi no início uma opção considerada.

Buscando aprofundamento, estudei a documentação da metodologia. Senti muita falta de exemplos. A sensação de confusão aumentava ao ouvir referências a casos de uso de sistema e de negócio, “tecnológicos” e “essenciais”. Como havia artefatos prontos para servirem de modelo, eu os segui, mas a sensação de que faltava alguma coisa durou muito tempo.

Acabei eventualmente questionando, e questionando busquei, e buscando encontrei não só as razões da confusão como uma solução: foi um diagrama de modelagem de funcionalidades. Após as ideias iniciais, validei e evoluí o metamodelo modelando todo o sistema em que trabalhava, que tinha na época 120 casos de uso.

Talvez a melhor validação tenha sido entanto gerar código fonte a partir do modelo; elaborar um programa testa conceitos no nível máximo de detalhe. Na prova de conceito mais complexa que já fiz, e que envolveu outros dois modelos, um programa gerou, para cada funcionalidade do tipo CRUD:

Uma outra validação decisiva foi apresentar o diagrama de estrutura funcional para outras pessoas sem explicações; para quem tinha familiaridade com o conteúdo, ele se revelou intuitivo.

Outros aspectos interessantes são não ter que pensar em “modo texto” e também, em decorrência, poder separar a análise da redação.

Posteriormente, usei esse diagrama para montar um processo completo de requisitos sem necessidade de casos de uso e histórias de usuário, e que ainda servia para gerar grande parte do código diretamente.

A seguir descrevo a dedução do modelo a partir de uma funcionalidade do Facebook; mais para o final comento como ele foi originalmente deduzido a partir de documentos de caso de uso.

O diagrama

Rigorosamente falando, o diagrama de estrutura funcional não foi inventado; ele foi deduzido, modelado a partir de casos de uso. Outra forma de deduzi-lo é a partir da observação externa de aplicativos, isto é, do ponto de vista de um usuário, a que usaremos nesta parte.

A essência da modelagem é simples e consiste em responder à pergunta: o que eu posso fazer com esse aplicativo?

Vamos partir de uma funcionalidade real. O Facebook tem uma tela chamada Criar publicação, como na figura.

O que está indicado que podemos fazer nessa tela?

(“Indicado” porque de fato, quando o diálogo for ativado, a tela vai mudar.)

Em um diagrama de estrutura funcional, representamos essas possibilidades assim:

Cada um desses “fazeres” é chamado de comportamento de aplicativo, no contexto somente comportamento. Um comportamento é a menor unidade de atividade de um aplicativo que faz algo relevante para o usuário. “Relevante” não é necessariamente “útil”, pode ser uma entrada de dados ou algo necessário para se fazer outra coisa. Por exemplo, a emissão de um relatório, para o usuário, é uma só ação, mas uma implementação assíncrona pode resultar em dois comportamentos, um de solicitação e outro de consulta.

Uma linha conectando dois comportamentos é chamada de transição. Há alguns tipos de transição; no exemplo foi necessário somente um tipo.

Quando clicamos no campo de texto da publicação, aparece um diálogo modal como o da figura.

Nessa tela aparecem outras possibilidades para fazermos, como formatar plano de fundo, inserir gif e emoji e selecionar público. A estrutura funcional fica assim:

Explorando as ramificações, vamos encontrando mais possibilidades para o que fazer. Por exemplo, ao selecionarmos Público, há uma opção para personalizar o público. Clicando no botão Ver mais, descobrimos que podemos inserir uma enquete, marcar um evento, e outras. Ao selecionar uma pergunta, podemos criar uma. Enviando no Messenger, podemos criar um grupo, e para isso pesquisar, adicionar e excluir pessoas. O diagrama fica como na próxima figura.

Note que a maioria dessas possibilidades não estão inicialmente visíveis; para descobri-las precisamos explorar. Com esse diagrama, podemos fazer isso em uma passada de olhos. Além disso, é muito mais fácil memorizar as possibilidades a partir de um diagrama do que a partir da exploração.

Todos esses comportamentos estão relacionados; eles compõem uma funcionalidade, no caso a funcionalidade Criar Publicação. Representando essa funcionalidade, temos o diagrama abaixo.

O comportamento Editar publicação está em cor diferente para marcar que ele é um ponto de entrada do aplicativo, isto é, um usuário pode acessar esse comportamento diretamente; os demais comportamentos só são acessíveis a partir de outro.

Como elemento de organização, a estrutura funcional também prevê módulos, que são grupos lógicos de funcionalidades.

Para sistemas maiores, também há submódulos e subfuncionalidades. No sistema que modelei originalmente havia um módulo gigante, o principal; para imprimir seu diagrama e pendurá-lo em uma parede, sem fragmentá-lo, usei uma plotter.

Estrutura Funcional como mapa

Um usuário entra no aplicativo por um ponto de entrada e dele vai passando por outros comportamentos, seguindo caminhos. Um diagrama de estrutura funcional funciona assim como um mapa de um aplicativo. Em um sentido, ele mostra o que é possível fazer com um aplicativo. Em outro, ele também mostra ao usuário onde ele está: editando, escolhendo o plano de fundo, marcando um evento?

Assim como um mapa responde à pergunta “Aonde posso ir a partir deste ponto?”, a estrutura funcional responde à pergunta “O que posso fazer a partir deste ponto?”. Por exemplo, se “estamos” em Criar grupo (figura), é possível pesquisar, adicionar e remover pessoas, além de retornar (é um padrão e geralmente fica implícito no diagrama de estrutura funcional).

De vez em quando, precisamos de respostas para uma pergunta básica, tanto como desenvolvedores quanto como usuários: o que é possível fazer em um aplicativo? Compare as seguintes possibilidades para obter essas respostas:

Para aplicativos maiores, é a mesma diferença entre explorar um território e ter um mapa desse território. Ou entre percorrer uma casa e observar um modelo de sua estrutura, a planta baixa.

Abaixo você vê uma miniatura de um diagrama de estrutura funcional de um módulo de tamanho médio de um sistema, usado profissionalmente. Note que, mesmo sem ler nada, você sabe quantas funcionalidades e comportamentos existem – dois níveis da estrutura. Também dá para saber onde está a funcionalidade central desse módulo. E, com um pouco de atenção, podemos até identificar que há três pontos de entrada e onde estão. Imagine obter as mesmas informações de qualquer outra maneira.

Estrutura Funcional como escopo

O fato de dispormos de um modelo da estrutura de algo facilita muitas coisas, além de conhecer. Por exemplo, quem for aprender vai planejar suas atividades segundo a estrutura; o mesmo para quem for ensinar. Em síntese, a estrutura é o escopo para a ação, assim como a planta de uma casa define o escopo para sua obra.

A estrutura funcional define e representa o escopo para o desenvolvimento de um aplicativo. Também analogamente à planta de uma casa, a estrutura funcional define o que será construído. Você deve bem saber a importância de termos um escopo claro e estável para o que vamos fazer.

Os requisitos funcionais têm portanto uma estrutura clara e completa para crescer e decrescer, na forma de:

Frequentemente precisamos atender certos objetivos durante o desenvolvimento, como fazer uma prova de conceito, mitigar riscos e certificar-nos de aspectos da infraestrutura. Para isso, podemos definir escopos intermediários, não entregáveis, em que apenas parte da estrutura funcional é codificada, como comportamentos de inclusão; os demais, se necessário, são manuais ou hard-coded. Com um diagrama de estrutura funcional, torna-se muito direto discutir e planejar esses escopos.

Na verdade, a estrutura funcional pode ser um pouco mais do que escopo de um aplicativo. Sendo essencial, ou seja, sem uma forma, de um mesmo modelo podem ser derivadas várias implementações, incluindo parciais.

Aplicabilidade

O valor de um diagrama pode ser medido pelos seus usos e aplicações. Já mostramos como a estrutura funcional pode ser usada para visualização rápida da estrutura de um aplicativo e tudo que isso facilita, incluindo o conhecimento e aprendizado rápidos. Vamos ver a seguir as principais aplicações desse diagrama que já descobrimos.

Modelo integrado de funcionalidades

Um dos problemas de quem usa histórias de usuário e casos de uso é a fragmentação da representação das funcionalidades: tudo fica muito espalhado em documentos, cartões ou coisa parecida, sem que as conexões entre os elementos fiquem aparentes. O RUP tem o modelo sintético de casos de uso, mas este, além de geralmente ficar visualmente bastante confuso, não mostra os comportamentos e, na minha experiência, somente é feita a versão inicial desse diagrama; se tivesse uma boa relação custo/benefício, ele seria atualizado.

O diagrama de estrutura funcional permite que todas as funcionalidades sejam mostradas no mesmo campo visual, com todas as transições explícitas. Na prática, sistemas muito grandes requerem particionamento do diagrama, mas isso pode ser feito por áreas ou módulos, e só precisamos repetir em cada diagrama o que estiver relacionado.

Modelo parcial de funcionalidades impactadas

No caso de manutenção no sistema, apenas um subconjunto das funcionalidades é relevante para um serviço. Para esses casos, podemos trabalhar somente com um diagrama parcial contendo somente as funcionalidades impactadas e algumas adjacentes, se for o caso.

Usei essa opção várias vezes, e nos casos mais complexos havia apenas uma ou duas funcionalidades novas e algumas outras importantes. Isso facilita muito tanto pensarmos sobre o serviço, o escopo de informação é bem menor, quanto nos comunicarmos sobre ele. Um princípio informal que adoto é que o que está presente e não é relevante está atrapalhando, e esse princípio se aplica muito adequadamente a diagramas.

Planejamento e controle

Um diagrama de estrutura funcional pode ser colorido de forma a mostrar a situação de desenvolvimento das funcionalidades e seus comportamentos. Por exemplo, verde está pronto, azul está em andamento e a cor normal para os não iniciados. Com isso, em segundos alguém pode ter uma ideia geral de como estão os trabalhos.

No caso de estar nos planos um MVP, este pode ser rapidamente discutido e definido com base no diagrama. Outra possibilidade é definir o que será automatizado e o que será manual em uma versão, o que também pode ser feito rapidamente.

Versões - Todo sistema é, bem, sistêmico, e assim tem muitas dependências funcionais. Em um diagrama de estrutura funcional feito por aplicativo especializado, é possível gerar um diagrama que mostra essas dependências e assim podemos visualizar os clusters funcionais e enxergar a estrutura para definir as versões do sistema. Em uma prova de conceito que fizemos, usamos o algoritmo de Sugiyama, de grafos, para essa finalidade.

Geração de código

Em um dos sistemas RUP em que trabalhei, havia uma etapa de arquitetura para os casos de uso, eventualmente com diagramas de sequência. Definindo-se uma correlação entre a estrutura funcional e a estrutura do código, essa etapa pode ser completamente eliminada.

Por exemplo, no caso do Java, podemos ter essas correspondências:

Temos usado essa estruturação nos últimos aplicativos que fizemos, incluindo um para diagramas e outro para o processo Requisitos Visuais, e está sendo uma experiência muitíssimo gratificante, em particular devido ao reduzido entrelaçamento das várias partes do código.

Havendo esses padrões, a estrutura do código pode ser gerada automaticamente a partir do modelo (o diagrama não é necessário).

No caso de aplicativo para a Web, fizemos uma prova de conceito em que cada funcionalidade era uma single page application, e todo o código ficava em um arquivo Javascript; dessa forma, um único template de página web atendia. Cada módulo tinha um diretório, e cada funcionalidade do módulo um subdiretório abaixo desse.

Os elementos do diagrama que apresentamos são somente uma introdução; o metamodelo tem outros elementos que permitem maior geração de código. Por exemplo, comportamentos podem ser on-line ou batch; os primeiros têm um elemento de interação do usuário onde podemos incluir dados, que podem ser usados para gerar formulários no aplicativo. A propósito, esse é um dos pontos de encontro da estrutura funcional com a camada de dados.

Ainda não testamos, mas também vislumbramos a possibilidade de incluir regras de negócio no modelo, o que aumentaria o poder de geração automática de código. Coisas como cálculos certamente podem ser automatizados, e no mínimo podemos usar regras em modo texto e associá-la aos comportamentos.

A ferramenta ICASE com que trabalhamos tinha uma linguagem própria para modelagem de comportamentos, toda metamodelada. Já fizemos alguns testes na direção de uma linguagem semelhante para detalhar comportamentos de aplicativos, e parece bem factível. Uma linguagem completa para essa finalidade permitirá gerar muito código automaticamente; com vinculação de código externo, 100% de automatização pode ser obtido.

Geração automática de documentos

O modelo de estrutura funcional (não o diagrama) por si permite estruturar um documento de caso de uso, por exemplo. Cada funcionalidade dá origem a um documento, um ponto de entrada se torna o fluxo básico e cada um dos demais comportamentos um fluxo alternativo.

Em um programa para essa finalidade, também foram geradas as referências cruzadas, assumindo que cada comportamento on-line teria uma ou mais telas. A base foi uma tipificação dos comportamentos on-line. Por exemplo, um comportamento de pesquisa tem duas telas, um de inclusão tem uma tela. Cada transição no modelo dá origem a uma referência cruzada.

O processo completo (veja este artigo) permite detalhar mais os passos de casos de uso através de diagramas de objetos de negócio e seu ciclo de vida.

Claro, é possível gerar documentos customizados para a estrutura funcional, incluindo imagens específicas para cada funcionalidade e suas conexões. Já investi muito em conversão e geração automática de conteúdo (todo este site, incluindo o autotreinamento em HTML e DOCX, foi gerado automaticamente a partir de manuscritos simplificados feitos no Word), e nesse contexto desenvolvi uma API com um builder de texto que torna a geração de conteúdo e sua conversão para documentos e HTML produtiva, confortável e verdadeiramente quase tão trivial quando editar em um aplicativo.

Reutilização

A estrutura funcional pode ser usada para modelar componentes e assim apoiar a reutilização nesse nível (há elementos de nível mais baixo para essa finalidade).

Para isso, seria mantida uma biblioteca de componentes, e o analista incluiria no seu diagrama de estrutura funcional os diagramas de outros componentes.

Ajuda

Sendo o diagrama de estrutura funcional uma espécie de mapa, ele pode ser usado como parte da ajuda do sistema. Dispondo-se das descrições, essa ajuda pode mostrá-las quando o cursor do mouse estiver sobre o elemento correspondente.

Na prova de conceito de geração automática de código que fizemos, um diagrama como ajuda estática foi gerado automaticamente e inserido no protótipo HTML.

Em uma versão mais sofisticada, a ajuda pode inclusive ser dinâmica, com um algoritmo que monta automaticamente instruções para o usuário a partir de onde ele está e o que quer fazer.

Estrutura funcional e casos de uso

A estrutura funcional teve sua origem na observação de que o que é conhecido como caso de uso, mais propriamente caso de uso de sistema, tinha uma estrutura interna que não era de fluxos de eventos. Por exemplo, um caso de uso chamado Manter Usuário tinha em sua descrição “pesquisar, incluir, consultar, alterar e excluir usuários”. Havia dependências entre essas unidades:

Essas unidades eram de fato estruturais mas não eram compatíveis com a estrutura de fluxo básico, fluxos alternativos e fluxos de exceção. Daí surgiu o conceito de comportamento de aplicativo e transições entre eles.

E a estrutura de fluxo de eventos mostrou-se bastante adequada como opção para modelar um comportamento (e não uma funcionalidade), incluindo pré- e pós-condições, o que inclusive confirmou a omissão do nível estrutural que detectamos.

Assim, em geral um caso de uso de sistema será uma funcionalidade e sua descrição conterá a relação dos comportamentos da funcionalidade.

Anomalias metodológicas

Essa incompatibilidade estrutural é uma anomalia metodológica muito grave: o nível estrutural primário para os usuários não está no metamodelo. Isso equivale a, em um planejamento usando o metamodelo do MS-Project, por exemplo, não ter a distinção ‘tarefa’. A ausência de conceitos estruturais tem grande impacto no pensamento e na comunicação; tente imaginar como você descreveria sua casa sem o conceito/ideia de “cômodo” e portanto sem suas especializações, como quarto, sala e cozinha.

Nesse caminho, descobrimos outra anomalia metodológica relacionada a casos de uso: este é um conceito originalmente concebido para modelar interações dos usuários com aplicativos. Assim, ele não pertence completamente nem ao contexto de negócio nem ao contexto de sistemas. Em toda empresa que trabalhei e de que soube, o caso de uso foi usado para modelar comportamento de aplicativos, e nunca para modelar as interações do usuário.

Acredito que isso se deve ao fato de que a UML não tem um metamodelo de aplicativo; imagino que alguém improvisou esse uso, justificado pela própria necessidade, e outros o seguiram. Essa inclusive seria a origem da incompatibilidade estrutural relatada acima.

O diagrama de estrutura funcional preenche essa importante lacuna metodológica.

Estrutura funcional e histórias de usuário

Embora ainda não trabalhado em um projeto que usasse histórias de usuário, o pouco que sei já me possibilitou enxergar relações bem interessantes desse conceito com a estrutura funcional.

Pelo que já observei, histórias de usuários podem indicar uma funcionalidade, um comportamento, uma regra de negócio. A melhor forma de verificar as correspondências entre histórias de usuário e a estrutura funcional é identificar qual ou quais elementos funcionais cada história contém. Veja o que consegui abaixo.

HISTÓRIA DE USUÁRIO/ÉPICO

ELEMENTO FUNCIONAL

Como vendedor, preciso poder consultar o preço de um produto para que eu possa informar ao cliente.

Comportamento Consultar preço produto

Como vendedor, devo selecionar uma forma de pagamento para que eu possa prosseguir com uma venda.

Comportamento Selecionar forma de pagamento

Como administrador, preciso ter acesso a um relatório de vendas para saber quanto recebi em determinado período.

Comportamento Gerar Relatório de Vendas

Detalhe: opção para escolher período

Estudantes só podem se matricular em cursos para os quais atendam os pré-requisito.

Regra de negócio do provável comportamento Efetuar matrícula.

Como um gerente, gostaria de visualizar todas as vendas pendentes para autorizar os andamentos das mesmas.

Dois comportamentos relacionados:

O cliente deseja atrelar à sua conta uma lista de desejos pela qual os amigos dele na plataforma consigam ver e presenteá-lo no aniversário.

Funcionalidade Manter Lista de Desejos. Esta deve ter definidos seus comportamentos para a lista e para os desejos (mais sobre isso abaixo).

Eu, enquanto comprador de livros, quero pesquisar um livro pelo título para poder comprá-lo.

Superficialmente pode parecer ser o comportamento Pesquisar livros por título, mas acho mais provável que seja Pesquisar livros, sendo o título uma opção para a pesquisa.

Listagem de produtos

Como um vendedor, eu gostaria de filtrar um produto na lista de produtos da loja para que eu possa filtrar os produtos por categoria e subcategoria.

Não me parece claro. Com a ajuda do título e pelas explicações de onde coletei o exemplo, parece ser algo assim:

Gostaria de fazer um comentário a respeito da qualidade metodológica do conceito de história de usuário. Adotar como critério de qualidade para esse conceito “Independência” (O “I” do modelo INVEST) me parece um tanto quanto desconectado da realidade. Por exemplo, no caso da lista de desejos exemplificada acima, um comportamento possível é incluir um produto na lista de desejos de alguém a partir da pesquisa de produtos. Funcionalmente, o comportamento Incluir produto em lista de desejo é da funcionalidade Manter Lista de Desejos, chamado do comportamento Detalhar produto da funcionalidade Manter Produtos (diagrama a seguir, parcial).

Essas dependências sistêmicas são frequentes em aplicativos maiores e não as ter em vista ao desenvolver acaba resultando em retrabalho não decorrente de evolução mas sim de fragmentação de modelagem, e portanto evitável.

Enxergamos um outro aspecto questionável em histórias de usuário. No livro User Stories Applied For Agile Software Development, Mike Kohn fornece o seguinte exemplo de épico, detalhado por algumas histórias de usuário:

A primeira história detalha o épico, enquanto as demais requerem ações do usuário. Ou seja, são histórias de tipos diferentes, aparecendo em um mesmo nível. Representar informações de níveis diferentes em um mesmo nível é perder organização e portanto confundir e dificultar o pensamento a respeito.

Uma primeira versão funcional para atender a esse requisito seria uma funcionalidade, digamos, Procurar Vagas, com os três comportamentos mostrados no diagrama abaixo.

Trabalhando com a estrutura funcional, primeiro estruturamos o que um usuário poderá fazer, para depois detalharmos cada unidade de fazer ou comportamento.


Veja também:

O processo Requisitos Visuais

Nem histórias de usuário, nem casos de uso, requisitos funcionais agora podem ser trabalhados só em diagramas, com visualização da estrutura!