<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-911701488457280480</id><updated>2024-12-14T17:09:05.245-08:00</updated><category term="Delphi"/><category term="Hudson"/><category term="Integração Contínua"/><category term="Padrões de Projeto"/><category term="Subversion"/><category term="Banco de dados"/><category term="DCC32"/><category term="DUnit"/><category term="Factory"/><category term="Singleton"/><category term="Strategy"/><category term="TDD"/><category term="git"/><category term="github"/><category term="teste unitários"/><category term="Delphi XE2"/><category term="DiffMerge"/><category term="GDD"/><category term="Google Maps"/><category term="Java"/><category term="Json"/><category term="LiveBinding"/><category term="Log4j"/><category term="Mock"/><category term="MongoDB"/><category term="NoSQL"/><category term="Oracle"/><category term="Podcast"/><category term="PostgreSQL"/><category term="Sql"/><category term="Tomcat"/><category term="TortoiseSVN"/><category term="Xml"/><title type='text'>Fabricio DEV</title><subtitle type='html'>Conteúdo sobre diversos assuntos relacionados à desenvolvimento de software</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://fabriciodev.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://fabriciodev.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Fabricio Colombo</name><uri>http://www.blogger.com/profile/06951517260984102149</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCedF2z6z0D9d8Adr564w0ZJwcy2ckdFrC48QG9iQ9roQTh2R7yylksaD9ccou06b0HoZ-S_Did-aXDwGIUuaHVO6Aw398CK6KbnI4bEkKbiYC8M_8rp5_so6uPrqGX1A/s220/unnamed.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>23</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-911701488457280480.post-8729693926924796402</id><published>2012-11-24T07:13:00.001-08:00</published><updated>2013-01-14T10:25:46.655-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Delphi"/><category scheme="http://www.blogger.com/atom/ns#" term="MongoDB"/><category scheme="http://www.blogger.com/atom/ns#" term="NoSQL"/><title type='text'>Instalando MongoDB no windows</title><content type='html'>É um fato que os &quot;bancos de dados&quot; chamados NoSQL(Not only Sql) estão ganhando cada vez mais destaque, pela sua versatilidade e performance. São implementações para armazenar tipos de dados específicos como: key-value (redis, riak), document(CouchDB, MongoDB), column family(Cassandra, H-Base), graph(Neo4j).&lt;br /&gt;
&lt;br /&gt;
Eu optei por experimentar o &lt;a href=&quot;http://www.mongodb.org&quot;&gt;MongoDB&lt;/a&gt;, pois além de ser um dos mais populares, &lt;a name=&#39;more&#39;&gt;&lt;/a&gt; o mesmo possui opção de download para windows 32-bit e 64bit, e também existem driver&#39;s disponíveis para Delphi, são eles: &lt;a href=&quot;https://github.com/stijnsanders/TMongoWire&quot;&gt;TMongoWire&lt;/a&gt;, &lt;a href=&quot;http://code.google.com/p/pebongo/&quot;&gt;pebongo&lt;/a&gt; e também um driver de minha autoria &lt;a href=&quot;https://github.com/fabriciocolombo/mongo-delphi-driver&quot;&gt;mongo-delphi-driver&lt;/a&gt;. Hoje vou me ater apenas a instalação e acesso ao MongoDB pelo shell, mais num próximo artigo vou abordar o consumo do serviço pelo Delphi. &lt;br /&gt;
&lt;br /&gt;
Confira &lt;a href=&quot;http://www.mongodb.org/display/DOCS/Drivers&quot;&gt;aqui&lt;/a&gt; os demais drivers existentes e tutoriais específico de cada driver.&lt;br /&gt;
&lt;br /&gt;
Você pode baixar a instalador compatível com o seu SO &lt;a href=&quot;http://www.mongodb.org/downloads&quot;&gt;aqui&lt;/a&gt;. E reforçando o aviso do site, a versão de 32-bit suporta algo em torno de 2GB de dados, portanto, deve ser utilizada apenas para testes. Se você for utilizar Windows Server 2008 R2 x64, Windows 7 x64, ou Windows 8 x64, há um build específico otimizado para estas versões.&lt;br /&gt;
&lt;br /&gt;
Depois de fazer o download do MongoDB, descompacte o arquivo em um local de sua preferência. Na pasta &lt;b&gt;bin&lt;/b&gt;, vem um conjunto de componentes e utilitários, conforme segue:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: text&quot;&gt;COMPONENTS
  bin/mongod - The database process.
  bin/mongos - Sharding controller.
  bin/mongo  - The database shell (uses interactive javascript).

UTILITIES
  bin/mongodump         - MongoDB dump tool - for backups, snapshots, etc..
  bin/mongorestore      - MongoDB restore a dump
  bin/mongoexport       - Export a single collection to test (JSON, CSV)
  bin/mongoimport       - Import from JSON or CSV
  bin/mongofiles        - Utility for putting and getting files from MongoDB GridFS
  bin/mongostat         - Show performance statistics

&lt;/pre&gt;&lt;br /&gt;
Aqui vamos usar apenas o mongod e mongo. Por padrão, o mongodb armazena os dados na pasta &quot;\data\db&quot;, e você precisa criar esse diretório manualmente, ele não cria de forma automática. Eu particularmente, prefiro deixar dentro da pasta onde estão instalado o mongo, ficando assim:&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKaZhOOOK5QV3ZrDXjCP3EF-puhk_GNMthWYSUbzZYPmzz6_kwIyJD1fFvwU-BVphVTp3GsiAyS1qBV7mQExyi9b479BqsR60RdUMw2ovpEku5cBgiuFlMiE_eqRNoMYW0RlZxxHqdBEO2/s1600/mongodir.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left:1em; margin-right:1em&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;82&quot; width=&quot;115&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKaZhOOOK5QV3ZrDXjCP3EF-puhk_GNMthWYSUbzZYPmzz6_kwIyJD1fFvwU-BVphVTp3GsiAyS1qBV7mQExyi9b479BqsR60RdUMw2ovpEku5cBgiuFlMiE_eqRNoMYW0RlZxxHqdBEO2/s320/mongodir.PNG&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Para que ele reconheça o diretório, é preciso passar o parâmetro &quot;--dbpath [dir]&quot; na inicialização do banco de dados. Também é possível modificar a porta que ele deve usar. Para consultar as demais configurações, utilize &quot;mongod --help&quot;. O comando abaixo inicia o serviço:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;terminal&quot;&gt;&lt;span class=&quot;codeline&quot;&gt;$ mongod --dbpath C:\mongodb\data\db --port 27017 --verbose&lt;/span&gt;
&lt;/pre&gt;&lt;br /&gt;
Feito isso, você deve visualizar uma saída como essa, indicando que o servidor foi iniciado e está aguardando conexões:&lt;br /&gt;
&lt;pre class=&quot;terminal&quot;&gt;&lt;span class=&quot;codeline&quot;&gt;C:\mongodb\bin&gt;mongod --dbpath c:\mongodb\data\db --port 27017&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;(...)&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;(...)&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;(...)&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;[initandlisten] waiting for connections on port 27017&lt;/span&gt;
&lt;/pre&gt;&lt;br /&gt;
Agora podemos brincar com o shell interativo. Execute o aplicativo mongo.exe e será aberto um shell conectado ao database &quot;test&quot;, que é o default. Então digite os comandos abaixo para ver o resultado.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;terminal&quot;&gt;&lt;span class=&quot;codeline&quot;&gt;C:\&gt; cd \mongodb\bin&lt;/span&gt;
&lt;span class=&quot;codeline&quot;&gt;C:\mongodb\bin&gt; mongo&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;MongoDB shell version: 2.0.2&lt;/span&gt;
&lt;span class=&quot;codeline&quot;&gt;&gt; db //mostra o database atual&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;test&lt;/span&gt;
&lt;span class=&quot;codeline&quot;&gt;&gt; db.foo.insert( { a : 1 } ) //Cria a collection &quot;foo&quot; e  insere um documento com a chave/valor a=1&lt;/span&gt;
&lt;span class=&quot;codeline&quot;&gt;&gt; db.foo.find() //Lista todos os objetos inserido na collection&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;{ _id : ..., a : 1 }&lt;/span&gt;
&lt;span class=&quot;codeline&quot;&gt;&gt; db.foo.insert( { b : 2 } ) //Insere um segundo objeto&lt;/span&gt;
&lt;span class=&quot;codeline&quot;&gt;&gt; db.foo.find()&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;{ _id : ..., a : 1 }&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;{ _id : ..., b : 2 }&lt;/span&gt;
&lt;span class=&quot;codeline&quot;&gt;&gt; show dbs //lista os databases existentes&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;local   (empty)&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;test    0.03125GB&lt;/span&gt;
&lt;span class=&quot;codeline&quot;&gt;&gt; show collections&lt;/span&gt; //lista as collections existentes
&lt;span class=&quot;bash-output&quot;&gt;foo&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;system.indexes&lt;/span&gt;
&lt;span class=&quot;codeline&quot;&gt;&gt; help&lt;/span&gt; //Mostra os demais comandos disponíveis 
&lt;/pre&gt;&lt;br /&gt;
Por isso era isso, em breve trago exemplos de como efetuar esse acesso pelo Delphi.</content><link rel='replies' type='application/atom+xml' href='http://fabriciodev.blogspot.com/feeds/8729693926924796402/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://fabriciodev.blogspot.com/2012/11/instalando-mongodb-no-windows.html#comment-form' title='4 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/8729693926924796402'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/8729693926924796402'/><link rel='alternate' type='text/html' href='http://fabriciodev.blogspot.com/2012/11/instalando-mongodb-no-windows.html' title='Instalando MongoDB no windows'/><author><name>Fabricio Colombo</name><uri>http://www.blogger.com/profile/06951517260984102149</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCedF2z6z0D9d8Adr564w0ZJwcy2ckdFrC48QG9iQ9roQTh2R7yylksaD9ccou06b0HoZ-S_Did-aXDwGIUuaHVO6Aw398CK6KbnI4bEkKbiYC8M_8rp5_so6uPrqGX1A/s220/unnamed.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiKaZhOOOK5QV3ZrDXjCP3EF-puhk_GNMthWYSUbzZYPmzz6_kwIyJD1fFvwU-BVphVTp3GsiAyS1qBV7mQExyi9b479BqsR60RdUMw2ovpEku5cBgiuFlMiE_eqRNoMYW0RlZxxHqdBEO2/s72-c/mongodir.PNG" height="72" width="72"/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-911701488457280480.post-1010783478065331775</id><published>2012-09-23T18:38:00.001-07:00</published><updated>2014-01-21T12:02:31.695-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Delphi"/><title type='text'>Instalando Indy 10 no Delphi 7</title><content type='html'>Olá, recentemente surgiu a necessidade de consumir recursos &lt;a href=&quot;http://www.infoq.com/br/articles/rest-introduction&quot;&gt;REST&lt;/a&gt; utilizando o Delphi, no caso a versão XE2, mas muitos projetos ainda utilizam delphi 7. O Delphi XE2 vem com a versão 10 da biblioteca Indy, e funcionou muito bem, e quando fui testar no Delphi 7, que vem com Indy 9, surgiram vários problemas na manipulação dos códigos de retorno HTTP, e para resolver isso decidi atualizar a versão da biblioteca indy do Delphi 7, da versão 9 para a versão 10.&lt;br /&gt;
&lt;br /&gt;
Para começar baixe a versão mais recente através do endereço &lt;a href=&quot;http://indy.fulgan.com/ZIP/&quot;&gt;http://indy.fulgan.com/ZIP&lt;/a&gt;, no momento desta publicação, a última versão disponível é o build 4782. &lt;br /&gt;
&lt;br /&gt;
No Delphi 7, vá na opção &lt;b&gt;Component\Install Packages&lt;/b&gt;, localize a biblioteca Indy conforme a imagem abaixo, e remova a biblioteca clicando no botão &lt;b&gt;Remove&lt;/b&gt;. &lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisLvnXEhepIJ4PHMtV8Ecip_jvvitJNhFN6cAS4aVcjAb0ipnDj_PV0pas_jLd7GSVZRXAxHBv6sfnUrwyUpUUBphbti8Uqn0NTrWWs2ovQgrdi3MgynFQRMzdQeM8IhOPwfxeqnmTYXmz/s1600/RemoverIndy9.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left:1em; margin-right:1em&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;302&quot; width=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisLvnXEhepIJ4PHMtV8Ecip_jvvitJNhFN6cAS4aVcjAb0ipnDj_PV0pas_jLd7GSVZRXAxHBv6sfnUrwyUpUUBphbti8Uqn0NTrWWs2ovQgrdi3MgynFQRMzdQeM8IhOPwfxeqnmTYXmz/s320/RemoverIndy9.PNG&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Feche o Delphi, pois é preciso remover as referências do Indy 9 na pasta de instalação do delphi. Vá até a pasta onde o delphi está instalado, por padrão &quot;C:\Program Files\Borland\Delphi7&quot;. Renomeie os arquivos do Indy adicionando o sufixo indy9, caso você queirar restaurar em outro momento, ou apague os arquivos se sentir a vontade. Deve ficar conforme segue:&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;Bin\indy70.bpl&lt;/b&gt; para &lt;b&gt;Bin\indy70_indy9.bpl&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Bin\indy70.map&lt;/b&gt; para &lt;b&gt;Bin\indy70_indy9.map&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Bin\dclindy70.bpl&lt;/b&gt; para &lt;b&gt;Bin\dclindy70_indy9.bpl&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Bin\dclindy70.map&lt;/b&gt; para &lt;b&gt;Bin\dclindy70_indy9.map&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Lib\indy.dcp&lt;/b&gt; para &lt;b&gt;Lib\indy_indy9.dcp&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Lib\indy.dcu&lt;/b&gt; para &lt;b&gt;Lib\indy_indy9.dcu&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Lib\dclindy.dcp&lt;/b&gt; para &lt;b&gt;Lib\dclindy_indy9.dcp&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Lib\dclindy.dcu&lt;/b&gt; para &lt;b&gt;Lib\dclindy_indy9.dcu&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Source\Indy&lt;/b&gt; para &lt;b&gt;Source\Indy_9&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
Remova também todos os dcu&#39;s existentes dentro das pastas Lib e Lib\Debug, que tenham o nome iniciado com &quot;id&quot;, por exemplo, &quot;IdBaseComponent.dcu&quot;.&lt;br /&gt;
&lt;br /&gt;
Descompacte o arquivo que você baixou. Dentro há uma pasta &lt;b&gt;Lib&lt;/b&gt; e um arquivo &lt;b&gt;Fulld7.bat&lt;/b&gt; que compila e instala para você, mais preferi fazer a instalação manualmente, para isso, é preciso compilar e instalar os seguintes pacotes, na sequência que segue:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;IndySystem70.dpk (in Lib\System) --&gt; Apenas Compila&lt;/li&gt;
&lt;li&gt;IndyCore70.dpk (in Lib\Core) --&gt; Apenas Compila&lt;/li&gt;
&lt;li&gt;IndyProtocols70.dpk (in Lib\Protocols) --&gt; Apenas Compila&lt;/li&gt;
&lt;li&gt;dclIndyCore70.dpk (in Lib\Core) --&gt; Compila e Instala&lt;/li&gt;
&lt;li&gt;dclIndyProtocols70.dpk (in Lib\Protocols) --&gt; Compila e Instala&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
Agora só falta adicionar os novos arquivos ao LibraryPath do delphi:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;C:\Indy10\Lib\System&lt;/li&gt;
&lt;li&gt;C:\Indy10\Lib\Core&lt;/li&gt;
&lt;li&gt;C:\Indy10\Lib\Protocols&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
Era isso, agora seu Delphi 7 pode usufruir das melhorias e correção de bugs adicionadas ao Indy 10.&lt;br /&gt;
&lt;br /&gt;
Qualque dúvida ou problema durante a atualização deixe um comentário.</content><link rel='replies' type='application/atom+xml' href='http://fabriciodev.blogspot.com/feeds/1010783478065331775/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://fabriciodev.blogspot.com/2012/09/instalando-indy-10-no-delphi-7.html#comment-form' title='24 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/1010783478065331775'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/1010783478065331775'/><link rel='alternate' type='text/html' href='http://fabriciodev.blogspot.com/2012/09/instalando-indy-10-no-delphi-7.html' title='Instalando Indy 10 no Delphi 7'/><author><name>Fabricio Colombo</name><uri>http://www.blogger.com/profile/06951517260984102149</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCedF2z6z0D9d8Adr564w0ZJwcy2ckdFrC48QG9iQ9roQTh2R7yylksaD9ccou06b0HoZ-S_Did-aXDwGIUuaHVO6Aw398CK6KbnI4bEkKbiYC8M_8rp5_so6uPrqGX1A/s220/unnamed.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisLvnXEhepIJ4PHMtV8Ecip_jvvitJNhFN6cAS4aVcjAb0ipnDj_PV0pas_jLd7GSVZRXAxHBv6sfnUrwyUpUUBphbti8Uqn0NTrWWs2ovQgrdi3MgynFQRMzdQeM8IhOPwfxeqnmTYXmz/s72-c/RemoverIndy9.PNG" height="72" width="72"/><thr:total>24</thr:total></entry><entry><id>tag:blogger.com,1999:blog-911701488457280480.post-2759114542414243543</id><published>2012-08-06T17:59:00.000-07:00</published><updated>2012-08-06T18:03:10.207-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="git"/><category scheme="http://www.blogger.com/atom/ns#" term="github"/><title type='text'>Primeiros passos com git</title><content type='html'>Depois de uma pausa, retomarei o assunto sobre git. Hoje vou mostrar como criar um novo repositório e efetuar as operações básicas. Se você não sabe o que é git ou ainda não tem o git instalado, leia o post anterior: &lt;a href=&quot;http://fabriciodev.blogspot.com.br/2012/05/instalando-e-configurando-git-no.html&quot;&gt;Instalando e Configurando git no windows&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Para começar, abra o Git Bash no diretório onde você vai criar seu projeto, para efeitos de exemplo vou manter o projeto na raiz do drive C.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;terminal&quot;&gt;&lt;span class=&quot;codeline&quot;&gt;$ mkdir learning-git&lt;/span&gt;
&lt;span class=&quot;codeline&quot;&gt;$ cd learning-git&lt;/span&gt;
&lt;span class=&quot;codeline&quot;&gt;$ git init&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;  Initialized empty Git repository in c:/learning-git/.git/&lt;/span&gt;
&lt;span class=&quot;codeline&quot;&gt;$ touch README.md&lt;/span&gt;
&lt;/pre&gt;&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
O que fizemos até agora? Criamos um diretório &quot;learning-git&quot; e dentro dele criamos um novo repositório git. O command &quot;touch&quot; cria um arquivo em branco, é uma boa prática ter o arquivo README com as instruções básicas sobre o projeto. A extensão .md se refere a &lt;a href=&quot;https://github.com/github/markup&quot;&gt;Markdown&lt;/a&gt;. &lt;br /&gt;
&lt;br /&gt;
Antes de fazer o commit, vamos executar o seguinte commando para verificar as alterações.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;terminal&quot;&gt;&lt;span class=&quot;codeline&quot;&gt;$ git status&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;# On branch master&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;#                 &lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;# Initial commit  &lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;#                 &lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;# Untracked files:&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;#   (use &quot;git add &lt;file&gt;...&quot; to include in what will be committed)&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;#                                                                 &lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;#       README.md                                                 &lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;nothing added to commit but untracked files present (use &quot;git add&quot; to track)&lt;/span&gt;
&lt;/pre&gt;&lt;br /&gt;
Como podem ver ele reconheceu o arquivo README.md como não rastreado, isso quer dizer que o mesmo ainda não se encontra no repositório. Antes de efetuar o commit do arquivo é necessário adicionar o mesmo ao repositório;&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;terminal&quot;&gt;&lt;span class=&quot;codeline&quot;&gt;$ git add .&lt;/span&gt;
&lt;span class=&quot;codeline&quot;&gt;$ git commit -a -m &quot;Meu Primeiro Commit&quot;&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;[master (root-commit) 6b97712] Meu Primeiro Commit&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt; 1 files changed, 1 insertions(+), 0 deletions(-)&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;create mode 100644 README.md&lt;/span&gt;
&lt;/pre&gt;&lt;br /&gt;
O primeiro comando irá adicionar todos os arquivos incluídos/removidos/modificados no próximo commit. Agora você precisa acessar o github e criar um &lt;a href=&quot;https://github.com/new&quot;&gt;novo repositório&lt;/a&gt;, conforme o exemplo abaixo. Lembre-se de utilizar como &quot;Repository Name&quot; o mesmo nome você usou na sua máquina local.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSAvZmJF3PvYtQyvMpQPPNMtWWkXxRkX6cKGXzOIuIGH8FHWRf2Q07p9iwhK5MAhXvIX1s9R0RiEhcRNV-17bwU21d_tOcDj-r8FZ7GIo4oWLEnk7ewx_ZvAn4MxpP2LVMshponGO-ZErD/s1600/NewRepository.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left:1em; margin-right:1em&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;352&quot; width=&quot;600&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSAvZmJF3PvYtQyvMpQPPNMtWWkXxRkX6cKGXzOIuIGH8FHWRf2Q07p9iwhK5MAhXvIX1s9R0RiEhcRNV-17bwU21d_tOcDj-r8FZ7GIo4oWLEnk7ewx_ZvAn4MxpP2LVMshponGO-ZErD/s400/NewRepository.PNG&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Feito isso, vamos executar os comandos abaixo. &lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;terminal&quot;&gt;&lt;span class=&quot;codeline&quot;&gt;$ git remote add origin https://github.com/fabriciocolombo/learning-git.git&lt;/span&gt;
&lt;span class=&quot;codeline&quot;&gt;$ git push -u origin master&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;Username:fabriciocolombo&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;Password:*******&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;Counting objects: 3, done.&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;Writing objects: 100% (3/3), 245 bytes, done.&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;Total 3 (delta 0), reused 0 (delta 0)&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;To https://github.com/fabriciocolombo/learning-git.git&lt;/span&gt;
 &lt;span class=&quot;bash-output&quot;&gt;* [new branch]      master -&gt; master&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;Branch master set up to track remote branch master from origin.&lt;/span&gt;
&lt;/pre&gt;&lt;br /&gt;
O primeito commando vai associar o repositório local com o repositório remote. O segundo commando executa o &quot;push&quot;, que vai subir os dados locais para o servidor remoto, para isso será solicitado o seu usuário e senha do github.&lt;br /&gt;
&lt;br /&gt;
Eu recomendo fortemente a leitura de um artigo do &lt;a href=&quot;http://akitaonrails.com&quot;&gt;Fábio Akita&lt;/a&gt; sobre a utilização do git, aliás, ele possue vários posts sobre o assunto, mais recomendo um em especial que mostra de forma bem didática como trabalhar com branches, fazer merge e outros recursos bacãnas. O post é &lt;a href=&quot;http://akitaonrails.com/2008/04/02/micro-tutorial-de-git&quot;&gt;Micro Tutorial de Git&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Abraços e até a próxima.</content><link rel='replies' type='application/atom+xml' href='http://fabriciodev.blogspot.com/feeds/2759114542414243543/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://fabriciodev.blogspot.com/2012/08/primeiros-passos-com-git.html#comment-form' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/2759114542414243543'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/2759114542414243543'/><link rel='alternate' type='text/html' href='http://fabriciodev.blogspot.com/2012/08/primeiros-passos-com-git.html' title='Primeiros passos com git'/><author><name>Fabricio Colombo</name><uri>http://www.blogger.com/profile/06951517260984102149</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCedF2z6z0D9d8Adr564w0ZJwcy2ckdFrC48QG9iQ9roQTh2R7yylksaD9ccou06b0HoZ-S_Did-aXDwGIUuaHVO6Aw398CK6KbnI4bEkKbiYC8M_8rp5_so6uPrqGX1A/s220/unnamed.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSAvZmJF3PvYtQyvMpQPPNMtWWkXxRkX6cKGXzOIuIGH8FHWRf2Q07p9iwhK5MAhXvIX1s9R0RiEhcRNV-17bwU21d_tOcDj-r8FZ7GIo4oWLEnk7ewx_ZvAn4MxpP2LVMshponGO-ZErD/s72-c/NewRepository.PNG" height="72" width="72"/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-911701488457280480.post-4762532150674194356</id><published>2012-05-19T11:20:00.002-07:00</published><updated>2012-05-21T16:57:24.281-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="git"/><category scheme="http://www.blogger.com/atom/ns#" term="github"/><title type='text'>Instalando e Configurando git no windows</title><content type='html'>&lt;p&gt;
Olá pessoal, hoje vou falar um pouco sobre &lt;a href=&quot;http://git-scm.com&quot; target=&quot;_blank&quot;&gt;git&lt;/a&gt; e &lt;a href=&quot;https://github.com&quot; target=&quot;_blank&quot;/&gt;github&lt;/a&gt;. Git é um sistema de controle de versão distribuído (&lt;a href=&quot;http://en.wikipedia.org/wiki/Distributed_Version_Control_System&quot; target=&quot;_blank&quot;&gt;DVCS&lt;/a&gt;) free e open source, para saber mais sobre o mesmo, acesse o &lt;a href=&quot;http://git-scm.com/documentation&quot; target=&quot;_blank&quot;&gt;site&lt;/a&gt;. Github é um serviço de hospedagem de código fonte que utiliza o git como sistema de controle de versão, possuí planos gratuítos e comerciais, e é amplamente utilizado pela comunidade open source. O Github pode se considerado como uma rede social, onde você pode ser seguido e seguir os projetos de outras pessoas, pode facilmente enviar contribuições à projetos open source, e também há empresas, pelo menos lá fora, que tem utilizado o github como forma de avaliar a contratação de programadores. 
&lt;/p&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;
&lt;p&gt;
Nos sistemas de controle de versão distribuído, quando se faz um fork de um projeto, você obtêm uma cópia de todo o repositório do projeto, com todo o histórico de commits, e o seu projeto ainda vai continuar vinculado ao projeto original, sendo assim, se você implementar novas features ou correção de bugs, você pode enviar um pull request ao dono do projeto original, que pode incorporar sua solicitação de forma bastante simples.
&lt;/p&gt;
&lt;p&gt;
Se você chegou até aqui é porque está interessado em conhecer melhor o git, e a melhor forma de aprender é fazendo, não é mesmo? Então antes de prosseguir com a leitura, accesse o site e &lt;a href=&quot;http://git-scm.com/download/win&quot; target=&quot;_blank&quot;&gt;baixe&lt;/a&gt; a versão do git compatível com seu sistema operacional. Enquanto faz o download aproveita e dá um pulinho no github e &lt;a href=&quot;https://github.com/signup/free&quot; target=&quot;_blank&quot;&gt;faça o seu cadastro&lt;/a&gt;.
&lt;/p&gt;

A instalação do git é bastante simples, só modifiquei o diretório para instalar em &quot;C:\Git&quot;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqM9yFBt6j0cvZ12OnJ-yNTiN3I5MTc-9qBosW6ocZaR3hrl_TlzQXT8eSGLDm22G3BTrTg0P_ZSYjOzP_rfAWzMYOm57qhW9N67DOedGb4Ag94qTX6kQKLkbeqsu2joLry7vhYiJstBuo/s1600/01-Location.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left:1em; margin-right:1em&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;250&quot; width=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqM9yFBt6j0cvZ12OnJ-yNTiN3I5MTc-9qBosW6ocZaR3hrl_TlzQXT8eSGLDm22G3BTrTg0P_ZSYjOzP_rfAWzMYOm57qhW9N67DOedGb4Ag94qTX6kQKLkbeqsu2joLry7vhYiJstBuo/s320/01-Location.PNG&quot; rel=&quot;lightbox[instalacao]&quot;/&gt;&lt;/a&gt;&lt;/div&gt;

Na tela de componentes deixei a configuração default. 
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqGewFJL_3H45vS8kbU5K704enUgTnB3B0dI5ONnUM5SbGSAOW48S-XlTLqyY0CBUhGvNLiMTBZYpaTnt5WGTcuYU4ADUsFgXl85kp5ONvw28ehd-oyZsoY9INJ4teCzxDd8-_UgOhqK7x/s1600/02-Components.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left:1em; margin-right:1em&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;249&quot; width=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqGewFJL_3H45vS8kbU5K704enUgTnB3B0dI5ONnUM5SbGSAOW48S-XlTLqyY0CBUhGvNLiMTBZYpaTnt5WGTcuYU4ADUsFgXl85kp5ONvw28ehd-oyZsoY9INJ4teCzxDd8-_UgOhqK7x/s320/02-Components.PNG&quot; rel=&quot;lightbox[instalacao]&quot;/&gt;&lt;/a&gt;&lt;/div&gt;

Na tela de configuração &quot;Path environment&quot; também mantive a opção default &quot;Use Git Bash only&quot;, que não adiciona o git ao path do windows, desse modo, sempre que for necessário acessar o git você pode precisa abrir o &quot;Git Bash&quot;. É a opção mais conservadora. Leia as demais opções com atenção e sinta-se a vontade para utilizá-las.
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5V62pFR5asX5ATl9UgBRdqFR3LAPGKxu5GxW3xzX-wDIg80NAr_QVF9j8nyuAntiqRpeSmVAeKoBomHnH7PkkPSnWuzipDFWlF13v3o51PHKPhOmMu-wvSCTNyAx-fyHvSE3_3rUq81mW/s1600/03-Environment.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left:1em; margin-right:1em&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;250&quot; width=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5V62pFR5asX5ATl9UgBRdqFR3LAPGKxu5GxW3xzX-wDIg80NAr_QVF9j8nyuAntiqRpeSmVAeKoBomHnH7PkkPSnWuzipDFWlF13v3o51PHKPhOmMu-wvSCTNyAx-fyHvSE3_3rUq81mW/s320/03-Environment.PNG&quot; rel=&quot;lightbox[instalacao]&quot;/&gt;&lt;/a&gt;&lt;/div&gt;

E por último mais não menos importante, a configuração de quebra de linha. Como você deve saber, o ambiente windows utiliza CRLF como quebra de linha, e o ambiente unix utiliza apenas LF. Na opção default para windows, as quebras de linhas são convertidas automaticamente no checkout e commit, então, deixe marcada a opção &quot;Checkout Windows-style, commit Unix-Style line endings&quot;.
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWzXcOorsf43ilHr-GpWkWsN7jlgbD5T-kKnIqel7u8rBdpKkUs73yNqbWqdTBxXebqJW8sehi49ynFhB-rxrYDPU1EbLt_mnFPN9Bp5T9_EXMahovORq_4zq27UQZVKvXm3b6a0D6xMER/s1600/04-LineEnding.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left:1em; margin-right:1em&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;250&quot; width=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWzXcOorsf43ilHr-GpWkWsN7jlgbD5T-kKnIqel7u8rBdpKkUs73yNqbWqdTBxXebqJW8sehi49ynFhB-rxrYDPU1EbLt_mnFPN9Bp5T9_EXMahovORq_4zq27UQZVKvXm3b6a0D6xMER/s320/04-LineEnding.PNG&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

Agora vamos configurar a chave SSH para conseguir fazer commits no github. Primeiro, abra o Git Bash (pode ser atráves da barra Quick Launch, Iniciar\Programas ou botão direito do mouse no windows explorer) e vá até o seu diretório home (representado pelo caracter til &quot;~&quot;). Vamos verificar a existência da pasta &quot;.ssh&quot;.
&lt;pre class=&quot;terminal&quot;&gt;
&lt;span class=&quot;codeline&quot;&gt;$ cd ~&lt;/span&gt;&lt;br&gt;
&lt;span class=&quot;codeline&quot;&gt;$ ls -lha | grep .ssh&lt;/span&gt;&lt;br&gt;
&lt;span class=&quot;bash-output&quot;&gt;  drwxr-xr-x 2 fabricio admin 0 May 18 01:44 .ssh&lt;/span&gt;
&lt;span class=&quot;codeline&quot;&gt;$ cd .ssh&lt;/span&gt;
&lt;/pre&gt;

Caso não exista, como no exemplo abaixo, você pode criar a mesma.
&lt;pre class=&quot;terminal&quot;&gt;
&lt;span class=&quot;codeline&quot;&gt;$ cd ~&lt;/span&gt;&lt;br&gt;
&lt;span class=&quot;codeline&quot;&gt;$ ls -lha | grep .ssh&lt;/span&gt;&lt;br&gt;
&lt;br&gt;
&lt;span class=&quot;codeline&quot;&gt;$ mkdir .ssh&lt;/span&gt;&lt;br&gt;
&lt;span class=&quot;codeline&quot;&gt;$ ls -lha | grep .ssh&lt;/span&gt;&lt;br&gt;
&lt;span class=&quot;bash-output&quot;&gt;  drwxr-xr-x 2 fabricio admin 0 May 18 01:44 .ssh&lt;/span&gt;
&lt;span class=&quot;codeline&quot;&gt;$ cd .ssh&lt;/span&gt;
&lt;/pre&gt;

Feito isso, vamos gerar um par de chaves pública e privada. Essa chave é utilizada quando fazemos commit(push) no github para garantir a nossa autenticidade. Nesse passo será utilizado o e-mail informado na conta do github. Ao ser solicitado o nome do arquivo para armazenar a chave, basta pressionar Enter e será utilizado o nome default. Também será solicitado uma senha (passphrase) que deverá ser informada toda vez que efetuar commit no github, então, coloque uma que você não vá esquecer :D

&lt;pre class=&quot;terminal&quot;&gt;
&lt;span class=&quot;codeline&quot;&gt;$ ssh-keygen -t rsa -C &quot;your_email@domain.com&quot;&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;Generating public/private rsa key pair.&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;Enter file in which to save the key (/Users/&lt;em&gt;YourUser&lt;/em&gt;/.ssh/id_rsa):&lt;em&gt;&amp;lt;press enter&amp;gt;&lt;/em&gt;&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;Enter passphrase (empty for no passphrase): &lt;em&gt;&amp;lt;informe sua senha&amp;gt;&lt;/em&gt;&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;Enter same passphrase again: &lt;em&gt;&amp;lt;informe a mesma senha novamente&amp;gt;&lt;/em&gt;&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;Your identification has been saved in /c/Users/&lt;em&gt;YourUser&lt;/em&gt;/.ssh/id_rsa.&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;Your public key has been saved in /c/Users/&lt;em&gt;YourUser&lt;/em&gt;/.ssh/id_rsa.pub.&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;The key fingerprint is:&lt;/span&gt;
&lt;span class=&quot;bash-output&quot;&gt;&lt;em&gt;&amp;lt;Uma chave hexadecimal&amp;gt; &amp;lt;seu e-mail&amp;gt;&lt;/em&gt;&lt;/span&gt;
&lt;/pre&gt;

Agora essa chave precisa ser cadastrada no github. Para isso acesse o github e efetue o login. Acesse a opção &quot;Account Settings&quot; &gt; Clique em &quot;SSH Keys&quot; &gt; Clique em &quot;Add SSH key&quot;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjFAtxrJ2b6eVJk1hvEkon0qzOfwXYzCv_85KxTEf9FbT6S-N44yQVQ9l4aQQEw5ddH9Aw-MKSLAchhOBiCYlXKryt6F-evuwkC-mUrGC3fcnEaJBEF9X8BWj9rmkUmtM87WJCUMoqId5_/s1600/ssh_key_add.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left:1em; margin-right:1em&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;184&quot; width=&quot;400&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjjFAtxrJ2b6eVJk1hvEkon0qzOfwXYzCv_85KxTEf9FbT6S-N44yQVQ9l4aQQEw5ddH9Aw-MKSLAchhOBiCYlXKryt6F-evuwkC-mUrGC3fcnEaJBEF9X8BWj9rmkUmtM87WJCUMoqId5_/s400/ssh_key_add.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

Abra o arquivo id_rsa.pub com um editor de texto &lt;strike&gt;descente&lt;/strike&gt; como Notepad++, UltraEdit, EditPlus, etc, nem pense em usar o Notepad :D , o conteúdo do arquivo é a sua chave pública, copie todo o conteúdo sem adicionar novas quebras de linha ou espaços em branco
 e cole dentro do campo &quot;Key&quot; no github. Dê um título para identificar a máquina que você está registrando e clique em &quot;Add key&quot;. Será solicitado a confirmação da sua senha e o processo está concluído.
 
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlTMxJ4u3W9FXI1SMCclCOX1PTDQ0nUEdfEHzhTnLEp7JVcjmzoaqzj_fd-vSGA_V24ykUa_-sOxWkLBdd99FIMrjs33cGKHecU3nr2Z6Ma0ydWi15x0Qa4_fiHMTPxiVhNO77B3GR35Lk/s1600/bootcamp_1_ssh.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left:1em; margin-right:1em&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;288&quot; width=&quot;400&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlTMxJ4u3W9FXI1SMCclCOX1PTDQ0nUEdfEHzhTnLEp7JVcjmzoaqzj_fd-vSGA_V24ykUa_-sOxWkLBdd99FIMrjs33cGKHecU3nr2Z6Ma0ydWi15x0Qa4_fiHMTPxiVhNO77B3GR35Lk/s400/bootcamp_1_ssh.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;

 Agora vamos verificar se tudo está funcionando. Volte ao Git Bash e execute o comando abaixo. Não se preocupe com a mensagem que vai aparecer, é esperado que isso ocorra, apenas digite &quot;yes&quot; e pressione &quot;enter&quot;.
 &lt;pre class=&quot;terminal&quot;&gt;
 &lt;span class=&quot;codeline&quot;&gt;$ ssh -T git@github.com&lt;/span&gt;
 &lt;span class=&quot;bash-output&quot;&gt;The authenticity of host &#39;github.com (207.97.227.239)&#39; can&#39;t be established.&lt;/span&gt;
 &lt;span class=&quot;bash-output&quot;&gt;RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48.&lt;/span&gt;
 &lt;span class=&quot;bash-output&quot;&gt;Are you sure you want to continue connecting (yes/no)? &lt;em&gt;&amp;lt;yes&amp;gt; &amp;lt;enter&amp;gt;&lt;/em&gt;&lt;/span&gt;
 &lt;span class=&quot;bash-output&quot;&gt;Warning: Permanently added &#39;githu.com,207.97.227.239&#39; (RSA) to the list of known hosts.&lt;/span&gt;
 &lt;span class=&quot;bash-output&quot;&gt;Connection closed by 207.97.227.239&lt;/span&gt;
 &lt;/pre&gt;
 
 Repita o commando anterior
 &lt;pre class=&quot;terminal&quot;&gt;
 &lt;span class=&quot;codeline&quot;&gt;$ ssh -T git@github.com&lt;/span&gt;
 &lt;span class=&quot;bash-output&quot;&gt;Enter passphrase for key &#39;/c/Users/YourUser/.ssh/id_rsa&#39;: &lt;em&gt;&amp;lt;informe sua senha&amp;gt;&lt;/em&gt;&lt;/span&gt;
 &lt;span class=&quot;bash-output&quot;&gt;Hi &lt;yourUser&gt;! You&#39;ve successfully authenticated, but GitHub does not provide shell access.&lt;/span&gt;
 &lt;/pre&gt;

 Vamos também configurar o nome de usuário e e-mail que será utilizado para identificar seus commits. 
 
 &lt;pre class=&quot;terminal&quot;&gt;
 &lt;span class=&quot;command&quot;&gt;$ git config --global user.name &quot;&lt;em&gt;Nome Completo&lt;/em&gt;&quot;&lt;/span&gt;
 &lt;span class=&quot;command&quot;&gt;$ git config --global user.email &quot;&lt;em&gt;your_email@domain.com&lt;/em&gt;&quot;&lt;/span&gt; 
 &lt;/pre&gt;
 
 Pronto, agora você já está pronto para utilizar o Git e Gitghub, no próximo post vou mostrar como criar um repositório e interagir com o repositório.
&lt;p&gt;
&lt;span&gt;&lt;h3&gt;Edit: &lt;/h3&gt; Esqueci de mencionar a configuração para quem utiliza proxy.&lt;/span&gt;
&lt;/p&gt;
&lt;pre class=&quot;terminal&quot;&gt;
 &lt;span class=&quot;command&quot;&gt;$ git config --global http.proxy &lt;em&gt;http://proxyuser:proxypwd@proxy.server.com:3128&lt;/em&gt;&lt;/span&gt;
 &lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://fabriciodev.blogspot.com/feeds/4762532150674194356/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://fabriciodev.blogspot.com/2012/05/instalando-e-configurando-git-no.html#comment-form' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/4762532150674194356'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/4762532150674194356'/><link rel='alternate' type='text/html' href='http://fabriciodev.blogspot.com/2012/05/instalando-e-configurando-git-no.html' title='Instalando e Configurando git no windows'/><author><name>Fabricio Colombo</name><uri>http://www.blogger.com/profile/06951517260984102149</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCedF2z6z0D9d8Adr564w0ZJwcy2ckdFrC48QG9iQ9roQTh2R7yylksaD9ccou06b0HoZ-S_Did-aXDwGIUuaHVO6Aw398CK6KbnI4bEkKbiYC8M_8rp5_so6uPrqGX1A/s220/unnamed.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjqM9yFBt6j0cvZ12OnJ-yNTiN3I5MTc-9qBosW6ocZaR3hrl_TlzQXT8eSGLDm22G3BTrTg0P_ZSYjOzP_rfAWzMYOm57qhW9N67DOedGb4Ag94qTX6kQKLkbeqsu2joLry7vhYiJstBuo/s72-c/01-Location.PNG" height="72" width="72"/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-911701488457280480.post-1044110629231669092</id><published>2012-03-20T17:06:00.000-07:00</published><updated>2013-05-14T14:37:04.352-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Banco de dados"/><category scheme="http://www.blogger.com/atom/ns#" term="PostgreSQL"/><title type='text'>Consultando e eliminando sessões ativas no PostgreSQL</title><content type='html'>Já mostrei como listar/matar as sessões ativas no oracle, hoje vou mostrar essa mesma funcionalidade acessando o banco de dados PostgreSQL. O sql a seguir lista todas as sessões ativas.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: sql&quot;&gt;select datname, 
       procpid, 
       usename, 
       application_name, 
       client_addr, 
       client_hostname, 
       backend_start 
  from pg_stat_activity
&lt;/pre&gt;&lt;br /&gt;
&lt;b&gt;EDIT:&lt;/b&gt;&lt;br /&gt;
&lt;blockquote&gt;A coluna procid foi renomeada para pid a partir da versão 9.2 do PostgreSQL&lt;br /&gt;
&lt;/blockquote&gt;&lt;br /&gt;
Com a lista de usuário em mãos, podemos optar por &quot;matar&quot; a sessão de algum usuário ativo, &lt;a name=&#39;more&#39;&gt;&lt;/a&gt; para isto basta executar o comando abaixo, substituindo o &quot;procpid&#39; pelo valor retornado da consulta anterior.  &lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: sql&quot;&gt;select pg_terminate_backend(procpid)
&lt;/pre&gt;&lt;br /&gt;
E para eliminar todas as conexões ativas, menos a conexão atual.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: sql&quot;&gt;SELECT pg_terminate_backend(procpid) 
   FROM pg_stat_activity 
  WHERE procpid &lt;&gt; pg_backend_pid();
&lt;/pre&gt;</content><link rel='replies' type='application/atom+xml' href='http://fabriciodev.blogspot.com/feeds/1044110629231669092/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://fabriciodev.blogspot.com/2012/03/consultando-e-eliminando-sessoes-ativas_20.html#comment-form' title='6 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/1044110629231669092'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/1044110629231669092'/><link rel='alternate' type='text/html' href='http://fabriciodev.blogspot.com/2012/03/consultando-e-eliminando-sessoes-ativas_20.html' title='Consultando e eliminando sessões ativas no PostgreSQL'/><author><name>Fabricio Colombo</name><uri>http://www.blogger.com/profile/06951517260984102149</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCedF2z6z0D9d8Adr564w0ZJwcy2ckdFrC48QG9iQ9roQTh2R7yylksaD9ccou06b0HoZ-S_Did-aXDwGIUuaHVO6Aw398CK6KbnI4bEkKbiYC8M_8rp5_so6uPrqGX1A/s220/unnamed.jpg'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-911701488457280480.post-8224947783189647040</id><published>2012-03-14T18:03:00.001-07:00</published><updated>2012-03-20T17:05:12.055-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Banco de dados"/><category scheme="http://www.blogger.com/atom/ns#" term="Oracle"/><title type='text'>Consultando e eliminando sessões ativas no Oracle</title><content type='html'>Hoje vou deixar uma dica rápida, como listar as sessões ativas no oracle, isto é, os usuários que estão conectados através de alguma aplicação cliente. O sql a seguir lista todas as sessões ativas excluindo os processos do próprio oracle.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: sql&quot;&gt;SELECT s.username,
     s.osuser,
     s.sid,
     s.serial#,
     p.spid,
     s.status,
     s.machine,
     s.program,
     TO_CHAR(s.logon_Time,&#39;DD-MON-YYYY HH24:MI:SS&#39;) AS logon_time
   FROM v$session s
  inner join v$process p
     on s.paddr = p.addr
  WHERE s.status = &#39;ACTIVE&#39; 
    and s.type &lt;&gt; &#39;BACKGROUND&#39;
&lt;/pre&gt;&lt;br /&gt;
&lt;br /&gt;
Com a lista de usuário em mãos, podemos optar por &quot;matar&quot; a sessão de algum usuário ativo. &lt;a name=&#39;more&#39;&gt;&lt;/a&gt; Para isso basta executar o comando abaixo, substituindo o &quot;sid&quot; e &quot;serial#&#39; pelos valores retornados da consulta anterior.  &lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: sql&quot;&gt;ALTER SYSTEM KILL SESSION &#39;sid,serial#&#39; IMMEDIATE; 
&lt;/pre&gt;&lt;br /&gt;
Por hoje era isso.</content><link rel='replies' type='application/atom+xml' href='http://fabriciodev.blogspot.com/feeds/8224947783189647040/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://fabriciodev.blogspot.com/2012/03/consultando-e-eliminando-sessoes-ativas.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/8224947783189647040'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/8224947783189647040'/><link rel='alternate' type='text/html' href='http://fabriciodev.blogspot.com/2012/03/consultando-e-eliminando-sessoes-ativas.html' title='Consultando e eliminando sessões ativas no Oracle'/><author><name>Fabricio Colombo</name><uri>http://www.blogger.com/profile/06951517260984102149</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCedF2z6z0D9d8Adr564w0ZJwcy2ckdFrC48QG9iQ9roQTh2R7yylksaD9ccou06b0HoZ-S_Did-aXDwGIUuaHVO6Aw398CK6KbnI4bEkKbiYC8M_8rp5_so6uPrqGX1A/s220/unnamed.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-911701488457280480.post-8398728810987996639</id><published>2012-02-16T16:22:00.000-08:00</published><updated>2012-02-16T16:22:22.130-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Delphi"/><category scheme="http://www.blogger.com/atom/ns#" term="Sql"/><title type='text'>Delphi SqlBuilder</title><content type='html'>Olá, há algum tempo eu havia desenvolvido uma rotina para modificar a cláusula Where de sql statements(pelo menos dos mais simples). Agora surgiu a oportunidade de compartilhar a solução, então aqui está.&lt;br /&gt;
&lt;br /&gt;
Logo abaixo podemos ver a definição da classe.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;TSqlBuilder = class
  private
  public
    class function AddWhere(ASql, AWhere: String; AMainTable: String = &#39;&#39;): String;
    class function ChangeOrdeBy(ASql, AOrderFields: String): String;
  class function RemoveOrderBy(ASql: String): String;
  end;
&lt;/pre&gt;&lt;br /&gt;
Como podem ver a definição da classe é bastante simples e possui apenas funções de classe, nada de parser&#39;s de sql complicados. &lt;a name=&#39;more&#39;&gt;&lt;/a&gt;O argumento &quot;AWhere&#39; já deve estar formatado ao chamar a função, dando mais liberdade ao desenvolvedor para manipular a claúsula Where da maneira mais conveniente, por exemplo:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;var
  qry: TAlgumTipoDeQuery;
begin
  (...)
 qry.Sql.Text := &#39;Select * from TabelaA Where X = 1&#39;;
  
 //Native Types
 qry.Sql.Text := TSqlBuilder.AddWhere(qry.Sql.Text, &#39; Y = &#39;&#39;a&#39;&#39;&#39;);
 qry.Open;
 
 //Bind Parameters
 qry.Sql.Text := TSqlBuilder.AddWhere(qry.Sql.Text, &#39; Y = :Y&#39;);
 qry.ParamByName(&#39;Y&#39;).AsString := &#39;a&#39;
 qry.Open;
end; 
&lt;/pre&gt;&lt;br /&gt;
O argumento adicional &quot;AMainTable&quot; que ainda não foi utilizado, é importante quando temos um sql que possui um subselect antes da claúsula from, por exemplo, veja o sql abaixo:&lt;br /&gt;
&lt;pre class=&quot;brush: sql&quot;&gt;Select a, 
        (select b.b from Tabela2 b where b.x = 3) as b
    from Tabela1 a
   where a.x = 2
&lt;/pre&gt;&lt;br /&gt;
Por padrão a claúsula &quot;Where&quot; será adicionada ao primeiro &quot;from&#39; encontrado, no caso, adicionando imediatamente após &quot;Tabela2&quot;. Para evitar que isso aconteça, devemos informar qual é a tabela principal do sql, passando como argumento para o método AddWhere o valor &quot;Tabela1&quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;qry.Sql.Text := &#39;Select a, &#39; +
                  &#39;       (select b.b from Tabela2 b where b.x = 3) as b &#39; +
                   &#39;  from Tabela1 a &#39; +
                   &#39; where a.x = 2&#39;;
   qry.Sql.Text := TSqlBuilder.AddWhere(qry.Sql.Text, &#39; Y = :Y&#39;, &#39;Tabela1&#39;);
 &lt;/pre&gt;&lt;br /&gt;
Também temos o método &lt;b&gt;ChangeOrdeBy&lt;/b&gt;, que adiciona ou modifica a cláusula &quot;Order by&quot;. O modo de usar o mesmo é como segue:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;var
  qry: TAlgumTipoDeQuery;
begin
  (...)
 qry.Sql.Text := &#39;Select * from TabelaA&#39;;
 qry.Sql.Text := TSqlBuilder.ChangeOrdeBy(qry.Sql.Text, &#39;a&#39;);
 //Retorna &quot;Select * from TabelaA order by a&quot;
 
 qry.Sql.Text := &#39;Select * from TabelaA oder by a&#39;;
 qry.Sql.Text := TSqlBuilder.ChangeOrdeBy(qry.Sql.Text, &#39;b asc, c desc&#39;);
 //Retorna &quot;Select * from TabelaA order by b asc, c desc&quot;
&lt;/pre&gt;&lt;br /&gt;
E por último, o método &lt;b&gt;RemoveOrderBy&lt;/b&gt;, que remove qualquer cláusula &quot;Order by&quot; que exista.&lt;br /&gt;
&lt;br /&gt;
O código completo contendo os testes unitários está disponível &lt;a href=&quot;https://bitbucket.org/fabriciocolombo/delphisqlbuilder&quot;&gt;aqui&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Qualquer sugestão, bug ou melhoria, façam um fork, modifiquem e façam um pull request que eu atualizo aqui, ou abra uma Issue no site do projeto, mais não deixe de me avisar. ;)&lt;br /&gt;
&lt;br /&gt;
Abraços.</content><link rel='replies' type='application/atom+xml' href='http://fabriciodev.blogspot.com/feeds/8398728810987996639/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://fabriciodev.blogspot.com/2012/02/delphi-sqlbuilder.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/8398728810987996639'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/8398728810987996639'/><link rel='alternate' type='text/html' href='http://fabriciodev.blogspot.com/2012/02/delphi-sqlbuilder.html' title='Delphi SqlBuilder'/><author><name>Fabricio Colombo</name><uri>http://www.blogger.com/profile/06951517260984102149</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCedF2z6z0D9d8Adr564w0ZJwcy2ckdFrC48QG9iQ9roQTh2R7yylksaD9ccou06b0HoZ-S_Did-aXDwGIUuaHVO6Aw398CK6KbnI4bEkKbiYC8M_8rp5_so6uPrqGX1A/s220/unnamed.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-911701488457280480.post-7967760276010854085</id><published>2012-02-15T18:58:00.001-08:00</published><updated>2012-03-21T19:08:06.142-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Java"/><category scheme="http://www.blogger.com/atom/ns#" term="Log4j"/><title type='text'>Criando um CustomAppender para JTextArea com Log4j</title><content type='html'>Recentemente estavámos trabalhando em um projeto de migração de dados em Java, e foi criada uma pequena interface para interagir com o usuário utilizando &lt;a href=&quot;http://www.guj.com.br/articles/38&quot;&gt;Swing&lt;/a&gt;. Em dado momento, decidimos incluir um JTextArea para mostrar ao usuário as informações emitidas pelo log do programa, no caso, utilizando &lt;a href=&quot;http://logging.apache.org/log4j/&quot;&gt;Log4j&lt;/a&gt;, para que o mesmo pudesse acompanhar com mais detalhes o que o conversor estava fazendo no momento.&lt;br /&gt;
&lt;br /&gt;
Foi então que pesquisando um pouco no google vimos que há como criar nossos próprios Appender&#39;s do Log4j, e é sobre isso que eu vou falar hoje.&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Para criar um novo appender vamos estender a classe abstrata &lt;a href=&quot;http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/AppenderSkeleton.html&quot;&gt;AppenderSkeleton&lt;/a&gt;, que já provê todas as funcionalidades básicas para tratamento da mensagem. São obrigatórios a implementação de 3 métodos:&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote class=&quot;tr_bq&quot;&gt;&lt;b&gt;close():&lt;/b&gt; Utilizado para liberar os recursos alocados pelo appender como arquivos, conexões de rede, etc.&lt;br /&gt;
&lt;/blockquote&gt;&lt;blockquote class=&quot;tr_bq&quot;&gt;&lt;b&gt;requiresLayout():&lt;/b&gt; Indica se o appender necessita de um layout configurado para funcionar. Em casos onde o appender pode trabalhar com ou sem layout, o método deve retornar true;&lt;br /&gt;
&lt;/blockquote&gt;&lt;blockquote class=&quot;tr_bq&quot;&gt;&lt;b&gt;append(LoggingEvent event):&lt;/b&gt; É o método principal que devemos implementar, é onde residirá o nosso tratamento customizado do log. Ele recebe um argumento do tipo &lt;a href=&quot;http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/spi/LoggingEvent.html&quot;&gt;LoggingEvent&lt;/a&gt;, que tem várias atributos como o Level da mensagem, a mensagem, a causa do erro em caso de exceções, etc.&lt;br /&gt;
&lt;/blockquote&gt;&lt;br /&gt;
Ok, agora vamos ver um pouco de código. Crie um projeto Maven e adicione as seguintes dependencias:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: xml&quot;&gt;&lt;dependency&gt;
 &lt;groupid&gt;log4j&lt;/groupId&gt;
 &lt;artifactid&gt;log4j&lt;/artifactId&gt;
 &lt;version&gt;1.2.16&lt;/version&gt;
&lt;/dependency&gt;

&lt;dependency&gt;
 &lt;groupid&gt;commons-lang&lt;/groupId&gt;
 &lt;artifactid&gt;commons-lang&lt;/artifactId&gt;
 &lt;version&gt;2.6&lt;/version&gt;
&lt;/dependency&gt;
&lt;/pre&gt;&lt;br /&gt;
Em seguida crie uma classe chamada TextAreaAppender e implemente os métodos necessários.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;public class TextAreaAppender extends AppenderSkeleton {
 
 //Outro métodos foram omitidos para simplificar o exemplo

 @Override
 protected void append(LoggingEvent event) {
  //formata a mensagem de acordo com o layout 
  String formatted = getLayout().format(event);

  jTextArea.append(formatted);

  // Se a mensagem possuí informações sobre a exceção que causou o erro
  if (event.getThrowableInformation() != null) {
   jTextArea.append(ExceptionUtils.getFullStackTrace(event
     .getThrowableInformation().getThrowable()));
  }
 }
}
&lt;/pre&gt;&lt;br /&gt;
Agora vou criar uma aplicação para exemplificar a configuração do Appender&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: java&quot;&gt;public class Main extends JFrame {

 public static void main(String[] args) {
  Main main = new Main();

  main.init();
 }

 private void init() {
 
  textLogArea = new JTextArea();
 
     //Criação dos demais componentes visuais
  
  //Instancia o nosso Appender
  TextAreaAppender appender = new TextAreaAppender(textLogArea);

  //Adiciona o appender ao logger
  Logger.getRootLogger().addAppender(appender);

  logger.info(&quot;Log inicializado&quot;);
 }
}
&lt;/pre&gt;&lt;br /&gt;
O projeto completo está disponível no meu &lt;a href=&quot;https://github.com/fabriciocolombo/TextAreaAppender&quot; target=&quot;_blank&quot;&gt;github&lt;/a&gt;.</content><link rel='replies' type='application/atom+xml' href='http://fabriciodev.blogspot.com/feeds/7967760276010854085/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://fabriciodev.blogspot.com/2012/02/criando-um-customappender-para.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/7967760276010854085'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/7967760276010854085'/><link rel='alternate' type='text/html' href='http://fabriciodev.blogspot.com/2012/02/criando-um-customappender-para.html' title='Criando um CustomAppender para JTextArea com Log4j'/><author><name>Fabricio Colombo</name><uri>http://www.blogger.com/profile/06951517260984102149</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCedF2z6z0D9d8Adr564w0ZJwcy2ckdFrC48QG9iQ9roQTh2R7yylksaD9ccou06b0HoZ-S_Did-aXDwGIUuaHVO6Aw398CK6KbnI4bEkKbiYC8M_8rp5_so6uPrqGX1A/s220/unnamed.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-911701488457280480.post-3439105673693421748</id><published>2012-02-13T11:44:00.001-08:00</published><updated>2012-02-15T18:51:55.529-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Delphi"/><category scheme="http://www.blogger.com/atom/ns#" term="Google Maps"/><category scheme="http://www.blogger.com/atom/ns#" term="Json"/><category scheme="http://www.blogger.com/atom/ns#" term="Xml"/><title type='text'>Serviços da Google Maps API de Geocodificação</title><content type='html'>Olá, hoje vou mostrar um exemplo de como consumir o serviço do &lt;a href=&quot;http://code.google.com/intl/pt-BR/apis/maps/documentation/geocoding&quot;&gt;Google Maps API de geocodificação&lt;/a&gt;. A definição de geocodificação eu extraí do próprio site do google:&lt;br /&gt;
&lt;br /&gt;
&lt;blockquote&gt;&quot;Geocodificação é o processo de conversão de endereços (como &quot;1600 Amphitheatre Parkway, Mountain View, CA&quot;) em coordenadas geográficas (como latitude 37.423021 e longitude -122.083739), que você pode usar para colocar marcadores ou posicionar o mapa. A Google Geocoding API fornece uma maneira direta de acessar um geocodificador por meio de uma solicitação HTTP. Além disso, o serviço permite que você realize a operação inversa (transformar coordenadas em endereços); esse processo é conhecido como &quot;geocodificação reversa&quot;.&quot;&lt;/blockquote&gt;&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
Uma solitação de geocoding deve ter basicamente os seguinte formato:&lt;br /&gt;
&lt;pre class=&quot;brush: text&quot;&gt;http://maps.googleapis.com/maps/api/geocode/output?parameters
&lt;/pre&gt;onde &lt;b&gt;output&lt;/b&gt; significa o formato do retorno dos dados, que pode ser &lt;b&gt;json&lt;/b&gt;(recomendável) ou &lt;b&gt;xml&lt;/b&gt;.&lt;br /&gt;
&lt;br /&gt;
Além disso são obrigatórios os parâmetros:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;address&lt;/b&gt; — o endereço que você deseja geocodificar&lt;br /&gt;
ou&lt;br /&gt;
&lt;b&gt;latlng&lt;/b&gt; — o valor textual de latitude/longitude para o qual você deseja obter o endereço mais próximo.&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;sensor&lt;/b&gt; — indica se a solicitação de geocodificação vem ou não de um dispositivo com sensor de localização. Esse valor deve ser true ou false.&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
A resposta da requisição contém dois elementos raiz:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;b&gt;status&lt;/b&gt; - contém metadados sobre a solicitação. Consulte os &lt;a href=&quot;http://code.google.com/intl/pt-BR/apis/maps/documentation/geocoding/#StatusCodes&quot;&gt;Códigos de status&lt;/a&gt; no site.&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;&lt;b&gt;results&lt;/b&gt; - contém uma matriz de informações de endereços geocodificados e informações geométricas.&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
Eu implementei uma biblioteca bem simples que suporta os dois formatos de resposta: json e xml. &lt;br /&gt;
&lt;br /&gt;
Para interpretar o resultando em json, utilizei a biblioteca &lt;a href=&quot;http://lkjson.sourceforge.net/&quot;&gt;lkjson&lt;/a&gt;, pois, já tinha utilizado a mesma em outros projetos e achei bastante simples de usar, mais existem outras opções como o &lt;a href=&quot;http://www.progdigy.com/?page_id=6&quot;&gt;SuperObject&lt;/a&gt; e &lt;a href=&quot;http://sourceforge.net/projects/is-webstart/&quot;&gt;Delphi Web Utils&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Para interpretar o formato xml optei por utilizar o &lt;a href=&quot;http://unitonedev.blogspot.com/2009/08/utilizando-xml-databinding.html&quot;&gt;Xml Data Binding&lt;/a&gt; do delphi, que através de um wizard cria classes tipadas a partir do arquivos xml, deixando todo o processo de transformação transparente.&lt;br /&gt;
&lt;br /&gt;
Basicamente o que fiz foi o seguinte, efetuei uma requisição no serviço de geocodificação no formato xml e salvei os dados retornados em um arquivo xml. Em seguida, utilizei o Xml Data Binding para transformar esse xml em classes. Essas classes são o resultado final da solicitação, seja ela em json ou xml.&lt;br /&gt;
&lt;br /&gt;
Quando a requisição é no formato xml, é utilizado o binding do XmlDocument:&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;class function TGoogleApiGeoXml.XmlToGeocodeResponse(const AXmlText: String): IGeocodeResponse;
var
  vXmlDocument: IXMLDocument;
begin
  vXmlDocument := TXMLDocument.Create(nil);
  vXmlDocument.LoadFromXml(UTF8Encode(AXmlText));

  Result := vXmlDocument.GetDocBinding(&#39;GeocodeResponse&#39;, TGeocodeResponse) as IGeocodeResponse;
end;
&lt;/pre&gt;&lt;br /&gt;
Quando a requisição é no formato json, escrevi o parser &quot;na unha&quot;, que retorna o mesmo tipo de objeto da solicitação em xml, deixando a aplicação que consome o serviço utilizar o mesmo sem se importar se é xml ou json.&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;function TGoogleApiGeoJson.ConvertFromJson(const AJsonText: String): IGeocodeResponse;
var
  vJsonResponse: TlkJSONobject;
  vResults: TlkJSONbase;
begin
  Result := TGeocodeResponse.NewGeocodeResponse;

  vJsonResponse := TlkJSONobject(TlkJSON.ParseText(UTF8Encode(AJsonText)));
  try
    vResults := TlkJSONlist(TlkJSONlist(vJsonResponse.Field[&#39;results&#39;]).Field[&#39;address_components&#39;]).Items[0];

    ParseStatus(Result, vJsonResponse);
    ParseType(Result, vResults);
    ParseFormattedAddress(Result, vResults);
    ParseAddresses(Result, vResults);
    ParseGeometry(Result, vResults);
  finally
    vJsonResponse.Free;
  end;
end;
&lt;/pre&gt;&lt;br /&gt;
Na sistema em si, o único código que ele precisa executar é esse:&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;var
  vResponse: IGeocodeResponse;
begin
  vResponse := TGoogleApiGeocodeDownload.GetGeocode(&quot;http://maps.googleapis.com/maps/api/geocode/json_ou_xml?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA&amp;sensor=true_ou_false&quot;);
 
 //Lógica que utiliza a resposta da solicitação
&lt;/pre&gt;&lt;br /&gt;
O implementação do método GetGeocode é bastante simples também, ele faz uma requisição HTTP utilizando indy conforme abaixo&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;class function TGoogleApiGeocodeDownload.HttpGet(Url: String): String;
var
  lHTTP: TIdHTTP;
  lStream: TStringStream;
begin
  lHTTP := TIdHTTP.Create(nil);
  lStream := TStringStream.Create(EmptyStr);
  try
    lHTTP.Get(Url, lStream);
    
    lStream.Position := 0;

    Result := UTF8Decode(lStream.DataString);
  finally
    FreeAndNil(lHTTP);
    FreeAndNil(lStream);
  end;
end;
&lt;/pre&gt;&lt;br /&gt;
E de acordo com o formato dos dados faz uma chamada ao parser correspondente para retornar o objeto.&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;class function TGoogleApiGeocodeDownload.GetGeocode(AUrl: String): IGeocodeResponse;
var
  vDados: String;
  vFormato: TOutputFormat;
begin
  vFormato := DiscoverFormat(AUrl);

  vDados := HttpGet(AUrl);

  case vFormato  of
    Json: Result := TGoogleApiGeoJson.JsonToGeocodeResponse(vDados);
    Xml : Result := TGoogleApiGeoXml.XmlToGeocodeResponse(vDados);   
  end;
end;
&lt;/pre&gt;&lt;br /&gt;
Mais informações sobre limitações de uso e sobre os parâmetros utilizados na requisição HTTP podem ser encontrados &lt;a href=&quot;http://code.google.com/intl/pt-BR/apis/maps/documentation/geocoding&quot;&gt;aqui&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
O código fonte completo com exemplo de como utilizar pode ser acessado &lt;a href=&quot;https://bitbucket.org/fabriciocolombo/googlemapapigeocode&quot;&gt;aqui&lt;/a&gt; no meu bitbucket.&lt;br /&gt;
&lt;br /&gt;
Um abraço e fique ligado nos próximos posts.</content><link rel='replies' type='application/atom+xml' href='http://fabriciodev.blogspot.com/feeds/3439105673693421748/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://fabriciodev.blogspot.com/2012/02/servicos-da-google-maps-api-de.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/3439105673693421748'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/3439105673693421748'/><link rel='alternate' type='text/html' href='http://fabriciodev.blogspot.com/2012/02/servicos-da-google-maps-api-de.html' title='Serviços da Google Maps API de Geocodificação'/><author><name>Fabricio Colombo</name><uri>http://www.blogger.com/profile/06951517260984102149</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCedF2z6z0D9d8Adr564w0ZJwcy2ckdFrC48QG9iQ9roQTh2R7yylksaD9ccou06b0HoZ-S_Did-aXDwGIUuaHVO6Aw398CK6KbnI4bEkKbiYC8M_8rp5_so6uPrqGX1A/s220/unnamed.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-911701488457280480.post-6112286686177523327</id><published>2012-02-03T04:05:00.000-08:00</published><updated>2012-02-03T04:19:19.225-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="DiffMerge"/><category scheme="http://www.blogger.com/atom/ns#" term="Subversion"/><category scheme="http://www.blogger.com/atom/ns#" term="TortoiseSVN"/><title type='text'>Simplificando o merge no TortoiseSVN com DiffMerge</title><content type='html'>Muitos de vocês já devem ter se aborrecido com a ferramenta de diff(comparação entre arquivos) que vem junto com o &lt;a href=&quot;http://tortoisesvn.tigris.org/&quot;&gt;TortoiseSVN&lt;/a&gt;. Ela não consegue resolver sozinha vários tipos de conflitos e a resolução manual é complicada.&lt;br /&gt;
&lt;br /&gt;
Procurando uma ferramenta melhor tempos atrás, encontrei esse post do &lt;a href=&quot;http://www.ericksasse.com.br/sourcegear-diffmerge/&quot;&gt;Erick Sasse&lt;/a&gt; onde ele recomendava a ferramenta &lt;a href=&quot;http://www.sourcegear.com/diffmerge/&quot;&gt;DiffMerge&lt;/a&gt; que é gratuita e funciona no Windows, Mac OS X e Linux.&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
Um dos diferenciais do DiffMerge é o suporte a merge de 3 arquivos, ou seja, quando mais de um desenvolvedor altera um arquivo ele  considera o arquivo base e as duas versões alteradas. &lt;br /&gt;
&lt;br /&gt;
Para configurar ele é bastante simples. Acesse a tela de configuração do TortoiseSVN (Botão direito do mouse -&amp;gt; TortoiseSVN -&amp;gt;Settings) e modifique as configuraçães conforme o exemplo abaixo.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: text&quot;&gt;External Programs
    Diff Viewer
      - External
     C:\Program Files\SourceGear\DiffMerge\DiffMerge.exe /t1=%bname /t2=%yname %base %mine
&lt;/pre&gt;&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTdsuX0HZW-gS2JFMLvO-6Y7_vR1IGTNpHoU9g_5h1E6aiFM_pUQC4xTpCLs1FBnDSTEie6jzfS3vaQHBn2uLfBEFJB6hEk8CzAo0DmKgyMP1g3pTWZxb3KPU9eJLadb4p_e5UHXYdkSUX/s1600/Diff.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;210&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTdsuX0HZW-gS2JFMLvO-6Y7_vR1IGTNpHoU9g_5h1E6aiFM_pUQC4xTpCLs1FBnDSTEie6jzfS3vaQHBn2uLfBEFJB6hEk8CzAo0DmKgyMP1g3pTWZxb3KPU9eJLadb4p_e5UHXYdkSUX/s320/Diff.jpg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;pre class=&quot;brush: text&quot;&gt;External Programs
    Merge Tool
      - External 
        C:\Program Files\SourceGear\DiffMerge\DiffMerge.exe /m /r=%merged /t1=%yname /t2=%bname /t3=%tname /c=%mname %mine %base %theirs
&lt;/pre&gt;&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTbEC6u5_A-0NWQqCb636U6k5qkuTfbf0pW9qy7ECZcPp1ek30QiwEB4ulc8FrLiy670fnBRUzQKN4egYnanITtXYh68GEX053czGumPGapRGt2vqJTmCwB7xuEZpYXYdutRuVYmfUCFau/s1600/Merge.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;211&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgTbEC6u5_A-0NWQqCb636U6k5qkuTfbf0pW9qy7ECZcPp1ek30QiwEB4ulc8FrLiy670fnBRUzQKN4egYnanITtXYh68GEX053czGumPGapRGt2vqJTmCwB7xuEZpYXYdutRuVYmfUCFau/s320/Merge.jpg&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Por hoje era isso, se alguém quiser sugerir outras ferramentas similares deixe um comentário.</content><link rel='replies' type='application/atom+xml' href='http://fabriciodev.blogspot.com/feeds/6112286686177523327/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://fabriciodev.blogspot.com/2012/02/simplificando-o-merge-no-tortoisesvn.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/6112286686177523327'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/6112286686177523327'/><link rel='alternate' type='text/html' href='http://fabriciodev.blogspot.com/2012/02/simplificando-o-merge-no-tortoisesvn.html' title='Simplificando o merge no TortoiseSVN com DiffMerge'/><author><name>Fabricio Colombo</name><uri>http://www.blogger.com/profile/06951517260984102149</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCedF2z6z0D9d8Adr564w0ZJwcy2ckdFrC48QG9iQ9roQTh2R7yylksaD9ccou06b0HoZ-S_Did-aXDwGIUuaHVO6Aw398CK6KbnI4bEkKbiYC8M_8rp5_so6uPrqGX1A/s220/unnamed.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiTdsuX0HZW-gS2JFMLvO-6Y7_vR1IGTNpHoU9g_5h1E6aiFM_pUQC4xTpCLs1FBnDSTEie6jzfS3vaQHBn2uLfBEFJB6hEk8CzAo0DmKgyMP1g3pTWZxb3KPU9eJLadb4p_e5UHXYdkSUX/s72-c/Diff.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-911701488457280480.post-6343660066925727789</id><published>2012-01-19T16:56:00.000-08:00</published><updated>2012-02-02T02:20:02.385-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Hudson"/><category scheme="http://www.blogger.com/atom/ns#" term="Integração Contínua"/><category scheme="http://www.blogger.com/atom/ns#" term="Subversion"/><category scheme="http://www.blogger.com/atom/ns#" term="Tomcat"/><title type='text'>Integração Contínua - Instalando as ferramentas(Java JRE, TomCat e Hudson)</title><content type='html'>Já faz algum tempo desde o último post, o tempo está curto, mais dando continuidade a série sobre &lt;a href=&quot;http://fabriciodev.blogspot.com/search/label/Integra%C3%A7%C3%A3o%20Cont%C3%ADnua&quot;&gt;Integração Contínua&lt;/a&gt;, hoje vou mostrar como instalar e configurar as ferramentas que iremos utilizar: Java JRE, Tomcat, Hudson e VisualSVN Server.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Java&lt;/b&gt;&lt;br /&gt;
Como servidor de aplicação utilizarei o &lt;a href=&quot;http://tomcat.apache.org/index.html&quot;&gt;Tomcat&lt;/a&gt; e para isso, precisamos do Java Runtime Edition (JRE) (ou Java Development Kit(JDK) caso já tenha instalado). Você pode obter o instalador nesse link  &lt;a href=&quot;http://www.oracle.com/technetwork/java/javase/downloads/index.html&quot;&gt;Java SE Downloads&lt;/a&gt;. Escolha a opção JRE. A instalação é no estilo next, next, finish.&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Tomcat&lt;/b&gt;&lt;br /&gt;
Agora vamos intalar o Tomcat. Você pode obter a última versão através dessa página &lt;a href=&quot;http://tomcat.apache.org/download-70.cgi&quot;&gt;Tomcat 7 downloads&lt;/a&gt;. Escolha a opção &lt;b&gt;32-bit/64-bit Windows Service Installer&lt;/b&gt;. Durante a instalação, pequenas configurações devem ser feitas. Na etapa ilustrada abaixo, deve ser informado um usuário e senha de administração do tomcat e no próximo passo, deve ser informado o diretório onde está instalado o java.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhegjh55CALQB9Ao3pb3tXZVRS0V39AoGRSOp6OGnssMPoL6zesA5T5jM467BOAAT4kDDIlOuszuMXjWIGGNDi9NTsLTOh2TMp_EPLVJay41Mc5bwOsF3mq3zMPzi4gmHLfuQlkuERkBoG3/s1600/TomCat+%25283%2529.jpg&quot; imageanchor=&quot;1&quot; style=&quot;margin-left:1em; margin-right:1em&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;246&quot; width=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhegjh55CALQB9Ao3pb3tXZVRS0V39AoGRSOp6OGnssMPoL6zesA5T5jM467BOAAT4kDDIlOuszuMXjWIGGNDi9NTsLTOh2TMp_EPLVJay41Mc5bwOsF3mq3zMPzi4gmHLfuQlkuERkBoG3/s320/TomCat+%25283%2529.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Após concluir a instalação, acesse pelo browser a url http://localhost:8080 e você deve ver a página do Tomcat. Ao acessar a opção &lt;b&gt;Tomcat Manager&lt;/b&gt; será solicitado a senha informada no momento da instalação, e você poderá controlar as aplicações instaladas no tomcat.&lt;br /&gt;
&lt;br /&gt;
&lt;imagem TomCat homepage http://localhost:8080/&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;Hudson&lt;/b&gt;&lt;br /&gt;
Agora precisamos do &lt;a href=&quot;http://java.net/projects/hudson&quot;&gt;Hudson&lt;/a&gt;. O Hudson é um servidor de integração contínua onde é possível criar projetos que podem ser construídos em vários passos. Acesse a página do hudson e faça o download da última versão estável no formato &lt;b&gt;war&lt;/b&gt;. No momento dessa publicação a última versão disponível é a &lt;a href=&quot;http://java.net/projects/hudson/downloads/download/war/hudson-2.2.0.war&quot;&gt;2.2&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
Após efetuado o download, copie o war para a pasta &quot;webapps&quot; dentro do diretório onde o Tomcat foi instalado e depois reinicie o serviço do Tomcat acessando o mesmo pelo painel de controle do windows. Acesse o endereço http://localhost:8080 e na opção Tomcat Manager, deve estar aparecendo a aplicação hudson com status rodando. &lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;VisualSVN Server&lt;/b&gt;&lt;br /&gt;
Ainda falta o servidor SVN para gerenciar o código fonte. No caso vou utilizar o &lt;a href=&quot;&quot;&gt;VisualSVN Server&lt;/a&gt;. Após a instalação vamos criar um usuário para acessar o repositório. Com o botão direito sobre a pasta &lt;b&gt;Users&lt;/b&gt; vá na opção &lt;b&gt;Create New User&lt;/b&gt; e informe um usuário e senha. Vamos repetir o processo para criar um repositório. Clique com o botão direito sobre a pasta &lt;b&gt;Repositories&lt;/b&gt;, informe um nome. Logo após clique com o botão direito sobre o repositório recém criado e escolha a opção Novo\Project Structure e informe o nome do projeto. Isso já criará as pastas branch, tag e trunk.&lt;br /&gt;
&lt;br /&gt;
Como client do SVN eu utilizarei o &lt;a href=&quot;http://tortoisesvn.tigris.org/&quot;&gt;TortoiseSVN&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
No próximo post mostrarei como criar a tarefa no hudson que vai fazer update do código fonte diretamente do svn, compilar o projeto e enviar e-mail de notificação, tudo isso de forma automática a cada commit no svn.</content><link rel='replies' type='application/atom+xml' href='http://fabriciodev.blogspot.com/feeds/6343660066925727789/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://fabriciodev.blogspot.com/2012/01/integracao-continua-instalando-as.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/6343660066925727789'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/6343660066925727789'/><link rel='alternate' type='text/html' href='http://fabriciodev.blogspot.com/2012/01/integracao-continua-instalando-as.html' title='Integração Contínua - Instalando as ferramentas(Java JRE, TomCat e Hudson)'/><author><name>Fabricio Colombo</name><uri>http://www.blogger.com/profile/06951517260984102149</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCedF2z6z0D9d8Adr564w0ZJwcy2ckdFrC48QG9iQ9roQTh2R7yylksaD9ccou06b0HoZ-S_Did-aXDwGIUuaHVO6Aw398CK6KbnI4bEkKbiYC8M_8rp5_so6uPrqGX1A/s220/unnamed.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhegjh55CALQB9Ao3pb3tXZVRS0V39AoGRSOp6OGnssMPoL6zesA5T5jM467BOAAT4kDDIlOuszuMXjWIGGNDi9NTsLTOh2TMp_EPLVJay41Mc5bwOsF3mq3zMPzi4gmHLfuQlkuERkBoG3/s72-c/TomCat+%25283%2529.jpg" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-911701488457280480.post-7428001114393551499</id><published>2011-12-05T15:18:00.000-08:00</published><updated>2011-12-05T15:19:37.483-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="DCC32"/><category scheme="http://www.blogger.com/atom/ns#" term="Hudson"/><category scheme="http://www.blogger.com/atom/ns#" term="Integração Contínua"/><title type='text'>Integração contínua - Compilar projeto delphi por linha de comando (dcc32) - Recursos Avançados</title><content type='html'>Olá pessoal. No último post falamos sobre &lt;a href=&quot;http://fabriciodev.blogspot.com/2011/11/integracao-continua-compilar-projeto.html&quot;&gt;compilar projeto delphi por linha de comando&lt;/a&gt;, continuando o assunto, hoje vamos ver como compilar o projeto habilitando opções mais específica de compilação para rodar o projeto em modo de depuração. Nosso projeto de teste utiliza duas bibliotecas externas: &lt;a href=&quot;http://sourceforge.net/projects/fastmm/&quot;&gt;FastMM&lt;/a&gt; e &lt;a href=&quot;http://dunit.sourceforge.net/&quot;&gt;DUnit&lt;/a&gt;, para que o FastMM(em FullDebugMode) consiga captar corretamente o nome das units e métodos onde ocorreram os &lt;a href=&quot;http://pt.wikipedia.org/wiki/Vazamento_de_mem%C3%B3ria&quot;&gt;leaks de memória&lt;/a&gt;, é necessário modificar algumas configurações no projeto. Outras ferramentas como o &lt;a ref=&quot;http://code.google.com/p/delphi-code-coverage/&quot;&gt;Delphi Code Coverage&lt;/a&gt;, utilizam o Map File do executável para analizar a cobertura de código, então também habilitamos a geração do mesmo.&lt;br /&gt;
&lt;br /&gt;
A configuração do projeto nessa caso deveria ficar assim:&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbM64n6iYF35-E4WpkiVHjwF37n7sc3qG45c-eZ6hwtk4jPjwxx0zGn0F6V37MEdIJObbclUVHbsfTOsm5s-s6xD4yZbynnNvCNFdWDPmA27nPWr8ZwEpqodDFv76s-IqrVoc524YeNM71/s1600/CompilerOptions.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left:1em; margin-right:1em&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;303&quot; width=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbM64n6iYF35-E4WpkiVHjwF37n7sc3qG45c-eZ6hwtk4jPjwxx0zGn0F6V37MEdIJObbclUVHbsfTOsm5s-s6xD4yZbynnNvCNFdWDPmA27nPWr8ZwEpqodDFv76s-IqrVoc524YeNM71/s320/CompilerOptions.PNG&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfqUfQXUdY6D5jVRE0Y-ukbGoMo_Cu7YEg-SPAFX0MjG1cDUe6271tTV4jelzvlTslUp2rGHIaKEqjInoO-0iyEJg8ZC6TIdiYhsDFTh5UnJrgZ9pv8GKWdNt9dU53YyAdXRE45CnKKvKw/s1600/Linker.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left:1em; margin-right:1em&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;302&quot; width=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjfqUfQXUdY6D5jVRE0Y-ukbGoMo_Cu7YEg-SPAFX0MjG1cDUe6271tTV4jelzvlTslUp2rGHIaKEqjInoO-0iyEJg8ZC6TIdiYhsDFTh5UnJrgZ9pv8GKWdNt9dU53YyAdXRE45CnKKvKw/s320/Linker.PNG&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Um dos nossos objetivos é automatizar o processo de build sem tem que ficar abrindo a IDE para reconfigurar o projeto, então, a IDE fica configurada no modo de release, digamos assim, e durante o build automatizado nos habilitamos o que for necessário de forma automática.&lt;br /&gt;
&lt;br /&gt;
Só para refrescar a memória, a última compilação que fizemos foi a seguinte:&lt;br /&gt;
* -Q: Quiet Compile&lt;br /&gt;
* -W-: Warnings off&lt;br /&gt;
* -H-: Hints Off&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: text&quot;&gt;&gt;ExemploDCC32&gt;dcc32.exe -b ExemploDCC32.dpr -Q -W- -H-
Borland Delphi Version 15.0
Copyright (c) 1983,2002 Borland Software Corporation
56 lines, 0.14 seconds, 314356 bytes code, 7433 bytes data.
&gt;ExemploDCC32&gt;
&lt;/pre&gt;&lt;br /&gt;
Agora vamos configurar o compilador conforme as opções destacadas nas imagens acima, na sequência em que elas aparecem. Primeiro o &lt;i&gt;Optimization&lt;/i&gt;, que é identificado pela diretiva de compilação &lt;i&gt;$O&lt;/i&gt;. As diretivas de compilação são ativadas/desativadas com a seguinte sintaxe -$LetraDaDiretiva seguidos de -(desativar) ou +(ativar). Agora podemos concluir que para desativar a diretiva &lt;i&gt;Optimization&lt;/i&gt;, devemos incluir o parâmetro &lt;i&gt;-$O-&lt;/i&gt;, e assim o faremos. &lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: text&quot;&gt;&gt;ExemploDCC32&gt;dcc32.exe -b ExemploDCC32.dpr -Q -W- -H- -$O-
Borland Delphi Version 15.0
Copyright (c) 1983,2002 Borland Software Corporation
56 lines, 0.14 seconds, 314372 bytes code, 7433 bytes data.
&gt;Build Automatizado\ExemploDCC32&gt;
&lt;/pre&gt;&lt;br /&gt;
Se prestarem atenção na saída do console, houve um ligeiro aumento no tamanho do código de &lt;b&gt;314356 bytes code&lt;/b&gt; para &lt;b&gt;314372 bytes code&lt;/b&gt; provando que nossa alteração surtiu efeito.&lt;br /&gt;
&lt;br /&gt;
Seguindo as opções que modificamos, devemos habilitar a opção &lt;i&gt;Stack Frames&lt;/i&gt;, que força o compilador a gerar o stack frames para todas as procedures e funções. Esse item também é um diretiva de compilação identificada pela letra &lt;i&gt;W&lt;/i&gt;, portanto, devemos acrescentar o parâmetro &lt;i&gt;-$W+&lt;/i&gt;. O código desse projeto é muito pequeno para essa alteração causa impacto no tamanho, mais podemos ver que o projeto compilou com sucesso.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: text&quot;&gt;&gt;ExemploDCC32&gt;dcc32.exe -b ExemploDCC32.dpr -Q -W- -H- -$O- -$W+
Borland Delphi Version 15.0
Copyright (c) 1983,2002 Borland Software Corporation
56 lines, 0.14 seconds, 314372 bytes code, 7433 bytes data.
&gt;ExemploDCC32&gt;
&lt;/pre&gt;&lt;br /&gt;
Já modificamos as duas opções da aba Compiler, agora vamos para a aba Linker, onde temo como primeira opção selecionada a geração do Map file. Há três opções do mesmo:&lt;br /&gt;
* Segments: Parâmetro -GS&lt;br /&gt;
* Publics: Parâmetro -GP&lt;br /&gt;
* Detailed: Parâmetro -GD&lt;br /&gt;
&lt;br /&gt;
A saída do console não é modificada, mais podemos solicitar a listagem do arquivo .map para confirmar sua geração. Observe.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: text&quot;&gt;&gt;ExemploDCC32&gt;dcc32.exe -b ExemploDCC32.dpr -Q -W- -H- -$O- -$W+ -GD
Borland Delphi Version 15.0
Copyright (c) 1983,2002 Borland Software Corporation
56 lines, 0.19 seconds, 314372 bytes code, 7433 bytes data.

&gt;ExemploDCC32&gt;dir *.map
 O volume na unidade D não tem nome.
 O número de série do volume é 745C-EA2C

 Pasta ExemploDCC32

15/08/2011  21:18           302.428 ExemploDCC32.map
               1 arquivo(s)        302.428 bytes
               0 pasta(s)  8.627.687.424 bytes disponíveis

&gt;ExemploDCC32&gt;
&lt;/pre&gt;&lt;br /&gt;
E por último, vamos habilitar a opção &lt;i&gt;Include TD32 debug info&lt;/i&gt;, que faz com que o compilador incluar informações adicionais de debug dentro do executável, tornando o tamanho do executável muito maior. O parâmetro utilizado nesse caso é o -V (Debug Information in EXE) e o executável aqui passou de 365kb para 2.790kb.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: text&quot;&gt;&gt;ExemploDCC32&gt;dcc32.exe -b ExemploDCC32.dpr -Q -W- -H- -$O- -$W+ -GD -V
Borland Delphi Version 15.0
Copyright (c) 1983,2002 Borland Software Corporation
56 lines, 0.30 seconds, 314372 bytes code, 7433 bytes data.

&gt;ExemploDCC32&gt;
&lt;/pre&gt;&lt;br /&gt;
Note como o tamanho do código não aumentou, apenas o tamanho do executável, e isso também não afeta a performance da aplicação, mas lembrando que os parâmetros apresentados neste post são para usar em modo de desenvolvimento.</content><link rel='replies' type='application/atom+xml' href='http://fabriciodev.blogspot.com/feeds/7428001114393551499/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://fabriciodev.blogspot.com/2011/12/integracao-continua-compilar-projeto.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/7428001114393551499'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/7428001114393551499'/><link rel='alternate' type='text/html' href='http://fabriciodev.blogspot.com/2011/12/integracao-continua-compilar-projeto.html' title='Integração contínua - Compilar projeto delphi por linha de comando (dcc32) - Recursos Avançados'/><author><name>Fabricio Colombo</name><uri>http://www.blogger.com/profile/06951517260984102149</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCedF2z6z0D9d8Adr564w0ZJwcy2ckdFrC48QG9iQ9roQTh2R7yylksaD9ccou06b0HoZ-S_Did-aXDwGIUuaHVO6Aw398CK6KbnI4bEkKbiYC8M_8rp5_so6uPrqGX1A/s220/unnamed.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbM64n6iYF35-E4WpkiVHjwF37n7sc3qG45c-eZ6hwtk4jPjwxx0zGn0F6V37MEdIJObbclUVHbsfTOsm5s-s6xD4yZbynnNvCNFdWDPmA27nPWr8ZwEpqodDFv76s-IqrVoc524YeNM71/s72-c/CompilerOptions.PNG" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-911701488457280480.post-1115441871828028450</id><published>2011-11-12T07:58:00.000-08:00</published><updated>2011-11-12T08:45:03.012-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="DCC32"/><category scheme="http://www.blogger.com/atom/ns#" term="Hudson"/><category scheme="http://www.blogger.com/atom/ns#" term="Integração Contínua"/><title type='text'>Integração contínua - Compilar projeto delphi por linha de comando (dcc32)</title><content type='html'>Olá pessoal, tudo bem? Nessa série de posts sobre &lt;a href=&quot;http://fabriciodev.blogspot.com/2011/11/integracao-continua-com-hudon.html&quot;&gt;Integração Contínua&lt;/a&gt;, precisamos compilar nosso projeto de forma automatizada, para conseguir rodas os testes sempre com a última versão disponível do código fonte, e é sobre isso que vou falar hoje.&lt;br /&gt;
&lt;br /&gt;
A partir do delphi 2007 há integração com &lt;a href=&quot;http://en.wikipedia.org/wiki/MSBuild&quot;&gt;msbuild&lt;/a&gt;, o que facilita muito a nossa vida, sem falar que no Delphi XE uma das ferramentas incluídas no pacote é o &lt;a href=&quot;http://www.finalbuilder.com/&quot;&gt;Final Builder&lt;/a&gt;, excelente ferramente de build automatizado. Infelizmente, muita gente ainda utiliza o delphi 7 (eu sou um deles) e nesse caso o trabalho é mais braçal. Esse post tem como foco aqueles que por algum motivo ainda utilizam - principalmente - o delphi 7.&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Para compilar os projetos, é utilizado o dcc32.exe, que é o compilador que vem junto com o delphi e que o mesmo usa para compilar nossos projetos. Ele fica localizado na pasta $(Delphi)\bin. Se digitar dcc32 no prompt de comando, será listado os parâmetros existentes para o mesmo. Caso haja mais de uma versão do delphi instalado, é recomendado utilizar o caminho absoluto do compilador para garantir que está utilizando a versão correta.&lt;br /&gt;
&lt;br /&gt;
Primeiro, vamos falar dos parâmetros mais importantes.&lt;br /&gt;
&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;-B: Indica que serão compiladas todas as units do projeto, ou seja, é equivalente ao Build da IDE.&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;-Q: Executa uma compilação silenciosa. A compilação normal lista todas as units que estão sendo compiladas, na compilação silenciosa, apenas Hints, Warnings e erros serão exibidos.&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;-H: Habilita (-H+) ou desabilita (-H-) a exibição de hints.&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;-W: Habilita (-W+) ou desabilita (-W-) a exibição dos Warnings emitidos pelo compilador. Para habilitar ou desabilitar um warning específico, é preciso especificá-lo após o parâmetro, precedidos de + ou -. Exemplo: -W-SYMBOL_PLATFORM+UNIT_DEPRECATED&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;-R: Conjunto de diretórios onde o compilador irá buscar por arquivos de resources (.RC, .RES) utilizados no projeto;&lt;/li&gt;
&lt;/ul&gt;&lt;ul&gt;&lt;li&gt;-U: Conjunto de diretórios onde o compilador irá procurar os arquivos .PAS ou .DCU utilizados no projeto. Isso inclui os arquivos do projeto e as biblietecas externas.&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
Os diretórios passados no parâmetro devem ser estar separados por ponto e vírgula (;) e entre aspas duplas - para cada diretório - caso haja espaço em branco em alguma parte do caminho&lt;br /&gt;
&lt;br /&gt;
Isso já é suficiente para compilar a maior parte dos projetos, então vamos por esse conhecimento em prática.&lt;br /&gt;
&lt;br /&gt;
Primeiro, vamos criar um novo projeto que terá apenas fim didático para conhecer melhor os recursos do compilador. No form principal adicione um botão e dê a ele o nome de btnFacaAlgo e no evento OnClick insira o código abaixo:&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;procedure TFrm_Main.btnFacaAlgoClick(Sender: TObject);
var
  i: Integer;
  k: Integer; //Hint - variable never used
begin
  if (DebugHook &amp;lt;&amp;gt; 0) then; //Warning - Symbol specific to a platform

  while i &amp;lt; 10 do //Warning - variable not initialized
  begin
    Inc(i);
  end;
end;
&lt;/pre&gt;Esse código produz dois Warnings e um Hint, e não faz absolutamente nada além disso. Salve o form principal como uMain.pas e o projeto como ExemploDcc32.dpr. Agora já podemos brincar com o compilador. Abra o prompt de comando e digite dcc32. Você deve ver uma saída como essa:  &lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjL1PYQLNfOfTFZ4kOgurGMGljS6-5Kpj-8pk6w2vMZsKxuDBeKkdjfZ3FUnzmy97m81CjNI5LAdfniOlhbpeagIVv8rTY0CUb4Eo1cWTkWb5jK7fxD9XoGWOqrUtulYh-6FXp-iNB2Z7-y/s1600/dcc32.PNG&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;349&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjL1PYQLNfOfTFZ4kOgurGMGljS6-5Kpj-8pk6w2vMZsKxuDBeKkdjfZ3FUnzmy97m81CjNI5LAdfniOlhbpeagIVv8rTY0CUb4Eo1cWTkWb5jK7fxD9XoGWOqrUtulYh-6FXp-iNB2Z7-y/s400/dcc32.PNG&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;Pelo prompt, navegue até o diretório do projeto para não precisar digitar o caminho absoluto do projeto. Feito isso, vamos a nosso primeira tentativa de compilação:  &lt;br /&gt;
&lt;pre class=&quot;brush: text&quot;&gt;&amp;gt;ExemploDCC32&amp;gt;dcc32.exe -b ExemploDCC32.dpr
Borland Delphi Version 15.0
Copyright (c) 1983,2002 Borland Software Corporation
uMain.pas(29) Warning: Symbol &#39;DebugHook&#39; is specific to a platform
uMain.pas(31) Warning: Variable &#39;i&#39; might not have been initialized
uMain.pas(27) Hint: Variable &#39;k&#39; is declared but never used in &#39;TFrm_Main.btnFacaAlgoClick&#39;
uMain.pas(38)
ExemploDCC32.dpr(16)
56 lines, 0.14 seconds, 314356 bytes code, 7433 bytes data.
&amp;gt;ExemploDCC32&amp;gt;
&lt;/pre&gt;Como podem ver, foram listados dois warnings, um hint e os arquivos contidos no projeto, no caso, uMain e ExemploDCC32.dpr. É fácil imaginar que uma saída de console assim ficaria um tanto quanto poluída quando lidamos com um projeto grande, então, vamos dar uma enxugada nisso. Primeiro, vamos deixar de fora a listagem das units incluídas no projeto, pois não será relevante para o nosso caso, e para isso, vou incluir a diretiva -Q (Quiet Compile) na linha de comando.  &lt;br /&gt;
&lt;pre class=&quot;brush: text&quot;&gt;&amp;gt;\ExemploDCC32&amp;gt;dcc32.exe -b ExemploDCC32.dpr -Q
Borland Delphi Version 15.0
Copyright (c) 1983,2002 Borland Software Corporation
uMain.pas(29) Warning: Symbol &#39;DebugHook&#39; is specific to a platform
uMain.pas(31) Warning: Variable &#39;i&#39; might not have been initialized
uMain.pas(27) Hint: Variable &#39;k&#39; is declared but never used in &#39;TFrm_Main.btnFacaAlgoClick&#39;
56 lines, 0.14 seconds, 314356 bytes code, 7433 bytes data.
&amp;gt;ExemploDCC32&amp;gt;
&lt;/pre&gt;Já melhorou, mais ainda há muita informação, por exemplo, o alerta de que &lt;i&gt;DebugHook&lt;/i&gt; é específico para uma plataforma não é relevante na maioria dos casos, pois a aplicações delphi em geral só rodam no windows de forma nativa(há opções como o Kylix e o Delphi XE2 que compila para iOS), então podemos tranquilamente desativar esse warning. Para isso, incluirei o parâmetro -W-DiretivaQueVouDesabilitar, no caso, &quot;-W-Symbol_Platform&quot;.   &lt;br /&gt;
&lt;pre class=&quot;brush: text&quot;&gt;&amp;gt;ExemploDCC32&amp;gt;dcc32.exe -b ExemploDCC32.dpr -Q -W-Symbol_Platform
Borland Delphi Version 15.0
Copyright (c) 1983,2002 Borland Software Corporation
uMain.pas(31) Warning: Variable &#39;i&#39; might not have been initialized
uMain.pas(27) Hint: Variable &#39;k&#39; is declared but never used in &#39;TFrm_Main.btnFacaAlgoClick&#39;
56 lines, 0.14 seconds, 314356 bytes code, 7433 bytes data.
&amp;gt;ExemploDCC32&amp;gt;
&lt;/pre&gt;Para desativar todos os warnings, bastaria o parâmetro &quot;-W-&quot;.  &lt;br /&gt;
&lt;pre class=&quot;brush: text&quot;&gt;&amp;gt;ExemploDCC32&amp;gt;dcc32.exe -b ExemploDCC32.dpr -Q -W-
Borland Delphi Version 15.0
Copyright (c) 1983,2002 Borland Software Corporation
uMain.pas(27) Hint: Variable &#39;k&#39; is declared but never used in &#39;TFrm_Main.btnFacaAlgoClick&#39;
56 lines, 0.14 seconds, 314356 bytes code, 7433 bytes data.
&amp;gt;ExemploDCC32&amp;gt;
&lt;/pre&gt;Agora só restou o Hint, e também vamos desativar ela pois não vão agregar valor para o nosso objetivo. Como dito anteriormente, basta incluir o parâmetro &quot;-H-&quot;, e veja-mos o resultado final.  &lt;br /&gt;
&lt;pre class=&quot;brush: text&quot;&gt;&amp;gt;ExemploDCC32&amp;gt;dcc32.exe -b ExemploDCC32.dpr -Q -W- -H-
Borland Delphi Version 15.0
Copyright (c) 1983,2002 Borland Software Corporation
56 lines, 0.14 seconds, 314356 bytes code, 7433 bytes data.
&amp;gt;ExemploDCC32&amp;gt;
&lt;/pre&gt;&lt;br /&gt;
No próximo post, vamos fazer isso com um projeto que utiliza bibliotecas externas  e explorar recursos mais avançados do compilador.&lt;br /&gt;
&lt;br /&gt;
Até a próxima.</content><link rel='replies' type='application/atom+xml' href='http://fabriciodev.blogspot.com/feeds/1115441871828028450/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://fabriciodev.blogspot.com/2011/11/integracao-continua-compilar-projeto.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/1115441871828028450'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/1115441871828028450'/><link rel='alternate' type='text/html' href='http://fabriciodev.blogspot.com/2011/11/integracao-continua-compilar-projeto.html' title='Integração contínua - Compilar projeto delphi por linha de comando (dcc32)'/><author><name>Fabricio Colombo</name><uri>http://www.blogger.com/profile/06951517260984102149</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCedF2z6z0D9d8Adr564w0ZJwcy2ckdFrC48QG9iQ9roQTh2R7yylksaD9ccou06b0HoZ-S_Did-aXDwGIUuaHVO6Aw398CK6KbnI4bEkKbiYC8M_8rp5_so6uPrqGX1A/s220/unnamed.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjL1PYQLNfOfTFZ4kOgurGMGljS6-5Kpj-8pk6w2vMZsKxuDBeKkdjfZ3FUnzmy97m81CjNI5LAdfniOlhbpeagIVv8rTY0CUb4Eo1cWTkWb5jK7fxD9XoGWOqrUtulYh-6FXp-iNB2Z7-y/s72-c/dcc32.PNG" height="72" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-911701488457280480.post-2484591488942931281</id><published>2011-11-05T08:09:00.000-07:00</published><updated>2011-11-12T08:46:27.378-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Hudson"/><category scheme="http://www.blogger.com/atom/ns#" term="Integração Contínua"/><category scheme="http://www.blogger.com/atom/ns#" term="Subversion"/><title type='text'>Integração contínua com Hudon, subversion e Delphi</title><content type='html'>Cada vez mais estamos buscando maneiras de melhorar a qualidade do software que produzimos, gerando um código com menos bugs e um produto final que gere valor para o cliente. Uma das melhores maneiras para se desenvolver software é praticar &lt;a href=&quot;http://improveit.com.br/xp/praticas/tdd&quot;&gt;TDD&lt;/a&gt;, não só por escrever o teste primeiro, mais por contribuir significativamente para a melhoria do design do código, com classes mais coesas e com poucas responsabilidades, consequentemente, temos classes mais fáceis de testar e menos suscetíveis a falhas, e ainda por cima ganhamos uma especificação testável de brinde. :P&lt;br /&gt;
&lt;br /&gt;
Estes testes tem também um papel fundamental garantindo que não haja regressão do software, ou seja, quando alguém altera o código, os testes devem continuar passando, garantindo que tudo continua funcionando adequadamente. Então antes de cada commit, precisamos fazer update no svn para atualizar nossa working copy, rodar os testes e deixar tudo verdinho e só depois integrar nossas alterações. Mais há algo errado com essa sequência de passos. É muito manual. Depende do desenvolvedor. Há muitos pontos de falha, ele pode esquecer de sincronizar seu repositório local, pode esquecer de rodar os testes, pode estar trabalhando até tarde e estar cansado demais pra rodar os teste, etc, etc. E o que devemos fazer então? Automatizar, é claro. &lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Vou mostrar em uma série de posts como construir um ambiente para aplicar na prática Integração Contínua. Claro que integração contínua não é apenas sobre ferramentas, é também uma mudança de comportamento, tem que ser incorporado à cultura do time, mais uma coisa de cada vez. Vamos ver a definição dada por &lt;a href=&quot;http://martinfowler.com/articles/continuousIntegration.html&quot;&gt;Martin Fowler&lt;/a&gt;:&lt;br /&gt;
&quot;Integração contínua é uma prática de desenvolvimento de software onde os membros de uma equipe integram seu trabalho frequentemente, geralmente cada um integra no mínimo diariamente – levando a múltiplas integrações por dia. Cada integração é verificada por um build automático (incluindo testes) para detectar erros de integração tão rápido quanto possível. Muitas equipes descobrem que esta prática leva a problemas de integração significativamente reduzidos e permite que a equipe desenvolva software coeso mais rapidamente.&quot;&lt;br /&gt;
&lt;br /&gt;
Para colocar isso em prática utilizare-mos o &lt;a href=&quot;hudson-ci.org&quot;&gt;Hudson&lt;/a&gt; como servidor de integração, &lt;a href=&quot;http://www.visualsvn.com/server/download/&quot;&gt;Visual SVN Server&lt;/a&gt; como sistema de controle de código fonte, &lt;a href=&quot;dunit.sourceforge.net&quot;&gt;DUnit&lt;/a&gt; para testes unitários e &lt;a href=&quot;code.google.com/p/delphi-code-coverage&quot;&gt;delphi-code-coverage&lt;/a&gt; para cobertura de código.&lt;br /&gt;
&lt;br /&gt;
Fique atento às próximas publicações.</content><link rel='replies' type='application/atom+xml' href='http://fabriciodev.blogspot.com/feeds/2484591488942931281/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://fabriciodev.blogspot.com/2011/11/integracao-continua-com-hudon.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/2484591488942931281'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/2484591488942931281'/><link rel='alternate' type='text/html' href='http://fabriciodev.blogspot.com/2011/11/integracao-continua-com-hudon.html' title='Integração contínua com Hudon, subversion e Delphi'/><author><name>Fabricio Colombo</name><uri>http://www.blogger.com/profile/06951517260984102149</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCedF2z6z0D9d8Adr564w0ZJwcy2ckdFrC48QG9iQ9roQTh2R7yylksaD9ccou06b0HoZ-S_Did-aXDwGIUuaHVO6Aw398CK6KbnI4bEkKbiYC8M_8rp5_so6uPrqGX1A/s220/unnamed.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-911701488457280480.post-5750262082172467818</id><published>2011-09-09T09:12:00.000-07:00</published><updated>2011-11-12T08:49:48.943-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Delphi XE2"/><category scheme="http://www.blogger.com/atom/ns#" term="LiveBinding"/><title type='text'>LiveBindings no delphi XE2</title><content type='html'>Hoje vamos falar sobre &lt;a href=&quot;http://docwiki.embarcadero.com/RADStudio/en/LiveBindings_in_RAD_Studio&quot;&gt;LiveBindings&lt;/a&gt;, um dos novos recursos do Delphi XE2.&lt;br /&gt;
&lt;br /&gt;
LiveBindings é um mecanismo de data-binding suportados pela VCL e FireMonkey. Ele é baseado em expressões (binding expressions), o que significa que usa expressões para ligar objetos uns aos outros, por meio de suas propriedades. &lt;br /&gt;
&lt;br /&gt;
É importante salientar que o LiveBinding foi criado devido a inclusão do FireMonkey, uma vez que o mesmo não possui componentes DB-Aware. Ao invés da criação desses componentes optou-se por criar um mecanismo de data-binding, e foi uma decisão muito feliz. No caso do FireMonkey os componentes podem ser ligados ao DataSource de maneira relativamente simples e de forma visual.&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Minha maior expectativa era pode utilizar esse recursos para ligar objetos de negócio a componentes visuais não data aware, deixando a manipulação dos dados mais transparente, sem precisar ficar alimentando manualmente os componentes visuais e depois recuperar esse valores também manualmente, e confesso que fiquei decepcionado com as opções oferecidas nesse sentido. É possível, mais é muito mais verboso e intrusivo do que eu gostaria que fosse.&lt;br /&gt;
&lt;br /&gt;
No site da embarcadero há três tutoriais: &lt;a href=&quot;http://docwiki.embarcadero.com/RADStudio/en/Tutorial:_Using_LiveBinding_Programatically&quot;&gt;Tutorial: Using LiveBinding Programatically&lt;/a&gt;, &lt;a href=&quot;http://docwiki.embarcadero.com/RADStudio/en/Tutorial:_Using_LiveBinding_in_VCL_Applications&quot;&gt;Tutorial: Using LiveBinding in VCL Applications&lt;/a&gt; e &lt;a href=&quot;http://docwiki.embarcadero.com/RADStudio/en/Tutorial:_Using_LiveBinding_to_Create_an_Application_Without_Code&quot;&gt;Tutorial: Using LiveBinding to Create a FireMonkey Application Without Code&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
De maneira resumida, quando às ligações envolvem apenas componentes visuais, ela é feita através do object inspector. Os componentes visuais possuem uma propriedade chamada &lt;b&gt;LiveBindings&lt;/b&gt;, onde você deve clicar e selecionar a opção &lt;b&gt;New LiveBinding...&lt;/b&gt;. Isso criará um BindExpression, onde você deve configurar:&lt;br /&gt;
- &lt;b&gt;ControlExpression:&lt;/b&gt; Propriedade do componente selecionado que deverá ser atualizada.&lt;br /&gt;
- &lt;b&gt;SourceComponent:&lt;/b&gt; Componente de origem. Quando ele for modificado o componente atual será notificado.&lt;br /&gt;
- &lt;b&gt;SourceExpression:&lt;/b&gt; Propriedade que será lida para atualizar a propriedade ControlExpression do componente atual.&lt;br /&gt;
&lt;br /&gt;
Esse TBindExpression fica armazenado em um componente TBindingsList, que é adicionado ao form automaticamente. &lt;br /&gt;
&lt;br /&gt;
Relativamente simples. Só tem um porém, dessa forma ainda não funcionará, porque não foi incluído recurso de auto notificação, ou seja, a VCL não gerencia os objetos envolvidos para fazer a notificação automaticamente quando o valor da propriedade do SourceComponent for modificada. Temos que fazer isso manualmente.Em cada objeto envolvido você tem que implementar o método OnChange e invocar BindingsList.Notify(ObjetoAlterado, &#39;PropriedadeAlterada&#39;), para que as alterações sejam propagadas para os &quot;ouvintes&quot; do objeto. &lt;br /&gt;
&lt;br /&gt;
Agora vamos ver como fazer o binding programaticamente, utilizando objetos não visuais. Dado uma classe TMyObject, vamos fazer o binding da classe com um TEdit adicionado em um form.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;type
  TMyObject = class(TObject)
  private
    FStringValue: String;
    procedure SetStringValue(const Value: String);
  public
    property StringValue: String read FStringValue write SetStringValue;
  end;
&lt;/pre&gt;&lt;br /&gt;
Para declarar o binding precisamos da unit System.Bindings.Helper, e código fica assim:&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;TBindings.CreateManagedBinding(
        { inputs }
        [TBindings.CreateAssociationScope([Associate(FMyObject, &#39;MyObject&#39;)])],
        &#39;MyObject.StringValue&#39;,
        { outputs }
        [TBindings.CreateAssociationScope([Associate(Edit1, &#39;edit1&#39;)])],
        &#39;edit1.text&#39;,
        nil);
&lt;/pre&gt;&lt;br /&gt;
Feito isso, quando alterar o valor da propriedade StringValue do objeto MyObject, o valor do edit1.text será alterado automaticamente, certo? Errado! Assim como o caso anterior, a notificação também não é automática. Quando o valor da propriedade for alterado, também devemos notificar o gerenciador.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;procedure TMyObject.SetStringValue(const Value: String);
begin
  if (FStringValue &lt;&gt; Value) then
  begin
    FStringValue := Value;
    TBindings.Notify(FMyObject, &#39;StringValue&#39;);
  end;
end;
&lt;/pre&gt;&lt;br /&gt;
O último detalhe é que os gerenciadores de bindings nos dois casos apresentados não são os mesmos. O TBindingsList gerencia uma lista de &lt;b&gt;TBindExpression&lt;/b&gt;, enquanto, o &lt;br /&gt;
TBindings gerencia uma lista de &lt;b&gt;TBindingExpression&lt;/b&gt;. Desse modo, se por algum motivo um componentes está associado aos dois tipos de binding, os dois gerenciadores devem ser notificados.&lt;br /&gt;
&lt;br /&gt;
Eu sinceramente esperava mais do que isso. Acredito ainda não ser possível utilizar isso em produção - utilizando VCL -, mais não posso negar que já é um avanço. Espero que na próxima versão esse recurso evolua e torne esse trabalho mais simples e transparente, com notificação automática e um gerenciador único para controlar o binding.&lt;br /&gt;
&lt;br /&gt;
Até a próxima.</content><link rel='replies' type='application/atom+xml' href='http://fabriciodev.blogspot.com/feeds/5750262082172467818/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://fabriciodev.blogspot.com/2011/09/livebindings-no-delphi-xe2.html#comment-form' title='4 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/5750262082172467818'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/5750262082172467818'/><link rel='alternate' type='text/html' href='http://fabriciodev.blogspot.com/2011/09/livebindings-no-delphi-xe2.html' title='LiveBindings no delphi XE2'/><author><name>Fabricio Colombo</name><uri>http://www.blogger.com/profile/06951517260984102149</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCedF2z6z0D9d8Adr564w0ZJwcy2ckdFrC48QG9iQ9roQTh2R7yylksaD9ccou06b0HoZ-S_Did-aXDwGIUuaHVO6Aw398CK6KbnI4bEkKbiYC8M_8rp5_so6uPrqGX1A/s220/unnamed.jpg'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-911701488457280480.post-8584420536079607244</id><published>2011-08-22T16:43:00.000-07:00</published><updated>2011-11-12T08:52:00.246-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Podcast"/><title type='text'>PodCasts</title><content type='html'>Olá pessoal. Gostaria de compartilhar com vocês os podcasts que acompanho e que ajudam muito a me manter atualizado sobre vários assuntos.&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;a href=&quot;http://grokpodcast.com/&quot;&gt;Grok podcast&lt;/a&gt; é o que tem assuntos mais variados, já &quot;grokamos&quot; sobre Ruby, Python, Arduíno, Node-JS e mais recentemente Erlang, e outros assuntos como Sistemas de controle de versão, carreira, desenvolvimento de games, e muito mais. Visite o site para saber o que significa o termo grok.&lt;br /&gt;
&lt;/li&gt;

&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;

&lt;li&gt;&lt;a href=&quot;http://improveit.com.br/podcast&quot;&gt;Improvecasts&lt;/a&gt; que foi produzido pelo &lt;a href=&quot;http://viniciusteles.com.br/sobre/pagina/home&quot;&gt;Vinícius Teles&lt;/a&gt; durante o ano de 2007. Apesar da longa data ele trazem um conteúdo muito rico sobre desenvolvimento ágil. &lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://ccsl.ime.usp.br/agilcoop/agilcast&quot;&gt;AgilCast&lt;/a&gt; que é mantido pela &lt;a href=&quot;http://ccsl.ime.usp.br/agilcoop/&quot;&gt;AgilCoop&lt;/a&gt;, Cooperativa de Desenvolvimento Ágil de Software, e é composta por professores, alunos e ex-alunos do IME/USP. Seu conteúdo visa promover o uso de métodos ágeis de desenvolvimento de software.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://blog.bluesoft.com.br/category/podcast&quot;&gt;Bluesoft podcast&lt;/a&gt;. No blog da bluesoft além dos podcasts tem muitos vídeos dos mais diversos assunto. Vale a pena conferir.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://podcast.dotnetarchitects.net/&quot;&gt;.Net Architects Podcast&lt;/a&gt;, como o próprio nome diz, tem foco na arquitetura do software, e traz discussões excelentes como: &lt;a href=&quot;http://podcast.dotnetarchitects.net/2009/11/podcast-8-principios-s-o-l-i-d/trackback/&quot;&gt;Princípios S.O.L.I.D&lt;/a&gt;, &lt;a href=&quot;http://podcast.dotnetarchitects.net/2009/11/podcast-8-principios-s-o-l-i-d/trackback/&quot;&gt;Arquitetura emergente&lt;/a&gt; e muitos outros.&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.ericksasse.com.br/tpodcast&quot;&gt;TPodCast&lt;/a&gt; é infelizmente, o único podcast sobre delphi que conheço (pelo menos em português). Méritos para &lt;a href=&quot;http://www.ericksasse.com.br/&quot;&gt;Erick Sasse&lt;/a&gt; e &lt;a href=&quot;http://twitter.com/ltogniolli&quot;&gt;Leonel Togniolli&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://voidpodcast.com/&quot;&gt;VoidPodcast&lt;/a&gt;,&amp;nbsp;Um bate papo descontraído e bem humorado entre três amigos:&amp;nbsp;&amp;nbsp;&lt;a href=&quot;http://reverb.leandrodaniel.com/&quot;&gt;Leandro Daniel&lt;/a&gt; (&lt;a href=&quot;http://twitter.com/leandronet&quot;&gt;@leandronet&lt;/a&gt;), &amp;nbsp;&lt;a href=&quot;http://viniciusquaiato.com/&quot;&gt;Vinícius Quaiato&lt;/a&gt; (&lt;a href=&quot;http://twitter.com/vquaiato&quot;&gt;@vquaiato&lt;/a&gt;, vulgo arrobinha) e &lt;a href=&quot;http://elemarjr.net/&quot;&gt;Elemar Júnior&lt;/a&gt; (&lt;a href=&quot;http://twitter.com/elemarjr&quot;&gt;@elemarjr&lt;/a&gt;)&lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.woompa.blog.br/category/woompacast&quot;&gt;WoompaCast&lt;/a&gt; é uma start-up que recentemente começou a gravar podcasts compartilhando suas experiência. &lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://sembugs.podomatic.com/&quot;&gt;Sembugs&lt;/a&gt;, é produzido por &lt;a href=&quot;http://sembugs.blogspot.com/&quot;&gt;Elias Nogueira&lt;/a&gt; e é voltado para teste e qualidade de software. &lt;br /&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://imasters.com.br/autor/1200&quot;&gt;DatabaseCast&lt;/a&gt; com foco principal em banco de dados.&lt;br /&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;br /&gt;
Se alguém conhecer algum &lt;a href=&quot;http://pt.wikipedia.org/wiki/Podcast&quot;&gt;podcast&lt;/a&gt; que não esteja na lista, deixe um comentário com o link que eu vou incrementando aqui.&lt;br /&gt;
&lt;br /&gt;
Abraços e até a próxima.</content><link rel='replies' type='application/atom+xml' href='http://fabriciodev.blogspot.com/feeds/8584420536079607244/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://fabriciodev.blogspot.com/2011/08/podcasts.html#comment-form' title='7 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/8584420536079607244'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/8584420536079607244'/><link rel='alternate' type='text/html' href='http://fabriciodev.blogspot.com/2011/08/podcasts.html' title='PodCasts'/><author><name>Fabricio Colombo</name><uri>http://www.blogger.com/profile/06951517260984102149</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCedF2z6z0D9d8Adr564w0ZJwcy2ckdFrC48QG9iQ9roQTh2R7yylksaD9ccou06b0HoZ-S_Did-aXDwGIUuaHVO6Aw398CK6KbnI4bEkKbiYC8M_8rp5_so6uPrqGX1A/s220/unnamed.jpg'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-911701488457280480.post-1145141850496532312</id><published>2011-08-13T07:18:00.000-07:00</published><updated>2011-11-12T08:52:46.491-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="GDD"/><title type='text'>Google Developer Day Brasil 2011 - Prova de Programação</title><content type='html'>Olá pessoal. Após ler o post do &lt;a href=&quot;http://www.ericksasse.com.br&quot;&gt;Erick Sasse&lt;/a&gt; entitulado &lt;a href=&quot;http://www.ericksasse.com.br/prova-do-google-developer-day-em-delphi&quot;&gt;Prova do Google Developer Day em Delphi&lt;/a&gt; decidi aceitar o desafio e resolver a prova (também em delphi) mesmo que eu não vá ao &lt;a href=&quot;http://www.google.com.br/events/developerday/2011/sao-paulo/&quot;&gt;Google Developer Day 2011 Brasil&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
A prova é bem interessante, é dado um texto em um alfabeto diferente do nosso e algumas regras para extrair do texto as quantidades de preposições e verbos, ordenar o texto e transformar as palavras em números base 20.&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Uma explicação mais detalhada dos problemas pode ser encontrado no post do Erick mencionado anteriormente (&lt;a href=&quot;http://www.ericksasse.com.br/prova-do-google-developer-day-em-delphi/&quot;&gt;Prova do Google Developer Day em Delphi&lt;/a&gt;).&lt;br /&gt;
&lt;br /&gt;
Para fazer a prova, o link é este &lt;a href=&quot;http://developerquiz.appspot.com/?lang=pt&quot;&gt;Provinha de Programação - Google Developer Day Brasil 2011&lt;/a&gt;, e você pode fazer mesmo que não queira participar do evento.&lt;br /&gt;
&lt;br /&gt;
A minha implementação está disponível no &lt;a href=&quot;https://bitbucket.org/fabriciocolombo/googledeveloperday2011&quot;&gt;meu bitbucket&lt;/a&gt;. Recomendo que façam, pois é um exercício bem interessante e a prova é diferente para cada um. Sugiro também que tentem resolver os problemas sem olhar nossas soluções, &quot;Quem sabe você não tem idéias muito melhores?&quot;</content><link rel='replies' type='application/atom+xml' href='http://fabriciodev.blogspot.com/feeds/1145141850496532312/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://fabriciodev.blogspot.com/2011/08/google-developer-day-brasil-2011-prova.html#comment-form' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/1145141850496532312'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/1145141850496532312'/><link rel='alternate' type='text/html' href='http://fabriciodev.blogspot.com/2011/08/google-developer-day-brasil-2011-prova.html' title='Google Developer Day Brasil 2011 - Prova de Programação'/><author><name>Fabricio Colombo</name><uri>http://www.blogger.com/profile/06951517260984102149</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCedF2z6z0D9d8Adr564w0ZJwcy2ckdFrC48QG9iQ9roQTh2R7yylksaD9ccou06b0HoZ-S_Did-aXDwGIUuaHVO6Aw398CK6KbnI4bEkKbiYC8M_8rp5_so6uPrqGX1A/s220/unnamed.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-911701488457280480.post-2282192644378643878</id><published>2011-08-06T11:35:00.000-07:00</published><updated>2011-11-12T08:51:27.242-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Factory"/><category scheme="http://www.blogger.com/atom/ns#" term="Mock"/><category scheme="http://www.blogger.com/atom/ns#" term="Padrões de Projeto"/><category scheme="http://www.blogger.com/atom/ns#" term="Strategy"/><title type='text'>Strategy - Separando os comportamentos - Parte Final</title><content type='html'>No &lt;a href=&quot;http://fabriciodev.blogspot.com/2011/08/strategy-separando-os-comportamentos.html&quot;&gt;último artigo&lt;/a&gt; falei sobre o padrão de projeto Strategy e expus um diagrama de como utilizar o strategy para exportação de dados. Hoje vou mostrar como podemos implementar o padrão seguindo a modelagem do diagrama. &lt;br /&gt;
&lt;br /&gt;
Primeiro, vamos a declaração da interface que define a API de exportação e o enumerator com os formatos de saída suportados.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot; title=&quot;Interface e Enumerator&quot;&gt;type
  TExporterType = (etText, etCSV, etXML);

  IExporterStrategy = interface
  [&#39;{AA69E6F1-389F-4DC3-AC14-7FA7A749B183}&#39;]
    function GetFileName: String;
    procedure SetFileName(const Value: String);

    property FileName: String read GetFileName write SetFileName;

    procedure ExportToFile(const Value: String);
  end;
&lt;/pre&gt;&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Agora vamos a implementação da classe responsável pela exportação em arquivo texto.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot; title=&quot;Implementação para formato Texto&quot;&gt;type
  TTextExporterStrategy = class(TInterfacedObject, IExporterStrategy)
  private
    FFileName: String;
  public
    procedure ExportToFile(const Value: String);
    
    function GetFileName: String;
    procedure SetFileName(const Value: String);
  end;
  
implementation
  
  /* Getter e Setter omitidos*/
  
procedure TTextExporterStrategy.ExportToFile(const Value: String);
var
  vFile: TextFile;
begin
  if (FFileName = EmptyStr) then
    raise EFileIsNotDefined.Create;

  AssignFile(vFile, FFileName);
  try
    Rewrite(vFile);

    WriteLn(vFile, Value);
  finally
    CloseFile(vFile);
  end;
end;  
&lt;/pre&gt;&lt;br /&gt;
Também implementei a exportação em formato CSV. Assumi que os espaços em branco seriam substituídos pelo separador.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot; title=&quot;Implementação para formato CSV&quot;&gt;type
  TCSVExporterStrategy = class(TInterfacedObject, IExporterStrategy)
  private
    FFileName: String;
  public
    procedure ExportToFile(const Value: String);
    
    function GetFileName: String;
    procedure SetFileName(const Value: String);
  end;
  
implementation
  
  /* Getter e Setter omitidos*/  
  
implementation

{ TCSVExporterStrategy }

procedure TCSVExporterStrategy.ExportToFile(const Value: String);
var
  vFile: TextFile;
  vCSVLine: TStringList;
  i: Integer;
begin
  if (FFileName = EmptyStr) then
    raise EFileIsNotDefined.Create;

  AssignFile(vFile, FFileName);
  try
    Rewrite(vFile);

    vCSVLine := TStringList.Create;
    try
      ExtractStrings([&#39; &#39;], [&#39; &#39;], PChar(Value), vCSVLine);

      for i := 0 to vCSVLine.Count-1 do
      begin
        if i = vCSVLine.Count-1 then
         WriteLn(vFile, vCSVLine[i])
        else
         Write(vFile, vCSVLine[i] + &#39;;&#39;);
      end;
    finally
      vCSVLine.Free;
    end;
  finally
    CloseFile(vFile);
  end;
end;  
&lt;/pre&gt;&lt;br /&gt;
Agora que já temos duas classes concretas que implementam a exportação, vamos criar a factory responsável por instanciar as classes adequadas. &lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot; title=&quot;Factory com função de classe&quot;&gt;TExporterFactoryStrategy = class
  private
  public
    class function NewExporter(const ExporterType: TExporterType): IExporterStrategy;
  end;
  
implementation

{ TExporterFactoryStrategy }
class function TExporterFactoryStrategy.NewExporter(const ExporterType: TExporterType): IExporterStrategy;
begin
  case ExporterType of
    etText: Result := TTextExporterStrategy.Create;
    etCSV : Result := TCSVExporterStrategy.Create;
  else
    raise EStrategyNotImplemented.Create(ExporterType);
  end;
end;  

{ EStrategyNotImplemented }
constructor EStrategyNotImplemented.Create(AExporterType: TExporterType);
begin
  inherited CreateFmt(&#39;Strategy não implementado para o tipo &quot;%s&quot;&#39;,[GetEnumName(TypeInfo(TExporterType), Ord(AExporterType))]);
end;
&lt;/pre&gt;&lt;br /&gt;
Caso alguém peça a factory para instanciar um objecto para exportar para XML, uma exceção do tipo &lt;i&gt;EStrategyNotImplemented&lt;/i&gt; será lançada.&lt;br /&gt;
&lt;br /&gt;
Finalmente, vamos a classe &lt;i&gt;TExporterContext&lt;/i&gt;, que representa a classe de negócio que faria a exportação dos dados na vida real, onde teria suas queries, cálculos e etc. O mais legal é que essa classe tem um nível de acoplamento extremamente baixo com o método de exportação, ela depende apenas da interface.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;type
  TExporterContext = class
  private
    FExporterStrategy: IExporterStrategy;
  public
    constructor Create(const AExporterStrategyStrategy: IExporterStrategy);

    procedure MakeExport(const AOutputFile: String);
  end;

implementation

{ TExporterContext }

constructor TExporterContext.Create(const AExporterStrategyStrategy: IExporterStrategy);
begin
  FExporterStrategy := AExporterStrategyStrategy;
end;

procedure TExporterContext.MakeExport(const AOutputFile: String);
begin
  FExporterStrategy.FileName := AOutputFile;

  FExporterStrategy.ExportToFile(ClassName);
end;  
&lt;/pre&gt;&lt;br /&gt;
E não poderiam faltar os Testes, como sempre, utilizando o &lt;a href=&quot;http://dunit.sourceforge.net/&quot;&gt;DUnit&lt;/a&gt;. Se você ainda não é familiarizado com testes unitários, leia os posts: &lt;a href=&quot;http://fabriciodev.blogspot.com/2011/08/usando-dunit-para-implementar-testes.html&quot;&gt;Usando DUnit para implementar testes unitários&lt;/a&gt; e &lt;a href=&quot;http://fabriciodev.blogspot.com/2011/08/usando-dunit-para-implementar-testes_01.html&quot;&gt;Usando DUnit para implementar testes unitários - 2&lt;/a&gt; &lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot; title=&quot;Teste unitário para formato texto&quot;&gt;type
  TTestTextExporter = class(TTestCase)
  private
  published
    procedure DeveLancarExcecaoQuandoFileNameNaoForDefinido;
    procedure DeveExportarParaArquivoNoFormatoTexto;
  end;

implementation

{ TTestTextExporter }

procedure TTestTextExporter.DeveExportarParaArquivoNoFormatoTexto;
var
  vTextExporter: IExporterStrategy;
  vValue,
  vFileName,
  vLine: String;
  vTextFile: TextFile;
begin
  vFileName := ExtractFilePath(ParamStr(0)) + &#39;textexporter.txt&#39;;

  vValue := &#39;Valor exportado&#39;;

  vTextExporter := TTextExporterStrategy.Create;
  vTextExporter.FileName := vFileName;
  vTextExporter.ExportToFile(vValue);

  CheckTrue(FileExists(vFileName), &#39;Arquivo não foi gerado.&#39;);
  
  AssignFile(vTextFile, vFileName);
  try
    Reset(vTextFile);

    Readln(vTextFile, vLine);

    CheckEqualsString(vValue, vLine);
  finally
    CloseFile(vTextFile);
  end;

  DeleteFile(vFileName);
end;

procedure TTestTextExporter.DeveLancarExcecaoQuandoFileNameNaoForDefinido;
begin
  ExpectedException := EFileIsNotDefined;
  TTextExporterStrategy.Create.ExportToFile(&#39;&#39;);
end;

initialization
  RegisterTest(&#39;Text Exporter&#39;,  TTestTextExporter.Suite);
&lt;/pre&gt;&lt;br /&gt;
Agora vou fazer um teste unitário e de integração na classe de contexto (TExporterContext). O teste de integração é o primeiro - método ExportaComoTexto - onde a classe de contexto recebe uma instância para o formato &lt;i&gt;etText&lt;/i&gt; através da factory. &lt;i&gt;TExporterFactoryStrategy&lt;/i&gt;. &lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot; title=&quot;Teste da classe de contexto&quot;&gt;TTextExporterContext = class(TTestCase)
  private
  published
    procedure ExportaComoTexto;
    procedure DeveInvocarOStrategy;
  end;

implementation

{ TTextExporterContext }

procedure TTextExporterContext.ExportaComoTexto;
var
  vExporter: TExporterContext;
  vFileName,
  vLine: String;
  vTextFile: TextFile;
begin
  vFileName := ExtractFilePath(ParamStr(0)) + &#39;textexporter.txt&#39;;

  vExporter := TExporterContext.Create(TExporterFactoryStrategy.NewExporter(etText));
  vExporter.MakeExport(vFileName);

  CheckTrue(FileExists(vFileName), &#39;Arquivo não foi gerado.&#39;);
  
  AssignFile(vTextFile, vFileName);
  try
    Reset(vTextFile);

    Readln(vTextFile, vLine);

    CheckEqualsString(vExporter.ClassName, vLine);
  finally
    CloseFile(vTextFile);
  end;

  DeleteFile(vFileName);
end;  
&lt;/pre&gt;&lt;br /&gt;
Esse teste é necessário para ver o funcionamento como um todo, mais tem um ponto a mais de falha, que é a classe de exportação, pois, a mesma pode gerar erros - de I/O, por exemplo - que não indicam necessariamente que a classe de contexto está com problemas,portanto, para testar a classe de forma realmente unitária, precisamos ter controle sobre a estratégia de exportação,e para isso, utilizamos &lt;a href=&quot;http://xunitpatterns.com/Mock%20Object.html&quot;&gt;Mock Objects&lt;/a&gt;. Para delphi, temos as opções: &lt;a href=&quot;http://sourceforge.net/projects/pascalmock/&quot;&gt;Pascal Mock&lt;/a&gt;, &lt;a href=&quot;http://delphixtreme.com/wordpress/?p=14&quot;&gt;Simple Mock&lt;/a&gt; e &lt;a href=&quot;http://sourceforge.net/projects/ubmock/&quot;&gt;Ultra Basic MockObjects&lt;/a&gt;. Se alguém conhece mais algum, deixe um comentário. Eu optei por utilizar o Pascal Mock. &lt;br /&gt;
&lt;br /&gt;
Não vou entrar em detalhes sobre &lt;a href=&quot;http://martinfowler.com/articles/mocksArentStubs.html&quot;&gt;Mocks&lt;/a&gt; nesse artigo, isso fica para uma próxima, mais segue abaixo como ficou a classe Mock e o teste.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;type
  TMockExporterStrategy = class(TMock, IExporterStrategy)
  public
    procedure ExportToFile(const Value: String);
    function GetFileName: String;
    procedure SetFileName(const Value: String);
  end; 
  
implementation
{ TMockExporterStrategy }

procedure TMockExporterStrategy.ExportToFile(const Value: String);
begin 
  //Registra que o método foi chamado e com qual valor para o parâmetro
  AddCall(&#39;ExportToFile&#39;).WithParams([Value]);
end;

function TMockExporterStrategy.GetFileName: String;
begin
  //Não é utilizado no teste
  Result := EmptyStr;
end;

procedure TMockExporterStrategy.SetFileName(const Value: String);
begin
  //Registra que o método foi chamado e com qual valor para o parâmetro
  AddCall(&#39;SetFileName&#39;).WithParams([Value]);
end;
  
procedure TTextExporterContext.DeveInvocarOStrategy;
const
  FileName = &#39;C:\Exporter\filename.txt&#39;;
var
  vMock: TMockExporterStrategy;
  vContext: TExporterContext;
begin
  //Instância o Mock
  vMock := TMockExporterStrategy.Create;
  try
    //Indica que deve ser invocado o método SetFileName uma vez com o valor FileName definido na constante.
    vMock.Expects(&#39;SetFileName&#39;, 1).WithParams([FileName]);
 //Indica que deve ser invocado o método ExportToFile uma vez.
    vMock.Expects(&#39;ExportToFile&#39;, 1);

 //Instancia a classe de contexto passando o Mock como argumento.
    vContext := TExporterContext.Create(vMock);
    try
      vContext.MakeExport(FileName);
    finally
      vContext.Free;
    end;

 //O mock verifica se os métodos configurados como esperados foram realmente invocados e com a quantidade esperada.
    vMock.Verify(&#39;Não invocou o método &quot;SetFileName&quot;&#39;);
  finally
    vMock.Free;
  end;
end;
&lt;/pre&gt;&lt;br /&gt;
Com isso encerramos a séria sobre Strategy. Como de costume, o &lt;a href=&quot;https://bitbucket.org/fabriciocolombo/exemplos/src/330ffdf26d90/Strategy/&quot;&gt;código fonte&lt;/a&gt; desse artigo e dos anteriores está disponível na &lt;a href=&quot;https://bitbucket.org/fabriciocolombo/exemplos&quot;&gt;minha conta do bitbucket&lt;/a&gt;.</content><link rel='replies' type='application/atom+xml' href='http://fabriciodev.blogspot.com/feeds/2282192644378643878/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://fabriciodev.blogspot.com/2011/08/strategy-separando-os-comportamentos_06.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/2282192644378643878'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/2282192644378643878'/><link rel='alternate' type='text/html' href='http://fabriciodev.blogspot.com/2011/08/strategy-separando-os-comportamentos_06.html' title='Strategy - Separando os comportamentos - Parte Final'/><author><name>Fabricio Colombo</name><uri>http://www.blogger.com/profile/06951517260984102149</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCedF2z6z0D9d8Adr564w0ZJwcy2ckdFrC48QG9iQ9roQTh2R7yylksaD9ccou06b0HoZ-S_Did-aXDwGIUuaHVO6Aw398CK6KbnI4bEkKbiYC8M_8rp5_so6uPrqGX1A/s220/unnamed.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-911701488457280480.post-677563061605985252</id><published>2011-08-04T19:08:00.000-07:00</published><updated>2011-11-12T08:51:45.566-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Factory"/><category scheme="http://www.blogger.com/atom/ns#" term="Padrões de Projeto"/><category scheme="http://www.blogger.com/atom/ns#" term="Strategy"/><title type='text'>Strategy - Separando os comportamentos - Parte 1</title><content type='html'>O padrão de projeto &lt;a href=&quot;http://en.wikipedia.org/wiki/Strategy_pattern&quot;&gt;Strategy&lt;/a&gt; define uma família de algoritmos, encapsula cada um e os torna intercambiáveis, traduzindo, definimos uma interface, criamos várias implementações para essa interface, e podemos mudar o comportamento do objeto trocando a implementação utilizada. Podemos inclusive fazer isso em runtime.&lt;br /&gt;
&lt;br /&gt;
Vamos observar o diagrama abaixo.&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqLTJujX1s-aU-rz99Gl-amKOzz5iJ8bvEZPLfTVGh7j-Ue1PJJ19BLPcN3LyU6NQ1UYrwdqwBAuI8lTe-fQz3E4q3gz1zTWzMyIxFudxrai306n3vwfgU_-V-ahLbXQzIRIdL9lMnTJ7s/s1600/Strategy3.png&quot; rel=&quot;lightbox&quot; title=&quot;Diagrama representando o padrão&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;213&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqLTJujX1s-aU-rz99Gl-amKOzz5iJ8bvEZPLfTVGh7j-Ue1PJJ19BLPcN3LyU6NQ1UYrwdqwBAuI8lTe-fQz3E4q3gz1zTWzMyIxFudxrai306n3vwfgU_-V-ahLbXQzIRIdL9lMnTJ7s/s400/Strategy3.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A interface IExporterStrategy define o comportamento da estratégia, no caso, uma propriedade &lt;i&gt;FileName&lt;/i&gt; que define o nome do arquivo de destino e um método &lt;i&gt;ExportToFile&lt;/i&gt; que executa a exportação em si. No diagrama está definido três implementações para o estrategy: Text, XML e CSV, e uma classe TExporterContext que representa o contexto da aplicação no qual a rotina de exportação está inserida.&lt;br /&gt;
&lt;br /&gt;
É importante ressaltar o relacionamento entre a classe TExporterContext e o Strategy. A classe depende apenas da interface, desconhecendo qualquer implementação. Isso é um bom indicador para o nosso design, pois, estamos &lt;a href=&quot;http://www.arquiteturajava.com.br/livro/programe-voltado-a-interface-nao-a-implementacao.pdf&quot;&gt;programando para uma interface, não para uma implementação&lt;/a&gt; (Interface no sentido de abstração).&lt;br /&gt;
&lt;br /&gt;
Note também a classe TExporterStrategyFactory. Ela é uma &lt;a href=&quot;http://www.c-sharpcorner.com/UploadFile/mosessaur/simplefactorypattern03012006124722PM/simplefactorypattern.aspx&quot;&gt;Simple Factory&lt;/a&gt;, uma classe comum com um método de classe que retornará uma instância para a classe de contexto. Quando fazemos isso, estamos &lt;a href=&quot;http://martinfowler.com/bliki/InversionOfControl.html&quot;&gt;invertendo&lt;/a&gt; &lt;a href=&quot;http://www.arquiteturajava.com.br/livro/inversao-de-controle-cade-minha-chave-de-fenda.pdf&quot;&gt;o controle&lt;/a&gt; dos objetos, o contexto não tem controle sobre qual implementação será retornada pela Factory. Qualquer mudança no que diz respeito a instanciação, faremos apenas na Factory, por exemplo, queremos substituir o framework de manipulação de xml, então, criamos mais uma implementação do Strategy e modificamos a factory para retornar essa implementação.&lt;br /&gt;
&lt;br /&gt;
A nomenclatura das classes também é importante, pois, um dos objetivos dos patterns é criar uma linguagem comum, de modo que a comunicação seja facilitada. E de fato olhando para o diagrama há uma rápida identificação dos padrões adotados para resolver o problema.&lt;br /&gt;
&lt;br /&gt;
No próximo post vou mostrar como fica a implementação dessas classes em delphi.&lt;br /&gt;
&lt;br /&gt;
Até a próxima.</content><link rel='replies' type='application/atom+xml' href='http://fabriciodev.blogspot.com/feeds/677563061605985252/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://fabriciodev.blogspot.com/2011/08/strategy-separando-os-comportamentos.html#comment-form' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/677563061605985252'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/677563061605985252'/><link rel='alternate' type='text/html' href='http://fabriciodev.blogspot.com/2011/08/strategy-separando-os-comportamentos.html' title='Strategy - Separando os comportamentos - Parte 1'/><author><name>Fabricio Colombo</name><uri>http://www.blogger.com/profile/06951517260984102149</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCedF2z6z0D9d8Adr564w0ZJwcy2ckdFrC48QG9iQ9roQTh2R7yylksaD9ccou06b0HoZ-S_Did-aXDwGIUuaHVO6Aw398CK6KbnI4bEkKbiYC8M_8rp5_so6uPrqGX1A/s220/unnamed.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiqLTJujX1s-aU-rz99Gl-amKOzz5iJ8bvEZPLfTVGh7j-Ue1PJJ19BLPcN3LyU6NQ1UYrwdqwBAuI8lTe-fQz3E4q3gz1zTWzMyIxFudxrai306n3vwfgU_-V-ahLbXQzIRIdL9lMnTJ7s/s72-c/Strategy3.png" height="72" width="72"/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-911701488457280480.post-1530553430116915287</id><published>2011-08-03T18:48:00.000-07:00</published><updated>2011-08-06T12:06:15.657-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Padrões de Projeto"/><category scheme="http://www.blogger.com/atom/ns#" term="Singleton"/><title type='text'>Singleton em Delphi utilzando interfaces</title><content type='html'>Olá, dando sequencia ao &lt;a href=&quot;http://www.blogger.com/post-edit.g?blogID=911701488457280480&amp;amp;postID=1530553430116915287&quot;&gt;post anterior&lt;/a&gt; sobre Singleton, hoje irei mostrar uma implementação alternativa, e ao meu ver, mais elegante.&lt;br /&gt;
&lt;br /&gt;
Nessa abordagem, o estado e/ou comportamento exposto pelo singleton deve ser declarado em uma interface.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;type
  ISingleton = interface
  [&#39;{F5B00272-536A-4C30-AB19-54496B106C7C}&#39;]
    procedure FacaAlgo;
  end;
&lt;/pre&gt;&lt;br /&gt;
Após a interface, vamos criar uma classe que seja responsável por implementá-la. O detalhe importante é que a classe fique abaixo da seção implementation, isso garante que ninguém fora dessa unit terá acesso a classe, tornado impossível criar uma nova instância da mesma.&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;implementation

type
  TSingletonInterface = class(TInterfacedObject, ISingleton)
  public
    procedure FacaAlgo;
  end;

{ TSingletonInterface }

procedure TSingletonInterface.FacaAlgo;
begin
  if IsConsole then
    Writeln(ClassName, &#39; Fazendo algo&#39;)
  else
    ShowMessageFmt(&#39;%s Fazendo algo&#39;, [ClassName]);
end;
&lt;/pre&gt;&lt;br /&gt;
Agora precisamos de uma forma única de acessar uma instância dessa classe, para isso, vamos criar uma função e uma variável global privada para armazenar a instância. É importante que a função e variável fiquem, respectivamente, acima e abaixo da seção implementation, &quot;blindando&quot; o acesso a variável e a classe.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;function GetSingleton: ISingleton;

implementation

var
  _Singleton: ISingleton = nil;

function GetSingleton: ISingleton;
begin
  if (_Singleton = nil) then
    _Singleton := TSingletonInterface.Create;

  Result := _Singleton;
end;
&lt;/pre&gt;&lt;br /&gt;
Ao meu ver, essa é uma implementação melhor do que a do post anterior, pois o Singleton deixa mais claro sua intenção, seus métodos fazem exatamente o que está descrito, e por ser uma interface não existem os métodos Create e Free, que são públicos em TObject.&lt;br /&gt;
&lt;br /&gt;
O código completo do exemplo pode ser acessado &lt;a href=&quot;https://bitbucket.org/fabriciocolombo/exemplos/src/dce080cd41d9/Singleton/&quot;&gt;aqui&lt;/a&gt;.</content><link rel='replies' type='application/atom+xml' href='http://fabriciodev.blogspot.com/feeds/1530553430116915287/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://fabriciodev.blogspot.com/2011/08/singleton-em-delphi-utilzando.html#comment-form' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/1530553430116915287'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/1530553430116915287'/><link rel='alternate' type='text/html' href='http://fabriciodev.blogspot.com/2011/08/singleton-em-delphi-utilzando.html' title='Singleton em Delphi utilzando interfaces'/><author><name>Fabricio Colombo</name><uri>http://www.blogger.com/profile/06951517260984102149</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCedF2z6z0D9d8Adr564w0ZJwcy2ckdFrC48QG9iQ9roQTh2R7yylksaD9ccou06b0HoZ-S_Did-aXDwGIUuaHVO6Aw398CK6KbnI4bEkKbiYC8M_8rp5_so6uPrqGX1A/s220/unnamed.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-911701488457280480.post-4258230763620155112</id><published>2011-08-02T16:27:00.000-07:00</published><updated>2011-08-06T12:05:53.003-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Padrões de Projeto"/><category scheme="http://www.blogger.com/atom/ns#" term="Singleton"/><title type='text'>Singleton em Delphi</title><content type='html'>O &lt;a href=&quot;http://pt.wikipedia.org/wiki/Singleton&quot;&gt;Singleton&lt;/a&gt; é um padrão de projeto utilizado para garantir que apenas uma única instância de determinada classe esteja disponível em todo o projeto, ou seja, ele garante que o objeto será instanciado apenas uma vez e será acessivel de forma global.&lt;br /&gt;
&lt;br /&gt;
Isso é muito útil, por exemplo, quando lidamos com factory, pois a &lt;a href=&quot;http://pt.wikipedia.org/wiki/Abstract_Factory&quot;&gt;factory&lt;/a&gt; não precisa ser instanciada a todo momento. Outros exemplos são Pool de Conexões, Registry, Logs, ou recursos que sejam caros de instanciar a cada uso.&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Contudo, há sempre muita controvérsia em torno da utilização do pattern singleton, isto porque ele é frequentemente mau empregado na solução dos problemas, fazendo com que o mesmo se torne apenas uma &quot;variável global&quot; e isso pode indicar que você tem um design pobre. &lt;br /&gt;
&lt;br /&gt;
Há pelo menos duas formas diferentes em delphi de implementar este padrão. Primeiro vou mostrar como implementar utilizando uma classe comum, que possui um método estático - GetInstance() - que retorna a instância da classe.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;type
  TSingleton = class
  private
    FCanFree: Boolean;

    class procedure InternalFree;
  public
    procedure FacaAlgo;

    class function GetInstance: TSingleton;

    class function NewInstance: TObject; override;
    procedure FreeInstance; override;
  end;

implementation

//Variável para armazenar a instância do Singleton
var
  _Singleton: TSingleton = nil;

{ TSingleton }

//Lógica de negócio
procedure TSingleton.FacaAlgo;
begin
  if IsConsole then
    Writeln(ClassName, &#39; Fazendo algo&#39;)
  else
    ShowMessageFmt(&#39;%s Fazendo algo&#39;,[ClassName]);
end;

//Indica que o objeto pode ser destruído
class procedure TSingleton.InternalFree;
begin
  if Assigned(_Singleton) then
  begin
    _Singleton.FCanFree := True;
    _Singleton.Free;
  end;
end;

//Só libera a instância quando o método InternalFree é chamado
procedure TSingleton.FreeInstance;
begin
  if FCanFree then
  begin
    inherited;
  end;
end;

//Na verdade o create vai invocar o método NewInstance indiretamente
class function TSingleton.GetInstance: TSingleton;
begin
  Result := TSingleton.Create;
end;

//Instanciação Preguiçosa - Só instancia o objeto quando alguém precisar
class function TSingleton.NewInstance: TObject;
begin
   if (_Singleton = nil) then
     _Singleton := TSingleton(inherited NewInstance);

   Result := _Singleton;
end;

initialization

finalization
  TSingleton.InternalFree;
&lt;/pre&gt;&lt;br /&gt;
Essa abordagem é relativamente simples, mais traz consigo alguns problemas em relação a deixar o código claro. O singleton não respeita o &quot;contrato&quot; descrito por seu métodos, isto é, quando eu chamo o método create, ele não cria um novo objeto e quando eu invoco o método Free, ele não destroy o objeto. Isso pode causar uma certa confusão na utilização do mesmo.&lt;br /&gt;
&lt;br /&gt;
Vamos dar uma olhada em um código de teste para garantir que a instância é única.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;type
  TTestSingleton = class(TTestCase)
  private
  published
    procedure GetInstanceDeveRetornarUmaInstancia;
    procedure GetInstanceECreateDeveRetornarAMesmaInstancia;
    procedure FreeNaoPodeDestruirInstancia;
    procedure DestroyNaoPodeDestruirInstancia;
    procedure FreeInstanceNaoPodeDestruirInstancia;
  end;
  
{ TTestSingleton }
  
procedure TTestSingleton.DestroyNaoPodeDestruirInstancia;
var
  vInstance,
  vInstanceAfterFree: TSingleton;
begin
  vInstance := TSingleton.GetInstance;
  vInstance.Destroy; //Não tem efeito
  vInstanceAfterFree := TSingleton.GetInstance;

  CheckTrue(vInstance = vInstanceAfterFree);
end;

procedure TTestSingleton.FreeInstanceNaoPodeDestruirInstancia;
var
  vInstance,
  vInstanceAfterFree: TSingleton;
begin
  vInstance := TSingleton.GetInstance;
  vInstance.FreeInstance; //Não tem efeito
  vInstanceAfterFree := TSingleton.GetInstance;

  CheckTrue(vInstance = vInstanceAfterFree);
end;

procedure TTestSingleton.FreeNaoPodeDestruirInstancia;
var
  vInstance,
  vInstanceAfterFree: TSingleton;
begin
  vInstance := TSingleton.GetInstance;
  vInstance.Free; //Não tem efeito
  vInstanceAfterFree := TSingleton.GetInstance;

  CheckTrue(vInstance = vInstanceAfterFree);
end;

procedure TTestSingleton.GetInstanceDeveRetornarUmaInstancia;
var
  vInstance: TSingleton;
begin
  vInstance := TSingleton.GetInstance;
  CheckNotNull(vInstance, &#39;Retornou nil&#39;);
  CheckTrue(vInstance is TSingleton, &#39;Não é um TSingleton&#39;);
  vInstance.FacaAlgo;
end;

procedure TTestSingleton.GetInstanceECreateDeveRetornarAMesmaInstancia;
var
  vFromGetInstance,
  vFromCreate: TObject;
begin
  vFromGetInstance := TSingleton.GetInstance;
  vFromCreate := TSingleton.Create; //Retorna a mesma instancia

  CheckTrue(vFromGetInstance = vFromCreate);

  vFromCreate := TSingleton.NewInstance; //Retorna a mesma instancia
  CheckTrue(vFromGetInstance = vFromCreate);
end;  
&lt;/pre&gt;&lt;br /&gt;
No próximo post vou mostrar o segundo tipo de implementação, utilizando interfaces.&lt;br /&gt;
&lt;br /&gt;
Por hoje era isso, até a próxima e usem o Singleton com moderação.</content><link rel='replies' type='application/atom+xml' href='http://fabriciodev.blogspot.com/feeds/4258230763620155112/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://fabriciodev.blogspot.com/2011/08/singleton-em-delphi.html#comment-form' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/4258230763620155112'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/4258230763620155112'/><link rel='alternate' type='text/html' href='http://fabriciodev.blogspot.com/2011/08/singleton-em-delphi.html' title='Singleton em Delphi'/><author><name>Fabricio Colombo</name><uri>http://www.blogger.com/profile/06951517260984102149</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCedF2z6z0D9d8Adr564w0ZJwcy2ckdFrC48QG9iQ9roQTh2R7yylksaD9ccou06b0HoZ-S_Did-aXDwGIUuaHVO6Aw398CK6KbnI4bEkKbiYC8M_8rp5_so6uPrqGX1A/s220/unnamed.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-911701488457280480.post-6161033534602133717</id><published>2011-08-01T19:03:00.000-07:00</published><updated>2011-08-06T10:43:59.258-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="DUnit"/><category scheme="http://www.blogger.com/atom/ns#" term="TDD"/><category scheme="http://www.blogger.com/atom/ns#" term="teste unitários"/><title type='text'>Usando DUnit para implementar testes unitários - Parte 2</title><content type='html'>No último &lt;a href=&quot;http://fccolombo.blogspot.com/2011/08/usando-dunit-para-implementar-testes.html&quot;&gt;post&lt;/a&gt; fiz uma introdução sobre a criação de testes unitários com o &lt;a href=&quot;http://dunit.sourceforge.net/&quot;&gt;DUnit&lt;/a&gt;. Hoje, vou explorar mais alguns recursos desta poderosa ferramenta, continuando com o exemplo da &lt;a href=&quot;https://bitbucket.org/fabriciocolombo/exemplos/src/98955511d157/DUnit_Calculadora/&quot;&gt;Calculadora&lt;/a&gt;, para isso, a calculadora vai ganhar um método para fazer divisão. Lembram do ritual? Red - Green - Refactor! Vejam a classe de teste, garanta que o teste falhe e então faça-o passar. &lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;procedure TTestCalculadora.DivisaoDe6Por2DeveSer3;
var
 vCalculadora: TCalculadora;
begin
 vCalculadora := TCalculadora.Create;
 try
   CheckEquals(3, vCalculadora.Soma(6).DividePor(2).GetTotal, &#39;Divisão inválida&#39;);
 finally
   vCalculadora.Free;
 end;
end;
&lt;/pre&gt;Fail!&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;function TCalculadora.DividePor(const AValor: Double): TCalculadora;
begin
  FValor := FValor / AValor;
  Result := Self;
end;
&lt;/pre&gt;Success!&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
E o que acontece se eu tentar uma divisão por zero? &lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;procedure TTestCalculadora.DivisaoDe6PorZero;
var
 vCalculadora: TCalculadora;
begin
 vCalculadora := TCalculadora.Create;
 try
   vCalculadora.Dividir(6, 0);
 finally
   vCalculadora.Free;
 end;
end;
&lt;/pre&gt;Isso não parece bom. Rode o teste e veja que será lançada uma exceção do tipo EZeroDivide - se fosse um Integer lançaria uma EDivByZero - e o teste falhará.&lt;br /&gt;
&lt;br /&gt;
Para esse tipo de teste, o DUnit oferece um recurso bastante útil, o ExpectedException, onde declaro que estou esperando uma exceção de determinado tipo. Se a exceção não for lançada, o teste falhará. Então vamos alterar o código e agora o mesmo deve passar.&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;procedure TTestCalculadora.DivisaoDe6PorZero;
var
 vCalculadora: TCalculadora;
begin 
 ExpectedException := EZeroDivide; 
 vCalculadora := TCalculadora.Create;
 try
   vCalculadora.Dividir(6, 0);
 finally
   vCalculadora.Free;
 end;
end;
&lt;/pre&gt;&lt;br /&gt;
Esses testes nos trouxeram a tona um problema de design em nossa classe de teste, a duplicação, não estamos sendo &lt;a href=&quot;http://en.wikipedia.org/wiki/Don%27t_repeat_yourself&quot;&gt;DRY&lt;/a&gt;. Em cada teste implementado estamos instanciando e destruindo o objeto Calculadora. Vamos extrair isso para outros métodos.&lt;br /&gt;
&lt;br /&gt;
A classe TTestCase da qual estamos herdando possue dois métodos adequados para o que precisamos: SetUp e TearDown. O SetUp é onde preparamento o teste - instanciar a calculadora. O TearDown é onde limpamos a sujeira - destruir a calculadora. É importante ressaltar que esses métodos são disparados para cada teste da suíte.&lt;br /&gt;
&lt;br /&gt;
Refatorei a classe de teste, e ela ficou assim. Rode os testes e veja se continua tudo funcionando.&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;type
  TTestCalculadora = class(TTestCase)
  private
    FCalculadora: TCalculadora;
  protected
    procedure SetUp; override;
    procedure TearDown; override;
  published
    procedure SomaDe2Mais3DeveSer5;
    procedure DeveResetarOValor;

    procedure DivisaoDe6Por2DeveSer3;
    procedure DivisaoDe6PorZero;
  end;

implementation

uses SysUtils;

{ TTestCalculadora }

procedure TTestCalculadora.SetUp;
begin
  inherited;
  FCalculadora := TCalculadora.Create;
end;

procedure TTestCalculadora.TearDown;
begin
  FCalculadora.Free;
  inherited;
end;

procedure TTestCalculadora.DeveResetarOValor;
begin
  FCalculadora.Soma(1).Reset;
  CheckEquals(0, FCalculadora.GetTotal, &#39;Não resetou o valor&#39;);
end;

procedure TTestCalculadora.DivisaoDe6Por2DeveSer3;
begin
  CheckEquals(3, FCalculadora.Soma(6).DividePor(2).GetTotal, &#39;Divisão inválida&#39;);
end;

procedure TTestCalculadora.DivisaoDe6PorZero;
begin
  ExpectedException := EZeroDivide;
  FCalculadora.Soma(6).DividePor(0);
end;

procedure TTestCalculadora.SomaDe2Mais3DeveSer5;
begin
  CheckEquals(5, FCalculadora.Soma(2).Soma(3).GetTotal);
end;
&lt;/pre&gt;&lt;br /&gt;
Existem ainda varias outras opções de métodos de validação além do CheckEquals, alguns dos mais usados são&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;procedure CheckTrue(condition: Boolean; msg: string = &#39;&#39;); 
    procedure CheckFalse(condition: Boolean; msg: string = &#39;&#39;); 
    procedure CheckNotEquals(expected, actual: integer; msg: string = &#39;&#39;); 
    procedure CheckNotNull(obj: TObject; msg: string = &#39;&#39;); 
    procedure CheckNull(obj: TObject; msg: string = &#39;&#39;); 
    procedure Fail(msg: sTring; ErrorAddrs: Pointer = nil); 
&lt;/pre&gt;&lt;br /&gt;
O código fonte dos exemplos está disponível &lt;a href=&quot;https://bitbucket.org/fabriciocolombo/exemplos/src/98955511d157/DUnit_Calculadora/&quot;&gt;aqui&lt;/a&gt;. Até o próximo post, abraços e bons testes.</content><link rel='replies' type='application/atom+xml' href='http://fabriciodev.blogspot.com/feeds/6161033534602133717/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://fabriciodev.blogspot.com/2011/08/usando-dunit-para-implementar-testes_01.html#comment-form' title='3 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/6161033534602133717'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/6161033534602133717'/><link rel='alternate' type='text/html' href='http://fabriciodev.blogspot.com/2011/08/usando-dunit-para-implementar-testes_01.html' title='Usando DUnit para implementar testes unitários - Parte 2'/><author><name>Fabricio Colombo</name><uri>http://www.blogger.com/profile/06951517260984102149</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCedF2z6z0D9d8Adr564w0ZJwcy2ckdFrC48QG9iQ9roQTh2R7yylksaD9ccou06b0HoZ-S_Did-aXDwGIUuaHVO6Aw398CK6KbnI4bEkKbiYC8M_8rp5_so6uPrqGX1A/s220/unnamed.jpg'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-911701488457280480.post-8990302088378494697</id><published>2011-08-01T18:33:00.000-07:00</published><updated>2011-08-06T08:30:48.953-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="DUnit"/><category scheme="http://www.blogger.com/atom/ns#" term="TDD"/><category scheme="http://www.blogger.com/atom/ns#" term="teste unitários"/><title type='text'>Usando DUnit para implementar testes unitários</title><content type='html'>Esse é meu primeiro post, e vou começar abordando um assunto que ao meu ver é pouco difundido na comunidade Delphi, Testes Unitários, e para isso vou demonstrar como utilizar a ferramenta &lt;a href=&quot;http://dunit.sourceforge.net/&quot;&gt;DUnit&lt;/a&gt; para construção dos testes.&lt;br /&gt;
&lt;br /&gt;
Cada vez mais é primordial que o desenvolvedor invista parte de seu tempo na construção de testes, se for utilizando TDD, melhor ainda. Uma boa suíte de teste nos dá segurança e confiança no momento de fazer um refactoring ou a correção de um bug. Também melhora significativamente o design do nosso código, pois, para pode testar de forma realmente unitária, nossas classes precisam ter baixo acoplamento, boa coesão, serem realmente testáveis.&lt;br /&gt;
&lt;br /&gt;
&lt;a name=&#39;more&#39;&gt;&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
Vou criar um exemplo de calculadora inspirado no padrão &lt;a href=&quot;http://pt.wikipedia.org/wiki/Builder&quot;&gt;Builder&lt;/a&gt; seguindo os passos do TDD - Red, Green, Refactor. Primeiro vamos escrever a classe de teste, e está deverá falhar antes da implementação da calculadora em si. &lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;type
 TTestCalculadora = class(TTestCase)¹
 private
 published²
   procedure SomaDe2Mais3DeveSer5;  
 end;

implementation

{ TTestCalculadora }

procedure TTestCalculadora.SomaDe2Mais3DeveSer5;
var
 vCalculadora: TCalculadora;
begin
 vCalculadora := TCalculadora.Create;
 try
   CheckEquals(5, FCalculadora.Soma(2).Soma(3).GetTotal);
 finally
   vCalculadora.Free;
 end;
end;

initialization
  RegisterTest(&#39;Calculadora&#39;, TTestCalculadora.Suite);³
&lt;/pre&gt;¹A classe deve herdar de TTestCase, que faz parte do framework DUnit. ²Os métodos que implementam os testes devem ser declarados na seção published, para que possam ser lidos utilizando RTTI. ³A classe deve ser registrada.&lt;br /&gt;
&lt;br /&gt;
Vamos ver se o teste falha. Para os mais puristas, o código não compilar já é o suficiente para a fase Red, eu particularmente, gosto de fazer a implementação suficiente para compilar o código, de qualquer modo, é importante garantir que o teste falhe. Então vou criar a classe calculadora mais não vou implementar o método GetTotal e no método Soma apenas vou retornar a Calculadora para não obter um Access Violation. &lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;type
  TCalculadora = class
  private
  public
    function Soma(const AValor: Double): TCalculadora;
    function GetTotal: Double;
  end;

implementation

{ TCalculadora }

function TCalculadora.GetTotal: Double;
begin
end;

function TCalculadora.Soma(const AValor: Double): TCalculadora;
begin
  Result := Self;
end;
&lt;/pre&gt;Rodando o teste, o mesmo vai falhar, pois o método retorna um valor qualquer atribuído em tempo de execução. Veja na imagem abaixo.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKy9WkMeDWcN_sEWjBgFh-oCheAOlZfjtR6jfUweC-RKRDa09obsyYXXw9ZqzrFjXGayzQb-dtrJM17rJZnvSyEV6oVPqdBWfDCY5EpWyeWdUgISvmC0juN5-RI24c797aanjxPP5WuDvq/s1600/DUnitRed.jpg&quot; imageanchor=&quot;1&quot; rel=&quot;lightbox[dunit]&quot; title=&quot;Teste falhando&quot; style=&quot;margin-left:1em; margin-right:1em&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;310&quot; width=&quot;320&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKy9WkMeDWcN_sEWjBgFh-oCheAOlZfjtR6jfUweC-RKRDa09obsyYXXw9ZqzrFjXGayzQb-dtrJM17rJZnvSyEV6oVPqdBWfDCY5EpWyeWdUgISvmC0juN5-RI24c797aanjxPP5WuDvq/s320/DUnitRed.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Agora vamos implementar o método Soma e GetTotal e rodar o teste novamente.&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;type
  TCalculadora = class
  private
    FValor: Double;
  public
    function Soma(const AValor: Double): TCalculadora;
    function GetTotal: Double;
  end;
  
function TCalculadora.GetTotal: Double;
begin
  Result := FValor;
end;

function TCalculadora.Soma(const AValor: Double): TCalculadora;
begin
  FValor := FValor + AValor;
  Result := Self;
end;
&lt;/pre&gt;O mesmo deve passar, como na imagem a seguir.&lt;br /&gt;
&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDD0LhYour_ofFYaAHSAIpc0wkfgTAyIwtce5j6jhptgAORCH9ajDhuDCJogZnxR1PNmN-3RuVyg1pvWpShioNhyw7-wMrWbTaA1xolRvxiu61jn21rInUpFwMfU9HjP-M14RS3N9Gw8w-/s1600/DUnitGreen.jpg&quot; rel=&quot;lightbox[dunit]&quot; title=&quot;Teste passando&quot; imageanchor=&quot;1&quot; style=&quot;margin-left:1em; margin-right:1em&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; width=&quot;319&quot; src=&quot;https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDD0LhYour_ofFYaAHSAIpc0wkfgTAyIwtce5j6jhptgAORCH9ajDhuDCJogZnxR1PNmN-3RuVyg1pvWpShioNhyw7-wMrWbTaA1xolRvxiu61jn21rInUpFwMfU9HjP-M14RS3N9Gw8w-/s320/DUnitGreen.jpg&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;
Estamos indo bem, vamos escrever mais um teste, vamos criar um método para resetar o valor. Aqui está o nosso teste.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;procedure TTestCalculadora.DeveResetarOValor;
var
 vCalculadora: TCalculadora;
begin
 vCalculadora := TCalculadora.Create;
 try
  vCalculadora.Reset;
  CheckEquals(0, vCalculadora.GetTotal, &#39;Não resetou o valor&#39;);
 finally
   vCalculadora.Free;
 end;
end;
&lt;/pre&gt;&lt;br /&gt;
Crie o método Reset na classe calculadora, mais não implemente.&lt;br /&gt;
&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;function TCalculadora.Reset: TCalculadora;
begin
end;
&lt;/pre&gt;&lt;br /&gt;
Agora rode o teste e você pode ver que... o teste passa. Mesmo sem implementação, ele passa. Por isso é tão importante garantir que o teste falhe antes de implementar, só assim ele tem valor. Um teste que passa antes mesmo de implementar não testa nada, não agrega valor algum. Vamos corrigir isso de modo que o teste falhe.&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;procedure TTestCalculadora.DeveResetarOValor;
var
 vCalculadora: TCalculadora;
begin
 vCalculadora := TCalculadora.Create;
 try
  vCalculadora.Soma(1).Reset;
  CheckEquals(0, vCalculadora.GetTotal, &#39;Não resetou o valor&#39;);
 finally
   vCalculadora.Free;
 end;
end;
&lt;/pre&gt;&lt;br /&gt;
Rode o teste e veja que o mesmo vai falhar. Feito isso vamos implementar o método Reset adequadamente para que o teste passe.&lt;br /&gt;
&lt;pre class=&quot;brush: delphi&quot;&gt;function TCalculadora.Reset: TCalculadora;
begin
  //Evitando número mágicos
  FValor := ZeroValue;
  Result := Self;
end;
&lt;/pre&gt;&lt;br /&gt;
Ainda há vários recursos do DUnit a serem explorados mais vou deixar isso para um próximo post, onde mostrarei também como testar exceções conhecidas. &lt;br /&gt;
&lt;br /&gt;
Não deixem de postar sobre dúvidas ou sugestões e escrevam testes. ;D&lt;br /&gt;
&lt;br /&gt;
Abraços.</content><link rel='replies' type='application/atom+xml' href='http://fabriciodev.blogspot.com/feeds/8990302088378494697/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://fabriciodev.blogspot.com/2011/08/usando-dunit-para-implementar-testes.html#comment-form' title='2 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/8990302088378494697'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/911701488457280480/posts/default/8990302088378494697'/><link rel='alternate' type='text/html' href='http://fabriciodev.blogspot.com/2011/08/usando-dunit-para-implementar-testes.html' title='Usando DUnit para implementar testes unitários'/><author><name>Fabricio Colombo</name><uri>http://www.blogger.com/profile/06951517260984102149</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjCedF2z6z0D9d8Adr564w0ZJwcy2ckdFrC48QG9iQ9roQTh2R7yylksaD9ccou06b0HoZ-S_Did-aXDwGIUuaHVO6Aw398CK6KbnI4bEkKbiYC8M_8rp5_so6uPrqGX1A/s220/unnamed.jpg'/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKy9WkMeDWcN_sEWjBgFh-oCheAOlZfjtR6jfUweC-RKRDa09obsyYXXw9ZqzrFjXGayzQb-dtrJM17rJZnvSyEV6oVPqdBWfDCY5EpWyeWdUgISvmC0juN5-RI24c797aanjxPP5WuDvq/s72-c/DUnitRed.jpg" height="72" width="72"/><thr:total>2</thr:total></entry></feed>