Programação Orientada à Objeto em Delphi! Para muitos: hã? O quê? Como?

Esse post trata de um assunto que pra muitos programadores da ferramenta Delphi (e pessoas que não conhecem esta ferramenta) é algo desconhecido ou inexistente no ambiente Delphi, a famosa Orientação à Objeto (P.O.O.).

Mas o Delphi é Orientado à Objetos e tem suporte aos conceitos de Classe, Objeto, Herança, Encapsulamento, Polimorfismo e etc?

A resposta é: SIM!! Tem suporte a tudo isso que foi colocado acima e muito mais, pena que muitos não usam, ou não conhecem esse poder por trás dos componentes!!

 

A Programação Orientada à Objetos é um conceito. Sendo assim, qualquer linguagem “pode” utilizar do seu poder (Se existir suporte de alguma forma ao conceito claro).

Para que uma linguagem tenha suporte a Orientação à Objetos (POO) basicamente é necessário suportar no mínimo os itens abaixo:

Classe

Objeto

Herança

Polimorfismo

Além de claro, método, atributo, encapsulamento e etc.Linguagens como Java deixam bem claro a forma de se trabalhar: Orientado à Objeto. Mas, nem todas as linguagens deixam claro esse uso e pior nem todos programadores sabem que estão trabalhando O.O.. É assim que acontece com o ambiente de desenvolvimento Delphi. Para muitos o Delphi é uma linguagem procedural, o que não é verdade pois Delphi não é nem uma Linguagem e sim um ambiente.

A linguagem usada no Delphi é Object Pascal, então pelo nome já percebemos que o Delphi tem sim suporte a P.O.O. e trabalhar de forma procedural nele já pode-se dizer que é coisa do passado.

Com delphi é fácil perceber o que é O.O. basta você ver os Componentes da ferramenta. Cada Form, Edit, ComboBox é um objeto que tem diversas propriedades como name, title, items, text e etc.

O que faz com que programadores não percebam o fato de trabalhar OO em Delphi ou até mesmo nem sabem que estão fazendo isso é a forma como ela faz tudo pra você. Coloca componentes na tela, cria, edita propriedades, tudo isso com o mouse e o famoso Object Inspector (que nada mais é que as características de cada objeto selecionado). Essa forma do Delphi fazer as coisas é sensacional (quando já se sabe o que é feito por trás), trás produtividade, rapidez, facilidade e muitos outros benefícios.

Mas, o que é que o Delphi faz tanto por mim que eu não vejo? Pois bem vamos ao primeiro exemplo.

Quando você deseja colocar um botão em um formulário qualquer o que você faz?

Muito bem! Porém o fato de clicar e arrastar não faz nascer um botão com um nome, texto, evento, largura, altura e seja lá o que ele tiver mais! Para isso o Delphi cria um objeto botão. Mas a única coisa que você ver além do botão na tela é a declaração da variável no editor:

Button1: TButton;

 

Assim, para se criar e utilizar um objeto qualquer, seja um botão, caixa de texto e etc. não basta declarar a variável objeto, você vai precisar instanciar (criar) a mesma e setar valores. Então a mágica que o Delphi faz é instanciar o seu botão com as características que você definiu arrastando e soltando o objeto. A criação que o Delphi faz é a seguinte para criar o Objeto na tela:

 

Button1: TButton;

Button1:= TButton.Create(Form1); //Formulário Onde o Botão foi colocado
Button1.Parent:=Form1; //Pai do Botão
Button1.Top:= 20; //Tamanho Definido na Propriedade Top(Integer)
Button1.Left:= 30; //Tamanho Definido na Propriedade Left(Integer)
Button1.Height:=50; //Tamanho Definido na Propriedade Height(Integer)
Button1.Width:=100; //Tamanho Definido na Propriedade Width (Integer)
Button1.Caption:='Texto Definido na Propriedade Caption';

 

 Entendendo essa forma de trabalhar vemos que podemos definir todo um formulários no que chamamos de: Tempo de Execução, ou seja, os componentes (objetos) da tela só seriam criados quando o programa iniciasse sua execução.

Isso serve para entendermos a forma com que o Delphi trabalha Orientado à Objeto, mas claro que não precisamos usar essa forma para construção de formulários, até porque o clicar, arrastar e soltar é bem mais prático e indicado em uma ferramenta como o Delphi (ferramenta RAD).

As vantagens oferecidas quando trabalhamos OO em Delphi são criação de formulários automáticos, formulários herdados e várias outras. Então se você trabalha com Delphi há anos e sempre que é pedido um novo formulário CRUD você arrasta componente por componente. Tá na hora de mudar. Como?? vamos ver uma idéia de como agora.

Construir um Sistema OO nem sempre é uma tarefa fácil, mas é possível e altamente recomendado. Porém é necessário ter um modelo de análise OO antes para que você não precise codificar sem existir um projeto anteriormente. Trabalhar de forma Orientada à Objetos no Delphi siginifica que você vai deixar de ter variáveis String, Integer, Float e etc para encapsular essas variáveis em Objetos definidos em uma análise feita anteriormente.

Vamos ao exemplo:

Cadastro de Pessoas.

Se fossemos construir um simples cadastro de pessoas poderiamos fazer isso da seguinte forma:

Caixas de Texto;

Botões;

Eventos.

Vamos ao evento que deve inserir os dados da pessoa num BD qualquer.

 

procedure TForm1.SalvarPessoaClick(Sender: TObject);
begin

QueryPessoa.Append;
QueryPessoa.FieldByName('NOME').AsString := edtNome.Text;
QueryPessoa.FieldByName('IDADE').AsInteger := StrToInt(edtIdade.Text);
...
QueryPessoa.Post;

end;

 

Simples e fácil quando precisamos apenas inserir uma pessoa no BD utilizando um Driver especifico, nesse caso o ADO (definido pela variável QueryPessoa). Porém, se quisermos trocar de Driver de BD por exemplo, já viu a confusão né! Os Problemas nesse caso são muitos, pois dependendo do Driver (DBExpress, IB, ADO) a forma de inserção pode exigir métodos diferentes, alterações em formulários, regras de negócios que não tinham absolutamente nada a ver com o Driver que deveria ser trocado.

Trabalhar OO em Delphi exigiria um pouco mais de código (mas, nada que um Framework caseiro seu não resolva) pois na insersão de uma pessoa teríamos algo parecido com o código abaixo:

 

procedure TForm1.SalvarPessoaClick(Sender: TObject);
var objDriver: TDriver;
objPessoa: TPessoa;
begin

objPessoa := TPessoa.create();
objPessoa.Nome := 'João';
objPessoa.Idade := 23;

objDriver := TADO.create();
objDriver.salvarPessoa(objPessoa);

end;

 

O que fizemos e quais os benefícios da implementação acima?

Primeiro criamos uma classe TPessoa, onde a mesma tem as características de uma Pessoa.

 

unit PessoaU;

interface

type
TPessoa = class

private
Fnome:String;
Fidade: integer;
procedure SetNome(const Value: String);
procedure SetIdade(const Value: Integer);

public
property Nome:String read Fnome write SetNome;
property Idade:Integer read Fidade write SetIdade;
end;

implementation

{ TPessoa }

procedure TPessoa.SetIdade(const Value: Integer);
begin
Fidade := Value;
end;

procedure TPessoa.SetNome(const Value: String);
begin
Fnome := Value;
end;

end.

 

Dessa forma passaremos a tratar os dados de qualquer pessoa como um objeto TPessoa.

Depois criamos uma classe que servirá como Classe Base para implementações de Drivers. Essa classe chamada TDriver contém os métodos de inserção, atualização e etc dos objetos do Sistema.

 

unit DriverU;

interface

uses PessoaU;

type
TDriver = class

procedure salvarPessoa(p:TPessoa); virtual; abstract;
end;

implementation

end.

 

 

Nesse caso declaramos o cabeçalho do método salvarPessoa como abstract (método abstrato), ou seja, a implementação deve ser de quem herdar essa classe, isso significa que como a pessoa é inserida depende de que Driver o Sistema utiliza.

Após isso criamos as classes relacionada aos Drivers, uma chamada TDBExpress e outra TADO, onde elas são responsáveis por implementar a inserção de fato do método.

Coloquei um ShowMessage() apenas para indicar quee método está sendo chamado naquele momento, porém ali estaria a implementação do método usando os Componentes de cada Driver. (DBExpress  = SQLConnection, ADO = AdoConnection).

 

unit DBExpressU;

interface

uses DriverU, PessoaU, Dialogs;

type
TDBExpress = class(TDriver)

procedure salvarPessoa(p:TPessoa); override;

end;

implementation

{ TDBExpress }

procedure TDBExpress.salvarPessoa(p: TPessoa);
begin
//inherited;
ShowMessage('Evento'+ ClassName);
end;

end.

 

 

 

unit ADOU;

interface

uses DriverU, PessoaU ,Dialogs;

type
TADO = class(TDriver)

procedure salvarPessoa(p:TPessoa); override;

end;

implementation

{ TADO }

procedure TADO.salvarPessoa(p: TPessoa);
begin
//inherited;
ShowMessage('Evento'+ ClassName);
end;

end.

 

Dessa forma utiliizamos os conceitos necessários para afirmar: Delphi é Orientado à Objetos pois utilizamos Classes, Objetos, Herança e Polimorfismo.

Assim, quando você tiver a necessidade de trocar de Driver em sua aplicação bastaria trocar a instância da variável objDriver:TDriver (lá no método salvarPessoa() do formulário) para

objDriver := TDBExpress.create();

Podendo ainda transformar sua aplicação Cliente/Servidor em uma aplicação Multicamada utilizando DataSnap de forma bem menos traumática (Assunto pra depois)!

A idéia desse artigo foi mostrar como entender a OO em Delphi para pode ajudar você a criar aplicações mais flexivéis e robustas. Claro que aqui é apenas uma idéia, o ideal é que possamos aplicar OO em Delphi em várias camadas no desenvolvimento de Software.

Você pode baixar este exemplo aqui.

Aécio Costa

27 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

Copyright © 2011-2017 Aécio Costa All rights reserved.