Programação baseada em fluxo

Da Wikipédia, a enciclopédia livre
Ir para a navegação Saltar para pesquisar

Na programação de computadores , a programação baseada em fluxo ( FBP ) é um paradigma de programação que define aplicativos como redes de processos "caixa preta" , que trocam dados através de conexões predefinidas por passagem de mensagens , onde as conexões são especificadas externamente aos processos. Esses processos de caixa preta podem ser reconectados infinitamente para formar diferentes aplicativos sem precisar ser alterados internamente. O FBP é, portanto, naturalmente orientado a componentes .

FBP é uma forma particular de programação de fluxo de dados baseada em buffers limitados, pacotes de informações com tempos de vida definidos, portas nomeadas e definição separada de conexões.

Introdução

A programação baseada em fluxo define aplicativos usando a metáfora de uma "fábrica de dados". Ele vê um aplicativo não como um processo único e sequencial, que começa em um ponto no tempo e faz uma coisa de cada vez até ser concluído, mas como uma rede de processos assíncronos se comunicando por meio de fluxos de blocos de dados estruturados, chamados "pacotes de informação" (IPs). Nessa visualização, o foco está nos dados do aplicativo e nas transformações aplicadas a eles para produzir as saídas desejadas. A rede é definida externamente aos processos, como uma lista de conexões que é interpretada por um software, geralmente chamado de "agendador".

Os processos se comunicam por meio de conexões de capacidade fixa. Uma conexão é anexada a um processo por meio de uma porta , que possui um nome acordado entre o código do processo e a definição da rede. Mais de um processo pode executar o mesmo trecho de código. A qualquer momento, um determinado IP só pode ser "propriedade" de um único processo ou estar em trânsito entre dois processos. As portas podem ser simples ou do tipo array, conforme usado, por exemplo, para a porta de entrada do componente Collate descrito abaixo. É a combinação de portas com processos assíncronos que permite que muitas funções primitivas de processamento de dados de longa duração, como Classificar, Mesclar, Resumir, etc., sejam suportadas na forma de caixas pretas de software .

Como os processos FBP podem continuar sendo executados desde que tenham dados para trabalhar e em algum lugar para colocar sua saída, os aplicativos FBP geralmente são executados em menos tempo decorrido do que os programas convencionais e fazem uso ideal de todos os processadores em uma máquina, sem necessidade de programação especial Para alcançar isto. [1]

A definição de rede geralmente é diagramática e é convertida em uma lista de conexões em alguma linguagem ou notação de nível inferior. FBP é frequentemente uma linguagem de programação visual neste nível. Definições de rede mais complexas têm uma estrutura hierárquica, sendo construídas a partir de sub-redes com conexões "fixas". Muitas outras linguagens/tempos de execução baseados em fluxo são construídos em torno de linguagens de programação mais tradicionais, o exemplo mais notável é o RaftLib, que usa operadores semelhantes a C++ iostream para especificar o gráfico de fluxo.

FBP tem muito em comum com a linguagem de Linda [2] na medida em que é, na terminologia de Gelernter e Carriero, uma "linguagem de coordenação": [3] é essencialmente independente da linguagem. De fato, dado um escalonador escrito em uma linguagem de nível suficientemente baixo, componentes escritos em diferentes linguagens podem ser vinculados em uma única rede. O FBP, portanto, se presta ao conceito de linguagens específicas de domínio ou "mini-linguagens".

FBP exibe "acoplamento de dados", descrito no artigo sobre acoplamento como o tipo mais solto de acoplamento entre componentes. O conceito de baixo acoplamento está, por sua vez, relacionado ao de arquiteturas orientadas a serviços , e o FBP se encaixa em vários critérios para tal arquitetura, embora em um nível mais refinado do que a maioria dos exemplos dessa arquitetura.

O FBP promove um estilo funcional de especificações de alto nível que simplifica o raciocínio sobre o comportamento do sistema. Um exemplo disso é o modelo de fluxo de dados distribuído para especificar e analisar construtivamente a semântica de protocolos multipartidários distribuídos.

História

A Programação Baseada em Fluxo foi inventada por J. Paul Morrison no início dos anos 1970 e inicialmente implementada em software para um banco canadense. [4] FBP em seu início foi fortemente influenciado por algumas linguagens de simulação da IBM do período, em particular GPSS , mas suas raízes remontam ao artigo seminal de Conway sobre o que ele chamou de corrotinas . [5]

O FBP passou por várias mudanças de nome ao longo dos anos: a implementação original foi chamada de AMPS (Advanced Modular Processing System). Um grande aplicativo no Canadá entrou em operação em 1975 e, a partir de 2013, está em uso de produção contínua, funcionando diariamente, há quase 40 anos. Como a IBM considerou as ideias por trás do FBP "muito parecidas com uma lei da natureza" para serem patenteáveis, eles colocaram os conceitos básicos do FBP no domínio público, por meio de um Boletim de Divulgação Técnica , "Sistema de Programação de Tarefas Modulares Responsivas a Dados". , [6] em 1971. [4] Um artigo descrevendo seus conceitos e experiência usando-o foi publicado em 1978 no IBM Research IBM Systems Journal sob o nome DSLM. [7] Uma segunda implementação foi feita como um projeto conjunto da IBM Canadá e IBM Japão, sob o nome "Data Flow Development Manager" (DFDM), e foi brevemente comercializada no Japão no final dos anos 80 sob o nome "Data Flow Programming Manager".

Geralmente os conceitos eram referidos dentro da IBM como "Fluxo de Dados", mas este termo foi considerado muito geral e, eventualmente, o nome "Programação Baseada em Fluxo" foi adotado.

Do início dos anos 80 a 1993, J. Paul Morrison e o arquiteto da IBM Wayne Stevens refinaram e promoveram os conceitos por trás do FBP. Stevens escreveu vários artigos descrevendo e apoiando o conceito FBP e incluiu material sobre ele em vários de seus livros. [8] [9] [ fonte não primária necessária ] [10] [ fonte não primária necessária ] . Em 1994, Morrison publicou um livro descrevendo o FBP e fornecendo evidências empíricas de que o FBP levou a tempos de desenvolvimento reduzidos. [11]

Conceitos

O diagrama a seguir mostra as principais entidades de um diagrama FBP (além dos Pacotes de Informações). Esse diagrama pode ser convertido diretamente em uma lista de conexões, que pode ser executada por um mecanismo apropriado (software ou hardware).

Diagrama FBP simples

A, B e C são processos que executam componentes de código. O1, O2 e as duas INs são portas que conectam as conexões M e N aos seus respectivos processos. É permitido que os processos B e C executem o mesmo código, então cada processo deve ter seu próprio conjunto de armazenamento de trabalho, blocos de controle, etc. Quer compartilhem ou não o código, B e C estão livres para usar a mesma porta nomes, pois os nomes das portas só têm significado dentro dos componentes que os referenciam (e no nível da rede, é claro).

M e N são o que muitas vezes são chamados de " buffers limitados ", e têm uma capacidade fixa em termos do número de IPs que podem conter a qualquer momento.

O conceito de portas é o que permite que um mesmo componente seja utilizado em mais de um local da rede. Em combinação com uma capacidade de parametrização, chamada Initial Information Packets (IIPs), as portas fornecem ao FBP uma capacidade de reutilização de componentes, tornando o FBP uma arquitetura baseada em componentes . A FBP exibe assim o que Raoul de Campo e Nate Edwards da IBM Research chamaram de modularidade configurável .

Os pacotes de informações ou IPs são alocados no que pode ser chamado de "espaço IP" (assim como as tuplas de Linda são alocadas em "espaço de tupla") e têm um tempo de vida bem definido até que sejam descartados e seu espaço seja recuperado - no FBP isso deve ser uma ação explícita por parte de um processo de propriedade. IPs que viajam através de uma determinada conexão (na verdade, são seus "handle" que viajam) constituem um "stream", que é gerado e consumido de forma assíncrona - esse conceito tem semelhanças com o conceito de preguiçoso descrito no artigo de 1976 de Friedman e Wise. [12]

Os IPs geralmente são blocos estruturados de dados - alguns IPs, no entanto, podem não conter nenhum dado real, mas são usados ​​simplesmente como sinais. Um exemplo disso são os "IPs de colchete", que podem ser usados ​​para agrupar IPs de dados em padrões sequenciais dentro de um fluxo, chamados de "subfluxos". Os subfluxos podem, por sua vez, ser aninhados. Os IPs também podem ser encadeados para formar "árvores de IP", que trafegam pela rede como objetos únicos.

O sistema de conexões e processos descritos acima pode ser "ramificado" para qualquer tamanho. Durante o desenvolvimento de uma aplicação, processos de monitoramento podem ser adicionados entre pares de processos, processos podem ser "explodidos" em sub-redes ou simulações de processos podem ser substituídas pela lógica do processo real. O FBP, portanto, presta-se à prototipagem rápida .

Esta é realmente uma imagem de linha de montagem de processamento de dados: os IPs viajando através de uma rede de processos podem ser vistos como widgets viajando de estação para estação em uma linha de montagem. "Máquinas" podem ser facilmente reconectadas, retiradas de linha para reparos, substituídas e assim por diante. Curiosamente, essa imagem é muito semelhante à do equipamento de registro unitário que era usado para processar dados antes dos dias dos computadores, exceto que os baralhos de cartas tinham que ser carregados manualmente de uma máquina para outra.

As implementações do FBP podem ser não preemptivas ou preemptivas - as implementações anteriores tendiam a ser não preemptivas (mainframe e linguagem C), enquanto a implementação Java mais recente (veja abaixo) usa a classe Java Thread e é preemptiva.

Exemplos

"Problema do Telegram"

Os componentes FBP geralmente formam pares complementares. Este exemplo usa dois desses pares. O problema descrito parece muito simples como descrito em palavras, mas na verdade é surpreendentemente difícil de realizar usando a lógica procedural convencional. A tarefa, chamada de "Problema do Telegrama", originalmente descrita por Peter Naur , é escrever um programa que aceite linhas de texto e gere linhas de saída contendo o maior número de palavras possível, onde o número de caracteres em cada linha não exceda um determinado comprimento. As palavras não podem ser divididas e assumimos que nenhuma palavra é maior do que o tamanho das linhas de saída. Isso é análogo ao problema de quebra de palavras em editores de texto. [13]

Na lógica convencional, o programador descobre rapidamente que nem as estruturas de entrada nem de saída podem ser usadas para conduzir a hierarquia de chamadas do fluxo de controle . No FBP, por outro lado, a própria descrição do problema sugere uma solução:

  • "palavras" são mencionadas explicitamente na descrição do problema, então é razoável que o projetista trate palavras como pacotes de informação (IPs)
  • no FBP não existe uma hierarquia de chamada única, então o programador não é tentado a forçar um subpadrão da solução a ser o nível superior.

Aqui está a solução mais natural no FBP (não existe uma única solução "correta" no FBP, mas isso parece um ajuste natural):

O "problema do Telegram" de Peter Naur

onde DC e RC significam "DeCompose" e "ReCompose", respectivamente.

Conforme mencionado acima, os Pacotes de Informações Iniciais (IIPs) podem ser usados ​​para especificar informações paramétricas, como o comprimento do registro de saída desejado (exigido pelos dois componentes mais à direita) ou nomes de arquivos. IIPs são blocos de dados associados a uma porta na definição de rede que se tornam IPs "normais" quando um "recebimento" é emitido para a porta relevante.

Atualização em lote

Esse tipo de programa envolve passar um arquivo de "detalhes" (alterações, adições e exclusões) em relação a um "arquivo mestre" e produzir (pelo menos) um arquivo mestre atualizado e um ou mais relatórios. Programas de atualização são geralmente muito difíceis de codificar usando código síncrono e procedimental, pois dois (às vezes mais) fluxos de entrada precisam ser mantidos sincronizados, mesmo que haja mestres sem detalhes correspondentes, ou vice-versa.

Estrutura canônica de "atualização em lote"

No FBP, um componente reutilizável (Collate), baseado na ideia de registro de unidade de um Collator, torna a escrita desse tipo de aplicação muito mais fácil, pois o Collate mescla os dois fluxos e insere IPs de colchetes para indicar níveis de agrupamento, simplificando significativamente a lógica downstream. Suponha que um fluxo ("mestres" neste caso) consista em IPs com valores de chave de 1, 2 e 3, e os segundo IPs de fluxo ("detalhes") tenham valores de chave de 11, 12, 21, 31, 32, 33 e 41, onde o primeiro dígito corresponde aos valores da chave mestra. Usando caracteres de colchete para representar IPs de "colchete", o fluxo de saída agrupado será o seguinte:

(m1 d11 d12) (m2 d21) (m3 d31 d32 d33) (d41)

Como não houve mestre com valor 4, o último grupo é composto por um único detalhe (mais colchetes).

A estrutura do fluxo acima pode ser descrita sucintamente usando uma notação do tipo BNF , como

{ ([m] d*) }*

Collate é uma caixa preta reutilizável que só precisa saber onde estão os campos de controle em seus IPs de entrada (mesmo isso não é estritamente necessário, pois os processos do transformador podem ser inseridos upstream para colocar os campos de controle em locais padrão) e podem de fato ser generalizados para qualquer número de fluxos de entrada e qualquer profundidade de aninhamento de colchetes. Collate usa uma porta do tipo array para entrada, permitindo um número variável de fluxos de entrada.

Processos de multiplexação

A programação baseada em fluxo suporta a multiplexação de processos de uma maneira muito natural. Como os componentes são somente leitura, qualquer número de instâncias de um determinado componente ("processos") pode ser executado de forma assíncrona entre si.

Exemplo de multiplexação

Quando os computadores geralmente tinham um único processador, isso era útil quando havia muita E/S acontecendo; agora que as máquinas geralmente têm vários processadores, isso está começando a se tornar útil quando os processos também exigem muita CPU. O diagrama nesta seção mostra um único processo "Load Balancer" distribuindo dados entre três processos, rotulados S1, S2 e S3, respectivamente, que são instâncias de um único componente, que por sua vez alimentam um único processo em um "primeiro a chegar". , primeiro a ser servido".

Rede interativa simples

Esquema do aplicativo interativo geral

Neste esquema geral, as solicitações (transações) provenientes dos usuários entram no diagrama no canto superior esquerdo e as respostas são retornadas no canto inferior esquerdo. Os "back-ends" (no lado direito) se comunicam com sistemas em outros sites, por exemplo, usando CORBA , MQSeries , etc. rede mais de uma vez antes de ser devolvido ao usuário.

Como diferentes solicitações podem usar diferentes back-ends e podem exigir diferentes quantidades de tempo para os back-ends (se usados) processá-los, deve-se fazer uma provisão para relacionar os dados retornados às transações solicitantes apropriadas, por exemplo, tabelas de hash ou caches.

O diagrama acima é esquemático no sentido de que a aplicação final pode conter muitos outros processos: processos podem ser inseridos entre outros processos para gerenciar caches, exibir tráfego de conexão, monitorar taxa de transferência, etc. Também os blocos no diagrama podem representar "sub-redes" - pequenas redes com uma ou mais conexões abertas.

Comparação com outros paradigmas e metodologias

Jackson Structured Programming (JSP) e Jackson System Development (JSD)

Esta metodologia assume que um programa deve ser estruturado como uma única hierarquia procedimental de sub-rotinas. Seu ponto de partida é descrever a aplicação como um conjunto de "linhas principais", baseado nas estruturas de dados de entrada e saída. Uma dessas "linhas principais" é então escolhida para conduzir todo o programa, e as outras precisam ser "invertidas" para transformá-las em sub-rotinas (daí o nome "inversão de Jackson"). Isso às vezes resulta no que é chamado de "choque", exigindo que o programa seja dividido em vários programas ou corrotinas. Ao usar o FBP, esse processo de inversão não é necessário, pois cada componente do FBP pode ser considerado uma "linha principal" separada.

FBP e JSP compartilham o conceito de tratar um programa (ou alguns componentes) como um analisador de um fluxo de entrada.

No trabalho posterior de Jackson, Jackson System Development (JSD), as idéias foram desenvolvidas ainda mais. [14] [15]

No JSD o design é mantido como um design de rede até a fase final de implementação. O modelo é então transformado em um conjunto de processos sequenciais para o número de processadores disponíveis. Jackson discute a possibilidade de executar diretamente o modelo de rede que existia antes desta etapa, na seção 1.3 de seu livro (itálico adicionado):

A especificação produzida no final da etapa System Timing é, em princípio, passível de execução direta. O ambiente necessário conteria um processador para cada processo, um dispositivo equivalente a um buffer ilimitado para cada fluxo de dados e alguns dispositivos de entrada e saída onde o sistema está conectado ao mundo real. Tal ambiente poderia, é claro, ser fornecido por um software adequado rodando em uma máquina suficientemente poderosa. Às vezes, essa execução direta da especificação será possível e pode até ser uma escolha razoável. [15]

FBP foi reconhecido por MA Jackson como uma abordagem que segue seu método de "Decomposição de programas em processos sequenciais comunicando-se por um mecanismo semelhante a corrotina" [16]

Programação aplicativa

WB Ackerman define uma linguagem aplicativa como aquela que faz todo o seu processamento por meio de operadores aplicados a valores. [17] A primeira linguagem de aplicação conhecida foi LISP.

Um componente FBP pode ser considerado como uma função que transforma seu(s) fluxo(s) de entrada em seu(s) fluxo(s) de saída. Essas funções são então combinadas para fazer transformações mais complexas, como mostrado aqui:

Duas funções alimentando uma

Se rotularmos os fluxos, como mostrado, com letras minúsculas, o diagrama acima pode ser representado sucintamente da seguinte forma:

c = G(F(a),F(b));

Assim como na notação funcional F pode ser usado duas vezes porque só funciona com valores e, portanto, não tem efeitos colaterais, no FBP duas instâncias de um determinado componente podem estar sendo executadas simultaneamente e, portanto, os componentes FBP não devem ter efeitos colaterais qualquer. A notação funcional pode claramente ser usada para representar pelo menos uma parte de uma rede FBP.

A questão então surge se os componentes FBP podem ser expressos usando notação funcional. WH Burge mostrou como as expressões de fluxo podem ser desenvolvidas usando um estilo de programação recursivo e aplicativo, mas este trabalho foi em termos de (fluxos de) valores atômicos. [18] Em FBP, é necessário ser capaz de descrever e processar blocos de dados estruturados (FBP IPs).

Além disso, a maioria dos sistemas aplicativos assume que todos os dados estão disponíveis na memória ao mesmo tempo, enquanto os aplicativos FBP precisam ser capazes de processar fluxos de dados de longa duração enquanto ainda usam recursos finitos. Friedman e Wise sugeriram uma maneira de fazer isso adicionando o conceito de "contras preguiçosos" ao trabalho de Burge. Isso removeu a exigência de que ambos os argumentos de "contras" estivessem disponíveis no mesmo instante de tempo. "Lazy contras" não constrói um fluxo até que ambos os argumentos sejam realizados - antes disso, ele simplesmente grava uma "promessa" de fazer isso. Isso permite que um fluxo seja realizado dinamicamente na frente, mas com um back-end não realizado. O final do fluxo permanece não realizado até o final do processo,

Linda

Muitos dos conceitos em FBP parecem ter sido descobertos independentemente em diferentes sistemas ao longo dos anos. Linda, mencionada acima, é uma delas. A diferença entre as duas técnicas é ilustrada pela técnica de balanceamento de carga Linda "escola de piranhas" - no FBP, isso requer um componente extra "balanceador de carga" que roteia solicitações para o componente em uma lista que tem o menor número de IPs esperando para ser processado. Claramente, FBP e Linda estão intimamente relacionados, e um poderia ser facilmente usado para simular o outro.

Programação orientada a objetos

Um objeto em OOP pode ser descrito como uma unidade semi-autônoma que compreende informações e comportamento. Os objetos se comunicam por meio de "chamadas de método", que são essencialmente chamadas de sub-rotinas, feitas indiretamente por meio da classe à qual o objeto receptor pertence. Os dados internos do objeto só podem ser acessados ​​por meio de chamadas de métodos, portanto, esta é uma forma de ocultação ou "encapsulação" de informações. O encapsulamento, no entanto, é anterior à OOP - David Parnas escreveu um dos artigos seminais sobre ela no início dos anos 70 [19] - e é um conceito básico em computação. O encapsulamento é a própria essência de um componente FBP, que pode ser pensado como uma caixa preta, realizando alguma conversão de seus dados de entrada em seus dados de saída. No FBP, parte da especificação de um componente são os formatos de dados e estruturas de fluxo que ele pode aceitar e aqueles que ele irá gerar. Isso constitui uma forma de projeto por contrato . Além disso, os dados em um IP só podem ser acessados ​​diretamente pelo processo proprietário atual. O encapsulamento também pode ser implementado no nível da rede, fazendo com que os processos externos protejam os internos.

Um artigo de C. Ellis e S. Gibbs distingue entre objetos ativos e objetos passivos. [20] Objetos passivos compreendem informação e comportamento, como dito acima, mas não podem determinar o tempo desse comportamento. Objetos ativos, por outro lado, podem fazer isso. Em seu artigo Ellis e Gibbs afirmam que objetos ativos têm muito mais potencial para o desenvolvimento de sistemas sustentáveis ​​do que objetos passivos. Uma aplicação FBP pode ser vista como uma combinação desses dois tipos de objeto, onde os processos FBP corresponderiam a objetos ativos, enquanto os IPs corresponderiam a objetos passivos.

Modelo de ator

A FBP considera o Ator de Carl Hewitt como um processo assíncrono com 2 portas: uma para mensagens de entrada e outra para sinais de controle. Um sinal de controle é emitido pelo próprio ator após cada rodada de execução. O objetivo deste sinal é evitar a execução paralela do corpo do ator e assim permitir o acesso aos campos do objeto ator sem sincronização.

Veja também

Referências

  1. ^ "Programação baseada em fluxo" .
  2. ^ Carriero, Nicholas; Gelernter, David (1989). "Linda em contexto". Comunicações da ACM . 32 (4): 444–458. doi : 10.1145/63334.63337 . S2CID 5900105 . 
  3. ^ Gelernter, David; Carriero, Nicholas (1992). "Línguas de coordenação e seu significado". Comunicações da ACM . 35 (2): 97–107. doi : 10.1145/129630.129635 . S2CID 7748555 . 
  4. ^ a b Gabe Stein (agosto de 2013). "Como um método de codificação arcano do software bancário da década de 1970 poderia salvar a sanidade dos desenvolvedores da Web em todos os lugares" . Recuperado em 24 de janeiro de 2016 .
  5. ^ Conway, Melvin E. (1963). "Projeto de um compilador de diagrama de transição separável". Comunicações da ACM . 6 (7): 396–408. doi : 10.1145/366663.366704 . S2CID 10559786 . 
  6. ^ J. Paul Morrison, Data Responsive Modular, Interleaved Task Programming System, IBM Technical Disclosure Bulletin, Vol. 13, nº 8, 2425-2426, janeiro de 1971
  7. ^ Morrison, JP (1978). "Mecanismo de Ligação de Fluxo de Dados". Jornal de Sistemas IBM . 17 (4): 383–408. doi : 10.1147/sj.174.0383 .
  8. ^ Stevens, WP (1982). "Como o fluxo de dados pode melhorar a produtividade do desenvolvimento de aplicativos". Jornal de Sistemas IBM . 21 (2): 162-178. doi : 10.1147/sj.212.0162 .
  9. ^ WP Stevens, Using Data Flow for Application Development , Byte, junho de 1985
  10. ^ WP Stevens, projeto de software - conceitos e métodos , série prática da engenharia de software, Ed. Allen Macro, Prentice Hall, 1990, ISBN 0-13-820242-7 
  11. ^ Johnston, Wesley M.; Hanna, JR Paul; Millar, Richard J. (2004). "Avanços em linguagens de programação de fluxo de dados". Pesquisas de Computação ACM . 36 (1): 1–34. CiteSeerX 10.1.1.99.7265 . doi : 10.1145/1013208.1013209 . S2CID 5257722 .  
  12. ^ DP Friedman e DS Wise, CONS não deve avaliar seus argumentos, Automata, Languages ​​and Programming, Edinburgh University Press, Edimburgo, 1976
  13. ^ "Cópia arquivada" . Arquivado a partir do original em 2014-09-06 . Recuperado 2014-09-06 .{{cite web}}: CS1 maint: cópia arquivada como título ( link )
  14. ^ " Programação " por MA Jackson, publicado em Proceedings of Workshop on Software in High-Energy Physics, páginas 1-12 , CERN, Genebra, 4-6 de outubro de 1982
  15. ^ a b " A System development method Archived 2012-02-06 at the Wayback Machine " por MA Jackson, publicado em Ferramentas e noções para construção de programas: um curso avançado , Cambridge University Press, 1982
  16. ^ " JSP em perspectiva " Michael Jackson; JSP em Perspectiva; em Pioneiros de Software: Contribuições para Engenharia de Software; Manfred Broy, Ernst Denert eds; Springer, 2002
  17. ^ WB Ackerman, Data Flow Languages , Proceedings National Computer Conference, pp. 1087-1095, 1979
  18. ^ WH Burge, técnicas de programação recursiva , Addison-Wesley, Reading, MA, 1975
  19. ^ Parnas, DL (1972). "Sobre os critérios a serem usados ​​na decomposição de sistemas em módulos". Comunicações da ACM . 15 (12): 1053-1058. doi : 10.1145/361598.361623 . S2CID 53856438 . 
  20. ^ C. Ellis e S. Gibbs, Active Objects: Realities and Possibilities , em Object-Oriented Concepts, Databases, and Applications , eds. W. Kim e FH Lochovsky, ACM Press, Addison-Wesley, 1989

Links externos