<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>Joao Morais</title>
	<atom:link href="http://blog.joaomorais.com.br/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.joaomorais.com.br</link>
	<description>Object Pascal e ferramentas de programação com Arte</description>
	<pubDate>Fri, 06 Feb 2009 11:03:34 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.5</generator>
	<language>en</language>
			<item>
		<title>Objetos com contagem de referência</title>
		<link>http://blog.joaomorais.com.br/2008/09/06/objetos-contagem-ref.html</link>
		<comments>http://blog.joaomorais.com.br/2008/09/06/objetos-contagem-ref.html#comments</comments>
		<pubDate>Sat, 06 Sep 2008 20:04:21 +0000</pubDate>
		<dc:creator>Joao Morais</dc:creator>
		
		<category><![CDATA[Object Pascal]]></category>

		<guid isPermaLink="false">http://blog.joaomorais.com.br/?p=81</guid>
		<description><![CDATA[Imagine um data module, que por motivo de economia de memória é criado e destruído com a aplicação em execução. Imagine este data module sendo referenciado por mais de um formulário ao mesmo tempo. Como garantir que o data module será destruído apenas quando nenhum formulário estiver apontando para ele? 
Este é o objetivo da [...]]]></description>
			<content:encoded><![CDATA[<p>Imagine um data module, que por motivo de economia de memória é criado e destruído com a aplicação em execução. Imagine este data module sendo referenciado por mais de um formulário ao mesmo tempo. Como garantir que o data module será destruído apenas quando nenhum formulário estiver apontando para ele? <span id="more-81"></span></p>
<p>Este é o objetivo da contagem de referência. Um membro da classe guarda a quantidade de objetos que apontam para ele. Logo que esta contagem cai para zero, significa que o objeto pode ser destruído. A estrutura da classe base fica assim:</p>
<pre>
TRefCountObject = class(TObject)
private
  FRefCount: Integer;
public
  function AddRef;
  class function NewInstance: TObject; override;
  function Release;
end;
</pre>
<p>e as respectivas implementações:</p>
<pre>
function TRefCountObject.AddRef;
begin
  Result := InterlockedIncrement(FRefCount);
end;

class function TRefCountObject.NewInstance: TObject;
begin
  Result := inherited NewInstance;
  TRefCountObject(Result).FRefCount := 1;
end;

function TRefCountObject.Release;
begin
  Result := InterlockedDecrement(FRefCount);
  if Result = 0 then
    Free;
end;
</pre>
<p>Como isto funciona? Quando o programador cria uma instância, o FRefCount é setado para 1. Não importa como ele chama o construtor, ou se ele sobrecarrega algum método e não chama inherited, o FRefCount sempre começa em 1. Cada nova referência, indicada através da chamada ao método AddRef, aumenta o contador de referências do objeto. Cada um que liberar aquele objeto chama o método Release. O último que liberar o objeto, fará com que ele se auto destrua.</p>
<p>Na implementação acima, as rotinas Interlocked trabalham de forma segura em ambiente multi thread, ao contrário do inc e dec tradicionais. Elas estão declaradas na unit Windows no Delphi, e na unit System no FPC. O método NewInstance intercepta o momento exato em que a instância é criada, e neste momento seta o valor do contador de referência.</p>
<p>Agora a primeira limitação desta implementação: programadores habituados com o controle do tempo de vida do objeto no Object Pascal tradicional vão precisar alterar todas as suas chamadas a .Destroy e a .Free para que a rotina funcione corretamente. E mesmo depois de alterar, precisarão habituar-se com esta nova filosofia, o que pode gerar códigos mais sujeitos a erros. O culpado é o destructor que, independente de ser virtual, uma vez chamado fará com que a instância seja destruída.</p>
<p>Por sorte, assim como existe um método virtual que é responsável por criar a instância, existe também outro que é responsável por destrui-la. Sobrecarregar este método e tratá-lo da mesma forma que o release, fará com que o .Free não destrua o objeto antes da hora. Veja a nova declaração da classe:</p>
<pre>
TRefCountObject = class(TObject)
private
  FRefCount: Integer;
  function Release;
public
  function AddRef;
  function FreeInstance; override;
  class function NewInstance: TObject; override;
end;
</pre>
<p>e a implementação. Note que o Release tem que ser reescrito para entrar no jogo do novo FreeInstance:</p>
<pre>
function TRefCountObject.Release;
begin
  Result := InterlockedDecrement(FRefCount);
  if Result < 0 then
    raise Exception.Create('Não é possível liberar a instância');
end;

function TRefCountObject.FreeInstance;
begin
  if Release = 0 then
    inherited;
end;
</pre>
<p>Os demais métodos continuam idênticos, e o Release passa a ser um coadjuvante. Ele até poderia ser usado para liberar contagem de referência, mas não é capaz de destruir uma instância a fim de evitar repetição de código. Por este motivo ele foi movido para a área private e passa a ser usado apenas internamente.</p>
<p>Este novo modelo está quase perfeito. Ao criar o objeto sua contagem é um. Ao chamar AddRef a contagem salta para dois. Ao chamar Destroy ou Free a contagem de referências cai para 1 e o inherited FreeInstance não é chamado, o que mantém o objeto na memória. Na segunda chamada ao Free, o objeto é liberado pois ninguém mais aponta para ele (FRefCount igual a zero).</p>
<p>A falha deste modelo é, ao meu ver, uma limitação do modelo de objeto do Object Pascal. O TObject foi desenhado pensando em um modelo aonde o tempo de vida de um objeto é determinado fora da instância. Ou seja, uma instância A que faz referência a uma instância B é a responsável por destruí-la, enquanto um modelo com um certo grau de coerência deveria deixar esta decisão para a própria instância B, e a instância A deveria limitar-se a avisar B que tem menos gente apontando para ela.</p>
<p>A parte do controle do tempo de vida do objeto já está resolvido, FreeInstance foi sobrecarregado e .Free vai meramente decrementar a contagem de referência quando esta for maior do que 1. No entanto o destructor padrão do TObject, o método Destroy, é virtual e é a opção lógica para ser sobrecarregado quando uma determinada ação é necessária durante a destruição do objeto. O problema do nosso novo modelo é que FreeInstance é chamado depois do Destroy, e qualquer rotina escrita em um Destroy sobrecarregado será chamado mesmo que a instância não seja destruída.</p>
<p>A forma de resolver este problema é &#8216;matar&#8217; o destructor virtual e impedir que o programador pendure código nele, e por outro lado, criar outro método virtual que é chamado a fim de notificar a destruição real do objeto. A declaração da classe fica assim:</p>
<pre>
TRefCountObject = class(TObject)
private
  FRefCount: Integer;
  function Release;
protected
  procedure Finit; virtual;
public
  destructor Destroy; reintroduce;
  function AddRef;
  function FreeInstance; override;
  class function NewInstance: TObject; override;
end;
</pre>
<p>e o que muda na declaração da classe:</p>
<pre>
destructor TRefCountObject.Destroy;
begin
end;

function TRefCountObject.Finit;
begin
end;

function TRefCountObject.FreeInstance;
begin
  if Release = 0 then
    try
      Finit;
    finally
      inherited;
    end;
end;
</pre>
<p>Agora a classe está pronta para criar instâncias que entendam contagem de referência sem perder a tradicional interface Create/Destroy/Free do Object Pascal.</p>
<p>Segue abaixo a declaração completa da classe, após todas as alterações:</p>
<pre>
TRefCountObject = class(TObject)
private
  FRefCount: Integer;
  function Release;
protected
  procedure Finit; virtual;
public
  destructor Destroy; reintroduce;
  function AddRef;
  function FreeInstance; override;
  class function NewInstance: TObject; override;
end;

...

function TRefCountObject.AddRef;
begin
  Result := InterlockedIncrement(FRefCount);
end;

destructor TRefCountObject.Destroy;
begin
end;

function TRefCountObject.Finit;
begin
end;

function TRefCountObject.FreeInstance;
begin
  if Release = 0 then
    try
      Finit;
    finally
      inherited;
    end;
end;

class function TRefCountObject.NewInstance: TObject;
begin
  Result := inherited NewInstance;
  TRefCountObject(Result).FRefCount := 1;
end;

function TRefCountObject.Release;
begin
  Result := InterlockedDecrement(FRefCount);
  if Result < 0 then
    raise Exception.Create('Não é possível liberar a instância');
end;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.joaomorais.com.br/2008/09/06/objetos-contagem-ref.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Forms management tip</title>
		<link>http://blog.joaomorais.com.br/2008/08/31/forms-management-tip.html</link>
		<comments>http://blog.joaomorais.com.br/2008/08/31/forms-management-tip.html#comments</comments>
		<pubDate>Sun, 31 Aug 2008 14:09:11 +0000</pubDate>
		<dc:creator>Joao Morais</dc:creator>
		
		<category><![CDATA[Object Pascal-en]]></category>

		<guid isPermaLink="false">http://blog.joaomorais.com.br/?p=84</guid>
		<description><![CDATA[(portuguese)
From my point of view, one thing that is really missing for Delphi/Lazarus is a better application&#8217;s form management. Two problems: an independent public variable is used to control an instance, and the &#8216;please place everything within the form&#8217; approach. The first one requires the programmer to either create the form at the start of [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.joaomorais.com.br/2008/08/31/dica-gerenciamento-form.html">(portuguese)</a></p>
<p>From my point of view, one thing that is really missing for Delphi/Lazarus is a better application&#8217;s form management. Two problems: an independent public variable is used to control an instance, and the &#8216;please place everything within the form&#8217; approach. The first one requires the programmer to either create the form at the start of the application and not destroy it anymore, or it requires the programmer to create the forms and keep track of object destruction insuring that no variable points to a destroyed object. The second, among other problems, requires that the first one works perfectly so that the communication between forms can work. <span id="more-84"></span></p>
<p>When using the second approach there is not much work to be done. You either have to live with this limitation or write a new framework to go around it. Now, in order to maintain an up-to-date public variable, the programmer can benefit from the small tricks I will be describing here.</p>
<p>My suggestion  to maintain an up-to-date public variable is to give it to a class method. This method takes care to create the form when this is necessary, and to update the variable when the form is destroyed. For this, implement the following method in the forms base class, in other words, the one from which all the forms will inherit:</p>
<pre>
  TBaseForm = class(TForm)
  public
    class procedure Execute(var AForm; AModal: Boolean = False);
  end;
</pre>
<p>And implement the methods like this:</p>
<pre>
class procedure TBaseForm.Execute(var AForm; AModal: Boolean);
var
  VIndex: Integer;
begin
  if not Assigned(_Forms) then
  begin
    _Forms := TStringList.Create;
    _Forms.Sorted := True;
  end;
  if not _Forms.Find(ClassName, VIndex) then
    VIndex := _Forms.Add(ClassName);
  if TForm(AForm) = nil then
    Application.CreateForm(Self, AForm);
  _Forms.Objects[VIndex] := TObject(@AForm);
  if AModal then
    TForm(AForm).ShowModal
  else
    TForm(AForm).Show;
end;
</pre>
<p>and make the public variable references nil the moment the form is destroyed:</p>
<pre>
destructor TBaseForm.Destroy;
type
  PForm = ^TForm;
var
  VIndex: Integer;
begin
  if Assigned(_Forms) and _Forms.Find(ClassName, VIndex) and
   (_Forms.Objects[VIndex] <> nil) then
  begin
    PForm(_Forms.Objects[VIndex])^ := nil;
    _Forms.Objects[VIndex] := nil;
  end;
  inherited;
end;
</pre>
<p>Finally, the StringList needs to be declared, and destroyed when the application is closed:</p>
<pre>
implementation

var
  _Forms: TStringList = nil;

...

initialization

finalization
  _Forms.Free;

end.
</pre>
<p>Done. The only thing needed is to create new forms that descend from this one and call TYourForm.Execute(YourForm). When the form is destroyed, the public variable will be assigned to nil.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.joaomorais.com.br/2008/08/31/forms-management-tip.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Dica para gerenciamento de formulários</title>
		<link>http://blog.joaomorais.com.br/2008/08/31/dica-gerenciamento-form.html</link>
		<comments>http://blog.joaomorais.com.br/2008/08/31/dica-gerenciamento-form.html#comments</comments>
		<pubDate>Sun, 31 Aug 2008 14:08:06 +0000</pubDate>
		<dc:creator>Joao Morais</dc:creator>
		
		<category><![CDATA[Object Pascal]]></category>

		<guid isPermaLink="false">http://blog.joaomorais.com.br/?p=73</guid>
		<description><![CDATA[(english)
Ao meu ver, uma parte mal elaborada do Delphi/Lazarus é o gerenciamento de formulários da aplicação. Tanto o fato de usar uma variável pública independente para controlar a instância quanto a isca &#8216;jogue tudo no form&#8217; trazem problemas. A primeira abordagem exige que o programador, ou crie os formulários no início da aplicação e não [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.joaomorais.com.br/2008/08/31/forms-management-tip.html">(english)</a></p>
<p>Ao meu ver, uma parte mal elaborada do Delphi/Lazarus é o gerenciamento de formulários da aplicação. Tanto o fato de usar uma variável pública independente para controlar a instância quanto a isca &#8216;jogue tudo no form&#8217; trazem problemas. A primeira abordagem exige que o programador, ou crie os formulários no início da aplicação e não os destrua mais, ou exige que ele cuide para não deixar a variável apontar para um objeto destruído. A segunda abordagem, entre outros problemas, exige que a primeira funcione perfeitamente para que ocorra comunicação entre formulários. <span id="more-73"></span></p>
<p>Quanto a segunda abordagem não há muito o que fazer. Ou convive-se com a limitação ou escreve-se um novo framework para contorná-la. Agora, para manter a variável pública atualizada, o programador pode beneficiar-se de pequenos truques como o que eu vou citar aqui.</p>
<p>A minha sugestão para manter a variável pública atualizada é passá-la para um método de classe. Este método cuida de inicializar o form caso necessário, e cuida de atualizar a variável quando o form for destruído. Para isto, implemente o seguinte método na classe base dos formulários, ou seja, aquela classe a partir da qual todos os forms irão herdar:</p>
<pre>
  TBaseForm = class(TForm)
  public
    destructor Destroy; override;
    class procedure Execute(var AForm; AModal: Boolean = False);
  end;
</pre>
<p>a implementação dos métodos fica assim:</p>
<pre>
class procedure TBaseForm.Execute(var AForm; AModal: Boolean);
var
  VIndex: Integer;
begin
  if not Assigned(_Forms) then
  begin
    _Forms := TStringList.Create;
    _Forms.Sorted := True;
  end;
  if not _Forms.Find(ClassName, VIndex) then
    VIndex := _Forms.Add(ClassName);
  if TForm(AForm) = nil then
    Application.CreateForm(Self, AForm);
  _Forms.Objects[VIndex] := TObject(@AForm);
  if AModal then
    TForm(AForm).ShowModal
  else
    TForm(AForm).Show;
end;
</pre>
<p>e associar nil à variável pública do form no momento em que ele for destruído:</p>
<pre>
destructor TBaseForm.Destroy;
type
  PForm = ^TForm;
var
  VIndex: Integer;
begin
  if Assigned(_Forms) and _Forms.Find(ClassName, VIndex) and
   (_Forms.Objects[VIndex] <> nil) then
  begin
    PForm(_Forms.Objects[VIndex])^ := nil;
    _Forms.Objects[VIndex] := nil;
  end;
  inherited;
end;
</pre>
<p>Por fim, falta declarar a StringList e destruí-la no encerramento da aplicação:</p>
<pre>
implementation

var
  _Forms: TStringList = nil;

...

initialization

finalization
  _Forms.Free;

end.
</pre>
<p>Pronto. Agora basta criar novos forms que descendam deste e chamar TSeuForm.Execute(SeuForm). Quando o form for destruído, a variável pública irá apontar para nil.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.joaomorais.com.br/2008/08/31/dica-gerenciamento-form.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Ponteiros e alocação dinâmica</title>
		<link>http://blog.joaomorais.com.br/2008/08/23/ponteiros.html</link>
		<comments>http://blog.joaomorais.com.br/2008/08/23/ponteiros.html#comments</comments>
		<pubDate>Sat, 23 Aug 2008 19:28:32 +0000</pubDate>
		<dc:creator>Joao Morais</dc:creator>
		
		<category><![CDATA[Object Pascal]]></category>

		<guid isPermaLink="false">http://blog.joaomorais.com.br/?p=46</guid>
		<description><![CDATA[Tem um ditado que diz: Eu não sei, mas tenho o telefone de quem sabe. Trabalhar com ponteiros é muito parecido com isto, mas o ditado fica assim: Eu não sei, mas tenho o endereço de quem sabe. 
Alguns tipos de variáveis são chamadas de Ponteiro porque elas apontam para algum endereço de memória. Isto [...]]]></description>
			<content:encoded><![CDATA[<p>Tem um ditado que diz: <em>Eu não sei, mas tenho o telefone de quem sabe.</em> Trabalhar com ponteiros é muito parecido com isto, mas o ditado fica assim: <em>Eu não sei, mas tenho o endereço de quem sabe.</em> <span id="more-46"></span></p>
<p>Alguns tipos de variáveis são chamadas de <em>Ponteiro</em> porque elas apontam para algum endereço de memória. Isto aparentemente complica a vida do programador, pois além de tratar da informação é necessário tratar também do endereço da informação. E não é só isto: basta uma variável ponteiro fazendo referência a uma área que não lhe diz respeito, e na melhor das hipóteses a aplicação emitirá uma <em>Violação de acesso à memória</em>. O lado bom é que sistemas operacionais modernos (para não dizer decentes) seguram o tranco e não deixam você destruir outras aplicações ou ele próprio. Nos tempos do DOS era muito comum ter que recorrer ao gabinete e disparar um reset via hardware.</p>
<p>Os novos tipos de dados do Object Pascal visam transformar ponteiros em algo mais simples, mais fácil de usar, ainda mais útil, e por vezes são tratados de forma tão transparente que muitas pessoas passam anos trabalhando com eles sem saber. Quer um bom exemplo? Ansi string (a string padrão do compilador Delphi, do FPC em modo delphi ou com a diretiva $H habilitada) é um ponteiro para string que é alocada e desalocada sozinha pelo compilador.</p>
<p>Segue alguns conceitos sobre o tema.</p>
<p><strong>VARIÁVEIS ESTÁTICAS</strong></p>
<p>São as variáveis da forma tradicional, que guardam a própria informação, e o compilador faz o tratamento de onde esta informação será guardada (pode ser um registrador do processador ou parte da pilha de chamadas). Não há preocupação com alocação nem liberação deste espaço por parte do programador.</p>
<pre>
var
  A: Longint;
  { A é uma variável do tipo Longint, ocupará 4 bytes, e a alocação deste espaço é tratada pelo compilador }
</pre>
<p><strong>ALOCAÇÃO DINÂMICA</strong></p>
<p>Entende-se por alocação dinâmica a criação e destruição de espaço na memória, em tempo de execução, para armazenamento e manipulação de informação. É de responsabilidade do programador desalocar toda memória que vier a alocar durante a execução do seu aplicativo, a menos que o próprio compilador faça isto. Também é dever do programador saber quando o compilador fará isto <img src='http://blog.joaomorais.com.br/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> .</p>
<p><strong>PONTEIROS</strong></p>
<p>Entende-se por ponteiros os tipos de variáveis que apontam para uma área da memória. Ponteiros podem apontar para:</p>
<ul>
<li>Áreas com informação, tal como uma variável;</li>
<li>Uma rotina (procedure, function ou método);</li>
<li>Um endereço nulo.</li>
</ul>
<p><strong>Ponteiros - Áreas com informação</strong></p>
<p>O ponteiro pode ser declarado como:</p>
<ul>
<li>tipado - ele sabe qual o tipo de informação para o qual está apontando.</li>
<li>não tipado - ele não sabe para que tipo de dado está apontando. É necessário fazer um typecast para recuperar a informação. Typecast será abordado adiante.</li>
</ul>
<p>O operador @ (arroba) pode ser usado para atribuir o endereço de uma variável para um ponteiro. Ex.:</p>
<pre>
  A := @B;
    { A recebe o endereço da variável B }
</pre>
<p>Ou ainda, um ponteiro pode receber o endereço de uma área de memória alocada especialmente para ele:</p>
<pre>
  { A - aponta para uma variável do tipo Longint }
  new(A);
    { É alocada uma área na memória, com um total de 4 bytes, e A está apontando para esta nova área }
</pre>
<p>Neste último caso o programador será responsável por esta área alocada, e deverá desalocar antes de encerrar a execução do seu programa. No primeiro caso isto não é necessário, e sequer deverá ser feito, pois o endereço de memória pertence à variável B que é de responsabilidade do compilador.</p>
<p><strong>Ponteiros - Uma rotina</strong></p>
<p>É possível criar ponteiros especialmente preparados para receber o endereço de uma rotina. Neste caso, um exemplo fala mais sobre a sua utilidade: na programação por eventos, o disparo de um click em um botão gera um evento que deve ser interpretado por uma rotina. Uma variável OnClick possui o endereço da rotina que fará o tratamento deste evento.</p>
<p><strong>Ponteiros - Um endereço nulo</strong></p>
<p>No Pascal é conhecido como <em>nil</em>. Utiliza-se associar um ponteiro à constante nil (A := nil) para que fique claro que este ponteiro não está apontando para informação alguma. Desta forma, torna-se possível a comparação:</p>
<pre>
if A = nil then
  writeln('Não há informação')
else
  writeln('A está apontando para alguma informação');
</pre>
<p><strong>DECLARAÇÃO</strong></p>
<p>Declara-se um ponteiro tipado informando o tipo da variável para o qual ele apontará, precedido pelo operador ^ (circunflexo).</p>
<pre>
var
  A: ^Longint; { A é uma variável ponteiro, e aponta para um Longint }
  B: ^string; { B é uma variável ponteiro e aponta para uma string }
</pre>
<p>É possível também declarar um ponteiro não tipado, ou seja, que não se sabe exatamente para qual tipo de informação ele irá apontar.</p>
<pre>
var
  C: Pointer;
  { C é uma variável ponteiro, e pode apontar para qualquer tipo de dado }
</pre>
<p>Pode-se declarar também um ponteiro à uma procedure ou função.</p>
<pre>
var
  D: procedure(Arg: Byte);

procedure rotina1(Arg: Byte);
begin
  writeln('Rotina 1 recebeu ', Arg);
end;

procedure rotina2(Arg: Byte);
begin
  writeln('Rotina 2 recebeu ', Arg);
end;

begin
  D := @rotina2;
  D(10); { Irá imprimir: 'Rotina 2 recebeu 10' }
end.
</pre>
<p><strong>RECUPERAÇÃO DOS DADOS</strong></p>
<p>Toda variável ponteiro (inclusive classes) possuem duas formas de se trabalhar - uma é com o endereço para o qual ela aponta, e outra é para a informação que está no respectivo endereço. Exemplo:</p>
<pre>
var
  A: ^Longint;
  B: Longint;
begin
  { A linha abaixo faz com que A aponte para o endereço de B, é lida assim:
    "A recebe o endereço de B" }
  A := @B;
    { primeira forma - utilizando o endereço para o qual A está apontando }

  { A linha abaixo guarda o valor 5 na área de memória apontada por A, é lida assim:
    "O endereço apontado por A recebe 5" }
  A^ := 5;
    { segunda forma - utilizando a informação apontada por A }

  writeln(B);
end.
</pre>
<p>Note a diferença no uso da variável. Sem circunflexo, é endereço. Com circunflexo, é a informação apontada por aquele endereço.</p>
<p><strong>TYPECAST</strong></p>
<p>O typecast informa ao compilador o tipo de dado para o qual a variável ponteiro está apontado.</p>
<p>Há situações em que não é possível determinar o tipo exato de um ponteiro em tempo de projeto. Isto é bastante comum em programação orientada a objetos, aonde o ponteiro (a variável de uma determinada classe) pode apontar para uma série de objetos semelhantes, mas não iguais entre si.</p>
<p>Apenas para fins de esclarecimento, segue uma utilização do Typecast. Não é o exemplo mais comum, mas é o mais simples de apresentar, explicar e entender:</p>
<pre>
var
  A: Pointer;
  B: Longint;
begin
  A := @B;
  B := 10;
  writeln(Longint(A^));
end;
</pre>
<p>Recordando o exemplo anterior: colocar o circunflexo após a variável ponteiro significa trabalhar com uma variável comum, que em seu conteúdo possui um número, uma string, etc. Isto é possível graças a forma com que o ponteiro é declarado:</p>
<pre>
var
  A: ^Longint; { Ponteiro para Longint }
begin
  writeln(A^); { Imprime um Longint }
</pre>
<p>Mas ao criar ponteiros não tipados com o Pointer, o compilador fica sem saber com o que está trabalhando quando o circunflexo é utilizado após a variável.</p>
<p><strong>DESALOCANDO O QUE FOI ALOCADO</strong></p>
<p>Tudo o que foi alocado pelo programador, e que não é controlado pelo compilador, deverá ser desalocado logo que possível.</p>
<pre>
var
  A: ^Longint;
begin
  New(A); { Aloca uma área na memória para armazenar um Longint }
  A^ := 10; { Coloca o valor 10 nessa nova área da memória }
  Dispose(A); { Desaloca o espaço reservado pela procedure New }
end;
</pre>
<p><strong>CONCLUSÃO</strong></p>
<p>Estes tópicos abordam tudo o que diz respeito a ponteiros. Conforme colocado, existe mais assunto relacionado devido aos novos tipos de dados do Object Pascal, tal como arrays dinâmicos, classes e interfaces, ansi strings, entre outros. No entanto todos estes tipos trabalham sobre estes conceitos recém abordados, o que muda é a interface do uso e a forma de alocar, acessar e desalocar esta área de memória.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.joaomorais.com.br/2008/08/23/ponteiros.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Decouple MVP and VCL with Interfaces.</title>
		<link>http://blog.joaomorais.com.br/2008/08/16/mvp-with-interfaces.html</link>
		<comments>http://blog.joaomorais.com.br/2008/08/16/mvp-with-interfaces.html#comments</comments>
		<pubDate>Sat, 16 Aug 2008 19:41:27 +0000</pubDate>
		<dc:creator>Joao Morais</dc:creator>
		
		<category><![CDATA[MVP-en]]></category>

		<guid isPermaLink="false">http://blog.joaomorais.com.br/?p=61</guid>
		<description><![CDATA[(portuguese)
Contrary to some object oriented programming gurus, I was not much into interfaces. The first uses were under utilized, as just a memory manager assistant (interfaces in object pascal have reference counting maintained by the compiler, contrary to classes). 
With the progress of the PressObjects&#8217; development,  it becomes necessary more frequently to make some [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.joaomorais.com.br/2008/08/16/mvp-com-interfaces.html">(portuguese)</a></p>
<p>Contrary to some object oriented programming gurus, I was not much into interfaces. The first uses were under utilized, as just a memory manager assistant (interfaces in object pascal have reference counting maintained by the compiler, contrary to classes). <span id="more-61"></span></p>
<p>With the progress of the PressObjects&#8217; development,  it becomes necessary more frequently to make some classes completely abstract in order to decouple the implementation of the classes. Something like (tersely summarized):</p>
<pre>
TIDEIntf = class(TObject)
Public
  procedure ReadText(...); virtual; abstract;
  procedure SaveText(...); virtual; abstract;
end;
</pre>
<p>Then, an implementation for Delphi, another for Lazarus and still another one for MSEide:</p>
<pre>
TDelphiIDEIntf = class(TIDEIntf)
public
  procedure ReadText(...); override;
  procedure SaveText(...); override;
end;
</pre>
<p>Two other identical declarations for Lazarus and MSEide, which differ from the Delphi version only in the implementation of each method. An advantage is to have a single routine that changes the IDE editor&#8217;s information (an Expert) through a common interface (the TIDEIntf class) and use this same expert in three different IDEs. The support of a new IDE is done by creating a new class that overloads these virtual methods.</p>
<p>This is a very simple example in which interface can be used instead of the abstract class. There is a disadvantage to the proposed model, which is exactly the propose of interfaces, and it&#8217;s not evident as the model does not become a limitation for the programmer (at least for now): the classes that implement the IDE functionality are required to descent from the TIDEIntf.</p>
<p>This disadvantage becomes much more evident when implementing decoupling between an MVP View and the VCL/LCL graphics library.</p>
<p>An MVP View is what is between the framework&#8217;s core and a visual control. There exists a View for ComboBox controls, which manages some events such as OnExit, OnDropDown, among others, and translates those to events that the framework understands. Same goes for a View that manages an Edit. Events such as OnEnter and OnChange are redirected.</p>
<p>Other than managing the events, a View has methods to access or manage and avoiding that the framework has direct access to the control (avoiding coupling). For example, a ComboBox View has a DropDown method, that makes the control drop down a list. The Edit and ComboBox have a property AsText, that reads and writes the control&#8217;s Text property.</p>
<p>Having understood how the View works, lets proceed to the next part. There is a necessity to decouple the View from the VCL classes. Why? Because there are other excellent options that can be used with the MVP instead of the VCL. Some of these are MSEgui, Kol/Mck, and for FPC (FreePascal Compiler) there is fpGUI (the LCL does not count as alternative, since it has the same interface as the VCL and its Views do use the same implementation).</p>
<p>My first idea was to create abstract classes, like the above examples, one for a ComboBox View and another for the Edit View. In simplified form it would be like this:</p>
<pre>
TEditView = class(TObject)
public
  procedure Text(...); virtual; abstract;
end;

TComboBoxView = class(TObject)
public
  procedure DropDown; virtual; abstract;
  procedure Text(...); virtual; abstract;
end;
</pre>
<p>And the concrete classes would be like so:</p>
<pre>
TVCLEditView = class(TEditView)
public
  procedure Text(...); override;
end;

TVCLComboBoxView = class(TComboBoxView)
public
  procedure DropDown; override;
  procedure Text(...); override;
end;
</pre>
<p>Different units would implement different set of classes. One for VCL/LCL, another for MSEgui, another for fpGUI, etc. To support a new graphics library, just implement a unit that overrides all these classes&#8217; methods.</p>
<p>So we have virtual methods in the abstract class, and in another unit exists concrete classes that overrides such methods in order to reach the visual components. The framework&#8217;s core accesses this abstract class, and the concrete class is the one that really accesses the visual control as this is coupled to the graphics library. A class register indicates that the user will use VCL, MSE or any other library.</p>
<p>Now the problem: Note that some components share characteristics, in the above example both ComboBox and Edit have a Text that does the same thing.</p>
<p>To remove the coupling between the View and the VCL, allowing code sharing and behavior through inheritance, I decided to create a set of interfaces that the concrete classes need to implement. The implementation is like so:</p>
<pre>
ICustomView = interface(IInterface)
[...]
  procedure Text(...);
end;

IEditView = interface(ICustomView)
[...]
end;

IComboBoxView = interface(ICustomView)
[...]
  procedure DropDown;
end;
</pre>
<p>An the classes that implement the interface, reusing code and maintaining zero coupling:</p>
<pre>
TVCLCustomView = class(TMyIntfObject, ICustomView)
public
  procedure Text(...);
end;

TVCLEditView = class(TVCLCustomView, IEditView)
end;

TVCLComboBoxView = class(TVCLCustomView, IComboBoxView)
public
  procedure DropDown;
end;
</pre>
<p>Note that in this model its possible to reuse the same Text procedure in both classes.  In the model that only uses classes, every descendant class needs to implement their own text as they can not inherit from a common class.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.joaomorais.com.br/2008/08/16/mvp-with-interfaces.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Desacoplar MVP e VCL com Interfaces</title>
		<link>http://blog.joaomorais.com.br/2008/08/16/mvp-com-interfaces.html</link>
		<comments>http://blog.joaomorais.com.br/2008/08/16/mvp-com-interfaces.html#comments</comments>
		<pubDate>Sat, 16 Aug 2008 19:40:53 +0000</pubDate>
		<dc:creator>Joao Morais</dc:creator>
		
		<category><![CDATA[MVP]]></category>

		<guid isPermaLink="false">http://blog.joaomorais.com.br/?p=30</guid>
		<description><![CDATA[(english)
Ao contrário de alguns astros da programação orientada a objetos, eu não era muito fã de interface. Os primeiros usos foram sub-utilizados, como mero auxiliar de gerenciamento de memória (interface em Object Pascal tem contagem de referência controlada pelo compilador, ao contrário de classes). 
Com o avanço no desenvolvimento do PressObjects, tornou-se cada vez mais [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.joaomorais.com.br/2008/08/16/mvp-with-interfaces.html">(english)</a></p>
<p>Ao contrário de alguns astros da programação orientada a objetos, eu não era muito fã de interface. Os primeiros usos foram sub-utilizados, como mero auxiliar de gerenciamento de memória (interface em Object Pascal tem contagem de referência controlada pelo compilador, ao contrário de classes). <span id="more-30"></span></p>
<p>Com o avanço no desenvolvimento do PressObjects, tornou-se cada vez mais comum a necessidade de desacoplar implementações a um ponto aonde certas classes passaram a ser totalmente abstratas. Algo assim (bem resumido):</p>
<pre>
TIDEIntf = class(TObject)
public
  procedure ReadText(...); virtual; abstract;
  procedure SaveText(...); virtual; abstract;
end;
</pre>
<p>E então, uma implementação para Delphi, outra para Lazarus e outra ainda para MSEide:</p>
<pre>
TDelphiIDEIntf = class(TIDEIntf)
public
  procedure ReadText(...); override;
  procedure SaveText(...); override;
end;
</pre>
<p>Outras duas declarações idênticas para Lazarus e MSEide. A diferença fica por conta da implementação de cada método, que utiliza rotinas próprias de cada uma destas IDEs. A vantagem é ter uma única rotina que lê e altera dados do editor da IDE (um Expert) através de um meio comum (a classe TIDEIntf) e utilizar este mesmo expert em três IDEs diferentes. E para aumentar o número de IDEs, basta implementar uma nova classe que sobrecarregue estes métodos virtuais.</p>
<p>Este é um exemplo bem simples em que uma interface pode ser utilizada no lugar da classe abstrata. Existe uma desvantagem no modelo proposto, e que é justamente a proposta das interfaces, mas que no entanto não está tão evidente porque o modelo não converte-se em limitação para o programador (ao menos por enquanto): as classes que implementam as funcionalidades para a IDE devem obrigatoriamente ser descendentes de TIDEIntf.</p>
<p>Esta desvantagem tornou-se mais evidente durante a implementação do desacoplamento ocorrido entre a View de um framework MVP e a biblioteca gráfica VCL/LCL.</p>
<p>Uma View de um framework MVP é o que faz a ponte entre o núcleo deste framework e um controle visual. Existe uma View para controles ComboBox, ao ser criada ela direciona alguns eventos como OnExit, OnDropDown, entre outros, e transforma-os em eventos que o framework conhece. Mesma coisa para a View que controla um Edit. Eventos como OnEnter e OnChange são redirecionados.</p>
<p>Além de controlar os eventos, a View possui métodos para acessar o controle e evitar que o framework faça referência direta a ele (evitando acoplamento). Exemplo, a View do controle ComboBox possui um método DropDown, que faz com que o controle abra uma lista. O Edit e o ComboBox possuem uma propriedade AsText, que lê e grava o conteúdo da propriedade Text do controle.</p>
<p>Tendo entendido como a View funciona, passemos para a próxima parte. Eu enxerguei a necessidade de desacoplar a View e classes da VCL. Por quê? Porque existem opções tão boas e até melhores do que a VCL para ser usado pelo MVP. Alguns exemplos são MSEgui, Kol/Mck, e para FPC ainda existe fpGUI (a LCL não conta, ela tem a mesma interface da VCL e suas Views utilizam a mesma implementação).</p>
<p>Tudo bem. Minha primeira idéia foi criar classes abstratas, que nos exemplos acima, seria uma para a View do ComboBox e outra para a View do Edit. Elas, de forma bem simplificada, ficariam assim:</p>
<pre>
TEditView = class(TObject)
public
  procedure Text(...); virtual; abstract;
end;

TComboBoxView = class(TObject)
public
  procedure DropDown; virtual; abstract;
  procedure Text(...); virtual; abstract;
end;
</pre>
<p>E as classes concretas, assim:</p>
<pre>
TVCLEditView = class(TEditView)
public
  procedure Text(...); override;
end;

TVCLComboBoxView = class(TComboBoxView)
public
  procedure DropDown; override;
  procedure Text(...); override;
end;
</pre>
<p>Diferentes units implementam diferentes conjuntos de classes. Uma unit para VCL/LCL, outra para MSEgui, outra para fpGUI e assim por diante. Para incluir uma nova biblioteca gráfica, basta implementar uma unit que sobrecarregue os métodos de todas estas classes.</p>
<p>Então temos métodos virtuais na classe abstrata, e em outra unit existe a classe concreta que sobrecarrega estes métodos e faz o acesso direto ao componente visual. O núcleo do framework acessa a classe abstrata, e a classe concreta é quem realmente acessa o controle visual porque apenas ela está acoplada à biblioteca gráfica. Um registro de classe feito pelo usuário dirá que ele vai trabalhar com VCL, MSE, ou seja lá qual for.</p>
<p>Agora o problema: note que alguns componentes compartilham características, no exemplo acima tanto ComboBox quanto Edit possuem um Text que fazem a mesma coisa.</p>
<p>Para remover o acoplamento entre View e VCL, e permitir aproveitamento de código e comportamento através de herança, eu decidi criar um conjunto de interfaces que descrevem o que as classes concretas devem implementar. A implementação ficou desta forma:</p>
<pre>
ICustomView = interface(IInterface)
[...]
  procedure Text(...);
end;

IEditView = interface(ICustomView)
[...]
end;

IComboBoxView = interface(ICustomView)
[...]
  procedure DropDown;
end;
</pre>
<p>E as classes que implementam a interface, reaproveitando tanto código quanto possível, com acoplamento zero:</p>
<pre>TVCLCustomView = class(TMyIntfObject, ICustomView)
public
  procedure Text(...);
end;

TVCLEditView = class(TVCLCustomView, IEditView)
end;

TVCLComboBoxView = class(TVCLCustomView, IComboBoxView)
public
  procedure DropDown;
end;
</pre>
<p>Note que apenas neste modelo é possível reaproveitar uma única procedure Text nas duas classes. No modelo que utiliza apenas classes, cada descendente deveria implementar seu próprio Text porque elas não poderiam herdar de uma classe em comum.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.joaomorais.com.br/2008/08/16/mvp-com-interfaces.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>do jmp às Interfaces - A história do acoplamento</title>
		<link>http://blog.joaomorais.com.br/2008/08/09/do-jmp-as-interfaces.html</link>
		<comments>http://blog.joaomorais.com.br/2008/08/09/do-jmp-as-interfaces.html#comments</comments>
		<pubDate>Sat, 09 Aug 2008 18:46:28 +0000</pubDate>
		<dc:creator>Joao Morais</dc:creator>
		
		<category><![CDATA[OO em Geral]]></category>

		<guid isPermaLink="false">http://blog.joaomorais.com.br/2008/08/09/do-jmp-as-interfaces.html</guid>
		<description><![CDATA[No princípio era o jmp. E o call. E o ret. E os saltos condicionais. E com isto os heróicos programadores da época conseguiam criar laços e blocos cuja execução dependia de alguma condição ter sido satisfeita. E a máquina começou a pensar. Um label indicava ao assembler aonde determinada rotina estava começando, e o [...]]]></description>
			<content:encoded><![CDATA[<p>No princípio era o jmp. E o call. E o ret. E os saltos condicionais. E com isto os heróicos programadores da época conseguiam criar laços e blocos cuja execução dependia de alguma condição ter sido satisfeita. E a máquina começou a pensar. Um label indicava ao assembler aonde determinada rotina estava começando, e o assembler transformava aquele label em um endereço de memória. Entre o label e o ret estava o que conhecemos hoje por procedure.<span id="more-29"></span></p>
<p>E então nascia a linguagem de alto nível. E os whiles. E os fors. E os ifs. E com isto os saltos condicionais tornaram-se mais humanos e transformaram-se em blocos quase compreensíveis. O label deu lugar a um cabeçalho com informações de passagem de parâmetro e o ret deu lugar à declaração do final daquele bloco. Nascia também a procedure, ou function, caso retorne algum valor.</p>
<p>Variáveis públicas acessíveis demais. Variáveis locais acessíveis de menos. E nascia a orientação a objetos com objetivo de ligar informação e código em uma mesma entidade. Cada objeto tem seus próprios membros, e cada procedure ou function &#8212; agora método &#8212; chamado através daquele objeto, têm acesso irrestrito aos seus respectivos membros. Nascia o encapsulamento, e a preocupação com a segurança da informação.</p>
<p>Objetos estáticos são inflexíveis, e então nascia o ponteiro para objetos com o objetivo de tornar seu manuseio, digamos, mais dinâmico. Depois de polido e ganhar novos recursos, os ponteiros para objetos passaram a se chamar classe.</p>
<p>E nascia o polimorfismo. Métodos das classes passam a ser escritos pensando sempre em reaproveitamento e customização. Registro de classes, métodos virtuais, acesso a rotinas de classes abstratas. E explodia o uso do reaproveitamento de código.</p>
<p>E com o fortalecimento do polimorfismo e reaproveitamento de código, quem enfraquecia era o acoplamento. A rotina que precisa de um recurso não precisa mais depender daquele recurso. Cria-se uma classe abstrata, utiliza-se o recurso através de um método virtual desta classe, implementa-se o recurso através de uma classe descendente e sobrecarregando o método, e por fim registra-se a classe que implementa o recurso. Um certo método M (notificação por email) que precisa de um certo recurso X (rotina de envio de emails) irá acessar uma classe abstrata A (TEnviaEmail) sem acoplar seu próprio código a um componente específico. Uma certa classe B (TIndyEnviaEmail), que descende de A, implementa o envio de emails através do framework Indy.</p>
<p>O enfraquecimento do acoplamento de implementação aumentou o uso de classes que precisam descender daquelas classes reconhecidas na outra camada. No caso acima, a classe B sempre descende da classe A. E passou a ocorrer um acoplamento entre uma hierarquia de classes.</p>
<p>E nascia então a interface. E a classe B não precisa mais descender da classe A, ela pode não descender de ninguém ou pode descender de outras classes que o método M não conhece. A classe B precisa apenas implementar métodos que o método M precisa chamar. Ou seja, a classe B precisa apenas implementar os métodos da interface I, e esta sim é conhecida por M.</p>
<p>E morria o acoplamento.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.joaomorais.com.br/2008/08/09/do-jmp-as-interfaces.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Construindo um interpretador orientado a objetos</title>
		<link>http://blog.joaomorais.com.br/2008/02/10/construindo_interpretador_oo.html</link>
		<comments>http://blog.joaomorais.com.br/2008/02/10/construindo_interpretador_oo.html#comments</comments>
		<pubDate>Sun, 10 Feb 2008 19:53:12 +0000</pubDate>
		<dc:creator>Joao Morais</dc:creator>
		
		<category><![CDATA[OO em Geral]]></category>

		<guid isPermaLink="false">http://blog.joaomorais.com.br/2008/02/10/construindo_um_interpretador_oo.html</guid>
		<description><![CDATA[Outro dia precisei colocar fórmula em um dos sistemas que desenvolvo, para que o usuário tenha mais liberdade para informar como um custo deva ser calculado. É permitido que ele faça algo como 0.012 * 66 * 96 * Chapas / FormatoImpressao, aonde as variáveis apresentadas são atributos do objeto de negócio. 
Nada tão sério, [...]]]></description>
			<content:encoded><![CDATA[<p>Outro dia precisei colocar fórmula em um dos sistemas que desenvolvo, para que o usuário tenha mais liberdade para informar como um custo deva ser calculado. É permitido que ele faça algo como <code>0.012 * 66 * 96 * Chapas / FormatoImpressao</code>, aonde as variáveis apresentadas são atributos do objeto de negócio. <span id="more-24"></span></p>
<p>Nada tão sério, existem alguns interpretadores de fórmula matemática por aí, no entanto dois motivos me fizeram implementar meu próprio interpretador: primeiro a falta de integração com meu framework, a menos que o parser fosse customizável suficiente para que eu construisse outro interpretador em cima dele para a interpretação dos meus atributos; segundo que eu perderia a oportunidade impar de construir outro parser, e ainda mais um para interpretação de fórmula matemática. A seguir conto um pouco sobre ele e como se constroi um interpretador.</p>
<p>Escrever o PressObjects fez com que eu precisasse pegar o espírito da coisa para construção de interpretadores. O projeto tem vários, como um interpretador Pascal para alteração automatizada dos fontes do projeto, um interpretador de arquivo de configuração para permitir a configuração de serviços (tal como um conector para banco de dados, entre vários outros) sem a necessidade de alterar o binário do projeto, um interpretador de metadata (parecido com DDL de bancos de dados) para criar classes de negócio com informações de runtime, e um interpretador de OQL (object query language) que transforma uma consulta orientada a objetos para uma SQL que bancos relacionais possam entender.</p>
<p>O interpretador de fórmula não seria tão diferente destes outros, utilizaria as mesmas classes base e precisaria meramente entender uma gramática diferente: uma fórmula matemática. Este interpretador já está disponível na versão atual do PressObjects (download <a href="http://pressobjects.org/snapshot/press-snapshot-20080209-r794.zip">aqui</a>)</p>
<p>Os interpretadores que construi foram baseados no padrão de projeto Interpreter (do GoF), com algumas adaptações que eu julguei pertinente. Na minha variante, um interpretador está dividido em duas partes: o reader e o parser.</p>
<p><strong>O reader</strong></p>
<p>O reader é a parte do interpretador que desmonta a entrada em partes menores, os tokens. Para a fórmula 22+-5*AB os tokens são 22, +, -5, * e AB. Essa parte parece moleza, mas cuidado com o julgamento precipitado. São vários os tipos de entrada que o interpretador precisa reconhecer, ele precisa entender quando um token termina, precisa reconhecer sinais iguais com significados diferentes, ex, aquele menos logo acima é um sinal, e não um operador. E por último mas não menos importante, precisa ter vários métodos para que tenha um uso tão simplificado quanto possível pelo parser.</p>
<p>O bom do reader é que, uma vez construido, ele será o mesmo para a esmagadora maioria de interpretadores, com alguma pequena customização como o token &#8220;>=&#8221;. Algumas gramáticas interpretam esta sequência como dois tokens, outras o lêem inteiro como um único token de dois caracteres.</p>
<p><strong>O parser</strong></p>
<p>Concluido o reader é hora de construir o parser. O parser é um conjunto de classes utilizadas para dar vida à gramática, e são dois os métodos mais importantes de cada uma de suas classes: apply e read.</p>
<p>O apply tem a função de validar a próxima entrada do reader, se a entrada bater com o que esta classe do parser está esperando, retorna verdadeiro. Exemplo:</p>
<pre>
class function TAddOperation.Apply(Reader: TParserReader): Boolean;
begin
  Result := Reader.ReadToken = '+';
end;
</pre>
<p>Simples assim. Se o próximo token para o qual o reader aponta for um sinal de mais, então a classe que interpreta o sinal de mais pode receber aquela entrada.</p>
<p>Já o read tem a função de ler e interpretar a entrada atual, devidamente apontada pelo reader. Para um exemplo mais simples, vou criar uma classe completa para ler o corpo de um select bem simplificado:</p>
<pre>class function TSelect.Apply(Reader: TParserReader): Boolean;
begin
  Result := SameText(Reader.ReadToken, 'select');
end;

procedure TSelect.Read(Reader: TParserReader);
begin
  Reader.ReadMatchText('select');
  FFields := Parse(Reader, [TSelectFields], 'campo(s) da tabela');
  Reader.ReadMatchText('from');
  FTableName := Reader.ReadIdentifier;
  FWhere := Parse(Reader, [TSelectWhere]);
  FOrderBy := Parse(Reader, [TSelectOrderBy]);
end;
</pre>
<p>ReadMatchText é um método do reader que verifica se a próxima entrada é o que está no parâmetro. Se não for ele ergue uma exception e nem deixa o processamento seguir adiante. ReadIdentifier lê o próximo token e ergue uma exception se o token não for um nome de identificador válido. Parse é um método do próprio parser que recebe uma lista de classes e verifica se alguma delas retorna True ao chamar o respectivo Apply. A primeira que retornar é a que interpretará a entrada, se nenhuma retornar ele erguerá uma exception caso o último argumento tenha o nome do que ele estava esperando. Ele também retorna o objeto que interpretou a entrada e deixa o reader no ponto para o próximo.</p>
<p>Para que o parser chegue ao seu objetivo, que é entregar informação mastigada, basta construir novos métodos que leiam as informações a partir dos objetos que foram criados. Estes objetos, no exemplo acima, são apontados pelo FFields, FTable, FWhere, FOrderBy. No caso do interpretador de fórmula, ele converte a entrada em uma lista de operações que será executada quando o usuário pedir o resultado da fórmula.</p>
<p>Que tal o truque? Não que um interpretador seja um primor de simplicidade, mas ele torna muito mais simples a construção de gramáticas, e diga-se de passagem com uma grande ajuda da programação orientada a objetos.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.joaomorais.com.br/2008/02/10/construindo_interpretador_oo.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Como remover vazamentos de memória</title>
		<link>http://blog.joaomorais.com.br/2008/02/06/remover-vazamento-de-memoria.html</link>
		<comments>http://blog.joaomorais.com.br/2008/02/06/remover-vazamento-de-memoria.html#comments</comments>
		<pubDate>Wed, 06 Feb 2008 10:26:08 +0000</pubDate>
		<dc:creator>Joao Morais</dc:creator>
		
		<category><![CDATA[Object Pascal]]></category>

		<guid isPermaLink="false">http://blog.joaomorais.com.br/2008/02/06/remover-vazamento-de-memoria.html</guid>
		<description><![CDATA[Ferramentas como FastMM melhoram o desempenho de aplicações que utilizam muita alocação dinâmica, e de quebra ainda relata se a aplicação está deixando vazamentos de memória.
Agora saber que a aplicação tem vazamento de memória é fácil, no entanto, dependendo do tamanho do projeto, torna-se mais difícil determinar aonde ela foi alocada. 
Os passos abaixo ajudam [...]]]></description>
			<content:encoded><![CDATA[<p>Ferramentas como FastMM melhoram o desempenho de aplicações que utilizam muita alocação dinâmica, e de quebra ainda relata se a aplicação está deixando vazamentos de memória.</p>
<p>Agora saber que a aplicação tem vazamento de memória é fácil, no entanto, dependendo do tamanho do projeto, torna-se mais difícil determinar aonde ela foi alocada. <span id="more-23"></span></p>
<p>Os passos abaixo ajudam a localizar a criação do objeto (em Delphi). Bom, o problema não é o fato de ele ter sido criado, mas sim de não ter sido destruido. Se este objeto não tem contagem de referência, então o trabalho será bem mais simples.</p>
<ul>
<li>Baixe o MemCheck <a href="http://v.mahon.free.fr/pro/freeware/memcheck/">aqui</a></li>
<li>Coloque-o como a primeira unit do seu .dpr (temporariamente no lugar do seu gerenciador de memória);</li>
<li>logo após o begin, coloque uma chamada à procedure MemChk;</li>
<li>Em project | options | compiler, ligue o stack frames;</li>
<li>Em project | options | linker, ligue o include TD32 debug info;</li>
<li>Dê um build all no projeto.</li>
</ul>
<p>Quando sua aplicação for fechada, o MemChk vai gerar uma exception no ponto em que o projeto aloca memória que não foi desalocada.</p>
<p>Depois de resolver o vazamento, lembre-se de voltar ao seu gerenciador de memória, desabilitar o stack frames e as informações de debug.</p>
<p>Se você tiver outras dicas, deixe-as nos comentários.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.joaomorais.com.br/2008/02/06/remover-vazamento-de-memoria.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>Wiki do PressObjects</title>
		<link>http://blog.joaomorais.com.br/2007/11/30/wiki-do-pressobjects.html</link>
		<comments>http://blog.joaomorais.com.br/2007/11/30/wiki-do-pressobjects.html#comments</comments>
		<pubDate>Fri, 30 Nov 2007 21:54:49 +0000</pubDate>
		<dc:creator>Joao Morais</dc:creator>
		
		<category><![CDATA[PressObjects]]></category>

		<guid isPermaLink="false">http://blog.joaomorais.com.br/2007/11/30/wiki-do-pressobjects.html</guid>
		<description><![CDATA[Há alguns posts atrás prometi colocar alguns artigos sobre PressObjects neste blog. Depois de terminar o rascunho do primeiro artigo, notei que ele tem um foco diferente do que tem sido aplicado aqui, sem falar que o próprio projeto tem muito pouco material. Resolvi escrever tais artigos diretamente para o projeto, e para tanto dei [...]]]></description>
			<content:encoded><![CDATA[<p>Há alguns posts atrás prometi colocar alguns artigos sobre PressObjects neste blog. Depois de terminar o rascunho do primeiro artigo, notei que ele tem um foco diferente do que tem sido aplicado aqui, sem falar que o próprio projeto tem muito pouco material. Resolvi escrever tais artigos diretamente para o projeto, e para tanto dei início a um wiki que você pode conferir <a href="http://wiki.pressobjects.org">aqui</a>.</p>
<p>Estes primeiros artigos vão para o wiki num instante, e vou deixar para o blog a missão de mandar algum recado ou publicar material que envolva ponto de vista.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.joaomorais.com.br/2007/11/30/wiki-do-pressobjects.html/feed</wfw:commentRss>
		</item>
	</channel>
</rss>

