POO: Objetos quot;Auto-instanciáveisquot;

07/09/2009

7

Olá todos, o objetivo deste post é colocar uma alternativa *real* ao artigo de mesmo título publicado na ClubeDelphi número 109.


Primeiramente, quero colocar que criar objetos na inicialização da aplicação é algo que deve ser feito com critério, uma vez que memória é alocada consumindo recursos, isto deve ser realizado apenas quando necessário (para objetos que realmente precisamos ´instanciados´ desde sempre)

Geralmente quando precisamos destes objetos sem ter que nos preocupar com sua inicialização, estes são objetos ´centrais´ que possuem uma única instância para ser utilizada por toda aplicação. Por isso, e apenas para estes casos, posto a seguir um código exemplo utilizando o padrão de projeto Singleton.

Nesta implementação o objeto não é ´instanciado´ na seção Initialization, mas sim APENAS quando for usado pelo primeira vez, em qualquer parte da aplicação. Vamos ao código:



unit MeuObjeto;

uses
  SysUtils, Classes;

type

  TMeuObjeto = class (TObject)
  private
    fNome: string;
    fLista: TStrings;
  public
    constructor Create;
    destructor Destroy; override;
    class function Instance: TMeuObjeto;
    property Nome: string read fNome write fNome;
    property Lista: TStrings read fLista;
  end;


  function MeuObjeto: TMeuObjeto;

implementation

var
  InstanciaMeuObjeto: TMeuObjeto = nil;


function MeuObjeto: TMeuObjeto;
begin
  Result := TMeuObjeto.Instance;
end;


constructor TMeuObjeto.Create;
begin
  inherited Create;
  fLista := TStringList.Create;
  fNome := ´´;
end;

destructor TMeuObjeto.Destroy;
begin
  fLista.Free;
  inherited;
end;

class function TMeuObjeto.Instance: TMeuObjeto;
begin
  if InstanciaMeuObjeto=nil then
    InstanciaMeuObjeto := TMeuObjeto.Create;
  Result := InstanciaMeuObjeto;
end;

initialization

finalization
  if InstanciaMeuObjeto<>nil then
    InstanciaMeuObjeto.Free;

end.


Comentários sobre o código:

Note que foi criada uma FUNÇÃO como ponto de acesso global a instância do objeto e não uma variável. Isto garante maior poder e controle sobre a inicialização e destruição da mesma. Exemplo: Mesmo que um programador ´desavisado´ em determinado momento chame:

MeuObjeto.Free;

na próxima chamada de MeuObjeto ele estará lá novamente (uma nova instância, claro -- mas não haverá uma exceção de violação de acesso de memória)

Mas principalmente, função permite que o objeto seja criado APENAS quando for chamado pela primeira vez (e não na inicialização do programa, como ocorre com código da inicialization)

Outro ponto importante de notar é que a ´variável´ que contém a instância de nosso objeto fica em IMPLEMENTATION garantindo assim que nenhuma outra unit possa acessá-la diretamente (garantindo encapsulamento)

Ainda, a criação do método de classe ´Instance´ é opcional. Seu código poderia estar direto na função de entrada ´MeuObjeto´, caso não desejasse ter o método de classe. No exemplo acima:

TMeuObjeto.Instance.Nome := ´Teste´;

é igual a

MeuObjeto.Nome := ´Teste´;


Por fim, é importante notar que o destructor da classe foi re-escrito para destruir o objeto fLista criado no constructor, e que a seção finalization foi escrita para garantir que uma vez que InstanciaMeuObjeto tenha sido criado, seja destruído ao final da aplicação.

Vale salientar que este mesmo padrão pode ser implementado para Forms e DataModules (ou qualquer outra classe).


Vou ficando por aqui, esperando ter sido útil de alguma forma. Abraços a todos.

Anderson


Afarias

Afarias

Responder

Posts

08/09/2009

Osocram

Minha revista ainda não chegou :(

Não tenho o costume de usar o Initialization e o Finalization para instanciar ou destruir objetos, E sim para registrar Classes.

Mas assim que minha revista chegar, vou dar uma olhada no artigo p discutir melhor.


Responder

08/09/2009

Osocram

Aguarde e confie ;-)


Responder

09/09/2009

Afarias

Amigo...
Recebi hj a minha revista, apenas com alguns dias de atraso.

Bom particularmente não gosto desse tipo de abordagem.

O que geralmente gosto, e estou tentando fazer nos sistema é que cada Objeto meu saiba se criar e se destruir.

Por exemplo meu sistema é MDI, mas as vezes tenho que usar alguns form SDI (não MDI) então qdo é assim eu criei uma classe no qual fiz uma ´Método de Classe´ geralmente .Execute; no qual faz o create do form e como é showmodal logo apos isso ele mesmo ja se destroi.
Ficando apenas assim a chamada do mesmo.
TMeuFormSDI.Execute;


Mas se for ver apenas estamos aplicando diferentemente os mesmos recursos que eles mostraram na materia.

Aquilo que colocaram deve ser usado com cautela. eu so vi uma aplicação para aquilo, até o momento, que seria para criar uma classe de usuario no sistema que ao logar eu guardaria todos os privilegios.
Mas nada impediria de eu criar isso no braço tbm usando um metodo Execute.


Responder

09/09/2009

Osocram

|Mas se for ver apenas estamos aplicando diferentemente os mesmos
|recursos que eles mostraram na materia.

Não vejo bem por ai...


|Aquilo que colocaram deve ser usado com cautela.

Na minha modesta opnião, não deve ser usado de jeito nenhum. Além do problema conceitual, os códigos exemplo estão cheios de falhas como memory leaks, etc.


|eu so vi uma aplicação para aquilo, até o momento, que seria para criar
|uma classe de usuario no sistema que ao logar eu guardaria todos os
|privilegios.

Para isso servem os Singletons como no exemplo q mostrei.

A implementação de o singleton que dei de exemplo pode até não parecer muito diferente do código da matéria, mas tem detalhes q dão uma diferença muito grande se observados com cuidado -- tanto a nível conceitual quanto de implementação.


|Mas nada impediria de eu criar isso no braço tbm usando um metodo
|Execute.

Gosto desta abordagem e tb utilizo. Mas existem classes q são manipuladas, trocam informações, etc, onde esta abordagem não se aplica.

Neste caso que vc citou, vc cria um método de classe q encapsula uma ação completa -- criação da instancia, execução de uma tarefa e destruição!

Isto vai além da questão de inicialização de objetos (como uso de padrões singleton, factories, etc) -- e o método é específico para uma tarefa.


T+


Responder

10/09/2009

Afarias

Concordo plenamente com o colega Afarias, raramente existe uma razão para instanciar um objeto no Inicialization, pois manter mts objetos enquanto a aplicação está sendo executada pode ser mt caro quando não se tem a real necessidade disso.


E para que os colegas do fórum entendam melhor o q ele falow sobre o Singleton, ele é um padrão de projeto utilizado quando queremos apenas uma única instância de algum objeto.


Este é apenas um dos muitos padrões utilizados hj no mercado, existem mts outros, quem não conhece seria uma boa pesquisar e ler um pouco sobre Padrões de Projetos.



fica aew a dica...


flw


Responder

10/09/2009

Wdrocha

Na minha modesta opnião, não deve ser usado de jeito nenhum. Além do problema conceitual, os códigos exemplo estão cheios de falhas como memory leaks, etc.


Afarias ,aonde vc ´viu´ memory Leaks nos códigos ???


Responder

10/09/2009

Marco Salles

Na minha modesta opnião, não deve ser usado de jeito nenhum. Além do problema conceitual, os códigos exemplo estão cheios de falhas como memory leaks, etc.


Afarias ,aonde vc ´viu´ memory Leaks nos códigos ???


Responder

10/09/2009

Marco Salles

Realmente é muito melhor usar Singleton.

Inclusive utilizo uma classe de conexão Singleton muito boa que um amigo criou, assim posso usar minha conexão apenas quando necessito dela.

Isso aumentou a performance de um de meus sistemas em 45¬, algo incrível.

Achei muito massa a iniciativa de discutir um tópico da revista aqui.


Responder

10/09/2009

Knight_of_wine

manter mts objetos enquanto a aplicação está sendo executada pode ser mt caro quando não se tem a real necessidade disso. ... Este é apenas um dos muitos padrões utilizados hj no mercado, existem mts outros, quem não conhece seria uma boa pesquisar e ler um pouco sobre Padrões de Projetos.


Rocha disse tudo.


[quote:bfe68019b8=´Marco Salles´]
Afarias ,aonde vc ´viu´ memory Leaks nos códigos ???
[/quote:bfe68019b8]


1) Nas listagem 3 é criado um construtor para a classe que cria um objeto TStringList que NUNCA é liberado da memória pq não é criado um Destructor que teria esse papel. No texto inclusive é afirmado que o destructor não é necessário!! MAS É!

A não ser que vc utilize interfaces (ref-counted) ou um memory manager habilitado com um garbage collector os objetos criados não são destruídos automaticamente.

2) Nas listagem 5, exemplo com DM, ainda pior... na seção finalization o DataModule NÃO é destruído, apenas ´apontado´ para NIL!

finalization
DMTeste := nil;

Neste caso o ponteiro aponta para nil e a memória que era usada pelo objeto continua sendo utilizada... No texto é alegado que todos os DataModules de um projeto são destruidos ao com o témino da aplicação. Mas está incorreto...

São destruidos automaticamente apenas DataModules (assim como os Forms) criados tendo o objeto Application (ou outro qualquer que seja destruído em algum momento) como OWNER. Sendo que no código o Datamodule em questão NÃO tem um Owner.

DMTeste := TDMTeste.Create(nil);


Achei muito massa a iniciativa de discutir um tópico da revista aqui.


Rsss.. Não achei outro espaço para isso... Achei q era aqui mesmo :wink:


T+


Responder

10/09/2009

Afarias

[quote:0c834bbb29]Marco Salles escreveu: Afarias ,aonde vc ´viu´ memory Leaks nos códigos ???


1) Nas listagem 3 é criado um construtor para a classe que cria um objeto TStringList que NUNCA é liberado da memória pq não é criado um Destructor que teria esse papel. No texto inclusive é afirmado que o destructor não é necessário!! MAS É!

A não ser que vc utilize interfaces (ref-counted) ou um memory manager habilitado com um garbage collector os objetos criados não são destruídos automaticamente.

2) Nas listagem 5, exemplo com DM, ainda pior... na seção finalization o DataModule NÃO é destruído, apenas ´apontado´ para NIL!

finalization
DMTeste := nil;

Neste caso o ponteiro aponta para nil e a memória que era usada pelo objeto continua sendo utilizada... No texto é alegado que todos os DataModules de um projeto são destruidos ao com o témino da aplicação. Mas está incorreto... [/quote:0c834bbb29]

Afarias , ja tinha percebido uma das falhas e tinha ate reportado o erro em um
email em particular para o autores e um deles gentilmente me respondeu
Como Resposta Obtive que a partir do DataModule foi INVENÇÃO do Pessoal
da Revista ..( Que estã precisando Aprender Delphi )

Agora gostaria de ser solidário aos Autores e isto não encaro como falta .
Errar todos nos erramos . Cometemos Erros e deslizes . Nos aprendemos muito
mais com os erros do que com os Acertos .

O que não podemos aqui em hipotese nenhuma é tomar este Artigo como
o Vilão da História . Vários são os Artigos que podemos considerar como
ruims e ate hj não tomou proporções como a que este esta tomando.
Gostaria de respeitar os autores , e se escrerem outro certamente eu os
lerei , mesmo que seja para critica-los ou não.

A Culpa no meu entender é a falta de um Intercambio mais eficiente entre a Revista e O Forum .


Responder

10/09/2009

Marco Salles

Como Resposta Obtive que a partir do DataModule foi INVENÇÃO do Pessoal da Revista ..( Que estã precisando Aprender Delphi ) ...


Veja, esta é uma revista TÉCNICA ao meu ver, e revistas técnicas (e PAGAS) devem apresentar matérias técnicas CORRETAMENTE ou não tem sentido.

Claro q falhas existem, mas tanto autores quanto principalmente os editores técnicos da revista deveriam estar mais atentos ou fica a impressão *no mínimo* de falta de atenção com o leitor.


Mas, voltando...

Meu objetivo com este tópico nem foi criticar -- isto eu fiz em e-mail enviado a REVISTA (não aos autores) q nunca foi respondido. Nem citei autores ou editores...

Meu meu tópico original apenas apresenta uma técnica em alternativa ao que fora colocado na matéria em questão -- na esperança que iniciantes desavisados fiquem atentos.


T+


Responder

10/09/2009

Afarias

Não quero defender nem criticar ninguém, um dos autores é um colaborador meu e posso dizer que foi meu aprendiz, eu apresentei o Delphi para ele.
O artigo ´Objetos Auto-instanciáveis´ veio a existir a partir de uma discussão que tivemos sobre classes que criei para facilitar o trabalho da equipe de desenvolvimento, entre estas classes por exemplo tenho uma que chamo de TDBUpdate, os métodos da classe podem ser chamados a qualquer momento de qualquer lugar do sistema sem se preocupar se ela foi instanciada ou não.

Ao meu ver foi uma infelicidade o exemplo aplicado no artigo e não o artigo como um todo.
Vejo tudo como afarias já colocou, a classe deve ser instanciada quando existir realmente e necessidade e não no Initialization, no meu ponto de vista usando o Initialization não houve “auto-instancia”.

Veja abaixo parte de um código com “auto-instancia”
{ TDBUpdate }

procedure TDBUpdate.CheckCreate;
begin
  if not Assigned(DBUpdate) then
    DBUpdate := TDBUpdate.Create(nil);
end;

procedure TDBUpdate.TableCreate(Table: ShortString; Fields: array of ShortString);
begin
  CheckCreate;
  ...
end;


A conversa pode ir muito mais além, um colega meu certificado em java uma vez me disse que eu era louco que um código deste jamais poderia existir.


Responder

10/09/2009

Weber

um colega meu certificado em java uma vez me disse que eu era louco que um código deste jamais poderia existir.


rssss... estou com esse seu colega :wink:



T+


Responder

10/09/2009

Afarias

Ao meu ver temos sim que discutir e criticar o artigo, até por que quando eu erro o que mais gosto de ouvir é críticas construtivas e alternativas mais atraentes como essas que encontrei aqui.

Ninguém é dono da verdade, mas podemos sim contribuir para que o pessoal aprimore os artigos e melhorem cada vez mais o conteúdo que pagamos pra ter.


Responder

10/09/2009

Knight_of_wine

Ao meu ver temos sim que discutir e criticar o artigo, até por que quando eu erro o que mais gosto de ouvir é críticas construtivas e alternativas mais atraentes como essas que encontrei aqui. Ninguém é dono da verdade, mas podemos sim contribuir para que o pessoal aprimore os artigos e melhorem cada vez mais o conteúdo que pagamos pra ter.



Na minha opinião, não poderia ter dito melhor.


T+


Responder

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários,
consulte nossa política de privacidade.

Aceitar