{"id":4939,"date":"2022-06-23T16:31:57","date_gmt":"2022-06-23T19:31:57","guid":{"rendered":"https:\/\/elemarjr.com\/arquiteturadesoftware\/?p=4939"},"modified":"2024-01-11T18:08:25","modified_gmt":"2024-01-11T21:08:25","slug":"projetando-software-com-pipes-filters-capitulo-6-v1-02","status":"publish","type":"volume-1","link":"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/volume-1\/projetando-software-com-pipes-filters-capitulo-6-v1-02\/","title":{"rendered":"Projetando software com &#8220;Pipes &#038; Filters&#8221; \/ Cap\u00edtulo 6 v1.02"},"content":{"rendered":"<p>O estilo arquitetural\u00a0<em>Pipes and Filters\u00a0<\/em>emerge, naturalmente, quando arquitetos e desenvolvedores decidem decompor opera\u00e7\u00f5es complexas em unidades de processamento independentes, mais f\u00e1ceis de desenvolver e manter.\u00a0Entretanto, por desconhecimento, com frequ\u00eancia \u00e9 implementado de maneira descuidada e, em virtude disso, deficiente.<\/p>\n<p>Sistemas constru\u00eddos utilizando o estilo <em>Pipes and Filters\u00a0<\/em>processam\u00a0<em>streams\u00a0<\/em>de dados em etapas. Cada etapa \u00e9 encapsulada em um componente <em>filter.\u00a0<\/em>Dados s\u00e3o &#8220;passados&#8221; atrav\u00e9s de\u00a0<em>pipes<\/em> entre filtros adjacentes. Eventualmente, a recombina\u00e7\u00e3o dos\u00a0<em>filters<\/em> permite a constru\u00e7\u00e3o de sistemas familiares, aprimorados ou mais espec\u00edficos.<\/p>\n<p>Neste estilo arquitetural, componentes podem ser particionados tanto tecnicamente quanto com base no dom\u00ednio. Ele favorece atributos de qualidade importantes como performance, escalabilidade e reusabilidade, permitindo que seus componentes sejam implantados e escalados de maneira independente, favorecendo o\u00a0<em>evolvability.\u00a0<\/em><\/p>\nEste estilo arquitetural raramente ser\u00e1 aplic\u00e1vel a sistemas inteiros, mas sempre \u00e9 uma boa op\u00e7\u00e3o para partes importantes.\n<hr \/>\n<p>Bons exemplos de aplica\u00e7\u00e3o desse estilo s\u00e3o compiladores, solu\u00e7\u00f5es para renderiza\u00e7\u00e3o gr\u00e1fica e o padr\u00e3o MapReduce.<\/p>\n<h2>Conceito fundamental<\/h2>\n<p>Sistemas projetados utilizando o estilo arquitetural\u00a0<em>pipes and filters\u00a0<\/em>fazem o tratamento de dados, obtidos atrav\u00e9s de algum mecanismo de ingest\u00e3o ou produzidos internamente, movimentando-os atrav\u00e9s\u00a0de unidades computacionais independentes (os <em>filters), <\/em>conectadas de maneira planejada (as\u00a0<em>pipes<\/em>) para serem processados e enriquecidos, de maneira incremental e cont\u00ednua.<\/p>\n<div class=\"card-insight\" style=\"background-color: #f0f0f0; width: 100%; padding: 35px 30px 30px 35px; border-radius: 5px 5px 5px 5px; margin-top: 30px; margin-bottom: 35px; font-size: 16px; box-shadow: 0px 4px 0px 0px #dddddd;\">\r\n<p style=\"font-size: 24px; font-weight:bold; line-height: 28px; font-family: Montserrat;\">Uma analogia \u00fatil<\/p>\r\nImagine um sistema hidr\u00e1ulico respons\u00e1vel por fazer o tratamento de \u00e1gua impr\u00f3pria para consumo. Internamente, a \u00e1gua \u00e9 tratada sendo deslocada por meio de dutos e processada em &#8220;filtros&#8221; espec\u00edficos, cada um com uma fun\u00e7\u00e3o singular determinada, como, por exemplo, remover impurezas, regular acidez, adicionar cloro e ajustar a temperatura.<\/p>\n<hr \/>\n<p>Em sistemas implementados utilizando o estilo\u00a0<em>pipes and filters<\/em>, a &#8220;\u00e1gua&#8221; \u00e9 substitu\u00edda por dados, os dutos s\u00e3o substitu\u00eddos por algum mecanismo de comunica\u00e7\u00e3o e, finalmente, os filtros, s\u00e3o substitu\u00eddos por unidades computacionais.<\/p>\n<p><\/div>\n<p>Este estilo arquitetural tem quatro elementos b\u00e1sicos:<\/p>\n<ol>\n<li><em>filters,\u00a0<\/em>que\u00a0l\u00eaem dados a partir de uma ou mais\u00a0<em>read\u00a0ports<\/em>,\u00a0executam algum tipo de processamento espec\u00edfico, e escrevem os resultados em uma ou mais\u00a0<em>write ports<\/em>.<\/li>\n<li><em>pipes<\/em>, que conectam dois\u00a0<em>filters,\u00a0<\/em>recebendo <em>input\u00a0<\/em>de uma\u00a0<em>write port\u00a0<\/em>e escrevendo dados em uma\u00a0<em>read port<\/em>.<\/li>\n<li><em>read ports<\/em>, que s\u00e3o pontos de entrada para <em>filters, sendo\u00a0<\/em>respons\u00e1veis por converter dados em formatos diversos para uma representa\u00e7\u00e3o interna compat\u00edvel;<\/li>\n<li><em>write ports<\/em>, que s\u00e3o pontos de sa\u00edda dos <em>filters,<\/em>\u00a0convertendo resultados do processamento para\u00a0representa\u00e7\u00f5es em formatos espec\u00edficos.<\/li>\n<\/ol>\n<hr \/>\n<p>De maneira gen\u00e9rica, o tipo de processamento executado por um\u00a0<i>filter <\/i>inclui gerar, filtrar, transformar (inclusive enriquecendo),agregar e dar finalidade a dados.<\/p>\n<p><img decoding=\"async\" class=\"aligncenter wp-image-1661\" src=\"https:\/\/elemarjr.com\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/filter_00.png\" alt=\"\" width=\"213\" height=\"187\" srcset=\"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/filter_00.png 758w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/filter_00-300x263.png 300w\" sizes=\"(max-width: 213px) 100vw, 213px\" \/><\/p>\n<div class=\"card-insight\" style=\"background-color: #f0f0f0; width: 100%; padding: 35px 30px 30px 35px; border-radius: 5px 5px 5px 5px; margin-top: 30px; margin-bottom: 35px; font-size: 16px; box-shadow: 0px 4px 0px 0px #dddddd;\">\r\n<p style=\"font-size: 24px; font-weight:bold; line-height: 28px; font-family: Montserrat;\">Apar\u00eancia funcional<\/p>\r\n<\/p>\n<p>Desenvolvedores habituados com o paradigma funcional t\u00eam mais facilidade para entender o estilo\u00a0<em>pipes and filters<\/em>.<\/p>\n<p>Todas as linguagens de programa\u00e7\u00e3o com suporte ao paradigma funcional oferecem algum mecanismo\/operador para criar cadeias de fun\u00e7\u00f5es, combinadas. Al\u00e9m disso, h\u00e1 sempre fun\u00e7\u00f5es especialistas em executar as opera\u00e7\u00f5es de\u00a0<em>filter<\/em>,\u00a0<em>map\u00a0<\/em>e\u00a0<em>reduce.<\/em><\/p>\n<p><\/div>\n<p>As\u00a0<em>write ports<\/em>, por sua vez, conectam o <em>filter\u00a0<\/em>com algum tipo de\u00a0<em>pipe<\/em> que transportam os dados, sem fazer modifica\u00e7\u00f5es de qualquer natureza inclu\u00eddo ordena\u00e7\u00f5es.<\/p>\n<p>Uma<i>\u00a0pipe\u00a0<\/i>&#8220;transporta&#8221; dados de uma\u00a0<i>write port<\/i>\u00a0at\u00e9 uma nova <em>read port<\/em><em>\u00a0<\/em>que serve como entrada para outro <em>filter.<\/em><\/p>\n<p><img fetchpriority=\"high\" decoding=\"async\" class=\"wp-image-1662 aligncenter\" src=\"https:\/\/elemarjr.com\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/pipe_filter.png\" alt=\"\" width=\"518\" height=\"187\" srcset=\"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/pipe_filter.png 1842w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/pipe_filter-300x108.png 300w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/pipe_filter-1024x369.png 1024w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/pipe_filter-768x277.png 768w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/pipe_filter-1536x554.png 1536w\" sizes=\"(max-width: 518px) 100vw, 518px\" \/><\/p>\n<p><em>Pipes\u00a0<\/em>e\u00a0<em>filters\u00a0<\/em>s\u00e3o organizadas de maneira sistem\u00e1tica e organizada, em uma topologia apropriada, com dados sendo coletados de uma origem\u00a0(<i>Source<\/i>), submetidos a diversas etapas de processamento<em>, <\/em>at\u00e9 serem, finalmente, &#8220;descartados&#8221; em um <em>sink.<\/em><\/p>\n<p><img decoding=\"async\" class=\"wp-image-1665 aligncenter\" src=\"https:\/\/elemarjr.com\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/source_sink.png\" alt=\"\" width=\"663\" height=\"187\" srcset=\"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/source_sink.png 2532w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/source_sink-300x85.png 300w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/source_sink-1024x289.png 1024w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/source_sink-768x217.png 768w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/source_sink-1536x433.png 1536w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/source_sink-2048x578.png 2048w\" sizes=\"(max-width: 663px) 100vw, 663px\" \/><\/p>\n<p>Por poderem ter mais de uma porta de leitura e de grava\u00e7\u00e3o, <em>filters<\/em> podem ser envolvidos em &#8220;redes&#8221; complexas, geralmente sem\u00a0<em>loops<\/em>.<\/p>\n<div class=\"card-insight\" style=\"background-color: #f0f0f0; width: 100%; padding: 35px 30px 30px 35px; border-radius: 5px 5px 5px 5px; margin-top: 30px; margin-bottom: 35px; font-size: 16px; box-shadow: 0px 4px 0px 0px #dddddd;\">\r\n<p style=\"font-size: 24px; font-weight:bold; line-height: 28px; font-family: Montserrat;\">Pipes and Filters no Shell dos sistemas Unix-like<\/p>\r\n<\/p>\n<p>As aplica\u00e7\u00f5es de linha de comando no\u00a0<i>Shell\u00a0<\/i>dos sistemas Unix-like s\u00e3o projetadas para operar como\u00a0<em>filters\u00a0<\/em>conectando-se com outras naturalmente.<\/p>\n<p>Um exemplo fascinante do poder dessa abstra\u00e7\u00e3o \u00e9 narrado no artigo &#8220;<a href=\"http:\/\/www.leancrew.com\/all-this\/2011\/12\/more-shell-less-egg\/\">More Shell, Less Egg<\/a>&#8220;, que conta como <a href=\"http:\/\/en.wikipedia.org\/wiki\/Douglas_McIlroy\">Doug McIlroy<\/a>\u00a0recriou, combinando poucos aplicativos Linux, um programa de\u00a0<a href=\"http:\/\/en.wikipedia.org\/wiki\/Donald_Knuth\">Donald Knuth<\/a>\u00a0com centenas de linhas.<\/p>\n<pre>tr -cs A-Za-z '\\n' |\r\ntr A-Z a-z |\r\nsort |\r\nuniq -c |\r\nsort -rn |\r\nsed ${1}q\r\n<\/pre>\n<p><\/div>\n<p>Finalmente, <em>filters<\/em>\u00a0devem ser independentes um dos outros, sem que qualquer comunica\u00e7\u00e3o aconte\u00e7a, exceto atrav\u00e9s de\u00a0<em>pipes<\/em>.\u00a0<em>Filters <\/em>tampouco devem assumir que natureza de processamento ocorrer\u00e1\u00a0<em>upstream\u00a0<\/em>e\u00a0<em>downstream<\/em>.<\/p>\n<h2>Flexibilidade para recombinar e aperfei\u00e7oar<\/h2>\n<p>O estilo arquitetural\u00a0<em>Pipes and Filters<\/em>, quando corretamente aplicado, \u00e9 muito flex\u00edvel por permitir aprimoramentos atrav\u00e9s da reordena\u00e7\u00e3o das etapas de processamento. Quanto mais &#8220;especialistas&#8221; forem os\u00a0<em>filters <\/em>(consequentemente menores), maior a flexibilidade e as possbilidades de reuso.<\/p>\n<p>Al\u00e9m da ordena\u00e7\u00e3o dos\u00a0<em>filters<\/em> h\u00e1 tamb\u00e9m de se considerar a possibilidade adotar novos <em>Sources<\/em> ao longo do tempo. Em tempos de ind\u00fastria 4.0 e IoT \u00e9 importante considerar que n\u00e3o apenas sensores sejam utilizados como <em>inputs\u00a0<\/em>em sistemas, mas que eles sejam cada vez mais numerosos.<\/p>\n<h2>Pipelines de pipelines<\/h2>\n<p>Um exemplo cl\u00e1ssico da implementa\u00e7\u00e3o do estilo\u00a0<em>Pipes and Filters\u00a0<\/em>s\u00e3o compiladores. A an\u00e1lise arquitetural deles nos permite um importante\u00a0<em>insight\u00a0<\/em>para o design: estipular diferentes n\u00edveis de <em>design.<\/em><\/p>\n<p>Em sua representa\u00e7\u00e3o mais simples, um compilador pode ser explicado como um \u00fanico agente computacional, onde c\u00f3digo-fonte \u00e9 submetido para an\u00e1lise e convers\u00e3o para outro formato, geralmente execut\u00e1vel.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-1738 aligncenter\" src=\"https:\/\/elemarjr.com\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/compiler.png\" alt=\"\" width=\"284\" height=\"85\" srcset=\"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/compiler.png 900w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/compiler-300x90.png 300w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/compiler-768x230.png 768w\" sizes=\"(max-width: 284px) 100vw, 284px\" \/><\/p>\n<p>Em uma representa\u00e7\u00e3o mais detalhada, compiladores podem ser entendidos como uma\u00a0<em>pipeline<\/em> com tr\u00eas etapas:\u00a0<em>frontend, optimizer, backend.<\/em><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-1739 aligncenter\" src=\"https:\/\/elemarjr.com\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/compiler_0.png\" alt=\"\" width=\"2036\" height=\"424\" srcset=\"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/compiler_0.png 2036w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/compiler_0-300x62.png 300w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/compiler_0-1024x213.png 1024w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/compiler_0-768x160.png 768w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/compiler_0-1536x320.png 1536w\" sizes=\"(max-width: 2036px) 100vw, 2036px\" \/><\/p>\n<p>Mais pr\u00f3ximo da implementa\u00e7\u00e3o, modernamente, cada uma das tr\u00eas etapas pode se expandir consideravelmente.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-full wp-image-1741\" src=\"https:\/\/elemarjr.com\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/compiler_01.png\" alt=\"\" width=\"2036\" height=\"576\" srcset=\"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/compiler_01.png 2036w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/compiler_01-300x85.png 300w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/compiler_01-1024x290.png 1024w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/compiler_01-768x217.png 768w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/compiler_01-1536x435.png 1536w\" sizes=\"(max-width: 2036px) 100vw, 2036px\" \/><\/p>\n<p>Manter e analisar modelos distintos da arquitetura, com diferentes n\u00edveis de detalhe, pode facilitar a comunica\u00e7\u00e3o e, principalmente, modelar solu\u00e7\u00f5es.<\/p>\n<h2>Pipelines fixas, mas program\u00e1veis<\/h2>\n<p>Outro exemplo intrutivo de implanta\u00e7\u00e3o do padr\u00e3o <em>Pipes and Filters\u00a0<\/em>\u00e9 o modelo de funcionamento do DirectX 11. Trata-se de uma sequ\u00eancia fixa de <em>Filters<\/em>, alguns deles program\u00e1veis.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-1743 aligncenter\" src=\"https:\/\/elemarjr.com\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/directx11_pipeline.png\" alt=\"\" width=\"537\" height=\"709\" srcset=\"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/directx11_pipeline.png 1510w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/directx11_pipeline-227x300.png 227w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/directx11_pipeline-775x1024.png 775w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/directx11_pipeline-768x1014.png 768w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/directx11_pipeline-1163x1536.png 1163w\" sizes=\"(max-width: 537px) 100vw, 537px\" \/><\/p>\n<p>Na figura, os\u00a0<em>filters\u00a0<\/em>program\u00e1veis est\u00e3o indicados em verde. Todos os demais, s\u00e3o &#8220;fixos&#8221;.<\/p>\n<p>Outra curiosidade dessa arquitetura \u00e9 a ado\u00e7\u00e3o de um &#8220;quadro negro&#8221;, ou seja, um espa\u00e7o compartilhado de mem\u00f3ria utilizado por todos os <em>filters\u00a0<\/em>que reduz a transfer\u00eancia de &#8220;estado&#8221; entre os filtros, melhorando a performance. Essa \u00e9 uma decis\u00e3o relativamente segura, dada a configura\u00e7\u00e3o &#8220;fixa&#8221; da <em>pipeline<\/em>.<\/p>\n<h2>MapReduce<\/h2>\n<p>MapReduce \u00e9 um modelo de programa\u00e7\u00e3o projetado para tratar grandes volumes de dados em paralelo, dividindo o trabalho em um conjunto de tarefas independentes executadas no estilo <em>Pipers and Filters<\/em>.<\/p>\n<p>O nome MapReduce consiste de duas tarefas: <em>Map\u00a0<\/em>e\u00a0<em>Reduce, <\/em>onde <em>Reduce\u00a0<\/em>acontece na sequ\u00eancia da tarefa\u00a0<em>Map.\u00a0<\/em>As &#8220;tarefas\u00a0<em>Map&#8221;<\/em> convertem entradas a pares &#8220;chave\/valor&#8221; que compila resultados intermedi\u00e1rios que servem como entrada para as &#8220;tarefas\u00a0<em>Reduce<\/em>&#8220;. As &#8220;tarefas\u00a0<em>Reduce<\/em>&#8221; recebem dados de diveras &#8220;tarefas\u00a0<em>Map&#8221;\u00a0<\/em>e geram tuplas compat\u00edveis, ou seja, em &#8220;chave\/valor&#8221; que, eventualmente, s\u00e3o processadas por outras &#8220;tarefas\u00a0<em>Reduce<\/em>&#8220;<em>.<\/em><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-1745 aligncenter\" src=\"https:\/\/elemarjr.com\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/map_reduce.png\" alt=\"\" width=\"551\" height=\"203\" srcset=\"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/map_reduce.png 2404w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/map_reduce-300x111.png 300w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/map_reduce-1024x377.png 1024w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/map_reduce-768x283.png 768w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/map_reduce-1536x566.png 1536w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/map_reduce-2048x755.png 2048w\" sizes=\"(max-width: 551px) 100vw, 551px\" \/><\/p>\n<p>Abordagens\u00a0<em>MapReduce\u00a0<\/em>s\u00e3o excelentes para produzir e manter de dados consolidados, ao longo do tempo, em cen\u00e1rios distribu\u00eddos ou frente a grandes volumes de dados.<\/p>\n<h2>Rela\u00e7\u00e3o natural com mensageria<\/h2>\n<p>O estilo\u00a0<i>Pipes and Filters\u00a0<\/i>conecta unidades de processamento independentes (<em>filters<\/em>)\u00a0com diferentes demandas e capacidades computacionais. Os <em>filters\u00a0<\/em>limitam o <em>throughput<\/em>\u00a0dos dados no sistema e, por isso, \u00e9 comum que dados se acumulem nas\u00a0<em>pipes <\/em>anteriores aos\u00a0<em>filters <\/em>mais &#8220;lentos&#8221;. <strong>Por essa raz\u00e3o, \u00e9 essencial que essas\u00a0<i>pipes\u00a0<\/i>sejam projetadas para &#8220;gerenciar estado&#8221;.\u00a0A sa\u00edda comum \u00e9 utilizar alguma solu\u00e7\u00e3o de mensageria.<\/strong><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-1694 aligncenter\" src=\"https:\/\/elemarjr.com\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/mensageria.png\" alt=\"\" width=\"552\" height=\"187\" srcset=\"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/mensageria.png 1960w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/mensageria-300x102.png 300w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/mensageria-1024x347.png 1024w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/mensageria-768x260.png 768w, https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/mensageria-1536x520.png 1536w\" sizes=\"(max-width: 552px) 100vw, 552px\" \/><\/p>\n<h2>Facilidade para escalar na horizontal<\/h2>\n<p><strong>A performance de um sistema com arquitetura no estilo\u00a0<em>pipes and filters<\/em> \u00e9 determinada pelo\u00a0<em>filter\u00a0<\/em>mais lento.\u00a0<\/strong><\/p>\n<p style=\"padding-left: 40px;\"><em>A for\u00e7a de uma corrente \u00e9 sempre determinada pelo elo mais fraco. &#8211; Eliyahu Goldratt<\/em><\/p>\n<p><strong>Eventualmente, na medida em que a escala aumenta, um ou mais\u00a0<em>filters\u00a0<\/em>mais lentos podem se converter em gargalo.<\/strong> Nesses casos, \u00e9 comum &#8220;levantar&#8221;\u00a0inst\u00e2ncias paralelas de filtros lentos, permitindo que o sistema espalhe a carga e melhore a taxa de transfer\u00eancia.<\/p>\n<p>Os <em>filters<\/em>\u00a0podem ser executados em diferentes computadores, permitindo que sejam escalados de forma independente e aproveitem a elasticidade que muitos ambientes de nuvem fornecem.<\/p>\n<p>Um <em>filter<\/em> que \u00e9 computacionalmente intensivo pode ser executado em m\u00e1quinas melhores, enquanto outros filtros menos exigentes podem ser hospedados em m\u00e1quinas mais simples, permitindo melhor gest\u00e3o de custos.<\/p>\n<h2>Intimidade com &#8220;<em>Actors Model<\/em>&#8220;<\/h2>\nA natureza dos <em>filters\u00a0<\/em>, desacoplados e coesos, combinados em ambientes necessariamente resilientes, d\u00e1 ao estilo arquitetural\u00a0<em>Pipes and Filters\u00a0<\/em>ajuste natural ao\u00a0<em>Actors Model.<\/em>\n<hr \/>\n<p>O modelo de atores \u00e9 uma abstra\u00e7\u00e3o matem\u00e1tica para computa\u00e7\u00e3o distribu\u00edda, paralela e concorrente, onde &#8220;ator&#8221; \u00e9 a primitiva essencial. Atores atuam sempre a partir de mensagens recebidas, executam algum tipo de processamento, modificam seu estado privado e se comunicam com outros atores, novamente, a partir de mensagens.<\/p>\nO modelo de atores \u00e9 a abstra\u00e7\u00e3o fundamental para tecnologias como ERLANG, Elixir, Akka, Akka.net, Orleans e mais.\n<hr \/>\n<p>A implementa\u00e7\u00e3o do estilo\u00a0<em>Pipes and Filters\u00a0<\/em>ocorre atrav\u00e9s da constru\u00e7\u00e3o de um ator para cada\u00a0<em>filter.<\/em><\/p>\n<h2>Intimidade com &#8220;<i>FaaS<\/i>&#8220;<\/h2>\n<p>Recentemente, tem ganho destaque um modelo computacional orientado a eventos, com unidades m\u00ednimas de processamento (fun\u00e7\u00f5es) executadas em\u00a0cont\u00eaineres\u00a0<em>stateless,\u00a0<\/em>que s\u00e3o executadas em ambientes gerenciados. Essas &#8220;fun\u00e7\u00f5es&#8221; s\u00e3o acionadas sempre que h\u00e1 a ocorr\u00eancia de um &#8220;evento&#8221;, com escalabilidade autom\u00e1tica.<\/p>\n<p>FaaS \u00e9 o modelo computacional que fundamenta tecnologias como AWS Lambdas e Azure Functions.<\/p>\nA implementa\u00e7\u00e3o do estilo arquitetural <em>Pipes and Filters\u00a0<\/em>tem ajuste natural com <em>FaaS<\/em>. A solu\u00e7\u00e3o \u00e9 adaptada com\u00a0<em>filters\u00a0<\/em>sendo implementados como fun\u00e7\u00f5es e as\u00a0<em>pipes\u00a0<\/em>como mecanismo para coleta e gest\u00e3o de eventos.\n<hr \/>\n<h2>Intimidade com plataformas de <em>stream\u00a0<\/em><\/h2>\n<p>Nos \u00faltimos anos, plataformas para tratamento distribu\u00eddo de <em>streams,\u00a0<\/em>como Apache Kafka e NiFi t\u00eam permitido a constru\u00e7\u00e3o de sistemas robustos capazes de tratar fluxos gigantes de informa\u00e7\u00f5es.<\/p>\n<strong>Apache NiFi, uma ferramenta visual (com API REST), \u00a0permite a configura\u00e7\u00e3o e conex\u00e3o entre processadores (<em>filters<\/em>) de maneira din\u00e2mica.<\/strong> Al\u00e9m disso, permite monitoramento e controle dos fluxos de execu\u00e7\u00e3o, autorizando ajustes de escala e pausas controladas.\n<hr \/>\n<strong>Apache Kafka, \u00a0uma implementa\u00e7\u00e3o distribu\u00edda do padr\u00e3o <em>publish-subscribe,<\/em>\u00a0permite aos desenvolvedores conectar programas (<em>filters<\/em>)\u00a0entre si, em diferentes linguagens e em um grande n\u00famero de m\u00e1quinas.<\/strong> Trata-se de uma alternativa poderosa para implementa\u00e7\u00e3o de\u00a0<em>pipes<\/em>.\n<hr \/>\n<p>Solu\u00e7\u00f5es como Kafka e NiFi autorizam escalar de maneira segura solu\u00e7\u00f5es projetadas seguindo o estilo\u00a0<em>Pipes and Filters<\/em>.<\/p>\n<h2>Conway, outra vez!<\/h2>\n<p>O desenvolvimento de solu\u00e7\u00f5es utilizando o estilo arquitetural\u00a0<em>Pipes and Filters\u00a0<\/em>conduz ao estabelecimento de pelo menos tr\u00eas tipos de times diferentes:<\/p>\n<ul>\n<li>Desenvolvedores de\u00a0<em>filters\u00a0<\/em>&#8211; preocupados com determinada demanda de neg\u00f3cio pontual e implementa\u00e7\u00e3o direta em c\u00f3digo.<\/li>\n<li>Supervisores de\u00a0<em>pipes\u00a0<\/em>&#8211; que desenvolvem e especializam plataformas ou solu\u00e7\u00f5es para gest\u00e3o de\u00a0<em>streams\u00a0<\/em>de dados.<\/li>\n<li>Gestores de\u00a0<em>Pipelines &#8211;\u00a0<\/em>que combinam diversos\u00a0<em>filters\u00a0<\/em>e tecnologias de\u00a0<em>pipes\u00a0<\/em>para o desenvolvimento de uma solu\u00e7\u00e3o completa para o neg\u00f3cio.<\/li>\n<\/ul>\n<h2>Eventualmente reativo!<\/h2>\n<strong>O estilo arquitetural\u00a0<em>Pipes and Filters\u00a0<\/em>habilita o desenvolvimento de sistemas reativos, que \u00e9 algo desej\u00e1vel. Tais sistemas, s\u00e3o responsivos, resilientes, el\u00e1sticos e orientados a mensagens.<\/strong>\n<hr \/>\n<p>A <strong>responsividade<\/strong> \u00e9 obtida pelo desacoplamento l\u00f3gico e operacional das diversas <em>filters<\/em>. Eventualmente, opera\u00e7\u00f5es mais pesadas s\u00e3o postergadas para processamento posterior enquanto <em>f<\/em><i>eedback\u00a0<\/i>r\u00e1pido \u00e9 dado aos usu\u00e1rios ou agentes externos.<\/p>\n<p>A <strong>resili\u00eancia<\/strong>, por sua vez, \u00e9 garantida pela estabilidade dos\u00a0<em>pipes\u00a0<\/em>que &#8220;seguram&#8221; os dados caso exista alguma instabilidade de processamento nos <em>filters<\/em>.<\/p>\n<p>A <strong>elasticidade<\/strong>, em sistemas baseados em\u00a0<em>Pipes and Filters\u00a0<\/em>\u00e9 poss\u00edvel desde que cada\u00a0<em>filter\u00a0<\/em>opere realmente de forma desacoplada com o fluxo quanto com outros\u00a0<em>filters.\u00a0<\/em>Em princ\u00edpio, quando a demanda sobe,\u00a0<em>filters\u00a0<\/em>mais pesados podem ter novas inst\u00e2ncias criadas e descartadas conforme a escala oscila.<\/p>\n<p>Por fim, o &#8220;fluxo dos dados&#8221; indica clara <strong>orienta\u00e7\u00e3o a mensagens<\/strong>.<\/p>\n<h2>Indica\u00e7\u00f5es e contraindica\u00e7\u00f5es<\/h2>\n<p>O estilo <em>Pipes and Filters\u00a0<\/em>\u00e9 uma abstra\u00e7\u00e3o poderosa que autoriza o desenvolvimento de sistemas robustos e potencialmente reativos. Entretanto, como \u00e9 sempre o caso, n\u00e3o \u00e9 uma solu\u00e7\u00e3o &#8220;bala de prata&#8221;.<\/p>\n<p>A aplica\u00e7\u00e3o de\u00a0<em>Pipes and Filters<\/em> deve ser considerada sempre (e apenas quando) que o processamento de uma aplica\u00e7\u00e3o puder ser dividido em conjunto de etapas independentes, n\u00e3o dependentes de uma \u00fanica unidade transacional. Eventualmente, isso n\u00e3o acontece para o software como um todo, mas, ser\u00e1 o caso para partes. <strong>O ganho ser\u00e1 mais percebido quando etapas diferentes tiverem demandas de escalabilidade diferentes.<\/strong><\/p>\n<p>Outro aspecto interessante do estilo, quando ele for aplic\u00e1vel, \u00e9 a separa\u00e7\u00e3o dos processos de desenvolvimento dos <em>filters\u00a0<\/em>e o projeto das\u00a0<em>pipelines\u00a0<\/em>indica maior flexibilidade para permitir reordena\u00e7\u00e3o das etapas de processamento executadas, al\u00e9m, obviamente, de sofistica\u00e7\u00e3o dos processos, adicionando ou removendo etapas.<\/p>\n<h2>Tratar erros \u00e9 importante, mas dif\u00edcil<\/h2>\n<p>Tratamento de erros \u00e9, provavelmente, o calcanhar de aquiles do estilo arquitetural\u00a0<em>Pipes and Filters<\/em>.<\/p>\n<p>\u00c9 muito importante que a arquitetura defina uma estrat\u00e9gia comum para reportar erros em produ\u00e7\u00e3o. Entretanto, a possibilidade de implantar mecanismos de recupera\u00e7\u00e3o pode ser dif\u00edcil, ou at\u00e9 mesmo imposs\u00edvel, dependendo da natureza do problema.<\/p>\n<h2>Em grandes jornadas, dividir para conquistar<\/h2>\nBoa parte das implementa\u00e7\u00f5es &#8220;chamadas&#8221; microsservi\u00e7os s\u00e3o, na verdade, realiza\u00e7\u00f5es de <em>Pipes and Filters<\/em>. O problema disso \u00e9 que, muitas vezes, abstra\u00e7\u00f5es importantes do estilo acabam ignoradas, causando dificuldades desnecess\u00e1rias.\n<hr \/>\nPensar sistemas em termos de <em>Pipes and Filters\u00a0<\/em>\u00e9 um come\u00e7o importante para quem deseja criar arquiteturas desacopladas e com bom\u00a0<em>evolvability<\/em>. Afinal, o estilo conta com familiaridade com mecanismos poderosos, admirados por muitos desenvolvedores. Al\u00e9m disso, acomoda muitas das &#8220;tend\u00eancias tecnol\u00f3gicas&#8221;.\n<h2>\/\/ TODO<\/h2>\n<p>Antes de avan\u00e7ar para o pr\u00f3ximo cap\u00edtulo, recomendo as seguintes reflex\u00f5es:<\/p>\n<ul>\n<li>Voc\u00ea conseguiria decompor seu sistema em um conjunto de &#8220;atividades&#8221; desacopladas, implement\u00e1veis como\u00a0<em>Pipes and Filters<\/em>?<\/li>\n<li>Voc\u00ea j\u00e1 utiliza Kafka, NiFi ou FaaS em seus sistemas? H\u00e1 semelhan\u00e7as, na sua solu\u00e7\u00e3o, com o padr\u00e3o\u00a0<em>Pipes and Filters<\/em>?<\/li>\n<\/ul>\n","protected":false},"featured_media":1715,"parent":0,"comment_status":"open","ping_status":"closed","template":"","url":[],"sessoes":[59],"apendices":[],"capitulos":[30],"class_list":["post-4939","volume-1","type-volume-1","status-publish","has-post-thumbnail","hentry","sessoes-secao-3","capitulos-capitulo-3-2"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.6 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Projetando software com &quot;Pipes &amp; Filters&quot; \/ Cap\u00edtulo 6 v1.02 - Manual do Arquiteto de Software<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/elemarjr.com\/arquiteturadesoftware\/projetando-software-com-pipes-filters\/\" \/>\n<meta property=\"og:locale\" content=\"pt_BR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Projetando software com &quot;Pipes &amp; Filters&quot; \/ Cap\u00edtulo 6 v1.02 - Manual do Arquiteto de Software\" \/>\n<meta property=\"og:description\" content=\"O estilo arquitetural\u00a0Pipes and Filters\u00a0emerge, naturalmente, quando arquitetos e desenvolvedores decidem decompor opera\u00e7\u00f5es complexas em unidades de processamento independentes, mais f\u00e1ceis de desenvolver e manter.\u00a0Entretanto, por desconhecimento, com frequ\u00eancia \u00e9 implementado de maneira descuidada e, em virtude disso, deficiente. Sistemas constru\u00eddos utilizando o estilo Pipes and Filters\u00a0processam\u00a0streams\u00a0de dados em etapas. Cada etapa \u00e9 encapsulada em [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/elemarjr.com\/arquiteturadesoftware\/projetando-software-com-pipes-filters\/\" \/>\n<meta property=\"og:site_name\" content=\"Manual do Arquiteto de Software\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/facebook.com\/eximiaco\" \/>\n<meta property=\"article:modified_time\" content=\"2024-01-11T21:08:25+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/chuttersnap-tStI4wL1cTQ-unsplash.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1024\" \/>\n\t<meta property=\"og:image:height\" content=\"684\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:site\" content=\"@eximiaco\" \/>\n<meta name=\"twitter:label1\" content=\"Est. tempo de leitura\" \/>\n\t<meta name=\"twitter:data1\" content=\"12 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/volume-1\/projetando-software-com-pipes-filters-capitulo-6-v1-02\/\",\"url\":\"https:\/\/elemarjr.com\/arquiteturadesoftware\/projetando-software-com-pipes-filters\/\",\"name\":\"Projetando software com \\\"Pipes & Filters\\\" \/ Cap\u00edtulo 6 v1.02 - Manual do Arquiteto de Software\",\"isPartOf\":{\"@id\":\"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/elemarjr.com\/arquiteturadesoftware\/projetando-software-com-pipes-filters\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/elemarjr.com\/arquiteturadesoftware\/projetando-software-com-pipes-filters\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/chuttersnap-tStI4wL1cTQ-unsplash.jpg\",\"datePublished\":\"2022-06-23T19:31:57+00:00\",\"dateModified\":\"2024-01-11T21:08:25+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/elemarjr.com\/arquiteturadesoftware\/projetando-software-com-pipes-filters\/#breadcrumb\"},\"inLanguage\":\"pt-BR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/elemarjr.com\/arquiteturadesoftware\/projetando-software-com-pipes-filters\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/elemarjr.com\/arquiteturadesoftware\/projetando-software-com-pipes-filters\/#primaryimage\",\"url\":\"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/chuttersnap-tStI4wL1cTQ-unsplash.jpg\",\"contentUrl\":\"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/chuttersnap-tStI4wL1cTQ-unsplash.jpg\",\"width\":1024,\"height\":684},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/elemarjr.com\/arquiteturadesoftware\/projetando-software-com-pipes-filters\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Volume 1\",\"item\":\"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/volume-1\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Projetando software com &#8220;Pipes &#038; Filters&#8221; \/ Cap\u00edtulo 6 v1.02\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/#website\",\"url\":\"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/\",\"name\":\"Manual do Arquiteto de Software\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"pt-BR\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/#organization\",\"name\":\"EximiaCo\",\"url\":\"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2022\/04\/simbolo-eximiaco.jpg\",\"contentUrl\":\"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2022\/04\/simbolo-eximiaco.jpg\",\"width\":150,\"height\":150,\"caption\":\"EximiaCo\"},\"image\":{\"@id\":\"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/facebook.com\/eximiaco\",\"https:\/\/x.com\/eximiaco\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Projetando software com \"Pipes & Filters\" \/ Cap\u00edtulo 6 v1.02 - Manual do Arquiteto de Software","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/elemarjr.com\/arquiteturadesoftware\/projetando-software-com-pipes-filters\/","og_locale":"pt_BR","og_type":"article","og_title":"Projetando software com \"Pipes & Filters\" \/ Cap\u00edtulo 6 v1.02 - Manual do Arquiteto de Software","og_description":"O estilo arquitetural\u00a0Pipes and Filters\u00a0emerge, naturalmente, quando arquitetos e desenvolvedores decidem decompor opera\u00e7\u00f5es complexas em unidades de processamento independentes, mais f\u00e1ceis de desenvolver e manter.\u00a0Entretanto, por desconhecimento, com frequ\u00eancia \u00e9 implementado de maneira descuidada e, em virtude disso, deficiente. Sistemas constru\u00eddos utilizando o estilo Pipes and Filters\u00a0processam\u00a0streams\u00a0de dados em etapas. Cada etapa \u00e9 encapsulada em [&hellip;]","og_url":"https:\/\/elemarjr.com\/arquiteturadesoftware\/projetando-software-com-pipes-filters\/","og_site_name":"Manual do Arquiteto de Software","article_publisher":"https:\/\/facebook.com\/eximiaco","article_modified_time":"2024-01-11T21:08:25+00:00","og_image":[{"width":1024,"height":684,"url":"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/chuttersnap-tStI4wL1cTQ-unsplash.jpg","type":"image\/jpeg"}],"twitter_card":"summary_large_image","twitter_site":"@eximiaco","twitter_misc":{"Est. tempo de leitura":"12 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/volume-1\/projetando-software-com-pipes-filters-capitulo-6-v1-02\/","url":"https:\/\/elemarjr.com\/arquiteturadesoftware\/projetando-software-com-pipes-filters\/","name":"Projetando software com \"Pipes & Filters\" \/ Cap\u00edtulo 6 v1.02 - Manual do Arquiteto de Software","isPartOf":{"@id":"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/#website"},"primaryImageOfPage":{"@id":"https:\/\/elemarjr.com\/arquiteturadesoftware\/projetando-software-com-pipes-filters\/#primaryimage"},"image":{"@id":"https:\/\/elemarjr.com\/arquiteturadesoftware\/projetando-software-com-pipes-filters\/#primaryimage"},"thumbnailUrl":"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/chuttersnap-tStI4wL1cTQ-unsplash.jpg","datePublished":"2022-06-23T19:31:57+00:00","dateModified":"2024-01-11T21:08:25+00:00","breadcrumb":{"@id":"https:\/\/elemarjr.com\/arquiteturadesoftware\/projetando-software-com-pipes-filters\/#breadcrumb"},"inLanguage":"pt-BR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/elemarjr.com\/arquiteturadesoftware\/projetando-software-com-pipes-filters\/"]}]},{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/elemarjr.com\/arquiteturadesoftware\/projetando-software-com-pipes-filters\/#primaryimage","url":"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/chuttersnap-tStI4wL1cTQ-unsplash.jpg","contentUrl":"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2021\/05\/chuttersnap-tStI4wL1cTQ-unsplash.jpg","width":1024,"height":684},{"@type":"BreadcrumbList","@id":"https:\/\/elemarjr.com\/arquiteturadesoftware\/projetando-software-com-pipes-filters\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/"},{"@type":"ListItem","position":2,"name":"Volume 1","item":"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/volume-1\/"},{"@type":"ListItem","position":3,"name":"Projetando software com &#8220;Pipes &#038; Filters&#8221; \/ Cap\u00edtulo 6 v1.02"}]},{"@type":"WebSite","@id":"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/#website","url":"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/","name":"Manual do Arquiteto de Software","description":"","publisher":{"@id":"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"pt-BR"},{"@type":"Organization","@id":"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/#organization","name":"EximiaCo","url":"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/","logo":{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/#\/schema\/logo\/image\/","url":"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2022\/04\/simbolo-eximiaco.jpg","contentUrl":"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-content\/uploads\/2022\/04\/simbolo-eximiaco.jpg","width":150,"height":150,"caption":"EximiaCo"},"image":{"@id":"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/facebook.com\/eximiaco","https:\/\/x.com\/eximiaco"]}]}},"_links":{"self":[{"href":"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-json\/wp\/v2\/volume-1\/4939","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-json\/wp\/v2\/volume-1"}],"about":[{"href":"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-json\/wp\/v2\/types\/volume-1"}],"replies":[{"embeddable":true,"href":"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-json\/wp\/v2\/comments?post=4939"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-json\/wp\/v2\/media\/1715"}],"wp:attachment":[{"href":"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-json\/wp\/v2\/media?parent=4939"}],"wp:term":[{"taxonomy":"url","embeddable":true,"href":"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-json\/wp\/v2\/url?post=4939"},{"taxonomy":"sessoes","embeddable":true,"href":"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-json\/wp\/v2\/sessoes?post=4939"},{"taxonomy":"apendices","embeddable":true,"href":"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-json\/wp\/v2\/apendices?post=4939"},{"taxonomy":"capitulos","embeddable":true,"href":"https:\/\/elemarjr.com\/livros\/arquiteturadesoftware\/wp-json\/wp\/v2\/capitulos?post=4939"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}