<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Object Pascal Programming</title>
    <description>Sacadas sobre Programação Orientada a Objetos e Object Pascal.
</description>
    <link>http://objectpascalprogramming.com/</link>
    <atom:link href="http://objectpascalprogramming.com/feed.xml" rel="self" type="application/rss+xml" />
    
      <item>
        <title>Memória Segura Utilizando Instâncias de Interfaces</title>
        <description>&lt;p&gt;Você sabe que ao utilizar instâncias de interfaces não é necessário destruir o objeto manualmente, utilizando o método &lt;code&gt;Free&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Isso ocorre por quê instâncias de interfaces possuem uma contagem de referência e, assim, o compilador sabe quando desalocar a instância automaticamente.&lt;/p&gt;

&lt;p&gt;Mas e se se ocorrer uma exceção dentro de um método de uma instância, numa composição de instâncias de interfaces, seria seguro não utilizar &lt;code&gt;try-finally&lt;/code&gt; para ter a certeza que todos os objetos serão desalocados, atribuindo &lt;code&gt;nil&lt;/code&gt; as instâncias?&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;&lt;img src=&quot;/images/2019/gabriel-gurrola-424227-unsplash.jpg&quot; alt=&quot;Unsplash image&quot; /&gt;
&lt;br /&gt;&lt;span style=&quot;font-family: &#39;Bebas Neue&#39;; font-size: 0.7em;&quot;&gt;Photo by Gabriel Gurrola on Unsplash&lt;/span&gt;&lt;/p&gt;

&lt;h2 id=&quot;introducao&quot;&gt;Introdução&lt;/h2&gt;

&lt;p&gt;Na semana passada eu recebi um email de um leitor do blog, o Carlos, e ele me questionou sobre ter ou não segurança na desalocação apropriada de memória quando utilizamos instâncias de interfaces.&lt;/p&gt;

&lt;p&gt;A dúvida dele é interessante.&lt;/p&gt;

&lt;p&gt;Segundo Carlos, utilizar instancias de interfaces seria inseguro em comparação com instâncias de classes, pois “se uma exceção ocorrer dentro de algum método, você não terá a chance de desalocar as variáveis de interfaces como fazemos com o &lt;code&gt;try-finally&lt;/code&gt; e instâncias de classes” — ele escreveu.&lt;/p&gt;

&lt;p&gt;Então ele me enviou um projeto de teste que “provaria” que instâncias de interfaces poderiam ser inseguras e que não há vantagem em relação às instâncias de classes no quesito desalocação de memória pois, segundo ele, seríamos obrigados a utilizar o &lt;code&gt;try-finally&lt;/code&gt; para estarmos “100% seguro”.&lt;/p&gt;

&lt;p&gt;O exemplo era um pouco mais complexo do que deveria, então eu o reescrevi e enviei à ele. Ele concordou que ficou mais &lt;a href=&quot;/posts/simplicidade/&quot;&gt;simples&lt;/a&gt; de entender mas, o novo exemplo ainda demonstrava que ele estava certo — ele afirmou — pois ainda haviam os vazamentos de memória no final da execução do programa.&lt;/p&gt;

&lt;p&gt;Mas até aquele momento, eu só queria ter uma base de código mais simples para, então, mostrar-lhe uma segunda opinião.&lt;/p&gt;

&lt;h2 id=&quot;codigo&quot;&gt;Código&lt;/h2&gt;

&lt;p&gt;O código original foi reescrito, porém a nova versão contem todos os “problemas” apontados por ele e, consequentemente, a mesma saída no final da execução.&lt;/p&gt;

&lt;p&gt;Esse é o código completo:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;program Project1;

{$mode delphi}

uses
  SysUtils, Classes;

type
  IFoo = interface
    procedure Execute;
  end;

  IBar = interface
    procedure Execute;
  end;

  TFoo = class(TInterfacedObject, IFoo)
  private
    fBar: IBar;
  public
    constructor Create(const aBar: IBar);
    procedure Execute;
  end;

  TBar = class(TInterfacedObject, IBar)
  public
    procedure Execute;
  end;

{ TFoo }

constructor TFoo.Create(const aBar: IBar);
begin
  inherited Create;
  fBar := aBar;
end;

procedure TFoo.Execute;
begin
  fBar.Execute;
end;

{ TBar }

procedure TBar.Execute;
begin
  raise Exception.Create(&#39;exception!!!&#39;);
end;

var
  foo: IFoo;
begin
  foo := TFoo.Create(TBar.Create);
  foo.Execute;
end.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;É um aplicativo de linha-de-comando.&lt;/p&gt;

&lt;p&gt;Crie um novo projeto e não se esqueça de marcar a opção para ver o resultado da memória — se você estiver utilizando Lazarus, marque a opção “Use Heaptrc…” em Project Options, debugging.&lt;/p&gt;

&lt;p&gt;O término do programa deverá ser algo parecido com isso:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; project1.exe
An unhandled exception occurred at $004017DA:
Exception: exception!!!
  $004017DA  TBAR__EXECUTE,  line 46 of W:/md/dev/proj/test/ide/projects/project1.lpr
  $004017C8  TFOO__EXECUTE,  line 40 of W:/md/dev/proj/test/ide/projects/project1.lpr
  $004018D2  main,  line 54 of W:/md/dev/proj/test/ide/projects/project1.lpr

Heap dump by heaptrc unit of W:\md\dev\proj\test\ide\projects\project1.exe
74 memory blocks allocated : 2075/2232
71 memory blocks freed     : 1975/2128
3 unfreed memory blocks : 100
True heap size : 262144 (112 used in System startup)
True free heap : 261600
Should be : 261640
Call trace for block $014D7628 size 64
  $0040A1AC
  $004017FA  TBAR__EXECUTE,  line 47 of W:/md/dev/proj/test/ide/projects/project1.lpr
  $004017C8  TFOO__EXECUTE,  line 40 of W:/md/dev/proj/test/ide/projects/project1.lpr
  $004018D2  main,  line 54 of W:/md/dev/proj/test/ide/projects/project1.lpr
Call trace for block $014A8D70 size 24
  $0040A1AC
  $004017FA  TBAR__EXECUTE,  line 47 of W:/md/dev/proj/test/ide/projects/project1.lpr
  $004017C8  TFOO__EXECUTE,  line 40 of W:/md/dev/proj/test/ide/projects/project1.lpr
  $004018D2  main,  line 54 of W:/md/dev/proj/test/ide/projects/project1.lpr
Call trace for block $014A8CF0 size 12
  $004017EE  TBAR__EXECUTE,  line 47 of W:/md/dev/proj/test/ide/projects/project1.lpr
  $004017C8  TFOO__EXECUTE,  line 40 of W:/md/dev/proj/test/ide/projects/project1.lpr
  $004018D2  main,  line 54 of W:/md/dev/proj/test/ide/projects/project1.lpr
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Não importando as diferenças na finalização do programa entre Lazarus e Delphi, apenas tenha atenção nessa linha:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;3 unfreed memory blocks
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;O código não tem nenhum &lt;code&gt;try-finally&lt;/code&gt; e estamos utilizando instâncias de interfaces, como &lt;code&gt;IFoo&lt;/code&gt; e &lt;code&gt;IBar&lt;/code&gt;, e a saída são 3 blocos de memória não liberados, devido ter ocorrido uma exceção em &lt;code&gt;TBar.Execute&lt;/code&gt;. Do contrário, não haveria nenhum vazamento de memória — você pode verificar isso comentando a linha que gera a exceção.&lt;/p&gt;

&lt;p&gt;Isso prova que interfaces são inseguras se exceções ocorrem, certo?&lt;/p&gt;

&lt;p&gt;Bem, não tão rápido.&lt;/p&gt;

&lt;p&gt;Primeiro de tudo, sugiro que você leia o código, linha a linha, e veja se consegue descobrir o que há de errado.&lt;/p&gt;

&lt;h2 id=&quot;detalhes&quot;&gt;O Diabo Mora nos Detalhes&lt;/h2&gt;

&lt;p&gt;Para começar, o vazamento de memória acima não tem nada haver com instâncias de interfaces. Na verdade, você pode remover as interfaces completamente, adicionar &lt;code&gt;try-finally&lt;/code&gt; para desalocar a memória manualmente e, mesmo assim, a saída do Heaptrc irá continuar a mesma.&lt;/p&gt;

&lt;p&gt;Não acredita?&lt;/p&gt;

&lt;p&gt;Tente você:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;program Project1;

{$mode delphi}

uses
  SysUtils, Classes;

type
  TBar = class;

  TFoo = class
  private
    fBar: TBar;
  public
    constructor Create(const aBar: TBar);
    procedure Execute;
  end;

  TBar = class
  public
    procedure Execute;
  end;

{ TFoo }

constructor TFoo.Create(const aBar: TBar);
begin
  inherited Create;
  fBar := aBar;
end;

procedure TFoo.Execute;
begin
  fBar.Execute;
end;

{ TBar }

procedure TBar.Execute;
begin
  raise Exception.Create(&#39;exception!!!&#39;);
end;

var
  bar: TBar;
  foo: TFoo;
begin
  bar := TBar.Create;
  foo := TFoo.Create(bar);
  try
    foo.Execute;
  finally
    bar.Free;
    foo.Free;
  end;
end.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Se você compilou e executou essa versão, viu que a saída do programa com o relatório do Heaptrc (ou similar) é praticamente o mesmo.&lt;/p&gt;

&lt;p&gt;Os 3 vazamentos de memória continuam, provando que o “problema” não são as interfaces.&lt;/p&gt;

&lt;p&gt;Será um problema no compilador?&lt;/p&gt;

&lt;h2 id=&quot;solucao&quot;&gt;Solução&lt;/h2&gt;

&lt;p&gt;Primeiramente, vamos separar o código principal em uma unidade para ser utilizada tanto em uma aplicação Console como GUI.&lt;/p&gt;

&lt;p&gt;Assim vou conseguir demostrar um ponto importante, futuramente.&lt;/p&gt;

&lt;p&gt;Aqui está o código refatorado, ou seja, apenas as interfaces e classes separadas em uma nova unidade chamada &lt;code&gt;MyClasses&lt;/code&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;unit MyClasses;

{$mode delphi}

interface

uses
  SysUtils, Classes;

type
  IFoo = interface
    procedure Execute;
  end;

  IBar = interface
    procedure Execute;
  end;

  TFoo = class(TInterfacedObject, IFoo)
  private
    fBar: IBar;
  public
    constructor Create(const aBar: IBar);
    procedure Execute;
  end;

  TBar = class(TInterfacedObject, IBar)
  public
    procedure Execute;
  end;

implementation

{ TFoo }

constructor TFoo.Create(const aBar: IBar);
begin
  inherited Create;
  fBar := aBar;
end;

procedure TFoo.Execute;
begin
  fBar.Execute;
end;

{ TBar }

procedure TBar.Execute;
begin
  raise Exception.Create(&#39;exception!!!&#39;);
end;

end.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Agora, crie um novo projeto GUI. Adicione um Form. Depois um botão nesse Form.&lt;/p&gt;

&lt;p&gt;Novamente, se você estiver utilizando Lazarus, marque a opção “Use Heaptrc…” em Project Options, debugging.&lt;/p&gt;

&lt;p&gt;Adicione &lt;code&gt;MyClasses&lt;/code&gt; ao projeto e ao &lt;code&gt;uses&lt;/code&gt; do Form.&lt;/p&gt;

&lt;p&gt;No click do botão, codifique:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;procedure TForm1.Button1Click(Sender: TObject);
var
  foo: IFoo;
begin
  foo := TFoo.Create(TBar.Create);
  foo.Execute;
end;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ao executar o projeto e clicar no botão, você verá a mensagem de exceção:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Project project1 raised exception class &#39;Exception&#39; with message: exception!!!
In file &#39;MyClasses.pas&#39; at line 51
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Clique em continuar para ver a verdadeira exceção e depois em OK.&lt;/p&gt;

&lt;p&gt;Finalmente, feche o programa.&lt;/p&gt;

&lt;p&gt;Se você não esqueceu de marcar o Heaptrc, um &lt;code&gt;ShowMessage&lt;/code&gt; será mostrado:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Heap dump by heaptrc unit of W:\md\dev\proj\test\ide\projects\project1.exe
1764 memory blocks allocated : 1804912/1810440
1764 memory blocks freed     : 1804912/1810440
0 unfreed memory blocks : 0
True heap size : 688128 (112 used in System startup)
True free heap : 688016
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Nenhum vazamento de memória, utilizando o mesmo código do início do artigo.&lt;/p&gt;

&lt;p&gt;O que está acontecendo aqui?&lt;/p&gt;

&lt;p&gt;O verdadeiro problema é não capturar a exceção em &lt;em&gt;nenhum&lt;/em&gt; lugar do programa.&lt;/p&gt;

&lt;p&gt;Mas um programa GUI, por padrão, captura todas as exceções caso o programador não o faça deliberadamente.&lt;/p&gt;

&lt;p&gt;E isso faz com que o programa continue em execução “mais ou menos” no ponto onde a exceção foi gerada, ou seja, o programa continua em execução.&lt;/p&gt;

&lt;p&gt;E aqui entra uma vantagem das instâncias de interfaces: o compilador adiciona um &lt;code&gt;try-finally&lt;/code&gt; implícito para que suas contagens de referência sejam decrementadas.&lt;/p&gt;

&lt;p&gt;Sabemos que um &lt;code&gt;try-finally&lt;/code&gt; sempre será executado, independentemente de houve uma exceção dentro do seu bloco.&lt;/p&gt;

&lt;p&gt;Por isso as instâncias de &lt;code&gt;IFoo&lt;/code&gt; e &lt;code&gt;IBar&lt;/code&gt; são decrementadas e, consequentemente, destruídas mesmo após ter ocorrido uma exceção.&lt;/p&gt;

&lt;p&gt;Vamos voltar ao programa de linha-de-comando.&lt;/p&gt;

&lt;p&gt;Crie um novo programa e adicione a unidade &lt;code&gt;MyClasses&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O código é similar ao código do botão, porém é necessário um &lt;code&gt;try-except&lt;/code&gt;, pois aplicações console (por padrão) não tem um &lt;em&gt;handle&lt;/em&gt; de exceções:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;program Project1;

{$mode delphi}

uses
  SysUtils, Classes, MyClasses;

var
  foo: IFoo;
begin
  foo := TFoo.Create(TBar.Create);
  try
    foo.Execute;
  except
    on e: Exception do
       writeln(e.Message);
  end;
end.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Compile e execute.&lt;/p&gt;

&lt;p&gt;Veja que não há mais vazamentos de memória.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt; project1.exe
exception!!!
Heap dump by heaptrc unit of W:/md/dev/proj/test/ide/projects/project1.exe
72 memory blocks allocated : 1916/2064
72 memory blocks freed     : 1916/2064
0 unfreed memory blocks : 0
True heap size : 196608 (112 used in System startup)
True free heap : 196496
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Mesmo sem o &lt;code&gt;try-finally&lt;/code&gt; as instâncias de &lt;code&gt;IBar&lt;/code&gt; e &lt;code&gt;IFoo&lt;/code&gt; foram destruídas automaticamente pelo compilador.&lt;/p&gt;

&lt;h2 id=&quot;conclusao&quot;&gt;Conclusão&lt;/h2&gt;

&lt;p&gt;A utilização de instâncias de interface é, de certa forma, mais segura do que instância de classes.&lt;/p&gt;

&lt;p&gt;No entanto, se você começar a brincar com ponteiros, cast entre instâncias de classe vs interface, &lt;a href=&quot;/posts/interfaces-e-a-referencia-circular-entre-objetos/&quot;&gt;referência circular&lt;/a&gt;, etc, sem saber o que está fazendo, será grande a chance de haver vazamentos de memória.&lt;/p&gt;

&lt;p&gt;Porém, utilizando o código padrão para instanciar objetos do tipo interface, seu código estará mais seguro contra vazamentos de memória, pois o compilador sempre irá desalocar as instâncias, caso você já as tenha feito atribuindo &lt;code&gt;nil&lt;/code&gt; as variáveis.&lt;/p&gt;

&lt;p&gt;Até logo.&lt;/p&gt;
</description>
        <pubDate>Mon, 17 Jun 2019 00:00:00 +0100</pubDate>
        <link>http://objectpascalprogramming.com/memoria-segura-com-instancias-de-interface</link>
        <guid isPermaLink="true">http://objectpascalprogramming.com/memoria-segura-com-instancias-de-interface</guid>
      </item>
    
      <item>
        <title>Classes Mutáveis vs Objetos Imutáveis</title>
        <description>&lt;p&gt;É possível ter a comodidade em utilizar classes mutáveis para construir os objetos aos poucos, configurando propriedades e opções de execução além do uso dos construtores, porém com a vantagem de obter instâncias imutáveis no final do processo.&lt;/p&gt;

&lt;p&gt;E eu não estou falando do padrão Builder. Aliás você não deveria precisar construir uma classe para criar uma instância de outra classe…&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;&lt;img src=&quot;/images/2019/djim-loic-69263-unsplash.jpg&quot; alt=&quot;Unsplash image&quot; /&gt;
&lt;br /&gt;&lt;span style=&quot;font-family: &#39;Bebas Neue&#39;; font-size: 0.7em;&quot;&gt;Photo by Djim Loic on Unsplash&lt;/span&gt;&lt;/p&gt;

&lt;h2 id=&quot;introducao&quot;&gt;Introdução&lt;/h2&gt;

&lt;p&gt;Os seres na natureza &lt;em&gt;não&lt;/em&gt; são criados num único instante.&lt;/p&gt;

&lt;p&gt;Um ser dentro do ventre de sua progenitora é “construído” aos poucos, parte por parte.&lt;/p&gt;

&lt;p&gt;Imagine todos os órgãos crescendo em um desenvolvimento constante.&lt;/p&gt;

&lt;p&gt;Mas mesmo que esse ser ainda não tenha nascido, ele já existe.&lt;/p&gt;

&lt;p&gt;Ele ocupa espaço.&lt;/p&gt;

&lt;p&gt;Ele interage com o mundo através do corpo de sua mãe…&lt;/p&gt;

&lt;p&gt;Porém ele ainda não é uma entidade 100% concluída ou estável.&lt;/p&gt;

&lt;p&gt;O mesmo pode acontecer com um objeto no software.&lt;/p&gt;

&lt;p&gt;O objeto pode não ter sido totalmente formado, mas ele já existe quando obtemos uma nova instância a partir do construtor de sua classe.&lt;/p&gt;

&lt;p&gt;O objeto já existe mas pode não estar pronto para uso.&lt;/p&gt;

&lt;p&gt;Faz sentido?&lt;/p&gt;

&lt;h2 id=&quot;mutavel-vs-imutavel&quot;&gt;Mutável vs Imutável&lt;/h2&gt;

&lt;p&gt;Na internet muito tem se falado sobre utilizar objetos imutáveis considerando seus prós e contras.&lt;/p&gt;

&lt;p&gt;Eu mesmo sou um defensor de &lt;a href=&quot;/posts/objetos-imutaveis/&quot;&gt;objetos imutáveis&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Porém há casos onde os objetos, apesar de já ter “nascido”, ainda não estão 100% pronto para uso.&lt;/p&gt;

&lt;p&gt;Você pode estar pensando: “se podemos ter um objeto mutável, e se isso parece até estar de acordo com a natureza e de como o mundo realmente funciona, por quê eu iria querer ter um objeto imutável afinal?”&lt;/p&gt;

&lt;p&gt;Objetos imutáveis são muito mais previsíveis, seguros e simples de usar. Isso é um fato.&lt;/p&gt;

&lt;p&gt;No entanto, também haverá casos onde nem todos os objetos em um software poderão ser imutáveis. Vide &lt;em&gt;widgets&lt;/em&gt; de formulários Desktop, por exemplo. Os Edits, Memos, Grids… todos são mutáveis.&lt;/p&gt;

&lt;p&gt;Apesar da imutabilidade ser o ideal a seguir, ela não é uma verdade absoluta.&lt;/p&gt;

&lt;p&gt;Então, se mutabilidade e imutabilidade tem seus prós e contras, e eventualmente iremos trabalhar com ambos, como decidir entre um e outro quando isso já não for pré-determinado?&lt;/p&gt;

&lt;p&gt;Eu diria para utilizarmos classes mutáveis em conjunto com objetos imutáveis.&lt;/p&gt;

&lt;h2 id=&quot;praticando&quot;&gt;Na Prática&lt;/h2&gt;

&lt;p&gt;Uma classe é a construtora de seus objetos — a progenitora.&lt;/p&gt;

&lt;p&gt;Um objeto deveria ser uma entidade 100% pronta para uso.&lt;/p&gt;

&lt;p&gt;Entretanto, assim como uma criatura ainda está sendo formada no ventre, um objeto ainda pode estar sendo construído.&lt;/p&gt;

&lt;p&gt;Mas o programador pode determinar quando essa construção termina em um momento especial: quando a &lt;em&gt;instância objeto&lt;/em&gt; se transforma em &lt;em&gt;instância de interface&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Se você não tiver nenhum método na interface que promova a mutabilidade do objeto, você poderá construir seus objetos aos poucos utilizando a mutabilidade dos métodos da classe, porém com a vantagem de ter uma instância final imutável que só implementa métodos imutáveis da interface.&lt;/p&gt;

&lt;p&gt;É como ter o melhor dos dois mundos.&lt;/p&gt;

&lt;p&gt;Imagine uma classe que faz um processamento de Faturas — &lt;code&gt;TInvoiceMaker&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Tal classe necessitaria de uma “configuração especial” sobre como fazer o processamento.&lt;/p&gt;

&lt;p&gt;Essa configuração poderia depender de muitos fatores, como período do ano, tipos de contrato, tipos de produtos, promoções, se é apenas um teste ou se está executando em produção.&lt;/p&gt;

&lt;p&gt;Estamos apenas especulando as opções.&lt;/p&gt;

&lt;p&gt;Primeiro, iniciamos com a definição de uma interface que &lt;code&gt;TInvoiceMaker&lt;/code&gt; deverá implementar:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;IDataMaker = interface
  procedure Make;
end;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Veja que não há métodos que promovem a mutabilidade, ou seja, não há [Setters].&lt;/p&gt;

&lt;p&gt;Uma instância &lt;code&gt;IDataMaker&lt;/code&gt; seria passada como argumento para algum objeto/rotina “big process” que recebe um “maker”, não importando quem:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;BigProcess(const aMaker: IDataMaker);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Internamente &lt;code&gt;aMaker.Make&lt;/code&gt; será chamado.&lt;/p&gt;

&lt;h2 id=&quot;imutavel&quot;&gt;Modelo Imutável&lt;/h2&gt;

&lt;p&gt;Então, vamos pensar como poderia ser essa implementação no “modelo imutável”:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;TInvoiceMaker = class(TInterfacedObject, IDataMaker)
public
   constructor Create(aPeriod: TPeriod; 
     aContracts: TContractTypes;
     aProducts: TProductTypes;  
     aPromotions: TPromotionArray); reintroduce;
   procedure Make;
end;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;O construtor da classe deverá ter &lt;em&gt;todas&lt;/em&gt; as dependências injetadas no construtor.&lt;/p&gt;

&lt;p&gt;Esse é um modelo sólido. Não há setters. Após o objeto ter sido construído, ele estará 100% pronto para uso.&lt;/p&gt;

&lt;p&gt;Esse seria um modelo de implementação ideal.&lt;/p&gt;

&lt;p&gt;A classe é pequena; não há muitos argumentos no construtor; fácil de instanciar; imutável.&lt;/p&gt;

&lt;p&gt;Agora imagine essa classe seja utilizada em muitos lugares no código e que, na maioria das vezes, seus argumentos serão sempre os mesmos.&lt;/p&gt;

&lt;p&gt;Mesmo que haja poucos argumentos no construtor, a repetição deles torna o código verboso e chato para o programador.&lt;/p&gt;

&lt;p&gt;Se os contratos são os mesmos, os produtos os mesmos, promoções… por quê não definir valores padrão para tais atributos?&lt;/p&gt;

&lt;p&gt;Então implementamos mais um [construtor secundário] que irá chamar o primário:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;TInvoiceMaker = class(TInterfacedObject, IDataMaker)
public
   constructor Create(aPeriod: TPeriod; 
     aContracts: TContractTypes;
     aProducts: TProductTypes;
     aPromotions: TPromotionArray); reintroduce; overload;
   constructor Create(aPeriod: TPeriod); overload;
   procedure Make;
end;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;O construtor secundário irá passar valores padrão para os argumentos &lt;code&gt;aContracts, aProducts, aPromotions&lt;/code&gt;. Apenas o período deverá sempre ser informado, por exemplo.&lt;/p&gt;

&lt;p&gt;E, novamente, temos um design limpo e sólido.&lt;/p&gt;

&lt;p&gt;Mas sabemos como é a vida de um desenvolvedor: os requisitos mudam; modelos mudam; não há tempo suficiente.&lt;/p&gt;

&lt;p&gt;E se, agora, o desenvolvedor precisar informar o período e, também, os contratos? Não há um &lt;em&gt;overload&lt;/em&gt; de construtor para informar apenas esses dois parâmetros.&lt;/p&gt;

&lt;p&gt;Seguindo o método acima, o desenvolvedor tem duas opções: a) criar um novo construtor ou b) utilizar o construtor principal passando todos os parâmetros — o que eu vejo acontecer bastante em códigos de terceiros onde tais parâmetros são dispostos, por exemplo, assim &lt;code&gt;foo(true, true, &#39;&#39;, &#39;&#39;, false, &#39;&#39;, 1)&lt;/code&gt;, que é difícil de ler/entender.&lt;/p&gt;

&lt;p&gt;Há os argumentos com valores padrão no Pascal. Mas eles não ajudariam muito se quisermos passar apenas 1 dos valores “no meio”. Nesses casos você terá que digitar os valores padrão até chegar na posição do argumento que você deseja informar.&lt;/p&gt;

&lt;p&gt;Voltando ao problema, o mais “correto”, seguindo o modelo imutável, seria implementar um novo construtor:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;TInvoiceMaker = class(TInterfacedObject, IDataMaker)
public
   constructor Create(aPeriod: TPeriod; 
     aContracts: TContractTypes;
     aProducts: TProductTypes;  
     aPromotions: TPromotionArray); reintroduce; overload;
   constructor Create(aPeriod: TPeriod; 
     aContracts: TContractTypes); overload;
   constructor Create(aPeriod: TPeriod); overload;
   procedure Make;
end;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Infelizmente essa abordagem pode não ser estável no longo prazo, dependendo das mudanças.&lt;/p&gt;

&lt;p&gt;Se os argumentos ou a &lt;em&gt;combinação&lt;/em&gt; deles aumentarem, teria de haver muitos outros construtores com inúmeras combinações.&lt;/p&gt;

&lt;p&gt;Esse é uma abordagem que funciona com classes estáveis com poucas mudanças, não sendo o ideal para classes que tem a tendência de mudar muito.&lt;/p&gt;

&lt;h2 id=&quot;mutavel&quot;&gt;Modelo Mutável&lt;/h2&gt;

&lt;p&gt;Então, vamos pensar como poderia ser essa implementação no “modelo mutável”:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;TInvoiceMaker = class(TInterfacedObject, IDataMaker)
private
   fPeriod: TPeriod;
   fContracts: TContractTypes;
   fProducts: TProductTypes;
   fPromotions: TPromotionArray;
public
   constructor Create(aPeriod: TPeriod); reintroduce;
   procedure Make;
   property Contracts: TContractTypes 
     read fContracts write fContracts;
   property Products: TProductTypes 
     read fProducts write fProducts;
   property Promotions: TPromotionArray 
     read aPromotions write fPromotions;
end;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A classe tem um construtor primário que solicita o essencial: um período.&lt;/p&gt;

&lt;p&gt;Todos os outros atributos que podem ter um valor padrão, poderiam ser implementados como propriedades.&lt;/p&gt;

&lt;p&gt;A vantagem é óbvia: não precisamos construir inúmeros construtores com inúmeras combinações. Além disso, podemos adicionar mais propriedades a qualquer momento, com tanto que cada uma tenha um valor padrão que será inicializado no construtor primário.&lt;/p&gt;

&lt;p&gt;Esse também é um um modelo limpo e (de certa forma) sólido.&lt;/p&gt;

&lt;p&gt;Muitos desenvolvedores acham que a classe deve ter apenas os mesmos métodos que a interface que implementam. Ledo engano.&lt;/p&gt;

&lt;p&gt;Há setters através das propriedades, porém cada uma delas terá um valor padrão definido no construtor. Então, o desenvolvedor não é obrigado a passar cada uma das propriedades.&lt;/p&gt;

&lt;p&gt;Após o objeto ter sido construído, ele estará 100% pronto para uso.&lt;/p&gt;

&lt;p&gt;Mas, como manter a imutabilidade utilizando essa classe?&lt;/p&gt;

&lt;p&gt;Na verdade, a instância será virtualmente imutável quando você transformá-la em instância de interface.&lt;/p&gt;

&lt;p&gt;Lembre-se que precisamos de uma instância &lt;code&gt;IDataMaker&lt;/code&gt; para passar a uma rotina:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/// imutable version
procedure Execute(aPeriod: TPeriod);
var
  maker: IDataMaker;  // interface
begin
  maker := TInvoiceMaker.Create(
    aPeriod, TDefContracts.Create, 
    TDefProducts.Create, []);
  BigProcess(maker);
end;

/// mutable version
procedure Execute(aPeriod: TPeriod);
var
  maker: TInvoiceMaker; // class
begin
  maker := TInvoiceMaker.Create(aPeriod);
  // changing default TDefProducts instance
  maker.Products := TOtherProducts.Create;
  BigProcess(maker);
end;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Você pode ainda utilizar uma construção sem ter que definir uma variável, utilizando WITH and &lt;a href=&quot;/metodo-ref&quot;&gt;REF&lt;/a&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/// mutable version using WITH
procedure Execute(aPeriod: TPeriod);
begin
  with TInvoiceMaker.Create(aPeriod) do
  begin
    // changing default TDefProducts instance
    Products := TOtherProducts.Create;
    BigProcess(Ref);  // obj.Ref
  end;
end;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;conclusao&quot;&gt;Conclusão&lt;/h2&gt;

&lt;p&gt;A rotina &lt;code&gt;BigProcess&lt;/code&gt; só sabe o que é um &lt;code&gt;IDataMaker&lt;/code&gt; com apenas o único método &lt;code&gt;Maker&lt;/code&gt;. É irrelevante para o processo se &lt;code&gt;aMaker&lt;/code&gt; é mutável com propriedades ou totalmente imutável, implementando somente o único método da interface.&lt;/p&gt;

&lt;p&gt;Dessa forma você teria classes mutáveis com outras propriedades e métodos gerando instâncias de objetos mutáveis.&lt;/p&gt;

&lt;p&gt;Porém, após as instâncias serem convertidas para instâncias de interface, você teria instâncias virtualmente imutáveis, provenientes de classes mutáveis.&lt;/p&gt;

&lt;p&gt;Combinar classes mutáveis com objetos imutáveis pode ser uma escolha poderosa no design de sua aplicação, trazendo a flexibilidade da construção de instâncias mutáveis com a segurança das instâncias imutáveis, após serem convertidas.&lt;/p&gt;

&lt;p&gt;Até logo.&lt;/p&gt;
</description>
        <pubDate>Mon, 10 Jun 2019 00:00:00 +0100</pubDate>
        <link>http://objectpascalprogramming.com/classe-mutavel-vs-objeto-imutavel</link>
        <guid isPermaLink="true">http://objectpascalprogramming.com/classe-mutavel-vs-objeto-imutavel</guid>
      </item>
    
      <item>
        <title>Implementando Interfaces Utilizando Diferente Assinaturas de Métodos</title>
        <description>&lt;p&gt;Como implementar em uma única classe, duas ou mais interfaces que tenham métodos com o mesmo nome e argumentos?&lt;/p&gt;

&lt;p&gt;Talvez o pensamento mais natural à essa pergunta seria: “por quê eu iria querer fazer isso?”.&lt;/p&gt;

&lt;p&gt;Se você nunca precisou implementar essa situação antes, pode ser difícil imaginar tal cenário agora. Mas vou lhe mostrar que ele existe e que não é só possível implementá-lo como também é uma ótima técnica para conhecer.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;&lt;img src=&quot;/images/2019/raka-rachgo-276831-unsplash.jpg&quot; alt=&quot;Unsplash image&quot; /&gt;
&lt;br /&gt;&lt;span style=&quot;font-family: &#39;Bebas Neue&#39;; font-size: 0.7em;&quot;&gt;Photo by Raka Rachgo on Unsplash&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Estávamos conversando sobre orientação a objetos em um chat privado entre amigos quando uma dúvida pairou no ar.&lt;/p&gt;

&lt;p&gt;Não era exatamente uma dúvida, mas mais um desdém sobre como a linguagem C++ consegue implementar herança múltipla sem ser um caos total.&lt;/p&gt;

&lt;p&gt;Como a maioria dos desenvolvedores lá utilizam Java, e como essa linguagem implementa herança simples — assim como Object Pascal — não conseguiram visualizar um cenário onde seria possível duas classes terem um método com o mesmo nome e argumentos, enquanto uma terceira classe deveria herdar de ambas.&lt;/p&gt;

&lt;p&gt;Nesse momento eu me lembrei de alguns casos de implementação em Object Pascal, onde essa situação é totalmente possível quando implementamos múltiplas interfaces.&lt;/p&gt;

&lt;p&gt;Object Pascal não tem herança múltipla como C++, mas podemos implementar mais de uma interface na mesma classe e é bem possível que uma ou mais interfaces tenham nomes e argumentos idênticos.&lt;/p&gt;

&lt;p&gt;Como você codificaria esse cenário?&lt;/p&gt;

&lt;p&gt;Pelo que eu pude entender lá na discussão, assim como também &lt;a href=&quot;https://stackoverflow.com/questions/2801878/implementing-two-interfaces-in-a-class-with-same-method-which-interface-method&quot;&gt;pesquisando na internet&lt;/a&gt;, Java não tem suporte no nível da linguagem para fazer tal construção ou diferenciação de métodos de interface com o mesmo nome e argumentos — e acho incrível ninguém falar sobre isso.&lt;/p&gt;

&lt;p&gt;É também interessante que praticamente todas as respostas a essa dúvida, no meio Java, tenham a mesma convicção que poderia ser resumida assim: se duas interfaces tem o mesmo nome, elas &lt;em&gt;não&lt;/em&gt; deveriam ter implementação diferenciada nas classes que as implementam.&lt;/p&gt;

&lt;p&gt;Eles estão enganados.&lt;/p&gt;

&lt;p&gt;Nomes de métodos iguais, mesmo com argumentos iguais, podem exigir implementação diferenciada devido a &lt;em&gt;semântica das interfaces&lt;/em&gt; e não devido a assinatura de seus métodos.&lt;/p&gt;

&lt;p&gt;Quando estamos definindo uma interface, deveríamos pensar apenas no contrato que ela representa e não como iremos implementá-la em classes mais tarde. Dessa forma, em teoria, não deveríamos nos preocupar se haveria algum conflito de nomenclatura na implementação das classes, pois isso é apenas um &lt;em&gt;detalhe da implementação&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Felizmente, fazer essa diferenciação e implementação utilizando a linguagem Object Pascal não é só possível como também existe uma sintaxe &lt;em&gt;específica&lt;/em&gt; para a codificação.&lt;/p&gt;

&lt;p&gt;A Embarcadero chama essa sintaxe de &lt;em&gt;&lt;a href=&quot;http://docwiki.embarcadero.com/RADStudio/Rio/en/Implementing_Interfaces#Method_Resolution_Clause&quot;&gt;Method Resolution Clause&lt;/a&gt;&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Agora que você sabe a sintaxe, consegue imaginar cenários para sua utilização?&lt;/p&gt;

&lt;p&gt;Vamos enumerar alguns possíveis cenários:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;O primeiro cenário&lt;/strong&gt; está no próprio exemplo da Embarcadero, e mesmo não tendo nada haver com herança múltipla de interfaces, ainda é um necessário válido.&lt;/p&gt;

&lt;p&gt;Lá, a explicação é que a interface &lt;code&gt;IMalloc&lt;/code&gt;  possui os métodos &lt;code&gt;Alloc&lt;/code&gt; e &lt;code&gt;Free&lt;/code&gt; e precisamos implementá-la na classe &lt;code&gt;TMemoryManager&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Poderíamos implementar um método &lt;code&gt;Alloc&lt;/code&gt; — mesma nomenclatura da interface — ao invés do &lt;code&gt;Allocate&lt;/code&gt; sugerido no exemplo. E tudo bem.&lt;/p&gt;

&lt;p&gt;Mas não poderíamos definir &lt;code&gt;Free&lt;/code&gt; — o mesmo da interface — pois esse é um método existente na classe &lt;code&gt;TObject&lt;/code&gt;, a classe de onde todas as outras herdam.&lt;/p&gt;

&lt;p&gt;O método &lt;code&gt;Free&lt;/code&gt; libera o próprio objeto, chamando seu destrutor. Seria esse o objetivo do programador que definiu &lt;code&gt;IMalloc&lt;/code&gt; em primeiro lugar, ou seja, desalocar a própria instância?&lt;/p&gt;

&lt;p&gt;Se a resposta for &lt;em&gt;sim&lt;/em&gt;, então não teríamos problemas pois &lt;code&gt;Free&lt;/code&gt; já está implementado em todas as classes. Feito.&lt;/p&gt;

&lt;p&gt;Mas se a resposta for &lt;em&gt;não&lt;/em&gt;, teríamos que fazer o que a documentação da Embarcadero sugere, definindo um novo &lt;em&gt;método de implementação&lt;/em&gt; para implementar o &lt;em&gt;método da interface&lt;/em&gt; afim de não chamar o &lt;code&gt;Free&lt;/code&gt; padrão de &lt;code&gt;TObject&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Um segundo cenário&lt;/strong&gt; é sobre reutilização de classes legadas que existiam antes da introdução de alguma interface no código.&lt;/p&gt;

&lt;p&gt;Imagine que você tem uma classe que define alguns métodos que implementam mensagens para o usuário em um programa Desktop:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;TUserMessages = class
public
  procedure MsgWarning(const aText: string);
  procedure MsgError(const aText: string);
  function MsgQuestion(const aText: string): boolean;
end;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Os métodos &lt;code&gt;MsgWarning&lt;/code&gt; e &lt;code&gt;MsgError&lt;/code&gt; apenas exibem uma mensagem ao usuário com os respectivos ícones de aviso ou erro. Já o método &lt;code&gt;MsgQuestion&lt;/code&gt; retorna &lt;code&gt;true&lt;/code&gt; ou &lt;code&gt;false&lt;/code&gt; dependendo da escolha do usuário.&lt;/p&gt;

&lt;p&gt;Então o sistema evoluiu. Começaram a pensar em introduzir TDD para codificar os testes de regressões. Seria necessário introduzir uma interface para essas interfaces, pois não iriam querer visualizar tais mensagens ao executar os testes automatizados. Seria necessário criar uma classe &lt;em&gt;fake&lt;/em&gt; para essas mensagens, implementando uma nova interface:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;IUserMessages = interface
  procedure Warning(const aText: string);
  procedure Error(const aText: string);
  function Question(const aText: string): boolean;
end;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Repare que os nomes dos métodos ficaram menos redundantes, pois eles não tem mais o prefixo “Msg” como os da classe original.&lt;/p&gt;

&lt;p&gt;Enquanto essa nova interface vai sendo introduzida no código, aos poucos, o que antes estava funcionando deve continuar assim. Isso significa que várias partes do código ainda continuarão utilizando a classe &lt;code&gt;TUserMessages&lt;/code&gt; original até a completa refatoração.&lt;/p&gt;

&lt;p&gt;Isso quer dizer que não podemos utilizar a classe original para implementar a nova interface fazendo, assim, que essa classe possa trabalhar tanto no código “antigo” como também no “novo”?&lt;/p&gt;

&lt;p&gt;Claro que podemos:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;TUserMessages = class(TInterfacedObject, IUserMessages)
private
  procedure IUserMessages.Warning = MsgWarning;
  procedure IUserMessages.Error = MsgError;
  function IUserMessages.Question = MsgQuestion;
public
  procedure MsgWarning(const aText: string);
  procedure MsgError(const aText: string);
  function MsgQuestion(const aText: string): boolean;
end;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Dessa forma &lt;code&gt;TUserMessages&lt;/code&gt; pode continuar a ser utilizada para construir instâncias da classe e continuar utilizando os métodos (antigos) com prefixo “Msg”, assim como pode ser utilizada no novo código como uma instância da interface &lt;code&gt;IUserMessages&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Um terceiro cenário&lt;/strong&gt; é sobre a implementação de múltiplas interfaces.&lt;/p&gt;

&lt;p&gt;A sintaxe para fazer isso você, agora, já sabe. Mas talvez ainda possa lhe faltar a imaginação onde esse cenário seria adequado ou mesmo requerido.&lt;/p&gt;

&lt;p&gt;Por quê, você diria, eu iria querer implementar 2 ou mais interfaces utilizando diferentes assinaturas de métodos?&lt;/p&gt;

&lt;p&gt;A resposta irá depender da sutil diferença semântica das interfaces que serão implementadas.&lt;/p&gt;

&lt;p&gt;Imagine que tenhamos que criar 2 interfaces que são &lt;em&gt;similares&lt;/em&gt;, porém &lt;em&gt;diferentes&lt;/em&gt;. Uma interface irá representar um Avião (&lt;code&gt;IPlane&lt;/code&gt;) e outra um Planador (&lt;code&gt;IGlider&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Eu não entendo tanto assim de aviação, porém podemos enumerar algumas diferenças entre ambos:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;o avião tem motor; o planador não;&lt;/li&gt;
  &lt;li&gt;o avião é muito mais pesado que o planador;&lt;/li&gt;
  &lt;li&gt;o avião pode levantar voo por ele mesmo; o planador precisa de outro avião para rebocá-lo ao ar;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agora imagine que uma empresa revolucionária acaba de lançar uma máquina que pode ser utilizada tanto como um avião como um planador.&lt;/p&gt;

&lt;p&gt;Incrível? Nem tanto, eu acho.&lt;/p&gt;

&lt;p&gt;Esses híbridos nascem o tempo todo: carros elétricos mas que também utilizam combustível fóssil; carros que andam na terra, mas num clique de um botão viram uma espécie de lancha para andar na água; até mesmo um &lt;a href=&quot;https://www.youtube.com/watch?v=_v1wc0bD_Cg&quot;&gt;carro/helicóptero&lt;/a&gt; já foi inventado; skates com motor a combustão ou elétrico; bicicletas elétricas, mas você pode continuar pedalando; etc.&lt;/p&gt;

&lt;p&gt;Na minha imaginação, essa nova máquina — será que já existe? — teria alguns requisitos básicos:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;ser feita de fibra de carbono para ser o mais leve e resistente possível;&lt;/li&gt;
  &lt;li&gt;possibilidade de acoplar um motor plug-n-play para se transformar num avião;&lt;/li&gt;
  &lt;li&gt;ter configurações diferentes para o “modo avião” vs “modo planador”;&lt;/li&gt;
  &lt;li&gt;no modo avião, levantar voo sozinha sendo auto-propulsionada;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Pensando no código, vamos retornar as interfaces e defini-las:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;IPlane = interface
  procedure Fly;
end;

IGlider = interface
  procedure Fly;
end;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;É isso. Não vamos complicar. São duas interfaces com apenas um método. Ambos são idênticos, ou seja, mesma assinatura.&lt;/p&gt;

&lt;p&gt;Nosso novo, incrível e imaginável veículo, representado por uma classe, deveria implementar o método &lt;code&gt;Fly()&lt;/code&gt; apenas uma única vez?&lt;/p&gt;

&lt;p&gt;Minha resposta é sonoro &lt;em&gt;não&lt;/em&gt;. Mas se você continua achando que sim, como uma única classe iria implementar os dois modos de voos tão distintos?&lt;/p&gt;

&lt;p&gt;Como explicado acima, o veículo pode ser tanto um avião como um planador. O usuário pode ou não utilizar um motor e, assim sendo, utilizar configurações de voo completamente diferentes.&lt;/p&gt;

&lt;p&gt;Apesar do avião e do planador voarem, ambos fazem de maneira completamente diferentes, ou seja, com &lt;em&gt;implementações&lt;/em&gt; diferentes.&lt;/p&gt;

&lt;p&gt;Precisamos de um nome para esse incrível veículo. Então sugiro batizar essa invenção de “OnePlane”.&lt;/p&gt;

&lt;p&gt;Então teríamos a implementação da classe:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;TOnePlane = class(TInterfacedObject, IPlane, IGlider)
private
  // real flying implementation methods
  procedure FlyAsPlane;
  procedure FlyAsGlider;
  // method resolution clause
  procedure IPlane.Fly = FlyAsPlane;
  procedure IGlider.Fly = FlyAsGlider;
public
  // will initialize the instance as a plane or glider
  constructor Create(asPlane: boolean = true); reintroduce;
end;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A classe acima exemplifica como implementar 2 métodos idênticos de interfaces distintas em uma mesma classe utilizando implementações completamente diferentes.&lt;/p&gt;

&lt;p&gt;A sintaxe é tão simples e explícita que até mesmo desenvolvedores de outras linguagens, como Java, poderão entender essa implementação sem problemas, eu acredito.&lt;/p&gt;

&lt;p&gt;Apesar da linguagem Object Pascal ter &lt;a href=&quot;/posts/delegacao-de-implementacao-de-interfaces/&quot;&gt;outra sintaxe&lt;/a&gt; ainda mais &lt;em&gt;limpa&lt;/em&gt; para implementar mais de uma interface em uma mesma classe, ainda assim esse código parece perfeitamente razoável pra mim. Iniciaríamos a implementação utilizando &lt;a href=&quot;/posts/metodos-privados/&quot;&gt;métodos privados&lt;/a&gt; que depois poderiam ser convertido em novas classes, se necessário.&lt;/p&gt;

&lt;p&gt;Finalmente, essa sintaxe não é novidade no Free Pascal nem no Delphi. Acredito que ela foi implementada quando surgiram as interfaces. Mas tenho certeza que você poderá utilizá-la perfeitamente na versão Delphi 7 de 2002 em diante, como eu continuo utilizando em vários projetos até hoje.&lt;/p&gt;

&lt;p&gt;Até logo.&lt;/p&gt;

</description>
        <pubDate>Mon, 20 May 2019 00:00:00 +0100</pubDate>
        <link>http://objectpascalprogramming.com/multiplas-interfaces</link>
        <guid isPermaLink="true">http://objectpascalprogramming.com/multiplas-interfaces</guid>
      </item>
    
      <item>
        <title>Usando Paths ao invés de Diretivas de Compilação</title>
        <description>&lt;p&gt;Já pensou em utilizar paths, ao invés de diretivas de compilação, para compilar seu projeto em diferentes plataformas?&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;&lt;img src=&quot;/images/2019/claudio-hirschberger-1326178-unsplash.jpg&quot; alt=&quot;Unsplash image&quot; /&gt;
&lt;br /&gt;&lt;span style=&quot;font-family: &#39;Bebas Neue&#39;; font-size: 0.7em;&quot;&gt;Photo by Nathan Dumlao on Unsplash&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Em meados de 2017 eu escrevi um &lt;a href=&quot;/diretivas-de-compilacao&quot;&gt;artigo&lt;/a&gt; sobre Diretivas de Compilação, explicando como poderíamos encapsulá-las para ajudar a tornar o código &lt;em&gt;multiplatform&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Basicamente teríamos uma unidade comum a todas as plataformas (FPC e Delphi) e outra(s) unidade(s) específica(s) para cada uma delas.&lt;/p&gt;

&lt;p&gt;Por exemplo: uma unidade &lt;code&gt;FooFuncs&lt;/code&gt; seria a principal enquanto &lt;code&gt;FooFuncsFPC&lt;/code&gt; e &lt;code&gt;FooFuncsDelphi&lt;/code&gt; seriam as especializadas.&lt;/p&gt;

&lt;p&gt;A unidade &lt;code&gt;FooFuncs&lt;/code&gt; utilizaria as unidades especializadas e seus identificadores—interfaces e classes—seriam &lt;a href=&quot;/redeclarando-classes&quot;&gt;redefinidos&lt;/a&gt; utilizando uma nomenclatura mais genérica para toda a lib ou projeto e sem dependências com qualquer plataforma.&lt;/p&gt;

&lt;p&gt;Após quase 2 anos, eu mudei esse conceito para um modelo que considero ainda mais simples e sem utilizar diretivas de compilação: utilização de apenas &lt;em&gt;paths&lt;/em&gt; para cada plataforma.&lt;/p&gt;

&lt;center&gt;&lt;span style=&quot;font-size: 1.0em;&quot;&gt;* * *&lt;/span&gt;&lt;/center&gt;

&lt;p&gt;Veja o projeto &lt;a href=&quot;https://github.com/mdbs99/xavier&quot;&gt;Xavier lib&lt;/a&gt;, por exemplo.&lt;/p&gt;

&lt;p&gt;Dentro do diretório &lt;code&gt;xavier/src/&lt;/code&gt; podemos ver dois subdiretórios: &lt;code&gt;fpc&lt;/code&gt; e &lt;code&gt;delphi&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Cada diretório possui 1 unidade com o mesmo nome: &lt;code&gt;XavierCorePlatform&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Sabemos que um projeto não pode ter unidades duplicadas, então como isso funciona?&lt;/p&gt;

&lt;p&gt;Basta aplicar o path por plataforma, ou seja, apenas 1 unidade será utilizada por projeto. Se você está utilizando o Delphi, irá utilizar apenas o path &lt;code&gt;src\delphi&lt;/code&gt;, por exemplo.&lt;/p&gt;

&lt;p&gt;E é só isso.&lt;/p&gt;

&lt;p&gt;As &lt;em&gt;vantagens&lt;/em&gt; são visíveis em relação a abordagem anterior que utilizava diretivas:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;sem necessidade de diretivas de compilação&lt;/li&gt;
  &lt;li&gt;não é necessário redeclarar identificadores de unidades especializadas&lt;/li&gt;
  &lt;li&gt;não é necessário haver uma unidade genérica—ex: &lt;code&gt;FooFuncs&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;basta 1 unidade por plataforma&lt;/li&gt;
  &lt;li&gt;menos código&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No entanto, você poderia considerar a (possível) &lt;a href=&quot;/posts/codigo-duplicado-talvez-nao/&quot;&gt;duplicação de código&lt;/a&gt; como uma desvantagem, visto que haverá implementações de classes, com o mesmo nome, em unidades por plataforma. No projeto Xavier, por exemplo, vemos que há algumas linhas muito similares… mas isso não é um problema real.&lt;/p&gt;

&lt;p&gt;A implementação por plataforma pode ser muito diferente uma da outra. Existir algumas linhas similares—ou mesmo iguais—é um preço mínimo a se pagar, na minha humilde opinião.&lt;/p&gt;

&lt;p&gt;Finalmente, repare que todo código comum entre as plataformas devem estar em outras unidades compartilhadas. No caso do Xavier, tais códigos compartilhados estão nas unidades &lt;code&gt;XavierCore&lt;/code&gt; e &lt;code&gt;XavierAdapters&lt;/code&gt;. Ambas são utilizadas pelas unidades &lt;code&gt;XavierCorePlatform&lt;/code&gt; referente a cada plataforma.&lt;/p&gt;

&lt;p&gt;Até logo.&lt;/p&gt;

</description>
        <pubDate>Mon, 15 Apr 2019 00:00:00 +0100</pubDate>
        <link>http://objectpascalprogramming.com/usando-paths-ao-inves-de-diretivas</link>
        <guid isPermaLink="true">http://objectpascalprogramming.com/usando-paths-ao-inves-de-diretivas</guid>
      </item>
    
      <item>
        <title>Trabalhando com Exceções em Requisições HTTP</title>
        <description>&lt;p&gt;Em requisições HTTP, devemos levantar uma exceção quando recebermos, por exemplo, um código 500?&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;&lt;img src=&quot;/images/2019/nathan-dumlao-744702-unsplash.jpg&quot; alt=&quot;Unsplash image&quot; /&gt;
&lt;br /&gt;&lt;span style=&quot;font-family: &#39;Bebas Neue&#39;; font-size: 0.7em;&quot;&gt;Photo by Nathan Dumlao on Unsplash&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Tivemos uma discussão em um grupo do &lt;a href=&quot;https://telegram.org/&quot;&gt;Telegram&lt;/a&gt; sobre utilizar ou não exceções em requisições HTTP, o que me inspirou a escrever esse artigo.&lt;/p&gt;

&lt;p&gt;Como todos sabemos, o &lt;a href=&quot;https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol&quot;&gt;protocolo HTTP&lt;/a&gt; é baseado em texto simples.&lt;/p&gt;

&lt;p&gt;Cada requisição do cliente é composto por um cabeçalho e um corpo (opcional):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;GET /index.html HTTP/1.1
Host: www.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A resposta do servidor segue o mesmo protocolo, contendo um cabeçalho e um corpo (também opcional) de resposta:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;HTTP/1.1 200 OK
Date: Mon, 23 May 2005 22:38:34 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 138
Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT
Server: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)
ETag: &quot;3f80f-1b6-3e1cb03b&quot;
Accept-Ranges: bytes
Connection: close

&amp;lt;html&amp;gt;
&amp;lt;head&amp;gt;
  &amp;lt;title&amp;gt;An Example Page&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
  Hello World, this is a very simple HTML document.
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;A beleza desse protocolo é que mesmo seres humanos, não apenas máquinas, podem ler entender (a maioria do) seu conteúdo.&lt;/p&gt;

&lt;p&gt;Então podemos perceber que há um padrão em ambas as mensagens acima, identificado na primeira linha, indicando o sucesso ou erro da requisição ou resposta.&lt;/p&gt;

&lt;p&gt;O padrão é determinado por um par de &lt;em&gt;código&lt;/em&gt; e &lt;em&gt;texto&lt;/em&gt; no qual identificaremos por &lt;em&gt;status&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;No exemplo acima, o status é determinado pelo código 200 e o texto “OK”. Mostrando uma resposta padrão de &lt;em&gt;sucesso&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Há uma &lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_HTTP_status_codes&quot;&gt;grande lista&lt;/a&gt; de códigos pré-determinados e toda aplicação deveria respeitá-los em todas as  requisições e respostas.&lt;/p&gt;

&lt;p&gt;Agora, repare que não existem objetos e tão pouco &lt;em&gt;objetos de exceções&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;No início do artigo eu disse que a dúvida que gerou a discussão foi utilizar ou não exceções, ou seja, objetos &lt;code&gt;Exception&lt;/code&gt; e derivados em clientes HTTP.&lt;/p&gt;

&lt;p&gt;Minha resposta?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Você não deveria utilizar exceções em clientes HTTP, somente nas suas classes de negócio.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Se o protocolo não tem exceções, por quê implementá-lo na classe mais básica, ou seja, a que faz a ponte entre o seu sistema e a requisição HTTP?&lt;/p&gt;

&lt;p&gt;Para mim, não faz sentido.&lt;/p&gt;

&lt;p&gt;É verdade que existem vários frameworks que implementam clientes HTTP como, por exemplo, &lt;a href=&quot;https://www.indyproject.org/&quot;&gt;Indy&lt;/a&gt;, &lt;a href=&quot;http://www.ararat.cz/synapse/doku.php/start&quot;&gt;Synapse&lt;/a&gt; ou até mesmo os clientes padrão da linguagem.&lt;/p&gt;

&lt;p&gt;Talvez esses clientes podem gerar uma exceção quando recebem um código 500 ou talvez não. Não importa. Você deveria encapsular essas classes de terceiros em suas próprias classes de acesso HTTP. Assim, você poderia mudar de framework apenas alterando essas classes.&lt;/p&gt;

&lt;p&gt;Pense apenas em um cliente HTTP genérico, cru, que implementa o protocolo como ele deve ser: envio e recebimento de mensagens no formato texto. A partir dele você constrói classes de negócio que utilizam o cliente, adicionando comportamento referente as regras de negócio.&lt;/p&gt;

&lt;p&gt;Na &lt;a href=&quot;/posts/microservices-delphi-parte-final/&quot;&gt;parte final&lt;/a&gt; da série “Microservices com Delphi” você poderá ver mais um exemplo de como fazer o tratamento de códigos de retorno do cliente HTTP. Esse é apenas mais um exemplo e não um padrão. Tudo irá depender da sua aplicação, quais códigos verificar e o que fazer quando recebê-los.&lt;/p&gt;

&lt;p&gt;Apenas mantenha os clientes o mais simples possível.&lt;/p&gt;

&lt;p&gt;Até logo.&lt;/p&gt;

</description>
        <pubDate>Mon, 01 Apr 2019 00:00:00 +0100</pubDate>
        <link>http://objectpascalprogramming.com/exceptions-no-protocolo-http</link>
        <guid isPermaLink="true">http://objectpascalprogramming.com/exceptions-no-protocolo-http</guid>
      </item>
    
      <item>
        <title>Tipo object Continua Vivo</title>
        <description>&lt;p&gt;Existe uma estrutura no Object Pascal que foi o precursor das classes.&lt;/p&gt;

&lt;p&gt;Você conhece o tipo &lt;code&gt;object&lt;/code&gt;?&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;&lt;img src=&quot;/images/2019/namroud-gorguis-253765-unsplash.jpg&quot; alt=&quot;Unsplash image&quot; /&gt;
&lt;br /&gt;&lt;span style=&quot;font-family: &#39;Bebas Neue&#39;; font-size: 0.7em;&quot;&gt;Photo by Namroud Gorguis on Unsplash&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;Em um &lt;a href=&quot;/formularios-e-widgets&quot;&gt;artigo&lt;/a&gt; anterior eu expliquei com dividir o código de um formulário em diferentes objetos, organizando os widgets em diferentes classes para dividir as responsabilidades em diferentes objetos.&lt;/p&gt;

&lt;p&gt;Separar partes do código em classes distintas melhoram a legibilidade e manutenção do código. Mas você pode implementar o mesmo conceito sem utilizar classes.&lt;/p&gt;

&lt;p&gt;Muitas vezes eu utilizo o tipo &lt;code&gt;object&lt;/code&gt; como um &lt;em&gt;helper&lt;/em&gt; para um widget ou conjunto deles.&lt;/p&gt;

&lt;p&gt;De fato, essa técnica pode ser utilizada não só na implementação de formulários, mas em &lt;em&gt;qualquer&lt;/em&gt; parte do código.&lt;/p&gt;

&lt;p&gt;Não confunda com os tipos Helpers que &lt;em&gt;adiciona&lt;/em&gt; comportamento a tipos já existentes. Existe uma sintaxe especial para declara-los, estendendo outros tipos sem utilizar herança… mas não é deles que estou falando.&lt;/p&gt;

&lt;p&gt;Se você não gosta de nomenclatura &lt;em&gt;helper&lt;/em&gt;, poderíamos chamá-los de &lt;em&gt;ferramentas&lt;/em&gt;, pois eles &lt;a href=&quot;/posts/objetos-representam-entidades/&quot;&gt;não representam&lt;/a&gt; uma entidade e não implementam uma &lt;a href=&quot;/posts/interfaces-em-todo-lugar/&quot;&gt;interface&lt;/a&gt;. São apenas ferramentas que serão utilizadas pelos verdadeiros objetos.&lt;/p&gt;

&lt;p&gt;Não representar uma entidade é um bom motivo para utilizar o tipo &lt;code&gt;object&lt;/code&gt;, mas há outras vantagens.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Performance&lt;/strong&gt;, por utilizar o stack ou invés do heap na alocação de memória.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Utiliza menos memória&lt;/strong&gt;, pois são estruturas mais simples, comparadas às classes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Uso de herança&lt;/strong&gt; é possível.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Determinar um escopo&lt;/strong&gt; para um conjunto de funções utilitárias, genéricas e reutilizáveis, ao invés de declarar funções e procedimentos diretamente no escopo da unit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Simplicidade&lt;/strong&gt;, sempre será um ótimo motivo para tomar decisões na arquitetura. Por exemplo: não é necessário o uso de &lt;code&gt;try..finally&lt;/code&gt;, tornando o código menos verboso.&lt;/p&gt;

&lt;p&gt;Uma &lt;strong&gt;desvantagem&lt;/strong&gt;, entretanto, é não existir um [construtor] e por isso não tem como garantir uma inicialização adequada dos campos privados. Diferentemente de uma classe, onde é &lt;em&gt;obrigatório&lt;/em&gt; o uso de seu construtor, um tipo &lt;code&gt;object&lt;/code&gt; pode ser utilizado diretamente como qualquer outra variável primitiva.&lt;/p&gt;

&lt;p&gt;Além disso, a Embarcadero descontinuou o uso do tipo &lt;code&gt;object&lt;/code&gt; desde o Delphi 2010, sugerindo o uso de “records com métodos” em seu lugar—uma decisão equivocada, na minha opinião, e &lt;a href=&quot;http://blog.synopse.info/post/2013/10/09/Good-old-object-is-not-to-be-deprecated-it-is-the-future&quot;&gt;não estou sozinho&lt;/a&gt; nesse pensamento. Além de perder a compatibilidade com o código legado, introduzir métodos em records é, no mínimo, duvidoso.&lt;/p&gt;

&lt;p&gt;Já tínhamos o tipo &lt;code&gt;object&lt;/code&gt; e ninguém solicitou pela sua descontinuidade, &lt;a href=&quot;http://blog.synopse.info/post/2010/08/06/Save-object%2C-stop-class-hegemony%21&quot;&gt;por quê não mantê-lo&lt;/a&gt;?&lt;/p&gt;

&lt;p&gt;E para aqueles que não conhecem a sintaxe do seu uso, aqui está um simples exemplo:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;type
  TMsg = object
    procedure Show(const aText: string);
  end;
{...}
var
  msg: TMsg;
begin
  msg.Show;
end;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Simples, direto, sem &lt;code&gt;try..finally&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Felizmente o tipo &lt;code&gt;object&lt;/code&gt; continua vivo no Free Pascal.&lt;/p&gt;

&lt;p&gt;Até logo.&lt;/p&gt;
</description>
        <pubDate>Mon, 18 Mar 2019 00:00:00 +0100</pubDate>
        <link>http://objectpascalprogramming.com/tipo-object-vivo</link>
        <guid isPermaLink="true">http://objectpascalprogramming.com/tipo-object-vivo</guid>
      </item>
    
      <item>
        <title>Array de Objetos</title>
        <description>&lt;p&gt;Quando você precisa de uma simples lista de objetos, qual estrutura você utiliza?&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;&lt;img src=&quot;/images/2019/antonio-garcia-339626-unsplash.jpg&quot; alt=&quot;Unsplash image&quot; /&gt;
&lt;br /&gt;&lt;span style=&quot;font-family: &#39;Bebas Neue&#39;; font-size: 0.7em;&quot;&gt;Photo by Antonio Garcia on Unsplash&lt;/span&gt;&lt;/p&gt;

&lt;h2 id=&quot;introducao&quot;&gt;Introdução&lt;/h2&gt;

&lt;p&gt;Todo sistema utiliza listas para armazenar desde valores primitivos até instancias de objetos.&lt;/p&gt;

&lt;p&gt;Aqui eu sempre advoguei sobre utilizar objetos em (quase) todos os lugares. Mas temos que ser eficientes e não desperdiçar recursos. Não devemos criar estruturas mais complexas, como classes e interfaces, quando outra estrutura pode resolver o problema, além de simplificar a solução.&lt;/p&gt;

&lt;p&gt;Basicamente uma lista pode ser representada por um array, um &lt;a href=&quot;/listas-genericas-sem-generics&quot;&gt;objeto genérico&lt;/a&gt; (ex: &lt;code&gt;TList&lt;/code&gt;) ou um objeto especializado que possui regras de negócio que irão trabalhar com os elementos de acordo com requisitos &lt;em&gt;específicos&lt;/em&gt; do usuário.&lt;/p&gt;

&lt;p&gt;Se você não precisa de uma lista com &lt;a href=&quot;/posts/codigo-duplicado-talvez-nao/#regras-de-negocio&quot;&gt;regras de negócio&lt;/a&gt;, arrays podem ser um boa escolha.&lt;/p&gt;

&lt;h2 id=&quot;vs&quot;&gt;Array vs Lista&lt;/h2&gt;

&lt;p&gt;Poderíamos utilizar lista de objetos em todos os lugares, mas os arrays continuam relevantes.&lt;/p&gt;

&lt;p&gt;Arrays armazenam informações no &lt;em&gt;stack&lt;/em&gt;, enquanto Listas utilizam o &lt;em&gt;heap&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;A utilização do stack tem muito mais performance pois o acesso a esse tipo de memória é muito mais rápido. A alocação da memória é determinada já na compilação do programa, tornando fácil o seu gerenciamento.&lt;/p&gt;

&lt;p&gt;O stack é protegido e mais rápido, pois é mais fácil para o compilador alocar/desalocar memória lá. Entretanto, ele é mais limitado quanto ao espaço, comparado ao heap. O heap é “ilimitado” (pode ocupar toda a memória RAM), porém mais lento. Sendo o heap compartilhado por toda a aplicação, é mais difícil/custoso para o compilador alocar/desalocar a memória. E, sendo esses dados “globais” à aplicação, eles muitas vezes devem ser sincronizados quando os acessamos utilizando multi-threading.&lt;/p&gt;

&lt;p&gt;Então, como escolher entre eles?&lt;/p&gt;

&lt;p&gt;Podemos definir 3 tópicos básicos que você deverá levar em conta, quando for tomar sua decisão: Performance, Regras de Negócio e Transferência de Dados.&lt;/p&gt;

&lt;h3 id=&quot;performance&quot;&gt;Performance&lt;/h3&gt;

&lt;p&gt;Você usa o stack quando souber a quantidade de dados à alocar na memória já em tempo de compilação. No entanto, não deve ser uma massa muito grande de dados—mesmo havendo configurações/diretivas em cada compilador para customização—ou você poderá obter um erro de memória em tempo de execução.&lt;/p&gt;

&lt;p&gt;O heap é utilizado quando você não souber, exatamente, quantos dados irá precisar em tempo de execução ou se houver a tendência de que será uma massa muito grande de dados.&lt;/p&gt;

&lt;p&gt;O stack sempre será mais rápido que o heap. Então, se você necessitar da máxima performance, tenha isso em mente quando tiver instanciando novas listas de objetos.&lt;/p&gt;

&lt;h3 id=&quot;regras&quot;&gt;Regras de Negócio&lt;/h3&gt;

&lt;p&gt;Imagine um sistema de estacionamento de veículos. Se você tem uma classe que representa o estacionamento, então você tem uma lista especializada para armazenar as vagas e carros ou ao menos uma lista genérica dentro da classe especializada.&lt;/p&gt;

&lt;p&gt;Você teria regras de negócios referente ao estacionamento como: horário de entrada/saída, número da vagas, serviço de manobrista, etc. Não vem ao caso pensar em todas as regras de negócio de um estacionamento. O mais importante é sabermos que &lt;em&gt;haveria&lt;/em&gt; regras de negócio para essa &lt;em&gt;lista especializada&lt;/em&gt;, o estacionamento.&lt;/p&gt;

&lt;p&gt;Apesar da maioria dos estacionamentos terem um número limitado de vagas, virtualmente pode-se adicionar mais carros em “vagas não-oficiais”, deixando um total de vagas “em aberto”—se isso não acontece na sua cidade/país, bem, apenas considere a possibilidade.&lt;/p&gt;

&lt;p&gt;Se o número de vagas é bem grande ou incerto, a melhor opção de escolha nesse caso seria uma lista especializada, alocada no heap, com outros métodos adicionais que implementam as regras de negócio.&lt;/p&gt;

&lt;h3 id=&quot;transferencia&quot;&gt;Transferência de Dados&lt;/h3&gt;

&lt;p&gt;Se sua lista existe apenas para armazenar temporariamente objetos ou para passagem de parâmetro entre contextos, por exemplo, um simples array poderia ser utilizado.&lt;/p&gt;

&lt;p&gt;Chamo de transferência de &lt;a href=&quot;/posts/pensando-em-dados/&quot;&gt;dados&lt;/a&gt;, pois você poderá transferir desde elementos simples e primitivos até objetos complexos de listas especializadas, entre contextos distintos. Esse seria o meio-termo entre performance vs especialização. Você pode ter listas de objetos, carregando instâncias de objetos complexos, mas utilizar os arrays para transportar apenas parte desses objetos de forma eficiente.&lt;/p&gt;

&lt;p&gt;Exemplo. A sua lista de vagas acima, o estacionamento, possui um número X de vagas em uso em um determinado momento. Cada vaga pode ser representada por uma instância. Imagine que o usuário selecionou 3 vagas para “deixar livre”. Após a seleção, é necessário fazer algumas operações com essas instâncias (vagas). Essas operações irão receber um “array de vagas” como parâmetro.&lt;/p&gt;

&lt;p&gt;O array seria utilizado por quê você já sabe a quantidade de elementos que ele iria ter—determinado pela seleção do usuário. Criar uma nova lista de vagas (do tipo estacionamento) para adicionar apenas 3 instâncias e então passar como parâmetro seria um desperdício de processamento, além de não fazer muito sentido passar “todo um estacionamento”—uma instância da mesma classe—ou uma cópia da lista oficial com menos registros, apenas para fazer o processamento da liberação das vagas.&lt;/p&gt;

&lt;p&gt;Um array seria a escolha mais simples. No entanto, não há só um tipo de array.&lt;/p&gt;

&lt;h2 id=&quot;utilizando&quot;&gt;Utilizando Arrays Dinâmicos&lt;/h2&gt;

&lt;p&gt;Existem alguns tipos de arrays como estáticos, constantes, dinâmicos, multi-dimensionais, etc.&lt;/p&gt;

&lt;p&gt;Para esse artigo, iremos utilizar os &lt;em&gt;arrays dinâmicos&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Utilizar arrays dinâmicos no Object Pascal é relativamente fácil, porém temos que prestar atenção em duas regras principais:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;O índice do primeiro elemento sempre será 0 (zero);&lt;/li&gt;
  &lt;li&gt;É necessário determinar o tamanho do array antes de inserir seus elementos;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;O índice&lt;/strong&gt; do primeiro elemento sempre será zero, diferentemente de arrays contantes, por exemplo, onde você pode informar outro valor para o primeiro elemento. Tenha sempre isso em mente quando utilizar o array em loops.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;O tamanho&lt;/strong&gt; de um array é determinado pela função &lt;code&gt;SetLength(array, size)&lt;/code&gt; padrão.&lt;/p&gt;

&lt;p&gt;Abaixo um exemplo do uso da função e a carga de um &lt;code&gt;array of Integer&lt;/code&gt; com valores:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var
  a: array of Integer;
begin
  SetLength(a, 10); // from 0 to 9 positions
  for i := 0 to 10 do
    a[i] := i;
end;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Diferentemente de classes e interfaces, para definir um array para armazenar elementos de um determinado tipo, basta apenas uma linha de código, como visto acima.&lt;/p&gt;

&lt;p&gt;Foi definido um array para &lt;code&gt;Integer&lt;/code&gt;, mas a mesma sintaxe vale para tipos de classes ou interfaces. Se estivermos trabalhando com Vagas—instâncias da interface &lt;code&gt;ISpot&lt;/code&gt;, por exemplo—poderíamos definir um array dessa forma:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;type
  TSpotArray = array of ISpot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Não precisamos nos preocupar com herança, métodos ou sobrescrita de métodos, caso estivéssemos definindo uma nova classe.&lt;/p&gt;

&lt;p&gt;Apenas uma única linha define um novo &lt;em&gt;container&lt;/em&gt; dinâmico de instâncias de &lt;code&gt;ISpot&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Utilizando uma variação do algoritmo acima, você é capaz de inicializar o array e adicionar os 3 itens que o usuário selecionou, passando-o como um parâmetro para o algoritmo que irá desalocar as vagas.&lt;/p&gt;

&lt;p&gt;Não há necessidade de se preocupar com o desalocamento de memória, pois tudo será feito automaticamente pelo compilador.&lt;/p&gt;

&lt;h2 id=&quot;conclusao&quot;&gt;Conclusão&lt;/h2&gt;

&lt;p&gt;Arrays são ótimas opções para trabalhar com objetos em memória e passagem de dados entre contextos.&lt;/p&gt;

&lt;p&gt;Eles são &lt;a href=&quot;/posts/simplicidade/&quot;&gt;simples&lt;/a&gt;, gerenciados pelo compilador no stack e muito mais rápidos que listas de objetos.&lt;/p&gt;

&lt;p&gt;Até logo.&lt;/p&gt;
</description>
        <pubDate>Mon, 11 Mar 2019 00:00:00 +0100</pubDate>
        <link>http://objectpascalprogramming.com/array-de-objetos</link>
        <guid isPermaLink="true">http://objectpascalprogramming.com/array-de-objetos</guid>
      </item>
    
      <item>
        <title>Variáveis Locais Deveriam ter Nomes Curtos</title>
        <description>&lt;p&gt;Já pensou que você pode estar dificultando a leitura do seu código por utilizar nomes mais longos e verbosos em variáveis locais do que utilizando nomes mais curtos?&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;&lt;img src=&quot;/images/2019/chuttersnap-413007-unsplash.jpg&quot; alt=&quot;Unsplash image&quot; /&gt;
&lt;br /&gt;&lt;span style=&quot;font-family: &#39;Bebas Neue&#39;; font-size: 0.7em;&quot;&gt;Photo by chuttersnap on Unsplash&lt;/span&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/posts/nomeando-variaveis-e-metodos/&quot;&gt;Nomenclatura&lt;/a&gt; é quase uma arte, especialmente no desenvolvimento de software.&lt;/p&gt;

&lt;p&gt;Escolher bons nomes irá deixar seu código mais legível e isso será imprescindível para a manutenção do mesmo no longo prazo.&lt;/p&gt;

&lt;p&gt;Entretanto, um bom nome não quer dizer um nome mais longo e verboso.&lt;/p&gt;

&lt;p&gt;Um bom nome irá depender de alguns fatores. Por exemplo: se o nome identificar uma variável de &lt;em&gt;índice&lt;/em&gt; para um &lt;em&gt;loop&lt;/em&gt;, a maioria dos programadores irá utilizar “i”.&lt;/p&gt;

&lt;p&gt;Por quê “i” e não “index”, já que este último é mais explícito?&lt;/p&gt;

&lt;p&gt;É claro que haverá todo tipo e código, todo tipo de nomenclatura. Mas, me refiro a maioria. E a maioria utiliza “i” para a nomenclatura de variáveis de índices.&lt;/p&gt;

&lt;p&gt;E se quisermos nos referir a uma posição na tela? Eu diria que a nomenclatura mais utiliza é “x,y”. Podemos declarar um &lt;em&gt;record&lt;/em&gt; ou classe como &lt;code&gt;TPoint&lt;/code&gt; mas é bem provável que seus atributos sejam &lt;code&gt;X&lt;/code&gt; e &lt;code&gt;Y&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;“Convenção” — você diria.&lt;/p&gt;

&lt;p&gt;Sim, convenção, porém eu acho que o motivo está além disso.&lt;/p&gt;

&lt;p&gt;Trata-se de &lt;strong&gt;legibilidade&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Quando estamos trabalhando em um contexto bem menor, como a implementação de um método por exemplo, não precisamos de nomes longos e verbosos. Sabemos o que X e Y significam; sabemos que “i” é o índice de um loop; sabemos que “s1” e “s2” (provavelmente) significam &lt;em&gt;strings&lt;/em&gt; 1 e 2, respectivamente.&lt;/p&gt;

&lt;p&gt;Não me entenda mal. Não estou dizendo que &lt;em&gt;todas&lt;/em&gt; as variáveis locais devem ter apenas uma ou duas letras. Depende. E talvez não haja uma regra para determinar qual nomenclatura mais adequada, uma regra que abrange todos os casos possíveis. Mas podemos utilizar o bom senso.&lt;/p&gt;

&lt;p&gt;Sugiro que os nomes sejam os menores possíveis, porém sem haver &lt;em&gt;ambiguidades&lt;/em&gt;. Por exemplo: seria estranho haver duas variáveis assim:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var
  s1: string;      
  s2: TStream;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;São dois tipos completamente diferentes, porém utilizando a mesma nomenclatura. É ambíguo e confuso. Por quê &lt;code&gt;s2&lt;/code&gt; representa o &lt;code&gt;TStream&lt;/code&gt; e não &lt;code&gt;s1&lt;/code&gt;? Falta lógica.&lt;/p&gt;

&lt;p&gt;Porém ainda assim, na minha opinião, ainda seriam melhores que isso:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var
  ClientNameTrimed: string;      
  ClientReturnedAsStream: TStream;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;O motivo é simples: se você está nomeando suas variáveis de forma tão longa, é por quê o método está fazendo coisas demais e você precisa identificar cada variável — talvez existam &lt;a href=&quot;/posts/menos-e-mais/#variaveis-locais&quot;&gt;mais de cinco&lt;/a&gt; — como única para tentar melhorar a legibilidade do método, mas ignorando os indícios de que o método deveria ser refatorado (dividido) em partes menores. Métodos menores poderiam ter menos variáveis, com nomenclatura mais simples.&lt;/p&gt;

&lt;p&gt;Seguindo o primeiro exemplo, podemos refatorar as variáveis:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var
  str: string;      
  stm: TStream;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Apesar de ainda haver certa ambiguidade — &lt;code&gt;str&lt;/code&gt; ainda poderia ser considerada uma abreviação de &lt;code&gt;TStream&lt;/code&gt; — a legibilidade é melhor. Poderíamos simplificar, refatorando &lt;code&gt;str&lt;/code&gt; para apenas &lt;code&gt;s&lt;/code&gt; já que trata-se de um tipo primitivo, aplicando a lógica de que “tipos primitivos estão abaixo de classes” e, portanto, utilizam menos caracteres…&lt;/p&gt;

&lt;p&gt;O importante é haver alguma &lt;em&gt;lógica de nomenclatura&lt;/em&gt; entre a equipe.&lt;/p&gt;

&lt;p&gt;Outro exemplo de nomenclatura interessante é dar nomes próprios às variáveis, quando estas são do tipo interface ou classe. Vejamos:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var
  bob: TStream;      
  john: TStream;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Temos 2 &lt;em&gt;streams&lt;/em&gt; e, ao invés de nomear como &lt;code&gt;stm1&lt;/code&gt; e &lt;code&gt;stm2&lt;/code&gt; ou algo parecido, apenas damos nomes próprios e curtos, de &lt;em&gt;fácil&lt;/em&gt; memorização.&lt;/p&gt;

&lt;p&gt;Uma vez que seu cérebro já sabe que &lt;code&gt;bob&lt;/code&gt; contém a entrada de dados (apenas um exemplo) e &lt;code&gt;john&lt;/code&gt; irá conter a saída processada, seria mais difícil esquecer dos nomes comparado a &lt;code&gt;stm1&lt;/code&gt; e &lt;code&gt;stm2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Mantenha os nomes de variáveis locais o mais curto possível.&lt;/p&gt;

&lt;p&gt;Essa é a minha sugestão.&lt;/p&gt;

&lt;p&gt;Até logo.&lt;/p&gt;
</description>
        <pubDate>Mon, 07 Jan 2019 00:00:00 +0000</pubDate>
        <link>http://objectpascalprogramming.com/variaveis-locais</link>
        <guid isPermaLink="true">http://objectpascalprogramming.com/variaveis-locais</guid>
      </item>
    
      <item>
        <title>Como Dividir e Organizar o Código em Formulários com Muitos Widgets</title>
        <description>&lt;p&gt;Definir dezenas de métodos em formulários e DataModules parece ser comum entre programadores. Podemos fazer algo para minimizar essa prática?&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018/robert-bye-200739-unsplash.jpg&quot; alt=&quot;Unsplash image&quot; /&gt;
&lt;br /&gt;&lt;span style=&quot;font-family: &#39;Bebas Neue&#39;; font-size: 0.7em;&quot;&gt;Photo by Robert Bye on Unsplash&lt;/span&gt;&lt;/p&gt;

&lt;h2 id=&quot;introducao&quot;&gt;Introdução&lt;/h2&gt;

&lt;p&gt;Em um formulário com muitos widgets, haveria dezenas de métodos para controlá-los. Esses métodos lidariam com o estado visual (visível, checado, cores,…); com os dados (texto, grids, labels,…); mensagens (dialogs, popups,…) e todo tipo de interação entre os componentes visuais e não-visuais.&lt;/p&gt;

&lt;p&gt;Definir dezenas de métodos em formulários e DataModules parece ser comum. O programador cria um DataModule com queries e componentes relacionados, acrescenta 50 métodos e considera ter feito um ótimo trabalho na reutilização e organização do código — no entanto ele só criou mais uma classe inchada, seguindo o anti-padrão conhecido como a &lt;a href=&quot;http://wiki.c2.com/?GodClass&quot;&gt;síndrome da classe Deus&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Nesse artigo você poderá aprender algumas técnicas para se livrar dessas classes com dezenas de métodos, difíceis de entender e gerenciar.&lt;/p&gt;

&lt;h2 id=&quot;rad&quot;&gt;A culpa é do RAD?&lt;/h2&gt;

&lt;p&gt;Na minha opinião, Delphi sempre foi a melhor IDE para desenvolvimento de aplicações Desktop — até surgirem opções como Lazarus — e grande parte desse sucesso é devido ao conceito e uso do RAD (Rapid Application Development).&lt;/p&gt;

&lt;p&gt;Largue um componente no formulário, defina algumas propriedades, implemente alguns eventos e pronto. Fácil. Rápido. Mas talvez, sujo.&lt;/p&gt;

&lt;p&gt;Para prototipagem é ótimo. Você consegue mostrar ao cliente algo funcionando em minutos. Mas para código real, para a manutenção, esse tipo de design pode se tornar um pesadelo no médio prazo.&lt;/p&gt;

&lt;p&gt;Mas a culpa não é do RAD. Ele é apenas uma ferramenta. Ferramentas sozinhas não fazem mal projetos. Os desenvolvedores fazem.&lt;/p&gt;

&lt;p&gt;RAD foi feito para agilizar o desenvolvimento, especialmente no design de formulários. Mas levaram esse conceito tão longe que muitos desenvolvedores só conhecem esse caminho para o desenvolvimento, desde formulários, regras de negócio, até a persistência.&lt;/p&gt;

&lt;p&gt;RAD significou o sucesso mas também a “desgraça” do Delphi. É por causa do RAD que o Delphi (até hoje) não é bem visto em círculos de desenvolvimento mais voltados a regras de negócio, padrões de projetos, aplicações em camadas, etc.&lt;/p&gt;

&lt;p&gt;Mas, novamente, não é culpa do RAD. Não há nada de errado com RAD. O errado e tentar implementar tudo no modelo RAD, na minha opinião.&lt;/p&gt;

&lt;p&gt;É mais fácil largar componentes no formulário e setar propriedades e eventos, do que pensar em padrões de projeto, orientação a objetos e desenvolvimento em camadas.&lt;/p&gt;

&lt;p&gt;RAD funciona, mas não é sustentável no longo prazo.&lt;/p&gt;

&lt;h2 id=&quot;forms&quot;&gt;Formulários sem Métodos&lt;/h2&gt;

&lt;p&gt;O uso indiscriminado do RAD pode deixar a aplicação tão acoplada que seria muito difícil ter camadas separadas entre GUI, regras de negócio e persistência.&lt;/p&gt;

&lt;p&gt;Acredito que para remover o conceito de “RAD para tudo”, temos que começar com o básico, por exemplo, como desenvolver formulários com uma quantidade mínima de métodos.&lt;/p&gt;

&lt;p&gt;A quantidade de métodos não está relacionado diretamente ao RAD — você pode ter uma classe com 100 métodos em qualquer linguagem, utilizando RAD ou não — no entanto, eu acredito que o RAD “estimula” essa prática, pois se todos os widgets e eventos estão declarados no formulário, onde mais eu iria implementar os métodos para lidar com esses componentes, certo?&lt;/p&gt;

&lt;p&gt;Essa prática e muito comum, porém equivocada. Uma classe deveria ser pequena — menor quantidade de métodos possível — e coesa — todos os seus atributos são utilizados na maior quantidade de métodos possível. E fazer isso em um formulário e praticamente impossível.&lt;/p&gt;

&lt;p&gt;A tendência é que cada novo método trabalhe com poucos widgets; os métodos terão uma nomenclatura tão verbosa quanto uma frase, pois todos irão fazer parte de uma mesma classe e não pode haver ambiguidade ou colisão de nomes.&lt;/p&gt;

&lt;p&gt;Quantas vezes isso já aconteceu com você?&lt;/p&gt;

&lt;p&gt;Seria possível termos formulários com o &lt;a href=&quot;https://objectpascalprogramming.com/posts/menos-e-mais/#metodos&quot;&gt;mínimo de métodos&lt;/a&gt; ou até nenhum e, mesmo assim, capazes de controlar as interações entre todos os widgets e componentes visuais e não-visuais?&lt;/p&gt;

&lt;p&gt;A primeira prática que eu recomendo é separar widgets em frames — disponíveis no Delphi desde as primeiras versões através da classe &lt;code&gt;TFrame&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Muitos formulários possuem &lt;em&gt;tabs&lt;/em&gt; e cada tab pode ser um frame que desconhece completamente o formulário onde ele está contido.&lt;/p&gt;

&lt;p&gt;Cada frame irá ter seu próprio conjunto de widgets, com nomenclatura simplificada, visto que não há colisões de nomes entre outros widgets se tudo estivesse em um mesmo formulário.&lt;/p&gt;

&lt;p&gt;Esse é o &lt;em&gt;primeiro&lt;/em&gt; nível da refatoração.&lt;/p&gt;

&lt;p&gt;Mas isso não elimina a quantidade enorme de métodos que poderão existir, pois o desenvolvedor precisa por ação nos formulários e frames.&lt;/p&gt;

&lt;p&gt;O segundo nível consiste em dividir para conquistar, eliminando quase que totalmente os métodos de um formulário.&lt;/p&gt;

&lt;h2 id=&quot;dividir&quot;&gt;Dividir para Conquistar&lt;/h2&gt;

&lt;p&gt;Independente de ser um formulário, frame ou DataModule, considere todos como sendo &lt;a href=&quot;2016-02-22-datamodule-e-apenas-um-container&quot;&gt;containers&lt;/a&gt; de componentes (visuais ou não).&lt;/p&gt;

&lt;p&gt;O objetivo é dividir os métodos em pequenos objetos que irão fazer uso dos componentes do container.&lt;/p&gt;

&lt;p&gt;Mesmo que esse artigo se refira a formulários complexos, vou lhe dar um exemplo simples, mostrando que com apenas 1 widget, poderíamos adicionar vários métodos ao formulário, erroneamente.&lt;/p&gt;

&lt;p&gt;Considere uma instância de um &lt;code&gt;TStatusBar&lt;/code&gt; para exibir informações da aplicação.&lt;/p&gt;

&lt;p&gt;O usuário precisaria ver a versão da aplicação; o database em uso; o status atual de algum processamento.&lt;/p&gt;

&lt;p&gt;Um StatusBar possui a propriedade &lt;code&gt;Panels[]&lt;/code&gt;que é como um array de objetos de texto — dado um índice, você altera o texto naquela posição.&lt;/p&gt;

&lt;p&gt;Um programador iniciante talvez iria utilizá-lo dessa forma:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;StatusBar1.Panels[0].Text := version;
StatusBar1.Panels[1].Text := database;
StatusBar1.Panels[2].Text := &#39;Loading...&#39;;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Um programador mais experiente saberia que não se deve utilizar índices arbitrários pelo código — se quisermos mudar a posição de alguma informação, teríamos que percorrer todo o código para mudar os índices para novas posições. Esse programador provavelmente iria criar constantes para cada índice, o que resolveria a manutenção futura, no entanto teríamos constantes (verbosas) no código que estão “desacopladas” do objeto no qual elas atuam, ou seja, o StatusBar.&lt;/p&gt;

&lt;p&gt;O código ficaria dessa forma:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;const
  STATUSBAR_VERSION = 0;
  STATUSBAR_DATABASE = 1;
  STATUSBAR_STATUS = 2;

StatusBar1.Panels[STATUSBAR_VERSION].Text := version;
StatusBar1.Panels[STATUSBAR_DATABASE].Text := database;
StatusBar1.Panels[STATUSBAR_STATUS].Text := &#39;Loading...&#39;;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Veja o quão é verboso cada constante, pois é (quase) obrigatório utilizar prefixos para deixar claro em qual componente(s) esse  “grupo de constantes” trabalham.&lt;/p&gt;

&lt;p&gt;Outro tipo de desenvolvedor iria utilizar métodos no formulário. O exemplo abaixo pode ser meio extremo, mas considere que eu não poderia dar um exemplo real pois não caberia nesse artigo. Portanto, utilizar tais métodos não estaria tão longe da realidade:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;  procedure SetStatusBarVersion(const aValue: string);
  procedure SetStatusBarDatabase(const aValue: string);
  procedure SetStatusBarStatus(const aValue: string);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Criando métodos no formulário elimina as constantes e índices, porém incha a classe do formulário.&lt;/p&gt;

&lt;p&gt;Veja, também, o quão é verboso cada método, novamente utilizando prefixos longos e entediantes — nomes longos em métodos e variáveis são sinais de que eles podem não fazer parte da classe onde estão.&lt;/p&gt;

&lt;p&gt;Foram adicionados 3 métodos para lidar com apenas 1 componente que exibe texto.&lt;/p&gt;

&lt;p&gt;Finalmente, um arquiteto de software teria objetivos maiores como: reutilizar os métodos em outro formulário ou projeto; simplificar o formulário, removendo métodos que lidam apenas com poucos componentes; retirar índices e constantes arbitrárias; trabalhar com o StatusBar sem pensar que ele é um StatusBar, abstraindo-o.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;TStatusBarWidget = class
private
  fOrigin: TStatusBar;
  fVersion: string;
  fDatabase: string;
  fStatus: string;
public
  constructor Create(aOrigin: TStatusBar); reintroduce;
  property Version: string read fVersion;
  property Database: string read fDatabase;
  property Status: string read fStatus write fStatus;
end;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Essa classe iria receber a instância do StatusBar real no construtor, inicializada no construtor do formulário; iria obter os dados da versão e database automaticamente, disponibilizando propriedades somente leitura; o status poderia ser atualizado e lido dentro dos eventos do formulário.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;begin
   fStatusBar.Status := &#39;Loading...&#39;;
end;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Toda a lógica referente ao StatusBar estaria encapsulada dentro da classe &lt;code&gt;TStatusBarWidget&lt;/code&gt;, podendo ser reutilizada em outro lugar.&lt;/p&gt;

&lt;p&gt;Outros programadores que porventura trabalhem no código, não iriam precisar lembrar de índices ou constantes arbitrárias. Eles iriam utilizar apenas um único objeto com métodos bem definidos para cada atividade, abstraindo sobre o que esta acontecendo internamente ao objeto — a atualização do StatusBar.&lt;/p&gt;

&lt;p&gt;O formulário não teria nenhum método (relacionado a StatusBar), contendo apenas um atributo privado do tipo &lt;code&gt;TStatusBarWidget&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O exemplo é simples, porém acredito que você tenha visualizado que poderá utilizar essa técnica não apenas para encapsular um componente, mas também para todo um conjunto deles, implementando toda a interação entre eles num único objeto.&lt;/p&gt;

&lt;h2 id=&quot;conclusao&quot;&gt;Conclusão&lt;/h2&gt;

&lt;p&gt;Toda vez que você nomear um método com nomenclatura composta, pare e pense se esse método deveria estar em outra classe.&lt;/p&gt;

&lt;p&gt;Não implemente vários métodos numa única classe. Separe-os em objetos menores e coesos, mesmo que esses objetos trabalhem diretamente com os componentes do container.&lt;/p&gt;

&lt;p&gt;É melhor ter vários objetos pequenos, mesmo que fortemente acoplados, do que por tudo num único objeto onde a manutenção irá se tornar um caos em pouco tempo.&lt;/p&gt;

&lt;p&gt;Até logo.&lt;/p&gt;

&lt;h2 id=&quot;bnus&quot;&gt;Bônus&lt;/h2&gt;

&lt;p&gt;Eu fiz um Webinar sobre esse artigo.&lt;/p&gt;

&lt;p&gt;Você pode baixar os fontes &lt;a href=&quot;/code/webinar-2.zip&quot;&gt;aqui&lt;/a&gt;.&lt;/p&gt;

&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/Zvc8Vnv0JnI&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
</description>
        <pubDate>Mon, 17 Dec 2018 00:00:00 +0000</pubDate>
        <link>http://objectpascalprogramming.com/formularios-e-widgets</link>
        <guid isPermaLink="true">http://objectpascalprogramming.com/formularios-e-widgets</guid>
      </item>
    
      <item>
        <title>Pascal Deveria ser Modernizado?</title>
        <description>&lt;p&gt;Ao longo dos anos, desde Turbo Pascal até as versões mais atuais do Delphi e Lazarus, temos visto muitas mudanças na linguagem.&lt;/p&gt;

&lt;p&gt;Você acha que estamos modernizando a linguagem Object Pascal?&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;&lt;img src=&quot;/images/2018/hayes-potter-1054894-unsplash.jpg&quot; alt=&quot;Unsplash image&quot; /&gt;
&lt;br /&gt;&lt;span style=&quot;font-family: &#39;Bebas Neue&#39;; font-size: 0.7em;&quot;&gt;Photo by Hayes Potter on Unsplash&lt;/span&gt;&lt;/p&gt;

&lt;h2 id=&quot;introducao&quot;&gt;Introdução&lt;/h2&gt;

&lt;p&gt;É incrível como até hoje eu ainda tenho que responder perguntas sobre os motivos de continuar utilizando a linguagem Object Pascal.&lt;/p&gt;

&lt;p&gt;Vou desenvolver utilizando Object Pascal — eu digo a um possível cliente.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Object Pas… Ah, aquela linguagem da Apple? (Objective C)&lt;/li&gt;
  &lt;li&gt;Acho que você quer dizer Delphi, não é?&lt;/li&gt;
  &lt;li&gt;Por quê você continua utilizando “isso”?&lt;/li&gt;
  &lt;li&gt;Por quê não utilizar C# ou Java?&lt;/li&gt;
  &lt;li&gt;Você ainda consegue achar emprego?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Eu já escrevi meus &lt;a href=&quot;/porque-eu-escolhi-delphi-e-object-pascal#motivos&quot;&gt;motivos&lt;/a&gt; mas entendo como pode ser difícil para a maioria das pessoas acreditarem.&lt;/p&gt;

&lt;p&gt;Talvez eles pensem que Object Pascal não é tão &lt;a href=&quot;https://castle-engine.io/modern_pascal_introduction.html&quot;&gt;moderno&lt;/a&gt; quanto as linguagens &lt;em&gt;mainstream&lt;/em&gt;.&lt;/p&gt;

&lt;h2 id=&quot;prioridade&quot;&gt;Quando o Concorrente é Prioridade&lt;/h2&gt;

&lt;p&gt;Existem linguagens muito mais “modernas” hoje em dia e escolher uma que “está morta” não parece uma opção razoável &lt;del&gt;para aqueles que só sabem seguir cegamente o que a maioria diz&lt;/del&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Se você quer chegar onde a maioria não chega, faça o que a maioria não faz — Bill Gates&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Talvez esse sentimento de modernização está abalando até mesmo os diretores e desenvolvedores do atual Delphi.&lt;/p&gt;

&lt;p&gt;A “modernização” a que me refiro pode ser simplificada dessa forma:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Se meu concorrente tem tal feature, eu preciso ter também.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;E isso pode matar a linguagem.&lt;/p&gt;

&lt;h3 id=&quot;inline&quot;&gt;Inline Variable Declarations&lt;/h3&gt;

&lt;p&gt;A alguns dias recebemos a notícia que a linguagem Delphi irá ter &lt;em&gt;Inline Variables&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Marco Cantu — respeitado e conceituado no mundo Delphi — já começou a “matar” a sintaxe Pascal clássica de declaração de variáveis quando inicia seu &lt;a href=&quot;http://blog.marcocantu.com/blog/2018-october-inline-variables-delphi.html&quot;&gt;artigo&lt;/a&gt; escrevendo “Old Style Var Blocks”.&lt;/p&gt;

&lt;p&gt;Então é oficial, estamos &lt;em&gt;defasados&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;Na linguagem Object Pascal, declaramos as variáveis em blocos bem definidos e organizados, diferentemente de outras linguagens onde pode-se declarar onde quiser. Entretanto, agora isso parece ser ruim, já que a maioria faz diferente.&lt;/p&gt;

&lt;p&gt;Solução? Ora, vamos copiar o concorrente!&lt;/p&gt;

&lt;p&gt;O foco parece ser mais no que o concorrente anda fazendo nos compiladores deles do que nos seus fieis usuários e desenvolvedores Pascal.&lt;/p&gt;

&lt;h3 id=&quot;inference&quot;&gt;Type Inference for Inline Variables&lt;/h3&gt;

&lt;p&gt;Na linguagem Pascal, tudo deve ser previamente declarado.&lt;/p&gt;

&lt;p&gt;Tudo.&lt;/p&gt;

&lt;p&gt;Isso é algo intrínseco a linguagem desde o seu nascimento e é um dos pontos fortes dela, pois minimiza qualquer ambiguidade na declaração de tipos.&lt;/p&gt;

&lt;p&gt;Tem quem goste, tem quem odeie. Não importa. Ela foi feita dessa forma e deve ser respeitada.&lt;/p&gt;

&lt;p&gt;Mas, agora temos a &lt;em&gt;inferência de tipo&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Isso existe em outras linguagens mas é provável que você conheça através do C#.&lt;/p&gt;

&lt;p&gt;E as pessoas “aplaudiram”…&lt;/p&gt;

&lt;p&gt;Sim, pode ser considerada uma facilidade. Você irá escrever menos. E 99% dos programadores Object Pascal — especialmente Delphi — adoram uma facilidade sem se preocupar com o custo. Sim, o custo, por quê na engenharia nada vem de graça.&lt;/p&gt;

&lt;p&gt;A compilação pode ficar mais lenta; pode haver erros de conversão obscuros; o código pode ficar menos legível… além de ir contra a própria filosofia da linguagem, que é declarar tudo antes.&lt;/p&gt;

&lt;p&gt;Mesmo assim, se é fácil para escrever e o concorrente tem… por quê não?&lt;/p&gt;

&lt;h2 id=&quot;conclusao&quot;&gt;Conclusão&lt;/h2&gt;

&lt;p&gt;Não há problemas com a declaração de variáveis atual. Esse é o estilo Pascal. Entretanto, parecem que estão mais preocupados em adicionar mais features a linguagem do que corrigir &lt;em&gt;bugs&lt;/em&gt;. Bem, cada um sabe o que é melhor para sua empresa.&lt;/p&gt;

&lt;p&gt;Trabalho com sistemas de alta performance que ainda utilizam a sintaxe clássica do Delphi 7. Então, posso afirmar que não é isso que irá deixar a linguagem melhor que seus concorrentes.&lt;/p&gt;

&lt;p&gt;Não me entenda mal. Não estou dizendo que não podemos alterar a linguagem. Existem algumas features ou acertos que que seriam muito bem vindos como, por exemplo, a correção da sintaxe &lt;a href=&quot;/a-declaracao-with-do-perfeita&quot;&gt;WITH-DO&lt;/a&gt; ou uma nova sintaxe para para determinar um &lt;a href=&quot;/fpc-macros#alias&quot;&gt;alias para uma Unit&lt;/a&gt;. Esses seriam melhorias que iriam corrigir problemas no design da linguagem, melhorando a leitura do código e tudo de acordo com a filosofia e estilo Pascal.&lt;/p&gt;

&lt;p&gt;Não quero um &lt;a href=&quot;https://en.wikipedia.org/wiki/Frankenstein&quot;&gt;Frankenstein&lt;/a&gt; de várias linguagens. Quero um design limpo, &lt;a href=&quot;/posts/simplicidade/&quot;&gt;simples&lt;/a&gt; e eficiente.&lt;/p&gt;

&lt;p&gt;Não quero copiar o concorrente. Quero escrever código Object Pascal.&lt;/p&gt;

&lt;p&gt;Não faz sentido levar seu BMW clássico ao mecânico dizendo para deixá-lo mais parecido com uma Mercedes-Benz mais moderna. Você acabará ficando com  &lt;em&gt;nenhum&lt;/em&gt; dos dois, apenas sucata.&lt;/p&gt;

&lt;p&gt;Até logo.&lt;/p&gt;
</description>
        <pubDate>Mon, 19 Nov 2018 00:00:00 +0000</pubDate>
        <link>http://objectpascalprogramming.com/pascal-deveria-ser-modernizado</link>
        <guid isPermaLink="true">http://objectpascalprogramming.com/pascal-deveria-ser-modernizado</guid>
      </item>
    
  </channel>
</rss>
