<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-2490744060677162130</id><updated>2025-09-18T00:30:34.755-07:00</updated><category term="programação"/><category term="arquitetura"/><category term="DDD"/><category term="Domain Driven Design"/><category term="boas práticas"/><category term="aplicação"/><category term="design"/><category term="pattern"/><category term="MVC"/><category term="análise"/><category term="ASP.NET"/><category term="Silverlight"/><category term="ebook"/><category term="visual studio"/><category term=".net remoting"/><category term="Domain Events"/><category term="Enterprise Library"/><category term="MVP"/><category term="MVVM"/><category term="artefato"/><category term="comunicação"/><category term="desenho"/><category term="framework"/><category term="log4net"/><category term="macros"/><category term="scripts"/><category term="segurança"/><category term="sql"/><category term="utilitários"/><category term="volumetria"/><category term="vídeos"/><category term="wcf"/><category term="ágil"/><title type='text'>Eduardo Silva</title><subtitle type='html'>Falando sobre programação</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://eduardodotnet.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://eduardodotnet.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/12442853817177091653</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>60</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-2490744060677162130.post-4831658296087580463</id><published>2014-08-04T22:30:00.000-07:00</published><updated>2014-08-04T22:30:00.970-07:00</updated><title type='text'>Problemas com Repository e ORM</title><content type='html'>&lt;div class=&quot;MsoNormal&quot;&gt;
Em um post anterior eu evidenciei uma tendência de se
encapsular frameworks em classes da própria aplicação. Dei uma atenção especial
ao padrão Repository utilizado com ORM’s, e nesse post resolvi&amp;nbsp; destacar outros problemas que podem ocorrer
com esse padrão.&lt;/div&gt;
&lt;h3&gt;
Nem sempre é fácil identificar a responsabilidade&lt;/h3&gt;
&lt;div&gt;
Quando estamos definindo os métodos do repositório os métodos básicos são fáceis de definir:&lt;/div&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;GetById;&lt;/li&gt;
&lt;li&gt;Save (InsertOrUpdate);&lt;/li&gt;
&lt;li&gt;Delete;&lt;/li&gt;
&lt;li&gt;GetBy(Filter filters);&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
Vamos pegar um cenário onde você tenha um classe Customer e a classe Sale tendo cada uma delas a sua devida implementação do Repository.&lt;br /&gt;
Agora imagine um item do seu dashboard onde você exibe o total de vendas dos clientes:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAqphdy6LNgXXHZEePr_xTEDSMkk8xJZNgzxy31OX4TaU76a_ZU-1rPbeIl13Kbu9ksX_eJeaLVoGmVnZnKau3WjUmXHimwpPeasZv4bue_Lw8cU8sJDDsyqdO67lkxhWP1yC-TvMHS1Y/s1600/post.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAqphdy6LNgXXHZEePr_xTEDSMkk8xJZNgzxy31OX4TaU76a_ZU-1rPbeIl13Kbu9ksX_eJeaLVoGmVnZnKau3WjUmXHimwpPeasZv4bue_Lw8cU8sJDDsyqdO67lkxhWP1yC-TvMHS1Y/s1600/post.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
Em qual repository você colocaria a implementação dessa consulta? Customer ou Sale?&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
Funcionalidades que requerem consultas e escritas no banco de dados que cruzam as fronteiras estabelecidas pelo padrão é algo muito comum. Quando surgem cenários desse tipo alguns utilizam estrategias que podem degradar a performance da aplicação como o Select N+1.&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;
Dificuldade para resolver problemas de Performance&lt;/h3&gt;
&lt;div&gt;
O Select N + 1 significa que você foi mais de uma vez no banco de dados para obter dados, no exemplo acima tivemos as seguintes requisições no banco de dados.&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;ol&gt;
&lt;li&gt;Obtém todos os clientes;&lt;/li&gt;
&lt;li&gt;Quando acionada a propridade Sales de o sistema foi no banco para obter as respectivas vendas, ou seja, se tivermos 10 clientes o sistema irá 10 vezes no banco buscar as vendas de dos clientes;&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
Até aqui esses problemas reportados não é culpa do padrão + ORM mas só do padrão. Com os repositories nós não conseguimos customizar o retorno do banco de dados para necessidades especificas, até por que isso foge um pouco das responsabilidades do padrão.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
Como uma solução pra esses tipos de problemas muitos
preferem expor recursos do ORM pelo Repository, como exemplo:&lt;o:p&gt;&lt;/o:p&gt;&lt;/div&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Enable/Disable Lazy Loading;&lt;/li&gt;
&lt;li&gt;Multi Queries;&lt;/li&gt;
&lt;li&gt;Operações em Batch;&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
O problema que isso se torna um “vazamento” da abstração que o Repository se propõe a fazer, se chegamos nesse ponto por que precisamos do padrão?&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;h3&gt;
Organização e reaproveitamento de código&lt;/h3&gt;
&lt;div&gt;
Alguns programadores ainda defendem a utilização do Repository por questões de organização e reaproveitamento de código e realmente processos de escrita e leituras duplicados não é legal. Pra resolver esses problemas já existem outros padrões bem interessantes pra ser utilizado (&lt;a href=&quot;http://lostechies.com/jimmybogard/2012/10/08/favor-query-objects-over-repositories/&quot; target=&quot;_blank&quot;&gt;QueryObjects&lt;/a&gt; e &lt;a href=&quot;http://martinfowler.com/bliki/CQRS.html&quot; target=&quot;_blank&quot;&gt;CQRS&lt;/a&gt;).&lt;br /&gt;
&lt;h3&gt;
Conclusão&lt;/h3&gt;
&lt;/div&gt;
Encapsular frameworks não é uma boa idéia, isso não significa que você não possa criar &quot;facilitadores&quot; para melhorar ou até mesmo contextualizar os frameworks para sua necessidade. Acredito que o ideal é sempre permitir que esses frameworks sejam utilizados diretamentes se necessário, assim todo o potencial dessas ferramentas sempre estará disponível.&lt;br /&gt;
&lt;div class=&quot;MsoNormal&quot;&gt;
&lt;o:p&gt;&lt;/o:p&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;/div&gt;
</content><link rel='replies' type='application/atom+xml' href='http://eduardodotnet.blogspot.com/feeds/4831658296087580463/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2490744060677162130/4831658296087580463' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/4831658296087580463'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/4831658296087580463'/><link rel='alternate' type='text/html' href='http://eduardodotnet.blogspot.com/2014/08/problemas-com-repository-e-orm.html' title='Problemas com Repository e ORM'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/12442853817177091653</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAqphdy6LNgXXHZEePr_xTEDSMkk8xJZNgzxy31OX4TaU76a_ZU-1rPbeIl13Kbu9ksX_eJeaLVoGmVnZnKau3WjUmXHimwpPeasZv4bue_Lw8cU8sJDDsyqdO67lkxhWP1yC-TvMHS1Y/s72-c/post.png" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2490744060677162130.post-1832035300010638691</id><published>2014-03-06T23:00:00.000-08:00</published><updated>2014-03-06T23:00:15.742-08:00</updated><title type='text'>Validando datas para envio ao banco de dados SQL Server</title><content type='html'>É muito comum achar validação de dados para envio ao banco de dados da seguinte forma:&lt;br /&gt;
&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/eduardosilva/1c49895870963405f86d.js&quot;&gt;&lt;/script&gt;

O problema de validar desta forma é que o DateTime.MinValue retorna&amp;nbsp;00:00:00.0000000, January 1, 0001 &amp;nbsp;enquanto a data minima aceita pelo SQL Server é 1/1/1753.&lt;br /&gt;
&lt;br /&gt;
Para que a validação seja valida para o envio a um banco de dados SQL Server você pode fazer como abaixo:&lt;br /&gt;
&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/eduardosilva/522d3ad5f2078bdbebc9.js&quot;&gt;&lt;/script&gt;</content><link rel='replies' type='application/atom+xml' href='http://eduardodotnet.blogspot.com/feeds/1832035300010638691/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2490744060677162130/1832035300010638691' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/1832035300010638691'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/1832035300010638691'/><link rel='alternate' type='text/html' href='http://eduardodotnet.blogspot.com/2014/03/validando-datas-para-envio-ao-banco-de.html' title='Validando datas para envio ao banco de dados SQL Server'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/12442853817177091653</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2490744060677162130.post-5887745471308268004</id><published>2014-01-24T22:00:00.000-08:00</published><updated>2014-01-24T22:00:00.938-08:00</updated><title type='text'>Ícones Sprite, só usar!</title><content type='html'>Ícones sprite com o css prontinho, só chegar e usar!&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;https://github.com/eduardosilva/icons-silk-sprite&quot;&gt;https://github.com/eduardosilva/icons-silk-sprite&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://github.com/eduardosilva/icons-fugue-sprite&quot;&gt;https://github.com/eduardosilva/icons-fugue-sprite&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://github.com/eduardosilva/icons-farm-fresh-sprite&quot;&gt;https://github.com/eduardosilva/icons-farm-fresh-sprite&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://eduardodotnet.blogspot.com/feeds/5887745471308268004/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2490744060677162130/5887745471308268004' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/5887745471308268004'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/5887745471308268004'/><link rel='alternate' type='text/html' href='http://eduardodotnet.blogspot.com/2014/01/icones-sprite-so-usar.html' title='Ícones Sprite, só usar!'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/12442853817177091653</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2490744060677162130.post-3031915698355708877</id><published>2014-01-14T22:00:00.000-08:00</published><updated>2014-01-14T22:00:02.862-08:00</updated><title type='text'>Carregando dinamicamente as configurações do Entity Framework Code First</title><content type='html'>&lt;p&gt;Abaixo um exemplo de como carregar as configurações customizadas de mapeamentos para o Entity Framework Code First.&lt;/p&gt;

&lt;script src=&quot;https://gist.github.com/eduardosilva/8417389.js&quot;&gt;&lt;/script&gt;</content><link rel='replies' type='application/atom+xml' href='http://eduardodotnet.blogspot.com/feeds/3031915698355708877/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2490744060677162130/3031915698355708877' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/3031915698355708877'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/3031915698355708877'/><link rel='alternate' type='text/html' href='http://eduardodotnet.blogspot.com/2014/01/carregando-dinamicamente-as.html' title='Carregando dinamicamente as configurações do Entity Framework Code First'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/12442853817177091653</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2490744060677162130.post-6789987710114272552</id><published>2013-12-12T22:00:00.000-08:00</published><updated>2013-12-12T22:00:02.686-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="programação"/><title type='text'>Postmon - API para consultar CEP</title><content type='html'>O Postmon é uma api REST construída em Python e MongoDB para consulta de CEP e encomendas.&lt;br /&gt;
Nessa &lt;a href=&quot;http://www.infoq.com/br/presentations/hackeando-codigos-postais&quot; target=&quot;_blank&quot;&gt;apresentação&lt;/a&gt; do InfoQ Alê Borba conta a história da criação da API.&lt;br /&gt;
&lt;br /&gt;
Site da API:&amp;nbsp;&lt;a href=&quot;http://postmon.com.br/&quot;&gt;http://postmon.com.br/&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://eduardodotnet.blogspot.com/feeds/6789987710114272552/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2490744060677162130/6789987710114272552' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/6789987710114272552'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/6789987710114272552'/><link rel='alternate' type='text/html' href='http://eduardodotnet.blogspot.com/2013/12/postmon-api-para-consultar-cep.html' title='Postmon - API para consultar CEP'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/12442853817177091653</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2490744060677162130.post-6884787462992628693</id><published>2013-12-10T22:00:00.000-08:00</published><updated>2013-12-10T22:00:08.276-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="design"/><title type='text'>Templates free para o Bootstrap</title><content type='html'>Pra quem ainda não conhece o&amp;nbsp;&lt;a href=&quot;http://getbootstrap.com/&quot; target=&quot;_blank&quot;&gt;Bootstrap&lt;/a&gt;, ele é um dos mais famosos frameworks de interface web.&lt;br /&gt;
Amplamente difundido entre designers e programadores, sua utilização tem sido cada vez mais utilizadas principalmente devido a recursos bem interessantes como recurso de layout reponsive.&lt;br /&gt;
&lt;br /&gt;
Um dos sites mais famosos de vendas de layout, o&amp;nbsp;&lt;a href=&quot;http://themeforest.net/&quot; target=&quot;_blank&quot;&gt;ThemeForest&lt;/a&gt;&amp;nbsp;tem em vários de seus produtos o Bootstrap como base. Mas pra quem não esta afim de gastar em torno U$30,00 (em média) para ter um layout pronto com o Bootstrap, você pode baixar layouts free (bem mais simples) no &lt;a href=&quot;http://startbootstrap.com/&quot; target=&quot;_blank&quot;&gt;Start Bootstrap&lt;/a&gt;&amp;nbsp;ele tem alguns templates prontos como:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Shop Homepage:&amp;nbsp;&lt;a href=&quot;http://startbootstrap.com/shop-homepage&quot;&gt;http://startbootstrap.com/shop-homepage&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;Admin:&amp;nbsp;&lt;a href=&quot;http://startbootstrap.com/sb-admin&quot;&gt;http://startbootstrap.com/sb-admin&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;Blog:&amp;nbsp;&lt;a href=&quot;http://startbootstrap.com/blog-home&quot;&gt;http://startbootstrap.com/blog-home&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;E vários outros para Business:&amp;nbsp;&lt;a href=&quot;http://startbootstrap.com/home-page-templates&quot;&gt;http://startbootstrap.com/home-page-templates&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://eduardodotnet.blogspot.com/feeds/6884787462992628693/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2490744060677162130/6884787462992628693' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/6884787462992628693'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/6884787462992628693'/><link rel='alternate' type='text/html' href='http://eduardodotnet.blogspot.com/2013/12/templates-free-para-o-bootstrap.html' title='Templates free para o Bootstrap'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/12442853817177091653</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2490744060677162130.post-4701257825411799283</id><published>2013-12-09T22:00:00.000-08:00</published><updated>2013-12-10T02:10:03.816-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="log4net"/><category scheme="http://www.blogger.com/atom/ns#" term="programação"/><category scheme="http://www.blogger.com/atom/ns#" term="wcf"/><title type='text'>WCF com Log4Net</title><content type='html'>Galera,&lt;br /&gt;
&lt;br /&gt;
Pra quem precisa utilizar o Log4Net com o WCF disponibilizei uma biblioteca bem simples de integração entre os dois:&lt;br /&gt;
&lt;a href=&quot;http://eduardosilva.github.io/Trinity.Wcf.Log4Net/&quot;&gt;http://eduardosilva.github.io/Trinity.Wcf.Log4Net/&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Endereço do NuGet:&lt;br /&gt;
&lt;a href=&quot;https://www.nuget.org/packages/TrinityWcfLog4Net/&quot;&gt;https://www.nuget.org/packages/TrinityWcfLog4Net/&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://eduardodotnet.blogspot.com/feeds/4701257825411799283/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2490744060677162130/4701257825411799283' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/4701257825411799283'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/4701257825411799283'/><link rel='alternate' type='text/html' href='http://eduardodotnet.blogspot.com/2013/12/wcf-com-log4net.html' title='WCF com Log4Net'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/12442853817177091653</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2490744060677162130.post-7960624572989687562</id><published>2012-12-23T15:00:00.000-08:00</published><updated>2012-12-23T15:00:04.185-08:00</updated><title type='text'>ASP.Net MVC: Muito código nas Controllers</title><content type='html'>&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;Eu tenho utilizado muito o ASP.Net MVC e sem dúvida é uma grande tecnologia, mas resolvi colocar nesse post alguns problemas que eu passei e como resolvi. &lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;Com o ASP.Net Web Forms, por padrão, temos um code behind (*.aspx.cs) por página (*.aspx) isso significa que temos tem uma classe, que podemos de certa forma caracterizar como uma controller, responsável por uma View. Já no ASP.Net MVC podemos ter um Controller responsável por varias views. Ex.: ProdutoController&amp;nbsp; responsável pelas view Pesquisar, Detalhe, Edicao. Nesta mesma controller podemos potencializar a sua aplicação deixando-a responsável por responder chamadas de json.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;&lt;br /&gt;Bom com isso acabamos tendo muito código nas nossas controllers (consultas, escritas, conversões de tipos etc). E isso não é culpa da tecnologia é apenas uma questão de como organizar as idéias e responsabilidades.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;Com essa quantidade de código nas Controller fica dificil de dar manutenção, mesmo refatorando em métodos você acaba vendo um código muito extenso na sua controller o que de cara parece ser um mal sinal (ou um mal cheiro). &lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;Não precisamos &quot;reinventar a roda&quot; para resolver esses problemas, grandes mentes já tem várias sugestões sobre isso e quero apenas apresentar algumas delas que eu estou utilizando e tem me agradado.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;&lt;a href=&quot;http://martinfowler.com/bliki/CQRS.html&quot; target=&quot;_blank&quot;&gt;CQRS&lt;/a&gt; (Command Query Responsibility Segregation) é um padrão que tenho utilizado para organizar esse tipo de coisa, não vou entrar em detalhes sobre o padrão, isso vai ficar para outro post, vou focar apenas em como estou aplicando nos meus projetos.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif; font-size: large;&quot;&gt;Consultas&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;O primeiro problema que eu resolvi foi referente a consultas. Se você utiliza um OR/M como o Entity Framework ou NHibernate com o ASP.Net MVC você pode acabar tendo muito código de consulta dentro da sua controller.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;OBS.: Eu não costumo encapsular os frameworks de OR/M com DAOs ou Repositories. Se estiver interessando no motivo leia o artigo &lt;a href=&quot;http://eduardodotnet.blogspot.com.br/2011/03/abstracao-da-abstracao.html&quot; target=&quot;_blank&quot;&gt;abstração da abstração&lt;/a&gt;. Só pra reforçar que isso também não é coisa da minha cabeça, &lt;a href=&quot;http://ayende.com/blog&quot; target=&quot;_blank&quot;&gt;Ayende Rahien&lt;/a&gt; é um grande defensor da idéia de que abstrair OR/M é um erro.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;Eu utilizo para as consultas o &lt;a href=&quot;http://www.martinfowler.com/eaaCatalog/queryObject.html&quot; target=&quot;_blank&quot;&gt;Query Object Pattern &lt;/a&gt;(&lt;a href=&quot;http://ayende.com/blog/2266/query-objects-vs-methods-on-the-repository&quot; target=&quot;_blank&quot;&gt;link&lt;/a&gt;), com isso consigo encapsular as consultas nessas classes. Isso também evita a questão de trazer todas as propriedades das entidades relacionadas na consulta, eu consigo criar consultas espeficidas para fins específicos de uma View, o que traz um grande ganho de performance. (uma coleção de uma determinada entidade para popular um combobox pode te dar muito dor de cabeça. Acredite!).&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif; font-size: large;&quot;&gt;Escritas&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;Para as escritas estou utilizando o &lt;a href=&quot;http://ayende.com/blog/159969/design-patterns-in-the-test-of-time-command-redux&quot; target=&quot;_blank&quot;&gt;Command Pattern&lt;/a&gt;, com ele eu consigo refatorar o processo de escrita em várias blocos de comando, afinal nem sempre nossas telas só precisamos executar um salvar correto? Como utilizo muito o Entity Framework, também fica fácil seperar esses comandos utilizando uma única instancia de context e controle de transação quando necessário.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;Se você pesquisar sobre esse padrão verá outros padrões relacionados como o &lt;a href=&quot;http://ayende.com/blog/154113/limit-your-abstractions-commands-vs-tasks-did-you-forget-the-workflow&quot; target=&quot;_blank&quot;&gt;Tasks&lt;/a&gt; e &lt;a href=&quot;http://ayende.com/blog/154113/limit-your-abstractions-commands-vs-tasks-did-you-forget-the-workflow&quot; target=&quot;_blank&quot;&gt;Events&lt;/a&gt;, porém os meus projetos até o momento não precisou desse potencial todo.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;Basicamente estou organizando os meus projetos da seguinte forma:&lt;/span&gt;&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;Entities&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;Commands&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;QueryObjects&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;Controllers&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;Views&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;Models&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;É claro que isso pode variar de projeto a projeto, mas no geral &lt;/span&gt;&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;os&lt;/span&gt; projetos que tenho trabalhado esse tipo de organização tem atendido muito bem, sendo bastante produtivo mas sem perder a organização e flexibilidade do código.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: Arial,Helvetica,sans-serif;&quot;&gt;Até a próxima!&lt;/span&gt;</content><link rel='replies' type='application/atom+xml' href='http://eduardodotnet.blogspot.com/feeds/7960624572989687562/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2490744060677162130/7960624572989687562' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/7960624572989687562'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/7960624572989687562'/><link rel='alternate' type='text/html' href='http://eduardodotnet.blogspot.com/2012/12/aspnet-mvc-muito-codigo-nas-controllers.html' title='ASP.Net MVC: Muito código nas Controllers'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/12442853817177091653</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2490744060677162130.post-3244897109084233198</id><published>2011-08-13T06:00:00.000-07:00</published><updated>2011-08-15T08:20:59.894-07:00</updated><title type='text'>Extensions Methods e Namespaces</title><content type='html'>&lt;p&gt;Eu utilizo &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/bb383977.aspx&quot; target=&quot;_blank&quot;&gt;Extensions Methods&lt;/a&gt; para praticamente duas finalidades: &lt;/p&gt; &lt;ul&gt; &lt;li&gt;Implementar uma funcionalidade não existente para um objeto;&lt;/li&gt; &lt;li&gt;Dar uma maior coesão a um trecho de código;&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Como exemplo de coesão, veja o trecho de código abaixo:&lt;/p&gt; &lt;p&gt;&lt;a href=&quot;http://lh4.ggpht.com/-6NNWshtBYNI/Tkk5ItqgAmI/AAAAAAAAAd8/J7ZMaNX0r-A/s1600-h/img01%25255B8%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;img01&quot; border=&quot;0&quot; alt=&quot;img01&quot; src=&quot;http://lh4.ggpht.com/-FgruULJaEB8/Tkk5JJly_CI/AAAAAAAAAeA/stP8Qu0bX_0/img01_thumb%25255B6%25255D.png?imgmax=800&quot; width=&quot;436&quot; height=&quot;54&quot;&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Para deixar o código um pouco mais coeso pode implementado da seguinte forma:&lt;/p&gt; &lt;p&gt;&lt;a href=&quot;http://lh3.ggpht.com/-Z56oKMbj0XA/Tkk5J-Hyh1I/AAAAAAAAAeE/3Vjt1UVCcQc/s1600-h/image%25255B8%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;http://lh5.ggpht.com/-iypN87dUi0w/Tkk5Kd_qHzI/AAAAAAAAAeI/Yfmmy-CNBK4/image_thumb%25255B4%25255D.png?imgmax=800&quot; width=&quot;184&quot; height=&quot;62&quot;&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Para criar uma classe que implemente o código que queremos é muito simples:&lt;/p&gt; &lt;p&gt;&lt;a href=&quot;http://lh5.ggpht.com/-_SVVg1wHFb0/Tkk5Ky7gFhI/AAAAAAAAAeM/qS02u8UkocE/s1600-h/image%25255B13%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;http://lh3.ggpht.com/-EXyvEYjCLvU/Tkk5LtaP3vI/AAAAAAAAAeQ/vRZ146_AwHs/image_thumb%25255B7%25255D.png?imgmax=800&quot; width=&quot;422&quot; height=&quot;118&quot;&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Agora pra utiliza-lo basta fazer o seguinte:&lt;/p&gt; &lt;p&gt;&lt;a href=&quot;http://lh5.ggpht.com/-NdqT-qN5eYM/Tkk5MLa_7NI/AAAAAAAAAeU/hbCsAd1zvFU/s1600-h/image%25255B17%25255D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top: 0px; border-right: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;http://lh4.ggpht.com/-XP8dmiK3piY/Tkk5M-pXRlI/AAAAAAAAAeY/D-AFT6WFmtM/image_thumb%25255B9%25255D.png?imgmax=800&quot; width=&quot;240&quot; height=&quot;172&quot;&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Pois é, o Visual Studio já me avisou que não encontrou o meu método de extensão. Isso se dá por que esqueci de fazer o using para o namespace onde esta a extensão, e isso aconteceu por que o intellisense&amp;nbsp; não me deu essa opção.&lt;br&gt;Quando criamos um &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/bb383977.aspx&quot; target=&quot;_blank&quot;&gt;extension method&lt;/a&gt; dentro de uma namespace precisamos lembrar de fazer o using manualmente toda vez que queremos utiliza-lo, o que nem sempre é legal.&lt;/p&gt; &lt;p&gt;O que podemos fazer nesse caso?&lt;/p&gt; &lt;p&gt;Duas opções:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Não definir uma namespace para a sua classe que contém os métodos de extensão;&lt;/li&gt; &lt;li&gt;Definir o namespace igual ao objeto ao qual o método esta atrelado.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Fica ai a dica, agora é só mandar bala nos &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/bb383977.aspx&quot; target=&quot;_blank&quot;&gt;extensions methods&lt;/a&gt;.&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://eduardodotnet.blogspot.com/feeds/3244897109084233198/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2490744060677162130/3244897109084233198' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/3244897109084233198'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/3244897109084233198'/><link rel='alternate' type='text/html' href='http://eduardodotnet.blogspot.com/2011/08/extensions-methods-e-namespaces.html' title='Extensions Methods e Namespaces'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/12442853817177091653</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/-FgruULJaEB8/Tkk5JJly_CI/AAAAAAAAAeA/stP8Qu0bX_0/s72-c/img01_thumb%25255B6%25255D.png?imgmax=800" height="72" width="72"/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2490744060677162130.post-2951542238341890690</id><published>2011-04-19T09:54:00.001-07:00</published><updated>2011-04-25T04:40:56.880-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="boas práticas"/><category scheme="http://www.blogger.com/atom/ns#" term="programação"/><title type='text'>O Inferno do Utils, Tools e afins!</title><content type='html'>&lt;p align=&quot;left&quot;&gt;&lt;img style=&quot;display: inline; float: left&quot; align=&quot;left&quot; src=&quot;http://www.keyboardjunkies.com/wp-content/uploads/2009/06/seo-tool.jpg&quot; width=&quot;199&quot; height=&quot;180&quot;&gt;Quando estamos pensando nas “camadas” da nossa solução, principalmente no começo do projeto, de uma forma geral temos grandes preocupações com assuntos como por exemplo coesão de responsabilidades, baixos acoplamentos, performance e segurança.&lt;br&gt;Se você esta em um projeto onde o pessoal diagrama tudo antes de começar a programar, se for criado uma classe diferente do que estava no diagrama os alarmes de incêndio são disparados.&lt;/p&gt; &lt;p&gt;De repente surge uma necessidade de enviar e-mail em mais de um ponto do sistema. Nós como “bons programadores”&amp;nbsp; que somos não vamos duplicar o código, então o que fazemos? Criamos um projeto chamado Utils (tools e seus primos).&lt;br&gt;Se precisamos encapsular uma transferência de arquivo via ftp agora não temos mais a “dor de cabeça” de decidir onde colocar esse tipo de funcionalidade, muito simples vai para o Utils.&lt;br&gt;Encapsulamento de leitura e gravação de um xml também não é mais problema, é só colocar no Utils que fica “tudo certo”.&lt;/p&gt; &lt;p&gt;Se pegarmos esse exemplo em particular fica claro que todos os cuidados que estávamos tomando na criação da solução foram totalmente ignorados quando passamos a ter o projeto Utils. E o pior é que fica tendencioso, se aparecer qualquer funcionalidade que não sabemos onde colocar, ela possivelmente irá parar no Utils.&lt;/p&gt; &lt;p&gt;Existem vários problemas com essa abordagem sendo alguns deles:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;O projeto fica dependendo de vários Assemblies, das mais diversas finalidades: E-mail, FTP e acesso a banco são dependências claras no exemplo citado.  &lt;li&gt;Se você tiver vários projetos que utiliza o seu Utils, cada alteração que você faça no seu Utils, recompila todos os projetos dependentes.  &lt;li&gt;O projeto vira um “saco de lixo” de código. Lixo mesmo, por que é incrível como a grande maioria das vezes a qualidade do código cai em classes que são colocadas nesses projetos.&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;Precisa realmente encapsular o envio de e-mail? Precisa mesmo? Será que você não esta sendo motivado em fazer isso simplesmente para facilitar o envio de e-mail? Será que você não esta criando uma &lt;a href=&quot;http://eduardodotnet.blogspot.com/2011/03/abstracao-da-abstracao.html&quot; target=&quot;_blank&quot;&gt;abstração da abstração&lt;/a&gt;? &lt;/p&gt; &lt;p&gt;&lt;br&gt;Caso seja realmente necessário encapsular o envio de e-mail minha sugestão é que faça isso de verdade, crie uma projeto com essa funcionalidade com um nome sugestivo para o que ele se propõe a fazer. Assim fica claro o que assembly fará, inclusive podemos prever possíveis dependências que isso pode trazer na hora de utilizá-lo.&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://eduardodotnet.blogspot.com/feeds/2951542238341890690/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2490744060677162130/2951542238341890690' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/2951542238341890690'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/2951542238341890690'/><link rel='alternate' type='text/html' href='http://eduardodotnet.blogspot.com/2011/04/o-inferno-do-utils-tools-e-afins.html' title='O Inferno do Utils, Tools e afins!'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/12442853817177091653</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2490744060677162130.post-180228420341854770</id><published>2011-03-25T13:35:00.001-07:00</published><updated>2013-12-11T11:45:18.241-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="arquitetura"/><category scheme="http://www.blogger.com/atom/ns#" term="boas práticas"/><title type='text'>A Abstração da Abstração</title><content type='html'>Eu acho engraçado como somos condicionados a tentar encapsular tudo o que é externo a nossa aplicação em nossas próprias classes. Muitas vezes baixamos um framework para um determinado trabalho e o encapusalmos por inúmeros motivos, para tornar o código um pouco mais aderente com que a funcionalidade se propõe a fazer, para facilitar uma determinada operação do framework que estamos utilizando, e por ai vai.&lt;br /&gt;
&lt;br /&gt;
O problema é que muitas vezes limitamos a utilização da ferramenta a aquilo que estamos diexando disponível nas nossas classes. O quanto isso vale a pena?&lt;br /&gt;
&lt;br /&gt;
Vou pegar como exemplo os nossos Repositories, geralmente o utilizamos como uma abstração de acesso a dados, e deixamos disponíveis em nossos repositories os famosos métodos Save, GetById, GetAll, etc…&lt;br /&gt;
Bom, hoje em dia é muito comum utilizarmos um framework ORM para facilitar as implementações de banco de dados, mas perceba, o ORM é uma abstração de acesso a dados, claro, não igual ao Repository, porém não deixa de ser uma abstração de acesso. &lt;br /&gt;
&lt;br /&gt;
Quando encapsulamos os métodos do ORM nos nossos repositories estamos perdendo poderosas features como por exemplo o &lt;a href=&quot;http://ayende.com/Blog/archive/2007/05/20/NHibernate-Multi-Criteria.aspx&quot; target=&quot;_blank&quot;&gt;Multiquery&lt;/a&gt; e e &lt;a href=&quot;http://ayende.com/Blog/archive/2009/04/27/nhibernate-futures.aspx&quot; target=&quot;_blank&quot;&gt;Future&lt;/a&gt; do NHbernate.&lt;br /&gt;
Não tenho a pretensão de classificar quando isso é bom ou ruim, mas cada caso precisa ser analisado com calma.&lt;br /&gt;
&lt;br /&gt;
Fica ai a bandeira levantada.&lt;br /&gt;
Até a próxima.</content><link rel='replies' type='application/atom+xml' href='http://eduardodotnet.blogspot.com/feeds/180228420341854770/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2490744060677162130/180228420341854770' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/180228420341854770'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/180228420341854770'/><link rel='alternate' type='text/html' href='http://eduardodotnet.blogspot.com/2011/03/abstracao-da-abstracao.html' title='A Abstração da Abstração'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/12442853817177091653</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2490744060677162130.post-3890100001250995550</id><published>2011-03-17T04:50:00.001-07:00</published><updated>2011-03-17T04:53:19.205-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Silverlight"/><title type='text'>Compilando para Silverlight</title><content type='html'>&lt;p&gt;Essa dica eu ja mandei para o &lt;a href=&quot;http://groups.google.com/group/maisumgruposobreprogramacao&quot; target=&quot;_blank&quot;&gt;MUGSP&lt;/a&gt; mas resolvi deixar registrado aqui também.&lt;/p&gt; &lt;p&gt;Não sei se alguém algum dia vai precisar disso, mas se estiver tentando gerar um dll com código C# compilado “na mão” para Silverlight, tem que fazer o seguinte:&lt;/p&gt; &lt;ol&gt; &lt;li&gt;Todas as referencias devem ser feitas para as dlls compiladas para Silverlight (System.dll, mscorlib.dll e assim por diante). No meu caso faço referencias as dlls que estão na pasta&amp;nbsp; c:\Arquivos de programas\ReferenceAssemblies\Microsoft\Framework\Silverlight\v4.0\  &lt;li&gt;Para o compilador (csc.exe) é necessário informar os argumentos /nostdlib+ /noconfig. Isso é necessário para que não seja gerado referencia para as bibliotecas padrões do .Net Framework.  &lt;li&gt;No caso de utilizar o CodeDom (que foi o meu caso), é necessário passar esses argumentos para CompilerParameters:&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;new CompilerParameters&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; OutputAssembly = Path.Combine(outputDir, baseNamespace + &quot;.Silverlight.dll&quot;),&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; CompilerOptions = @&quot;/noconfig /nostdlib&quot;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }; &lt;/p&gt; &lt;p&gt;Fica ai a dica pra quem precisar.&lt;/p&gt; &lt;p&gt;Até a próxima.&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://eduardodotnet.blogspot.com/feeds/3890100001250995550/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2490744060677162130/3890100001250995550' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/3890100001250995550'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/3890100001250995550'/><link rel='alternate' type='text/html' href='http://eduardodotnet.blogspot.com/2011/03/compilando-para-silverlight.html' title='Compilando para Silverlight'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/12442853817177091653</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2490744060677162130.post-8123697777659627291</id><published>2011-03-14T11:07:00.001-07:00</published><updated>2011-03-14T16:19:57.389-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="análise"/><category scheme="http://www.blogger.com/atom/ns#" term="arquitetura"/><category scheme="http://www.blogger.com/atom/ns#" term="DDD"/><category scheme="http://www.blogger.com/atom/ns#" term="Domain Driven Design"/><title type='text'>DDD: Melhorando a forma de carregar as Views utilizando Modelo Rico.</title><content type='html'>&lt;p&gt;DDD sem dúvida é uma excelente ferramenta para auxiliar a resolver problemas que surgem em domínios complexos porém, como todo mundo diz, não é bala de prata. Mas o problema que eu vou expor aqui não é exclusivo de quem utiliza DDD e sim de qualquer solução que se utiliza de Modelo de Domínio Rico.&lt;/p&gt; &lt;p&gt;Quando você tem um Modelo de domínio rico as operações de escrita ficam mais coesas, as responsabilidades ficam mais claras além de outros benefícios, no entando, você pode ganhar alguns problemas nas operações de leitura.&lt;br&gt;Imagine uma tela onde você tenha três combobox, cada combobox populada com uma entidade diferente. Agora imagine essas entidades com um número significativo de propriedades (não vou definir aqui o quanto seria esse número, essa discussão não vem ao caso agora) e uma cadeia de relacionamento complexa (A relacionada com B que se relaciona com C e assim por diante). Como faríamos para popular esses combos da tela?&lt;/p&gt; &lt;p&gt;Certamente você utilizaria o repositorio especifico para cada uma das entidades e faria a consulta apropriada para popular os combos.&lt;/p&gt; &lt;p&gt;Você conseguiu identificar alguma problema nisso? Não? Então deixa eu ajudar.&lt;/p&gt; &lt;p&gt;Você percebeu quantas chamadas ao banco de dados você teve que fazer? Se você tiver utilizando alguma forma de serviço (WCF, WCF Data Services, ou qualquer outro tipo de serviço) você teve que chamar no mínimo três chamadas de serviço e cada chamada de serviço resultou em uma chamada de banco de dados. &lt;/p&gt; &lt;p&gt;Pronto, ta ai o pretesto que o seu companheiro de trabalho ou o seu gerente de projetos precisava para falar que DDD não presta! Mas esse tipo de problema também tem solução.&lt;/p&gt; &lt;p&gt;Primeira coisa: Pelo amor de Deus, use um ORM. Se você é daqueles programadores que ainda tem resistência a um ORM (como eu tinha) pare com isso agora antes que a coisa fique feia!&lt;br&gt;Com a utilização de ORM podemos utilizar recursos que nos ajudam na performance da aplicação como Lazy Loading, Cache, operações em Batch. O NHibernate tem funcionalidades excelentes para esses tipos de caso, por exemplo, com o &lt;a href=&quot;http://ayende.com/Blog/archive/2009/04/27/nhibernate-futures.aspx&quot; target=&quot;_blank&quot;&gt;Future&lt;/a&gt; poríamos popular os três combobox com uma única chamada para o banco de dados.&lt;/p&gt; &lt;p&gt;Segundo: Popule sua View somente com dados que ela precisa. Se para um combobox só precisamos de um Id e Descrição, pra que vamos trazer todos os dados da entidade? Novamente ferramentas como o NHibernate nos ajudam com esse tipo de situação.&lt;/p&gt; &lt;p&gt;De onde eu tirei essas soluções? &lt;a href=&quot;http://cqrsinfo.com/&quot; target=&quot;_blank&quot;&gt;CQRS&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;Pretendo colocar algumas soluções práticas para esse tipo de situação, mas ja adianto as dicas apresentadas aqui é apenas uma das várias formas que temos para resolver esse problema. O importante é reconhecer que o problema esta lá e ter a mente aberta para as muitas formas de resolve-lo.&lt;/p&gt; &lt;p&gt;Até mais.&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://eduardodotnet.blogspot.com/feeds/8123697777659627291/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2490744060677162130/8123697777659627291' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/8123697777659627291'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/8123697777659627291'/><link rel='alternate' type='text/html' href='http://eduardodotnet.blogspot.com/2011/03/ddd-melhorando-forma-de-carregar-as.html' title='DDD: Melhorando a forma de carregar as Views utilizando Modelo Rico.'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/12442853817177091653</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2490744060677162130.post-114162252624886952</id><published>2011-03-11T10:49:00.001-08:00</published><updated>2011-03-11T10:49:30.967-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="design"/><category scheme="http://www.blogger.com/atom/ns#" term="Silverlight"/><title type='text'>Silverlight: Dica de performance</title><content type='html'>&lt;p&gt;Essa semana resolvi um problema interessante de uma aplicação feita em Silverlight. &lt;/p&gt; &lt;p&gt;Estava investigando por que uma determinada aplicação estava lenta e atacamos nas coisas mais óbvias: acesso a banco, chamadas de serviço, tamanho de objetos e por ai vai. Aparentemente não havia que justificasse a lentidadão da aplicação.&lt;/p&gt; &lt;p&gt;Resolvemos então verificar se não havia algum recurso que estavamos usando do silverlight para causar o problema. Procurando no Google por pessoas que passaram pelo mesmo problema, vimos várias dicas referentes ao uso de transparencia e os problemas que isso pode causar quando não utilizado com moderação. &lt;br&gt;A nossa aplicação não estava utilizando transparencia mas sim sombra (DropShadow), quando removemos o efeito: Bingo!&lt;/p&gt; &lt;p&gt;Não estou querendo dizer que o DropShadow causa problema de performance, tanto que continuamos usando, mas removemos esse efeito em alguns pontos para ter a melhoria necessária sem prejudicar o layout, ou seja, é importante ficar atento ao uso desse tipo de recurso e o quanto ele pode onerar o desempenho da aplicação.&lt;/p&gt; &lt;p&gt;Abraços!&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://eduardodotnet.blogspot.com/feeds/114162252624886952/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2490744060677162130/114162252624886952' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/114162252624886952'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/114162252624886952'/><link rel='alternate' type='text/html' href='http://eduardodotnet.blogspot.com/2011/03/silverlight-dica-de-performance.html' title='Silverlight: Dica de performance'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/12442853817177091653</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2490744060677162130.post-9144588028763080930</id><published>2011-03-08T03:36:00.001-08:00</published><updated>2011-03-08T03:43:14.067-08:00</updated><title type='text'>HTTPS no IIS Express</title><content type='html'>&lt;p&gt;Recentemente comecei a utilizar o IIS Express para conferir as suas funcionalidades.&lt;/p&gt; &lt;p&gt;Um dos recursos que eu achei interessante é a utilização do HTTPS local. Para utiliza-lo basta clicar com o botão direito sobre o projeto e selecionar a opção &lt;em&gt;“Use IIS Express…”&lt;/em&gt;&lt;/p&gt; &lt;p&gt;&lt;a href=&quot;http://lh6.ggpht.com/_4YU41vAO9bk/TXYUyxRsxhI/AAAAAAAAAY0/h2mGzU-m3A4/s1600-h/img%2001%5B2%5D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;img 01&quot; border=&quot;0&quot; alt=&quot;img 01&quot; src=&quot;http://lh3.ggpht.com/_4YU41vAO9bk/TXYUzmcuIwI/AAAAAAAAAY4/OVJXD_BSMG8/img%2001_thumb.png?imgmax=800&quot; width=&quot;244&quot; height=&quot;205&quot;&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Será exibido uma janela pedindo confirmação para a criação de um diretório virtual para o seu projeto.&lt;/p&gt; &lt;p&gt;Depois de criado o diretório virtual você deve acionar o botão F4 sobre o projeto e habilitar a opção “SSL Enable”.&lt;/p&gt; &lt;p&gt;&lt;a href=&quot;http://lh3.ggpht.com/_4YU41vAO9bk/TXYUz3VB-XI/AAAAAAAAAY8/cZsqNm3PM2Q/s1600-h/img%2002%5B2%5D.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;img 02&quot; border=&quot;0&quot; alt=&quot;img 02&quot; src=&quot;http://lh5.ggpht.com/_4YU41vAO9bk/TXYU0X8N0ZI/AAAAAAAAAZA/NPa2c0ORATM/img%2002_thumb.png?imgmax=800&quot; width=&quot;244&quot; height=&quot;34&quot;&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Prontinho, agora basta você rodar a sua aplicação através do endereço mesmo endereço só que utilizando https ao invés do http.&lt;/p&gt; &lt;p&gt;&lt;a href=&quot;http://www.microsoft.com/downloads/en/details.aspx?FamilyID=abc59783-89de-4adc-b770-0a720bb21deb&quot; target=&quot;_blank&quot;&gt;Baixar o IIS Express&lt;/a&gt;.&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://eduardodotnet.blogspot.com/feeds/9144588028763080930/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2490744060677162130/9144588028763080930' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/9144588028763080930'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/9144588028763080930'/><link rel='alternate' type='text/html' href='http://eduardodotnet.blogspot.com/2011/03/https-no-iis-express.html' title='HTTPS no IIS Express'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/12442853817177091653</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/_4YU41vAO9bk/TXYUzmcuIwI/AAAAAAAAAY4/OVJXD_BSMG8/s72-c/img%2001_thumb.png?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2490744060677162130.post-1661528434397030141</id><published>2010-09-10T06:12:00.000-07:00</published><updated>2010-09-10T06:15:43.097-07:00</updated><title type='text'>Site sobre CQRS</title><content type='html'>&lt;span style=&quot;font-family:verdana;&quot;&gt;Você pode encontrar vídeos, documentos e exemplos sobre CQRS no &lt;/span&gt;&lt;a href=&quot;http://cqrsinfo.com/&quot;&gt;&lt;span style=&quot;font-family:verdana;&quot;&gt;http://cqrsinfo.com/&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot;font-family:verdana;&quot;&gt;. Vale a pena conferir.&lt;/span&gt;</content><link rel='replies' type='application/atom+xml' href='http://eduardodotnet.blogspot.com/feeds/1661528434397030141/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2490744060677162130/1661528434397030141' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/1661528434397030141'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/1661528434397030141'/><link rel='alternate' type='text/html' href='http://eduardodotnet.blogspot.com/2010/09/site-sobre-cqrs.html' title='Site sobre CQRS'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/12442853817177091653</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2490744060677162130.post-3274773809848305442</id><published>2010-09-03T17:28:00.000-07:00</published><updated>2010-09-03T17:48:54.250-07:00</updated><title type='text'>Contextualizando os seus testes</title><content type='html'>O Giovanni Bassi postou em seu &lt;a href=&quot;http://unplugged.giggio.net/&quot;&gt;blog&lt;/a&gt; sobre a &lt;a href=&quot;http://unplugged.giggio.net/unplugged/post/Testando-com-AAA-(Arrange-Act-Assert).aspx&quot;&gt;técnica AAA&lt;/a&gt; (Arrange, Act, Assert) para criação de testes. Ele aproveita para abordar o principio de que cada teste só deve testar uma única coisa, e o quanto isso pode ser complicado.&lt;br /&gt;&lt;br /&gt;Aproveitando o gancho, partindo do exemplo que ele apresentou da calculado, vamos implementar o método de divisão:&lt;br /&gt;&lt;br /&gt;[TestClass]&lt;br /&gt;public class TestCalculadora&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private Calculadora _calculadora;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private int _resultado;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[TestInitialize]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public void Inicializar()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Arrange();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Act();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private void Arrange()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_calculadora = new Calculadora();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private void Act()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;_resultado = _calculadora.Dividir(10, 5);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[TestMethod]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public void Resultado2()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Assert.AreEqual&lt;int&gt;(2, _resultado);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class Calculadora&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public int Dividir(int a, int b)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return a / b;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Legal, mas também precisamos testar a divisão por zero para saber como o método irá se comportar. Como podemos fazer isso?&lt;br /&gt;&lt;br /&gt;É nesse momento que precisamos contextualizar nossos testes, isso significa que vamos testar a mesma rotina em cenários diferentes, no exemplo da calculadora precisamos gerar o cenário do dividir com o divisor maior que zero e divisor zero. Podemos testar conforme abaixo:&lt;br /&gt;&lt;br /&gt;public abstract class TestarCalculadora&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected Calculadora Calculadora { get; private set; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected int Resultado { get; set; }&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[TestInitialize]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public void Inicializar()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Arrange();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Act();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private void Arrange()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Calculadora = new Calculadora();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected abstract void Act();&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;[TestClass]&lt;br /&gt;public class TestarDivisaoComDivisorMaiorQueZero : TestarCalculadora&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected override void Act()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Resultado = Calculadora.Dividir(10, 5);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[TestMethod]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public void ResultadoIgual2()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Assert.AreEqual&lt;double&gt;(2, Resultado);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;[TestClass]&lt;br /&gt;public class TestarDivisaoComDivisorZero : TestarCalculadora&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;private bool _divisaoPorZeroGerada = false;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protected override void Act()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try { Resultado = Calculadora.Dividir(10, 0); }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;catch (DivideByZeroException) { _divisaoPorZeroGerada = true; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[TestMethod]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public void ExcecaoDivisaoPorZeroGerada()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Assert.IsTrue(_divisaoPorZeroGerada);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;[TestMethod]&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public void ResultadoIgualZero()&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Assert.AreEqual&lt;int&gt;(0, 0);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;Contextualizar os testes em cenários nos permite realizar várias verificações em vários cenários de uma mesma transação.&lt;br /&gt;Essa é uma técnica muito simples, porém muito poderosa. Se você utiliza BDD com certeza já conhecia.</content><link rel='replies' type='application/atom+xml' href='http://eduardodotnet.blogspot.com/feeds/3274773809848305442/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2490744060677162130/3274773809848305442' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/3274773809848305442'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/3274773809848305442'/><link rel='alternate' type='text/html' href='http://eduardodotnet.blogspot.com/2010/09/contextualizando-os-seus-testes.html' title='Contextualizando os seus testes'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/12442853817177091653</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2490744060677162130.post-1345496166179184290</id><published>2010-04-19T15:42:00.000-07:00</published><updated>2010-04-20T03:24:19.849-07:00</updated><title type='text'>Grupo de estudos: Referências de DDD</title><content type='html'>Pro pessoal do grupo de estudos e para todos os outros que se interessarem por DDD, abaixo segue uma série de links que considero interessante para ficar por dentro do assunto (Lembrando que o livro do Evans é leitura obrigatória ok?).&lt;br /&gt;&lt;br /&gt;&lt;a href=&quot;http://domaindrivendesign.org/&quot;&gt;http://domaindrivendesign.org/&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;http://www.infoq.com/minibooks/domain-driven-design-quickly&quot;&gt;http://www.infoq.com/minibooks/domain-driven-design-quickly&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;http://www.infoq.com/presentations/greg-young-unshackle-qcon08&quot;&gt;http://www.infoq.com/presentations/greg-young-unshackle-qcon08&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;http://www.infoq.com/presentations/Value-Objects-Dan-Bergh-Johnsson&quot;&gt;http://www.infoq.com/presentations/Value-Objects-Dan-Bergh-Johnsson&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;http://www.infoq.com/articles/ddd-in-practice&quot;&gt;http://www.infoq.com/articles/ddd-in-practice&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;http://devlicious.com/blogs/casey/archive/tags/DDD/default.aspx&quot;&gt;http://devlicious.com/blogs/casey/archive/tags/DDD/default.aspx&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;http://codebetter.com/blogs/gregyoung/archive/tags/DDD/default.aspx&quot;&gt;http://codebetter.com/blogs/gregyoung/archive/tags/DDD/default.aspx&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;http://jimmynilsson.com/blog/&quot;&gt;http://jimmynilsson.com/blog/&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;http://elegantcode.com/category/ddd/&quot;&gt;http://elegantcode.com/category/ddd/&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;http://www.vimeo.com/7838858&quot;&gt;http://www.vimeo.com/7838858&lt;/a&gt;</content><link rel='replies' type='application/atom+xml' href='http://eduardodotnet.blogspot.com/feeds/1345496166179184290/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2490744060677162130/1345496166179184290' title='3 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/1345496166179184290'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/1345496166179184290'/><link rel='alternate' type='text/html' href='http://eduardodotnet.blogspot.com/2010/04/grupo-de-estudos-referencias-de-ddd.html' title='Grupo de estudos: Referências de DDD'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/12442853817177091653</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2490744060677162130.post-3630808860510927076</id><published>2010-04-16T14:57:00.000-07:00</published><updated>2010-04-16T15:10:38.250-07:00</updated><title type='text'>Permitir que faça errado!!</title><content type='html'>Você já tomou uma bronca por ter feito uma chamada de um método em um lugar errado? (Ex.: gravar um log, abrir ou fechar uma conexão ou transação).&lt;br /&gt;Geralmente quando tomamos uma bronca dessa, do arquiteto responsável por exemplo, abaixamos a cabeça e vamos arrumar o &quot;erro&quot;. Mas hoje, quando me deparo esse tipo de coisa eu levanto a questão: O método só foi chamado do lugar errado por que a aplicação deixou que isso fosse feito.&lt;br /&gt;&lt;br /&gt;Desenhar uma aplicação de forma que seja fácil fazer o que é certo e difícil fazer o errado é um grande desafio, mas o fato de ser difícil não significa que não deva ser tentado. Ter um conhecimento mais profundo de OO e das ferramentas que utilizamos com certeza nos ajudam a alcançar esse objetivo.&lt;br /&gt;&lt;br /&gt;Por tanto, da próxima vez que você passar por esse tipo de situação independente do seu papel, do cara que esta dando ou recebendo a bronca, reflita sobre como esta desenhado a aplicação, isso pode fazer uma grande diferença.</content><link rel='replies' type='application/atom+xml' href='http://eduardodotnet.blogspot.com/feeds/3630808860510927076/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2490744060677162130/3630808860510927076' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/3630808860510927076'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/3630808860510927076'/><link rel='alternate' type='text/html' href='http://eduardodotnet.blogspot.com/2010/04/permitir-que-faca-errado.html' title='Permitir que faça errado!!'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/12442853817177091653</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2490744060677162130.post-8865715798919146936</id><published>2010-04-16T14:38:00.000-07:00</published><updated>2010-04-16T15:09:45.834-07:00</updated><title type='text'>Desvendando o Application Layer</title><content type='html'>&lt;span style=&quot;font-family:verdana;&quot;&gt;Sabemos que o coração do DDD esta no domínio, dedicamos grande parte da nossa atenção a ele.&lt;br /&gt;Mas gostaria de destacar o papel do application layer e tentar esclarecer algumas confusões sobre ele.&lt;br /&gt;&lt;br /&gt;Se você já procurou sobre application layer na internet, que vou chamar aqui de camada de aplicação, com certeza deve ter encontrado várias definições e aplicabilidades diferentes sobre o mesmo, por exemplo, &quot;Application Layer é o mesmo que Service Layer&quot; ou até mesmo relacionar com tecnologias como Web Services e WCF.&lt;br /&gt;&lt;br /&gt;Essa confusão de certa forma se justifica pelo fato de que, a responsabilidade da camada de aplicação é de coordenar (ou delegar) os trabalhos realizados pelo domínio, o que é muitas vezes encarado como um façade, o que não esta errado, mas é nessa comparação que começa os problemas, por que o service layer também pode ser um façade.&lt;br /&gt;&lt;br /&gt;Devido a esses problemas de definições e comparações, como você não tem um Service Layer em todos os projetos, você pode encarar que talvez não precise de uma camada de aplicação, e é ai que ao meu ver chegamos no ápice do engano.&lt;br /&gt;&lt;br /&gt;Para entender bem as diferenças entre eles é necessário destacar uma frase da definição do Evans sobre o application layer: &quot;The tasks this layer is responsible for are meaningful to the business&quot;&lt;br /&gt;&lt;br /&gt;Ou seja, não é simplemente chamar métodos de objetos de domínio em uma ordem específica, mas coordenar as tarefas de forma significativa ao negócio. Se você vê semelhanças entre a camada de aplicação e o controller do MVC elas param na palavra coordenar, ok? A controller coordena as interações entre a View e a Model, não é disto que estamos tratamos nesse momento.&lt;br /&gt;&lt;br /&gt;Nós, desenvolvedores, geralmente pensamos nas funcionalidades essencialmente como CRUD, fazemos isso por vários motivos, mas talvez o principal se refere a comodidades de interações com banco de dados. O problema desse pensamento é que para o negócio nem sempre o CRUD atende, o cliente não deleta um recebimento ele provavelmente faz um estorno, o cliente não faz um insert de ordem ele abre uma ordem de produção.&lt;br /&gt;&lt;br /&gt;A função da camada de aplicação é expor operações realizadas pelo domínio de forma que façam sentido ao domínio, por tanto, se o seu domínio abre uma ordem de produção não faz sentido eu ter SaveProductionOrder() na minha camada de aplicação mas sim OpenProductionOrder().&lt;br /&gt;&lt;br /&gt;Isso não quer dizer que os famosos métodos Save, Delete e similires não devam existir na sua camada de aplicação, devido ao fato de que, em alguns casos, não é possível determinar um termo de negócio para essas ações.&lt;br /&gt;&lt;br /&gt;Outro ponto importante é a questão da leitura de dados, no DDD nós obtemos os dados através do repositório, faz sentido criar métodos no Application Layer para ler dados? Eu respondo, nenhum. Enquanto em um serviço nós geralmente o utilizamos para operações de leitura e/ou escrita, a camada de aplicação só coordena as operações realizadas pelo meu domínio, quando eu preciso ler alguma coisa eu peço direto para o repositório.&lt;br /&gt;&lt;br /&gt;Você deve estar se perguntando: Mas eu preciso de um acesso único ao domínio, não preciso?&lt;br /&gt;Essa busca por um caminho linear é herança do BOLOVO onde você tinha UI &gt; BL &gt; DL &gt; BL &gt; UI.&lt;br /&gt;Essa idéia de que tudo tem que passar pelo domínio gera grandes transtornos para identificar as responsabilidades de cada coisa ou de até mesmo um alto acoplamento entre o domínio e outros recursos da minha aplicação, afinal, tudo passa pelo meu domínio.&lt;br /&gt;&lt;br /&gt;No desenho apresentado pelo Evans vemos claramente que isso não é necessário e nem deve ser praticado. Se precisamos de uma funcionalidade que se encontra na camada de infraestrutura podemos acessar diretamente dessa camada.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2CoYlwUUhbQ1GIR7PtdIdkxx23Td5JdQzfJmHPv1yMkcGNTxo3pVyNVioJHcBKksZmSdwP-OwAdLKtCCfmEXD0R-x9IuqxxAK1d8tRgrCqSPE_KziOPehyaMfhAyMeZRtY5IUiDLQPOc/s1600/dddlayered.png&quot;&gt;&lt;span style=&quot;font-family:verdana;&quot;&gt;&lt;img style=&quot;TEXT-ALIGN: center; MARGIN: 0px auto 10px; WIDTH: 265px; DISPLAY: block; HEIGHT: 320px; CURSOR: hand&quot; id=&quot;BLOGGER_PHOTO_ID_5460857187551908178&quot; border=&quot;0&quot; alt=&quot;&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2CoYlwUUhbQ1GIR7PtdIdkxx23Td5JdQzfJmHPv1yMkcGNTxo3pVyNVioJHcBKksZmSdwP-OwAdLKtCCfmEXD0R-x9IuqxxAK1d8tRgrCqSPE_KziOPehyaMfhAyMeZRtY5IUiDLQPOc/s320/dddlayered.png&quot; /&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot;font-family:verdana;&quot;&gt; &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:verdana;&quot;&gt;Concluíndo, apesar das semelhanças que a camada de aplicação tenha com outras funcionalidades precisamos ter em mente que ela precisa estar totalmente comprometida com o negócio.&lt;/span&gt;</content><link rel='replies' type='application/atom+xml' href='http://eduardodotnet.blogspot.com/feeds/8865715798919146936/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2490744060677162130/8865715798919146936' title='3 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/8865715798919146936'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/8865715798919146936'/><link rel='alternate' type='text/html' href='http://eduardodotnet.blogspot.com/2010/04/desvendando-o-application-layer.html' title='Desvendando o Application Layer'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/12442853817177091653</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg2CoYlwUUhbQ1GIR7PtdIdkxx23Td5JdQzfJmHPv1yMkcGNTxo3pVyNVioJHcBKksZmSdwP-OwAdLKtCCfmEXD0R-x9IuqxxAK1d8tRgrCqSPE_KziOPehyaMfhAyMeZRtY5IUiDLQPOc/s72-c/dddlayered.png" height="72" width="72"/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2490744060677162130.post-9196185733198518942</id><published>2010-04-04T16:04:00.000-07:00</published><updated>2010-04-04T16:07:46.087-07:00</updated><title type='text'>Problema com códigos no post</title><content type='html'>&lt;span style=&quot;font-size:85%;&quot;&gt;Estou com problemas com o syntaxhighlighter, nisso exibir código aqui no blog esta um pouco complicado, estou tentando resolver esse problema, mas até lá vou disponibilizar os códigos para download.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;Na sexta feira vou finalizar uma apresentação sobre DDD e vou publicar o código utilizado, nele tem exemplos de BDD e Domain Events.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-size:85%;&quot;&gt;Aguardem.&lt;/span&gt;</content><link rel='replies' type='application/atom+xml' href='http://eduardodotnet.blogspot.com/feeds/9196185733198518942/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2490744060677162130/9196185733198518942' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/9196185733198518942'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/9196185733198518942'/><link rel='alternate' type='text/html' href='http://eduardodotnet.blogspot.com/2010/04/problema-com-codigos-no-post.html' title='Problema com códigos no post'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/12442853817177091653</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2490744060677162130.post-1250276986217556071</id><published>2010-04-04T14:36:00.000-07:00</published><updated>2010-04-04T16:01:25.433-07:00</updated><title type='text'>Testes unitário x TDD x BDD</title><content type='html'>&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;Acompanhando os grupos de discussão eu percebo que ainda tem muita gente fazendo confusão entre testes unitários, TDD e BDD. Eu sei que a &quot;sopa de letrinhas&quot; não colabora, mas é fundamental entender as as diferenças entre eles para que você consiga usufluir dos seus benefícios.&lt;br /&gt;&lt;br /&gt;Eu não vou ficar aqui dando as definições formais de cada um, abaixo segue alguns links onde você pode obter mais informações, mas vou me preocupar em destacar as diferenças entre eles. &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:Verdana;font-size:85%;&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;a href=&quot;http://pt.wikipedia.org/wiki/Teste_de_unidade&quot;&gt;http://pt.wikipedia.org/wiki/Teste_de_unidade&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;http://pt.wikipedia.org/wiki/Test_Driven_Development&quot;&gt;http://pt.wikipedia.org/wiki/Test_Driven_Development&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;http://pt.wikipedia.org/wiki/Behavior_Driven_Development&quot;&gt;http://pt.wikipedia.org/wiki/Behavior_Driven_Development&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Quando estamos aplicando teste unitário, estamos testando um único trecho do nosso código, nada mais do que isso. Se o nosso teste faz mais do que isso ou ele é um teste de integração ou é qualquer outra coisa parecida mas não é teste unitário.&lt;br /&gt;&lt;br /&gt;Isso quer dizer que testes de integração não importantes? De forma alguma, mas um dos problemas em se ter teste de integração sem testes unitários é que se o seu teste falhar como você irá descobrir o motivo? Lembrando que, dependendo do tipo de teste de integração que você esteja fazendo, outros fatores podem influenciar o resultado (fatores externos como banco de dados por exemplo). &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;Um dos fatores de resistência aos testes unitários é a mudança que ele causa no nosso código. Como escrevemos testes para que testem apenas um único trecho, precisamos desacoplar nossas classes e métodos para garantir que estamos testando apenas uma única coisa.&lt;br /&gt;&lt;br /&gt;TDD é uma disciplina de desenvolvimento, o seu conceito é bem simples, você cria o testa, o teste falha, você faz funcionar e refatora caso necessário. O famoso red, green, refactoring.&lt;br /&gt;Se você não desenvolve dessa forma você não esta utilizando TDD, isso não significa que você não esteja produzindo testes unitários, mas você não esta seguindo a disciplina de desenvolvimento.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;Uma das desvantagens mais levantadas contra a disciplina contida no TDD é referente ao tempo: &quot;Escrever testes e fazer falhar é muito demorado.&quot;. A parte ironica disso, é que não é uma reclamação dos gestores mas sim dos desenvolvedores.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;BDD é uma evolução do TDD, a quem diz que o TDD foi mal interpretado e que na verdade o BDD sempre existiu. &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;Com o BDD não é apenas testar, o BDD tem como finalidade documentar o código através de testes feitos com base em especificações contruídas a partir de contextos. &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;Se você acha o desenvolvimento com TDD é demorado o BDD talvez não ajude a mudar esse conceito.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;Bom, podemos ter teste unitário sem TDD e BDD, podemos desenvolver com TDD sem BDD e podemos escrever especificações conforme o BDD sem TDD, entretanto não podemos ter BDD ou TDD sem teste unitário.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;Se você vai utilizar TDD ou BDD o mais importante é ter os testes escritos e utilizando as melhores práticas da mesma forma que você escreve o código do produto final, pois com certeza, testes mal escritos são difíceis de entender e manter atualizados.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family:verdana;font-size:85%;&quot;&gt;Como você tem escrito seus testes?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;</content><link rel='replies' type='application/atom+xml' href='http://eduardodotnet.blogspot.com/feeds/1250276986217556071/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2490744060677162130/1250276986217556071' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/1250276986217556071'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/1250276986217556071'/><link rel='alternate' type='text/html' href='http://eduardodotnet.blogspot.com/2010/04/testes-unitario-x-tdd-x-bdd.html' title='Testes unitário x TDD x BDD'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/12442853817177091653</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2490744060677162130.post-614222608842164892</id><published>2010-03-13T13:48:00.001-08:00</published><updated>2010-03-13T13:48:05.642-08:00</updated><title type='text'>Pensando em ágil</title><content type='html'>&lt;p&gt;&lt;a href=&quot;http://lh3.ggpht.com/_4YU41vAO9bk/S5wIEdQdlRI/AAAAAAAAAX8/X1blt5ChVCg/s1600-h/150px-Rodin_The_Thinker_Laeken_cemetery%5B2%5D.jpg&quot;&gt;&lt;img style=&quot;border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px&quot; title=&quot;150px-Rodin_The_Thinker_Laeken_cemetery&quot; border=&quot;0&quot; alt=&quot;150px-Rodin_The_Thinker_Laeken_cemetery&quot; align=&quot;right&quot; src=&quot;http://lh3.ggpht.com/_4YU41vAO9bk/S5wIEwCLZEI/AAAAAAAAAYA/aeEcAZEQRb8/150px-Rodin_The_Thinker_Laeken_cemetery_thumb.jpg?imgmax=800&quot; width=&quot;154&quot; height=&quot;204&quot; /&gt;&lt;/a&gt; O quanto às metodologias ágeis são eficases? Essa é uma pergunta que todos com certeza já se fizeram a partir do momento que tiveram contato com elas.&lt;/p&gt;  &lt;p&gt;Mas realmente é muito complicado garantir que tais metodologias funcionam ou não. Mas eu ando bem desencanado com isso, Por quê?&lt;/p&gt;  &lt;p&gt;Por que já vi projetos ágeis falharem e terem sucesso, assim como já vi projetos cascata falharem e terem sucesso também.&lt;/p&gt;  &lt;p&gt;Ayende Rahien, o cara por trás do Rhino Mock, escreveu um &lt;a href=&quot;http://ayende.com/Blog/archive/2010/02/20/nice-process-but-what-about-the-engineering-bits.aspx&quot; target=&quot;_blank&quot;&gt;post&lt;/a&gt;&amp;#160; falando sobre metologias e sabe o que é engraçado? Nenhuma delas fala sobre engenharia de software.&lt;/p&gt;  &lt;p&gt;Uma vez fui questionado por um colega se eu gostava de XP e quando eu perguntei o porquê ele me falou: O projeto “xyz” foi feito com XP. O detalhe desse projeto em questão é que ele funciona, o cliente esta satisfeito de uma forma geral, mas tem um código horrível de dar manutenção. Por isso eu respondi: “Que culpa a qualidade do código tem de você utilizar XP?”.&lt;/p&gt;  &lt;p&gt;Não interessa que tipo de metodologia você utiliza, sem aplicar boas práticas de engenharia de software, boa arquitetura, bom profissionais, adivinha o que vai acontecer? &lt;/p&gt;  &lt;p&gt;Bom, mas o que tem realmente chamado a minha atenção e que me tem trazido bons resultados são algumas práticas contidas nas metodologias ágeis. Aqui vão algumas que tenho me atentado:&lt;/p&gt;  &lt;p&gt;1) Comece a desenvolver pelo que agrega maior valor ao negócio.&lt;/p&gt;  &lt;p&gt;Eu não sei com vocês, mas geralmente as funcionalidades que você tem que desenvolver que agregam maior valor ao negócio, ou seja, o que seu cliente mais precisa, também são as mais difíceis.&lt;/p&gt;  &lt;p&gt;Mas isso é bom, pois afeta diretamente o desenho do projeto, arquitetura, forma de comunicação entre outras coisas. &lt;/p&gt;  &lt;p&gt;Exemplo, no ramo de manufatura se a funcionalidade que agrega maior valor é a de ordem de produção, por que começar com cadastro de produtos? Ai você vai me questionar o seguinte: Mas você não precisa de produto para criar a ordem de produção? Sim, realmente vou precisar de produtos. Porém, nesse nosso cenário a tela de produto pode ser afetada por várias funcionalidades do nosso sistema (compras, por exemplo).&lt;/p&gt;  &lt;p&gt;Bom se eu sei que a tela de ordem de produção vai precisar de informações de produto, não é melhor eu colocar no produto somente as informações necessárias para gerar a ordem de produção?&lt;/p&gt;  &lt;p&gt;Perceba o seguinte, se você já desenvolveu tudo que as outras funcionalidades precisam de produto, a tela de produto só terá o necessário, nada a mais e nada a menos. Isso ajuda muito para evitar que você fique tendo retrabalho em funcionalidades que já estavam prontas por que precisa atender necessidades de outras funcionalidades.&lt;/p&gt;  &lt;p&gt;2) Revisão entre pares&lt;/p&gt;  &lt;p&gt;Eu ainda não tive a oportunidade de trabalhar em lugar que adota programação em pares, mas é uma realidade, se você tem uma pessoa te ajudando a desenvolver ou revisando algo que você já tenha feito as chances disso sair com sucesso aumentam, principalmente se a outra pessoa for mais experiente que você.&lt;/p&gt;  &lt;p&gt;3) Validação contínua com o cliente&lt;/p&gt;  &lt;p&gt;Tem pessoas que simplesmente tem pavor de validar uma funcionalidade com o cliente antes da entrega formal do projeto, por quê? E o se o cliente pedir alguma alteração?&lt;/p&gt;  &lt;p&gt;Ivar Jacobson diz o seguinte:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;&amp;quot;Todos os sistemas mudam durante o ciclo de vida. Isto deve estar na cabeça quando se desenvolve sistemas que se espera durar mais do que a primeira versão.&amp;quot;&lt;/em&gt;&lt;/p&gt;    &lt;p&gt;&lt;font size=&quot;1&quot;&gt;Obs.: Estou à procura da fonte onde ele disse essa frase, assim que eu encontrar eu atualizo o post.&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;Ou seja, a mudança é uma constante em nosso cotidiano podemos estar desenvolvendo novos produtos ou dando manutenção, o negócio é algo que vive evoluindo, a isso é devido a importância de construirmos softwares flexíveis o bastante para acompanhar essas mudanças.&lt;/p&gt;  &lt;p&gt;O que eu coloquei acima não é nenhuma novidade, se você conhecer o &lt;a href=&quot;http://agilemanifesto.org/&quot; target=&quot;_blank&quot;&gt;manifesto agile&lt;/a&gt; vai encontrar tudo isso e muito mais lá. Vale apena conhecer as práticas independente se você irá utilizá-las ou não.&lt;/p&gt;  </content><link rel='replies' type='application/atom+xml' href='http://eduardodotnet.blogspot.com/feeds/614222608842164892/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2490744060677162130/614222608842164892' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/614222608842164892'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/614222608842164892'/><link rel='alternate' type='text/html' href='http://eduardodotnet.blogspot.com/2010/03/pensando-em-agil.html' title='Pensando em ágil'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/12442853817177091653</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/_4YU41vAO9bk/S5wIEwCLZEI/AAAAAAAAAYA/aeEcAZEQRb8/s72-c/150px-Rodin_The_Thinker_Laeken_cemetery_thumb.jpg?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2490744060677162130.post-5702217395071653899</id><published>2010-02-23T16:46:00.001-08:00</published><updated>2010-02-26T02:33:26.415-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="arquitetura"/><category scheme="http://www.blogger.com/atom/ns#" term="DDD"/><category scheme="http://www.blogger.com/atom/ns#" term="Domain Driven Design"/><category scheme="http://www.blogger.com/atom/ns#" term="Domain Events"/><title type='text'>Domain Events</title><content type='html'>&lt;p&gt;Quando você utiliza DDD e começa a trabalhar com o modelo rico, você pode começar a se deparar com algumas situações que nem sempre é muito simples achar a melhor a solução, mas uma dessas soluções que você pode utilizar são os eventos de domínio (&lt;a href=&quot;http://martinfowler.com/eaaDev/DomainEvent.html&quot; target=&quot;_blank&quot;&gt;Domain Events&lt;/a&gt;).&lt;/p&gt;&lt;p&gt;Vamos imaginar o seguinte cenário: “Eu preciso cadastrar uma ordem de compra, que no momento da criação ela fica aguardando aprovação.”&lt;/p&gt;&lt;p&gt;Antes de adicionar algum tempero nesse cenário vamos começar a desenhar a classe:&lt;/p&gt;&lt;pre class=&quot;brush: csharp;&quot;&gt;namespace Domain.Entities&lt;br /&gt;{&lt;br /&gt;    public enum PurchaseOrderStateEnum&lt;br /&gt;    {&lt;br /&gt;        WaitingApproval,&lt;br /&gt;        Approval&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public class PurchaseOrder&lt;br /&gt;    {&lt;br /&gt;        public virtual int Id { get; private set; }&lt;br /&gt;        public virtual int OrderNumber { get; private set; }&lt;br /&gt;        public virtual PurchaseOrderStateEnum State { get; private set; }&lt;br /&gt;&lt;br /&gt;        protected PurchaseOrder() { }&lt;br /&gt;&lt;br /&gt;        public PurchaseOrder(int orderNumber)&lt;br /&gt;        {&lt;br /&gt;            OrderNumber = orderNumber;&lt;br /&gt;            State = PurchaseOrderStateEnum.WaitingApproval;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public virtual void Approval()&lt;br /&gt;        {&lt;br /&gt;            State = PurchaseOrderStateEnum.Approval;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;Agora vamos começar a adicionar os temperos: “Quando a ordem de aprovação for aprovada é necessário enviar um e-mail para o gestor da área de compas informando da aprovação da ordem.”&lt;/p&gt;&lt;p&gt;Bom nós já discutimos &lt;a href=&quot;http://eduardodotnet.blogspot.com/2009/09/ddd-enviar-e-mail-onde-vai-esse-negocio.html&quot; target=&quot;_blank&quot;&gt;aqui&lt;/a&gt; que enviar e-mail é algo que deve ser feito na camada de infraestrutura, e também sabemos que o domínio não pode depender da camada de infraestrutura, certo?&lt;/p&gt;&lt;p&gt;Uma possível solução para o problema poderia ser o seguinte:&lt;/p&gt;&lt;pre class=&quot;brush: csharp;&quot;&gt;public class PurchaseOrder&lt;br /&gt;{&lt;br /&gt;    public virtual ISendEmailBeforeApprovedPurchase SendEmailBeforeApprovedPurchase { get; private set; }&lt;br /&gt;    public virtual int Id { get; private set; }&lt;br /&gt;    public virtual int OrderNumber { get; private set; }&lt;br /&gt;    public virtual PurchaseOrderStateEnum State { get; private set; }&lt;br /&gt;&lt;br /&gt;    protected PurchaseOrder() { }&lt;br /&gt;&lt;br /&gt;    public PurchaseOrder(int orderNumber)&lt;br /&gt;    {&lt;br /&gt;        OrderNumber = orderNumber;&lt;br /&gt;        State = PurchaseOrderStateEnum.WaitingApproval;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public virtual void Approval()&lt;br /&gt;    {&lt;br /&gt;        State = PurchaseOrderStateEnum.Approval;&lt;br /&gt;      SendEmailBeforeApprovedPurchase.SendEmail(this);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public interface ISendEmailBeforeApprovedPurchase()&lt;br /&gt;{&lt;br /&gt;    void SendEmail(PurchaseOrder purchaseOrder);&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;Dessa forma podemos “injetar” o serviço de envio de e-mail através de um DI/IoC, mas como tudo nessa vida nada é perfeito, só Deus.&lt;/p&gt;&lt;p&gt;Como faríamos para implementar um segundo comportamento quando uma ordem compra fosse aprovada? Vamos ver como fazer isso com eventos de domínio:&lt;/p&gt;&lt;pre class=&quot;brush: csharp;&quot;&gt;public virtual void Approval()&lt;br /&gt;   {&lt;br /&gt;       State = PurchaseOrderStateEnum.Approval;&lt;br /&gt;       DomainEvents.Raise(new PurchaseOrderAprrovedEvent { PurchaseOrder = this });&lt;br /&gt;   }&lt;/pre&gt;&lt;p&gt;O que estamos fazendo é dizendo para o gerenciador de eventos de domínio que, quando o método Approval for chamado, o evento PurchaseOrderApprovedEvent deve ser disparado. Vamos analisar a estrutura do evento:&lt;/p&gt;&lt;pre class=&quot;brush: csharp;&quot;&gt;namespace Domain.Events&lt;br /&gt;{&lt;br /&gt;    public interface IDomainEvent { }&lt;br /&gt;&lt;br /&gt;    public class PurchaseOrderAprrovedEvent : IDomainEvent&lt;br /&gt;    {&lt;br /&gt;        public PurchaseOrder PurchaseOrder { get; set; }&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;Veja o código do gerenciador de eventos:&lt;/p&gt;&lt;pre class=&quot;brush: csharp;&quot;&gt;public static class DomainEvents&lt;br /&gt;{&lt;br /&gt;    [ThreadStatic] //so that each thread has its own callbacks&lt;br /&gt;    private static List&lt;delegate&gt; actions;&lt;br /&gt;&lt;br /&gt;    //Registers a callback for the given domain event&lt;br /&gt;    public static void Register&lt;t&gt;(Action&lt;t&gt; callback) where T : IDomainEvent&lt;br /&gt;    {&lt;br /&gt;        if (actions == null)&lt;br /&gt;            actions = new List&lt;delegate&gt;();&lt;br /&gt;        actions.Add(callback);&lt;br /&gt;    }&lt;br /&gt;    //Clears callbacks passed to Register on the current thread&lt;br /&gt;    public static void ClearCallbacks()&lt;br /&gt;    {&lt;br /&gt;        actions = null;&lt;br /&gt;    }&lt;br /&gt;    //Raises the given domain event&lt;br /&gt;    public static void Raise&lt;t&gt;(T args) where T : IDomainEvent&lt;br /&gt;    {&lt;br /&gt;        if (actions != null)&lt;br /&gt;            foreach (var action in actions)&lt;br /&gt;                if (action is Action&lt;t&gt;)&lt;br /&gt;                    ((Action&lt;t&gt;)action)(args);&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;Agora que disparamos o evento precisamos criar interessados em saber quando esse evento é disparado.&lt;/p&gt;&lt;pre class=&quot;brush: csharp;&quot;&gt;namespace Domain.Handles&lt;br /&gt;{&lt;br /&gt;    public interface IHandles&lt;t&gt; where T : IDomainEvent&lt;br /&gt;    {&lt;br /&gt;        void Handles(T args);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;namespace Infrastructure.Handles&lt;br /&gt;{&lt;br /&gt;    public class SendEmailBeforeApprovedPurchaseHandler : IHandles&lt;PurchaseOrderAprrovedEvent&gt;&lt;br /&gt;    {&lt;br /&gt;        public void Handles(PurchaseOrderAprrovedEvent args)&lt;br /&gt;        {&lt;br /&gt;            Console.WriteLine(&quot;mail sent successfully&quot;);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;Agora só precisamos adicionar “o interessado” na classe de gerenciamento de eventos de domínio para que ele seja notificado:&lt;/p&gt;&lt;pre class=&quot;brush: csharp;&quot;&gt;static void Main(string[] args)&lt;br /&gt;{&lt;br /&gt;    DomainEvents.Register&lt;PurchaseOrderAprrovedEvent&gt;(&lt;br /&gt;        new Action&lt;PurchaseOrderAprrovedEvent&gt;(delegate(PurchaseOrderAprrovedEvent evt)&lt;br /&gt;        {&lt;br /&gt;            new SendEmailBeforeApprovedPurchaseHandler().Handles(evt);&lt;br /&gt;        }));&lt;br /&gt;    var purchase = new PurchaseOrder(123456);&lt;br /&gt;    purchase.Approval();&lt;br /&gt;&lt;br /&gt;    Console.Read();&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;&lt;a href=&quot;http://lh6.ggpht.com/_4YU41vAO9bk/S4b8uSyeNvI/AAAAAAAAAX0/c99owB7XUs8/s1600-h/print12.png&quot;&gt;&lt;img style=&quot;BORDER-RIGHT-WIDTH: 0px; DISPLAY: inline; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px&quot; title=&quot;print 1&quot; border=&quot;0&quot; alt=&quot;print 1&quot; src=&quot;http://lh4.ggpht.com/_4YU41vAO9bk/S4b8vE7dyzI/AAAAAAAAAX4/k2hio8gXymo/print1_thumb.png?imgmax=800&quot; width=&quot;244&quot; height=&quot;125&quot; /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;Talvez você esteja pensando o seguinte: “Cara, consigo fazer a mesma coisa com mas de outro jeito.”. Com certeza existe outras formas de se chegar no mesmo resultado, mas vamos adicionar um pouco mais de tempero para ver o potencial dos eventos de domínio: “Ao aprovar uma ordem de compra, além de enviar o e-mail, eu preciso que um recebimento seja gerado com as mesmas informações da ordem de compra automaticamente.”.&lt;/p&gt;&lt;p&gt;Primeiramente vamos criar mais um “interessado” em saber que a ordem de compra foi aprovada.&lt;/p&gt;&lt;pre class=&quot;brush: csharp;&quot;&gt;public class GenerateReceiptFromPurchaseOrderApprovedHandler : IHandles&lt;PurchaseOrderAprrovedEvent&gt;&lt;br /&gt;{&lt;br /&gt;    public void Handles(PurchaseOrderAprrovedEvent args)&lt;br /&gt;    {&lt;br /&gt;        Console.WriteLine(&quot;Receipt order created.&quot;);&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;Agora basta apenas adicioná-lo ao gerenciador de eventos de domínio:&lt;/p&gt;&lt;pre class=&quot;brush: csharp;&quot;&gt;static void Main(string[] args)&lt;br /&gt;{&lt;br /&gt;    DomainEvents.Register&lt;PurchaseOrderAprrovedEvent&gt;(&lt;br /&gt;        new Action&lt;PurchaseOrderAprrovedEvent&gt;(delegate(PurchaseOrderAprrovedEvent evt)&lt;br /&gt;        {&lt;br /&gt;            new SendEmailBeforeApprovedPurchaseHandler().Handles(evt);&lt;br /&gt;        }));&lt;br /&gt;    DomainEvents.Register&lt;PurchaseOrderAprrovedEvent&gt;(&lt;br /&gt;        new Action&lt;PurchaseOrderAprrovedEvent&gt;(delegate(PurchaseOrderAprrovedEvent evt)&lt;br /&gt;        {&lt;br /&gt;            new GenerateReceiptFromPurchaseOrderApprovedHandler().Handles(evt);&lt;br /&gt;        }));&lt;br /&gt;    var purchase = new PurchaseOrder(123456);&lt;br /&gt;    purchase.Approval();&lt;br /&gt;    Console.Read();&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;Pronto, conseguimos adicionar mais umcomportamento ao processo de aprovação de ordem de compra sem a necessidade de alterar a classe, respeitando assim o &lt;a href=&quot;http://en.wikipedia.org/wiki/Open/closed_principle&quot; target=&quot;_blank&quot;&gt;OCP&lt;/a&gt;, e cada novo comportamento tem apenas uma única responsabilidade respeitando o &lt;a href=&quot;http://en.wikipedia.org/wiki/Single_responsibility_principle&quot; target=&quot;_blank&quot;&gt;SRP&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Mas perceba o ato de adicionar os interessado, esta sendo feito manualmente pra facilitar um puco podemos utilizar um DI/IoC para adiciona-los ao gerenciador de eventos. Vamos ver um exemplo com o &lt;a href=&quot;http://structuremap.sourceforge.net/Default.htm&quot; target=&quot;_blank&quot;&gt;StructureMap&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Precisamos fazer a seguinte alteração no gerenciador de eventos:&lt;/p&gt;&lt;pre class=&quot;brush: csharp;&quot;&gt;public static class DomainEvents&lt;br /&gt;{&lt;br /&gt;    [ThreadStatic] //so that each thread has its own callbacks&lt;br /&gt;    private static List&lt;delegate&gt; actions;&lt;br /&gt;&lt;br /&gt;    public static IContainer HandlesContainer { get; set; }&lt;br /&gt;&lt;br /&gt;    //Registers a callback for the given domain event&lt;br /&gt;    public static void Register&lt;t&gt;(Action&lt;t&gt; callback) where T : IDomainEvent&lt;br /&gt;    {&lt;br /&gt;        if (actions == null)&lt;br /&gt;            actions = new List&lt;delegate&gt;();&lt;br /&gt;        actions.Add(callback);&lt;br /&gt;    }&lt;br /&gt;    //Clears callbacks passed to Register on the current thread&lt;br /&gt;    public static void ClearCallbacks()&lt;br /&gt;    {&lt;br /&gt;        actions = null;&lt;br /&gt;    }&lt;br /&gt;    //Raises the given domain event&lt;br /&gt;    public static void Raise&lt;t&gt;(T args) where T : IDomainEvent&lt;br /&gt;    {&lt;br /&gt;        if (HandlesContainer != null)&lt;br /&gt;            foreach (var handler in HandlesContainer.GetAllInstances&lt;ihandles&gt;&lt;t&gt;&amp;gt;())&lt;br /&gt;                handler.Handles(args);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        if (actions != null)&lt;br /&gt;            foreach (var action in actions)&lt;br /&gt;                if (action is Action&lt;t&gt;)&lt;br /&gt;                    ((Action&lt;t&gt;)action)(args);&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;Agora vamos juntar tudo:&lt;/p&gt;&lt;pre class=&quot;brush: csharp;&quot;&gt;static void Main(string[] args)&lt;br /&gt;{&lt;br /&gt;  var container = new Container(x =&amp;gt;&lt;br /&gt;  {&lt;br /&gt; x.For&amp;lt;IHandles&amp;lt;PurchaseOrderAprrovedEvent&amp;gt;&amp;gt;().Add&amp;lt;SendEmailBeforeApprovedPurchaseHandler&amp;gt;();&lt;br /&gt; x.For&amp;lt;IHandles&amp;lt;PurchaseOrderAprrovedEvent&amp;gt;&amp;gt;().Add&amp;lt;GenerateReceiptFromPurchaseOrderApprovedHandler&amp;gt;();&lt;br /&gt;&lt;br /&gt;  });&lt;br /&gt;&lt;br /&gt;  DomainEvents.HandlesContainer = container;&lt;br /&gt;&lt;br /&gt;  var purchase = new PurchaseOrder(123456);&lt;br /&gt;  purchase.Approval();&lt;br /&gt;&lt;br /&gt;  Console.Read();&lt;br /&gt;&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;Legal né, mas no mundo real, quem faz uma alteração em uma entidade e não persiste no banco né? Como é que colocamos a persistencia no meio de tudo isso? &lt;/p&gt;&lt;p&gt;Vamos criar o repositório, pra isso vou utilizar o &lt;a href=&quot;http://fluentnhibernate.org/&quot; target=&quot;_blank&quot;&gt;Fluent NHibernate&lt;/a&gt;:&lt;/p&gt;&lt;pre class=&quot;brush: csharp;&quot;&gt;namespace Domain.Repositories&lt;br /&gt;{&lt;br /&gt;    public interface IPurchaseOrderRepository&lt;br /&gt;    {&lt;br /&gt;        void Save(PurchaseOrder purchaseOrder);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;namespace Infrastructure.Repositories.Mapping&lt;br /&gt;{&lt;br /&gt;    public class PurchaseOrderMap : ClassMap&lt;purchaseorder&gt;&lt;br /&gt;    {&lt;br /&gt;        public PurchaseOrderMap()&lt;br /&gt;        {&lt;br /&gt;            Id(x =&amp;gt; x.Id).GeneratedBy.Identity();&lt;br /&gt;            Map(x =&amp;gt; x.OrderNumber).Not.Nullable();&lt;br /&gt;            Map(x =&amp;gt; x.State);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;namespace Infrastructure.Repositories&lt;br /&gt;{&lt;br /&gt;    public class PurchaseOrderRepository : IPurchaseOrderRepository&lt;br /&gt;    {&lt;br /&gt;        private readonly ISession _session;&lt;br /&gt;        public PurchaseOrderRepository(ISession session)&lt;br /&gt;        {&lt;br /&gt;            _session = session;&lt;br /&gt;        }&lt;br /&gt;        public void Save(PurchaseOrder purchaseOrder)&lt;br /&gt;        {&lt;br /&gt;            _session.SaveOrUpdate(purchaseOrder);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;} &lt;/pre&gt;&lt;p&gt;Vamos salvar a ordem de compra após realizar a aprovação:&lt;/p&gt;&lt;pre class=&quot;brush: csharp;&quot;&gt;static void Main(string[] args)&lt;br /&gt;{&lt;br /&gt;    Configuration configuration = null;&lt;br /&gt;&lt;br /&gt;    var sessionFactory = Fluently.Configure()&lt;br /&gt;        .Database(SQLiteConfiguration.Standard.InMemory().ShowSql())&lt;br /&gt;        .Mappings(M =&amp;gt; M.FluentMappings.AddFromAssembly(typeof(PurchaseOrderRepository).Assembly))&lt;br /&gt;        .ExposeConfiguration(c =&amp;gt; configuration = c)&lt;br /&gt;        .BuildSessionFactory();&lt;br /&gt;&lt;br /&gt;    var container = new Container(x =&amp;gt;&lt;br /&gt;    {&lt;br /&gt;        x.For&lt;ihandles&gt;&lt;PurchaseOrderAprrovedEvent&gt;&amp;gt;().Add&lt;sendemailbeforeapprovedpurchasehandler&gt;();&lt;br /&gt;        x.For&lt;ihandles&gt;&lt;PurchaseOrderAprrovedEvent&gt;&amp;gt;().Add&lt;generatereceiptfrompurchaseorderapprovedhandler&gt;();&lt;br /&gt;&lt;br /&gt;        x.For&lt;isessionfactory&gt;().Singleton().Use(sessionFactory);&lt;br /&gt;        x.For&lt;isession&gt;().Singleton().Use(s =&amp;gt; s.GetInstance&lt;isessionfactory&gt;().OpenSession());&lt;br /&gt;        x.For&lt;ipurchaseorderrepository&gt;().Use&lt;purchaseorderrepository&gt;();&lt;br /&gt;    });&lt;br /&gt;&lt;br /&gt;    DomainEvents.HandlesContainer = container;&lt;br /&gt;&lt;br /&gt;    BuildSchema(configuration, container.GetInstance&lt;isession&gt;());&lt;br /&gt;&lt;br /&gt;    var purchase = new PurchaseOrder(123456);&lt;br /&gt;    purchase.Approval();&lt;br /&gt;    var repository = container.GetInstance&lt;ipurchaseorderrepository&gt;();&lt;br /&gt;    repository.Save(purchase);&lt;br /&gt;&lt;br /&gt;    Console.Read();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public static void BuildSchema(Configuration cfg, ISession se)&lt;br /&gt;{&lt;br /&gt;    SchemaExport export = new SchemaExport(cfg);&lt;br /&gt;    export.Execute(true, true, false, se.Connection, null);&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class NHibernateTestRegistry : Registry&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;    public static Configuration cfg;&lt;br /&gt;&lt;br /&gt;    public NHibernateTestRegistry()&lt;br /&gt;    {&lt;br /&gt;        Configuration configuration = null;&lt;br /&gt;&lt;br /&gt;        var sessionFactory = Fluently.Configure()&lt;br /&gt;            .Database(SQLiteConfiguration.Standard.InMemory().ShowSql())&lt;br /&gt;            .Mappings(M =&amp;gt; M.FluentMappings.AddFromAssembly(typeof(PurchaseOrderRepository).Assembly))&lt;br /&gt;            .ExposeConfiguration(c =&amp;gt; configuration = c)&lt;br /&gt;            .BuildSessionFactory();&lt;br /&gt;&lt;br /&gt;        For&lt;isessionfactory&gt;().Singleton().Use(sessionFactory);&lt;br /&gt;        For&lt;isession&gt;().Use(x =&amp;gt; x.GetInstance&lt;isessionfactory&gt;().OpenSession());&lt;br /&gt;        For&lt;ipurchaseorderrepository&gt;().Use&lt;purchaseorderrepository&gt;();&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;p&gt;Concluindo: Eventos de domínio é uma grande solução para manter a sua arquitetura saudavel. Podemos incorporar vários comportamentos a uma determinada ação que ocorre em um objeto do domínio sem ter que alterá-lo, com certeza vale a pena tê-lo como uma carta na manga.&lt;/p&gt;&lt;p&gt;Fontes:&lt;/p&gt;&lt;p&gt;&lt;a title=&quot;http://www.udidahan.com/2009/06/14/domain-events-salvation/&quot; href=&quot;http://www.udidahan.com/2009/06/14/domain-events-salvation/&quot;&gt;http://www.udidahan.com/2009/06/14/domain-events-salvation/&lt;/a&gt;&lt;br /&gt;&lt;a title=&quot;http://martinfowler.com/eaaDev/DomainEvent.html&quot; href=&quot;http://martinfowler.com/eaaDev/DomainEvent.html&quot;&gt;http://martinfowler.com/eaaDev/DomainEvent.html&lt;/a&gt;&lt;br /&gt;&lt;a title=&quot;http://unplugged.giggio.net/unplugged/post/Domain-Events.aspx&quot; href=&quot;http://unplugged.giggio.net/unplugged/post/Domain-Events.aspx&quot;&gt;http://unplugged.giggio.net/unplugged/post/Domain-Events.aspx&lt;/a&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://eduardodotnet.blogspot.com/feeds/5702217395071653899/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2490744060677162130/5702217395071653899' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/5702217395071653899'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/5702217395071653899'/><link rel='alternate' type='text/html' href='http://eduardodotnet.blogspot.com/2010/02/domain-events.html' title='Domain Events'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/12442853817177091653</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/_4YU41vAO9bk/S4b8vE7dyzI/AAAAAAAAAX4/k2hio8gXymo/s72-c/print1_thumb.png?imgmax=800" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-2490744060677162130.post-7486190884204712319</id><published>2010-02-03T01:51:00.001-08:00</published><updated>2010-02-03T12:35:28.185-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="arquitetura"/><category scheme="http://www.blogger.com/atom/ns#" term="ASP.NET"/><category scheme="http://www.blogger.com/atom/ns#" term="boas práticas"/><category scheme="http://www.blogger.com/atom/ns#" term="design"/><category scheme="http://www.blogger.com/atom/ns#" term="programação"/><title type='text'>Boas Práticas para interface</title><content type='html'>&lt;p&gt;Eu ja havia levantado a bandeira sobre qualidade e organização de código na camada de interface &lt;a href=&quot;http://eduardodotnet.blogspot.com/2009/09/boas-praticas-tambem-serve-para-camada.html&quot;&gt;aqui&lt;/a&gt; no blog, e tenho percebido que a comunidade tem desprendido um grande esforço nesse sentido também. &lt;/p&gt;  &lt;p&gt;O Jeremy D. Miller publicou no seu blog uma série de posts sobre melhores práticas na elaboração de interface: &lt;/p&gt;  &lt;p&gt;&lt;strong&gt;The Build Your Own CAB Series Table of Contents &lt;/strong&gt;  &lt;br /&gt;&lt;a href=&quot;http://codebetter.com/blogs/jeremy.miller/archive/2007/07/25/the-build-your-own-cab-series-table-of-contents.aspx&quot;&gt;http://codebetter.com/blogs/jeremy.miller/archive/2007/07/25/the-build-your-own-cab-series-table-of-contents.aspx&lt;/a&gt;  &lt;br /&gt;&lt;a href=&quot;http://www.jeremydmiller.com/ppatterns/(X(1)S(x4of0b450vkpvp454kqddkvw))/default.aspx?AspxAutoDetectCookieSupport=1&quot;&gt;http://www.jeremydmiller.com/ppatterns/(X(1)S(x4of0b450vkpvp454kqddkvw))/default.aspx?AspxAutoDetectCookieSupport=1&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Já temos também vários recursos para facilitar a nossa vida: &lt;strong&gt;ASP.Net MVC Framework&lt;/strong&gt;  &lt;br /&gt;&lt;a href=&quot;http://www.asp.net/%28S%28d35rmemuuono1wvm1gsp2n45%29%29/mvc/&quot;&gt;http://www.asp.net/%28S%28d35rmemuuono1wvm1gsp2n45%29%29/mvc/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;E para quem tem o Visual Studio temos também: &lt;br /&gt;&lt;strong&gt;Web Client Developer Guidance&lt;/strong&gt;  &lt;br /&gt;&lt;a href=&quot;http://www.codeplex.com/webclientguidance&quot;&gt;http://www.codeplex.com/webclientguidance&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Composite WPF and Silverlight&lt;/strong&gt;  &lt;br /&gt;http://www.codeplex.com/CompositeWPF&lt;/p&gt;&lt;p&gt;Se o grande problema para se utilizar as boas práticas era a perca de produtividade, já faz algum tempo que esse argumento não cola a mais.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://eduardodotnet.blogspot.com/feeds/7486190884204712319/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment/fullpage/post/2490744060677162130/7486190884204712319' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/7486190884204712319'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/2490744060677162130/posts/default/7486190884204712319'/><link rel='alternate' type='text/html' href='http://eduardodotnet.blogspot.com/2010/02/boas-praticas-para-interface.html' title='Boas Práticas para interface'/><author><name>Anonymous</name><uri>http://www.blogger.com/profile/12442853817177091653</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='https://img1.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>