<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10portuguesefull.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="br"><title type="text">tucaz.blog.now()</title><link rel="alternate" type="text/html" href="http://blog.tucaz.net" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/tucaz" /><subtitle type="html">Software architecture, agile and all that stuff that you can find everywhere</subtitle><updated>2011-01-11T21:00:29+00:00</updated><generator>http://wordpress.org/?v=2.9.1</generator><sy:updatePeriod xmlns:sy="http://purl.org/rss/1.0/modules/syndication/">hourly</sy:updatePeriod><sy:updateFrequency xmlns:sy="http://purl.org/rss/1.0/modules/syndication/">1</sy:updateFrequency><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/tucaz" /><feedburner:info uri="tucaz" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><link rel="license" type="text/html" href="http://creativecommons.org/licenses/by-sa/3.0/" /><feedburner:emailServiceId>tucaz</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><feedburner:feedFlare href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Ffeeds.feedburner.com%2Ftucaz" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Ftucaz" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://feeds.my.aol.com/add.jsp?url=http%3A%2F%2Ffeeds.feedburner.com%2Ftucaz" src="http://o.aolcdn.com/favorites.my.aol.com/webmaster/ffclient/webroot/locale/en-US/images/myAOLButtonSmall.gif">Subscribe with My AOL</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://feeds.feedburner.com/tucaz" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.feedburner.com%2Ftucaz" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2Ftucaz" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2Ftucaz" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><entry><title type="text">Começando a aprender F# com: Ubuntu, Mono e Vim</title><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tucaz/~3/_-znBnQ2bMo/" /><category term=".NET" /><category term="Desenvolvimento" /><category term="FSharp" /><category term="Linux" /><category term="Vim" /><category term="F#" /><category term="fp" /><category term="functional programming" /><category term="mono" /><category term="ubuntu" /><category term="vi" /><author><name>tucaz</name></author><updated>2011-01-10T16:58:47-08:00</updated><id>http://blog.tucaz.net/?p=479</id><summary type="html">Já faz algum tempo que estou meio de saco cheio de desenvolvimento comercial tradicional que a maioria de nós, desenvolvedores, está acostumado a fazer. De uma forma ou de outra, exceto em projetos excepcionais tudo é uma variação de CRUD o que é um pé no saco pra quem gosta de código. Chega uma hora [...]</summary><content type="html">&lt;p&gt;Já faz algum tempo que estou meio de saco cheio de desenvolvimento comercial tradicional que a maioria de nós, desenvolvedores, está acostumado a fazer. De uma forma ou de outra, exceto em projetos excepcionais tudo é uma variação de CRUD o que é um pé no saco pra quem gosta de código. Chega uma hora que a gente começa a procurar maneiras diferentes (não necessariamente melhores) de fazer a mesma coisa só pra acabar com o tédio. Isso estava me incomodando.&lt;/p&gt;
&lt;p&gt;Há alguns meses quando este sentimento veio novamente decidi que iria tentar algo diferente. Foi ai que comecei com o combo título deste post. Uma mudança radical de ares.&lt;/p&gt;
&lt;p&gt;Não sou o primeiro e com certeza não serei o último.&lt;/p&gt;
&lt;p&gt;Apesar de trabalhar com Windows e depender dele pro meu ganha pão adotei o Ubuntu como sistema operacional padrão deixando o Windows em uma VM &lt;strong&gt;[1]&lt;/strong&gt; apenas para trabalho e comecei a estudar F# que é uma linguagem com paradigma funcional que é completamente diferente de C#, Java e parentes próximos. Não bastasse a mudança de sistema operacional e de paradigma decidi também aprender mais a respeito de shell e editores de texto pra me livrar mais ainda dos atalhos que uma IDE como o VS proporcionam e adotei o VIM como editor de texto.&lt;/p&gt;
&lt;p&gt;Nest post vou mostrar como montar um ambiente como o meu e os primeiros (primeiros mesmo, nada avançado) passos nessa estrada de aprendizado. Se tudo der certo e eu não desistir transformo numa série pra poder compartilhar meu aprendizado e com a colaboração de vocês aprender mais sobre o assunto.&lt;/p&gt;
&lt;p&gt;Tudo que estou fazendo é no Ubuntu 10.10, mas deve funcionar com uma boa parte dos *nix por ai.&lt;/p&gt;
&lt;h3&gt;Instalando F# com Mono&lt;/h3&gt;
&lt;p&gt;Provavelmente o Linux que você tem instalado já deve ter o mono instalado, portanto não precisamos nos preocupar com esta etapa. De qualquer forma, só pra garantir abra o shell (Terminal) veja se você está realmente como o Mono instalado e qual sua versão:&lt;/p&gt;
&lt;pre class="shell" name="code"&gt;mono -V&lt;/pre&gt;
&lt;p&gt;Se tudo estiver certo teremos algo parecido com isso:&lt;/p&gt;
&lt;pre class="bash" name="code"&gt;Mono JIT compiler version 2.6.7 (Debian 2.6.7-3ubuntu1)
Copyright (C) 2002-2010 Novell, Inc and Contributors. www.mono-project.com
    TLS:           __thread
    GC:            Included Boehm (with typed GC and Parallel Mark)
    SIGSEGV:       altstack
    Notifications: epoll
    Architecture:  amd64
    Disabled:      none&lt;/pre&gt;
&lt;p&gt;Caso ele não esteja instalado basta ir ao Ubuntu Software Center &lt;strong&gt;[2] &lt;/strong&gt;para instalá-lo ou &lt;a title="Mono Downloads" href="http://www.go-mono.com/mono-downloads/download.html"&gt;baixá-lo no site oficial&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Com Mono instalado corretamente e acessível de qualquer lugar precisamos agora baixar a última versão disponível da biblioteca e compilador FSharp. Temos três opções para a instalação: &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Efetuar o download do código fonte, compilá-lo e efetuar a instalação &lt;/li&gt;
&lt;li&gt;Baixar um &lt;a href="http://fsxplat.codeplex.com/"&gt;pacote cross-platform&lt;/a&gt; que faz a instalação de tudo &lt;/li&gt;
&lt;li&gt;Baixar o pacote oficial compilado, efetuar a instalação e configurar as variáveis de ambiente “manualmente” &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Vamos com a terceira opção, pra ver onde vai cada coisa e como cada um dos executáveis funciona.&lt;/p&gt;
&lt;p&gt;A última versão disponível no momento deste post é a 2.0.0.0 de Novembro de 2010.&lt;/p&gt;
&lt;p&gt;Como somos usuários ninjas de Linux vamos efetuar o download via linha de comando com &lt;a href="http://www.gnu.org/software/wget/"&gt;wget&lt;/a&gt;.&lt;/p&gt;
&lt;pre class="bash" name="code"&gt;wget http://download.microsoft.com/download/4/5/B/45BD9FBC-22BA-4B45-84B7-17D1AD0122A1/fsharp.zip&lt;/pre&gt;
&lt;p&gt;Terminado o download, um pacote zip, extraimos todo o conteúdo pra uma pasta qualquer.&lt;/p&gt;
&lt;pre class="bash" name="code"&gt;unzip fsharp.zip&lt;/pre&gt;
&lt;p&gt;Agora devemos ter todo o conteúdo do zip extraido em uma pasta chamada &lt;em&gt;FSharp-2.0.0.0&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Antes de instalar sugiro mover a pasta com o conteúdo extraido do zip para um local mais apropriado para este tipo de arquivos já que é a partir desta pasta que iremos fazer referência mais pra frente aos executáveis do FSharp. Eu utilizo &lt;em&gt;/usr/lib/ &lt;/em&gt;&lt;strong&gt;[3]&lt;/strong&gt;. Além de mover, vamos renomear a pasta de destino apenas para fsharp a fim de deixar tudo mais simples.&lt;/p&gt;
&lt;pre class="bash" name="code"&gt;sudo mv FSharp-2.0.0.0/ /usr/lib/fsharp/
cd /usr/lib/fsharp/&lt;/pre&gt;
&lt;p&gt;Agora para instalar basta executar:&lt;/p&gt;
&lt;pre class="bash" name="code"&gt;cd fsharp
sudo sh install-mono.sh&lt;/pre&gt;
&lt;p&gt;Este comando provavelmente retornará um erro indicando que a DLL não pôde ser adicionada ao GAC por conta de seu strongname. O que acontece é que a versão compilada que baixamos está com uma assinatura para o .NET Framework do Windows então antes de conseguir instalar o FSharp no Mono devemos baixar um &lt;a title="mono.snk @ GitHub" href="https://github.com/mono/mono/raw/master/mcs/class/mono.snk"&gt;arquivo.snk&lt;/a&gt; próprio para ele e ai sim executar novamente o setup.&lt;/p&gt;
&lt;pre class="bash" name="code"&gt;wget -O mono.snk https://github.com/mono/mono/raw/master/mcs/class/mono.snk --no-check-certificate
sudo sh install-mono.sh&lt;/pre&gt;
&lt;p&gt;Dando tudo certo, devemos receber uma mensagem de sucesso:&lt;/p&gt;
&lt;pre class="bash" name="code"&gt;-- Resigning FSharp.Core.dll with mono.snk
Assembly bin/FSharp.Core.dll signed.
-- Installing FSharp DLLS into the GAC
Installed bin/FSharp.Core.dll into the gac (/usr/lib/mono/gac)&lt;/pre&gt;
&lt;p&gt;Pra testar se tudo der certo, ainda de dentro do diretório onde instalamos o FSharp, podemos executar:&lt;/p&gt;
&lt;pre class="bash" name="code"&gt;mono bin\fsi.exe&lt;/pre&gt;
&lt;p&gt;Se tudo estiver OK vamos entrar no FSharp Interactive que é uma console &lt;a title="REPL @ Wikipedia" href="http://en.wikipedia.org/wiki/Read-eval-print_loop"&gt;REPL&lt;/a&gt; pra F# muito legal:&lt;/p&gt;
&lt;pre class="bash" name="code"&gt;Microsoft (R) F# 2.0 Interactive build 2.0.0.0
Copyright (c) Microsoft Corporation. All Rights Reserved.

For help type #help;;

&amp;gt; &lt;/pre&gt;
&lt;p&gt;Podemos também fazer o tradicional “Hello World”:&lt;/p&gt;
&lt;pre class="bash" name="code"&gt;&amp;gt; printfn &amp;quot;Hello World!&amp;quot;;;
Hello World!
val it : unit = ()&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Pronto! &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Tecnicamente temos o FSharp instalado com sucesso e pronto para usar. No entanto, tanto o compilador (fsc.exe) e o REPL (fsi.exe) não fazem parte do PATH configurado em nosso Linux. Desta forma, ele está apenas acessível a partir do diretório onde está localizado.&lt;/p&gt;
&lt;p&gt;Pra resolver isso vamos baixar o pacote de ferramentas adicionais para FSharp que irá nos prover algums aliases que permitirão o acesso as ferramentas a partir de qualquer diretório.&lt;/p&gt;
&lt;p&gt;Dessa vez, como este pacote está hospedado no Codeplex, temos que efetuar o download do pacote “Additional scripts and tools only (.tgz archive)” manualmente localizado em &lt;a title="http://fsxplat.codeplex.com/releases/view/55463" href="http://fsxplat.codeplex.com/releases/view/55463"&gt;http://fsxplat.codeplex.com/releases/view/55463&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Feito o download podemos voltar ao nosso querido shell e instalar o pacote de bonus.&lt;/p&gt;
&lt;pre class="bash" name="code"&gt;cd ~/Downloads
mkdir fsharp-bonus
tar -xvzf fsharp-bonus.tgz -C fsharp-bonus
cd fsharp-bonus
sudo bash install-bonus.sh&lt;/pre&gt;
&lt;p&gt;Este script de instalação espera que as DLLs do FSharp estejam na pasta &lt;em&gt;/usr/lib/fsharp. &lt;/em&gt;No entanto, no nosso caso elas se encontram em &lt;em&gt;/usr/lib/fsharp/bin&lt;/em&gt;, portanto caso o script solicite esta informação, fica fácil de prover. &lt;img src='http://blog.tucaz.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /&gt; &lt;/p&gt;
&lt;p&gt;Feito isso é hora de testar e já podemos chamar &lt;em&gt;fsharpi&lt;/em&gt; de qualquer lugar no shell:&lt;/p&gt;
&lt;pre class="bash" name="code"&gt;tucaz@tucaz-nb:~$ fsharpi

Microsoft (R) F# 2.0 Interactive build 2.0.0.0
Copyright (c) Microsoft Corporation. All Rights Reserved.

For help type #help;;

&amp;gt; &lt;/pre&gt;
&lt;p&gt;Agora podemos chamar tanto o REPL quanto o compilador a partir de qualquer diretório já que os alias foram devidamente criados e adicionados ao PATH.&lt;/p&gt;
&lt;h3&gt;Primeiro Hello World com Vim&lt;/h3&gt;
&lt;p&gt;Agora que temos todo o ambiente instalado (o que na minha opinião é um dos primeiros grandes obstáculos no aprendizado de uma nova linguagem) podemos fazer nosso primeiro Hello World e gerar uma DLL .NET com F#!&lt;/p&gt;
&lt;p&gt;Primeiro, vamos definir um diretório de trabalho onde vamos colocar todos nossos projetos. Eu costumo usar um diretório chamado &lt;em&gt;Workspace&lt;/em&gt; dentro do meu profile:&lt;/p&gt;
&lt;pre class="bash" name="code"&gt;cd ~
mkdir Workspace
cd Workspace
mkdir HelloWorldFSharp
cd HelloWorldFSharp&lt;/pre&gt;
&lt;p&gt;Criado o diretório, criamos também nosso primeiro arquivo com código fonte FSharp utilizando o Vim &lt;strong&gt;[4]&lt;/strong&gt;:&lt;/p&gt;
&lt;pre class="bash" name="code"&gt;vim HelloWorldFSharp.fs&lt;/pre&gt;
&lt;p&gt;Isso cria um arquivo chamado HelloWorldFSharp.fs (assumindo que um não exista ou abre para edição caso ele exista) e o abre no nosso editor de texto funcionando dentro de um terminal shell, que pra um usuário Windows (que não tenha usado o Edit do DOS) é algo geralmente desconhecido.&lt;/p&gt;
&lt;p&gt;O Vim (como o Vi) oferece basicamente dois modos de trabalho: modo de comando e edição/inserção de texto. Quando abrimos um arquivo, por padrão temos o modo de comando onde o texto digitado não é o que vai para o arquivo, mas sim interpretado como um comando (a seguir).&lt;/p&gt;
&lt;p&gt;Para entrar no modo de edição de texto digitamos &lt;em&gt;i&lt;/em&gt; ou apertamos a tecla &lt;em&gt;insert&lt;/em&gt; do teclado. Note que o texto &amp;#8211;INSERT&amp;#8211; irá aparecer no canto esquerdo inferior da tela indicando que agora estamos no modo de inserção de texto. Esta área é destinada aos comandos e mensagens do editor.&lt;/p&gt;
&lt;p&gt;Estando no modo de edição vamos escrever nosso Hello World!&lt;/p&gt;
&lt;pre class="fsharp" name="code"&gt;#light 

printfn &amp;quot;Hello World!&amp;quot;&lt;/pre&gt;
&lt;p&gt;Com “todo” nosso código completo vamos sair do modo de edição (e voltar ao modo comando) apertando &lt;em&gt;ESC. &lt;/em&gt;Para salvar e sair digitamos o comando :wq (write and quit) e enter retornando ao terminal.&lt;/p&gt;
&lt;p&gt;Pra compilar nosso código fonte e gerar o primeiro .exe no Linux:&lt;/p&gt;
&lt;pre class="bash" name="code"&gt;fsharpc HelloWorldFSharp.fs&lt;/pre&gt;
&lt;p&gt;Obtendo a resposta:&lt;/p&gt;
&lt;pre class="bash" name="code"&gt;Microsoft (R) F# 2.0 Compiler build 2.0.0.0
Copyright (c) Microsoft Corporation. All Rights Reserved.
tucaz@tucaz-nb:~/Workspace/HelloWorldFSharp$ ls
HelloWorldFSharp.exe  HelloWorldFSharp.fs
tucaz@tucaz-nb:~/Workspace/HelloWorldFSharp$ &lt;/pre&gt;
&lt;p&gt;E por último, vamos executar nosso primeiro programa .NET em Linux:&lt;/p&gt;
&lt;pre class="bash" name="code"&gt;mono HelloWorldFSharp.exe
Hello World!&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Fim!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Neste post vimos como instalar Mono/F# no Linux e como criar nosso primeiro programa Hello World em F# utilizando o Vim. No próximo, quero começar a falar mais a respeito de F# e Vim e deixar para trás&lt;strong&gt;&amp;#160;&lt;/strong&gt;questões de ambiente.&lt;/p&gt;
&lt;p&gt;Até lá!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;[1] – &lt;/strong&gt;Estou utilizando Ubuntu 10.10 AMD64 rodando em um notebook Core i7 (2.66ghz) com 6gb de memória RAM sendo que 2gb ficam exclusivos para VM rodando no Virtual Box. A performance é ótima!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;[2] – &lt;/strong&gt;Menu Principal –&amp;gt; Applications –&amp;gt; Ubuntu Software Center&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;[3] –&lt;/strong&gt; Alguma outra sugestão?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;[4]&lt;/strong&gt; – Se o Vim não estiver instalado, basta executar “sudo apt-get install vim” para instalá-lo&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=_-znBnQ2bMo:H0wyJRyBaww:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=_-znBnQ2bMo:H0wyJRyBaww:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?i=_-znBnQ2bMo:H0wyJRyBaww:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=_-znBnQ2bMo:H0wyJRyBaww:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=_-znBnQ2bMo:H0wyJRyBaww:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?i=_-znBnQ2bMo:H0wyJRyBaww:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=_-znBnQ2bMo:H0wyJRyBaww:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tucaz/~4/_-znBnQ2bMo" height="1" width="1"/&gt;</content><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.tucaz.net/2011/01/10/comeando-a-aprender-f-com-ubuntu-mono-e-vim/feed/</wfw:commentRss><slash:comments xmlns:slash="http://purl.org/rss/1.0/modules/slash/">7</slash:comments><feedburner:origLink>http://blog.tucaz.net/2011/01/10/comeando-a-aprender-f-com-ubuntu-mono-e-vim/</feedburner:origLink></entry><entry><title type="text">Lendo e consumindo XML com dynamic em C# 4</title><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tucaz/~3/jL71inMiRF8/" /><category term=".NET" /><category term="C#" /><author><name>tucaz</name></author><updated>2010-11-18T15:57:30-08:00</updated><id>http://blog.tucaz.net/?p=474</id><summary type="html">Sei que faz tempo que não posto então aqui vai um post rápido, mas com conteúdo (espero que vocês vejam dessa forma também). Finalmente comecei a trabalhar efetivamente com C# 4 e por coincidência (ou não) já precisei de dynamic objects pra resolver um problema.
Meu sistema recebe como entrada alguns arquivos XML para serem processados [...]</summary><content type="html">&lt;p&gt;Sei que faz tempo que não posto então aqui vai um post rápido, mas com conteúdo (espero que vocês vejam dessa forma também). Finalmente comecei a trabalhar efetivamente com C# 4 e por coincidência (ou não) já precisei de dynamic objects pra resolver um problema.&lt;/p&gt;
&lt;p&gt;Meu sistema recebe como entrada alguns arquivos XML para serem processados e transformados em outros objetos posteriormente. XML é um saco e é definitivamente uma das coisas que eu mais odeio em desenvolvimento de software. Tudo com XML é trabalhoso. Sendo assim criei uma pequena Lib que transforma XML em objetos dinamicos pra eliminar a necessidade de lidar com nós e atributos diretamentes e também permitir futuras implementacões.&lt;/p&gt;
&lt;p&gt;Com XmlToObjectParser é possível:&lt;/p&gt;
&lt;pre class="xml" name="code"&gt;
&amp;lt;?xml version="1.0" encoding="ISO-8859-1"?&amp;gt;
&amp;lt;catalog&amp;gt;
  &amp;lt;cd country="USA"&amp;gt;
    &amp;lt;title&amp;gt;Empire Burlesque&amp;lt;/title&amp;gt;
    &amp;lt;artist&amp;gt;Bob Dylan&amp;lt;/artist&amp;gt;
    &amp;lt;price&amp;gt;10.90&amp;lt;/price&amp;gt;
  &amp;lt;/cd&amp;gt;
  &amp;lt;cd country="UK"&amp;gt;
    &amp;lt;title&amp;gt;Hide your heart&amp;lt;/title&amp;gt;
    &amp;lt;artist&amp;gt;Bonnie Tyler&amp;lt;/artist&amp;gt;
    &amp;lt;price&amp;gt;10.0&amp;lt;/price&amp;gt;
  &amp;lt;/cd&amp;gt;
  &amp;lt;cd country="USA"&amp;gt;
    &amp;lt;title&amp;gt;Greatest Hits&amp;lt;/title&amp;gt;
    &amp;lt;artist&amp;gt;Dolly Parton&amp;lt;/artist&amp;gt;
    &amp;lt;price&amp;gt;9.90&amp;lt;/price&amp;gt;
  &amp;lt;/cd&amp;gt;
&amp;lt;/catalog&amp;gt;
&lt;/pre&gt;
&lt;pre class="csharp" name="code"&gt;
var numberOfCDsinCatalog = catalog.catalog.cd.Count; //Retorna 3
var titleFromUKCD = catalog.catalog.cd[1].title; // Retorna "Hide your heart"
&lt;/pre&gt;
&lt;p&gt;Bem mais legível e prático de usar, na minha opinião.&lt;/p&gt;
&lt;p&gt;O &lt;a href="https://github.com/tucaz/XmlToObjectParser"&gt;projeto&lt;/a&gt; e a &lt;a href="https://github.com/downloads/tucaz/XmlToObjectParser/XmlToObjectParser-1.0.zip"&gt;DLL compilada&lt;/a&gt; estão no GitHub assim como a &lt;a href="https://github.com/tucaz/XmlToObjectParser/wiki/Getting-Started"&gt;documentacão e informacões adicionais&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Enjoy! &lt;img src='http://blog.tucaz.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /&gt; &lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=jL71inMiRF8:fcUkQR5-K2k:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=jL71inMiRF8:fcUkQR5-K2k:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?i=jL71inMiRF8:fcUkQR5-K2k:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=jL71inMiRF8:fcUkQR5-K2k:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=jL71inMiRF8:fcUkQR5-K2k:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?i=jL71inMiRF8:fcUkQR5-K2k:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=jL71inMiRF8:fcUkQR5-K2k:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tucaz/~4/jL71inMiRF8" height="1" width="1"/&gt;</content><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.tucaz.net/2010/11/18/lendo-e-consumindo-xml-com-dynamic-em-c-4/feed/</wfw:commentRss><slash:comments xmlns:slash="http://purl.org/rss/1.0/modules/slash/">4</slash:comments><feedburner:origLink>http://blog.tucaz.net/2010/11/18/lendo-e-consumindo-xml-com-dynamic-em-c-4/</feedburner:origLink></entry><entry><title type="text">Performance: NHibernate versus ADO.NET</title><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tucaz/~3/Mbh8HP8uQuA/" /><category term="Banco de Dados" /><category term="C#" /><category term="NHibernate" /><category term="adhoc" /><category term="ADO.NET" /><category term="cache" /><category term="performance" /><category term="stored procedures" /><author><name>tucaz</name></author><updated>2010-08-31T18:18:21-07:00</updated><id>http://blog.tucaz.net/?p=466</id><summary type="html">Disclaimer
Os testes neste post apresentados não representam uma amostra exata ou fidedigna que represente uma condição real de acesso a dados de uma aplicação a fim de comparar a performance das duas tecnologias. A idéia é apenas mostrar alguns dados e exemplos com o objetivo de dismistificar a idéia de que ORM é uma ferramenta [...]</summary><content type="html">&lt;h1&gt;&lt;em&gt;&lt;span style="color: #ff0000"&gt;Disclaimer&lt;/span&gt;&lt;/em&gt;&lt;/h1&gt;
&lt;p&gt;&lt;em&gt;&lt;span style="color: #ff0000"&gt;Os testes neste post apresentados não representam uma amostra exata ou fidedigna que represente uma condição real de acesso a dados de uma aplicação a fim de comparar a performance das duas tecnologias. A idéia é apenas mostrar alguns dados e exemplos com o objetivo de dismistificar a idéia de que ORM é uma ferramenta lenta e estes testes são apenas um exercício.&lt;/span&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;span style="color: #ff0000"&gt;Sou usuário de NHibernate e defendo o uso de ORM’s portanto as conclusões apresentadas com certeza não são as mais imparciais possíveis.&lt;/span&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Motivado &lt;a title="DDD - Objetos de consulta usando ORM - o que vcs acham? @ DotNetArchitects" href="http://groups.google.com/group/dotnetarchitects/browse_thread/thread/dc01630511ec34ec"&gt;por esta thread no DNA hoje&lt;/a&gt; decidi fazer alguns testes de perfomance pra comparar acesso a dados utilizando ADO.NET nativo (queries AdHoc e Stored Procedures) versus NHibernate.&lt;/p&gt;
&lt;p&gt;Sempre rolam diversas discussões a respeito do assunto e a conclusão que geralmente se chega é de que qualquer ORM vai ser mais lento do que uma chamada nativa. É uma conclusão óbvia já que utilizar um ORM é adicionar uma camada de abstração a mais dentro da nossa aplicação. No entanto, até então eu nunca havia efetuado nenhuma medição pra ver qual a diferença de performance.&lt;/p&gt;
&lt;p&gt;Todos os testes foram executados na minha máquina com código compilado em modo Release com banco de dados Sql Server 2008 também local.&lt;/p&gt;
&lt;p&gt;Vamos aos testes.&lt;/p&gt;
&lt;h1&gt;Cenário de testes&lt;/h1&gt;
&lt;p&gt;Criei uma tabela (Product) e populei com cerca de 500 registros vindos do AdventureWorks (banco de dados exemplo do SqlServer).&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.tucaz.net/wp-content/uploads/2010/08/image.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Modelo de Dados" border="0" alt="Modelo de Dados" src="http://blog.tucaz.net/wp-content/uploads/2010/08/image_thumb.png" width="237" height="175" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Contra essa tabela executei duas categorias de testes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Carregar todos os registros da tabela em um List&amp;lt;&amp;gt; &lt;/li&gt;
&lt;li&gt;Carregar apenas um registro &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Pra ficar mais interessante fiz algumas variações dos testes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Query AdHoc/Inline &lt;/li&gt;
&lt;li&gt;Query AdHoc/Inline com hidratação&lt;strong&gt;[1]&lt;/strong&gt; via reflection &lt;/li&gt;
&lt;li&gt;Query utilizando uma procedure &lt;/li&gt;
&lt;li&gt;NHibernate com LINQ &lt;/li&gt;
&lt;li&gt;NHibernate com HQL &lt;/li&gt;
&lt;li&gt;NHibernate com Criteria &lt;/li&gt;
&lt;li&gt;Nhibernate com Projections &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Como rodando uma única vez não foi possível obter dados suficientes, executei cada teste dentro de um loop com 1000 (numberOfIterations = 1000) iterações que resultou no código abaixo:&lt;/p&gt;
&lt;p&gt;Método principal:&lt;/p&gt;
&lt;pre class="csharp" name="code"&gt;static void Main(string[] args)
{
    for (int i = 1; i &amp;lt;= 3; i++)
    {
        Console.WriteLine(&amp;quot;Test &amp;quot; + i.ToString());
        Console.WriteLine(&amp;quot;======================&amp;quot;);

        SqlAdHocAllProducts();
        SqlAdHocAllProductsWithReflection();
        SProcAllProducts();
        NHibernateAllProductsWithLinq();
        NHibernateAllProductsWithHql();
        NHibernateAllProductsWithCriteria();
        NHibernateAllProductsWithProjections();

        SqlAdHocOneProduct();
        SqlAdHocOneProductWithReflection();
        SProcOneProduct();
        NHibernateOneProduct();

        Console.WriteLine();
    }

    Console.ReadLine();
}&lt;/pre&gt;
&lt;p&gt;
  &lt;br /&gt;Um dos métodos usando Sql AdHoc e outro usando NHibernate:&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;pre class="csharp" name="code"&gt;private static void SqlAdHocAllProducts()
{
    List&amp;lt;Product&amp;gt; allProducts = null;

    var connectionString = &amp;quot;Data Source=(local);Integrated Security=SSPI;Database=TDC2010;&amp;quot;;
    var select = @&amp;quot;SELECT P.Id, P.Description, P.Name, P.Price FROM dbo.Product P&amp;quot;;

    var connection = new SqlConnection(connectionString);
    connection.Open();

    Stopwatch watch = new Stopwatch();
    watch.Start();

    for (int i = 0; i &amp;lt; numberOfIterations; i++)
    {
        allProducts = new List&amp;lt;Product&amp;gt;();
        var command = new SqlCommand(select, connection);
        var reader = command.ExecuteReader();

        while (reader.Read())
        {
            allProducts.Add(new Product()
                {

                    Id = Convert.ToInt32(reader[&amp;quot;Id&amp;quot;]),
                    Name = Convert.ToString(reader[&amp;quot;Name&amp;quot;]),
                    Description = Convert.ToString(reader[&amp;quot;Description&amp;quot;]),
                    Price = Convert.ToDecimal(reader[&amp;quot;price&amp;quot;])
                });
        }

        reader.Close();
    }

    watch.Stop();

    connection.Close();
    connection.Dispose();

    Console.WriteLine(
        &amp;quot;Loading &amp;quot; + allProducts.Count + &amp;quot; Products with Sql AdHoc took &amp;quot; + watch.ElapsedMilliseconds + &amp;quot; ms&amp;quot;);
}&lt;/pre&gt;
&lt;p&gt;
  &lt;/p&gt;
&lt;pre class="csharp" name="code"&gt;private static void NHibernateAllProductsWithLinq()
{
    List&amp;lt;Product&amp;gt; allProducts = null;

    var session = CreateForSqlServer().OpenSession();

    Stopwatch watch = new Stopwatch();
    watch.Start();

    for (int i = 0; i &amp;lt; numberOfIterations; i++)
    {
        allProducts = session.Linq&amp;lt;Product&amp;gt;().ToList();
    }

    watch.Stop();

    session.Close();

    Console.WriteLine(
        &amp;quot;Loading &amp;quot; + allProducts.Count + &amp;quot; Products with NHibernate took &amp;quot; + watch.ElapsedMilliseconds + &amp;quot; ms&amp;quot;);
}&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Vou omitir o restante dos métodos para evitar duplicações já que eles são apenas variações dos dois exemplos acima.&lt;/strong&gt;&lt;/p&gt;
&lt;h1&gt;Resultado Geral&lt;/h1&gt;
&lt;p&gt;&lt;a href="http://blog.tucaz.net/wp-content/uploads/2010/08/image1.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="Resultados dos Testes" border="0" alt="Resultados dos Testes" src="http://blog.tucaz.net/wp-content/uploads/2010/08/image_thumb1.png" width="681" height="648" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h1&gt;Análise dos Resultados&lt;/h1&gt;
&lt;h3&gt;Stored Procedures versus Queries AdHoc/Inline [500 registros]&lt;/h3&gt;
&lt;p&gt;A diferença entre o uso de stored procedures e queries AdHoc é praticamente inexistente. A diferença média medida foi de &lt;strong&gt;menos de 1%&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Isso acontece, pois não existe complexidade suficiente neste tipo de query para que a armazenagem do plano de execução no banco de dados faça diferença.&lt;/p&gt;
&lt;p&gt;Portanto, na grande maioria dos cenários Stored Procedures não são necessárias.&lt;/p&gt;
&lt;h3&gt;NHibernate versus NHibernate [500 registros]&lt;/h3&gt;
&lt;p&gt;Na média, todas as variações de consulta utilizando NHibernate também tiveram &lt;strong&gt;mais ou menos o mesmo resultado (~1500ms)&lt;/strong&gt; com exceção do uso de &lt;strong&gt;Projections&lt;/strong&gt;, que levou o dobro&lt;strong&gt; (~3000ms)&lt;/strong&gt; do tempo.&lt;/p&gt;
&lt;p&gt;Não conheço o NHibernate suficiente pra afirmar com 100% de certeza o motivo, mas acredito que seja pelo fato de esse tipo de query retornar Arrays bidimensionais que são criados e redimensionados em runtime até que todos os itens possam ser acomodados.&lt;/p&gt;
&lt;h3&gt;NHibernate versus ADO.NET [500 registros]&lt;/h3&gt;
&lt;p&gt;Este e o comparativo mais importante. Carregando (e hidratando) 500 registros o ADO.NET é cerca de &lt;strong&gt;30% mais&lt;/strong&gt; rapido do que o NHibernate. A causa dessa discrepância é uma só e se chama reflection.&lt;/p&gt;
&lt;p&gt;Apesar de todas as otimizações o NHibernate utiliza-se de reflection para efetuar a hidratação&lt;strong&gt;[1] &lt;/strong&gt;de todos os objetos e é dai que vem a queda de performance que fica clara quando executamos queries AdHoc usando hidratação via reflection conforme o código abaixo.&lt;/p&gt;
&lt;pre class="csharp" name="code"&gt;private static void SqlAdHocAllProductsWithReflection()
{
    List&amp;lt;Product&amp;gt; allProducts = null;

    var connectionString = &amp;quot;Data Source=(local);Integrated Security=SSPI;Database=TDC2010;&amp;quot;;
    var select = @&amp;quot;SELECT P.Id, P.Description, P.Name, P.Price FROM dbo.Product P&amp;quot;;

    var connection = new SqlConnection(connectionString);
    connection.Open();

    Stopwatch watch = new Stopwatch();
    watch.Start();

    for (int i = 0; i &amp;lt; numberOfIterations; i++)
    {
        allProducts = new List&amp;lt;Product&amp;gt;();
        var command = new SqlCommand(select, connection);
        var reader = command.ExecuteReader();

        while (reader.Read())
        {
            var newProduct = Activator.CreateInstance&amp;lt;Product&amp;gt;();
            SetProperty(newProduct, &amp;quot;Id&amp;quot;, Convert.ToInt32(reader[&amp;quot;Id&amp;quot;]));
            SetProperty(newProduct, &amp;quot;Description&amp;quot;, Convert.ToString(reader[&amp;quot;Description&amp;quot;]));
            SetProperty(newProduct, &amp;quot;Name&amp;quot;, Convert.ToString(reader[&amp;quot;Name&amp;quot;]));
            SetProperty(newProduct, &amp;quot;Price&amp;quot;, Convert.ToDecimal(reader[&amp;quot;Price&amp;quot;]));
            allProducts.Add(newProduct);
        }

        reader.Close();
    }

    watch.Stop();

    connection.Close();
    connection.Dispose();

    Console.WriteLine(
&amp;quot;Loading &amp;quot; + allProducts.Count + &amp;quot; Products with Sql AdHoc and Reflection took &amp;quot; + watch.ElapsedMilliseconds + &amp;quot; ms&amp;quot;);
}

private static void SetProperty(object instance, string property, object val)
{
    Type t = instance.GetType();
    var prop = t.GetProperty(property, BindingFlags.Instance | BindingFlags.Public);
    prop.SetValue(instance, val, null);
}&lt;/pre&gt;
&lt;p&gt;Este código quando executado demora cerca de &lt;strong&gt;6000ms, ou 4 vezes mais&lt;/strong&gt;, do que o código executado pelo NHibernate.&lt;/p&gt;
&lt;p&gt;Mas por que a diferença não é de 30%? Porque o NHibernate possui otimizações quanto ao modo de hidratar um objeto via reflection. No meu código acima podemos ver, por exemplo, que toda vez que chamo o método SetProperty o Type da propriedade a ser refletida ainda não está criado. Provavelmente o NHibernate deve manter cache deste tipo de informação (e de outras) a fim de otimizar o processo de hidratação das entidades.&lt;/p&gt;
&lt;h3&gt;Stored Procedures versus Queries AdHoc/Inline [1 registro]&lt;/h3&gt;
&lt;p&gt;Mesmo resultado do cenário onde 500 registros são carregados. Não há diferença.&lt;/p&gt;
&lt;h3&gt;NHibernate versus ADO.NET [1 registro]&lt;/h3&gt;
&lt;p&gt;Aqui a diferença é gigantesca sendo de &lt;strong&gt;quase 4000% a favor do NHibernate. &lt;/strong&gt;Isso acontece, pois o NHibernate implementa cache nível 1 nativamente então dentro de uma mesma ISession o objeto é carregado apenas uma vez enquanto com ADO.NET é necessário ir ao banco e carregar o objeto diversas vezes.&lt;/p&gt;
&lt;h1&gt;Conclusões&lt;/h1&gt;
&lt;p&gt;Olhando para os números apenas, em casos onde diversos registros precisam ser carregados, ADO.NET nativo oferece uma performance superior e parece ser a escolha óbvia. No entanto:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Os testes com NHibernate foram executados utilizandos exemplos simples e sem qualquer tipo de otimização. &lt;/li&gt;
&lt;li&gt;NHibernate oferece nativamente cache de resultados de queries e cache nível 2 que se utilizados iriam exibir um resultado bem próximo ao cenário “&lt;em&gt;NHibernate versus ADO.NET [1 registro]” &lt;/em&gt;onde o NHibernate é 4 vezes mais rápido. &lt;/li&gt;
&lt;li&gt;ADO.NET oferece um custo de desenvolvimento e manutenção altissimo e este custo torna-se ainda maior se utilizado com Stored Procedures que transformam o cenário em algo totalmente caótico de gerenciar devido a dificuldade de manter a rastreabilidade desses diabinhos malignos. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;No caso de sistemas &lt;a title="OLTP @ Wikipedia" href="http://pt.wikipedia.org/wiki/OLTP"&gt;OLTP&lt;/a&gt; onde as transações carregam unidades individuais e/ou pequenas coleções de entidades por sessão, NHibernate não só é mais rápido como também oferece muito mais flexibilidade pra lidar com praticamente todos os cenários existentes. &lt;a title="25 reasons not to write your own ORM @ Ayende&amp;#39;s Blog" href="http://ayende.com/Blog/archive/2006/05/12/25ReasonsNotToWriteYourOwnObjectRelationalMapper.aspx"&gt;Este post do Ayende&lt;/a&gt; mostra 25 funcionalidades importantes (cache, gerenciamento de concorrência, etc) que você vai precisar quando estiver lidando com dados e que custariam muito caro (tempo e complexidade) caso você queira escreve-las “na mão”.&lt;/p&gt;
&lt;p&gt;Em cenários de aplicações de internet onde o número de leituras é infinitamente superior ao número de escritas no banco de dados deve se utilizar cache no front end (IIS), portanto o tempo que se leva pra montar uma página é irrelevante. Mesmo que você carregasse os dados de um servidor remoto via conexão discada não faria diferença uma vez que os dados estivessem em cache.&lt;/p&gt;
&lt;p&gt;Por último, se você se encontrar em uma situação utilizando NHibernate onde o acesso a dados é o gargalo da sua aplicação seu problema não é o NHibernate (a não ser que você tenha usado-o de maneira totalmente absurda, mas a probabilidade de você fazer o mesmo com ADO.NET é grande também). Nestes cenários o problema não é o acesso a dados em si, mas o resto da arquitetura que não escala de maneira adequada seja por meio de cache, processamento assincrono, filas, etc.&lt;/p&gt;
&lt;p&gt;Sendo assim, acredito que podemos concluir que não faz sentido algum no meio do ano de 2010 utilizar queries AdHoc ou Stored Procedures em aplicações &lt;a title="Line of Business @ Wikipedia" href="http://en.wikipedia.org/wiki/Line_of_business"&gt;LoB&lt;/a&gt;. &lt;img src='http://blog.tucaz.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /&gt; &lt;/p&gt;
&lt;p&gt;O código completo utilizado está no GitHub e pode ser &lt;a title="NHPerf Source Code @ GitHub" href="http://github.com/tucaz/Samples/tree/master/NHPerf/"&gt;acessado online&lt;/a&gt; ou baixado em &lt;a title="Download of NHPerf Source Code @ GitHub" href="http://github.com/downloads/tucaz/Samples/NHPerf.zip"&gt;formato zip&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;[1] – Hidratação é o processo de preenchimento (filling) das propriedades de uma entidade&lt;/strong&gt;&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=Mbh8HP8uQuA:Am2mVxt63p4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=Mbh8HP8uQuA:Am2mVxt63p4:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?i=Mbh8HP8uQuA:Am2mVxt63p4:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=Mbh8HP8uQuA:Am2mVxt63p4:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=Mbh8HP8uQuA:Am2mVxt63p4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?i=Mbh8HP8uQuA:Am2mVxt63p4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=Mbh8HP8uQuA:Am2mVxt63p4:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tucaz/~4/Mbh8HP8uQuA" height="1" width="1"/&gt;</content><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.tucaz.net/2010/08/31/performance-nhibernate-versus-ado-net/feed/</wfw:commentRss><slash:comments xmlns:slash="http://purl.org/rss/1.0/modules/slash/">17</slash:comments><feedburner:origLink>http://blog.tucaz.net/2010/08/31/performance-nhibernate-versus-ado-net/</feedburner:origLink></entry><entry><title type="text">Material da palestra no TDC2010 – ORM: Por que isso te interessa?</title><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tucaz/~3/R0pUn1h64zE/" /><category term=".NET" /><category term="Apresentações" /><category term="NHibernate" /><category term="dao" /><category term="data access" /><category term="Evento" /><category term="orm" /><category term="Palestras" /><category term="slides" /><category term="tdc2010" /><author><name>tucaz</name></author><updated>2010-08-26T15:09:38-07:00</updated><id>http://blog.tucaz.net/?p=459</id><summary type="html">No último fim de semana rolou em São Paulo o TDC2010 organizado pela Globalcode. Fui convidado a palestrar na trilha de .NET pelo @giovannibassi pra falar um pouquinho sobre ORM e porque é uma boa idéia usá-lo.
Abaixo estão os slides da minha palestra, que não fazem muito sentido por si só, mas que tem umas [...]</summary><content type="html">&lt;p&gt;&lt;a href="http://blog.tucaz.net/wp-content/uploads/2010/08/barratopbasic.jpg"&gt;&lt;img style="display: inline; border-width: 0px;" title="barra-top-basic" src="http://blog.tucaz.net/wp-content/uploads/2010/08/barratopbasic_thumb.jpg" border="0" alt="barra-top-basic" width="390" height="68" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;No último fim de semana rolou em São Paulo o &lt;a href="http://www.thedevelopersconference.com.br/"&gt;TDC2010&lt;/a&gt; organizado pela &lt;a href="http://www.globalcode.com.br"&gt;Globalcode&lt;/a&gt;. Fui convidado a palestrar na &lt;a href="http://www.thedevelopersconference.com.br/tdc/2010/sp/trilha-dot-net"&gt;trilha de .NET&lt;/a&gt; pelo &lt;a href="http://www.twitter.com/giovannibassi"&gt;@giovannibassi&lt;/a&gt; pra falar um pouquinho sobre ORM e porque é uma boa idéia usá-lo.&lt;/p&gt;
&lt;p&gt;Abaixo estão os &lt;a href="http://www.slideshare.net/tucaz/orm-por-que-isso-te-interessa-tdc2010/"&gt;slides da minha palestra&lt;/a&gt;, que não fazem muito sentido por si só, mas que tem umas imagens divertidas!&lt;/p&gt;
&lt;div id="__ss_5047644" style="width: 425px;"&gt;&lt;strong&gt;&lt;a title="ORM: Por que isso te interessa? (TDC2010)" href="http://www.slideshare.net/tucaz/orm-por-que-isso-te-interessa-tdc2010"&gt;ORM: Por que isso te interessa? (TDC2010)&lt;/a&gt;&lt;/strong&gt;&lt;object id="__sse5047644" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="355" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="allowFullScreen" value="true" /&gt;&lt;param name="allowScriptAccess" value="always" /&gt;&lt;param name="src" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=orm-100824141739-phpapp01&amp;amp;stripped_title=orm-por-que-isso-te-interessa-tdc2010" /&gt;&lt;param name="name" value="__sse5047644" /&gt;&lt;param name="allowfullscreen" value="true" /&gt;&lt;embed id="__sse5047644" type="application/x-shockwave-flash" width="425" height="355" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=orm-100824141739-phpapp01&amp;amp;stripped_title=orm-por-que-isso-te-interessa-tdc2010" name="__sse5047644" allowscriptaccess="always" allowfullscreen="true"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/p&gt;
&lt;div style="padding-bottom: 12px; padding-left: 0px; padding-right: 0px; padding-top: 5px;"&gt;View more &lt;a href="http://www.slideshare.net/"&gt;presentations&lt;/a&gt; from &lt;a href="http://www.slideshare.net/tucaz"&gt;tucaz&lt;/a&gt;.&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Em um dos últimos slides tem uma porção de links muito legais sobre NHibernate então pra quem não quiser ter o trabalho de ver os slides ai vai:&lt;/p&gt;
&lt;p&gt;&lt;span style="text-decoration: underline;"&gt;&lt;a href="http://nhforge.org/"&gt;http://nhforge.org/&lt;/a&gt;&lt;/span&gt; -&amp;gt; NHibernate official website&lt;br /&gt;
&lt;span style="text-decoration: underline;"&gt;&lt;a href="http://fluentnhibernate.org/"&gt;http://fluentnhibernate.org/&lt;/a&gt;&lt;/span&gt; -&amp;gt; Fluent Mappings for Nhibernate&lt;br /&gt;
&lt;span style="text-decoration: underline;"&gt;&lt;a href="http://nhprof.com/"&gt;http://nhprof.com/&lt;/a&gt;&lt;/span&gt; -&amp;gt; NHibernate Profiler with 30 day trial&lt;br /&gt;
&lt;span style="text-decoration: underline;"&gt;&lt;a href="http://www.summerofnhibernate.com/"&gt;http://www.summerofnhibernate.com/&lt;/a&gt;&lt;/span&gt; -&amp;gt; More than 14 hours of free videos&lt;br /&gt;
&lt;span style="text-decoration: underline;"&gt;&lt;a href="http://www.manning.com/kuate/"&gt;http://www.manning.com/kuate/&lt;/a&gt; &lt;/span&gt;-&amp;gt; “NHibernate In Action” Book by Manning&lt;br /&gt;
&lt;span style="text-decoration: underline;"&gt;&lt;a href="http://ayende.com/Blog/category/510.aspx"&gt;http://ayende.com/Blog/category/510.aspx&lt;/a&gt;&lt;/span&gt;&lt;span style="text-decoration: underline;"&gt; &lt;/span&gt;-&amp;gt; NHibernate @ Ayende’s&lt;br /&gt;
&lt;span style="text-decoration: underline;"&gt;&lt;a href="http://tinyurl.com/25reasons"&gt;http://tinyurl.com/25reasons&lt;/a&gt;&lt;/span&gt; -&amp;gt; 25 reasons NOT to write yout own ORM @ Ayende’s&lt;br /&gt;
&lt;a href="http://fabiomaulo.blogspot.com/search/label/NHibernate"&gt;http://fabiomaulo.blogspot.com/search/label/NHibernate&lt;/a&gt; -&amp;gt; NHibernate @ Fabio Maulo’s&lt;br /&gt;
&lt;a href="http://blogs.hibernatingrhinos.com/nhibernate/"&gt;http://blogs.hibernatingrhinos.com/nhibernate/&lt;/a&gt; -&amp;gt; NHibernate Blog&lt;br /&gt;
&lt;span style="text-decoration: underline;"&gt;&lt;a href="http://code.google.com/p/unhaddins/"&gt;http://code.google.com/p/unhaddins/&lt;/a&gt;&lt;/span&gt; -&amp;gt; unhaddins, Unofficial addins for Nhibernate&lt;/p&gt;
&lt;p&gt;Além dos slides, &lt;a href="http://github.com/tucaz/Samples"&gt;coloquei no GitHub também o código fonte do projetinho que usei na demo que fiz&lt;/a&gt;. Apesar de ser uma demo, o código serve como referência pra começar a utilizar o NHibernate e FluentMapping e ter uma idéia de algumas features bem legais que ele oferece.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://github.com/downloads/tucaz/Samples/TDC2010.zip"&gt;Download do zip com o código.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Palestraram também, da Stefanini, &lt;a href="http://www.twitter.com/vquaiato"&gt;@vquaiato&lt;/a&gt; na trilha de Ruby e .NET, &lt;a href="http://www.twitter.com/alnascimento"&gt;@alnascimento&lt;/a&gt; e &lt;a href="http://www.twitter.com/manoelp"&gt;@manoelp&lt;/a&gt; em Agile, &lt;a href="http://www.twitter.com/vcavalcante"&gt;@vcavalcante&lt;/a&gt; em .NET e &lt;a href="http://www.twitter.com/jorgediz"&gt;@jorgediz&lt;/a&gt; em Testes.&lt;/p&gt;
&lt;p&gt;Por último, mas não menos importante eu queria deixar registrado meu agradecimento ao &lt;a href="http://ayende.com/"&gt;Oren Eini (a.k.a. Ayende Rahien&lt;/a&gt;) pelos cupons de desconto e licensa do &lt;a href="http://nhprof.com/"&gt;NHProf&lt;/a&gt; que distribui ao final da palestra e também a Candace da &lt;a href="http://www.manning.com/"&gt;Manning Publications&lt;/a&gt; pelas cópias dos eBooks “&lt;a href="http://www.manning.com/kuate/"&gt;NHibernate In Action&lt;/a&gt;” que também dei de brinde. Muito obrigado pelas contribuições a comunidade! &lt;img src='http://blog.tucaz.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /&gt; &lt;/p&gt;
&lt;p&gt;Now in English so I can make this public to English speakers too. Thanks to &lt;a href="http://ayende.com/"&gt;Oren Eini (a.k.a Ayende Rahien&lt;/a&gt;) for the discount coupons and &lt;a href="http://nhprof.com/"&gt;NHProf&lt;/a&gt; license that I gave out and to Candace from &lt;a href="http://www.manning.com/"&gt;Manning Publications&lt;/a&gt; for the copies of “&lt;a href="http://www.manning.com/kuate/"&gt;NHibernate In Action&lt;/a&gt;” that were also given at the event. You guys are amazing. Thanks a lot for contributing with this growing community! &lt;img src='http://blog.tucaz.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /&gt; &lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=R0pUn1h64zE:36K1UoRPI3I:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=R0pUn1h64zE:36K1UoRPI3I:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?i=R0pUn1h64zE:36K1UoRPI3I:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=R0pUn1h64zE:36K1UoRPI3I:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=R0pUn1h64zE:36K1UoRPI3I:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?i=R0pUn1h64zE:36K1UoRPI3I:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=R0pUn1h64zE:36K1UoRPI3I:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tucaz/~4/R0pUn1h64zE" height="1" width="1"/&gt;</content><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.tucaz.net/2010/08/26/material-da-palestra-no-tdc2010-orm-por-que-isso-te-interessa/feed/</wfw:commentRss><slash:comments xmlns:slash="http://purl.org/rss/1.0/modules/slash/">2</slash:comments><feedburner:origLink>http://blog.tucaz.net/2010/08/26/material-da-palestra-no-tdc2010-orm-por-que-isso-te-interessa/</feedburner:origLink></entry><entry><title type="text">Ninject, StructureMap e Padrões de Injeção de Dependência</title><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tucaz/~3/Tp8pcDyKN-0/" /><category term="Design Patterns" /><category term="OO" /><category term="abstract factory" /><category term="DI" /><category term="factory" /><category term="IoC" /><category term="ninject" /><category term="structuremap" /><author><name>tucaz</name></author><updated>2010-08-03T20:57:56-07:00</updated><id>http://blog.tucaz.net/?p=433</id><summary type="html">Este post foi motivado por esta thread no DNA e por essa question no StackOverflow.com a respeito de um problema que encontrei nesta última semana em um cenário relativamente complexo de injeção de dependência.
Contexto
A arquitetura em questão utiliza injeção de dependência com base em interfaces, ou seja, todas as dependências das minhas classes são sempre [...]</summary><content type="html">&lt;p&gt;Este post foi motivado por &lt;a title="Discussão a respeito de IoC/DI no DotNetArchitects" href="http://groups.google.com/group/dotnetarchitects/browse_thread/thread/3fc4c95c4f0c150d"&gt;esta thread no DNA&lt;/a&gt; e por &lt;a title="Resolving dependencies @ StackOveflow.com" href="http://stackoverflow.com/questions/3335735/resolving-automatic-and-manual-dependencies"&gt;essa question no StackOverflow.com&lt;/a&gt; a respeito de um problema que encontrei nesta última semana em um cenário relativamente complexo de injeção de dependência.&lt;/p&gt;
&lt;h2&gt;Contexto&lt;/h2&gt;
&lt;p&gt;A arquitetura em questão utiliza injeção de dependência com base em interfaces, ou seja, todas as dependências das minhas classes são sempre pra interfaces (contratos) e nunca para classes concretas (implementação) exatamente como manda o figurino.&lt;/p&gt;
&lt;p&gt;Meu domínio é o padrão: carrinho de compras com Pedido e seus itens. Uma classe é responsável por efetuar o processamento do pedido (&lt;em&gt;GeradorPedido&lt;/em&gt;). Ela executa todos os procedimentos necessários para que um pedido seja gerado de maneira correta, dentre eles aplicar um determinado fator de ajuste de preços dos itens acordo com a loja onde o pedido foi vendido. Este fator de ajuste é determinado pela classe &lt;em&gt;Precificador&lt;/em&gt; e deve ser desconhecido para o restante dos outros objetos a fim de não violar o &lt;a title="Single Responsibility Principle @ Wikipedia" href="http://en.wikipedia.org/wiki/Single_responsibility_principle"&gt;SRP&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;O diagrama abaixo representa as classes envolvidas e suas dependências:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.tucaz.net/wp-content/uploads/2010/07/classes2.png"&gt;&lt;img class="aligncenter size-full wp-image-437" title="Diagrama de Classes" src="http://blog.tucaz.net/wp-content/uploads/2010/07/classes2.png" alt="" width="619" height="426" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Como aplicar este fator ao preço do item não é responsabilidade do &lt;em&gt;GeradorPedido&lt;/em&gt;, sempre que uma instância de &lt;em&gt;GeradorPedido&lt;/em&gt; é criada, injeto via construtor uma nova instância de &lt;em&gt;Precificador&lt;/em&gt; pra ser usado quando necessário. Neste caso, temos uma dependência direta de &lt;em&gt;GeradorPedido&lt;/em&gt; para &lt;em&gt;IPrecificador&lt;/em&gt; que é resolvida em tempo de execução.&lt;/p&gt;
&lt;p&gt;Tudo estava sendo resolvido utilizando &lt;a title="Ninject's Website" href="http://www.ninject.org/"&gt;Ninject&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;MyModule.cs&lt;/p&gt;
&lt;pre name="code" class="csharp"&gt;public class MyModule : NinjectModule
{
    public override void Load()
    {
        Bind&amp;lt;IPrecificador&amp;gt;().To&amp;lt;Precificador&amp;gt;();
        Bind&amp;lt;IGeradorPedido&amp;gt;().To&amp;lt;GeradorPedido&amp;gt;();
    }
}&lt;/pre&gt;
&lt;p&gt;UnitTest1.cs&lt;/p&gt;
&lt;pre name="code" class="csharp"&gt;[TestMethod]
public void consegue_resolver_GeradorPedido()
{
    MyModule module = new MyModule();
    StandardKernel kernel = new StandardKernel(module);
    var geradorPedido = kernel.Get();

    Assert.IsNotNull(geradorPedido);
}&lt;/pre&gt;
&lt;p&gt;Precificador.cs&lt;/p&gt;
&lt;pre name="code" class="csharp"&gt;class Precificador : IPrecificador
{
    private decimal _fatorAjuste;

    public Precificador()
    {
        _fatorAjuste = 10m;
    }

    public decimal CalcularPreco(ItemPedido item)
    {
        return item.Preco * _fatorAjuste;
    }
}&lt;/pre&gt;
&lt;p&gt;GeradorPedido.cs&lt;/p&gt;
&lt;pre name="code" class="csharp"&gt;class GeradorPedido : IGeradorPedido
{
    private IPrecificador _precificador;

    public GeradorPedido(IPrecificador precificador)
    {
        _precificador = precificador;
    }

    public string Processar(Pedido novoPedido)
    {
        decimal total = 0;

        foreach (var item in novoPedido.Itens)
        {
            total += _precificador.CalcularPreco(item);
        }

        //Faz mais algumas operações com pedido

        //Número do pedido
        return "ABC123";
    }
}&lt;/pre&gt;
&lt;p&gt;Até aqui, tudo OK, certo? Ai entra um novo requisito e com ele aparece o problema&amp;#8230;&lt;/p&gt;
&lt;h2&gt;Novo Requisito&lt;/h2&gt;
&lt;p&gt;Alguém decidiu que o fator dos preços deveria variar de acordo com a loja em que o pedido estava sendo feito. Se isso é uma regra de preço, a qual classe pertence? &lt;em&gt;Precificador&lt;/em&gt;!&lt;/p&gt;
&lt;p&gt;Quais opções temos pra implementar isso com o mínimo de impacto possível no sistema (já que a interface &lt;em&gt;IPrecificador&lt;/em&gt; já estava sendo usada) e de maneira que a coesão e desacoplamento seja mantido?&lt;/p&gt;
&lt;h3&gt;Opção 1 &amp;#8211; Adicionar um paramêtro no método CalcularPreco&lt;/h3&gt;
&lt;p&gt;A primeira opção que me veio a cabeça foi adicionar o paramêtro com a loja diretamente no método CalcularPreco da interface &lt;em&gt;IPrecificador&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;IPrecificador.cs&lt;/p&gt;
&lt;pre name="code" class="csharp"&gt;class Precificador : IPrecificador
{
    private decimal _fatorAjuste;

    public decimal CalcularPreco(ItemPedido item, Loja vendaEfetuadaEm)
    {
        if (vendaEfetuadaEm == Lojas.LojaUm)
            _fatorAjuste = 10m;
        else if (vendaEfetuadaEm == Lojas.LojaDois)
            _fatorAjuste = 15.4m;
        else
            _fatorAjuste = 0.9m;

        return item.Preco * _fatorAjuste;
    }
}&lt;/pre&gt;
&lt;p&gt;Parecia uma boa saída, mas depois de pensar alguns minutos encontrei dois side-effects graves que me fizeram mudar de idéia:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;O novo paramêtro, &lt;em&gt;Loja&lt;/em&gt;, passaria também a virar uma dependência direta pra todos que consumissem a interface &lt;em&gt;IPrecificador&lt;/em&gt; já que estes [consumidores] seriam responsáveis por repassar a loja para poder realizar a chamada a CalcularPreco. Com isso estariamos violando o SRP adicionando um motivo a mais pra classe &lt;em&gt;GeradorPedido&lt;/em&gt; e outras mudarem.&lt;/li&gt;
&lt;li&gt;Diversos testes seriam quebrados pela adição do novo paramêtro, indicando que talvez não fosse a melhor alternativa já que essa alteração deveria afetar apenas uma classe&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Opção 2 &amp;#8211; Adicionar este paramêtro ao construtor da classe Precificador e utilizar uma Factory&lt;/h3&gt;
&lt;p&gt;Já que esta alteração diz respeito apenas a responsabilidade da classe &lt;em&gt;Precificador&lt;/em&gt;, que tal adicionar este paramêtro ao construtor da classe? Ótima idéia, não?&lt;/p&gt;
&lt;p&gt;De fato foi a solução que fez mais sentido já que necessariamente para chegar ao fator de preço a ser aplicado a classe precisa saber com qual loja estamos lidando. Para implementar, bastaria fornecer a loja via construtor e armazenar o valor em um membro privado da classe pra uso posterior. Dessa forma, todos os consumidores dessa classe iriam receber uma instância de &lt;em&gt;IPrecificador&lt;/em&gt; já configurada e pronta pra uso sem a necessidade de se preocupar em fornecer a loja.&lt;/p&gt;
&lt;p&gt;Nosso novo Precificador.cs ficaria assim:&lt;/p&gt;
&lt;pre name="code" class="csharp"&gt;class Precificador : IPrecificador
{
    private decimal _fatorAjuste;

    public Precificador(Loja vendaEfetuadaEm)
    {
        if (vendaEfetuadaEm == Lojas.LojaUm)
            _fatorAjuste = 10m;
        else if (vendaEfetuadaEm == Lojas.LojaDois)
            _fatorAjuste = 15.4m;
        else
            _fatorAjuste = 0.9m;
    }

    public decimal CalcularPreco(ItemPedido item)
    {
        return item.Preco * _fatorAjuste;
    }
}&lt;/pre&gt;
&lt;p&gt;No entanto, na hora que fui implementar esta solução esbarrei no meu container de DI, até então o Ninject, que resolvia a dependência de &lt;em&gt;IPrecificador&lt;/em&gt; pra mim automaticamente sempre que necessário. Contudo, pra esta implementação eu precisaria fornecer um valor (a &lt;em&gt;Loja&lt;/em&gt;) que só podia ser obtido em runtime na hora de construir a instância de &lt;em&gt;IPrecificador&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Então a solução seria utilizar uma Factory!&lt;/p&gt;
&lt;p&gt;GeradorPedidoFactory.cs&lt;/p&gt;
&lt;pre name="code" class="csharp"&gt;class GeradorPedidoFactory
{
    public static IGeradorPedido Criar(Loja vendaEfetuadaEm)
    {
        IPrecificador precificador = new Precificador(vendaEfetuadaEm);
        return new GeradorPedido(precificador);
    }
}&lt;/pre&gt;
&lt;p&gt;Mas trinta segundos depois descartei essa idéia porque &lt;em&gt;IPrecificador&lt;/em&gt; estava sendo usado por outras classes além de &lt;em&gt;GeradorPedido&lt;/em&gt; então eu teria que criar uma factory pra cada uma das classes que fosse consumidora de &lt;em&gt;IPrecificador&lt;/em&gt;. Também dessa forma eu estaria anulando meu Container de DI espalhando a criação de tipos concretos por diversas factories ao invés de centralizar em apenas um ponto.&lt;/p&gt;
&lt;h3&gt;Opção 3 – Manter o construtor e utilizar uma Abstract Factory pra criar IPrecificador&lt;/h3&gt;
&lt;p&gt;A terceira e ultima opção antes da solução final foi utilizar uma Abstract Factory, que seria injetada via DI em todo mundo que precisasse de &lt;em&gt;IPrecificador&lt;/em&gt; eliminando a necessidade de uma factory pra cada construtor e mantendo a responsabilidade no lugar adequado. Algo assim:&lt;/p&gt;
&lt;p&gt;PrecificadorFactory.cs&lt;/p&gt;
&lt;pre name="code" class="csharp"&gt;class PrecificadorFactory : IPrecificadorFactory
{
    public IPrecificador Criar(Loja vendaEfetuadaEm)
    {
        return new Precificador(vendaEfetuadaEm);
    }
}&lt;/pre&gt;
&lt;p&gt;MyModule.cs&lt;/p&gt;
&lt;pre name="code" class="csharp"&gt;public class MyModule : NinjectModule
{
    public override void Load()
    {
        Bind&amp;lt;IPrecificadorFactory&amp;gt;().To&amp;lt;PrecificadorFactory&amp;gt;();
        Bind&amp;lt;IGeradorPedido&amp;gt;().To&amp;lt;GeradorPedido&amp;gt;();
    }
}&lt;/pre&gt;
&lt;p&gt;GeradorPedido.cs&lt;/p&gt;
&lt;pre name="code" class="csharp"&gt;class GeradorPedido : IGeradorPedido
{
    private IPrecificadorFactory _precificadorFactory;

    public GeradorPedido(IPrecificadorFactory precificadorFactory)
    {
        _precificadorFactory = precificadorFactory;
    }

    public string Processar(Pedido novoPedido, Loja vendaEfetuadaEm)
    {
        IPrecificador precificador = _precificadorFactory.Criar(vendaEfetuadaEm);
        decimal total = 0;

        foreach (var item in novoPedido.Itens)
        {
            total += precificador.CalcularPreco(item);
        }

        //Faz mais algumas operações com pedido

        //Número do pedido
        return "ABC123";
    }
}&lt;/pre&gt;
&lt;p&gt;Contudo, na hora que implementei pra ver como ficaria, percebi que tinha o mesmo problema da primeira solução: todo mundo que precisasse consumir &lt;em&gt;IPrecificador&lt;/em&gt; teria que receber o paramêtro informando a &lt;em&gt;Loja&lt;/em&gt; onde a venda foi efetuada para repassar para a abstract factory de IPrecificador a fim de criar uma instância concreta da classe. A dependência tinha voltado, apesar de a responsabilidade estar um pouco melhor distribuida. &lt;img src='http://blog.tucaz.net/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /&gt; &lt;/p&gt;
&lt;h3&gt;A Solução Final&lt;/h3&gt;
&lt;p&gt;Quando eu já estava quase desistindo de procurar outra alternativa (mais uma) o &lt;a title="Pedro Reys @ Twitter" href="http://twitter.com/pedroreys"&gt;@pedroreys&lt;/a&gt; deu uma idéia excelente: fornecer previamente ao container de DI a instância de &lt;em&gt;IPrecificador&lt;/em&gt; que deveria ser usada quando ela fosse necessária.&lt;/p&gt;
&lt;p&gt;Na hora fui atrás de como fazer isso com o Ninject que, era meu container até então. Infelizmente ele não implementa essa funcionalidade especifíca. Pelo menos não da maneira que eu gostaria &lt;strong&gt;[1]&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Foi ai que decidi mudar para o &lt;a title="StructureMap @ GitHub" href="http://structuremap.github.com/structuremap/index.html"&gt;StructureMap&lt;/a&gt;, container utilizado no exemplo do &lt;a title="Pedro Reys @ Twitter" href="http://twitter.com/pedroreys"&gt;@pedroreys&lt;/a&gt;. O StructureMap, apesar de ter sido um dos primeiros containers de DI/IoC lançados (e de ser um pouco &lt;em&gt;verboso&lt;/em&gt; demais pro meu gosto), se mantém atualizado e com uma excelente interface fluente exatamente como o Ninject.&lt;/p&gt;
&lt;p&gt;A troca foi simples já que eu utilizo um Wrapper (omitido por breviedade) pro Ninject e a aplicação não tem contato com o container em si. O resultado acabou sendo um Mix de todas as soluções:&lt;/p&gt;
&lt;p&gt;PrecificadorFactory.cs&lt;/p&gt;
&lt;pre name="code" class="csharp"&gt;class PrecificadorFactory
{
    public static IPrecificador Criar(Loja vendaEfetuadaEm)
    {
        return new Precificador(vendaEfetuadaEm);
    }
}&lt;/pre&gt;
&lt;p&gt;UnitTest1.cs&lt;/p&gt;
&lt;pre name="code" class="csharp"&gt;[TestMethod]
public void consegue_resolver_GeradorPedido()
{
    Loja vendaEfetuadaEm = RecuperarLojaOndeVendaFoiEfetuada();

    IPrecificador precificador = PrecificadorFactory.Criar(vendaEfetuadaEm);

    Container container = new Container();

    IGeradorPedido geradorPedido = container.With&amp;lt;IPrecificador&amp;gt;(precificador).GetInstance&amp;lt;IGeradorPedido&amp;gt;();

    Assert.IsNotNull(geradorPedido);
}&lt;/pre&gt;
&lt;p&gt;Dessa forma consigo:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Criar a instância de &lt;em&gt;IPrecificador&lt;/em&gt; separadamente&lt;/li&gt;
&lt;li&gt;Dizer ao container que quero que esta instância especifica seja usada somente nesta resolução de &lt;em&gt;IGeradorPedido&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Manter cada classe com sua responsabilidade&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Any thoughts o this?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;[1] – O Ninject, na última versão (2.0), implementa o método Rebind() que permite trocar o bind de uma interface em runtime. No entanto, esta troca é permanente e afeta todos os consumidores do container (Singleton, no meu caso) e no meu contexto, não faz muito sentido.&lt;/strong&gt;&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=Tp8pcDyKN-0:jqfHnwy9TNE:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=Tp8pcDyKN-0:jqfHnwy9TNE:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?i=Tp8pcDyKN-0:jqfHnwy9TNE:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=Tp8pcDyKN-0:jqfHnwy9TNE:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=Tp8pcDyKN-0:jqfHnwy9TNE:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?i=Tp8pcDyKN-0:jqfHnwy9TNE:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=Tp8pcDyKN-0:jqfHnwy9TNE:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tucaz/~4/Tp8pcDyKN-0" height="1" width="1"/&gt;</content><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.tucaz.net/2010/08/04/ninject-structuremap-e-padroes-de-injecao-de-dependncia/feed/</wfw:commentRss><slash:comments xmlns:slash="http://purl.org/rss/1.0/modules/slash/">7</slash:comments><feedburner:origLink>http://blog.tucaz.net/2010/08/04/ninject-structuremap-e-padroes-de-injecao-de-dependncia/</feedburner:origLink></entry><entry><title type="text">A caminho do Zen</title><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tucaz/~3/QaJlgLd9z-c/" /><category term="Uncategorized" /><category term="Produtividade" /><category term="zen" /><author><name>tucaz</name></author><updated>2010-04-18T18:24:33-07:00</updated><id>http://blog.tucaz.net/?p=429</id><summary type="html">Hoje temos a nossa disposição milhares de fontes de informação e algumas dezenas de grandes agregadores de informação (rss, twitter, etc) que multiplicam a quantidade de informação a que somos expostos diariamente.
Agora, o desafio não é encontrar a informação, mas sim escolher qual informação iremos consumir. Até pouco tempo atrás quantidade significava qualidade, mas isso [...]</summary><content type="html">&lt;p&gt;Hoje temos a nossa disposição milhares de fontes de informação e algumas dezenas de grandes agregadores de informação (rss, twitter, etc) que multiplicam a quantidade de informação a que somos expostos diariamente.&lt;/p&gt;
&lt;p&gt;Agora, o desafio não é encontrar a informação, mas sim escolher qual informação iremos consumir. Até pouco tempo atrás quantidade significava qualidade, mas isso já não é mais verdade e a maioria das pessoas está tentando diminuir a quantidade de coisas que faz e a quantidade de informação a que é exposta. Menos virou mais.&lt;/p&gt;
&lt;p&gt;Diariamente, incluindo RSS, Twitter, DNA e os links gerados a partir destes agregadores (que são os que mais uso) acho que gasto umas quatro horas lendo. Isso sem contar a pilha de livros que compro mensalmente e que vai se acumulando para leitura posterior.&lt;/p&gt;
&lt;p&gt;Por conta disso, acabo não tendo tempo de executar os projetos que gostaria, entre eles escrever mais neste blog. Ler é excelente, mas a rede da web faz com que cada link aberto gere mais outros 200 e não conseguimos processar tudo ao mesmo tempo. Por isso, foco é fundamental.&lt;/p&gt;
&lt;p&gt;Nos últimos dias defini uma lista de projetos/items que quero concluir nas próximas semanas. Sendo assim, vou tentar reduzir minha exposição à toda essa informação pra dar uma &amp;#8220;desintoxicada&amp;#8221; e focar nestes itens.&lt;/p&gt;
&lt;p&gt;Estou compartilhando essa dificuldade por dois motivos: 1) Tornar um problema público faz com que a gente se mexa pra resolve-lo, afinal ninguém gosta de ter seus problemas expostos (ainda mais sem resolve-los, né?) e 2) Ver se alguém compartilha do mesmo &amp;#8220;problema&amp;#8221; e entender como cada um lida com isso, portanto você que está lendo isso, saia do read-only mode e comente este post! &lt;img src='http://blog.tucaz.net/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /&gt; &lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=QaJlgLd9z-c:vXeJS21KZFU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=QaJlgLd9z-c:vXeJS21KZFU:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?i=QaJlgLd9z-c:vXeJS21KZFU:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=QaJlgLd9z-c:vXeJS21KZFU:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=QaJlgLd9z-c:vXeJS21KZFU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?i=QaJlgLd9z-c:vXeJS21KZFU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=QaJlgLd9z-c:vXeJS21KZFU:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tucaz/~4/QaJlgLd9z-c" height="1" width="1"/&gt;</content><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.tucaz.net/2010/04/18/a-caminho-do-zen/feed/</wfw:commentRss><slash:comments xmlns:slash="http://purl.org/rss/1.0/modules/slash/">8</slash:comments><feedburner:origLink>http://blog.tucaz.net/2010/04/18/a-caminho-do-zen/</feedburner:origLink></entry><entry><title type="text">Você é importante?</title><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tucaz/~3/DQzTx1wSmf0/" /><category term="Leadership" /><category term="Management" /><category term="Carreira" /><category term="Motivação" /><author><name>tucaz</name></author><updated>2010-03-02T18:50:51-08:00</updated><id>http://blog.tucaz.net/?p=427</id><summary type="html">Reza a lenda[1] que, trabalhando na Apple, a qualquer momento você pode encontrar Steve Jobs e ouvir dele a seguinte pergunta: &amp;#8220;O que você faz aqui?&amp;#8221; e, caso ele não goste da resposta você pode ser demitido na hora.
Apesar de essa ser uma atitude drástica, acho que faz bastante sentido, principalmente no cenário de desenvolvimento [...]</summary><content type="html">&lt;p&gt;Reza a lenda[1] que, trabalhando na Apple, a qualquer momento você pode encontrar Steve Jobs e ouvir dele a seguinte pergunta: &amp;#8220;O que você faz aqui?&amp;#8221; e, caso ele não goste da resposta você pode ser demitido na hora.&lt;/p&gt;
&lt;p&gt;Apesar de essa ser uma atitude drástica, acho que faz bastante sentido, principalmente no cenário de desenvolvimento de software. Alguma vez você já se perguntou o que &lt;strong&gt;realmente&lt;/strong&gt; faz na empresa onde trabalha? Se a resposta for tão simples como &amp;#8220;escrevo código&amp;#8221; talvez você esteja prestes a ser (merecidamente) &lt;span style="text-decoration: line-through;"&gt;demitido&lt;/span&gt; promovido ao mercado de trabalho . Mesmo como programador seu trabalho não é apenas escrever código, mas sim transformar idéias em maravilhas tecnológicas que vão fazer seu usuário delirar e com isso agregar valor para a empresa ou qualquer outra coisa que o valha. Isso vale para todas as posições.&lt;/p&gt;
&lt;p&gt;Desde gerentes (que tradicionalmente só controlam cronogramas, ou seja, fazem nada) até gerentes de produto que ficam pra cima e pra baixo mandando as pessoas fazerem coisas. O ponto é, se você não contribui para o produto final você é &lt;strong&gt;inútil, totalmente dispensável e deveria arrumar uma outra coisa pra fazer&lt;/strong&gt;. Sua contribuição não precisa ser necessariamente técnica (com código), mas também com soft skills (organização, segurança, criatividade, etc) que ajudem efetivamente seu time a chegar ao objetivo.&lt;/p&gt;
&lt;p&gt;Acho que esse é um ponto importante de reflexão. Para sermos melhores no que fazemos temos que entender realmente o que queremos e temos de fazer.&lt;/p&gt;
&lt;p&gt;O que você acha?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;[1]&lt;/strong&gt; &amp;#8211; Segundo relatos existentes de (ex) funcionários no livro &amp;#8220;A cabeça de Steve Jobs&amp;#8221;&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=DQzTx1wSmf0:gVIqxXnfmkQ:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=DQzTx1wSmf0:gVIqxXnfmkQ:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?i=DQzTx1wSmf0:gVIqxXnfmkQ:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=DQzTx1wSmf0:gVIqxXnfmkQ:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=DQzTx1wSmf0:gVIqxXnfmkQ:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?i=DQzTx1wSmf0:gVIqxXnfmkQ:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=DQzTx1wSmf0:gVIqxXnfmkQ:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tucaz/~4/DQzTx1wSmf0" height="1" width="1"/&gt;</content><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.tucaz.net/2010/03/02/voce-e-importante/feed/</wfw:commentRss><slash:comments xmlns:slash="http://purl.org/rss/1.0/modules/slash/">5</slash:comments><feedburner:origLink>http://blog.tucaz.net/2010/03/02/voce-e-importante/</feedburner:origLink></entry><entry><title type="text">Cuidado com os especialistas!</title><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tucaz/~3/XFS9xUQmgI4/" /><category term="Uncategorized" /><author><name>tucaz</name></author><updated>2010-02-23T18:42:30-08:00</updated><id>http://blog.tucaz.net/?p=425</id><summary type="html">Conhece um especialista? Eu conheço um monte, e você?</summary><content type="html">&lt;p&gt;Hoje em dia com toda essa modernidade (como diria minha vovó) e a facilidade na disseminação da informação que a internet nos trouxe surgem a cada dia mais e mais especialistas. Em cada esquina da internet é possível encontrar um. Não importa o assunto.&lt;/p&gt;
&lt;p&gt;O cara começa com um blog ou um grupo de discussão, manda bastante tweets, adiciona uma pitada de promoção pessoal em todo canto, dai avança pra meia dúzia de palestras e até se propõe a ministrar um curso sobre o assunto. De repente, em poucos tempo virou especialista &lt;strong&gt;E&lt;/strong&gt; referência no assunto!&lt;/p&gt;
&lt;p&gt;Vendo tanta propaganda você deve achar que o cara tem muita experiência e é uma ótima fonte de informação. Boa fonte de informação pode até ser, mas repetir tudo que ve como um papagaio é ser um especialista? Ministrar cursos e posar de conhecedor do assunto apenas com conhecimento teórico é suficiente? É ético?&lt;/p&gt;
&lt;p&gt;Será que é essa mesmo a definição de especialista que procuramos? Ainda mais sobre assuntos não técnicos ou &lt;a title="Definição de Soft Skills by Wikipedia" href="http://en.wikipedia.org/wiki/Soft_skills" target="_self"&gt;soft-skills&lt;/a&gt; onde toda a bagagem e experiência que podemos conferir é escrita/falada?  São essas nossas referências?&lt;/p&gt;
&lt;p&gt;Tenha cuidado quando alguém lhe apresentar o título de &amp;#8220;Especialista em XYZ&amp;#8221;. Papel e meios de comunicação similares aceitam qualquer coisa, já dizia minha professora na quina série.&lt;/p&gt;
&lt;p&gt;Infelizmente não há maneiras práticas e fáceis de reconhecer falsos especialistas. O único jeito é desconfiar sempre e não disseminar informações baseadas na &lt;a title="Appeal to Authority - Falacy" href="http://www.nizkor.org/features/fallacies/appeal-to-authority.html" target="_self"&gt;falácia da autoridade&lt;/a&gt;. Seus amigos, seu chefe e seu bolso agradecem!&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=XFS9xUQmgI4:4Ar5N7rgNtI:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=XFS9xUQmgI4:4Ar5N7rgNtI:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?i=XFS9xUQmgI4:4Ar5N7rgNtI:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=XFS9xUQmgI4:4Ar5N7rgNtI:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=XFS9xUQmgI4:4Ar5N7rgNtI:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?i=XFS9xUQmgI4:4Ar5N7rgNtI:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=XFS9xUQmgI4:4Ar5N7rgNtI:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tucaz/~4/XFS9xUQmgI4" height="1" width="1"/&gt;</content><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.tucaz.net/2010/02/23/cuidado-com-os-especialistas/feed/</wfw:commentRss><slash:comments xmlns:slash="http://purl.org/rss/1.0/modules/slash/">5</slash:comments><feedburner:origLink>http://blog.tucaz.net/2010/02/23/cuidado-com-os-especialistas/</feedburner:origLink></entry><entry><title type="text">Lidando melhor com WCF – Ciclo de vida no cliente</title><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tucaz/~3/9fNLvM6Z0kw/" /><category term="Arquitetura" /><category term="C#" /><category term="Desenvolvimento" /><category term="WCF" /><category term="channelfactory" /><category term="performance" /><author><name>tucaz</name></author><updated>2010-02-23T09:02:31-08:00</updated><id>http://blog.tucaz.net/?p=415</id><summary type="html">Início de uma pequena série a respeito de melhores práticas no uso do WCF em .NET. Neste primeiro post falo a respeito do ChannelFactory&lt;t&gt; e como seu ciclo de vida deve ser gerenciado. &lt;/t&gt;</summary><content type="html">&lt;p&gt;&lt;strong&gt;&lt;em&gt;&amp;lt;Importante&amp;gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Todos sabem que WCF é uma plataforma poderosa e extensível. O que muita gente não sabe é que WCF é para poucos.&lt;/p&gt;
&lt;p&gt;WCF é uma plataforma que permite a construção de sistemas distribuidos e sistemas distribuidos raramente são necessários. De maneira simplificada, podemos dizer que um sistema é distribuido quando tem seus componentes instalados em mais de um computador.&lt;/p&gt;
&lt;p&gt;O problema da construção de sistemas distribuídos é que devido a não centralização de seus compnentes existe um overhead de comunicação entre os computadores e serialização/deserialização de objetos e isso consome muita memória e banda de rede.&lt;/p&gt;
&lt;p&gt;Como gastamos mais recursos do que necessário temos como resultado final um aumento no tempo de resposta e gasto extra de hardware que, as vezes pode ser um problema grave além é claro do aumento da complexidade técnica.&lt;/p&gt;
&lt;p&gt;No entanto, não sei por qual motivo, no momento em que lançou o produto, a Microsoft esqueceu de avisar seus &amp;#8220;consumidores&amp;#8221; a respeito destes pequenos detalhes. Talvez porque queria promover o produto?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;lt;/Importante&amp;gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&amp;lt;Importante 2&amp;gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;WCF é uma tecnologia relativamente simples, mas apenas depois que você entende o BeABá da coisa (ou ABC&lt;strong&gt;[1]&lt;/strong&gt; no caso do WCF). Até lá, qualquer coisa que fuja do point&amp;amp;click que o Visual Studio nos oferece é relativamente complexo.&lt;/p&gt;
&lt;p&gt;Portanto, sugiro que antes de aplicar WCF você procure entender um pouco mais dos fundamentos e do papel de cada objeto que ele utiliza.&lt;strong&gt; &lt;/strong&gt;&lt;strong&gt; &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;&amp;lt;/Importante 2&amp;gt;&lt;/em&gt;&lt;br /&gt;
&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Agora que entendemos que não devemos usar WCF em toda aplicação que construimos (talvez isso seja tópico pra outro post?) vou falar um pouco da experiência que estou tendo com esta tecnologia e das boas práticas e atalhos que conheci.&lt;/p&gt;
&lt;p&gt;Pretendo fazer uma pequena série e pra começar vou abordar boas práticas de consumo de serviços WCF, ou em outras palavras, como acessar um serviço WCF a partir de um cliente da maneira mais eficiente possível.&lt;/p&gt;
&lt;p&gt;Para que seja possível consumir um serviço WCF é necessário que alguém o tenha publicado e também que tenha disponibilizado o WSDL&lt;strong&gt;[2]&lt;/strong&gt; do serviço.&lt;/p&gt;
&lt;p&gt;O WSDL nada mais é do que um arquivo XML que descreve quais são os tipos de dados que o serviço irá trafegar e quais operações ele oferece.&lt;/p&gt;
&lt;p&gt;Geralmente, assim que temos um WSDL para consumir vamos ao Visual Studio e utilizamos a funcionalidade de &lt;em&gt;Add Service Reference&lt;/em&gt; que ele nos oferece para gerar o objeto proxy que irá cuidar pra nós da comunicação com WCF. A partir dai utilizamos este objeto em toda nossa aplicação&lt;em&gt;&lt;/em&gt;. E este é o nosso maior erro.&lt;/p&gt;
&lt;p&gt;Este proxy, gerado pelo Wizard, encapsula todas as classes necessárias para ler o WSDL, criar os tipos necessários e lidar com os canais de comunicação em cada operação que executamos. No entanto, ele o faz da &lt;strong&gt;pior&lt;/strong&gt; maneira possível.&lt;/p&gt;
&lt;p&gt;Cada vez que invocamos uma operação através deste proxy, ele cria uma instância da classe &lt;a title="ChannelFactory&amp;lt;T&amp;gt; @ Msdn.com" href="http://msdn.microsoft.com/en-us/library/ms576132.aspx" target="_self"&gt;ChannelFactory&amp;lt;T&amp;gt;&lt;/a&gt;. Esta classe é responsável por ler as configurações definidas em nosso app.config e baseado nestas configurações abrir os canais de comunicação com o serviço que iremos consumir. Este processo é &lt;strong&gt;muito lento&lt;/strong&gt;, pois todos os sockets, listeners e objetos necessários da própria infra estrutura do WCF são criados e configurados neste momento.&lt;/p&gt;
&lt;p&gt;No entanto, este processo não precisa ser feito a cada chamada para o serviço WCF uma vez que estas informações não mudarão enquanto a aplicação estiver rodando. Então, para otimizar bastante o consumo de serviços devemos ignorar o proxy gerado pelo Wizard e cuidar da criação e destruição de canais nós mesmos mantendo este objeto (ChannelFactory&amp;lt;T&amp;gt;) como &lt;a title="Singleton @ Wikipedia.org" href="http://pt.wikipedia.org/wiki/Singleton" target="_self"&gt;Singleton&lt;/a&gt; que irá durar pelo tempo de vida da aplicação. Dessa forma toda vez que chamamos uma operação remota não existe a necessidade de executar o setup e tear down desse objeto.&lt;/p&gt;
&lt;p&gt;Para facilitar a gerência desses objetos construi uma pequena DLL que é composta apenas de uma classe. O código está disponível no &lt;a title="Communications Manager @ GitHub" href="http://github.com/tucaz/CommunicationsManager" target="_self"&gt;github&lt;/a&gt; e a &lt;a title="Communications Manager @ GitHub" href="http://github.com/tucaz/CommunicationsManager/downloads" target="_self"&gt;DLL compilada está aqui&lt;/a&gt;. A &lt;a title="Communications Manager Docs @ GitHub" href="http://wiki.github.com/tucaz/CommunicationsManager/"&gt;documentação inicial também está lá&lt;/a&gt;. Tudo pronto para ser usado.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Referências adicionais (e importantes)&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a title="Performance Improvement for WCF Client Proxy Creation in .NET 3.5 and Best Practices @ Wenlong Dong's Blog" href="http://blogs.msdn.com/wenlong/archive/2007/10/27/performance-improvement-of-wcf-client-proxy-creation-and-best-practices.aspx" target="_self"&gt;Performance improvement for WCF client proxy creation in .NET 3.5 and best practices @ Wenlong Dong&amp;#8217;s Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a title="Internals - Proxy de Serviço WCF @ Israel Aece" href="http://www.israelaece.com/post/Internals-Proxy-de-servicos-WCF.aspx" target="_self"&gt;Internals &amp;#8211; Proxy de Serviços WCF @ Israel Aece&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a title="WCF Client Channel Pool - Improved Client Performance @ Glavs Blog" href="http://weblogs.asp.net/pglavich/archive/2007/05/07/wcf-client-channel-pool-improved-client-performance.aspx"&gt;WCF Client Channel Pool &amp;#8211; Improved Client Performance @ Glavs Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/1825990/wcf-channelfactory-and-channel-caching-in-asp-net-client-application" target="_self"&gt;Bate papo que me levou a este componente @ StackOverflow&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;[1]&lt;/strong&gt; ABC = Address, Bindings e Contracts&lt;br /&gt;
&lt;strong&gt;[2]&lt;/strong&gt; É possível consumir um serviço WCF sem acesso ao WSDL, mas este é um cenário pouco comum&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=9fNLvM6Z0kw:w6ZZSLL8Ecg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=9fNLvM6Z0kw:w6ZZSLL8Ecg:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?i=9fNLvM6Z0kw:w6ZZSLL8Ecg:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=9fNLvM6Z0kw:w6ZZSLL8Ecg:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=9fNLvM6Z0kw:w6ZZSLL8Ecg:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?i=9fNLvM6Z0kw:w6ZZSLL8Ecg:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=9fNLvM6Z0kw:w6ZZSLL8Ecg:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tucaz/~4/9fNLvM6Z0kw" height="1" width="1"/&gt;</content><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.tucaz.net/2010/02/23/lidando-com-wcf-ciclo-de-vida-no-cliente/feed/</wfw:commentRss><slash:comments xmlns:slash="http://purl.org/rss/1.0/modules/slash/">2</slash:comments><feedburner:origLink>http://blog.tucaz.net/2010/02/23/lidando-com-wcf-ciclo-de-vida-no-cliente/</feedburner:origLink></entry><entry><title type="text">[Off-Topic] Problemas com monitor Samsung e exemplo de péssimo atendimento</title><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/tucaz/~3/2pAN9aSGJgo/" /><category term="Uncategorized" /><category term="autorizada" /><category term="monitor" /><category term="problema" /><category term="samsung" /><author><name>tucaz</name></author><updated>2010-02-13T04:32:58-08:00</updated><id>http://blog.tucaz.net/?p=412</id><summary type="html">Inexistência de qualidade no atendimento ao consumidor prestado pela Samsung.</summary><content type="html">&lt;p&gt;Não costumo fazer esse tipo de off-topic, mas essa situação me revolta simplesmente pelo fato de não poder fazer nada além de reclamar e &amp;#8220;chorar&amp;#8221; por ai.&lt;/p&gt;
&lt;p&gt;Em dezembro de 2007 adquiri um monitor Samsung 2232BW pelo valor de &lt;strong&gt;R$1027,00&lt;/strong&gt;. Até onde eu sei esse valor não é baixo e tem gente que não ganha isso em um ano inteiro de trabalho.&lt;/p&gt;
&lt;p&gt;Pouco mais de 2 anos passados, mês passado ele começou a apresentar um problema com seu painel. Isso já me deixou p*** da vida, pois 2 anos de vida útil em um produto deste valor é rídiculo. Meu CRT 17 nunca deu um problema em quase 5 anos que ficou em uso.&lt;/p&gt;
&lt;p&gt;Como um monitor equivalente hoje custa na faixa de R$500, decidi que valeria a pena tentar levar meu monitor para conserto e caso o custo do serviço ficasse em até R$200,00 acredito que compensaria.&lt;/p&gt;
&lt;p&gt;Procurei no site da Samsung as assistências técnicas autorizadas, que apesar de serem terceirizadas, levam o nome Samsung e deveriam responder com o  mesmo padrão de qualidade que a Samsung vende em seus produtos e encontrei 3 em um ráio de 20km da minha casa. Fui as três e realmente conclui que elas atendem seguinde o mesmo padrão inexistente de qualidade da Samsung com filas de mais de uma hora e meia apenas para ser atendido na recepção pra tentar descobrir se é possível o conserto e qual seria o valor.&lt;/p&gt;
&lt;p&gt;Conclusão: é mais fácil ser atendido no poupa tempo ou em um posto do INSS do que em um serviço autorizado da Samsung que iria &lt;em&gt;&lt;strong&gt;receber&lt;/strong&gt;&lt;/em&gt; pelo atendimento.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Obrigado Samsung pelos momentos de frustração e pela demonstração de como operar um negócio onde o cliente claramente não tem importância nenhuma além, é claro, de me colocar em uma posição onde eu tenha que implorar para ter meu monitor consertado!&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=2pAN9aSGJgo:qNX5J5LvFMg:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=2pAN9aSGJgo:qNX5J5LvFMg:D7DqB2pKExk"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?i=2pAN9aSGJgo:qNX5J5LvFMg:D7DqB2pKExk" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=2pAN9aSGJgo:qNX5J5LvFMg:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=2pAN9aSGJgo:qNX5J5LvFMg:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?i=2pAN9aSGJgo:qNX5J5LvFMg:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/tucaz?a=2pAN9aSGJgo:qNX5J5LvFMg:7Q72WNTAKBA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/tucaz?d=7Q72WNTAKBA" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/tucaz/~4/2pAN9aSGJgo" height="1" width="1"/&gt;</content><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blog.tucaz.net/2010/02/13/off-topic-problemas-com-monitor-samsung-e-exemplo-de-pessimo-atendimento/feed/</wfw:commentRss><slash:comments xmlns:slash="http://purl.org/rss/1.0/modules/slash/">1</slash:comments><feedburner:origLink>http://blog.tucaz.net/2010/02/13/off-topic-problemas-com-monitor-samsung-e-exemplo-de-pessimo-atendimento/</feedburner:origLink></entry></feed>

