Resumo: ``Mordendo a Bala de Prata'':
Um Futuro mais Claro para o Desenvolvimento de Sistemas



David Harel


``Biting the Silver Bullet: Toward a Brighter Future for System Development''
IEEE Computer, Janeiro de 1992

Christian Reis
<kiko at async.com.br>

Resumo:

O artigo de Frederico Brooks ``No Silver Bullet'' [Brooks 1987] expressa opiniões fortes sobre as ilusões e esperanças que a engenharia de software pode oferecer. Este artigo [Harel 1992] revê estas opiniões e tenta dar um olhar mais positivo sobre a situação atual e futura. O artigo ainda expõe métodos novas que surgiram desde a publicação do artigo original: um framework geral para modelagem, associado às noções de executabilidade e geração do código baseadas neste modelo.

Passado versus Presente

A visão exposta por Fred Brooks em ``No Silver Bullet'' é uma tentativa de se desfazer mitos associados ao poder da Engenharia de Software. Embora a maior parte dos pontos que levanta estejam corretos, vale a pensa tentar levantar os pontos mais positivos da ciência, e expor novos desenvolvimentos na área.

Os argumentos de Brooks

Embora Brooks descreva, corretamente, que o maior problema do desenvolvimento será especificar, projetar e testar o sistema, sua análise dos novos desenvolvimentos na área (como programação em alto nível, projeto iterativo e reuso de componentes) é bastante pessimista, e a impressão que seu artigo fornece é de que as soluções possíveis são as já existentes, e de que o problema da complexidade do desenvolvimento nunca será resolvido. Além disso, o artigo releva os pontos associados ao desenvolvimento e codificação em si como sendo marginais aos problemas do desenvolvimento.

Uma situação semelhante anterior

O artigo de Brooks foca em uma margem de 10 anos de tempo. Fazendo uma análise dos últimos 40 anos, no entanto, podemos ter uma idéia melhor da evolução que a engenharia sofreu. Na época, o problema que a computação enfrentava era o de criar programas simples que perfaziam tarefas algoritmicas comuns. Embora não tenha aparecido uma solução mágica, e tenha levado mais de 10 anos para ser melhorado o processo de desenvolvimento, houve uma melhora inegável de uma ordem de magnitude no desenvolvimento de sistemas simples.

Frameworks conceituais

O ponto mais importante em gerar esta mudança foi o aparecimento de frameworks conceituais de propósito comum [chamada no texto do artigo original de vanilla ou ``baunilha'']. A base deste paradigma foram as noções da dicotomia de dados e controle, e formas convenientes de estruturar e combinar estes. Daí surgiram os tipos e estruturas de de dados, e uma série de métodos aritméticos para atacar o problema: programação dinâmica e dividir-para-conquistar, por exemplo. Podemos entender, portanto, que para programas simples, a solução para o problema da engenharia de software nos mostra que os problemas essenciais (especificação, modelagem e teste) estavam intimamente relacionados aos acidentais (a codificação em si).

Para o futuro

A situação atual, onde o problema é desenvolver sistemas complexos, pode ser similar. Destes sistemas, focaremos aqui nos programas reativos, categoria que inclui sistemas embutidos, concorrentes e de tempo real, por serem considerados particularmente problemáticos. Será exposta uma proposta para uma base para o desenvolvimento deste tipo de sistema.

Modelando o Sistema

Para capturar o conceito do sistema, precisamos criar abstrações que serão a base da solução. A tarefa seguinte é classificar estas abstrações em conjuntos análogos aos conjuntos dados e controle da programação algoritmica. Baseando-se em modularização e ocultação da informação, criamos uma hierarquia de atividades, que capturam as funções do sistema decompostas até um nível confortável, e associamos à hierarquia elementos e repositórios de dados às entradas e saídas das atividades. Associado a esta hierarquia, criamos descrições de comportamento que serão as atividades de controle, que se comportam como um sistema nervoso central do sistema, ativando funções e causando leitura de dados, por exemplo.

Junto ao modelo conceitual, é importante gerar um modelo físico, que descreva a arquitetura do sistema com relação aos módulos, canais e áreas de armazenamento.

Modelando comportamento e dados

A forma melhor encontrada para se modelar o comportamento tem sido descrever modos ou estados, junto com eventos e condições que geram transições entre as anteriores. Um série de soluções tem sido propostas para esta descrição, que vão desde estender máquinas de estados até statecharts.

Para a modelagem dos dados, podemos usar uma versão adaptada do modelo entidade-relacionamento, e associar as descrições aos repositórios de dados.

Camadas de modelos conceituais

Ao invés de se abstrair todo o sistema em descrições, é útil separar os níveis de refinamento em diversas camadas, onde existe um mapeamento entre os modelos refinados e os módulos em si. Esta idéia se adapta bem ao conceito de desenvolvimento iterativo top-down que Brooks defende.

Representação visual

Uma representação visual, embora muitas vezes ignorada, tem impacto direto sobre a forma com que pensamos na hora de construir o modelo. Embora flowcharts não seja mais apropriados, é interessante montar uma série de formalismos visuais com semânticas matemáticas associadas para descrever as relações entre os modelos e hierarquias. O surgimento de técnicas 3D para visualização pode influenciar bastante o uso destas formas de representação.

Métodos e guias

Criar um framework de propósito geral onde se possa capturar e representar um modelo de sistema, ao invés de se dar soluções completas e inflexíveis, parece ser a melhor forma de se criar um método para o desenvolvimento. Construir modelos bons, e escolher os guias corretos permanecerá como a tarefa do engenheiro de sistemas. Desta forma -- assim como temos diversas técnicas algoritmicas -- teremos um conjunto de metodologias que se adaptam a uma certa classe de problemas.

Analisando o Modelo

Embora seja comprovada a utilidade e necessidade de se fazer análise e teste do software, esta avaliação em geral começa tarde demais no processo de desenvolvimento, e se foca apenas em aspectos ``sintáticos'' do modelo. Para fazer uma análise real de erros semânticos e lógicos deste modelo, precisamos realmente testar e analisar o modelo.

Execução do modelo

Uma noção interessante é a de criar uma especificação executável do modelo, apoiado em semânticas formais para este modelo. A execução do modelo geraria eventos externos e acessaria as estruturas de dados internas do sistema, simulando a operação do sistema de uma forma passo-a-passo.

Interação e execução automatizada

Uma ferramenta poderia permitir ao usuário especificar e fazer esta execução passo-a-passo o sistema. Além disso, seria útil poder especificar um lote de comandos para processamento automático. O importante é que seja possível realizar esta execução em qualquer ponto e tempo do desenvolvimento, e que se construa o sistema em torno de uma base que está continuamente sendo corroborada.

Partindo deste conceito, poderíamos criar uma meta-linguagem para a execução do programa, associando breakpoints, especificando entradas - possivelmente randômicas - e gerando cenários diferentes. Usando a ferramenta para testar estes cenários seria muito mais informativo que simples análise de dependências de processos.

Execuções exaustivas

Embora testar exaustivamente o modelo completo seja em geral infactível, em geral é possível testar uma parte delimitada do sistema, ou uma seção com nível de complexidade reduzído. Desta forma, um teste poderia levar uma quantidade de tempo razoável, e ajudar a descobrir se condições pré-definidas poderiam ser alcançadas em algum momento.

Verificação temporal

Para estabelecer condições mais específicas do sistema, é possível utilizar a execução exaustiva associada a uma especificação de comportamento - um watchdog. Podem ser modelados em watchdogs também expressões de lógica temporal, ajudando a especificar limitações globais no comportamento do sistema. Um passo além da execução exaustiva poderia consistir em aplicar verificação automatizada e maquinas de estado muito grandes ao conceito de lógica temporal.

Geração e uso de código gerado

A compilação do modelo em código, se apoiada em um modelo mais completo como o descrito neste artigo, poderia ser feita muito mais completa e profundamente que atualmente é oferecida em ferramentas de geração. Este modelo mais completo teria já aspectos comportamentais, e o código poderia levar em conta estes relacionamentos. Partes não-especificadas mas disponíveis em bibliotecas poderiam ser ligadas ao código na hora da geração.

Este código, além de poder ser executado para teste, pode ser associado a uma simulação da interface para avaliação do cliente. Alterações ao modelo poderiam ser recompiladas em código e re-executadas. Código poderia também ser gerado para seções limitadas de comportamento, como os watchdogs discutidos acima.

Verificação de consistência entre camadas

Técnicas de análise de modelo podem ajudar a estabelecer se o refinamento das camadas foram corretos ou não. Baseados na executabilidade do modelo, bastaria comparar modelos de níveis diferentes para verificar se tem o comportamento esperado ou não. Mudanças nos sub-sistemas inferiores poderiam refletir em mudanças nos níveis superiores, de forma que o sistema ficaria cada vez mais completo. Aliado à otimização do código, esta técnica tem chance de oferecer finalmente a viabilidade à geração do código.

Conclusões

Existem realmente pontos onde este framework é menos aceito; a especificação de comportamento do modelo é um exemplo. No entanto, a idéia de um framework geral é boa, e certamente surgirá alguma alternativa vencedora. É bastante provável que inclua comportamento reativo, semânticas rigorosas, e visualização gráfica.

O surgimento de ferramentas com poder de geração e execução de código poderosas é bastante provável, e o poder de executar e testar o modelo será de grande valor. Em algum tempo, podem surgir técnicas associadas à executabilidade, como análise de timing e performance.

Estes prospectos para melhora, associados à cooperação entre os pesquisadores, sugerem que, ao invés de uma época de complexidade sem solução, é bastante possível que estejamos entrando em um período de desenvolvimentos e melhoras significativas.

Bibliografia

Brooks 1987
Brooks, Frederick P. ``No Silver Bullet: essence and accidents of Software Engineering.'' IEEE Computer, Abril de 1987.

Harel 1992
Harel, David. ``Biting the Silver Bullet: towards a brighter future for Systems Development.'' IEEE Computer, Janeiro de 1992.



Christian Reis 2000-09-14