<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/rss2portuguesefull.xsl" type="text/xsl" media="screen"?><?xml-stylesheet href="http://feeds.feedburner.com/~d/styles/itemcontent.css" type="text/css" media="screen"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>TechTips</title>
	
	<link>http://www.techtips.com.br</link>
	<description>Dicas de Tecnologia</description>
	<pubDate>Tue, 04 Nov 2008 18:51:26 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.1</generator>
	<language>en</language>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://www.techtips.com.br/feed" type="application/rss+xml" /><feedburner:feedFlare href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Fwww.techtips.com.br%2Ffeed" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Fwww.techtips.com.br%2Ffeed" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://feeds.my.aol.com/add.jsp?url=http%3A%2F%2Fwww.techtips.com.br%2Ffeed" src="http://o.aolcdn.com/favorites.my.aol.com/webmaster/ffclient/webroot/locale/en-US/images/myAOLButtonSmall.gif">Subscribe with My AOL</feedburner:feedFlare><feedburner:feedFlare href="http://www.rojo.com/add-subscription?resource=http%3A%2F%2Fwww.techtips.com.br%2Ffeed" src="http://blog.rojo.com/RojoWideRed.gif">Subscribe with Rojo</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://www.techtips.com.br/feed" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Fwww.techtips.com.br%2Ffeed" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Fwww.techtips.com.br%2Ffeed" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Fwww.techtips.com.br%2Ffeed" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><item>
		<title>Modularização de Aplicativos – Single Package</title>
		<link>http://feeds.feedburner.com/~r/techtipsbr/~3/442385520/</link>
		<comments>http://www.techtips.com.br/programacao/modularizao-de-aplicativos-single-package/#comments</comments>
		<pubDate>Tue, 04 Nov 2008 18:42:50 +0000</pubDate>
		<dc:creator>Wanderson</dc:creator>
		
		<category><![CDATA[Delphi]]></category>

		<category><![CDATA[Programação]]></category>

		<category><![CDATA[Práticas]]></category>

		<guid isPermaLink="false">http://www.techtips.com.br/programacao/modularizao-de-aplicativos-single-package/</guid>
		<description><![CDATA[Quem desenvolve aplicativos modularizados, pode já ter se deparado com uma desvantagem comum quando se trata de distribuir pacotes de runtime: como controlar quais packages distribuir junto com o aplicativo/módulos e suas versões e facilitar suas atualizações?
Normalmente quando compilamos um aplicativo com a opção “Build with runtime packages” marcada, no mínimo teremos que redistribuir os [...]]]></description>
			<content:encoded><![CDATA[<p>Quem desenvolve aplicativos modularizados, pode já ter se deparado com uma desvantagem comum quando se trata de distribuir pacotes de runtime: como controlar quais packages distribuir junto com o aplicativo/módulos e suas versões e facilitar suas atualizações?</p>
<p>Normalmente quando compilamos um aplicativo com a opção “Build with runtime packages” marcada, no mínimo teremos que redistribuir os pacotes rtlxx.bpl e vclxx.bpl (onde o “xx” equivale à versão do Delphi, pelo menos até o Delphi 7), mais os pacotes referenciados pelas units da vcl e/ou de terceiros.</p>
<p>Agora imagine um projeto grande, onde temos vários componentes de terceiros empregados. Quantos arquivos extras se tornariam dependências para o aplicativo?</p>
<p>Procurando uma maneira simples para minimizar o número de arquivos a serem distribuídos em conjunto com um aplicativo que use runtime packages, me deparo com o excelente tutorial de <a href="http://www.saxon.co.uk/SinglePkg/">Keith Johnson</a>, ao qual não posso acrescentar muita coisa, por já ser muito completo e didático. Contento-me a simplificá-lo e torná-lo útil para a realidade de muitos aqui.</p>
<h3>Direto ao ponto</h3>
<p><a href="http://www.techtips.com.br/wp-content/uploads/2008/11/clip-image001.gif"><img style="0px" src="http://www.techtips.com.br/wp-content/uploads/2008/11/clip-image001-thumb.gif" border="0" alt="clip_image001" width="379" height="180" /></a></p>
<p>Figura 1 – Aplicativo com pacotes dinâmicos de forma convencional.</p>
<p><a href="http://www.techtips.com.br/wp-content/uploads/2008/11/clip-image002.gif"><img style="0px" src="http://www.techtips.com.br/wp-content/uploads/2008/11/clip-image002-thumb.gif" border="0" alt="clip_image002" width="379" height="144" /></a></p>
<p>Figura 2 – Aplicativo com pacotes dinâmicos carregando de um único pacote.</p>
<p>Abra o Delphi, crie um novo aplicativo e salve o projeto. Adicione os componentes necessários de forma natural, como se fosse um projeto comum e salve.</p>
<p>Agora você pode fechar seu projeto e criar um novo package, ou criá-lo no mesmo grupo de projetos. Para simplificar, vou usar a segunda opção. Crie uma Unit vazia dentro deste novo package.</p>
<p><a href="http://www.techtips.com.br/wp-content/uploads/2008/11/clip-image0016.gif"><img src="http://www.techtips.com.br/wp-content/uploads/2008/11/clip-image0016-thumb.gif" border="0" alt="clip_image001[6]" width="295" height="337" /></a></p>
<p>Você deverá percorrer TODOS os forms do seu projeto, vasculhando as cláusulas Uses para que todas as units referenciadas sejam adicionadas àquela unit do nosso pacote. Nosso objetivo será fazer com que o pacote importe todas essas units implicitamente para dentro dele, para que o executável tenha apenas ele como dependência. Para isso vá até Project -&gt; Options e escolha a opção “Directories/Conditionals”, altere o “Output directory” e o “DCP directory” para uma pasta onde estará seu executável (o “DCP directory” é necessário na hora da compilação do executável, pois ele vai procurar pelo arquivo .dcp do pacote, mas em tempo de execução, ele só precisará do arquivo .bpl), ou onde ele tenha acesso pelo path do Windows.</p>
<p><a href="http://www.techtips.com.br/wp-content/uploads/2008/11/clip-image003.jpg"><img style="0px" src="http://www.techtips.com.br/wp-content/uploads/2008/11/clip-image003-thumb.jpg" border="0" alt="clip_image003" width="515" height="349" /></a></p>
<p>É preferível deixar junto ao executável como numa pasta “bin” do seu projeto para facilitar a localização e distribuição, evitando um “bpl hell”. Clique em Ok e vá até aquela unit que você criou dentro do pacote. Adicione uma cláusula Uses a ela e coloque todas as units referenciadas pelo seu aplicativo.</p>
<p><a href="http://www.techtips.com.br/wp-content/uploads/2008/11/clip-image005.jpg"><img style="0px" src="http://www.techtips.com.br/wp-content/uploads/2008/11/clip-image005-thumb.jpg" border="0" alt="clip_image005" width="531" height="186" /></a></p>
<p>No diretório de saída que você acabou de configurar, coloque uma cópia da SysInit.dcu, que se encontra em $(BDS)\lib (ex: C:\Arquivos de programas\CodeGear\RAD Studio\5.0\lib). Esta unit faz-se necessária, pois se você tentar compilar seu projeto sem ela, vai disparar uma exceção, informando que não foi possível encontrar SysInit.dcu (lembre-se: o search path que você configurou sobrepõe o default do Delphi, daí ele não achar). Mesmo assim, esta unit não deve ser adicionada na sessão uses da unit do pacote, deverá apenas permanecer lá na pasta de destino. Vá até a sessão “requires” do seu pacote lá no Project manager e elimine TODAS as referências a outros packages, deixando-a vazia.</p>
<p>Agora compile seu pacote. Irá aparecer uma mensagem, dizendo que você deve incluir os packages da lista para manter compatibilidade com outros pacotes já instalados.</p>
<p><a href="http://www.techtips.com.br/wp-content/uploads/2008/11/clip-image006.gif"><img style="0px" src="http://www.techtips.com.br/wp-content/uploads/2008/11/clip-image006-thumb.gif" border="0" alt="clip_image006" width="389" height="305" /></a></p>
<p>É agora que vem o segredo: Escolha “Cancel” para que as units referenciadas sejam importadas para dentro de nosso pacote, e não as referências aos seus respectivos packages. Outro diálogo aparecerá com a mensagem: “If these changes are not applied, errors may occur when the package is loaded. Cancel changes?”.</p>
<p><a href="http://www.techtips.com.br/wp-content/uploads/2008/11/clip-image008.jpg"><img style="0px" src="http://www.techtips.com.br/wp-content/uploads/2008/11/clip-image008-thumb.jpg" border="0" alt="clip_image008" width="522" height="113" /></a></p>
<p>Escolha “Yes” agora. Toda vez que esse pacote for recompilado você deverá seguir estes passos.</p>
<p><a href="http://www.techtips.com.br/wp-content/uploads/2008/11/clip-image010.jpg"><img style="0px" src="http://www.techtips.com.br/wp-content/uploads/2008/11/clip-image010-thumb.jpg" border="0" alt="clip_image010" width="526" height="408" /></a></p>
<p>Se você verificar o resultado, poderá comprovar um package de até vários megabytes na pasta de destino (em um projeto que temos por aqui, está em torno de 13MB). Então, acabou? Ainda não, só mais uns ajustes no executável.</p>
<p>Considerando que você seguiu meu conselho e criou uma pasta só para os binários (“bin”, onde estarão .exe, .dcp, .bpl), selecione o projeto do executável agora, vá até Project -&gt; Options e escolha a opção “Directories/Conditionals”, lá em “Search path”, coloque o caminho da pasta Bin do seu projeto e faça o mesmo para o “Output directory”.</p>
<p><a href="http://www.techtips.com.br/wp-content/uploads/2008/11/clip-image012.jpg"><img style="0px" src="http://www.techtips.com.br/wp-content/uploads/2008/11/clip-image012-thumb.jpg" border="0" alt="clip_image012" width="554" height="349" /></a></p>
<p>Ainda nesta tela, escolha a opção “Packages”, marque a opção “Build with runtime pakages” e no Edit, limpe tudo, para adicionar apenas o nome do seu pacote.</p>
<p><a href="http://www.techtips.com.br/wp-content/uploads/2008/11/clip-image014.jpg"><img style="0px" src="http://www.techtips.com.br/wp-content/uploads/2008/11/clip-image014-thumb.jpg" border="0" alt="clip_image014" width="555" height="410" /></a></p>
<p>Clique em Ok e dê um build no seu aplicativo. Com isso, você já poderá notar uma redução de até 90% no tamanho do executável.</p>
<p><a href="http://www.techtips.com.br/wp-content/uploads/2008/11/clip-image015.gif"><img style="0px" src="http://www.techtips.com.br/wp-content/uploads/2008/11/clip-image015-thumb.gif" border="0" alt="clip_image015" width="552" height="143" /></a></p>
<p>Como já dito antes, para a distribuição do nosso aplicativo teste, apenas os 2 arquivos acima marcados serão necessários.</p>
<h3>Conclusão</h3>
<p>Quais as vantagens que podemos tirar deste método? Teremos todas as vantagens de se utilizar pacotes dinâmicos em um aplicativo, como velocidade na compilação (lembre-se que na maioria das vezes, você compilará apenas o código associado diretamente ao seu aplicativo, pois o código dos componentes já está embutido no pacote), executáveis e dlls muito menores (muito mais simples e rápido para atualizar seu aplicativo junto aos clientes) e maior facilidade para implementação de plugins, seja com dlls ou bpls. Se você colocar regras de negócio em um pacote ou fizer uso de rotinas muito sigilosas, poderá distribuir apenas os bpls do pacote livremente entre os desenvolvedores do projeto sem medo, pois estará fazendo uso do encapsulamento de código a seu favor.</p>
<p>E as desvantagens? Se você considerar todos os benefícios desta abordagem, o fato de ter que atualizar um pacote de 13MB (se compactar pode cair para 4MB ou 5MB) toda vez que mudar algum componente não pesará tão contra assim.</p>
<p>Este exemplo criou um único pacote com todas as units utilizadas pelo aplicativo, mas se você preferir poderá criar 2, 3 ou quantos pacotes precisar, separando-os por categoria, como pacotes de componentes visuais, acesso a dados, regras de negócio ou outra categoria que for necessária para seu projeto.</p>
<p>Este é o meu primeiro post, e espero que seja útil para quem precisar aplicar tais conceitos.</p>
<p><center>&copy; <a href="">TechTips</a></center></p>]]></content:encoded>
			<wfw:commentRss>http://www.techtips.com.br/programacao/modularizao-de-aplicativos-single-package/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.techtips.com.br/programacao/modularizao-de-aplicativos-single-package/</feedburner:origLink></item>
		<item>
		<title>Delphi 2009 Disponível para Download</title>
		<link>http://feeds.feedburner.com/~r/techtipsbr/~3/388175472/</link>
		<comments>http://www.techtips.com.br/semcategoria/delphi-2009-disponivel-para-download/#comments</comments>
		<pubDate>Wed, 10 Sep 2008 01:11:41 +0000</pubDate>
		<dc:creator>Leonel Togniolli</dc:creator>
		
		<category><![CDATA[Sem Categoria]]></category>

		<guid isPermaLink="false">http://www.techtips.com.br/semcategoria/delphi-2009-disponivel-para-download/</guid>
		<description><![CDATA[A versão trial do Delphi 2009 já está disponível para download. Não deixe de experimentar a nova versão.
&#169; TechTips]]></description>
			<content:encoded><![CDATA[<p>A versão trial do Delphi 2009 já está disponível para <a href="http://cc.codegear.com/free/delphi">download</a>. Não deixe de experimentar a nova versão.</p>
<p><center>&copy; <a href="http://www.techtips.com.br">TechTips</a></center></p>]]></content:encoded>
			<wfw:commentRss>http://www.techtips.com.br/semcategoria/delphi-2009-disponivel-para-download/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.techtips.com.br/semcategoria/delphi-2009-disponivel-para-download/</feedburner:origLink></item>
		<item>
		<title>Google Chrome – O Browser do Google</title>
		<link>http://feeds.feedburner.com/~r/techtipsbr/~3/380660501/</link>
		<comments>http://www.techtips.com.br/web/google-chrome-o-browser-do-google/#comments</comments>
		<pubDate>Mon, 01 Sep 2008 18:09:05 +0000</pubDate>
		<dc:creator>Leonel Togniolli</dc:creator>
		
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://www.techtips.com.br/web/google-chrome-o-browser-do-google/</guid>
		<description><![CDATA[Aparentemente o Google esteve trabalhando em segredo em um novo browser, chamado Google Chrome. Não, o link ainda não funciona, e não foi anunciado oficialmente. Mas algumas pessoas receberam uma história em quadrinhos, desenhada por Scott McCloud, um cartunista da DC Comics. A história tem os funcionários do Google como personagens e mostra os recursos [...]]]></description>
			<content:encoded><![CDATA[<p>Aparentemente o Google esteve trabalhando em segredo em um novo browser, chamado <a href="http://www.google.com/chrome">Google Chrome</a>. Não, o link ainda não funciona, e não foi anunciado oficialmente. Mas algumas pessoas receberam uma <a href="http://blogoscoped.com.nyud.net/google-chrome/">história em quadrinhos</a>, desenhada por <a href="http://en.wikipedia.org/wiki/Scott_McCloud">Scott McCloud</a>, um cartunista da DC Comics. A história tem os funcionários do Google como personagens e mostra os recursos do novo browser, dos quais eu destacaria:</p>
<ul>
<li>Completamente nova engine de JavaScript, chama V8, prometendo performance extremamente superior às existentes.</li>
<li>Abas isoladas em processos separados, com a finalidade de melhorar a estabilidade e segurança.</li>
<li>Modelo de segurança onde páginas rodam em uma sandbox especial, sem contato com nada. O ponto fraco ainda são os plugins.</li>
<li>Renderização de HTML feita pelo <a href="http://webkit.org/">WebKit</a>.</li>
<li><a href="http://gears.google.com/">Google Gears</a> integrado</li>
<li>Várias pequenas melhorias técnicas em relação aos browsers atuais.</li>
</ul>
<p>O projeto é prometido para ser completamente open source. Acho interessante a engine de JavaScript, em particular, por não ser acoplada ao browser e plugável em outros projetos.</p>
<p>Ainda é extremamente cedo para tirar qualquer tipo de conclusão, principalmente apenas a partir de uma história em quadrinhos, mas tenho a impressão que é um projeto que vale a pena ficar de olho.</p>
<p><center>&copy; <a href="http://www.techtips.com.br">TechTips</a></center></p>]]></content:encoded>
			<wfw:commentRss>http://www.techtips.com.br/web/google-chrome-o-browser-do-google/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.techtips.com.br/web/google-chrome-o-browser-do-google/</feedburner:origLink></item>
		<item>
		<title>Anonymous Methods e Closures no Delphi 2009</title>
		<link>http://feeds.feedburner.com/~r/techtipsbr/~3/377736577/</link>
		<comments>http://www.techtips.com.br/programacao/delphi/linguagem-delphi/anonymous-methods-e-closures-no-delphi-2009/#comments</comments>
		<pubDate>Fri, 29 Aug 2008 03:53:39 +0000</pubDate>
		<dc:creator>Leonel Togniolli</dc:creator>
		
		<category><![CDATA[Linguagem Delphi]]></category>

		<guid isPermaLink="false">http://www.techtips.com.br/programacao/delphi/linguagem-delphi/anonymous-methods-e-closures-no-delphi-2009/</guid>
		<description><![CDATA[Já conhecemos a sintaxe dos anonymous methods do Delphi 2009. A parte interessante deste novo recurso é que eles são closures.
Closure é a união do código com o seu escopo. Isso quer dizer que o novo método tem acesso às variáveis locais do método que o criou, mesmo depois que ele terminou. Vamos ver como [...]]]></description>
			<content:encoded><![CDATA[<p>Já conhecemos a sintaxe dos <a href="http://www.techtips.com.br/programacao/delphi/linguagem-delphi/anonymous-methods-no-delphi-2009/">anonymous methods</a> do Delphi 2009. A parte interessante deste novo recurso é que eles são <a href="http://en.wikipedia.org/wiki/Closure_(computer_science)">closures</a>.</p>
<p>Closure é a união do código com o seu escopo. Isso quer dizer que o novo método tem acesso às variáveis locais do método que o criou, mesmo depois que ele terminou. Vamos ver como isso funciona com um exemplo:</p>
<pre>type
  TContador = reference to function: Integer;

function CriaContador(Inicial, Final: Integer): TContador;
var
  i: Integer;
begin
  i := Inicial;
  Result := function: Integer
  begin
    Result := i;
    Inc(i);
    if i &gt; Final then
      i := Inicial;
  end;
end;

var
  Contador: TContador;
  i: Integer;
begin
  Contador := CriaContador(5, 12);
  for i := 0 to 20 do
    WriteLn(Contador);
end.</pre>
<p>Antes de ver a listagem da saída do programa, Vamos entender o código. TContador é um tipo que representa uma referência a uma função que retorna um número. Neste caso, vai retornar uma sequência de números, um número novo cada vez que for chamada. CriaContador é uma função que retorna um método desse tipo, recebendo os valores inicial e final que a sequência vai ter. Repare que o corpo de CriaContador tem apenas duas linhas de código que serão executadas quando ela for chamada: ela inicializa o contador, e atribui um novo método para o resultado.</p>
<p>No corpo do programa criamos um novo contador na faixa 5 até 12, e chamamos essa função 21 vezes, escrevendo o resultado no console.  Em cada chamada da função, ela retorna o valor atual de i, o incrementa, e caso tenha passado do valor final, volta ao primeiro.</p>
<p>Quais serão os 21 números escritos no console?</p>
<pre>5
6
7
8
9
10
11
12
5
6
7
8
9
10
11
12
5
6
7
8
9</pre>
<p>Ou seja, o programa funciona exatamente como descrevi.</p>
<p>Cada instância do método captura o escopo daquele momento. Se criarmos dois contadores:</p>
<pre>var
  Contador, Contador2: TContador;
  i: Integer;
begin
  Contador := CriaContador(5, 8);
  Contador2 := CriaContador(1, 3);
  for i := 0 to 5 do
    WriteLn(Contador,':',Contador2);
end.</pre>
<p>podemos ver que eles funcionam de forma completamente independente:</p>
<pre>5:1
6:2
7:3
8:1
5:2
6:3</pre>
<p>Essa é uma nova técnica possível no Delphi 2009. Para implementar o equivalente sem este recurso, seria necessário criar classes para o contador, construir instâncias e liberá-las. Ou seja, muito mais código e complicação.</p>
<p>O Craig Stuntz <a href="http://blogs.teamb.com/craigstuntz/2008/08/28/37831">escreveu um exemplo</a> muito interessante utilizando esse método pra implementar o <a href="http://pt.wikipedia.org/wiki/Crivo_de_Erat%C3%B3stenes">Crivo de Eratóstenes</a>. Ele entrou no assunto da técnica de <a href="http://en.wikipedia.org/wiki/Currying">currying</a>, que vai ficar para o próximo artigo.</p>
<p><center>&copy; <a href="http://www.techtips.com.br">TechTips</a></center></p>]]></content:encoded>
			<wfw:commentRss>http://www.techtips.com.br/programacao/delphi/linguagem-delphi/anonymous-methods-e-closures-no-delphi-2009/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.techtips.com.br/programacao/delphi/linguagem-delphi/anonymous-methods-e-closures-no-delphi-2009/</feedburner:origLink></item>
		<item>
		<title>Anonymous Methods no Delphi 2009</title>
		<link>http://feeds.feedburner.com/~r/techtipsbr/~3/377353215/</link>
		<comments>http://www.techtips.com.br/programacao/delphi/linguagem-delphi/anonymous-methods-no-delphi-2009/#comments</comments>
		<pubDate>Thu, 28 Aug 2008 18:27:09 +0000</pubDate>
		<dc:creator>Leonel Togniolli</dc:creator>
		
		<category><![CDATA[Linguagem Delphi]]></category>

		<guid isPermaLink="false">http://www.techtips.com.br/programacao/delphi/linguagem-delphi/anonymous-methods-no-delphi-2009/</guid>
		<description><![CDATA[Um dos novos recursos no Delphi 2009 é anonymous methods. É também chamado de “referências a métodos”, pois a declaração de um tipo procedural é feita com a sintaxe “reference to function/procedure”:
type
  TComparaString = reference to function(const S1, S2: string): Integer;
Esse tipo pode ser usado como qualquer outro tipo procedural:
procedure TLista.Ordena(Compara: TComparaString);
var
  i, [...]]]></description>
			<content:encoded><![CDATA[<p>Um dos novos recursos no Delphi 2009 é anonymous methods. É também chamado de “referências a métodos”, pois a declaração de um <a href="http://www.techtips.com.br/programacao/delphi/linguagem-delphi/guardando-mtodos-funces-e-procedimentos-em-variveis-com-tipos-procedurais/">tipo procedural</a> é feita com a sintaxe “reference to function/procedure”:</p>
<pre>type
  TComparaString = reference to function(const S1, S2: string): Integer;</pre>
<p>Esse tipo pode ser usado como qualquer outro tipo procedural:</p>
<pre>procedure TLista.Ordena(Compara: TComparaString);
var
  i, j: Integer;
begin
  for i := 0 to FItems.Count - 2 do
    for j := FItems.Count - 1 downto i + 1 do
      if Compara(FItems[j], FItems[i]) &lt; 0 then
         Troca(i, j);
end;</pre>
<p>(Perdoem-me o <a href="http://en.wikipedia.org/wiki/Bubble_sort">Bubble Sort</a>)</p>
<p>Não precisamos mais declarar um método separadamente para cada forma diferente de ordenação que for necessária. O código abaixo ordena uma lista alfabeticamente, depois de forma inversa, e finalmente de acordo com o tamanho da string:</p>
<pre>  Lista := TLista.Create;
  try
    Lista.Adiciona('Um');
    Lista.Adiciona('Dois');
    Lista.Adiciona('Tres');
    Lista.Adiciona('Quatro');
    Lista.Adiciona('Cinco');
    Lista.Ordena(function(const S1, S2: string): Integer
                 begin
                   Result := CompareStr(S1, S2);
                 end);
    WriteLn(Lista.Texto);
    Lista.Ordena(function(const S1, S2: string): Integer
                 begin
                   Result := CompareStr(S2, S1);
                 end);
    WriteLn(Lista.Texto);
    Lista.Ordena(function(const S1, S2: string): Integer
                 begin
                   Result := Length(S1) - Length(S2);
                   if Result = 0 then
                     Result := CompareStr(S1, S2);
                 end);
    WriteLn(Lista.Texto);
  finally
    Lista.Free;
  end;</pre>
<p>A resultado do programa é:</p>
<pre>Cinco
Dois
Quatro
Tres
Um

Um
Tres
Quatro
Dois
Cinco

Um
Dois
Tres
Cinco
Quatro</pre>
<p>Até aí, o recurso não é nada demais – permite economizar algumas linhas em troca de uma sintaxe discutivelmente mais confusa. Ele fica realmente interessante quando se nota que é, de fato, uma <a href="http://en.wikipedia.org/wiki/Closure_(computer_science)">Closure</a>, que exploraremos no próximo artigo.</p>
<p><center>&copy; <a href="http://www.techtips.com.br">TechTips</a></center></p>]]></content:encoded>
			<wfw:commentRss>http://www.techtips.com.br/programacao/delphi/linguagem-delphi/anonymous-methods-no-delphi-2009/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.techtips.com.br/programacao/delphi/linguagem-delphi/anonymous-methods-no-delphi-2009/</feedburner:origLink></item>
		<item>
		<title>Beyond Compare v.3</title>
		<link>http://feeds.feedburner.com/~r/techtipsbr/~3/376477633/</link>
		<comments>http://www.techtips.com.br/utilitarios/beyond-compare-v3/#comments</comments>
		<pubDate>Wed, 27 Aug 2008 20:05:47 +0000</pubDate>
		<dc:creator>Leonel Togniolli</dc:creator>
		
		<category><![CDATA[Utilitários]]></category>

		<guid isPermaLink="false">http://www.techtips.com.br/semcategoria/beyond-compare-v3/</guid>
		<description><![CDATA[Acho essencial revisar alterações feitas no código fonte antes de um check-in, além de fazer comparar revisões no histórico. Uma boa ferramenta de comparação de arquivos é fundamental.
Já experimentei diferentes ferramentas, inclusive mantendo algumas customizações no exemplo TextDiff, que acompanha o componente TDiff (que permite embutir esse tipo de comparação na sua aplicação feita em [...]]]></description>
			<content:encoded><![CDATA[<p>Acho essencial revisar alterações feitas no código fonte antes de um check-in, além de fazer comparar revisões no histórico. Uma boa ferramenta de comparação de arquivos é fundamental.</p>
<p>Já experimentei diferentes ferramentas, inclusive mantendo algumas customizações no exemplo TextDiff, que acompanha o componente <a href="http://www.angusj.com/delphi/textdiff.html">TDiff</a> (que permite embutir esse tipo de comparação na sua aplicação feita em Delphi). Mas sempre gostei mesmo do <a href="http://www.scootersoftware.com/">Beyond Compare</a>, e acabei comprando uma licença cerca de um ano e meio atrás, por um preço bastante razoável.</p>
<p>Semana passada vi que o Beyond Compare tinha lançado a versão 3.0:</p>
<p><a href="http://www.techtips.com.br/wp-content/uploads/2008/08/bc31.png"><img style="0px" src="http://www.techtips.com.br/wp-content/uploads/2008/08/bc3-thumb1.png" border="0" alt="BC3" width="644" height="320" /></a></p>
<p>A nova versão possui diversos novos recursos, incluindo suporte a Unicode e 3-way merge (<a href="http://www.ericksasse.com.br/sourcegear-diffmerge/">que fazia falta no passado</a>).</p>
<p>Fui para o site preparado para comprar a atualização – para minha surpresa eles oferecem atualização grátis para quem comprou uma licença a partir de 1º de janeiro de 2007, quase um ano e nove meses atrás. Preenchi um formulário no site deles e em alguns minutos tinha a chave da nova versão no meu email.</p>
<p>Definitivamente recomendo Beyond Compare para comparação e sincronização de arquivos e pastas, pelos recursos e preço acessível. Qual a ferramenta de comparação que você usa?</p>
<p><center>&copy; <a href="http://www.techtips.com.br">TechTips</a></center></p>]]></content:encoded>
			<wfw:commentRss>http://www.techtips.com.br/utilitarios/beyond-compare-v3/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.techtips.com.br/utilitarios/beyond-compare-v3/</feedburner:origLink></item>
		<item>
		<title>Otimização de Código, parte II: Conhecendo Gargalos e Profilers</title>
		<link>http://feeds.feedburner.com/~r/techtipsbr/~3/375440062/</link>
		<comments>http://www.techtips.com.br/programacao/performance/otimizacao-de-codigo-parte-ii-conhecendo-gargalos-e-profilers/#comments</comments>
		<pubDate>Tue, 26 Aug 2008 18:32:03 +0000</pubDate>
		<dc:creator>Leonel Togniolli</dc:creator>
		
		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://www.techtips.com.br/programacao/performance/otimizacao-de-codigo-parte-ii-conhecendo-gargalos-e-profilers/</guid>
		<description><![CDATA[Já vi acontecer inúmeras vezes: o sistema é escrito, testado, e funciona bem. É instalado em produção e funciona por uma semana ou duas. Então começa a ficar extremamente lento, a ponto de não ser mais usável. A sequência é também muito comum: o programador vai “otimizando” o código no escuro, usando a intuição, e [...]]]></description>
			<content:encoded><![CDATA[<p>Já vi acontecer inúmeras vezes: o sistema é escrito, testado, e funciona bem. É instalado em produção e funciona por uma semana ou duas. Então começa a ficar extremamente lento, a ponto de não ser mais usável. A sequência é também muito comum: o programador vai “otimizando” o código no escuro, usando a intuição, e perde muito tempo fazendo pequenas melhorias.</p>
<p>A solução para a primeira parte do problema é simples, mas geralmente ignorada: sempre teste utilizando um volume considerável de dados. É simples testar com dois ou três registros que você mesmo cadastrou, mas é importantíssimo garantir que a performance continue adequada com um volume de dados real. Utilize uma cópia de dados de produção caso existam e estejam disponíveis, ou utilize um gerador de dados (como o exemplo&#160; que acompanha o DBX4) para popular uma quantidade de registros compatível com o que volume esperado para produção. </p>
<p>O segundo problema é mais interessante. A intuição geralmente está errada – o que torna o código lento pode ser o que você menos espera. </p>
<h3>Gargalos</h3>
<p>Geralmente a lentidão é causada por gargalos no código, trecho de uma ou duas linhas que levam uma grande porcentagem do tempo total de processamento. Muitas vezes é fácil de encontrar uma alternativa para evitar essa demora, como reordenar o código para tratar a condição mais comum primeiro. Ao resolver um gargalo geralmente outro toma seu lugar, passando a ser responsável pela maioria da demora restante. A partir daí, resolver gargalos é uma questão de um retorno decrescente: cada otimização vai diminuir cada vez menos o retorno obtido.</p>
<p>Como um exemplo, vamos imaginar um hipotético processamento de registros que leve 10 segundos. Utilizando ferramentas apropriadas, descobrimos que a abertura da query para trazer os registros leva 80% do tempo. Analisando esta consulta, descobrimos uma forma de alterá-la para abrir praticamente instantaneamente. Agora o processamento leva cerca de 2 segundos. Se conseguirmos encontrar um novo gargalo que leve 80% do novo tempo e uma forma de removê-lo, ganhamos mais 1.6 segundos. Se repetirmos o processo mais uma vez, não conseguiremos melhorar mais que meio segundo. Se a qualquer momento trabalharmos em em outro trecho do código que não ser um desses três gargalos, estaremos perdendo nosso tempo e não teremos melhorias maiores que alguns milisegundos. É necessário bom senso para determinar a hora de parar.</p>
<p>Se não existe um gargalo claro, e a performance em geral ainda não é adequada, provavelmente é hora de procurar um algoritmo completamente diferente para resolver o problema.</p>
<p>Na prática nem sempre é possível remover gargalos completamente. Mesmo assim, deve se ter em mente que otimizar o restante do código muitas vezes não trará resultados perceptíveis.</p>
<p>No exemplo acima, escrevi que descobrimos o tempo levado por cada trecho do código utilizando “ferramentas apropriadas”. O que seria isso?</p>
<h3>Profilers</h3>
<p>Profilers são ferramentas que permitem determinar o tempo gasto na execução do seu código. Existem várias formas de fazer essa medição, desde uma forma arcaica manual, salvando o horário atual em um arquivo de log por exemplo, ou bem elaborada utilizando uma ferramenta profissional como o <a href="http://www.automatedqa.com/products/aqtime/">AQTime</a>. Utilizar uma ferramenta profissional é ótimo, é claro, mas é cara e algumas vezes até um exagero para um problema mais simples.</p>
<p>Existem duas categorias de profilers: Sampling Profilers e Intrumenting Profilers. A primeira faz medições (samples) regulares em pontos aleatórios (a cada milisegundo, por exemplo). Essa forma não afeta a execução do código, mas pode ser pouco precisa. Um Intrumenting Profiler adiciona código para efetuar medições em lugares exatos dentro do seu programa. Essa categoria se subdivide em profilers que instrumentam seu código fonte inserindo essas verificações, e profilers que alteram o código de máquina conforme ele é executado para inseri-las. Uma maior precisão é conseguida desta forma, mas sob o custo de alterar sutilmente o fluxo do seu código. Como na mecânica quântica, o ato de medir pode pode estar alterando o resultado. Na prática, nenhum dos dois é extremamente superior: deve-se pesar os prós e contras, e quem sabe até utilizar os dois tipos como uma boa alternativa para encontrar diferentes tipos de gargalos.</p>
<p>A forma mais simples de determinar o tempo levado por um método é utilizar uma forma simples e manual de um source intrumenting profiler - escrever código para salvar o tempo inicial e final, e exibir/armazenar esse valor. A glanularidade é exatamente qual quiser, até cada linha. A precisão depende da forma que o tempo for medido – não recomendo a função Now, pois não é muito precisa. GetTickCount é adequada para a maioria dos casos, tendo precisão de 1ms. Pode ser usada mais ou menos assim:</p>
<pre><b>var</b>
  t: Cardinal;
<b>begin</b>
  t := GetTickCount;
  EfetuaProcessamento;
  WriteLn(GetTickCount - t);
<b>end;</b></pre>
</p>
<p>Se uma precisão maior que 1ms for necessária, recomendaria a API QueryPerformanceCounter. A precisão dela depende do processador, e é necessário chamar QueryPerformanceFrequency para determiná-la. Outra alternativa é o opcode <strong>RDTSC</strong>, mnemônico para <em>read time stamp counter</em>, que também retorna o número de ticks desde que o processador foi reiniciado, assim como GetTickCount, mas com maior resolução. Essa alternativa não é recomendada hoje em dia por potenciais problemas relacionados a processadores multicore e processadores com clock variável (geralmente em portáteis).</p>
<p>Essa forma manual de profiling é claramente adequada apenas para pequenos problemas e testes rápidos. Para casos mais elaborados, deve-se considerar utilizar algum dos profilers disponíveis:</p>
<p><a href="http://www.prodelphi.de/">ProDelphi</a> é um source instrumenting profiler, portanto ele faz (e desfaz) alterações no seu código fonte. Possui uma versão gratuita, com limitações, e uma versão comercial por 47.50 €.</p>
<p><a href="http://17slon.com/gp/gpprofile/index.htm">GpProfile</a> é outro source intrumenting profiler. Gratuito, open source, mas sem atualizações por muitos anos.</p>
<p><a href="http://www.techtips.com.br/arquivos/SamplingProfiler-1.5.0.zip">Sampling Profiler</a> é, como o nome diz, um sampling profiler, Freeware, mas sem código fonte. Uma boa alternativa pra quem não quer gastar com ferramentas comerciais e não quer alterações no seu código fonte.</p>
<p><a href="http://www.automatedqa.com/products/aqtime/index.asp">AQTime</a> é, sem dúvida, a ferramenta mais avançada e completa. É um instrumenting profiler que só altera o código de máquina ao ser executado, então não requer nenhuma alteração no código fonte. Além de tempo gasto em procedimentos e linha por linha, possui modos onde verifica uso de memória, de recursos, e diversas outras análises extremamente interessantes. Custa $599.</p>
<p>Na terceira parte desta série pretendo apresentar um exemplo prático de otimização de um projeto usando um profiler.</p>
<p><center>&copy; <a href="http://www.techtips.com.br">TechTips</a></center></p>]]></content:encoded>
			<wfw:commentRss>http://www.techtips.com.br/programacao/performance/otimizacao-de-codigo-parte-ii-conhecendo-gargalos-e-profilers/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.techtips.com.br/programacao/performance/otimizacao-de-codigo-parte-ii-conhecendo-gargalos-e-profilers/</feedburner:origLink></item>
		<item>
		<title>Anunciado Delphi 2009</title>
		<link>http://feeds.feedburner.com/~r/techtipsbr/~3/374437356/</link>
		<comments>http://www.techtips.com.br/programacao/delphi/anunciado-delphi-2009-2/#comments</comments>
		<pubDate>Mon, 25 Aug 2008 17:02:39 +0000</pubDate>
		<dc:creator>Leonel Togniolli</dc:creator>
		
		<category><![CDATA[Delphi]]></category>

		<guid isPermaLink="false">http://www.techtips.com.br/programacao/delphi/anunciado-delphi-2009-2/</guid>
		<description><![CDATA[O Delphi 2009 acaba de ser anunciado. Já está disponível para pré-venda, e acredito que já esteja disponível para download para quem optar por Eletronic Software Delivery em pouco tempo.
Apesar de o principal novo recurso ser o total suporte de Unicode na VCL, vários outros novos recursos chamam a atenção:

Novos controles na VCL, com destaque [...]]]></description>
			<content:encoded><![CDATA[<p>O <a href="http://www.codegear.com/br/products/delphi/win32">Delphi 2009</a> acaba de ser <a href="http://www.embarcadero.com/news/press_releases/delphicppbuilder.html">anunciado</a>. Já está disponível para pré-venda, e acredito que já esteja disponível para download para quem optar por <em>Eletronic Software Delivery </em>em pouco tempo.</p>
<p>Apesar de o principal novo recurso ser o total suporte de Unicode na VCL, vários outros novos recursos chamam a atenção:</p>
<ul>
<li>Novos controles na VCL, com destaque ao Ribbons estilo Office 2007.</li>
<li>Melhorias na ImageList, incluindo suporte a PNG.</li>
<li>Novos recursos de linguagem, com destaque a Generics e Anonymous Methods.</li>
<li>VCL pra Web atualizada com suporte a AJAX e Silverlight.</li>
<li>DataSnap 2009, que simplifica o desenvolvimento de aplicações três camadas sem uso de COM.</li>
</ul>
<p>Vale a pena conferir a <a href="http://dn.codegear.com/article/38459">lista de componentes de terceiros</a> que já foram atualizados para ter suporte ao Delphi 2009.</p>
<p>Pretendo detalhar os novos recursos em futuros artigos, portanto aguarde atualizações.</p>
<p><center>&copy; <a href="http://www.techtips.com.br">TechTips</a></center></p>]]></content:encoded>
			<wfw:commentRss>http://www.techtips.com.br/programacao/delphi/anunciado-delphi-2009-2/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.techtips.com.br/programacao/delphi/anunciado-delphi-2009-2/</feedburner:origLink></item>
		<item>
		<title>Otimização de Código, parte I: Entendendo a Complexidade de Algoritmos</title>
		<link>http://feeds.feedburner.com/~r/techtipsbr/~3/258363429/</link>
		<comments>http://www.techtips.com.br/programacao/performance/otimizacao-de-codigo-parte-i-entendendo-a-complexidade-de-algoritmos/#comments</comments>
		<pubDate>Wed, 26 Mar 2008 14:44:24 +0000</pubDate>
		<dc:creator>Leonel Togniolli</dc:creator>
		
		<category><![CDATA[Performance]]></category>

		<guid isPermaLink="false">http://www.techtips.com.br/programacao/performance/otimizacao-de-codigo-parte-i-entendendo-a-complexidade-de-algoritmos/</guid>
		<description><![CDATA[A otimiza&#231;&#227;o de c&#243;digo &#233; uma tarefa muitas vezes deixada de lado, e, muito pior, feita de formas erradas muitas vezes por inexperi&#234;ncia do programador, tendo como resultado programas que funcionam bem em testes com um volume pequeno de dados e que demoram horas conforme o volume de dados aumenta.
Para entender os passos necess&#225;rios para [...]]]></description>
			<content:encoded><![CDATA[<p>A otimiza&#231;&#227;o de c&#243;digo &#233; uma tarefa muitas vezes deixada de lado, e, muito pior, feita de formas erradas muitas vezes por inexperi&#234;ncia do programador, tendo como resultado programas que funcionam bem em testes com um volume pequeno de dados e que demoram horas conforme o volume de dados aumenta.</p>
<p>Para entender os passos necess&#225;rios para otimizar seu c&#243;digo de uma forma que tenha um bom resultado pr&#225;tico sem comprometer a qualidade do c&#243;digo, deve-se entender alguns conceitos importantes:</p>
<ol>
<li>Quando otimizar. </li>
<li>Como reconhecer qual parte do c&#243;digo toma mais tempo. </li>
<li>E o que fazer para diminuir o tempo tomado por essas partes do c&#243;digo. </li>
</ol>
<p>Vou elaborar o primeiro item hoje, e deixar os pr&#243;ximos dois para artigos futuros.</p>
<h3>Quando Otimizar</h3>
<p>Donald Knuth <a href="http://pplab.snu.ac.kr/courses/adv_pl05/papers/p261-knuth.pdf">escreveu</a>, em 1974, a j&#225; famosa e gasta frase: &quot;<em>Devemos esquecer das pequenas efici&#234;ncias, cerca de 97% do tempo. Otimiza&#231;&#227;o prematura &#233; a raiz de todo o mal</em>&quot;. Em seguida, ele elabora que n&#227;o se deve ignorar os 3% restantes, mas apenas ap&#243;s que eles forem identificados.</p>
<p>Mais que isso, diz que a experi&#234;ncia universal de programadores (incluindo a minha), &#233; que ap&#243;s utilizar ferramentas para medir a performance do c&#243;digo, voc&#234; percebe que o que as tentativas de adivinhar quais s&#227;o esses trechos cr&#237;ticos geralmente s&#227;o falhas. &#201; f&#225;cil perceber que tempo gasto otimizando partes do c&#243;digo que n&#227;o s&#227;o cr&#237;ticas para a performance &#233; uma perda de tempo, e acabam tendo um impacto negativo quando se considera o tempo que ser&#225; levado para depurar e manter esse c&#243;digo, agora mais complexo por otimiza&#231;&#245;es desnecess&#225;rias. </p>
<p>O retorno da otimiza&#231;&#227;o costuma seguir o <a href="http://pt.wikipedia.org/wiki/Principio_de_Pareto">Principio de Pareto</a>, que postula que apenas 20% do c&#243;digo &#233; respons&#225;vel por cerca de 80% da performance. Dessa forma, mesmo que se diminua pela metade o tempo levado por um trecho espec&#237;fico de c&#243;digo, se ele s&#243; influencia em 1% no tempo total de determinado processo, voc&#234; s&#243; teve 0.5% de ganho de performance. Por outro lado, ao identificar um trecho que leva 30% do tempo, qualquer melhoria de performance nele ter&#225; um retorno 30 vezes maior. Na pr&#225;tica, vejo porcentagens ainda maiores que essa, acentuando ainda mais a importancia de localizar corretamente os trechos que levam mais tempo, conhecidos como gargalos, ou bottlenecks, se preferir um <a href="http://rafaelrgi.wordpress.com/2007/11/27/mim-fala-portuges/">informatiqu&#234;s</a> mais elaborado.</p>
<p>Isso quer dizer, que, na pr&#225;tica, ao escrever c&#243;digo, evite tomar qualquer decis&#227;o no impacto de performance que ela vai ter. Decis&#245;es como usar uma ou outra fun&#231;&#227;o para realizar determinada tarefa devem ser tomadas com base nos m&#233;ritos de legibilidade e mantenabilidade do c&#243;digo, muito acima de qualquer suposta diferen&#231;a de performance entre elas. N&#227;o deixe a intui&#231;&#227;o de que algum ponto ser&#225; um gargalo influenciar essa decis&#227;o (lembre-se, intui&#231;&#245;es geralmente s&#227;o desbancadas por medi&#231;&#245;es de performance). Qualquer escolha errada nesse ponto &#233; facilmente adequada nas fases de medi&#231;&#227;o e otimiza&#231;&#227;o.</p>
<p>O que isso n&#227;o quer dizer, em contrapartida, &#233; que se deve ignorar a performance na hora de planejar a solu&#231;&#227;o que vai ser implementada, antes da codifica&#231;&#227;o. &#201; importante saber o que est&#225; sendo implementado e qual a complexidade dessa solu&#231;&#227;o. Deve-se estimar a quantidade de itens que o c&#243;digo deve ser capaz de processar, e adequar a complexidade do algoritmo e estruturas de dados escolhidas para obter uma performance apropriada a esse n&#250;mero. Uma das solu&#231;&#245;es na etapa de diminuir o tempo tomado por determinado gargalo &#233; substituir o algoritmo por um mais eficiente, mas tal substitui&#231;&#227;o costuma ser trabalhosa e demanda mais trabalho que um planejamento adequado tomaria.</p>
<h3>Complexidade de Algoritmos</h3>
<p>A complexidade de algoritmos &#233; uma medida da escalabilidade de um algoritmo. De quanto trabalho ele precisa fazer para resolver o problema conforme o n&#250;mero de itens aumenta. Existe uma forma padr&#227;o de analisar e representar a complexidade de algoritmos, que &#233; a nota&#231;&#227;o Big-O (raramente traduzida para Grande-O). Para determinar a complexidade de um algoritmo, conta-se o n&#250;mero de opera&#231;&#245;es que ele faz para cada item, onde opera&#231;&#227;o pode ser compara&#231;&#245;es, trocas, leituras de disco, etc. Em seguida, &#233; determinada uma express&#227;o que representa essa quantidade. Uma complexidade O(n), ou linear, representa que o n&#250;mero de opera&#231;&#245;es &#233; constante e proporcional ao n&#250;mero de itens na lista. O(n<i></i>&#178;), ou quadr&#225;tica, mostra a propor&#231;&#227;o que o n&#250;mero de opera&#231;&#245;es cresce conforme o n&#250;mero de itens aumenta.</p>
<p>&#201; muito mais f&#225;cil de entender essa representa&#231;&#227;o graficamente:</p>
<p><a href="http://www.techtips.com.br/wp-content/uploads/2008/03/bigo.png"><img height="227" alt="O(n) vs O(n&#178;)" src="http://www.techtips.com.br/wp-content/uploads/2008/03/bigo-thumb.png" width="483" border="0" /></a> </p>
<p>A figura representa o n&#250;mero de opera&#231;&#245;es efetuadas por dois algoritmos hipot&#233;ticos, um O(n) e o segundo O(n<i></i>&#178;). Algumas caracter&#237;sticas importantes:</p>
<ul>
<li>&#201; f&#225;cil de observar a falta de escalabilidade do segundo algoritmo. Conforme o n&#250;mero de itens aumenta, o n&#250;mero de opera&#231;&#245;es aumenta muito rapidamente. </li>
<li>N&#227;o &#233; um gr&#225;fico de f(x) = n e g(x)=x&#178;, apesar que esse seria um exemplo igualmente v&#225;lido (e mais simples). A express&#227;o mostrada pela nota&#231;&#227;o O n&#227;o &#233; exatamente o n&#250;mero de opera&#231;&#245;es que v&#227;o ser executadas, mas sim uma representa&#231;&#227;o de como esse n&#250;mero muda em rela&#231;&#227;o &#224; quantidade de itens processados. N&#227;o existe O(n + 10) nem O(10n). Ambos seriam representados por O(n). Dois algoritmos podem ter a mesma complexidade mas um efetuar mais opera&#231;&#245;es, ou o mesmo n&#250;mero de opera&#231;&#245;es e levar um tempo maior que o outro (se a opera&#231;&#227;o for mais demorada). </li>
<li>O algoritmo mais complexo pode levar menos tempo que o menos complexo. O tempo extra gasto no caso mais simples pode ser a gera&#231;&#227;o de uma tabela de pesquisa, por exemplo, que pode levar mais tempo do que a busca por for&#231;a em um n&#250;mero pequeno de itens. Supondo que no gr&#225;fico acima a opera&#231;&#227;o efetuada pelos dois algoritmos seja equivalente, o mais complexo vai ser mais r&#225;pido at&#233; um pouco mais de 150 itens. Se o n&#250;mero de itens vai ser baixo (por exemplo, processar as janelas abertas em um editor de imagens), a segunda op&#231;&#227;o pode ser a mais adequada. Se o n&#250;mero for alto (ou desconhecido), deve-se tomar uma extrema aten&#231;&#227;o na complexidade do algoritmo que ser&#225; usado. </li>
</ul>
<p>Sabendo desses detalhes, fica mais f&#225;cil determinar a complexidade de um algoritmo qualquer. Um exemplo seria a busca de um item em uma lista desordenada. Em pseudoc&#243;digo:</p>
<pre>resultado = -1
de i := 1 at&#233; Lista.Count
  se Lista[i] = Item
    resultado = i
retorne resultado</pre>
<p>A opera&#231;&#227;o que est&#225; sendo contada &#233; a compara&#231;&#227;o. O n&#250;mero de opera&#231;&#245;es &#233; sempre igual ao n&#250;mero de itens na lista, claramente O(n). Uma otimiza&#231;&#227;o &#243;bvia reduz o n&#250;mero de compara&#231;&#245;es:</p>
<pre>de i := 1 at&#233; Lista.Count
  se Lista[i] = Item
    retorne i
retorne -1</pre>
<p>Nesse novo exemplo, no melhor caso, o item procurado &#233; o primeiro da lista, sendo feita apenas uma compara&#231;&#227;o. No pior caso, n&#227;o &#233; encontrado, sendo feitas n compara&#231;&#245;es. O complexidade analisa o pior caso, ainda mantendo esse algoritmo como O(n). Perceba que se forem feitas diversas buscas em uma lista, o n&#250;mero m&#233;dio de compara&#231;&#245;es ser&#225; entre 1 e N, e cresce proporcionalmente a N, mantendo a caracter&#237;stica de complexidade.&#160; A m&#233;dia seria 3n/4 para uma lista n&#227;o ordenada e n/2 em uma lista ordenada, caso tenha curiosidade.</p>
<p>Um algoritmo para encontrar todos os itens duplicados em uma lista poderia ser escrito assim:</p>
<pre>de i := 1 at&#233; Lista.Count
  de j := 1 at&#233; Lista.Count
    se (i &lt;&gt; j) e (Lista[i] = Lista[j])
      Duplicados.Adiciona(i, j)</pre>
<p>Este seria um exemplo de O(n<i></i>&#178;). Para cada item, todos os outros itens s&#227;o percorridos. Otimiza&#231;&#245;es simples, como no exemplo anterior, podem ser limitar a itera&#231;&#227;o no loop interno de 1 at&#233; N-1, e no loop interno para a faixa i + 1 at&#233; N, que diminuem o n&#250;mero de compara&#231;&#245;es, mas n&#227;o alteram a complexidade. O n&#250;mero de itera&#231;&#245;es ainda &#233; proporcional ao quadrado do n&#250;mero de itens.</p>
<p>Algumas medidas Big-O comuns s&#227;o as seguintes, em ordem crescente de complexidade:</p>
<ul>
<li>O(1), ou <em>constante</em> - O tempo do algoritmo independe do n&#250;mero de itens. Claramente a melhor op&#231;&#227;o quando N pode crescer muito. &#201; a complexidade em inser&#231;&#227;o e busca em <a href="http://pt.wikipedia.org/wiki/Tabela_hash">Tabelas Hash</a> </li>
<li>O(log n), ou <em>logar&#237;tmico </em>- &#201; proporcional ao logaritmo de n, que cresce em uma taxa muito mais lenta que n. &#201; uma op&#231;&#227;o bem adequada quando n&#227;o &#233; poss&#237;vel utilizar O(1). A busca bin&#225;ria em uma lista ordenada tem essa complexidade. </li>
<li>O(n), ou <em>linear </em>- &#201; o exemplo que j&#225; vimos de uma busca de for&#231;a bruta em uma lista qualquer. Come&#231;a a ser um problema quando seu c&#243;digo tem que tratar um n&#250;mero indeterminado de itens. </li>
<li>O(n&#178;), ou <em>quadr&#225;tica</em> - O n&#250;mero de opera&#231;&#245;es &#233; proporcional ao quadrado do n&#250;mero de itens. O algoritmo intuitivo de ordena&#231;&#227;o, a <a href="http://pt.wikipedia.org/wiki/Insertion_sort">ordena&#231;&#227;o por inser&#231;&#227;o</a>, tem essa complexidade. Deve ser evitada praticamente para qualquer n&#250;mero de itens que n&#227;o estejam sobre estrito controle. </li>
<li>O(n!), ou <em>fatorial</em> - Proporcional ao fatorial de n, ou seja, cresce extremamente r&#225;pido. Mesmo que as opera&#231;&#245;es sejam r&#225;pidas, rapidamente com o crescimento de n o tempo tomado pelo algoritmo passar&#225; a ser excessivamente grande (horas, dias, ou mais). A for&#231;a bruta de uma senha tem essa essa complexidade, ou a solu&#231;&#227;o do problema do <a href="http://pt.wikipedia.org/wiki/Problema_do_caixeiro_viajante">caixeiro viajante</a>. </li>
</ul>
<h3>Conclus&#227;o</h3>
<p>A complexidade de algoritmos &#233; um ponto importante para ser considerado na escolha do design ou das estruturas usadas na codifica&#231;&#227;o, evitando introduzir problemas de escalabilidade. Para isso, &#233; importante saber estimar a complexidade de um c&#243;digo e reconhecer a complexidade de inser&#231;&#245;es e buscas em estruturas de dados comuns. Apesar disso, deve-se evitar a tenta&#231;&#227;o de intuitivamente deduzir quais ser&#227;o os gargalos no momento da codifica&#231;&#227;o e tomar decis&#227;o baseadas nessa intui&#231;&#227;o, prezando a legibilidade acima de tudo. &#201; muito mais f&#225;cil localizar e corrigir gargalos depois de ter o c&#243;digo escrito do que localizar e corrigir problemas de estilo.</p>
<p><center>&copy; <a href="http://www.techtips.com.br">TechTips</a></center></p>]]></content:encoded>
			<wfw:commentRss>http://www.techtips.com.br/programacao/performance/otimizacao-de-codigo-parte-i-entendendo-a-complexidade-de-algoritmos/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.techtips.com.br/programacao/performance/otimizacao-de-codigo-parte-i-entendendo-a-complexidade-de-algoritmos/</feedburner:origLink></item>
		<item>
		<title>Introdução ao BlackfishSQL</title>
		<link>http://feeds.feedburner.com/~r/techtipsbr/~3/191919634/</link>
		<comments>http://www.techtips.com.br/programacao/bancos-de-dados/blackfishsql/introduo-ao-blackfishsql/#comments</comments>
		<pubDate>Wed, 28 Nov 2007 16:46:25 +0000</pubDate>
		<dc:creator>Leonel Togniolli</dc:creator>
		
		<category><![CDATA[BlackfishSQL]]></category>

		<guid isPermaLink="false">http://www.techtips.com.br/programacao/bancos-de-dados/blackfishsql/introduo-ao-blackfishsql/</guid>
		<description><![CDATA[No final de outubro apresentei o BlackfishSQL na sétima Borland Conference, em São Paulo. Os slides desta apresentação e das outras já estão disponíveis para download.
Ontem apresentei uma palestra semelhante na CodeRage II, em português e inglês. A CodeRage ainda está acontecendo (e é grátis!), e algum tempo depois do seu término o replay será [...]]]></description>
			<content:encoded><![CDATA[<p>No final de outubro apresentei o BlackfishSQL na sétima Borland Conference, em São Paulo. Os slides desta apresentação e das outras <a href="http://dn.codegear.com/br/article/37375">já estão disponíveis</a> para download.</p>
<p>Ontem apresentei uma palestra semelhante na <a href="http://conferences.codegear.com/coderage07/">CodeRage II</a>, em português e inglês. A CodeRage ainda está acontecendo (e é grátis!), e algum tempo depois do seu término o replay será disponibilizado na <a href="http://dn.codegear.com/tv">CodeGearTV</a>. </p>
<p>Enquanto isso, se você estiver interessando em mais uma oportunidade de conhecer&nbsp; o BlackfishSQL, aprender a escrever Stored Procedures e Triggers em Delphi, e fazer perguntas ao vivo, não perca o <a href="http://dn.codegear.com/br/article/37399">CodeGear Delphi Day em Português</a>, dia 7 de dezembro. Além da minha apresentação do BlackfishSQL, existem seis outras palestras técnicas, gratuitas, em português.</p>
<p>Se você ainda não conheçe o BlackfishSQL, vou mostrar rapidamente porque você deve assistir minha apresentação.</p>
<h2>BlackfishSQL</h2>
<p>BlackfishSQL é um banco 100% gerenciado, rodando completamente sobre uma máquina virtual, sem dependências de nenhum sistema operacional. Existem versões de BlackfishSQL para a plataforma Java e para a plataforma .Net. Apesar de ser o primeiro lançamento para plataforma .Net, e a primeira vez que é chamado de BlackfishSQL, é a oitava versão do banco de dados, que existia com nome JDataStore anteriormente, acompanhando o desenvolvimento do JBuilder por um bom tempo. Apesar de ainda termos poucas escolhas de plataforma com .Net, Java existe em praticamente todo lugar e o BlackfishSQL o acompanha em Linux, Solaris, ou no seu celular, por exemplo.</p>
<p>BlackfishSQL suporta o padrão SQL92, conhecido de todos que já trabalham com SQL, tendo uma boa compatibilidade, sem muitas extensões fora do padrão, preferindo prover os recursos adicionais através de stored procedures já embutidas.</p>
<p>Outras caracteristicas importantes são a fácil distribuição de um servidor BlackfishSQL, de uma aplicação que acessa tal servidor, ou de um aplicação que utiliza o BlackfishSQL de forma embutida no processo - não é necessário instalação, registrar DLLs, ou nada disso - é copiar alguns arquivos e rodar.</p>
<p>A caracteristica do BlackfishSQL que vai interessar mais desenvolvedores Delphi é a possibilidade de escrever Stored Procedures, UDFs e triggers em código Delphi (ou reaproveitar seu código Delphi existente como Stored Procedures), e usar o editor e debugger do Delphi para esse desenvolvimento, de uma forma bem fácil.</p>
<p>Se isso parece interessante, não perca o Delphi Day para conhecer o BlackfishSQL de verdade e ver as outras apresentações.</p>
<p><center>&copy; <a href="http://www.techtips.com.br">TechTips</a></center></p>]]></content:encoded>
			<wfw:commentRss>http://www.techtips.com.br/programacao/bancos-de-dados/blackfishsql/introduo-ao-blackfishsql/feed/</wfw:commentRss>
		<feedburner:origLink>http://www.techtips.com.br/programacao/bancos-de-dados/blackfishsql/introduo-ao-blackfishsql/</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic Page Served (once) in 1.016 seconds -->
