tag:blogger.com,1999:blog-39379444178962304252023-11-16T04:24:57.079-08:00Tatu.Blogging();Carlos Henrique Agneshttp://www.blogger.com/profile/10084689043014290783noreply@blogger.comBlogger17125tag:blogger.com,1999:blog-3937944417896230425.post-48915384674954664122021-01-30T14:13:00.002-08:002021-01-31T03:24:02.853-08:00Você está fazendo isso errado! Tópico #2<p> Fala galera! Como estão todos? Sejam bem-vindos ao primeiro <i>post</i> de 2021.</p><p>Continuando o tema "Você está fazendo isso errado", vamos ao tópico #2, onde falaremos do uso da recursividade.</p><p>Não lembro exatamente a primeira vez que vi o recurso recursividade sendo explicado (acho que foi numa aula de Programação I - tenho a impressão que não vi esse recurso nas aulas de algoritmos), mas lembro que fiquei impressionado, tanto pelo recurso em si, quanto como a palavra recursividade se encaixava bem ao propósito do recurso.</p><p>Pois bem, já perdi as contas de quantas vezes escrevi algoritmos baseados em recursividade, então vai novamente a ressalva, pessoal, de que o objetivo deste <i>post</i> não é cravar a regra "não use recursividade", mas sim, avalie se a recursividade realmente é a melhor solução para o seu algoritmo.</p><p>A verdade é que, para fins de leitura e simplificação de código, a recursividade muito mais agrega do que prejudica. Normalmente códigos recursivos são simples e elegantes.</p><p>A recursividade começa a se tornar um problema a partir do momento que não sabemos ou não é possível determinar quantas vezes a função vai chamar a si mesma (direta ou indiretamente), e não levar isso em consideração pode gerar um gargalo absurdo nos nossos algoritmos.</p><p>Sei que o exemplo que vou usar é batido: Descobrir o valor de uma determinada posição na sequência de Fibonacci. Todavia, neste caso em específico, não temos motivo para reinventar a roda, pois o exemplo demonstra claramente três coisas:</p><p></p><ul style="text-align: left;"><li>O quanto um código pode ficar mais legível com recursividade;</li><li>O quanto a performance pode cair ao usarmos recursividade;</li><li>Recursividade não necessariamente é a única solução para alguns problemas.</li></ul><div>Vamos começar analisando a implementação recursiva para Fibonacci:</div><div style="background: rgb(255, 255, 255); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;"><table><tbody><tr><td><pre style="line-height: 125%; margin: 0px;">1
2
3
4
5
6
7</pre></td><td><pre style="line-height: 125%; margin: 0px;"><span style="color: #008800; font-weight: bold;">class</span> <span style="color: #008800; font-weight: bold;">function</span> <span style="color: #bb0066; font-weight: bold;">TFibonacci</span><span style="color: #333333;">.</span><span style="color: #0066bb; font-weight: bold;">GetValorDaPosicao</span>(<span style="color: #008800; font-weight: bold;">const</span> pPosicao<span style="color: #333333;">:</span> UInt32)<span style="color: #333333;">:</span> UInt32<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">begin</span>
<span style="color: #008800; font-weight: bold;">if</span> pPosicao <span style="color: #333333;"><</span> <span style="color: #0000dd; font-weight: bold;">2</span> <span style="color: #008800; font-weight: bold;">then</span>
<span style="color: #007020;">Result</span> <span style="color: #333333;">:=</span> pPosicao
<span style="color: #008800; font-weight: bold;">else</span>
<span style="color: #007020;">Result</span> <span style="color: #333333;">:=</span> GetValorDaPosicao(pPosicao <span style="color: #333333;">-</span> <span style="color: #0000dd; font-weight: bold;">1</span>) <span style="color: #333333;">+</span> GetValorDaPosicao(pPosicao <span style="color: #333333;">-</span> <span style="color: #0000dd; font-weight: bold;">2</span>)<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
</pre></td></tr></tbody></table></div>
<div><br /></div><div>É um código claro, que representa exatamente como a sequência é calculada ou até mesmo explicada para alguém que está sendo apresentado à sequência de Fibonacci.</div><div><br /></div><div>Vamos agora dar uma olhada em como o algoritmo pode ser implementado de forma iterativa, eliminando a recursividade:</div><div style="background: rgb(255, 255, 255); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;"><table><tbody><tr><td><pre style="line-height: 125%; margin: 0px;"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16</pre></td><td><pre style="line-height: 125%; margin: 0px;"><span style="color: #008800; font-weight: bold;">class</span> <span style="color: #008800; font-weight: bold;">function</span> <span style="color: #bb0066; font-weight: bold;">TFibonacci</span><span style="color: #333333;">.</span><span style="color: #0066bb; font-weight: bold;">GetValorDaPosicaoSemRecursividade</span>(pPosicao<span style="color: #333333;">:</span> UInt32)<span style="color: #333333;">:</span> UInt32<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">begin</span>
<span style="color: #008800; font-weight: bold;">if</span> pPosicao <span style="color: #333333;"><</span> <span style="color: #0000dd; font-weight: bold;">2</span> <span style="color: #008800; font-weight: bold;">then</span>
<span style="color: #007020;">Result</span> <span style="color: #333333;">:=</span> pPosicao
<span style="color: #008800; font-weight: bold;">else</span>
<span style="color: #008800; font-weight: bold;">begin</span>
<span style="color: #008800; font-weight: bold;">var</span> lUltimaPosicao<span style="color: #333333;">:</span> UInt32 <span style="color: #333333;">:=</span> <span style="color: #0000dd; font-weight: bold;">1</span><span style="color: #333333;">;</span>
<span style="color: #007020;">Result</span> <span style="color: #333333;">:=</span> <span style="color: #0000dd; font-weight: bold;">1</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">while</span> pPosicao <span style="color: #333333;">></span> <span style="color: #0000dd; font-weight: bold;">2</span> <span style="color: #008800; font-weight: bold;">do</span>
<span style="color: #008800; font-weight: bold;">begin</span>
<span style="color: #007020;">Inc</span>(<span style="color: #007020;">Result</span><span style="color: #333333;">,</span> lUltimaPosicao)<span style="color: #333333;">;</span>
lUltimaPosicao <span style="color: #333333;">:=</span> <span style="color: #007020;">Result</span> <span style="color: #333333;">-</span> lUltimaPosicao<span style="color: #333333;">;</span>
<span style="color: #007020;">Dec</span>(pPosicao)<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
</pre></td></tr></tbody></table></div>
<div><br /></div><div>Alguém ficou em dúvida de quanto um código é mais simples que o outro? 😝 A diferença é gritante! Bom, para trocar a primeira opção pela segunda, é bom ter um bom motivo, não é?</div><div><br /></div><div>Nas apresentações do "Você está fazendo isso errado" em eventos, eu expliquei o problema, a sua origem, e também como resolver o mesmo, mas, em nenhuma das apresentações eu citei números para demonstrar a queda de performance. Pois bem, aqui vamos ver números (lembrando que esses números são específicos para cada caso, e aqui estamos falando da recursividade e complexidade gerada para resolver a sequência de Fibonacci).</div><div><br /></div><div>Antes dos números, vamos contextualizar que, para realizar este tipo de teste de performance, é importante reduzir ao máximo a quantidade de variáveis. Para isso, os algoritmos acima foram compilados em um exe de 64 bits configurado como <i>release</i>, e este executável foi testado em um servidor que estava ocioso durante os testes, conferindo assim um ambiente mais uniforme possível para os testes. Também é importante dizer que as medidas de performance foram executadas somente durante o processamento da lógica de negócio em si, não considerando atualizações visuais que usei como saída dos resultados. Por fim, os números demonstrados abaixo são as médias obtidas em 3 execuções de cada um dos cenários testados.</div><div><br /></div><div>Sem mais delongas, vamos aos números:</div><table class="tg" style="border-collapse: collapse; border-spacing: 0px;"><thead><tr><th rowspan="2" style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; font-weight: bold; overflow: hidden; padding: 2px 20px; text-align: center; vertical-align: middle; word-break: normal;">Posição</th><th rowspan="2" style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; font-weight: bold; overflow: hidden; padding: 2px 20px; text-align: center; vertical-align: middle; word-break: normal;">Resultado</th><th colspan="2" style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; font-weight: bold; overflow: hidden; padding: 2px 20px; text-align: center; vertical-align: middle; word-break: normal;">Recursivo</th><th colspan="2" style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; font-weight: bold; overflow: hidden; padding: 2px 20px; text-align: center; vertical-align: middle; word-break: normal;">Não Recursivo</th></tr><tr><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; font-weight: bold; overflow: hidden; padding: 2px 20px; text-align: center; vertical-align: middle; word-break: normal;">Tempo (ms)</td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; font-weight: bold; overflow: hidden; padding: 2px 20px; text-align: center; vertical-align: middle; word-break: normal;"><i>Ticks</i></td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; font-weight: bold; overflow: hidden; padding: 2px 20px; text-align: center; vertical-align: middle; word-break: normal;">Tempo (ms)</td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; font-weight: bold; overflow: hidden; padding: 2px 20px; text-align: center; vertical-align: middle; word-break: normal;"><i>Ticks</i></td></tr></thead><tbody><tr><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">0</td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">0</td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">< 1</td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">44</td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">< 1</td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">41</td></tr><tr><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">3</td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">2</td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">< 1</td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">47</td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">< 1</td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">41</td></tr><tr><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">8</td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">21</td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">< 1</td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">51</td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">< 1</td><td style="border-color: rgb(0, 0, 0); border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">42</td></tr><tr><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">15</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">610</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">< 1</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">96</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">< 1</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">50</td></tr><tr><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">20</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">6.765</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">< 1</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">556</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">< 1</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">44</td></tr><tr><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">25</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">75.025</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">< 1</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">5.486</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">< 1</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">41</td></tr><tr><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">30</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">832.040</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">5</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">55.810</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">< 1</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">42</td></tr><tr><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">35</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">9.227.465</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">40</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">403.651</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">< 1</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">49</td></tr><tr><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">40</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">102.334.155</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">433</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">4.331.396</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">< 1</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">46</td></tr><tr><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">43</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">433.494.437</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">1.813</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">18.131.228</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">< 1</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">52</td></tr><tr><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">44</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">701.408.733</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">2.938</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">29.383.621</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">< 1</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">49</td></tr><tr><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">45</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">1.134.903.170</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">4.714</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">47.141.376</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">< 1</td><td style="border-color: black; border-style: solid; border-width: 1px; font-family: Arial, sans-serif; font-size: 14px; overflow: hidden; padding: 2px 20px; text-align: right; vertical-align: middle; word-break: normal;">49</td></tr></tbody></table><div><br /></div><div>Vamos às conclusões...<br /><br />Durante a busca por posições iniciais (até a posição 8), a performance de ambos os algoritmos é muito semelhante, ao ponto das variações nos resultados estarem mais ligadas à variáveis que não temos controle (como o escalonamento de processos do Windows) do que qualquer outro fator.</div><div><br /></div><div>Já a partir da busca pela posição 15 em diante, a performance do algoritmo recursivo começa a degradar significativamente. Na busca pela posição 15, especificamente, ainda estamos na faixa de tempo abaixo do 1ms, mas a quantidade de <i>ticks</i> já começa a apresentar o problema. Claro que daí para frente a deterioração é exponencial, na mesma base da evolução da sequência de Fibonacci (aproximadamente 1,618 - O(1,618 na potência n) - o que fica comprovado ao analisarmos as últimas 3 linhas da tabela).</div><div><br /></div><div>Em contrapartida, a complexidade do algoritmo iterativo é linear (obviamente), sendo que, para as buscas apresentadas nesta tabela, as variações não estão relacionadas à variável n, mas às mesmas variáveis citadas dois parágrafos acima.</div><div><br /></div><div>E então? O que acharam? É bom ter atenção aos detalhes dos algoritmos, não?</div><div><br /></div><div>Abraço e até a próxima!!!</div>Carlos Henrique Agneshttp://www.blogger.com/profile/10084689043014290783noreply@blogger.com0tag:blogger.com,1999:blog-3937944417896230425.post-2402958094022570002020-12-30T07:18:00.002-08:002020-12-30T07:18:40.299-08:00Você está fazendo isso errado - Introdução!<p>Fala galera! Como vocês estão em tempos de pandemia? Espero que bem!</p><p><b>Hoje vou contar um pouco sobre a apresentação "Você está fazendo isso errado!".</b></p><p>Como alguns de vocês já sabem, eu fui instrutor certificado e também consultor Delphi durante muitos anos. Isto me permitiu ver códigos de todos os tipos, foi um período de muito aprendizado, em todos os sentidos possíveis.</p><p>Foi neste período que comecei a montar uma pequena lista de erros que desenvolvedores Delphi cometem, pequenos erros, mas com uma frequência grande o suficiente para me chamar a atenção.</p><p>Pois bem, separei alguns destes itens, dando prioridade para os que poderiam ser explicados em poucos minutos, e montei uma apresentação que foi rodada a primeira vez ano passado (2019) no Delphi Squad, aqui em Porto Alegre, com o já mencionado título "Você está fazendo isso errado!". Esta apresentação teve bastante repercussão e excelente aceitação.</p><p>Pois bem, este ano montei a versão II da apresentação, que foi apresentada na Embarcadero Conference 2020, que também foi muito bem aceita (obrigado comunidade pelas avaliações!).<br /><br /></p><p>Ontem, dia 28/12, ainda respondi um e-mail relativo à dúvidas decorrentes da apresentação da Conference, então, decidi aprofundar alguns dos itens (ou todos, vamos ver), aqui no blog também, e quem sabe, atingir mais Delpheiros que, por ventura, ainda praticam estes erros ;D</p><p>De imediato, vou começar por falar talvez do item com mais repercussão em todas as vezes que já rodei a primeira edição da apresentação...</p><p><b>#1 A correta relação entre Create x Try x Finally x Free de um objeto!</b></p><p>Uma das primeiras coisas que aprendemos no Delphi é instanciar objetos a partir de classes. Algum breve momento depois, aprendemos que, na maioria dos casos, somos também responsáveis por destruir os objetos que criamos. Depois, um novo elemento é inserido neste aprendizado, que é o fato de que nem sempre tudo acontece segundo o "caminho feliz", e nosso código deve estar preparado para eventuais erros, e aqui me refiro às exceções mesmo, e neste momento, em outras palavras, a destruição destes objetos deve estar protegida quanto à possíveis exceções.</p><p>Este é um conhecimento relativamente básico, um desenvolvedor Delphi júnior deve ter este conhecimento, e até aqui tudo bem. O problema surge quando avaliamos as inúmeras variações que os desenvolvedores usam para resolver o cenário acima. Quem me conhece sabe que eu sou contra as receitas definitivas, ou, pior ainda, frases de efeito como "nunca faça isso", "nunca use aquilo", mas, existem alguns casos onde o "nunca" realmente se aplica (vide comando with ;D), e existem também os casos que o desenvolvedor, ao seguir uma receita de bolo, realmente vai resolver 98% dos seus problemas, e os outros 2% passam por entender o que cada dos comandos usados faz na prática, e então o desenvolvedor está livre para escrever a variação que desejar, e este é o caso para construir objetos cujo ciclo de vida é local.</p><p>Se o seu objetivo é criar um objeto, usá-lo, e então destruí-lo, esta deveria ser a receita de bolo a ser seguida na grande maioria dos casos:</p><div style="background: rgb(255, 255, 255); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;"><table><tbody><tr><td><pre style="line-height: 125%; margin: 0px;">1
2
3
4
5
6</pre></td><td><pre style="line-height: 125%; margin: 0px;"><span style="color: #008800; font-weight: bold;">var</span> lObjeto <span style="color: #333333;">:=</span> TMinhaClasse<span style="color: #333333;">.</span>Create<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">try</span>
<span style="color: #888888;">{ uso do objeto aqui }</span>
<span style="color: #008800; font-weight: bold;">finally</span>
lObjeto<span style="color: #333333;">.</span>Free<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
</pre></td></tr></tbody></table></div><p>Volto a chamar a atenção para o fato de que este código é extremamente simples, muitos desenvolvedores devem estar pensando agora que "é exatamente assim que eu faço" (ótimo!), e tem também a galera que diz "sim, eu faço assim, aaaaahhhh, na realidade eu faço uma coisa aqui ou ali diferente, mas é assim que eu faço!", e aqui entram os códigos que, ou não caracterizam erros, mas poderiam ser melhores, mais otimizados, ou são códigos que realmente podem gerar erros quando a situação sai do caminho feliz.</p><p>Vamos para algumas das variações incorretas ou que permitem otimizações:</p><p></p><ul style="text-align: left;"><li><b>Instanciar o objeto dentro do bloco try</b>: Existem situações em que esta prática realmente não configura erro, mas em se tratando de uso de variáveis locais, que não foram inicializadas antes do try, aí realmente trata-se de uma prática bem ruim.</li></ul><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;">Lembrem-se que, uma vez dentro de um try protegido por finally, o finally vai ser executado independentemente do que acontecer no try (conhecimento básico de tratamento de exceções, eu sei). O problema todo está na possibilidade de acontecer um erro antes da associação da variável com o objeto criado. "Ah, mas a primeira coisa que eu faço dentro do bloco try é criar o objeto na variável", muitos desenvolvedores esquecem que este processo também é executado, no mínimo, em dois passos, e a associação da variável será sempre o último destes passos. Qual seria o primeiro passo? R: A criação do objeto em si. </blockquote><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;"> </blockquote><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;">Sendo assim, sempre temos que assumir que a própria criação do objeto pode levantar uma exceção, e neste caso, a variável nunca vai receber o objeto criado. Como consequência, a variável local vai continuar apontando para uma área de memória "aleatória", e o resultado do bloco vai ser, muito provavelmente, um Access Violation durante o bloco finally. </blockquote><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;"> </blockquote><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;">Um dos motivos para que os desenvolvedores levem a criação para dentro do bloco try, é justamente pensar que é necessário proteger a destruição do objeto para também no caso do construtor levantar uma exceção: Errado! Caso uma exceção seja disparada e não tratada dentro do construtor, o Delphi SEMPRE vai chamar, automaticamente, o destrutor daquela mesma classe, para então voltar a propagar a exceção, e ainda assim, não ficando objeto vazado na memória. No resumo, é isto aqui que acontece com essa prática:</blockquote><ul style="text-align: left;"><div style="background: rgb(255, 255, 255); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;"><table><tbody><tr><td><pre style="line-height: 125%; margin: 0px;">1
2
3
4
5
6</pre></td><td><pre style="line-height: 125%; margin: 0px;"><span style="color: #008800; font-weight: bold;">try</span>
lObjeto <span style="color: #333333;">:=</span> TMinhaClasse<span style="color: #333333;">.</span>Create<span style="color: #333333;">;</span> <span style="color: #888888;">// se der exceção aqui...</span>
<span style="color: #888888;">{ uso do objeto aqui }</span>
<span style="color: #008800; font-weight: bold;">finally</span>
lObjeto<span style="color: #333333;">.</span>Free<span style="color: #333333;">;</span> <span style="color: #888888;">// provavelmente vai dar AV aqui.</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span></pre></td></tr></tbody></table></div></ul><ul style="text-align: left;"><li><b>Testar se a variável está associada antes de chamar o Free</b>: Quando eu vejo esta prática, eu sempre pergunto ao autor do código, qual é o nome do destrutor padrão do Delphi? R: Destroy (obviamente). E então, por que temos o hábito de usar Objeto.Free e não Objeto.Destroy? Existe alguma diferença prática entre um e outro? R: Existe!</li></ul><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;">Ainda me impressiono com a quantidade de Delpheiros que não sabe que o método Free, implicitamente, já faz este teste para nós. Não ficou claro? Esta é uma cópia da implementação do método Free de TObject, retirada do Delphi Sydney:</blockquote><ul style="text-align: left;"><div style="background: rgb(255, 255, 255); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;"><table><tbody><tr><td><pre style="line-height: 125%; margin: 0px;">1
2
3
4
5
6
7
8
9</pre></td><td><pre style="line-height: 125%; margin: 0px;"><span style="color: #008800; font-weight: bold;">procedure</span> <span style="color: #bb0066; font-weight: bold;">TObject</span><span style="color: #333333;">.</span><span style="color: #0066bb; font-weight: bold;">Free</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">begin</span>
<span style="color: #888888;">// under ARC, this method isn't actually called since the compiler translates</span>
<span style="color: #888888;">// the call to be a mere nil assignment to the instance variable, which then calls _InstClear</span>
<span style="color: #888888;">{$IFNDEF AUTOREFCOUNT}</span>
<span style="color: #008800; font-weight: bold;">if</span> <span style="color: #008800; font-weight: bold;">Self</span> <span style="color: #333333;"><></span> <span style="color: #008800; font-weight: bold;">nil</span> <span style="color: #008800; font-weight: bold;">then</span>
Destroy<span style="color: #333333;">;</span>
<span style="color: #888888;">{$ENDIF}</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span></pre></td></tr></tbody></table></div></ul><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;">Então, na prática, testar se o objeto está associado ou não, para então chamar o Free, é redundância de código. Não ficou claro? É mais ou menos isso que o Delphi vai fazer quando você coloca o if antes do Free:</blockquote><ul style="text-align: left;"><div style="background: rgb(255, 255, 255); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;"><table><tbody><tr><td><pre style="line-height: 125%; margin: 0px;">1
2
3</pre></td><td><pre style="line-height: 125%; margin: 0px;"><span style="color: #008800; font-weight: bold;">if</span> ObjetoASerDestruido <span style="color: #333333;"><></span> <span style="color: #008800; font-weight: bold;">nil</span> <span style="color: #008800; font-weight: bold;">then</span>
<span style="color: #008800; font-weight: bold;">if</span> ObjetoASerDestruido <span style="color: #333333;"><></span> <span style="color: #008800; font-weight: bold;">nil</span> <span style="color: #008800; font-weight: bold;">then</span>
ObjetoASerDestruido<span style="color: #333333;">.</span>Destroy<span style="color: #333333;">;</span></pre></td></tr></tbody></table></div></ul><ul style="text-align: left;"><li><b>Usar FreeAndNil para variáveis que vão ser eliminadas do contexto</b>: Assim como o item anterior, este é um caso menos grave, mas me intriga ver como existem desenvolvedores que se atem às suas raízes, hábitos, muitas vezes paixões (:D) ao estilo e práticas de escrita de código, sem se perguntar o porquê de fazerem isso ou aquilo, simplesmente saem implementando daquela maneira porque aprenderam assim, ou tiveram um problema que aparentemente foi resolvido por aquela prática, e então criam a regra do "sempre faço assim, não me pergunte por que.".</li></ul><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;">O FreeAndNil é um destes casos, existe a igreja do "Uso FreeAndNil sempre", que tem milhares de devotos mundo afora. E vamos deixar bem claro, eu não estou dizendo que não se deve usar FreeAndNil, eu acho que existem casos e casos, e na grande maioria deles, EU NÃO USO FreeAndNil. Isto se deve ao fato de que a maioria dos objetos que eu preciso destruir manualmente tem ciclos de vida local, e consequentemente, uso também variáveis locais. </blockquote><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;"> </blockquote><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;">Faz mal usar FreeAndNil indiscriminadamente? Depende o que você considera como "mal". Vamos começar por analisar a diferença entre chamar o Free diretamente ou chamar o FreeAndNil. </blockquote><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;"> </blockquote><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;">O Free já discutimos o que faz no item acima, beleza. </blockquote><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;"> </blockquote><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;">Do FreeAndNil, quem nomeou o procedimento foi feliz na tarefa, ele descreve exatamente o que vai acontecer com a variável do tipo objeto que passarmos para ele como parâmetro: resumidamente, vai ser chamado o método Free do objeto apontado pela variável, e então a variável vai ser desassociada (vai apontar para nil). Se analisarmos o código do FreeAndNil, é um código de baixa complexidade, que não envolve a chamada de stack (é um procedimento inline), mas que continua dando mais trabalho ao processador do que um Free daria. </blockquote><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;"> </blockquote><blockquote style="border: none; margin: 0px 0px 0px 40px; padding: 0px; text-align: left;">Gosto de fazer uma analogia: você já alugou muitos apartamentos ao longo da vida, sempre que você tem que devolver o apartamento, você sabe que tem que fazer a pintura nova do apartamento, eventuais pequenos reparos, e de tanto fazer isso, você já ficou craque na coisa, toda vez que precisa entregar o apartamento, sai fazendo tudo por impulso, afinal, é simples, sempre fez e deu certo. Então, você recebe uma carta dizendo que você deve deixar o atual apartamento que você aluga, não por pedido do proprietário ou algo assim, mas porque o prédio vai ser implodido. Beleza, você dispara o tradicional script de liberação do apartamento: tira suas coisas, pinta o apartamento, repara o que precisa de reparo, deixa tudo brilhando.... Espeeeeera! Por que raios você vai fazer isso tudo? O apartamento vai ser implodido! Ninguém vai alugar ele depois de você! Concorda? Espero que sim, e sendo assim, bem, o que você faz ao chamar sempre o FreeAndNil é pintar o apartamento toda vez que você desocupa ele, independentemente se vai ser usado por outra pessoa ou se o prédio vai ser implodido. "Ah, é injusta essa comparação, afinal, executar o FreeAndNil é um trabalho simples para o processador.", posso concordar partes com essa frase, mas uma coisa eu tenho certeza pelos vários anos de consultor, é esta falta de preciosismo com o código, de coisas que não mudamos por "sempre fiz assim", preguiça, ou outra desculpa, que nos fazem abrir portas para outras rotinas menos otimizadas ainda onde, por fim, ou impede a migração do mesmo para um cenário onde uma performance melhor seria necessária, como ser reutilizado em um server REST, entre outras situações. Devemos nos preocupar com os grandes gargalos, com os tradicionais grandes erros ao desenvolver um sistema? Não tenho dúvidas, a prioridade é essa. Mas, ao mesmo tempo, continuar escrevendo pequenos códigos que poderiam ser melhores porque "sempre fiz assim", não curto não. ;-)</blockquote><p><br /></p><p>Enfim, estes foram alguns dos tópicos que demonstrei neste tema do Você está fazendo isso errado". Em um futuro bem próximo vou abordar mais temas da apresentação, bem como podemos falar de outras variações que ainda podem acontecer na relação Create x Try x Finally x Free.</p><p><br /></p><p>Encerro o post por aqui, desejando que todos tenham crescido de alguma forma com tudo que aconteceu em 2020, e desejando que 2021 seja um super ano para todos, que seja o ano que encerraremos este ciclo triste que estamos vivendo. De coração, muitas felicidades para o ano novo! Até 2021!</p><p></p>Carlos Henrique Agneshttp://www.blogger.com/profile/10084689043014290783noreply@blogger.com0tag:blogger.com,1999:blog-3937944417896230425.post-22830728732633349622020-10-31T07:19:00.001-07:002020-10-31T07:19:32.355-07:00Retomando os trabalhos - Parte 2!<p>Fala Delpheiros!!!! Outubro foi um mês corrido, tive uma apresentação interna para a Agro1, retomada de viagens para Erechim (onde fica a matriz a matriz da Agro1), e claro, tivemos a Embarcadero Conference Brasil 2020, que infelizmente (e corretamente) teve que ser online neste ano.</p><p>Em Setembro contei um pouco do que estava acontecendo por aqui, falei do trabalho na Agro1, e deixei o <i>link</i> pronto para começar a a falar da TMR. Pois bem...</p><p>Pouco tempo depois de eu ter acertado com a Agro1, usando palavras do próprio, "o meu <i>brother</i>" Samuel "Muka" David me procurou com o fim de rodarmos um projeto audacioso (e vindo do Muka, era de se esperar o quê? 😜). O objetivo era criar uma empresa para atender demandas de mercado que surgiam a todo momento, montar realmente uma equipe de elite, e se tornar referência no fornecimento de desenvolvedores Delphi!</p><p>Começamos o processo de análise de mercado, viabilidade, recrutamento... e no meio de todos esses processos, recrutamos o terceiro elemento e formamos o tripé que seria fundamental para a sustentação necessária da empresa: entrou na parada o nosso outro <i>brother</i> Luiz "Radical" Sfolia.</p><p>Em maio de 2018 começamos a rodar a primeira etapa do projeto, com o Muka e eu na retaguarda organizacional, e o Radical com mais 3 devs mandando ver no Delphi!</p><div class="separator" style="clear: both; text-align: center;"><br /></div><br /><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBnFkY6QHvExMAZTBTbgTE3J2k6Kg1boilEeHf-wTRFckN9dLZmAZQRAmGHS2tpUe0p9ReCuLZt1YAQAur7Dw7NHW5wNpytslEEZV2zVSY8YUlx8dqCYDBjuGFQP-LVzmuMW8wqPVpgy8j/s1280/tmr+maio+2018.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="960" data-original-width="1280" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgBnFkY6QHvExMAZTBTbgTE3J2k6Kg1boilEeHf-wTRFckN9dLZmAZQRAmGHS2tpUe0p9ReCuLZt1YAQAur7Dw7NHW5wNpytslEEZV2zVSY8YUlx8dqCYDBjuGFQP-LVzmuMW8wqPVpgy8j/w400-h300/tmr+maio+2018.jpeg" width="400" /></a></div><br /><p>Foi somente em outubro daquele mesmo ano que, com a consolidação da empresa, adotamos o nome TMR (criatividade, nota.... 10! 😂😂).</p><p>Com o tempo, novos projetos foram iniciados, novos clientes, novos integrantes na equipe, e a TMR está, felizmente, cada vez mais forte!</p><p>A TMR ainda é uma empresa relativamente nova, mas desde o princípio nossa prioridade maior é proporcionar o melhor ambiente possível para a "nossa galera", seja através de constante atualização técnica da equipe, manter um ambiente legal para trabalhar, ou até mesmo prezar por momentos de integração constante, seja em eventos técnicos e até mesmo no trabalho diário, bem como nos nossos encontros "extra-campo". Dizem que imagens valem mais do que palavras, certo? Então vou parar de escrever...</p><p><br /></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCsN_VAXW0wCx_QKv2iFmyzI035EghKO1ZvSoMUMdJHjgFKirqB9bTCxC2E8jqmD132rCbVeGdv8e5la36ythsIZCuRBx1Ewi7RIxpqKZSq3pSZEVW8FbpbeBG9HbUfmrtem-HjB5_Tozi/s766/Captura+de+Tela+2020-10-31+a%25CC%2580s+11.06.51.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="350" data-original-width="766" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhCsN_VAXW0wCx_QKv2iFmyzI035EghKO1ZvSoMUMdJHjgFKirqB9bTCxC2E8jqmD132rCbVeGdv8e5la36ythsIZCuRBx1Ewi7RIxpqKZSq3pSZEVW8FbpbeBG9HbUfmrtem-HjB5_Tozi/s320/Captura+de+Tela+2020-10-31+a%25CC%2580s+11.06.51.png" width="320" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjChtbIvpA6TySFAnjK_zgGNKr1kffE7NOuIVzkp9Mvsbefulq17zh3O6wtg6ZSZp_hD93sqr-D4HbYp0g0Kmd1X0ahFYDDM_qWzaFnPv252HzbHBEG-rIOIO7PCLHCp1NFTBqjd3bCxvBj/s1040/tmr+update.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="780" data-original-width="1040" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjChtbIvpA6TySFAnjK_zgGNKr1kffE7NOuIVzkp9Mvsbefulq17zh3O6wtg6ZSZp_hD93sqr-D4HbYp0g0Kmd1X0ahFYDDM_qWzaFnPv252HzbHBEG-rIOIO7PCLHCp1NFTBqjd3bCxvBj/s320/tmr+update.jpeg" width="320" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWosobLK-y4gzXHx6z7hZeT2pfTj6hXB-3PJcd0dOtmjts8QAyrgxKxA2EjwvTZD4lwBqdkWbgULXNS9ZVTu1dmm2mdJAo5f2tg7ZrAhblpu7puvamU3Iw6Y1PV4Jc0HnFMvMIlachXsqf/s1280/tmr+radical.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="960" data-original-width="1280" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWosobLK-y4gzXHx6z7hZeT2pfTj6hXB-3PJcd0dOtmjts8QAyrgxKxA2EjwvTZD4lwBqdkWbgULXNS9ZVTu1dmm2mdJAo5f2tg7ZrAhblpu7puvamU3Iw6Y1PV4Jc0HnFMvMIlachXsqf/s320/tmr+radical.jpeg" width="320" /></a></div></div><br /><div class="separator" style="clear: both; text-align: center;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgc1EVhUJfQofQ_ZLumj6MtGXAmZW-y03Z9_bUkuf571769l16CEm_QXjL0ylf0Q8MV1_9aA7dRPqVNkdMdPoQMvGcxAb1k8rbokSIdeTERqvAPOaiyj0kHj6tzFZpmbRF9nETpJ8j1p5oZ/s1280/tmr+conference.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="624" data-original-width="1280" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgc1EVhUJfQofQ_ZLumj6MtGXAmZW-y03Z9_bUkuf571769l16CEm_QXjL0ylf0Q8MV1_9aA7dRPqVNkdMdPoQMvGcxAb1k8rbokSIdeTERqvAPOaiyj0kHj6tzFZpmbRF9nETpJ8j1p5oZ/s320/tmr+conference.jpeg" width="320" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbgC4iABfFSgK0C3usuhm6rGO1Bk2Vf4R019ACFhurmdq65pS0ESrnmjNOQlRrpb8Zxcl69V9GuqPrncXs3Z0jFreauSsc594HqNfK9H1W3v83uYfMUawwpHfvvopgyl81uvlXvH82FhlA/s1280/tmr+squad.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="960" data-original-width="1280" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgbgC4iABfFSgK0C3usuhm6rGO1Bk2Vf4R019ACFhurmdq65pS0ESrnmjNOQlRrpb8Zxcl69V9GuqPrncXs3Z0jFreauSsc594HqNfK9H1W3v83uYfMUawwpHfvvopgyl81uvlXvH82FhlA/s320/tmr+squad.jpeg" width="320" /></a></div><br /></div><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglso5JdvkmCXpJe2bYgIvVRBpgeS4kRqtUsWGgzUVjd5GgqEv68jUbjSLJU8duP9xDlpxxuShKPKqdzQtZffcF7_Q1kTfdA83q02tT0La-kmrQfMytRLTaNzdSukH74ScnpuKbiT3jO_wh/s1024/tmr+porto+das+mesas.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1024" data-original-width="769" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEglso5JdvkmCXpJe2bYgIvVRBpgeS4kRqtUsWGgzUVjd5GgqEv68jUbjSLJU8duP9xDlpxxuShKPKqdzQtZffcF7_Q1kTfdA83q02tT0La-kmrQfMytRLTaNzdSukH74ScnpuKbiT3jO_wh/s320/tmr+porto+das+mesas.jpeg" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlLkZM4SaGy8NJ0kKBYoAXCr0VTpmIya_7mhYqj6YWDPDin6g4n3ZpmNfC9fUCpQKjfxpe5JubxLiUddWCjzsh1TU76R_uBrcwz6tCapEY3ZSZW9Ily8jRdMra1gI0jxUoHOpY5n6qSR65/s1280/tmr+fim+de+ano.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="720" data-original-width="1280" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhlLkZM4SaGy8NJ0kKBYoAXCr0VTpmIya_7mhYqj6YWDPDin6g4n3ZpmNfC9fUCpQKjfxpe5JubxLiUddWCjzsh1TU76R_uBrcwz6tCapEY3ZSZW9Ily8jRdMra1gI0jxUoHOpY5n6qSR65/s320/tmr+fim+de+ano.jpeg" width="320" /></a></div><div class="separator" style="clear: both; text-align: center;"><br /></div><br />Infelizmente 2020 não foi um bom ano para mantermos estas atividades, mas espero que logo essa condição que vivemos hoje mude, e assim a primeira medida que tomaremos será reunir toda a galera, saudades da junção 😂!<br /><p></p><p>Enfim, em outro momento volto a escrever sobre as novidades da TMR. Enquanto isso, se quiser conhecer um pouco mais sobre a empresa, pode enviar um mail para contato@tmrti.com.br.</p><p>Por hoje era isto. Até o próximo <i>post</i>!</p>Carlos Henrique Agneshttp://www.blogger.com/profile/10084689043014290783noreply@blogger.com0tag:blogger.com,1999:blog-3937944417896230425.post-46185039638545594412020-09-30T15:59:00.003-07:002020-09-30T15:59:38.435-07:00Memory leak inesperado<p>Essa é uma séria de <i>posts</i> que estava na minha mira há bastante tempo, sendo que hoje tomei vergonha na cara para começar. Nesta série tentarei compartilhar as coisas que me acontecem, surpreendem, e aprendo no dia a dia de desenvolvedor. Então hoje começo a série "hoje eu aprendi...".</p><p>Já há alguns vários dias eu fui surpreendido por um vazamento de memória (<i>memory leak</i>) em um sistema da Agro1. O vazamento de memória estava em um código semelhante a este:</p><!--HTML generated using hilite.me--><div style="background: rgb(255, 255, 255); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;"><table><tbody><tr><td><pre style="line-height: 125%; margin: 0px;"> 1
2
3
4
5
6
7
8
9
10
11
12</pre></td><td><pre style="line-height: 125%; margin: 0px;"><span style="color: #008800; font-weight: bold;">var</span>
[weak] lAlgumaCoisa<span style="color: #333333;">:</span> IAlgumaCoisa<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">begin</span>
<span style="color: #008800; font-weight: bold;">If</span> <span style="color: #007020;">Supports</span>(pAlgumObjeto<span style="color: #333333;">,</span> IAlgumaCoisa<span style="color: #333333;">,</span> lAlgumaCoisa) <span style="color: #008800; font-weight: bold;">then</span>
<span style="color: #008800; font-weight: bold;">begin</span>
RegistrarMetodoQueSeraExecutadoDepois(
<span style="color: #008800; font-weight: bold;">procedure</span>
<span style="color: #008800; font-weight: bold;">begin</span>
<span style="color: #bb0066; font-weight: bold;">lAlgumaCoisa</span><span style="color: #333333;">.</span><span style="color: #0066bb; font-weight: bold;">ExecutarAlgumaCoisa</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span>)<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
</pre></td></tr></tbody></table></div>
<p></p><p><br /></p><p>Pois bem, uma das bases do novo framework em que estamos trabalhando na Agro1 é o uso massivo de interfaces, e felizmente o Delphi Berlin trouxe a opção de declarar variáveis do tipo interface (ou <i>fields</i>, parâmetros, etc.) como sendo referências fracas ou não seguras, e um dos efeitos destes atributos é fazer com que estas variáveis não passem pelos métodos _AddRef e _Release de IInterface durante sua manipulação (você pode ler um pouco mais sobre estes atributos <a href="https://blog.marcocantu.com/blog/2016-april-weak-unsafe-interface-references.html" target="_blank">aqui</a>).</p><p>Claro que o método acima é um resumo do que precisava ser feito e pode parecer confuso, mas trouxe para este exemplo somente o básico para mostrar o problema.</p><p>O que aprendi neste dia foi que <b>os metadados da variável passada como terceiro parâmetro do método Supports não são considerados no momento de fazer a atribuição da referência para a variável</b>, logo, a variável estar marcada ou não com o atributo <i>weak</i> não faz a menor diferença. Isto tudo porque o método Suppoprts chama diretamente o método QueryInterface, que por sua vez chama o método GetInterface, que chama explicitamente o _AddRef. Como a implementação do _AddRef, neste caso, fazia uso de contagem de referência, a variável entrou na contagem, fechou-se um circuito fechado entre as variáveis envolvidas no processo, e consequentemente geramos um vazamento de memória.</p><p><b>Solução</b>: tivemos que declarar uma segunda variável usada somente com escopo local, sem o atributo <i>weak</i>, e outra variável dedicada ao <i>closure</i>, esta sim com o marcador <i>weak</i>. Resumindo, ficou algo parecido com isto:</p><div style="background: rgb(255, 255, 255); border-color: gray; border-image: initial; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;"><table><tbody><tr><td><pre style="line-height: 16.25px; margin-bottom: 0px; margin-top: 0px;"> 1
2
3
4
5
6
7
8
9
10
11
12</pre><pre style="line-height: 16.25px; margin-bottom: 0px; margin-top: 0px;">13</pre><pre style="line-height: 16.25px; margin-bottom: 0px; margin-top: 0px;">14</pre></td><td><pre style="line-height: 16.25px; margin-bottom: 0px; margin-top: 0px;"><span style="color: #008800; font-weight: bold;">var</span>
<span style="color: #008800; font-weight: bold;"><pre style="color: black; font-weight: 400; line-height: 16.25px; margin-bottom: 0px; margin-top: 0px;"> lAlgumaCoisaClosure<span style="color: #333333;">:</span> IAlgumaCoisa<span style="color: #333333;">;</span>
</pre><pre style="color: black; font-weight: 400; line-height: 16.25px; margin-bottom: 0px; margin-top: 0px;"> [weak] lAlgumaCoisaClosure<span style="color: #333333;">:</span> IAlgumaCoisa<span style="color: #333333;">;</span>
</pre>begin</span>
<span style="color: #008800; font-weight: bold;">If</span> <span style="color: #007020;">Supports</span>(pAlgumObjeto<span style="color: #333333;">,</span> IAlgumaCoisa<span style="color: #333333;">,</span> lAlgumaCoisa) <span style="color: #008800; font-weight: bold;">then</span>
<span style="color: #008800; font-weight: bold;">begin</span></pre><pre style="line-height: 16.25px; margin-bottom: 0px; margin-top: 0px;"> lAlgumaCoisaClosure := lAlgumaCoisa;
RegistrarMetodoQueSeraExecutadoDepois(
<span style="color: #008800; font-weight: bold;">procedure</span>
<span style="color: #008800; font-weight: bold;">begin</span>
<span style="color: #bb0066; font-weight: bold;">lAlgumaCoisaClosure</span><span style="color: #333333;">.</span><span style="color: #0066bb; font-weight: bold;">ExecutarAlgumaCoisa</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span>)<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
</pre></td></tr></tbody></table></div><p><br /></p><p>Bom, se você passar por situação parecida, já sabe, está aí o problema e possível solução, espero que este <i>post</i> lhe ajude.</p><p>Grande abraço e até o próximo!</p><p></p>Carlos Henrique Agneshttp://www.blogger.com/profile/10084689043014290783noreply@blogger.com0tag:blogger.com,1999:blog-3937944417896230425.post-18956460478807073012020-09-30T15:54:00.001-07:002020-09-30T15:54:48.473-07:00Retomando os trabalhos - Parte 1!Fala galera! Há quanto tempo não passava por aqui?!<div><br /></div><div>Pois é, o blog já teve um hiato anteriormente, foi durante um período de várias mudanças na minha vida, principalmente profissional. Na época, eu tinha saído da Aquasoft e entrado na Softplus.</div><div><br /></div><div>Por circunstâncias de mercado, minha estada na Softplus foi curta, encerrei minhas atividades com aproximadamente um ano de trabalho na Softplus. A Softplus foi uma empresa que gostei muito de trabalhar, aprendi muito sobre diversas tecnologias, principalmente processos de automatização como CI e CD. Mas o mais importante, tive ótimos colegas, e fiz amigos de verdade por lá (no aguardo do próximo xis no Xodó ;-D).</div><div><br /></div><div>Enfim, não querendo estender muito a história, eu encerrei minhas atividades na Softplus para começar a trabalhar na Agro1, empresa dedicada ao desenvolvimento de soluções para o agronegócio, e felizmente estou na Agro1 desde Abril de 2018.</div><div><br /></div><div>Na Agro1, eu tenho trabalhado com projetos incríveis, estamos evoluindo diariamente em diversos aspectos, muitas coisas legais sendo implementadas (baixíssimo nível de acoplamento com interfaces e injeção de dependência, testes unitários, outros testes automatizados, melhorias nos processos de versionamento, a lista é longa), a equipe abraçou projetos de qualificação, e a busca por inovação e outras melhorias tem sido uma constante.<br /><br />Estamos sempre buscando por novos integrantes para a equipe, então, se você quer ser meu colega na Agro1, me manda um mail no tatu@taturs.com. Bora!?</div><div><br /></div><div>Para a parte 2, vou contar um pouquinho de como estão as coisas na TMR.</div>Carlos Henrique Agneshttp://www.blogger.com/profile/10084689043014290783noreply@blogger.com0tag:blogger.com,1999:blog-3937944417896230425.post-60975859335126561692018-03-07T08:15:00.000-08:002018-03-07T08:28:12.494-08:00DROP Wiki (English) #2 - Connecting to DBMSs<i>Você pode ler este post em português clicando <a href="http://www.taturs.com/2017/09/drop-wiki-2.html">aqui</a>.</i><br />
<br />
Continuing the DROP Wiki Series, the current topic is the connection establishment with a data source (usually a DBMS) and the choice of the best class to perform the task.<br />
<br />
Further on, we will see that for the DROP ORM to work, a few prerequisites are necessary. Of them all, the most important is to create an object of TAqDBConnection, and, trough it, to establish a connection with the data source.<br />
<br />
The TAqDBConnection class (in unit AqDrop.DB.Connection) is almost entirely abstract. This class goal is to abstract the minimum required to execute commands in the supported DBMSs. Obviously, this abstraction exists to provide the framework extension to different data access engines, being that we already have implementations for DBX and FireDAC.<br />
<br />
Basically, the interfaces provided by TAqDBConnection are:<br />
- Transaction manipulation routines;<br />
- Command preparing (Prepare e Unprepare);<br />
- Cursor opening routines;<br />
- Command execution routines (usually DMLs);<br />
<br />
The routines of transaction manipulation, command preparation and execution are not so different from the routines provided by any other data access engine (including third party components). The most significant difference is that of the cursor opening routines, which were built to provide interfaces similar to the readers in DBX Framework, providing a code that is more suitable to O.O. characteristics (summing up: no DataSets ;-)<br />
<br />
Aiming to split the specific code to support DBX and FireDAC, two classes were implemented and, as VCL style, both of them have the prefix 'Custom' on their names (TAqDBXCustomConnection e TAqFDCustomConnection), doing the heavy work so as to achieve their respective goals. Two direct inheritances, omitting the 'Custom' from their names (TAqDBXConnection e TAqFDConnection), have only the job of publishing the parameters provided by DROP and the mapped engines, in order to allow the complete configuration to access the desired DBMS.<br />
<br />
Our first example will use Interbase as the DBMS and DBX as the internal engine, so, we will use the generic class TAqDBXConnection, as shown in the example:<br />
<div>
<br /></div>
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<table><tbody>
<tr><td><pre style="line-height: 125%; margin: 0;"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25</pre>
</td><td><pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">function</span> <span style="color: #bb0066; font-weight: bold;">TfrmDW0002</span><span style="color: #333333;">.</span><span style="color: #0066bb; font-weight: bold;">GetConnection</span>
(<span style="color: #008800; font-weight: bold;">const</span> pDatabasePath<span style="color: #333333;">:</span> <span style="color: #008800; font-weight: bold;">string</span>)<span style="color: #333333;">:</span> TAqDBConnection<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">var</span>
lConnection<span style="color: #333333;">:</span> TAqDBXConnection<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">begin</span>
lConnection <span style="color: #333333;">:=</span> TAqDBXConnection<span style="color: #333333;">.</span>Create<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">try</span>
lConnection<span style="color: #333333;">.</span>DriverName <span style="color: #333333;">:=</span> <span style="background-color: #fff0f0;">'InterBase'</span><span style="color: #333333;">;</span>
lConnection<span style="color: #333333;">.</span>VendorLib <span style="color: #333333;">:=</span> <span style="background-color: #fff0f0;">'GDS32.DLL'</span><span style="color: #333333;">;</span>
lConnection<span style="color: #333333;">.</span>LibraryName <span style="color: #333333;">:=</span> <span style="background-color: #fff0f0;">'dbxint.dll'</span><span style="color: #333333;">;</span>
lConnection<span style="color: #333333;">.</span>GetDriverFunc <span style="color: #333333;">:=</span> <span style="background-color: #fff0f0;">'getSQLDriverINTERBASE'</span><span style="color: #333333;">;</span>
lConnection<span style="color: #333333;">.</span>Properties[TDBXPropertyNames<span style="color: #333333;">.</span>Database] <span style="color: #333333;">:=</span> pDatabasePath<span style="color: #333333;">;</span>
lConnection<span style="color: #333333;">.</span>Properties[TDBXPropertyNames<span style="color: #333333;">.</span>Username] <span style="color: #333333;">:=</span> <span style="background-color: #fff0f0;">'SYSDBA'</span><span style="color: #333333;">;</span>
lConnection<span style="color: #333333;">.</span>Properties[TDBXPropertyNames<span style="color: #333333;">.</span>Password] <span style="color: #333333;">:=</span> <span style="background-color: #fff0f0;">'masterkey'</span><span style="color: #333333;">;</span>
lConnection<span style="color: #333333;">.</span>DBXAdapter <span style="color: #333333;">:=</span> TAqDBXIBAdapter<span style="color: #333333;">.</span>Create<span style="color: #333333;">;</span>
lConnection<span style="color: #333333;">.</span>Connect<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">except</span>
lConnection<span style="color: #333333;">.</span>Free<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">raise</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
<span style="color: #007020;">Result</span> <span style="color: #333333;">:=</span> lConnection<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
</pre>
</td></tr>
</tbody></table>
</div>
<br />
The above example shows that to configuring a DROP connection or a TSQLConnection, for example, are similar tasks. However, a clear difference between the DROP connection and any other connection component provided by Delphi, is in the building of an adapter, which is necessary for a complete operation of the DROP features. The adapters tell DROP how to solve some tasks, or else, how to read some DBMS data types.<br />
<br />
As the DROP aims to work more as a library and less as a component, the above task can be simplified through the use of other set of classes, which easily wrap some distinctions of the supported DBMSs. Bellow we'll see the creation of a connection with the same database, however, using another class, which wraps DBX and the Interbase particularities.<br />
<div>
<br /></div>
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<table><tbody>
<tr><td><pre style="line-height: 125%; margin: 0;"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20</pre>
</td><td><pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">function</span> <span style="color: #bb0066; font-weight: bold;">TfrmDW0002</span><span style="color: #333333;">.</span><span style="color: #0066bb; font-weight: bold;">GetConnectionBySpecificClass</span>
(<span style="color: #008800; font-weight: bold;">const</span> pDatabasePath<span style="color: #333333;">:</span> <span style="color: #008800; font-weight: bold;">string</span>)<span style="color: #333333;">:</span> TAqDBConnection<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">var</span>
lConnection<span style="color: #333333;">:</span> TAqDBXIBConnection<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">begin</span>
lConnection <span style="color: #333333;">:=</span> TAqDBXIBConnection<span style="color: #333333;">.</span>Create<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">try</span>
lConnection<span style="color: #333333;">.</span>DataBase <span style="color: #333333;">:=</span> pDatabasePath<span style="color: #333333;">;</span>
lConnection<span style="color: #333333;">.</span>UserName <span style="color: #333333;">:=</span> <span style="background-color: #fff0f0;">'SYSDBA'</span><span style="color: #333333;">;</span>
lConnection<span style="color: #333333;">.</span>Password <span style="color: #333333;">:=</span> <span style="background-color: #fff0f0;">'masterkey'</span><span style="color: #333333;">;</span>
lConnection<span style="color: #333333;">.</span>Connect<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">except</span>
lConnection<span style="color: #333333;">.</span>Free<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">raise</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
<span style="color: #007020;">Result</span> <span style="color: #333333;">:=</span> lConnection<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
</pre>
</td></tr>
</tbody></table>
</div>
<div>
<br />
In the above example we can notice that the class TAqDBXIBConnection takes responsibility of configuring the properties as standards defines for Interbase, and exposes properties that are specific to IB. These properties allow us to statically setup some data like the GDB path, user and password, unlike the first example, where this information was dynamically provided.<br />
<br />
Well, this was the example using the Interbase, and examples with other DBMSs simply mean a little bit of the same, talking specifically of the code. However, it is important at least to provide the list of specialized classes already available in DROP, each of them setting up the connection as the known standards of the supported DBMSs, and providing their particular properties. Here goes the complete list of classes, grouped by the data access engine:<br />
<br />
DBX:<br />
- TAqDBXIBConnection;<br />
- TAqDBXMSSQLConnection;<br />
- TAqDBXMySQLConnection;<br />
- TAqDBXFBConnection;<br />
- TAqDBXOraConnection;<br />
- TAqDBXSQLiteConnection;<br />
<br />
FD:<br />
- TAqFDIBConnection;<br />
- TAqFDMSSQLConnection;<br />
- TAqFDMySQLConnection;<br />
- TAqFDFBConnection;<br />
- TAqFDOraConnection;<br />
- TAqFDSQLiteConnection;<br />
- TAqFDPGConnection;<br />
<br />
You may notice that FireDAC has an additional variation, which is PostgreSQL.<br />
<br />
And, for the time being, that will be all. As a follow-up, we will have the episode #3, which will show how to use these objects, and in future episodes, how to use them inside the ORM aspect.<br />
<br />
Until the next post!</div>
<div>
<br /></div>
Carlos Henrique Agneshttp://www.blogger.com/profile/10084689043014290783noreply@blogger.com0tag:blogger.com,1999:blog-3937944417896230425.post-51227435621666894292018-02-28T17:41:00.002-08:002018-03-08T16:09:28.196-08:00DROP Wiki #5 - Abstração de comandos SQLUma das premissas do DROP é fornecer interfaces uniformes para que o código seja escrito uma vez, e este opere sobre múltiplos SGBDs. O tema deste post é sobre um dos principais pilares do DROP para garantir a veracidade desta premissa, que são as interfaces de abstração de comandos SQL.<br />
<br />
Sabemos que os recursos oferecidas pelos SGDBs e respectivas DMLs são muito parecidos. Todos entregam praticamente as mesmas funcionalidades, por estruturas de SQLs ligeiramente diferentes.<br />
<br />
As units AqDrop.DB.SQL.Intf e AqDrop.DB.SQL fornecem, respectivamente, interfaces e classes que abstraem as funcionalidades de DML, sendo que as instâncias destas classes são traduzidas para a respectiva DML do SGBD apontado pela conexão do DROP que for executar o comando.<br />
<br />
Vamos começar por algo simples: '<i>select * from country</i>'. Sabemos que praticamente todo SGBD relacional aceitará este comando, desde que exista a uma tabela chamada <i>country</i> no esquema selecionado. O código abaixo demonstra como é simples usar as interfaces e classes de abstração de comandos SQL para executar o comando:<br />
<br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<table><tbody>
<tr><td><pre style="line-height: 125%; margin: 0;"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16</pre>
</td><td><pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">procedure</span> <span style="color: #bb0066; font-weight: bold;">TfrmDW0005</span><span style="color: #333333;">.</span><span style="color: #0066bb; font-weight: bold;">TestSelect</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">var</span>
lSelect<span style="color: #333333;">:</span> IAqDBSQLSelect<span style="color: #333333;">;</span>
lReader<span style="color: #333333;">:</span> IAqDBReader<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">begin</span>
MemoCountries<span style="color: #333333;">.</span>Lines<span style="color: #333333;">.</span>Clear<span style="color: #333333;">;</span>
MemoCountries<span style="color: #333333;">.</span>Lines<span style="color: #333333;">.</span>Add(<span style="background-color: #fff0f0;">'List of all registered contries:'</span>)<span style="color: #333333;">;</span>
lSelect <span style="color: #333333;">:=</span> TAqDBSQLSelect<span style="color: #333333;">.</span>Create(<span style="background-color: #fff0f0;">'country'</span>)<span style="color: #333333;">;</span>
lReader <span style="color: #333333;">:=</span> FEmployeeConnection<span style="color: #333333;">.</span>OpenQuery(lSelect)<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">while</span> lReader<span style="color: #333333;">.</span>Next <span style="color: #008800; font-weight: bold;">do</span>
<span style="color: #008800; font-weight: bold;">begin</span>
MemoCountries<span style="color: #333333;">.</span>Lines<span style="color: #333333;">.</span>Add(lReader<span style="color: #333333;">.</span>Values[<span style="background-color: #fff0f0;">'country'</span>]<span style="color: #333333;">.</span>AsString)<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
</pre>
</td></tr>
</tbody></table>
</div>
<br />
Detalhes importantes sobre o código acima:<br />
<ul>
<li>Note que a variável lSelect, que armazena a referência para o comando, é do tipo IAqDBSQLSelect;</li>
<li>Na linha 9, é instanciado um objeto do tipo <i>select</i>, onde a origem deste <i>select</i> (utilizada na cláusula <i>from</i>) é uma tabela de nome <i>country</i> (a origem pode ser também uma <i>view</i>, uma <i>string</i> contendo um <i>subselect</i>, ou um <i>subselect</i> na forma de outra interface do tipo IAqDBSQLSelect);</li>
<li>Não é informada nenhuma coluna de retorno no <i>select</i>, logo, o DROP assume o * como lista de colunas a serem retornadas;</li>
<li>Tanto o comando OpenQuery quanto o funcionamento do <i>reader</i> foram apresentados no <a href="http://www.taturs.com/2017/10/drop-wiki-3-instrucoes-sql-via-texto.html">DROP Wiki #3</a>, mas na oportunidade, a sobrecarga utilizada do comando foi um <i>select</i> escrito manualmente em uma constante <i>string</i>. Já neste caso, estamos vendo o uso da sobrecarga que recebe uma interface do tipo IAqDBSQLSelect (linha 11);</li>
<li>A partir do início do <i>while</i> segue a mesma lógica já apresentada no Wiki #3.</li>
</ul>
Vamos partir agora para um comando que continua simples, mas que já exige um <i>select</i> diferente para (quase) cada um dos SGDBs suportados, que é a limitação da quantidade de registros que devem ser retornados pelo <i>select</i>. Segue novo método que retorna no máximo 3 registros da tabela <i>country</i>:<br />
<div>
<br /></div>
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<table><tbody>
<tr><td><pre style="line-height: 125%; margin: 0;"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17</pre>
</td><td><pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">procedure</span> <span style="color: #bb0066; font-weight: bold;">TfrmDW0005</span><span style="color: #333333;">.</span><span style="color: #0066bb; font-weight: bold;">TestSelectLimited</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">var</span>
lSelect<span style="color: #333333;">:</span> IAqDBSQLSelect<span style="color: #333333;">;</span>
lReader<span style="color: #333333;">:</span> IAqDBReader<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">begin</span>
MemoCountries<span style="color: #333333;">.</span>Lines<span style="color: #333333;">.</span>Clear<span style="color: #333333;">;</span>
MemoCountries<span style="color: #333333;">.</span>Lines<span style="color: #333333;">.</span>Add(<span style="background-color: #fff0f0;">'List of up to 3 countries:'</span>)<span style="color: #333333;">;</span>
lSelect <span style="color: #333333;">:=</span> TAqDBSQLSelect<span style="color: #333333;">.</span>Create(<span style="background-color: #fff0f0;">'country'</span>)<span style="color: #333333;">;</span>
lSelect<span style="color: #333333;">.</span>Limit <span style="color: #333333;">:=</span> <span style="color: #0000dd; font-weight: bold;">3</span><span style="color: #333333;">;</span>
lReader <span style="color: #333333;">:=</span> FEmployeeConnection<span style="color: #333333;">.</span>OpenQuery(lSelect)<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">while</span> lReader<span style="color: #333333;">.</span>Next <span style="color: #008800; font-weight: bold;">do</span>
<span style="color: #008800; font-weight: bold;">begin</span>
MemoCountries<span style="color: #333333;">.</span>Lines<span style="color: #333333;">.</span>Add(lReader<span style="color: #333333;">.</span>Values[<span style="background-color: #fff0f0;">'country'</span>]<span style="color: #333333;">.</span>AsString)<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
</pre>
</td></tr>
</tbody></table>
</div>
<div>
<br /></div>
<div>
Ao executar o comando acima, o DROP traduz a informação para os recursos nativos de cada um dos SGDBs, limitando a quantidade de registros retornados.<br />
<br />
Visando uma melhor performance do comando, vamos tornar explícito que o <i>select</i> deve trazer somente a coluna <i>country</i> de cada registro, e somente para ampliar os recursos demonstrados, vamos fazer com que esta coluna seja retornada com o alias 'country_name'. Segue método demonstrando as alterações necessárias (para deixar claro, o alias não é obrigatório ao definir uma coluna):<br />
<br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<table><tbody>
<tr><td><pre style="line-height: 125%; margin: 0;"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18</pre>
</td><td><pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">procedure</span> <span style="color: #bb0066; font-weight: bold;">TfrmDW0005</span><span style="color: #333333;">.</span><span style="color: #0066bb; font-weight: bold;">TestSelectWithColumnAndAlias</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">var</span>
lSelect<span style="color: #333333;">:</span> IAqDBSQLSelect<span style="color: #333333;">;</span>
lReader<span style="color: #333333;">:</span> IAqDBReader<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">begin</span>
MemoCountries<span style="color: #333333;">.</span>Lines<span style="color: #333333;">.</span>Clear<span style="color: #333333;">;</span>
MemoCountries<span style="color: #333333;">.</span>Lines<span style="color: #333333;">.</span>Add(<span style="background-color: #fff0f0;">'List of up to 3 countries:'</span>)<span style="color: #333333;">;</span>
lSelect <span style="color: #333333;">:=</span> TAqDBSQLSelect<span style="color: #333333;">.</span>Create(<span style="background-color: #fff0f0;">'country'</span>)<span style="color: #333333;">;</span>
lSelect<span style="color: #333333;">.</span>AddColumn(<span style="background-color: #fff0f0;">'country'</span><span style="color: #333333;">,</span> <span style="background-color: #fff0f0;">'country_name'</span>)<span style="color: #333333;">;</span>
lSelect<span style="color: #333333;">.</span>Limit <span style="color: #333333;">:=</span> <span style="color: #0000dd; font-weight: bold;">3</span><span style="color: #333333;">;</span>
lReader <span style="color: #333333;">:=</span> FEmployeeConnection<span style="color: #333333;">.</span>OpenQuery(lSelect)<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">while</span> lReader<span style="color: #333333;">.</span>Next <span style="color: #008800; font-weight: bold;">do</span>
<span style="color: #008800; font-weight: bold;">begin</span>
MemoCountries<span style="color: #333333;">.</span>Lines<span style="color: #333333;">.</span>Add(lReader<span style="color: #333333;">.</span>Values[<span style="background-color: #fff0f0;">'country_name'</span>]<span style="color: #333333;">.</span>AsString)<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
</pre>
</td></tr>
</tbody></table>
</div>
<br />
Também no <a href="http://www.taturs.com/2017/10/drop-wiki-3-instrucoes-sql-via-texto.html">DROP Wiki #3</a> comentei que o objetivo de um ORM não é fazer com que o usuário escreva manualmente os comandos SQL. Pois bem, o objetivo do DROP também não é fazer o desenvolvedor criar os próprios comandos de SQL através destas interfaces e classes. Então, por que fiz questão de passar por este conteúdo antes de chegar no ORM propriamente dito?<br />
<br />
Eventualmente (ou algo com frequência muito maior que eventualmente), teremos que customizar os comandos que serão disparados contra o SGDB. Para fazer esta customização, o DROP conta diversas variações e recursos, no entanto, a variação mais indicada passa por conhecermos as interfaces de abstração de SQLs.<br />
<br />
Mais adiante veremos que o ORM do DROP pode nos retornar objetos instanciados e configurados para as interfaces dos tipos IAqDBSQLSelect, IAqDBSQLInsert, IAqDBSQLUpdate e IAqDBSQLDelete. Manipular estas referências já devidamente configuradas é a maneira mais rápida e simples para customizar os comandos enviados para o SGDB.<br />
<br />
Através destas interfaces, é possível realizar uma série de customizações, como adicionar cláusulas <i>where</i>, <i>joins</i> (use com moderação, afinal você está em um ambiente que visa o uso do ORM ;-), funções de agregação de dados, ordenação, etc. E sempre que for necessário mudar o texto resultante do comando de DML, o DROP faz isso por você.<br />
<br />
Segue uma última variação do método de busca de países, onde uma cláusula <i>where</i> é adicionada, trazendo somente países em que a moeda seja o Euro:<br />
<br /></div>
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<table><tbody>
<tr><td><pre style="line-height: 125%; margin: 0;"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17</pre>
</td><td><pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">procedure</span> <span style="color: #bb0066; font-weight: bold;">TfrmDW0005</span><span style="color: #333333;">.</span><span style="color: #0066bb; font-weight: bold;">TestSelectWithCondition</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">var</span>
lSelect<span style="color: #333333;">:</span> IAqDBSQLSelect<span style="color: #333333;">;</span>
lReader<span style="color: #333333;">:</span> IAqDBReader<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">begin</span>
MemoCountries<span style="color: #333333;">.</span>Lines<span style="color: #333333;">.</span>Clear<span style="color: #333333;">;</span>
MemoCountries<span style="color: #333333;">.</span>Lines<span style="color: #333333;">.</span>Add(<span style="background-color: #fff0f0;">'List of countries where the currency is Euro:'</span>)<span style="color: #333333;">;</span>
lSelect <span style="color: #333333;">:=</span> TAqDBSQLSelect<span style="color: #333333;">.</span>Create(<span style="background-color: #fff0f0;">'country'</span>)<span style="color: #333333;">;</span>
lSelect<span style="color: #333333;">.</span>CustomizeCondition<span style="color: #333333;">.</span>AddColumnEqual(<span style="background-color: #fff0f0;">'currency'</span><span style="color: #333333;">,</span> <span style="background-color: #fff0f0;">'Euro'</span>)<span style="color: #333333;">;</span>
lReader <span style="color: #333333;">:=</span> FEmployeeConnection<span style="color: #333333;">.</span>OpenQuery(lSelect)<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">while</span> lReader<span style="color: #333333;">.</span>Next <span style="color: #008800; font-weight: bold;">do</span>
<span style="color: #008800; font-weight: bold;">begin</span>
MemoCountries<span style="color: #333333;">.</span>Lines<span style="color: #333333;">.</span>Add(lReader<span style="color: #333333;">.</span>Values[<span style="background-color: #fff0f0;">'country'</span>]<span style="color: #333333;">.</span>AsString)<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
</pre>
</td></tr>
</tbody></table>
</div>
<div>
<br /></div>
<div>
Sobre o método acima, é importante dizer que foi utilizado o método AddColumnEqual, que monta uma condição com o operador de igualdade entre valores, mas existem diversos outros métodos que mudam o operador a ser utilizado. Cada um destes métodos possui várias sobrecargas, sendo que cada uma das sobrecargas permite o uso de tipos primitivos para seus respectivos fins, e o DROP traduz o tipo primitivo do Delphi para o respectivo tipo primitivo do SGDB, se este existir.<br />
<br />
Por exemplo, alguns SGDBs trazem suporte nativo ao tipo <i>Boolean</i>, no entanto, o uso deste tipo varia de SGDB para SGDB. Em alguns deles a constante <i>True</i> se escreve desta forma, em outros se escreve como se fosse uma <i>string</i> ('True'), e em outros ela sequer existe. Para todos estes casos, o DROP faz a devida tradução para a constante do SGDB utilizado (ou para o formato padrão, como no caso de datas), e para os SGDBs sem suporte a esta constante, o DROP propõe outras como 1 ou 'T'. E se você não estiver satisfeito com estas propostas, você ainda pode informar ao DROP como traduzir cada um dos tipos de dados do Delphi para os tipos de dados do seu SGDB.<br />
<br />
Finalizando, segue uma pequena demonstração destas variações de métodos e suas sobrecargas:<br />
<br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<table><tbody>
<tr><td><pre style="line-height: 125%; margin: 0;"> 1
2
3
4
5
6
7
8
9
10
11
12
13</pre>
</td><td><pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">procedure</span> <span style="color: #bb0066; font-weight: bold;">TfrmDW0005</span><span style="color: #333333;">.</span><span style="color: #0066bb; font-weight: bold;">ShowSQL</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">var</span>
lSelect<span style="color: #333333;">:</span> IAqDBSQLSelect<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">begin</span>
lSelect <span style="color: #333333;">:=</span> TAqDBSQLSelect<span style="color: #333333;">.</span>Create(<span style="background-color: #fff0f0;">'any_table'</span>)<span style="color: #333333;">;</span>
lSelect<span style="color: #333333;">.</span>CustomizeCondition<span style="color: #333333;">.</span>AddColumnEqual(<span style="background-color: #fff0f0;">'intcolumn'</span><span style="color: #333333;">,</span> <span style="color: #0000dd; font-weight: bold;">1</span>)<span style="color: #333333;">.</span>
AddColumnEqual(<span style="background-color: #fff0f0;">'boolcolumn'</span><span style="color: #333333;">,</span> <span style="color: #008800; font-weight: bold;">True</span>)<span style="color: #333333;">.</span>
AddColumnGreaterEqualThan(<span style="background-color: #fff0f0;">'datecolumn'</span><span style="color: #333333;">,</span> <span style="color: #007020;">EncodeDate</span>(<span style="color: #0000dd; font-weight: bold;">2018</span><span style="color: #333333;">,</span> <span style="color: #0000dd; font-weight: bold;">2</span><span style="color: #333333;">,</span> <span style="color: #0000dd; font-weight: bold;">28</span>))<span style="color: #333333;">.</span>
AddColumnIsNull(<span style="background-color: #fff0f0;">'nullablecolumn'</span>)<span style="color: #333333;">;</span>
ShowMessage(FEmployeeConnection<span style="color: #333333;">.</span>Adapter<span style="color: #333333;">.</span>SQLSolver<span style="color: #333333;">.</span>SolveSelect(lSelect))<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
</pre>
</td></tr>
</tbody></table>
</div>
<br />
E o resultado obtido (formatado para melhor leitura):<br />
<br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<table><tbody>
<tr><td><pre style="line-height: 125%; margin: 0;">1
2
3
4
5
6
7
8
9</pre>
</td><td><pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">select</span>
<span style="color: #333333;">*</span>
<span style="color: #008800; font-weight: bold;">from</span>
any_table
<span style="color: #008800; font-weight: bold;">where</span> (
intcolumn <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">1</span> <span style="color: #008800; font-weight: bold;">and</span>
boolcolumn <span style="color: #333333;">=</span> <span style="color: #008800; font-weight: bold;">True</span> <span style="color: #008800; font-weight: bold;">and</span>
datecolumn <span style="color: #333333;">>=</span> <span style="background-color: #fff0f0;">'2018.02.28 00:00:00:000'</span> <span style="color: #008800; font-weight: bold;">and</span>
nullablecolumn <span style="color: #008800; font-weight: bold;">is</span> <span style="color: #008800; font-weight: bold;">null</span>)
</pre>
</td></tr>
</tbody></table>
</div>
<br />
<br />
E para o momento era isto! Em algum momento da série voltaremos às interfaces de abstração para cobrir todas as variações implementadas, mas acredito que o conteúdo até aqui descrito já seja suficiente para orientar o usuário do DROP, mostrando de onde estas interfaces vêm, como vivem, como se reproduzem, e do que se alimentam.<br />
<br />
Até o próximo episódio!<br />
<br />
<table style="width: 100%;">
<tbody>
<tr>
<td><a href="http://www.taturs.com/2017/11/drop-wiki-4-transacoes.html">Episódio Anterior</a></td>
<td style="text-align: right;"></td>
</tr>
</tbody></table>
</div>
Carlos Henrique Agneshttp://www.blogger.com/profile/10084689043014290783noreply@blogger.com0tag:blogger.com,1999:blog-3937944417896230425.post-10618820998857881022018-01-30T06:48:00.000-08:002018-01-30T06:48:15.049-08:00DROP Wiki (English) #1 - Introduction<i>Você pode ler este post em português clicando <a href="http://www.taturs.com/2017/06/drop-wiki-1.html">aqui</a>.</i><br />
<br />
With the main goal of providing large documentation about the DROP, I'll start the series DROP Wiki, and as lots of conversations about the framework start with the question "What is the DROP?", nothing better than to start the series by trying to answer this question.<br />
<br />
Using the shortest possible answer, the DROP is a set of classes built in Delphi, to make the daily tasks of the developer easier. A bunch of these classes have been developed to support their own ORM framework (object relational mapping), and it is mainly for fulfilling this goal that the DROP is best known.<br />
<br />
Another great thing about the DROP is that it is a totally free and open source (MIT license), and if you are already interested in downloading or using it, you can do it through <a href="https://github.com/AquasoftTI/AqDrop">GitHub</a>, or by downloading the source in a compacted file using <a href="http://www.aquasoft.com.br/site/drop/AqDrop.zip">this link</a>. Now, lets break the DROP down a little further.<br />
<br />
I remember that, while developing/rewriting the DROP, for many times I have talked with my teammates at Aquasoft, or among other developers (as my friend Muka), and the subject of these conversations was the reason of the DROP having been divided into some layers, each of them with one responsibility. Understanding these layers can make the understanding of the whole DROP easier:<br />
<ul>
<li>Core: contains useful classes for several tasks, with generic development purposes. On this layer there's nothing implemented to access DBMSs. To tell you the truth, some classes are not even used directly or indirectly in ORM tasks;</li>
<li>DB: the classes contained here abstract the communication with DBMSs, and therefore, many of these classes are abstract as well, providing uniform structures, that further allows to DROP write code once, however compatible with the supported DBMSs. Even though on this level there aren't concrete classes to access data, there are lots of specific classes to some DBMSs, like the classes that solve the SQL objects, translating them into the specific language of each of the supported DBMSs;</li>
<li>ORM: contains the ORM classes, proper. They transform classes structures and their attributes to SQL objects, as enable those entities objects to be persisted and retrieved from the DBMSs;</li>
<li>ORM Base (I still think that this name needs a facelift from a marketing department ;-): the ORM layer doesn't requier that the classes to be mapped inherit from the DROP classes, however, the DROP provides, by this layer, some classes that can be extended, reducing the developer work while doing the ORM.</li>
</ul>
The Core layer presents all its units in a namesake package, being that all other layers are implemented in a package called DB. It is important to emphasize that all classes contained in these packages are free from specific any data access engines.<br />
<br />
To perform the physical data access, the DROP can work with both DBX Framework or FireDAC. It is up to the developer to use one technology or the other. Therefore, each of the implementation of the DROP to the above technologies has received its own package.<br />
<br />
Talking about physical data access, the DROP currently supports seven relational DBMSs:<br />
<div>
<ul>
<li>Interbase;</li>
<li>Oracle;</li>
<li>Microsoft SQL Server;</li>
<li>PostgreSQL (only by FireDAC);</li>
<li>MySQL;</li>
<li>Firebird;</li>
<li>SQLite (ok, not really a DBMS, but...).</li>
</ul>
</div>
<div>
Concluding, if it were possible to summarize the above content in an image, it would be something like this:</div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg538UoNp0x8oyqBo058GI4GDn7mpq8CJzYiTFqylO8Z3JaB26wyrythKJhCYdgEunTZmu7SnQABom9yNjynU70Lq5KFHUbOHZNOjgVnKURejdt_48r4_fcI0gtwj37ZmMTmE0ArZn4bmLb/s1600/Captura+de+Tela+2017-10-26+a%25CC%2580s+22.49.02.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="832" data-original-width="1147" height="290" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg538UoNp0x8oyqBo058GI4GDn7mpq8CJzYiTFqylO8Z3JaB26wyrythKJhCYdgEunTZmu7SnQABom9yNjynU70Lq5KFHUbOHZNOjgVnKURejdt_48r4_fcI0gtwj37ZmMTmE0ArZn4bmLb/s400/Captura+de+Tela+2017-10-26+a%25CC%2580s+22.49.02.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both;">
Finishing this post, the sequence of these serie are still being written (some of the Portuguese posts are already published, and I'll work in the translation ASAP). The next posts will cover the above topics alternating topics between all the DROP layers.</div>
<div class="separator" style="clear: both;">
<br /></div>
<div class="separator" style="clear: both;">
Thank you for reading! See ya!</div>
</div>
Carlos Henrique Agneshttp://www.blogger.com/profile/10084689043014290783noreply@blogger.com0tag:blogger.com,1999:blog-3937944417896230425.post-79107261101493649412017-11-07T07:14:00.001-08:002018-03-08T16:09:25.098-08:00DROP Wiki #4 - TransaçõesO <i>post</i> de hoje é extremamente simples, mas sobre algo muito importante: Transações!<br />
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjX0nFojjgCPZjsdOmwuai6gwub2cRvCu30NKmE09tqq3FPJHZKFyBSQDadR0qBJbQpSn1kv9Vh_Ky3OF1m0543XVwbQL_4BaN5jiNMRMzrkbMeqrxJmmb8SiLlufsHxHVlgnIBrFvpKmzS/s1600/drop+and+transactions.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="333" data-original-width="820" height="129" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjX0nFojjgCPZjsdOmwuai6gwub2cRvCu30NKmE09tqq3FPJHZKFyBSQDadR0qBJbQpSn1kv9Vh_Ky3OF1m0543XVwbQL_4BaN5jiNMRMzrkbMeqrxJmmb8SiLlufsHxHVlgnIBrFvpKmzS/s320/drop+and+transactions.png" width="320" /></a></div>
<br />
<br />
O sistema de transações do DROP trabalha com o conceito de chamadas cumulativas. E o que isto quer dizer?<br />
<i><br />Nota: O exemplo a seguir é uma versão resumida do que podemos encontrar em produção, mas demonstra bem o conceito do sistema de transações do DROP (não queime neurônios discutindo se você resolveria com uma estrutura de classes diferentes ou não, se concentre no recurso apresentado).</i><br />
<br />
Começaremos com uma classe de nome TProduto. Esta possui um método que, entre outros, trata a movimentação do estoque deste produto. Toda movimentação deve atualizar o campo de saldo de estoque do produto, e também incluir um registro de detalhamento da movimentação. Este método deve ser auto-suficiente, e consequentemente, se responsabilizar pela garantia de que os dados armazenados são consistentes, o que com certeza demandará o uso de transação com o banco, concorda? Se você concorda, este método seria escrito mais ou menos assim:<br />
<br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<table><tbody>
<tr><td><pre style="line-height: 125%; margin: 0;"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15</pre>
</td><td><pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">procedure</span> <span style="color: #bb0066; font-weight: bold;">TProduto</span><span style="color: #333333;">.</span><span style="color: #0066bb; font-weight: bold;">Movimentar</span>(<span style="color: #008800; font-weight: bold;">const</span> pIDDocumento<span style="color: #333333;">:</span> UInt32<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">const</span> pMovimentacao<span style="color: #333333;">:</span> <span style="color: #333399; font-weight: bold;">Currency</span>)<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">begin</span>
ConexaoDoDROP<span style="color: #333333;">.</span>StartTransaction<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">try</span>
ConexaoDoDROP<span style="color: #333333;">.</span>ExecuteCommand(<span style="background-color: #fff0f0;">'update estoque_produto ...'</span>)<span style="color: #333333;">;</span>
ConexaoDoDROP<span style="color: #333333;">.</span>ExecuteCommand(<span style="background-color: #fff0f0;">'insert into movimento_estoque ...'</span>)<span style="color: #333333;">;</span>
ConexaoDoDROP<span style="color: #333333;">.</span>CommitTransaction<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">except</span>
ConexaoDoDROP<span style="color: #333333;">.</span>RollbackTransaction<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">raise</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
</pre>
</td></tr>
</tbody></table>
</div>
<br />
Pois bem, imagine que outra classe, de nome TVenda, possui um método responsável por consolidar uma venda de produtos no banco de dados. Este método registra os dados da venda em diversas tabelas, e como neste momento a venda está sendo consolidada, o estoque dos produtos também deve ser movimentado. Como bom programador, você deve estar pensando em reutilizar o método anterior para persistir a nova posição do estoque, certo? Vamos ao código de TVenda.Consolidar:<br />
<br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<table><tbody>
<tr><td><pre style="line-height: 125%; margin: 0;"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21</pre>
</td><td><pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">procedure</span> <span style="color: #bb0066; font-weight: bold;">TVenda</span><span style="color: #333333;">.</span><span style="color: #0066bb; font-weight: bold;">Consolidar</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">var</span>
lItem<span style="color: #333333;">:</span> TVendaItem<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">begin</span>
ConexaoDoDROP<span style="color: #333333;">.</span>StartTransaction<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">try</span>
ConexaoDoDROP<span style="color: #333333;">.</span>ExecuteCommand(<span style="background-color: #fff0f0;">'insert into venda ...'</span>)<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">for</span> lItem <span style="color: #008800; font-weight: bold;">in</span> Itens <span style="color: #008800; font-weight: bold;">do</span>
<span style="color: #008800; font-weight: bold;">begin</span>
ConexaoDoDROP<span style="color: #333333;">.</span>ExecuteCommand(<span style="background-color: #fff0f0;">'insert into venda_item ...'</span>)<span style="color: #333333;">;</span>
lItem<span style="color: #333333;">.</span>Produto<span style="color: #333333;">.</span>Movimentar(<span style="color: #008800; font-weight: bold;">Self</span><span style="color: #333333;">.</span>ID<span style="color: #333333;">,</span> lItem<span style="color: #333333;">.</span>Quantidade)<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
ConexaoDoDROP<span style="color: #333333;">.</span>CommitTransaction<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">except</span>
ConexaoDoDROP<span style="color: #333333;">.</span>RollbackTransaction<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">raise</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
</pre>
</td></tr>
</tbody></table>
</div>
<br />
Muitos desenvolvedores optam por esta solução. No entanto, o que acontece com a sua <i>engine</i> de acesso a dados se você chamar uma segunda vez o comando de início de transação, sem ter terminado a transação anterior? Algumas <i>engines</i> não suportam esta técnica, e portanto, várias alternativas de <i>workaround</i> normalmente são implementadas, como testar se a conexão já possui uma transação aberta, ou delegar a abertura da transação para outro método, entre outras.<br />
<br />
O sistema de chamadas cumulativas de transações do DROP permite que o comando de início da transação possa ser chamado mais de uma vez, sem que tenha que existir o desfecho da transação entre estas chamadas. Claro que, para que este sistema faça sentido, todas as chamadas de início de transação devem ser finalizadas também cumulativamente.<br />
<br />
Concluindo, o DROP permite que, tanto o código de TProduto.Movimentar possa ser chamado individualmente, quanto possa ser reutilizado em outras rotinas já com transação aberta, sem que você precise escrever qualquer desvio para que isto tudo aconteça.<br />
<br />
Era isto, até o próximo <i>post</i>!<br />
<br />
<table style="width: 100%;">
<tbody>
<tr>
<td><a href="http://www.taturs.com/2017/10/drop-wiki-3-instrucoes-sql-via-texto.html">Episódio Anterior</a></td>
<td style="text-align: right;"><a href="http://www.taturs.com/2018/02/drop-wiki-5-abstracao-de-comandos-sql.html">Próximo Episódio</a></td>
</tr>
</tbody></table>
Carlos Henrique Agneshttp://www.blogger.com/profile/10084689043014290783noreply@blogger.com2tag:blogger.com,1999:blog-3937944417896230425.post-66690918466738526082017-11-03T07:42:00.000-07:002017-11-03T15:33:27.887-07:00DROP 1.3.1 - Edição Especial Embarcadero Conference 2017<br />
Conforme anunciado antes mesmo do evento, saiu a nova versão do DROP, em edição especial para a Embarcadero Conference 2017. A nova versão está liberada nos tradicionais canais de distribuição:<br />
<br />
<ul>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiixK3z7uj2Q63kL-gawEdoVE1iaZwv3KbX7pDBK6i3bmKD4RV-Rv1pnDkm_AWYFNds-GZxw6sqAcKd3KsZb5AD2Zmv99xW0eRr-M9xTJaJEhZnqH2wqJn88EIuSPhEoQZxs5hqmep4aCgI/s1600/DROP131.PNG" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="440" data-original-width="320" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiixK3z7uj2Q63kL-gawEdoVE1iaZwv3KbX7pDBK6i3bmKD4RV-Rv1pnDkm_AWYFNds-GZxw6sqAcKd3KsZb5AD2Zmv99xW0eRr-M9xTJaJEhZnqH2wqJn88EIuSPhEoQZxs5hqmep4aCgI/s320/DROP131.PNG" width="232" /></a>
<li><a href="http://www.aquasoft.com.br/site/produtos">Página de produtos da Aquasoft (arquivo zip);</a></li>
<li><a href="http://github.com/AquasoftTI/AqDrop">No repositório do GitHub;</a></li>
</ul>
<br />
Os esforços para esta versão se concentraram no suporte ao Interbase (nova <i>feature</i>), total tradução dos testes automatizados para a nova plataforma de testes, e claro, diversas pequenas melhorias foram realizadas.<br />
<br />
Quer ajudar a desenvolver o DROP? Fique à vontade para enviar Pull Requests pelo GitHub.<br />
<br />
Tem dúvidas de como usar o DROP ou quer entrar em contato para trocar ideias? Por favor, envie seu e-mail para drop@aquasoft.com.br.<br />
<br />
E para fechar, novos posts sobre o DROP já estão em produção. Aguarde, pois muitas novidades estão por vir!!!Carlos Henrique Agneshttp://www.blogger.com/profile/10084689043014290783noreply@blogger.com0tag:blogger.com,1999:blog-3937944417896230425.post-89468354594638145972017-10-26T08:12:00.000-07:002017-10-26T15:42:43.877-07:00Embarcadero Conference 2017Hoje estou dando uma passada rápida aqui só para registrar que a Embarcadero Conference deste ano foi demais!!!<br />
<br />
Obrigado a todos os participantes, especialmente aos que prestigiaram minhas apresentações! Me sinto honrado em merecer a atenção de vocês!<br />
<br />
<br />
Nota importante: A versão especial do DROP para a Embarcadero Conference (1.3.1 - conforme prometido) já foi publicada. Os participantes do evento receberão via e-mail as instruções de como obtê-la.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJiErbCjaOSJHghEpZpBrve-WcPsvbujNv93VoSGjDMUrW0wH28LWzChaObp0p5xQo3jHYbYnVB9mTgK2Ko8NdjsJAO5Cj5LZqMMfo1-IfJztPdf28kMnASzJHmD3gj_lOWUe3CpITmVro/s1600/geral.jpeg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="960" data-original-width="1280" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJiErbCjaOSJHghEpZpBrve-WcPsvbujNv93VoSGjDMUrW0wH28LWzChaObp0p5xQo3jHYbYnVB9mTgK2Ko8NdjsJAO5Cj5LZqMMfo1-IfJztPdf28kMnASzJHmD3gj_lOWUe3CpITmVro/s400/geral.jpeg" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Auditório principal durante a abertura do evento.</td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><img border="0" data-original-height="960" data-original-width="1280" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhF0bHgb5jj_nDav8FkRCsxFXCJV5Ni_G1mr10cCiJEgx68upwmEH7E_bWRmsPyUWL-RaoaTArkAoHeItbZHfVSqkKt0W0_QX5yUkENJ8lDuOPJXthksMmrfKPDQS2wYJ88vYmpAjbY7Ymw/s400/sagua%25CC%2583o.jpeg" style="margin-left: auto; margin-right: auto;" width="400" /></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Momento de break, e muito networking.</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhF0bHgb5jj_nDav8FkRCsxFXCJV5Ni_G1mr10cCiJEgx68upwmEH7E_bWRmsPyUWL-RaoaTArkAoHeItbZHfVSqkKt0W0_QX5yUkENJ8lDuOPJXthksMmrfKPDQS2wYJ88vYmpAjbY7Ymw/s1600/sagua%25CC%2583o.jpeg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"></a></div>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQauNFkeDoTCCRfg0pOZv9wY0o4owtXVQY7bLRv8z_Cd7BuEVkiDPUgG-Q8pV4EW2kfKMvVtHzL0zDl1GwDCRarDaq_JMUeUSxONT37PbeaOJPt-Gos4EBa4hwUjB3-lCRKsmh41zzfUB5/s1600/IMG_2826.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1600" data-original-width="1200" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiQauNFkeDoTCCRfg0pOZv9wY0o4owtXVQY7bLRv8z_Cd7BuEVkiDPUgG-Q8pV4EW2kfKMvVtHzL0zDl1GwDCRarDaq_JMUeUSxONT37PbeaOJPt-Gos4EBa4hwUjB3-lCRKsmh41zzfUB5/s400/IMG_2826.jpg" width="300" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Durante a minha primeira apresentação.</td></tr>
</tbody></table>
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgctiAHaXnINhBAGKVF0yK5EkrG96vpv3L52jUl4xt_AykZv8SJul7jwOWz5KoB7Ai59ae9s5grfd1-Xnr1lKBD1QWkDhZ9fsrTIadenxi2pOlKhuXgC6pbaeQO4RT7-28HgT64bfIF9KI3/s1600/IMG_2820.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="1200" data-original-width="1600" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgctiAHaXnINhBAGKVF0yK5EkrG96vpv3L52jUl4xt_AykZv8SJul7jwOWz5KoB7Ai59ae9s5grfd1-Xnr1lKBD1QWkDhZ9fsrTIadenxi2pOlKhuXgC6pbaeQO4RT7-28HgT64bfIF9KI3/s400/IMG_2820.jpg" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Meu muito obrigado aos expectadores!</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiERkX7kT4ySzWzQVFWjCbEOYm7SyPBCxMHNQZnkfgnz4ZkV86G6xR5acVddk5JUhYd7TJSY451HLcgjSYMw6zycymT7UYT685iMLDw-onCQCQqVnSRhyphenhyphenGQatYNR5tfWCjCNwAePLmFqgbQ/s1600/foto_geral.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" data-original-height="540" data-original-width="960" height="225" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiERkX7kT4ySzWzQVFWjCbEOYm7SyPBCxMHNQZnkfgnz4ZkV86G6xR5acVddk5JUhYd7TJSY451HLcgjSYMw6zycymT7UYT685iMLDw-onCQCQqVnSRhyphenhyphenGQatYNR5tfWCjCNwAePLmFqgbQ/s400/foto_geral.jpg" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Tradicional foto com os palestrantes e MVPs.</td></tr>
</tbody></table>
<br />
<br class="Apple-interchange-newline" />
Embarcadero Conference 2018, nos aguarde!<br />
<div>
<br /></div>
Carlos Henrique Agneshttp://www.blogger.com/profile/10084689043014290783noreply@blogger.com0tag:blogger.com,1999:blog-3937944417896230425.post-82486433289829307662017-10-06T20:03:00.000-07:002018-03-08T16:09:23.250-08:00DROP Wiki #3 - Instruções SQL via textoPor mais que um ORM tenha o objetivo de não escrever explicitamente instruções SQL, usuários novos de ORMs tendem a não aceitar uma ferramenta que não permita usar uma instrução SQL escrita manualmente. Em outras palavras, a aceitação de um framework com suporte a ORM passa por também suportar SQLs via texto, é quase que uma válvula de escape para desenvolvedores que não dominam ou até mesmo não confiam 100% na técnica.<br />
<br />
No post anterior, foi apresentada a lista de classes nativas do DROP para estabelecimento de conexões com os SGBDs suportados. Como estratégia de evolução na apresentação e uso dos recursos do DROP, este post demonstrará como conversar com o SGBD, via instruções SQL escritas manualmente.<br />
<br />
Os exemplos a seguir serão implementados sobre o Interbase, mas como já mencionado no post anterior, os recursos apresentados aqui estão disponíveis para todos os SGBDs suportados pelo DROP. Para os exemplos abaixo, assuma que já existe um objeto de conexão instanciado, e apontando para a tradicional base de exemplos <i>Employee</i>.<br />
<br />
Inicialmente, o DROP não possui componentes ou objetos a parte para executar os comandos, como os tradicionais TSQLQuery, TFDQuery, entre outros. Todos os acessos e manipulações de dados são executados diretamente a partir do objeto de conexão com o SGBD.<br />
<br />
Para começar, vamos buscar dados através de um <i>select</i> simples. As instruções SQL que retornam cursores são executadas através do método OpenQuery. Uma das sobrecargas do OpenQuery permite passar diretamente o texto de um <i>select</i> (demais sobrecargas serão demonstradas em outro post). Todas as sobrecargas do método OpenQuery retornam uma implementação da interface IAqDBReader.<br />
<br />
A interface IAqDBReader foi especificada visando ser uma camada de acesso muito fina entre o seu código e os dados do cursor aberto pela instrução SQL. Portanto, o retorno não faz cache, e é unidirecional. Também é muito importante dizer que a leitura do primeiro registro passa obrigatoriamente pela primeira chamada do método Next no reader (ao estilo DBX Framework e <i>readers</i> de outras linguagens). E por fim, existem duas maneiras de ler colunas do cursor, as tradicionais referências por índice ou nome das mesmas.<br />
<br />
O exemplo abaixo demonstra a leitura de todos os países da base, e então a alimentação de um componente memo com cada um dos nomes retornados.<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<table><tbody>
<tr><td><pre style="line-height: 125%; margin: 0;"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14</pre>
</td><td><pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">procedure</span> <span style="color: #bb0066; font-weight: bold;">TfrmExemplos</span><span style="color: #333333;">.</span><span style="color: #0066bb; font-weight: bold;">btnSelectClick</span>(Sender<span style="color: #333333;">:</span> <span style="color: #333399; font-weight: bold;">TObject</span>)<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">var</span>
lReader<span style="color: #333333;">:</span> IAqDBReader<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">begin</span>
mmoResultados<span style="color: #333333;">.</span>Lines<span style="color: #333333;">.</span>Clear<span style="color: #333333;">;</span>
lReader <span style="color: #333333;">:=</span> FConexao<span style="color: #333333;">.</span>OpenQuery(<span style="background-color: #fff0f0;">'select country from country'</span>)<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">while</span> lReader<span style="color: #333333;">.</span>Next <span style="color: #008800; font-weight: bold;">do</span>
<span style="color: #008800; font-weight: bold;">begin</span>
<span style="color: #888888;">// mmoResultados.Lines.Add(lReader.Values[0].AsString);</span>
mmoResultados<span style="color: #333333;">.</span>Lines<span style="color: #333333;">.</span>Add(lReader<span style="color: #333333;">.</span>Values[<span style="background-color: #fff0f0;">'country'</span>]<span style="color: #333333;">.</span>AsString)<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
</pre>
</td></tr>
</tbody></table>
</div>
<br />
Note que no laço de alimentação do memo constam duas linhas. A primeira linha, que está comentada e, portanto, sem efeito, o índice da coluna seria usado para referenciá-la, e na segunda linha, acessamos o valor da coluna através do seu nome.<br />
<br />
Aos que não estão habituados com este conceito de <i>reader</i>, é necessário salientar que o método Next já é responsável por informar se o cursor chegou ao seu fim ou não, fazendo com que o teste de quebra do laço realize a troca do registro apontado pelo cursor.<br />
<br />
O próximo exemplo visa demonstrar uma variação do exemplo acima, desta vez criando um parâmetro para execução da consulta.<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<table><tbody>
<tr><td><pre style="line-height: 125%; margin: 0;"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18</pre>
</td><td><pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">procedure</span> <span style="color: #bb0066; font-weight: bold;">TfrmExemplos</span><span style="color: #333333;">.</span><span style="color: #0066bb; font-weight: bold;">btnSelectComParametrosClick</span>(Sender<span style="color: #333333;">:</span> <span style="color: #333399; font-weight: bold;">TObject</span>)<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">var</span>
lReader<span style="color: #333333;">:</span> IAqDBReader<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">begin</span>
mmoResultados<span style="color: #333333;">.</span>Lines<span style="color: #333333;">.</span>Clear<span style="color: #333333;">;</span>
lReader <span style="color: #333333;">:=</span> FConexao<span style="color: #333333;">.</span>OpenQuery(
<span style="background-color: #fff0f0;">'select country from country where currency = :currency'</span><span style="color: #333333;">,</span>
<span style="color: #008800; font-weight: bold;">procedure</span>(pParametros<span style="color: #333333;">:</span> IAqDBParameters)
<span style="color: #008800; font-weight: bold;">begin</span>
pParametros[<span style="background-color: #fff0f0;">'currency'</span>]<span style="color: #333333;">.</span>AsString <span style="color: #333333;">:=</span> <span style="background-color: #fff0f0;">'Euro'</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span>)<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">while</span> lReader<span style="color: #333333;">.</span>Next <span style="color: #008800; font-weight: bold;">do</span>
<span style="color: #008800; font-weight: bold;">begin</span>
mmoResultados<span style="color: #333333;">.</span>Lines<span style="color: #333333;">.</span>Add(lReader<span style="color: #333333;">.</span>Values[<span style="background-color: #fff0f0;">'country'</span>]<span style="color: #333333;">.</span>AsString)<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
</pre>
</td></tr>
</tbody></table>
</div>
<br />
É possível observar que a criação de parâmetros segue o tradicional padrão de quase todas as <i>engines</i> de acesso a dados do Delphi, com a prefixação do parâmetro com o caractere ':'. A principal diferença do DROP às demais metodologias está na passagem dos valores dos parâmetros, que acontece com um método anônimo (<i>callback</i>) que dá acesso aos parâmetros antes da execução da instrução contra o SGBD.<br />
<br />
Como nota importante do exemplo acima, é importante dizer que, mesmo quando usando o DBX Framework como <i>engine</i> da conexão do DROP, o método de parâmetros nomeados também está disponível. Para quem não lembra, o DBX Framework não suporta parâmetros nomeados, mas o DROP realiza um <i>parse</i> sobre a instrução SQL, mapeia os parâmetros, e então faz o meio de campo entre os parâmetros do DBX e os parâmetros disponibilizados ao usuário, podendo estes serem acessados também via nome.<br />
<br />
Por fim, vamos a um exemplo de instrução de DML. Estes comandos são executados a partir do método ExecuteCommand, que entre outras sobrecargas, também possui a capacidade de receber uma instrução de DML via texto, e passagens dos parâmetros via <i>callback</i>. Observe o exemplo abaixo.<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<table><tbody>
<tr><td><pre style="line-height: 125%; margin: 0;"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14</pre>
</td><td><pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">procedure</span> <span style="color: #bb0066; font-weight: bold;">TfrmExemplos</span><span style="color: #333333;">.</span><span style="color: #0066bb; font-weight: bold;">btnUpdateClick</span>(Sender<span style="color: #333333;">:</span> <span style="color: #333399; font-weight: bold;">TObject</span>)<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">var</span>
lRegistrosAfetados<span style="color: #333333;">:</span> <span style="color: #333399; font-weight: bold;">Int64</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">begin</span>
lRegistrosAfetados <span style="color: #333333;">:=</span> FConexao<span style="color: #333333;">.</span>ExecuteCommand(
<span style="background-color: #fff0f0;">'update country set currency = :currency where country = :country'</span><span style="color: #333333;">,</span>
<span style="color: #008800; font-weight: bold;">procedure</span>(pParametros<span style="color: #333333;">:</span> IAqDBParameters)
<span style="color: #008800; font-weight: bold;">begin</span>
pParametros[<span style="background-color: #fff0f0;">'currency'</span>]<span style="color: #333333;">.</span>AsString <span style="color: #333333;">:=</span> <span style="background-color: #fff0f0;">'US Dollar'</span><span style="color: #333333;">;</span>
pParametros[<span style="background-color: #fff0f0;">'country'</span>]<span style="color: #333333;">.</span>AsString <span style="color: #333333;">:=</span> <span style="background-color: #fff0f0;">'USA'</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span>)<span style="color: #333333;">;</span>
ShowMessage(lRegistrosAfetados<span style="color: #333333;">.</span>ToString)<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
</pre>
</td></tr>
</tbody></table>
</div>
<br />
Dúvidas? Por favor, não hesite em me contatar através do mail tatu@taturs.com, ou ainda por drop@aquasoft.com.br.<br />
<br />
Abraço e até o próximo post!<br />
<br />
<table style="width: 100%;">
<tbody>
<tr>
<td><a href="http://www.taturs.com/2017/09/drop-wiki-2.html">Episódio Anterior</a></td>
<td style="text-align: right;"><a href="http://www.taturs.com/2017/11/drop-wiki-4-transacoes.html">Próximo Episódio</a></td>
</tr>
</tbody></table>
Carlos Henrique Agneshttp://www.blogger.com/profile/10084689043014290783noreply@blogger.com0tag:blogger.com,1999:blog-3937944417896230425.post-14333924209192283202017-09-08T19:13:00.000-07:002018-03-08T15:58:27.366-08:00DROP Wiki #2 - Conexões com SGBDs<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: small;">
<i>You can read this post in english <a href="http://www.taturs.com/2018/03/drop-wiki-english-2-connecting-to-dbmss.html">here</a>.</i><br />
<br />
Dando continuidade à série DROP Wiki, o assunto da vez é o estabelecimento da conexão com uma fonte de dados (normalmente um SGBD) e a escolha da melhor classe para realizar esta tarefa.</div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: small;">
Mais adiante veremos que para o ORM do DROP funcionar, poucos pré-requisitos são necessários. Destes pré-requisitos, o mais importante com certeza é criar um objeto do tipo TAqDBConnection, e através deste objeto, estabelecer uma conexão com a fonte de dados.</div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: small;">
A classe TAqDBConnection (<i>unit</i> AqDrop.DB.Connection) é quase totalmente abstrata (existem planos, ainda que remotos, para transformá-la em interface, o que pode facilitar a implementação de testes). A responsabilidade da classe é abstrair o mínimo necessário para execução de comandos pelos SGDBs suportados. Obviamente, esta abstração visa possibilitar a extensão do framework para diferentes <i>engines</i> de acesso, sendo que, não custa relembrar, já temos extensões implementadas para DBX e FireDAC.</div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: small;">
Basicamente as interfaces fornecidas por TAqDBConnection são:</div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: small;">
- Rotinas para manipulação de Transações;</div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: small;">
- Preparação de comandos (ao estilo Prepare e Unprepare);</div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: small;">
- Rotinas para abertura de cursores;</div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: small;">
- Rotinas para execução de comandos (normalmente DMLs);</div>
<div style="background-color: white; color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div style="background-color: white;">
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
As rotinas de manipulação de transações, preparação e execução de comandos não diferem muito de qualquer <i>engine</i> de acesso a dados do Delphi (inclusive de terceiros). A diferença mais significativa está nas rotinas de abertura de cursores, que foram construídas de forma a fornecer interfaces semelhantes às fornecidas pelos <i>readers </i>do DBX Framework, conferindo ao código de leitura dos cursores um <i>aproach </i>mais voltado à orientação a objetos (em resumo, <i>no DataSets</i> ;-).</div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
Visando dividir os trabalhos do suporte ao DBX e FireDAC, duas classes foram implementadas e, ao estilo VCL, ambas tem o termo 'Custom' em seus nomes (TAqDBXCustomConnection e TAqFDCustomConnection), realizando o trabalho pesado no que diz respeito a alcançar seus respectivos objetivos. Duas heranças diretas, omitindo o termo 'Custom' de seus nomes (TAqDBXConnection e TAqFDConnection) tem somente o trabalho de disponibilizar ao usuário da classe todos os parâmetros fornecidos pelo DROP e as <i>engines</i> mapeadas, de forma a permitir a configuração completa para acesso ao SGBD desejado.</div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
Conforme prometido em outras oportunidades, uma <i>feature </i>que estava no forno e agora está pronta (faltando somente terminar a escrita dos novos testes para liberar a publicação), é o suporte ao Interbase. Já que esta é uma novidade, aproveito a oportunidade para usar o SGDB da Embarcadero para demonstrar, via DBX, a configuração de uma conexão. Segue exemplo de uso da classe TAqDBXConnection:</div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<!-- HTML generated using hilite.me --><br /></div>
<div style="background: rgb(255, 255, 255); border: solid gray; color: #222222; font-family: arial, sans-serif; font-size: small; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<table><tbody>
<tr><td><pre style="line-height: 125%; margin: 0;"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22</pre>
</td><td><pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">function</span> <span style="color: #bb0066; font-weight: bold;">TTesteConexaoDBXConnection</span><span style="color: #333333;">.</span><span style="color: #0066bb; font-weight: bold;">GetConexao</span><span style="color: #333333;">:</span> TAqDBConnection<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">var</span>
lConexao<span style="color: #333333;">:</span> TAqDBXConnection<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">begin</span>
lConexao <span style="color: #333333;">:=</span> TAqDBXConnection<span style="color: #333333;">.</span>Create<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">try</span>
lConexao<span style="color: #333333;">.</span>DriverName <span style="color: #333333;">:=</span> <span style="background-color: #fff0f0;">'InterBase'</span><span style="color: #333333;">;</span>
lConexao<span style="color: #333333;">.</span>VendorLib <span style="color: #333333;">:=</span> <span style="background-color: #fff0f0;">'GDS32.DLL'</span><span style="color: #333333;">;</span>
lConexao<span style="color: #333333;">.</span>LibraryName <span style="color: #333333;">:=</span> <span style="background-color: #fff0f0;">'dbxint.dll'</span><span style="color: #333333;">;</span>
lConexao<span style="color: #333333;">.</span>GetDriverFunc <span style="color: #333333;">:=</span> <span style="background-color: #fff0f0;">'getSQLDriverINTERBASE'</span><span style="color: #333333;">;</span>
lConexao<span style="color: #333333;">.</span>Properties[TDBXPropertyNames<span style="color: #333333;">.</span>Database] <span style="color: #333333;">:=</span> <span style="background-color: #fff0f0;">'C:\ALGUMCAMINHO\ALGUM.GDB'</span><span style="color: #333333;">;</span>
lConexao<span style="color: #333333;">.</span>Properties[TDBXPropertyNames<span style="color: #333333;">.</span>Username] <span style="color: #333333;">:=</span> <span style="background-color: #fff0f0;">'SYSDBA'</span><span style="color: #333333;">;</span>
lConexao<span style="color: #333333;">.</span>Properties[TDBXPropertyNames<span style="color: #333333;">.</span>Password] <span style="color: #333333;">:=</span> <span style="background-color: #fff0f0;">'masterkey'</span><span style="color: #333333;">;</span>
lConexao<span style="color: #333333;">.</span>DBXAdapter <span style="color: #333333;">:=</span> TAqDBXIBAdapter<span style="color: #333333;">.</span>Create<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">except</span>
lConexao<span style="color: #333333;">.</span>Free<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">raise</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
<span style="color: #007020;">Result</span> <span style="color: #333333;">:=</span> lConexao<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
</pre>
</td></tr>
</tbody></table>
</div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
O exemplo acima mostra que configurar uma conexão do DROP ou um TSQLConnection, por exemplo, são tarefas muito parecidas. No entanto, uma diferença clara da configuração do DROP para outras conexões do Delphi, está na construção de um <i>adapter,</i> necessário para um completo funcionamento dos recursos do DROP. Os <i>adapters </i>informam ao DROP como resolver algumas tarefas, ou então, como ler alguns tipos de dados do SGDB.</div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
Como o DROP visa funcionar mais como biblioteca, e menos como componente, a tarefa acima pode ser simplificada através do uso de um outro conjunto de classes, que mapeiam mais facilmente algumas distinções entre os SGBDs suportados. Abaixo vemos a criação de uma conexão com a mesma base de dados utilizada acima, no entanto, usando diretamente uma classe que mapeia DBX e as particularidades do Interbase.</div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<!-- HTML generated using hilite.me --></div>
<div style="background: rgb(255, 255, 255); border: solid gray; color: #222222; font-family: arial, sans-serif; font-size: small; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<table><tbody>
<tr><td><pre style="line-height: 125%; margin: 0;"> 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17</pre>
</td><td><pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">function</span> <span style="color: #bb0066; font-weight: bold;">TTesteConexaoDBXIB</span><span style="color: #333333;">.</span><span style="color: #0066bb; font-weight: bold;">GetConexao</span><span style="color: #333333;">:</span> TAqDBConnection<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">var</span>
lConexao<span style="color: #333333;">:</span> TAqDBXIBConnection<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">begin</span>
lConexao <span style="color: #333333;">:=</span> TAqDBXIBConnection<span style="color: #333333;">.</span>Create<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">try</span>
lConexao<span style="color: #333333;">.</span>DataBase <span style="color: #333333;">:=</span> <span style="background-color: #fff0f0;">'C:\ALGUMCAMINHO\ALGUM.GDB'</span><span style="color: #333333;">;</span>
lConexao<span style="color: #333333;">.</span>UserName <span style="color: #333333;">:=</span> <span style="background-color: #fff0f0;">'SYSDBA'</span><span style="color: #333333;">;</span>
lConexao<span style="color: #333333;">.</span>Password <span style="color: #333333;">:=</span> <span style="background-color: #fff0f0;">'masterkey'</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">except</span>
lConexao<span style="color: #333333;">.</span>Free<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">raise</span><span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
<span style="color: #007020;">Result</span> <span style="color: #333333;">:=</span> lConexao<span style="color: #333333;">;</span>
<span style="color: #008800; font-weight: bold;">end</span><span style="color: #333333;">;</span>
</pre>
</td></tr>
</tbody></table>
</div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<span style="color: #222222; font-family: "arial" , sans-serif; font-size: small;">No exemplo acima percebemos que a classe TAqDBXIBConnection se responsabiliza por configurar as propriedades conforme padrão para conectar com o Interbase, e expõe propriedades que são específicas do IB. Estas propriedades permitem configurar estaticamente alguns dados como o percurso do GDB, usuário e senha, ao contrário do primeiro exemplo, onde estas informações são dadas dinamicamente.</span><br />
<span style="color: #222222; font-family: "arial" , sans-serif; font-size: small;"><br /></span>
<span style="color: #222222; font-family: "arial" , sans-serif;">Bom, este foi o exemplo com o SGDB Interbase, e exemplos com outros SGDBs simplesmente significariam um pouco "mais do mesmo" em se tratando de código. No entanto, é válido colocar no mínimo a lista de classes especializadas já disponíveis no DROP, cada uma configurando a conexão para o comportamento padrão do SGDB, e disponibilizando propriedades particulares ao mesmo. Segue lista completa de classes, separadas por <i>engine</i>:</span><br />
<span style="color: #222222; font-family: "arial" , sans-serif;"><br /></span>
<span style="color: #222222; font-family: "arial" , sans-serif;">DBX:</span><br />
<span style="color: #222222; font-family: "arial" , sans-serif;"> - </span><span style="color: #222222; font-family: "arial" , sans-serif;">TAqDBXIBConnection;</span><br />
<span style="color: #222222; font-family: "arial" , sans-serif;"> - </span><span style="color: #222222; font-family: "arial" , sans-serif;">TAqDBXMSSQLConnection;</span><br />
<span style="color: #222222; font-family: "arial" , sans-serif;"> - </span><span style="color: #222222; font-family: "arial" , sans-serif;">TAqDBXMySQLConnection;</span><br />
<span style="color: #222222; font-family: "arial" , sans-serif;"> - </span><span style="color: #222222; font-family: "arial" , sans-serif;">TAqDBXFBConnection;</span><br />
<span style="color: #222222; font-family: "arial" , sans-serif;"> - </span><span style="color: #222222; font-family: "arial" , sans-serif;">TAqDBXOraConnection;</span><br />
<span style="color: #222222; font-family: "arial" , sans-serif;"> - </span><span style="color: #222222; font-family: "arial" , sans-serif;">TAqDBXSQLiteConnection;</span><br />
<span style="color: #222222; font-family: "arial" , sans-serif; font-size: small;"><br /></span>
<span style="color: #222222; font-family: "arial" , sans-serif; font-size: small;">FD:</span><br />
<span style="color: #222222; font-family: "arial" , sans-serif;"> - </span><span style="color: #222222; font-family: "arial" , sans-serif;">TAqFDIBConnection;</span><br />
<span style="color: #222222; font-family: "arial" , sans-serif;"> - </span><span style="color: #222222; font-family: "arial" , sans-serif;">TAqFDMSSQLConnection;</span><br />
<span style="color: #222222; font-family: "arial" , sans-serif;"> - </span><span style="color: #222222; font-family: "arial" , sans-serif;">TAqFDMySQLConnection;</span><br />
<span style="color: #222222; font-family: "arial" , sans-serif;"> - </span><span style="color: #222222; font-family: "arial" , sans-serif;">TAqFDFBConnection;</span><br />
<span style="color: #222222; font-family: "arial" , sans-serif;"> - </span><span style="color: #222222; font-family: "arial" , sans-serif;">TAqFDOraConnection;</span><br />
<span style="color: #222222; font-family: "arial" , sans-serif;"> - </span><span style="color: #222222; font-family: "arial" , sans-serif;">TAqFDSQLiteConnection;</span><br />
<div>
<span style="color: #222222; font-family: "arial" , sans-serif;"> - </span><span style="color: #222222; font-family: "arial" , sans-serif;">TAqFDPGConnection;</span><br />
<span style="color: #222222; font-family: "arial" , sans-serif;"><br /></span>
<span style="color: #222222; font-family: "arial" , sans-serif;">Notem que no FireDAC, temos um SGDB a mais, que é o PostgreSQL.</span><br />
<span style="color: #222222; font-family: "arial" , sans-serif;"><br /></span>
<span style="color: #222222; font-family: "arial" , sans-serif;">E, para o momento, vamos ficando por aqui. Na sequência teremos o episódio #3 da série, que vai mostrar como usar estes objetos de forma independente, e em episódios futuros, como usar dentro do aspecto do mapeamento objeto-relacional.</span></div>
<div>
<span style="color: #222222; font-family: "arial" , sans-serif;"><br /></span></div>
<div>
<span style="color: #222222; font-family: "arial" , sans-serif;">Até o próximo post!</span><br />
<span style="color: #222222; font-family: "arial" , sans-serif;"><br /></span>
<br />
<div style="text-align: right;">
<div style="text-align: left;">
<br /></div>
</div>
</div>
<div>
<table style="width: 100%;">
<tbody>
<tr>
<td><a href="http://www.taturs.com/2017/06/drop-wiki-1.html">Episódio Anterior</a></td>
<td style="text-align: right;"><a href="http://www.taturs.com/2017/10/drop-wiki-3-instrucoes-sql-via-texto.html">Próximo Episódio</a></td>
</tr>
</tbody></table>
<span style="color: #222222; font-family: "arial" , sans-serif;"><br /></span></div>
<span style="color: #222222; font-family: "arial" , sans-serif; font-size: small;"></span>
<span style="color: #222222; font-family: "arial" , sans-serif; font-size: small;"><br /></span></div>
Carlos Henrique Agneshttp://www.blogger.com/profile/10084689043014290783noreply@blogger.com0tag:blogger.com,1999:blog-3937944417896230425.post-59418623745124484472017-06-06T08:22:00.000-07:002018-03-08T16:02:59.542-08:00DROP Wiki #1 - Introdução<i>You can read this post in english <a href="http://www.taturs.com/2018/01/drop-wiki-english-1-introduction.html">here</a>.</i><br />
<br />
Com o objetivo de fornecer documentação extensa sobre o DROP, vou começar a série DROP Wiki, e como muitas conversas sobre o <i>framework</i> começam pela pergunta "O que é o DROP?", nada melhor do que começar a série tentando responder esta pergunta.<br />
<br />
De forma mais resumida possível, O DROP é um conjunto de classes feitas em Delphi, para facilitar tarefas do cotidiano do desenvolvedor. Muitas destas classes foram desenvolvidas para suportar um framework próprio de ORM (mapeamento objeto-relacional), e é principalmente por cumprir este objetivo que o DROP é mais conhecido.<br />
<br />
Outra coisa importante sobre o DROP é que ele é totalmente grátis e <i>open source</i> (licença MIT), e se você já está interessado em baixá-lo ou usá-lo, você pode fazer através do <a href="https://github.com/AquasoftTI/AqDrop">GitHub</a>, ou fazendo o download dos fontes através de um arquivo compactado neste link. Agora, vamos esmiuçar mais um pouco o DROP.<br />
<br />
Lembro que, enquanto o DROP estava sendo desenvolvido/remodelado, muitas vezes conversei com a equipe da Aquasoft e outros desenvolvedores (como meu amigo Muka), e o assunto de várias destas conversas era o porquê do DROP ser dividido em algumas camadas, cada camada com uma responsabilidade. Entender melhor estas camadas, faz com que o entendimento sobre o DROP seja facilitado:<br />
<br />
<ul>
<li>Core: contém classes úteis para diversas coisas, com fins genéricos no desenvolvimento em geral. Nesta camada ainda não há nada implementado para acessar ou conversar com SGBDs. Para falar a verdade, algumas classes nem chegam a ser consumidas direta ou indiretamente nas tarefas de ORM;</li>
<li>BD: as classes contidas aqui abstraem a comunicação com SGBDs, e consequentemente, muitas destas classes são abstratas, fornecendo estruturas uniformes, que mais adiante permitem ao DROP escrever o código uma única vez, porém compatível com todos os bancos de dados suportados até então. Por mais que neste nível não existam classes concretas de acesso a dados, já existem muitas classes específicas para alguns SGBDs, como as classes que resolvem os objetos de SQL, traduzindo-os para a linguagem específica de cada um dos SGBDs suportados;</li>
<li>ORM: contém as classes de ORM, propriamente ditas. Transformam estruturas de classes e seus atributos em objetos SQL, bem como possibilitam com que objetos que representam entidades sejam persistidas e recuperadas dos SGBDs;</li>
<li>Base para ORM (este nome ainda precisa de um <i>facelift</i> do setor de marketing ;-): a camada de ORM não exige que as classes a serem mapeadas herdem de classes do DROP, no entanto, o DROP fornece, nesta camada, algumas classes que podem ser estendidas, reduzindo o trabalho do desenvolvedor ao realizar o mapeamento objeto-relacional.</li>
</ul>
<br />
A camada Core apresenta todas as suas <i>units</i> em um pacote homônimo, sendo que as demais camadas estão implementadas no pacote DB. É importante salientar que todas as <i>units</i> das camadas acima estão livres de código específico para acesso a dados via alguma das tecnologias para tal tarefa.<br />
<div>
<br /></div>
<div>
Para realizar o acesso físico aos dados, o DROP pode trabalhar tanto com o DBX framework, quanto FireDAC, fica a critério do desenvolvedor usar uma tecnologia ou outra. Sendo assim, cada uma das implementações do DROP para as tecnologias acima recebeu seu próprio pacote.</div>
<div>
<br /></div>
<div>
Falando em acesso físico a dados, o DROP atualmente suporta seis SGBDs relacionais:</div>
<div>
<ul>
<li>Interbase;</li>
<li>Oracle;</li>
<li>Microsoft SQL Server;</li>
<li>PostgreSQL (somente via FireDAC);</li>
<li>MySQL;</li>
<li>Firebird;</li>
<li>SQLite.</li>
</ul>
</div>
<div>
Concluindo, se fosse possível resumir o conteúdo acima com uma imagem, seria mais ou menos assim:</div>
<div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiiwq8EtGotetM-S_3Oe5OmugsnDT6HfxDjstfcRkXfW3u1IwuTksu8H5OnD0f3Qc5ZI-eaHdRgPsWSnIxFNLJ5WnwSb_1rAbqJGWbIehvvZedq9pMFazqomIcuOK2vWY5nAMrBsDKipth/s1600/Captura+de+Tela+2017-06-05+a%25CC%2580s+23.45.20.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="863" data-original-width="1188" height="290" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhiiwq8EtGotetM-S_3Oe5OmugsnDT6HfxDjstfcRkXfW3u1IwuTksu8H5OnD0f3Qc5ZI-eaHdRgPsWSnIxFNLJ5WnwSb_1rAbqJGWbIehvvZedq9pMFazqomIcuOK2vWY5nAMrBsDKipth/s400/Captura+de+Tela+2017-06-05+a%25CC%2580s+23.45.20.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Para encerrar, os próximos <i>posts</i> da série alternarão assuntos de como usar ORM, bem como as classes que circundam todo o eco-sistema. Até lá!!!</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<table style="width: 100%;">
<tbody>
<tr>
<td></td><td style="text-align: right;"><a href="http://www.taturs.com/2017/09/drop-wiki-2.html">Próximo Episódio</a></td>
</tr>
</tbody></table>
</div>
Carlos Henrique Agneshttp://www.blogger.com/profile/10084689043014290783noreply@blogger.com0tag:blogger.com,1999:blog-3937944417896230425.post-50069429088909596032017-05-22T02:00:00.000-07:002017-10-26T15:38:39.084-07:00Aquasoft DROP 1.3.0<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
Conforme prometido, estou de volta tanto às atividades do blog, quanto à continuidade do DROP.</div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
Até o dia de ontem, a última <i>release</i> oficial do DROP havia sido lançada ainda no ano de 2015. Durante o ano de 2016 trabalhei em várias melhorias, mas, por diversos motivos, nenhuma delas havia sido publicada ainda. Como consequência deste <i>gap</i>, foi criado um problema que precisava ser corrigido, que era a ausência do suporte oficial ao Delphi Berlin, e também do suporte ao Delphi Tokyo.</div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
Priorizada esta tarefa, ontem foi feita a entrega de uma nova versão. Diversas das melhorias no DROP feitas durante o ano de 2016 foram publicadas, e junto com elas os novos pacotes e a garantia de fontes compatíveis com as versões mais recentes do Delphi.<br />
<br />
<br /></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBh8Lu84be9uisBz731NuZpJtIyqyYjraZTCXygKGA6OydBX-dvI81q5_GRPsuuhzGDgIo_x88v2WvPxC0u8mAuVkjakrZUWNCf3FfGg9fBobvhzJmG2CTYamW0TWNAPVt9dFzD1dILgb2/s1600/Captura+de+Tela+2017-05-19+a%25CC%2580s+13.00.44.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="252" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBh8Lu84be9uisBz731NuZpJtIyqyYjraZTCXygKGA6OydBX-dvI81q5_GRPsuuhzGDgIo_x88v2WvPxC0u8mAuVkjakrZUWNCf3FfGg9fBobvhzJmG2CTYamW0TWNAPVt9dFzD1dILgb2/s400/Captura+de+Tela+2017-05-19+a%25CC%2580s+13.00.44.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<br /></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
O DROP pode ser baixado como arquivo compactado através do site da <a href="http://www.aquasoft.com.br/site/produtos">Aquasoft</a>, ou através do <a href="https://github.com/AquasoftTI/AqDrop">GitHub</a>.<br />
<br /></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
Muitas coisas estão no <i>roadmap</i> do DROP, posso garantir que muitos <i>updates</i> acontecerão este ano.<br />
<br />
Até breve!<br />
<br />
<br /></div>
Carlos Henrique Agneshttp://www.blogger.com/profile/10084689043014290783noreply@blogger.com0tag:blogger.com,1999:blog-3937944417896230425.post-42500523764077442102017-05-11T18:01:00.000-07:002017-10-26T15:42:53.256-07:00Delphi Tour 2017<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<b><i>Porto Alegre</i></b></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
Encerrei o meu último post comentando que nesta semana aconteceria a passagem do Delphi Tour 2017 pela cidade de Porto Alegre. O Delphi Tour é um evento da Embarcadero para aproximar a comunidade de desenvolvedores e anunciar de perto o que há de novo no RAD Studio, nesta edição, o recém lançado RAD Studio 10.2 Tokyo. A organização dos eventos aqui no sul mais uma vez coube à Aquasoft, e a apresentação ficou por conta do Fernando Rizzato.</div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
Não pretendo detalhar os assuntos do Tour, até porque vídeos oficiais sobre as novidades já saíram e mais estão por sair (<a href="https://www.embarcadero.com/products/rad-studio/whats-new-in-10-2-tokyo">como neste what's new</a>). Mas, segue lista de assuntos que preencheu a manhã do dia 09/05:</div>
<div>
<ul>
<li style="color: #222222; font-family: arial, sans-serif;"><b><span style="font-size: x-small;">IDE - algumas novidades como:</span></b></li>
<ul style="color: #222222; font-family: arial, sans-serif;">
<li><span style="font-size: x-small;">Reorganização do menu;</span></li>
<li><span style="font-size: x-small;">Quick Edit;</span></li>
</ul>
<li style="color: #222222; font-family: arial, sans-serif;"><b><span style="font-size: x-small;">Facilidade de desenvolvimento para múltiplas plataformas:</span></b></li>
<ul style="color: #222222; font-family: arial, sans-serif;">
<li><span style="font-size: x-small;">Componente Multiview;</span></li>
<li><span style="font-size: x-small;">View master e suas descendências;</span></li>
<li><span style="font-size: x-small;">Multi device viewer;</span></li>
<li><span style="font-size: x-small;">Fire UI Live Preview;</span></li>
</ul>
<li><span style="color: #222222; font-family: "arial" , sans-serif; font-size: x-small;"><b>Android:</b></span></li>
<ul>
<li><span style="color: #222222; font-family: "arial" , sans-serif; font-size: x-small;">Integração das threads do processo Android;</span></li>
</ul>
<li><span style="color: #222222; font-family: "arial" , sans-serif; font-size: x-small;"><b>FireDAC:</b></span></li>
<ul>
<li><span style="color: #222222; font-family: "arial" , sans-serif; font-size: x-small;">Estendido para Linux;</span></li>
<li><span style="color: #222222; font-family: "arial" , sans-serif; font-size: x-small;">Suporte a Maria DB;</span></li>
<li><span style="color: #222222; font-family: "arial" , sans-serif; font-size: x-small;">LocalSQL;</span></li>
<li><span style="color: #222222; font-family: "arial" , sans-serif; font-size: x-small;">Recursos para aplicações multi-banco;</span></li>
</ul>
<li><span style="color: #222222; font-family: "arial" , sans-serif; font-size: x-small;"><b>Windows 10:</b></span></li>
<ul>
<li><span style="color: #222222; font-family: "arial" , sans-serif; font-size: x-small;">Novidades;</span></li>
<li><span style="color: #222222; font-family: "arial" , sans-serif; font-size: x-small;">Publicação na Windows Store;</span></li>
<li><span style="color: #222222; font-family: "arial" , sans-serif; font-size: x-small;">Contratos e Notificações;</span></li>
</ul>
<li><span style="color: #222222; font-family: "arial" , sans-serif; font-size: x-small;"><b>RAD Server:</b></span></li>
<ul>
<li><span style="color: #222222; font-family: "arial" , sans-serif; font-size: x-small;">Facilidade no desenvolvimento de interfaces REST;</span></li>
<li><span style="color: #222222; font-family: "arial" , sans-serif; font-size: x-small;">Gerenciamento de usuários, grupos e estatísticas de acesso;</span></li>
<li><span style="color: #222222; font-family: "arial" , sans-serif; font-size: x-small;">Push notifications nativo;</span></li>
<li><span style="color: #222222; font-family: "arial" , sans-serif; font-size: x-small;">Beacon fence;</span></li>
<li><span style="color: #222222; font-family: "arial" , sans-serif; font-size: x-small;">Multy-tenancy;</span></li>
</ul>
<li><span style="color: #222222; font-family: "arial" , sans-serif; font-size: x-small;"><b>IOT:</b></span></li>
<ul>
<li><span style="color: #222222; font-family: "arial" , sans-serif; font-size: x-small;">Mercado e novidades da ferramenta;</span></li>
</ul>
<li><span style="color: #222222; font-family: "arial" , sans-serif; font-size: x-small;"><b>Compilador Linux:</b></span></li>
<ul>
<li><span style="color: #222222; font-family: "arial" , sans-serif; font-size: x-small;">Suporte (homologado) para Ubuntu e Red Hat;</span></li>
<li><span style="color: #222222; font-family: "arial" , sans-serif; font-size: x-small;">Deploy simples, mantendo o padrão com PA Server;</span></li>
<li><span style="color: #222222; font-family: "arial" , sans-serif; font-size: x-small;">RTL;</span></li>
<ul>
<li><span style="color: #222222; font-family: "arial" , sans-serif; font-size: x-small;"><i>Quer se aventurar no mundo Linux, comece pelas dicas do <a href="http://josearaujo.com.br/delphi-linux-apache-parte1/">Araújo</a> e do <a href="http://vivaitaocara.com.br/landersongomes/tecnologia/instalando-vm-ubuntu-server-no-virtual-box">Landerson</a>!</i></span></li>
</ul>
</ul>
</ul>
</div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSPNP_f1pKGAwgW5YwGi7gD8Rzt5l0QS0U4TGYDAkzIfOuxquZd_w3-mDLJ4teOW4T_5F_ydJ37AdcEWpczgINQINBygtYWrs8chKTDtYmrgC7BOppXfdOuzwdXgH54sdT1nyIbYkRMUTB/s1600/IMG_1315.JPG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="172" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSPNP_f1pKGAwgW5YwGi7gD8Rzt5l0QS0U4TGYDAkzIfOuxquZd_w3-mDLJ4teOW4T_5F_ydJ37AdcEWpczgINQINBygtYWrs8chKTDtYmrgC7BOppXfdOuzwdXgH54sdT1nyIbYkRMUTB/s400/IMG_1315.JPG" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Panorâmica da galera na Faculdade Decision / FGV!</td></tr>
</tbody></table>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<b><i>O Tour seguiu</i></b></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
Também tomo a liberdade de colocar aqui algumas fotos tiradas pela Luciane Lopes (da <a href="http://www.aquasoft.com.br/">Aquasoft</a>), em Florianópolis e Chapecó. Nestas fotos é possível perceber que não era só eu que estava com saudades do evento ;-)</div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1GVEnY1wcj7ZawT69bJMsE1gbX1bmFjYthmNA81mIK5zKlZPTAFkasLQfe5vUo0WA4csUdO8FbdTVq47ilpXM7mS4ibFoXwmeNRvk8rKfytZntmkczBS_FxQNkY_3d7GIOnbQv1oS45hV/s1600/floripa.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg1GVEnY1wcj7ZawT69bJMsE1gbX1bmFjYthmNA81mIK5zKlZPTAFkasLQfe5vUo0WA4csUdO8FbdTVq47ilpXM7mS4ibFoXwmeNRvk8rKfytZntmkczBS_FxQNkY_3d7GIOnbQv1oS45hV/s400/floripa.jpg" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Floripa</td></tr>
</tbody></table>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHpvp7DAUtSrIW3cGqTl2SURGy6pkySoFr-qmffUi8Le8OHKCFVOTWvfcxAR_8Ru-rmbeuf9bzyNTqYSiyf1C92scQCQnHIghRhTziRCKfNzoW1OAdXaHerMZ9Vi_Z-ThrebZCTF2Zbx3V/s1600/chapeco%25CC%2581.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHpvp7DAUtSrIW3cGqTl2SURGy6pkySoFr-qmffUi8Le8OHKCFVOTWvfcxAR_8Ru-rmbeuf9bzyNTqYSiyf1C92scQCQnHIghRhTziRCKfNzoW1OAdXaHerMZ9Vi_Z-ThrebZCTF2Zbx3V/s400/chapeco%25CC%2581.jpg" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Chapecó</td></tr>
</tbody></table>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
Ainda restam algumas cidades que serão visitadas amanhã, e também na semana que vem.</div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<b><i>Falando em eventos...</i></b></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
Falando em eventos, durante o Tour foi anunciada a trilha Embarcadero na TDC 2017 - São Paulo, que acontecerá em Julho, bem como a Embarcadero Conference 2017, que acontecerá em Outubro.</div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<b><i>Em resumo</i></b></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
Muitos assuntos deste Tour já vem de outros encontros, servem como resumo dos últimos capítulos para aqueles que não estiveram acompanhando as melhorias da ferramenta em suas últimas versões. Mas minha principal conclusão, e também de muitos participantes com os quais tive a oportunidade de conversar durante e após o evento, é que está evidente o compromisso da Embarcadero em trabalhar na entrega de um produto cada vez melhor. A equipe de desenvolvimento do RAD Studio está trabalhando em muitas frentes, diversas novas <i>features</i> estão sendo acrescidas a cada versão, tanto <i>features</i> grandes, como o compilador para Linux, que com certeza demandou muitos recursos e horas de trabalho, quanto <i>features</i> menores, como os novos Quick Edits (presentes já no último update da versão Berlin), que em um primeiro momento parecem algo simples, mas que rapidamente se tornam algo imprescindível, devido à agilidade dada ao executar tarefas do nosso cotidiano.</div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<br /></div>
<div style="color: #222222; font-family: arial, sans-serif; font-size: small;">
<b><i>E, até o próximo Tour!</i></b></div>
<div>
<br /></div>
Carlos Henrique Agneshttp://www.blogger.com/profile/10084689043014290783noreply@blogger.com0tag:blogger.com,1999:blog-3937944417896230425.post-18949069027499165492017-05-04T09:11:00.002-07:002017-05-12T18:59:42.018-07:00"Sometimes all we need is a fresh start..."<i><b><span style="font-family: Arial, Helvetica, sans-serif;">Com muito prazer, volto a escrever por aqui</span></b></i><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;">Imagino que alguns devem ter notado que o blog passou por um "RecreateWnd". Pois é, achei que recomeçar o blog do zero seria um bom ponto de partida para as mudanças que têm acontecido na minha vida profissional nos últimos meses.</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;">No final de Março, oficializamos a minha saída do quadro social da empresa Aquasoft TI, empresa na qual tive a honra de trabalhar e colaborar por mais de nove anos, e destes, quase sete anos atuando na direção técnica da empresa. Foi, com certeza, o meu período de maior crescimento, em todos os aspectos possíveis. Nestes nove anos, tive colegas e amigos incríveis, e as amizades não se restringem aos colegas da Aquasoft, mas se estendem a diversos clientes que tive o prazer de atender durante anos, cuja participação na minha vida com certeza não será esquecida.</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;">Pois bem, durante o período de finalização das atividades, conforme alguns clientes e parceiros foram sendo comunicados, muitos me perguntaram se eu estava deixando o Delphi ou sua comunidade. E este é um dos motivos deste post. Então vamos aos pingos nos Is.</span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<ul>
<li><span style="font-family: Arial, Helvetica, sans-serif;">O mais importante: continuo trabalhando com Delphi ("Delphi, eu te amo!" foi meu <i>slogan</i> durante muito tempo nas minhas palestras, e <b>continua</b> sendo ;-)</span></li>
<li><span style="font-family: Arial, Helvetica, sans-serif;">Também muito importante: continuo parceiro da Aquasoft! Seja para treinamentos, consultorias, suporte à comunidade, estamos aí!</span></li>
<li><span style="font-family: Arial, Helvetica, sans-serif;">O desenvolvimento do Drop ficou suspenso durante este tempo de novas definições, mas agora que tanto os caminhos da Aqua quanto os meu estão novamente definidos, é importante dizer que a parceria com a Aquasoft continua inclusive no desenvolvimento do Drop, projeto para o qual continuarei trabalhando (ou me divertindo);</span></li>
</ul>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span>
<div>
<b><i><span style="font-family: Arial, Helvetica, sans-serif;">Estando as premissas acima salvas, comitadas e lavradas em cartório... vamos falar sobre o blog</span></i></b></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;">O blog ficou parado por muito tempo, o que me incomodou bastante, e agora pretendo remediar isto. Continuarei falando de eventos e novidades, claro que também continuarei falando do Drop, mas acima de tudo, pretendo escrever sobre o assunto que particularmente mais me agrada, que é o underground do Delphi, e obviamente os temas acima tendem a se misturar, muitas vezes. A lista de assuntos dos quais pretendo escrever já está bem grande, e não vou me prender a escrever posts muito grandes (como os artigos que escrevi para a Active Delphi, por exemplo); assuntos menores, porém interessantes aos meus olhos, também vão aparecer.</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div>
<b><i><span style="font-family: Arial, Helvetica, sans-serif;">Aproveitando o post, lá vem o Tour (onde? logo ali...)</span></i></b></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;">Depois de um tempo fora, um velho amigo também voltou: o Delphi Tour, que pra falar a verdade começou ontem, pela cidade de Recife.</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="http://www.embarcaderobr.com.br/tour/"><span style="font-family: Arial, Helvetica, sans-serif;"><img border="0" height="165" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhNMVKFWV5tlb-BR8CGJ2kAe_5nCQwuy3hhh6hn7aqg0SqWISCKlL4xvaDEsnp0SGd0GDAZW6oJsT2O3UAHytE-N5hOaWkY4RldhROynM28Ga9xb2u_tP1FyIljFSfTZAFxU1zMokqHCSOx/s400/banner_home.png" width="400" /></span></a></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;">Dia 09/05 o Tour passa por Porto Alegre, e certamente estarei lá para rever amigos e, principalmente, acompanhar de perto as novidades do Delphi 10.2 (Tokyo). A equipe da Aquasoft, como de praxe, também estará presente nos eventos de SC, dia 10 em Floripa, e dia 11 em Chapecó.</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;">O Tour está rolando e muitas cidades ainda serão visitadas, se quer tirar a dúvida se sua cidade está na lista, ou se dá tempo de se inscrever, acesse o site do evento <a href="http://www.embarcaderobr.com.br/tour/">aqui</a>.</span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div>
<span style="font-family: Arial, Helvetica, sans-serif;"><br /></span></div>
<div>
<b><i><span style="font-family: Arial, Helvetica, sans-serif;">Abraço, e sucesso a todos!!!</span></i></b><br />
<b><i><br /></i></b></div>
Carlos Henrique Agneshttp://www.blogger.com/profile/10084689043014290783noreply@blogger.com0