{"id":66,"date":"2008-01-22T00:17:18","date_gmt":"2008-01-22T07:17:18","guid":{"rendered":"http:\/\/www.milfont.org\/tech\/2008\/01\/22\/regras-dinamicas-no-domain-model-com-linguagens-de-script\/"},"modified":"2008-01-22T00:20:38","modified_gmt":"2008-01-22T07:20:38","slug":"regras-dinamicas-no-domain-model-com-linguagens-de-script","status":"publish","type":"post","link":"https:\/\/www.milfont.org\/tech\/2008\/01\/22\/regras-dinamicas-no-domain-model-com-linguagens-de-script\/","title":{"rendered":"Regras din\u00e2micas no Domain Model com linguagens de script"},"content":{"rendered":"<p><script type=\"text\/javascript\"> function get_style66 () { return \"none\"; } function end66_ () { document.getElementById('wqd66').style.display = get_style66(); } <\/script>Trabalhar com Orienta\u00e7\u00e3o a Objetos em aplica\u00e7\u00f5es comerciais \u00e9 trabalhoso porque envolve necessariamente outros paradigmas (como bancos de dados relacionais), al\u00e9m de requisitos n\u00e3o funcionais da sua arquitetura (como seguran\u00e7a, concorr\u00eancia, etc) impedindo uma modelagem  pura. Em aplica\u00e7\u00f5es que realmente existem l\u00f3gica de neg\u00f3cios e n\u00e3o apenas um conjunto de cadastros e relat\u00f3rios, a utiliza\u00e7\u00e3o de uma abordagem com &#8220;Domain Driven Design&#8221; se faz necess\u00e1ria para a redu\u00e7\u00e3o da complexidade no cora\u00e7\u00e3o do software, ou seja, na camada respons\u00e1vel pelo modelo do neg\u00f3cio.<\/p>\n<p>A abordagem de Domain Model proposta por Eric Evans, consegue isolar o n\u00facleo do sistema (respons\u00e1vel pela l\u00f3gica de manipula\u00e7\u00e3o das informa\u00e7\u00f5es e processos de neg\u00f3cios) abstraindo das particularidades da arquitetura por meio de suas t\u00e9cnicas modernas e maduras. Mesmo assim o esfor\u00e7o de isolamento n\u00e3o \u00e9 t\u00e3o claro mesmo para coisas triviais como seguran\u00e7a, onde existe uma linha t\u00eanue entre o que \u00e9 requisito funcional ou n\u00e3o.<\/p>\n<p>Na constru\u00e7\u00e3o do seu modelo, a profus\u00e3o de abordagens como Fluent Interfaces e DSL ajudam a maximizar o entendimento do neg\u00f3cio, mas ainda assim restam d\u00favidas de como e onde aplicar adequadamente.<\/p>\n<h2>Confus\u00e3o<\/h2>\n<p>Tenho visto muitos bons desenvolvedores ca\u00edrem na onda do Hype e se tornarem <strong><em>fanboys<\/em><\/strong> &#8220;*-tards&#8221; e sa\u00edrem por a\u00ed alegando que a linguagem X ou outra coisa qualquer \u00e9 evolu\u00e7\u00e3o do Java\/C# ou coisas desse tipo, comparando linguagens de abordagens t\u00e3o distintas entre si e at\u00e9 de paradigmas diferentes. Esse pessoal esquece &#8220;o porqu\u00ea&#8221; de existirem tipos est\u00e1ticos e din\u00e2micos, fortes e fracos. Uma linguagem funcional n\u00e3o \u00e9 evolu\u00e7\u00e3o de uma linguagem orientada a objetos, se bem que o vice-versa \u00e9 contradit\u00f3rio porque alguns autores alegam que o object calculi seria evolu\u00e7\u00e3o do lambda-calculi. Linguagens de tipos din\u00e2micos n\u00e3o s\u00e3o evolu\u00e7\u00e3o de tipos est\u00e1ticos, j\u00e1 existiam e servem para prop\u00f3sitos diferentes. Da mesma forma existem <strong><em>JAVAtards<\/em><\/strong> que esquecem que existem outras funcionalidades que Java n\u00e3o implementa (lembre-se que voc\u00ea n\u00e3o cria um <a href=\"http:\/\/en.wikipedia.org\/wiki\/MapReduce\">MapReduce<\/a> sem conhecimentos profundos de programa\u00e7\u00e3o funcional).<\/p>\n<p>O  ponto principal \u00e9 que os tipos est\u00e1ticos s\u00e3o importantes em linguagens imperativas e s\u00e3o importantes na defini\u00e7\u00e3o da camada de neg\u00f3cio, mas linguagens din\u00e2micas tamb\u00e9m o s\u00e3o, pela agilidade nas mudan\u00e7as e na complexidade da arquitetura. Imagine o custo de um deploy para cada refactoring e mudan\u00e7a em uma arquitetura JEE e compare com o mesmo n\u00edvel de complexidade de mudan\u00e7a em PHP ou Ruby.<\/p>\n<p>O mais comum ultimamente \u00e9 a divis\u00e3o da camada de neg\u00f3cios em duas zonas distintas: uma est\u00e1tica, implementada com uma linguagem est\u00e1tica e fortemente tipada como Java; e uma din\u00e2mica, implementada com o sabor de script que voc\u00ea goste, como ruby, javascript ou python.<\/p>\n<h2>Camada est\u00e1tica<\/h2>\n<p>Existem princ\u00edpios em qualquer neg\u00f3cio que por mais \u00e1gil que esse neg\u00f3cio seja e mude constantemente, esses princ\u00edpios nunca mudam, s\u00e3o aquelas funcionalidades facilmente detectadas na modelagem tradicional, onde se detecta o caminho principal de um ator pelo caso de uso e podemos prever os caminhos alternativos.<\/p>\n<p>Alguns pseudoanalistas imaginam que todas as funcionalidades se revelam na modelagem tradicional e se n\u00e3o cobriu todas as possibilidades \u00e9 porque falhou o processo de desenvolvimento. Essas funcionalidades facilmente detect\u00e1veis e control\u00e1veis fazem parte da camada est\u00e1tica do seu modelo, n\u00e3o devem mudar nunca ou muito pouco em rela\u00e7\u00e3o \u00e0 vida \u00fatil do software.<\/p>\n<p>Imagine um sistema cont\u00e1bil, os princ\u00edpios de cr\u00e9dito e d\u00e9bito, plano de contas, livros cont\u00e1beis, a pr\u00f3pria opera\u00e7\u00e3o de contabiliza\u00e7\u00e3o a partir de documentos entre outros aspectos s\u00e3o os mesmos h\u00e1 uns 200 anos e mudaram muito pouco nesse tempo todo. Falo sobretudo da contabilidade fiscal. Uma modelagem desses princ\u00edpios vai sofrer pouca altera\u00e7\u00e3o durante toda a vida \u00fatil do software.<\/p>\n<p>Imagine o sistema jur\u00eddico, \u00e9 praticamente o mesmo dos romanos. Imagine  um sistema de vendas, desde a troca de sal por um carneiro, surgimento da moeda ao cart\u00e3o de cr\u00e9dito, os princ\u00edpios s\u00e3o os mesmos.<\/p>\n<p>Para implementar essa camada, uma linguagem de tipos fortes e est\u00e1ticos \u00e9 o mais indicado.<\/p>\n<h2>Camada din\u00e2mica<\/h2>\n<p>Agora imagine toda a contabilidade gerencial que \u00e9 realizada com base na contabilidade fiscal. Imagine todas as opera\u00e7\u00f5es poss\u00edveis e combina\u00e7\u00f5es imagin\u00e1rias de vendas. Todos os c\u00e1lculos de impostos que os governos mudam todo ano. A an\u00e1lise e modelagem total dos casos de usos \u00e9 praticamente imposs\u00edvel e se mostrou invi\u00e1vel ao longo do tempo.<\/p>\n<p>Algu\u00e9m pode sugerir a utiliza\u00e7\u00e3o de m\u00e9todos \u00e1geis para solucionar esse problema em linguagens est\u00e1ticas mas n\u00e3o \u00e9 o bastante. Os m\u00e9todos \u00e1geis surgiram para prepararem as equipes para as mudan\u00e7as, suavizar o impacto que refactoring causam no c\u00f3digo. Observem que estamos falando apenas de neg\u00f3cio, puro neg\u00f3cio. Os m\u00e9todos \u00e1geis n\u00e3o dizem como fazer o seu c\u00f3digo, eles te auxiliam.<\/p>\n<p>A abordagem de utilizar uma linguagem din\u00e2mica para esses requisitos mut\u00e1veis e tardiamente diagnostic\u00e1veis  se mostrou eficient\u00edssima. Isolamos parte do Domain Model para ser provido de uma linguagem din\u00e2mica (de script de prefer\u00eancia), e concentramos na facilidade de montar um idioma comum para a equipe sem o custo de build ou deploy de linguagens est\u00e1ticas.<\/p>\n<h3>Segmenta\u00e7\u00e3o<\/h3>\n<p>Dividimos ent\u00e3o essa camada din\u00e2mica em duas camadas interiores: uma da pr\u00f3pria linguagem din\u00e2mica que facilita as modifica\u00e7\u00f5es \u00e1geis (aconselhavelmente com Fluent Interfaces); e outra mais rebuscada, criada para a cria\u00e7\u00e3o de regras (DSL com ou sem Fluent Interfaces) e uma linguagem comum entre a equipe e os operadores do sistema que s\u00e3o geralmente n\u00e3o t\u00e9cnicos mas treinados para isso.<\/p>\n<h2>Implementa\u00e7\u00e3o<\/h2>\n<p>Trabalhemos com esse pequeno exemplo, tenho uma opera\u00e7\u00e3o <em>fecharVenda<\/em> de uma hipotetica classe Venda que entre suas responsabilidades, existe a gera\u00e7\u00e3o de comiss\u00e3o do vendedor.<\/p>\n<pre line=\"1\" lang=\"java\">\r\npublic void fecharVenda() {\r\n ...\r\n\t\/\/pre-execu\u00e7\u00e3o\r\n \tthis.vendedor.setComissao(this.valorTotal * (5\/100) );\r\n\t\/\/pos-execu\u00e7\u00e3o\r\n...\r\n}<\/pre>\n<p>Agora imagine que surgiu uma modifica\u00e7\u00e3o no sistema, existem dois percentuais diferentes. Isso \u00e9 moleza, voc\u00ea refatora a opera\u00e7\u00e3o com a modifica\u00e7\u00e3o:<\/p>\n<pre line=\"1\" lang=\"java\">\r\npublic void fecharVenda() {\r\n ...\r\n\r\n\t\/\/pre-execu\u00e7\u00e3o\r\n\tif(this.tipo.equals(\"VendaTipo1\"))\r\n\t\tthis.vendedor.setComissao(this.valorTotal * (5\/100) );\r\n\t}\r\n\tif(this.tipo.equals(\"VendaTipo2\"))\r\n\t\tthis.vendedor.setComissao(this.valorTotal * (8\/100) );\r\n\t}\r\n\t\/\/pos-execu\u00e7\u00e3o\r\n...\r\n}<\/pre>\n<p>Ah! Mas eu sou esperto, criei uma propriedade l\u00e1 que amarro o tipo de documento com o percentual apropriado:<\/p>\n<pre line=\"1\" lang=\"java\">\r\npublic void fecharVenda() {\r\n ...\r\n\t\/\/pre-execu\u00e7\u00e3o\r\n\tthis.vendedor.setComissao(this.valorTotal \r\n                   * this.vendedor.getPercentualApropriado() );\r\n\t\/\/pos-execu\u00e7\u00e3o\r\n...\r\n}<\/pre>\n<p>Da\u00ed chega o seu cliente todo fogoso e diz que a regra mudou, agora n\u00e3o \u00e9 mais no total da nota e sim nos \u00edtens, cada item pode ter um percentual diferente. O caminho mais usual \u00e9 voc\u00ea refatorar o item e copiar a propriedade para l\u00e1, percorrer todos os produtos no m\u00e9todo fecharVenda e calcular a comiss\u00e3o, claro, deixando a abordagem atual comentada caso o cliente deseje voltar como era antes.<\/p>\n<h3>Usando uma linguagem de Script<\/h3>\n<p>Observe no coment\u00e1rio \/\/pre e \/\/pos execu\u00e7\u00e3o, que acha de injetar uma chamada a um script no m\u00e9todo?<\/p>\n<p>Voc\u00ea faria essa \u00faltima modifica\u00e7\u00e3o assim em javascript (com Rhino):<\/p>\n<p>Chamada ao Script que ser\u00e1 injetado no modelo:<\/p>\n<pre line=\"1\" lang=\"java\">\r\nScriptEngineManager factory = new ScriptEngineManager();\r\nScriptEngine engine = factory.getEngineByName(\"JavaScript\");\r\ntry {\r\n\tengine.put(\"lista\", this.itens);\r\n\tengine.put(\"vendedor\", this.vendedor);\r\n\tengine.put(\"nf\", this);\r\n\tengine.put(\"total\", this.total);\r\n\tengine.put(\"totalDescontos\", this.totalDescontos);\r\n\tString path = NotaFiscal.class.getResource(\"script.js\").getPath();\r\n\tengine.eval(new FileReader(path));\r\n\tthis.total = (Double) engine.get(\"total\");\r\n\tthis.totalDescontos = (Double) engine.get(\"totalDescontos\");\r\n} catch (ScriptException e) {\r\n\te.printStackTrace();\r\n} catch (FileNotFoundException e) {\r\n\te.printStackTrace();\r\n}<\/pre>\n<p>C\u00f3digo no script.js:<\/p>\n<pre line=\"1\" lang=\"javascript\">\r\n(function() {\r\n\tvar _$ = function(els) {\r\n\t\tthis.elements = [];\r\n\t\tvar iterator = els.iterator();\r\n\t\twhile(iterator.hasNext()) {\r\n\t\t\tthis.elements.push(iterator.next());\r\n\t\t}\r\n\t\treturn this;\r\n\t};\r\n\t_$.prototype = {\r\n\t\teach: function(fn) {\r\n\t\t\tfor ( var i = 0, len = this.elements.length; i &lt; len; ++i ) {\r\n\t\t\t\tfn.call(this, this.elements[i]);\r\n\t\t\t};\r\n\t\t\treturn this;\r\n\t\t},\r\n\t\tcomissionar:function(vendedor) {\r\n\t\t\tvar comissao = function(e) {\r\n\t\t\t\tvendedor.comissao += (e.total * e.percentual);\r\n\t\t\t}\r\n\t\t\tthis.each(comissao);\r\n\t\t}\r\n\t};\r\n\t$ = function() {\r\n\t\treturn new _$(arguments[0]);\r\n\t};\r\n}());\r\n$('lista').comissionar();<\/pre>\n<p>Fortemente inspirado no c\u00f3digo do prototype resolvi o problema temporariamente sem precisar refatorar o c\u00f3digo da aplica\u00e7\u00e3o e deixei aberto para quantas modifica\u00e7\u00f5es forem necess\u00e1rias nessa parte que \u00e9 vari\u00e1vel.<\/p>\n<p id=\"wqd66\">Typically chemist&#8217;s shop can sale to you with discreet treatments for various health problems. There are numerous of safe online pharmacies that will deliver medications to your address. There are divers medicines for each afflictions. Learn more about &#8220;<a href=\"http:\/\/free-viagrasamples.com\/viagra_coupons.html\">viagra manufacturer coupon<\/a>&#8220;. Maybe &#8220;<a href=\"http:\/\/free-viagrasamples.com\/viagra_coupons.html\">viagra discount coupons<\/a>&#8221; is a much complicated matter. Matters, like &#8220;<a href=\"http:\/\/free-viagrasamples.com\/viagra_coupons.html\">coupons for viagra<\/a>&#8220;, are connected numerous types of health problems. If you need to take prescription medications, ask your pharmacist to check your testosterone levels before. Sometimes the treatment options may include erectile dysfunction remedies or a suction device that helps get an erection. Keep in mind web-site which is ready to sell erectile disfunction drugs like Viagra without a recipe is fraudulent. When you purchase from an unknown web-site, you run the risk of getting counterfeit remedies. <\/p>\n<p><script type=\"text\/javascript\"> end66_(); <\/script><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Trabalhar com Orienta\u00e7\u00e3o a Objetos em aplica\u00e7\u00f5es comerciais \u00e9 trabalhoso porque envolve necessariamente outros paradigmas (como bancos de dados relacionais), al\u00e9m de requisitos n\u00e3o funcionais da sua arquitetura (como seguran\u00e7a, concorr\u00eancia, etc) impedindo uma modelagem pura. Em aplica\u00e7\u00f5es que realmente existem l\u00f3gica de neg\u00f3cios e n\u00e3o apenas um conjunto de cadastros e relat\u00f3rios, a utiliza\u00e7\u00e3o [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[96,11,97,3,38,27,39],"tags":[393,394,372,98,99],"_links":{"self":[{"href":"https:\/\/www.milfont.org\/tech\/wp-json\/wp\/v2\/posts\/66"}],"collection":[{"href":"https:\/\/www.milfont.org\/tech\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.milfont.org\/tech\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.milfont.org\/tech\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.milfont.org\/tech\/wp-json\/wp\/v2\/comments?post=66"}],"version-history":[{"count":0,"href":"https:\/\/www.milfont.org\/tech\/wp-json\/wp\/v2\/posts\/66\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.milfont.org\/tech\/wp-json\/wp\/v2\/media?parent=66"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.milfont.org\/tech\/wp-json\/wp\/v2\/categories?post=66"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.milfont.org\/tech\/wp-json\/wp\/v2\/tags?post=66"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}