Baixe o app para aproveitar ainda mais
Prévia do material em texto
.CSEG Automation POO – Parte 01 Delphi – Programação Orientado a Objeto em 3 Camada s – Parte 01 Objetivo do Artigo é mostrar de maneira simples e detalhada, como desenvolver um programa em Delphi Orientado a Objeto utilizando a modelagem em camadas. O Sistema consiste em uma tela de Consulta e Cadastro de Vendedor. Ambiente utilizado: Borland Delphi 7 Banco de Dados Firebird. Informações do caminho do Banco de Dados e dos Font es: Fonte: C:\POO_3-Camada\Fonte Banco de Dados: C:\POO_3-Camada\Banco Abaixo está a estrutura da tabela Vendedor: Nome Campo Tipo IDVENDEDOR INTEGER MATRICULA VARCHAR(4) NOME VARCHAR(40) SALARIOBRUTO Double precision PERCENTUALCOMISSAO Double precision Para quem quiser ter mais detalhes sobre o Banco de Dados, logo abaixo se encontra o Metadata da base: --------------------------------------------------- INÍCIO --------------------------------------------------------- SET SQL DIALECT 3; CREATE DATABASE 'C:\POO_3-Camada\Banco\BD_POO3C.FDB' PAGE_SIZE 4096 DEFAULT CHARACTER SET WIN1252; /* Table: VENDEDOR, Owner: SYSDBA */ CREATE TABLE "VENDEDOR" ( "IDVENDEDOR" INTEGER NOT NULL, "MATRICULA" VARCHAR(4) CHARACTER SET WIN1252 COLLATE PXW_INTL850, "NOME" VARCHAR(40) CHARACTER SET WIN1252 COLLATE PXW_INTL850, "SALARIOBRUTO" DOUBLE PRECISION, "PERCENTUALCOMISSAO" DOUBLE PRECISION, CONSTRAINT "PK_VENDEDOR" PRIMARY KEY ("IDVENDEDOR") ); Cesar Rodrigo www.cseg.eng.br 11/2006 .CSEG Automation POO – Parte 01 CREATE GENERATOR "GEN_VENDEDOR"; SET TERM ^ ; /* Triggers only will work for SQL triggers */ CREATE TRIGGER "TRIG_VENDEDOR_1" FOR "VENDEDOR" ACTIVE BEFORE INSERT POSITION 0 AS BEGIN NEW.IDVENDEDOR = GEN_ID(GEN_VENDEDOR, 1); END ^ COMMIT WORK ^ SET TERM ;^ -------------------------------------------------------- FIM --------------------------------------------------------- Implementando O.O. em Camadas A Modelagem em camadas consiste em: Interface, Regra de Negócio e Persistência. 1ª Camada (Interface) Identifica como apresentação Responsáveis pela interação dos usuários 2ª Camada (Negócios) Controla as regras de negócios Armazenam nossos requisitos Que determinam como: “Calcular”, “Processar”, “O que Persistir” e “o que Recuperar” 3ª Camada (Persistência) Controla a persistência dos nossos dados Obs.: Os dados vivem temporariamente nas instâncias das classes Armazenamento em um meio físico permanente Dicas: As telas devem ser criadas com base: ● Diagramas de Casos de Uso Implementações das Rotinas: ● Diagramas de Seqüência Cesar Rodrigo www.cseg.eng.br 11/2006 .CSEG Automation POO – Parte 01 Iniciando o desenvolvimento O nosso primeiro passo é iniciar uma nova aplicação no Delphi. (File -> News -> Application). E logo em seguida devemos salvar esse projeto, a Unit receberá o nome de uPrincipal.pas e o Projeto de POO_3C.dpr . No formulário Principal configurei a propriedade FormStyle = fsMDIForm. Com a Aplicação Salva vamos agora adicionar um novo formulário nesse projeto, que será a tela de Vendedor, ou seja, a 1ª Camada (Inferface) . Salvar essa Unit de uVendedor.pas, e alterar a propriedade FormStyle = fsMDIChild. Depois basta inserir Edit's, Label's e Button's na tela. Como mostra a figura: Obs.: Até agora só “desenhamos” a tela, não colocamos nenhum código. Certo? O nosso segundo passo é criar a 3ª Camada (Persistência) onde ficará a conexão com a Base de Dados (Firebird) e a Query que irá executar nossos comandos SQL's. Para isso precisamos criar um DataModule, basta criar no menu File -> New -> Data Module. Veja a imagem: Vamos dar o nome do DataModule de DM e salvar essa Unit com o nome de uDM.pas Para conectar em nosso Banco de Dados Firebird (BD_POO3C.FDB) iremos utilizar os componentes da Palheta Interbase do Delphi. Cesar Rodrigo www.cseg.eng.br 11/2006 .CSEG Automation POO – Parte 01 O primeiro componente que iremos colocar no DM é o IBDatabase: Selecionando Componente Data Module (DM), com compon ente Componente: IBDatabase Obs: Vamos alterar a propriedade NAME do IBDatabase1 para IBConexao Após alterar o nome vamos dar duplo clique no Componente IBDatabase e configurar a conexão como mostra a imagem: Feito isso basta clicar no Botão “Test” para verificar se esta tudo certo e depois clicar no “OK”. Cesar Rodrigo www.cseg.eng.br 11/2006 .CSEG Automation POO – Parte 01 Agora vamos Adicionar um IBTransaction no DataModule, esse componente é responsável por administrar as transações do Banco de Dados. Selecionando Componente Data Module (DM), com compon ente Componente: IBTransaction Obs.: Lembre-se de alterar o propriedade NAME do IBTransaction para IBTrans Em seguida de duplo clique no IBTrans e configure como mostra a figura abaixo: Não podemos esquecer de Configurar o IBTransaction (IBTrans) e alterar a Propriedade DefaultDatabase e selecionar "IBConexao". Veja figura: Cesar Rodrigo www.cseg.eng.br 11/2006 .CSEG Automation POO – Parte 01 Voltando para o componente IBConexao e alterar a propriedade DefaultTransaction e selecionar "IBTrans". Veja a figura: Agora só está faltando adicionar uma Query no DataModule que será a responsável para executar nossos comandos SQL's. Selecionando Componente Data Module (DM), com compon ente Componente: IBQuery, palheta Interbase Obs.: Lembre-se de alterar o propriedade NAME da IBQuery para qry_Temp Cesar Rodrigo www.cseg.eng.br 11/2006 .CSEG Automation POO – Parte 01 Temos que configurar a propriedades Database da qry_Temp e selecionar IBConexao . Veja figura: Com isso encerramos a configuração da 3ª Camada , se lembre-se que não colocamos nenhum código no DataModule até este momento. Agora vamos iniciar a criação da 2ª Camada, a Classe Vendedor onde vai armazenar toda a Regra de Negócio. Vamos adicionar uma nova Unit, Menu Flie -> New -> Unit Cesar Rodrigo www.cseg.eng.br 11/2006 .CSEG Automation POO – Parte 01 Obs.: Vamos salvar essa Unit com o nome de Vendedor.pas Não esqueça de salvar essa unit no diretório: C:\POO_3-Camada\Fonte A estrutura básica da Unit Vendedor é essa: Agora vamos começar a criar a Classe Tvendedor. Nosso primeiro passo agora é escrever o código que está entre Interface e Implementation . Veja a imagem do código: Cesar Rodrigo www.cseg.eng.br 11/2006 .CSEG Automation POO – Parte 01 O mesmo código se encontra aqui: --------------------------------------------------- INÍCIO --------------------------------------------------------- interface uses Classes ; type TVendedor = class protected // Escopo de Visibilidade FId : integer ; FMatricula : String ; FNome : String ; FSalarioBruto : Real; FSalarioLiquido : Real; FPercentualComissao: Real; // Utilizamos "F" na frente do "campo" para ide ntificar que é um "Field". // Procedure para tratar a Escrita na Property SalarioBruto procedure SetSalarioBruto(Valor : Real); // Procedure para tratar a Escrita na Property PercentualComissao procedure SetPercentualComissao(Valor : Real); public // Escopo de Visibilidade constructor Create; procedure Clear; function Grava:Boolean; function Busca(sMatricula : String) : Boolean; // Propriedades que acessam os Field's, assim n ão quebramos o //"encapsulamento". property Id: Integer read FId; // Nesta propriedade só podemos ler, e não escrever . property Matricula : String read FMatricula write FMatricula; property Nome : String read FNome write FNome; property SalarioBruto : Real read FSalarioBruto write SetSalarioBruto; property PercentualComissao : Real read FPercentualComissao write SetPercentualComissao; end; implementation -------------------------------------------------------- FIM --------------------------------------------------------- Cesar Rodrigo www.cseg.eng.br 11/2006 .CSEG Automation POO – Parte 01 Agora vamos definir o que cada procedure e function irá fazer na Classe , essa implementação deve ser escrita entre “implementation” e “end.” Veja o código entre implementation e end. : --------------------------------------------------- INÍCIO --------------------------------------------------------- implementation uses uDM, DB; { TVendedor } function TVendedor.Busca(sMatricula: String): boolean; var iId : Integer; begin if Dm.BuscaVendedor(sMatricula,Self,iID) then begin FId := iId; Result := true; end else Result := false; end; Cesar Rodrigo www.cseg.eng.br 11/2006 .CSEG Automation POO – Parte 01 procedure TVendedor.Clear; begin FId := 0; // Zero identifica que esta cadastrando um novo reg istro FMatricula := ''; FNome := ''; FSalarioBruto := 0; FPercentualComissao := 0; FSalarioLiquido := 0; end; constructor TVendedor.Create; begin Clear; // Chamo a mesma coisa que tem na Procedure Clear; end; function TVendedor.Grava: Boolean; begin //Agora vamos chamar o GravarVendedor passando o Self, que é a Classe //a intancia TVendedor, onde tem todas as informa ções do Objeto. Result := DM.GravaVendedor(Self); end; procedure TVendedor.SetPercentualComissao(Valor: Real); begin if Valor > 0 then if Valor > 1 then FPercentualComissao := Valor / 100 else FPercentualComissao := Valor else FPercentualComissao := 0; end; procedure TVendedor.SetSalarioBruto(Valor: Real); begin if Valor >= 0 then FSalarioBruto := Valor else FSalarioBruto := 0; end; end. -------------------------------------------------------- FIM --------------------------------------------------------- Obs.: Existem duas function muito importante nesse código. A primeira é a Busca e a segunda Grava . Cesar Rodrigo www.cseg.eng.br 11/2006 .CSEG Automation POO – Parte 01 Detalhando a function: Busca A function Busca da 2ª Camada (Regra de Negocio) invoca uma outra function BuscaVendedor que se encontra na 3ª Camanda (Persistência). Isso é uma troca de Mensagem entre as Camadas. Obs.: O mesmo acontece com a function Grava . Se você tentar compilar/executar seu programa agora ele vai dar mensagem de erro. Isso acontece porque não definimos as function's do DataModule (DM). Esse será nosso próximo passo. Implementando as function's no DataModule (DM) Agora vamos colocar o protótipo das duas function: BuscaVendedor , GravaVendedor . Veja a figura: Cesar Rodrigo www.cseg.eng.br 11/2006 .CSEG Automation POO – Parte 01 Observe que as duas funções foram escritas no Public. public { Public declarations } // Declarando a function com Global, para todo o projeto executar function BuscaVendedor(sMatricula:String ; oVendedor:TVendedor; var Id : Integer): Boolean; function GravaVendedor(oVendedor:TVendedor) : Boolean; end; Feito o protótipo agora vamos para a definição das funções. Se você deixar o cursor em cima das function's e apertar as teclas: Ctrl + Shift + C o Delphi irá fazer isso para você, veja na figura: Agora basta colocar o código de cada uma. ;-) Cesar Rodrigo www.cseg.eng.br 11/2006 .CSEG Automation POO – Parte 01 O Código da function BuscaVendedor é esse: O mesmo código esta aqui também: --------------------------------------------------- INÍCIO --------------------------------------------------------- function TDM.BuscaVendedor(sMatricula: String ; oVendedor: TVendedor; var Id: Integer): Boolean; var sSql : String; begin try result := false; // De inicio falo que não encontrei o registro if Not IBConexao.Connected then // Checando a conexão IBConexao.Connected := true; qry_Temp.Close; qry_Temp.SQL.Clear; //Montando o código SQL para realizar a busca d o Vendedor pela Matricula sSql := ' select IdVendedor, Matricula, Nome, SalarioBruto, PercentualComissao '+ ' From Vendedor '+ ' where Matricula = :prmMat '; qry_Temp.SQL.Add(sSql); qry_Temp.ParamByName('prmMat').Value := sMatricula; qry_Temp.Open; Cesar Rodrigo www.cseg.eng.br 11/2006 .CSEG Automation POO – Parte 01 // Se eu encontrei alguma coisa, atribuo no Obj eto (Vendedor) if not qry_Temp.IsEmpty then begin oVendedor.Matricula := qry_Temp.fieldByName('MAtricula').AsString; oVendedor.Nome := qry_Temp.FieldByName('Nome').AsString; oVendedor.SalarioBruto := qry_Temp.FieldByName('SalarioBruto').AsFloat; oVendedor.PercentualComissao := qry_Temp.FieldByName('PercentualComissao').AsFloat; Id := qry_Temp.FieldByName('IdVendedor').AsInteger; result := true; end; except result := false; Raise Exception.Create('Erro ao Buscar Vendedor'); end; end; -------------------------------------------------------- FIM --------------------------------------------------------- Neste código podemos observar que a função verifica se está conectado com o banco e conecta caso não esteja. E monta um SQL que irá buscar o vendedor através da Matricula, e usa a query qry_Temp para processar esse SQL. Caso ele encontre ele atribui as informações da Query, no objeto oVendedor e retorna TRUE, dizendo que encontrou o registro. O Código da function GravaVendedor é esse: Cesar Rodrigo www.cseg.eng.br 11/2006 .CSEG Automation POO – Parte 01 O mesmo código esta aqui também: --------------------------------------------------- INÍCIO --------------------------------------------------------- function TDM.GravaVendedor(oVendedor: TVendedor): Boolean; var sSql : String ; begin try if Not IBConexao.Connected then IBConexao.Connected := true; qry_Temp.Close; qry_Temp.SQL.Clear; if oVendedor.Id <> 0 thenbegin sSql := ' update Vendedor Set Matricula = :prmMat, '+ ' Nome = :prmNome, '+ ' SalarioBruto = :prmSal, '+ ' PercentualComissao = :prmPerc '+ ' where IDVendedor = :prmId '; qry_Temp.Sql.Add(sSql); qry_Temp.ParamByName('prmId').Value := oVendedor.Id; qry_Temp.ParamByName('prmMat').Value := oVendedor.Matricula; qry_Temp.ParamByName('prmNome').Value := oVendedor.Nome; qry_Temp.ParamByName('prmSal').Value := oVendedor.SalarioBruto; qry_Temp.ParamByName('prmPerc').Value := oVendedor.PercentualComissao; end else begin sSql := ' insert into Vendedor (Matricula, Nome, SalarioBruto, PercentualComissao )'+ ' Values '+ ' (:prmMat, :prmNome, :prmSal, :prmPerc )'; qry_Temp.Sql.Add(sSql); qry_Temp.ParamByName('prmMat').Value := oVendedor.Matricula; qry_Temp.ParamByName('prmNome').Value := oVendedor.Nome; qry_Temp.ParamByName('prmSal').Value := oVendedor.SalarioBruto; qry_Temp.ParamByName('prmPerc').Value := oVendedor.PercentualComissao; end; qry_Temp.ExecSQL; Result := True; except Result := false; raise Exception.Create('Erro ao Gravar Vendedor'); end; end; -------------------------------------------------------- FIM --------------------------------------------------------- O código de GravaVendedor tem duas funções, se o campo ID for igual a zero significa que é para INCLUIR o registro caso contrario ele ALTERA o registro. Sendo que o valor é lido do Objeto oVendedor. Cesar Rodrigo www.cseg.eng.br 11/2006 .CSEG Automation POO – Parte 01 Voltando para 1ª Camanda Após implementar a 3ª e a 2ª camada, podemos voltar para a 1ª e terminar a implementação desse nosso projeto. Voltando para Unit uVendendor . Agora precisamos criar uma Variável do tipo Tvendedor. Veja a figura abaixo: Obs.: Podemos observar que foi informando o oVendedor : TVendedor embaixo do Escopo de Visibilidade private . Não pode esquecer de colocar Vendedor no USES no topo. Cesar Rodrigo www.cseg.eng.br 11/2006 .CSEG Automation POO – Parte 01 Agora vamos selecionar o Formulário do Vendedor e colocar o seguinte código no evento onCreate . Veja o figura: Feito a Instanciação , vamos agora fazer a “Limpeza da Memória” , esse código será o responsável para limpar a memória utilizada pelo Objeto quando o Sistema for Fechado. Então esse código deve ser colocado no Evento OnClose do Formulário do Vendedor. Veja a figura: O FreeAndNill é responsável por verificar se: ● O objeto está alocado (Assigned) ● Limpar a área de memória ● Liberar o apontador (ponteiro) Já o Anction := CaFree é o comando que "Destroy" o formulário da memória, isso é necessário porque estamos utilizando "Formulários MDI" . No componente Edit da Matricula, devemos alterar o nome desse componente para: edt_Matricula Veja figura: O “Name” desse componente edit vai ser: edt_Matricula Após alterar o nome do componente devemos adicionar o código que irá fazer a pesquisa de um vendedor quando o usuário digitar uma matricula. Esse código será no Evento OnChange . Cesar Rodrigo www.cseg.eng.br 11/2006 .CSEG Automation POO – Parte 01 Veja figura: O Código também esta aqui, veja: procedure Tfrm_Vendedor.edt_MatriculaChange(Sender: TObject); begin //Verificando se o Usuário digitou 4 caractere if Length( Trim(edt_Matricula.Text) ) <> 4 then begin edt_Nome.Text := ''; edt_SalarioBruto.Text := ''; edt_PercentualComissao.Text := ''; oVendedor.Clear; // Limpando o conteúdo dos campos do objeto end else begin // Vou buscar essa matricula no banco de daos . // Se encontrou atribuo nos Edit's. if oVendedor.Busca( Trim(edt_Matricula.Text) ) then begin edt_Nome.Text := oVendedor.Nome; edt_SalarioBruto.Text := FloatToStr(oVendedor.SalarioBruto); edt_PercentualComissao.Text := FloatToStr(oVendedor.PercentualComissao); end; end; end; Obs.: Esse código é responsável por ir buscar o vendedor se o usuário digitar um número de matricula válido. Cesar Rodrigo www.cseg.eng.br 11/2006 .CSEG Automation POO – Parte 01 E por fim vamos colocar o código no Botão:”Cadastrar/Alterar” no Evento OnClick vamos informar o código da figura: Obs.: Esse código tem como objetivo verificar se todos os campos foram preenchido e atribuir o conteúdo dos edit's no objeto e depois gravar essas informações no banco de dados. O código também pode ser visualizado logo abaixo: Cesar Rodrigo www.cseg.eng.br 11/2006 .CSEG Automation POO – Parte 01 Código do Botão: ”Cadastrar/Alterar” - OnClick --------------------------------------------------- INÍCIO --------------------------------------------------------- procedure Tfrm_Vendedor.Button1Click(Sender: TObject); begin if ( Trim (edt_Matricula.Text) <> '') and ( Trim (edt_Nome.Text) <> '') and ( Trim (edt_SalarioBruto.Text) <> '') and ( Trim (edt_PercentualComissao.Text) <> '') then begin oVendedor.Matricula := edt_Matricula.Text; oVendedor.Nome := edt_Nome.Text; oVendedor.SalarioBruto := StrToFloat(edt_SalarioBruto.Text); oVendedor.PercentualComissao := StrToFloat(edt_PercentualComissao.Text); //Mando gravar if oVendedor.Grava then begin edt_Matricula.Text := ''; edt_Nome.Text := ''; edt_SalarioBruto.Text := ''; edt_PercentualComissao.Text := ''; oVendedor.Clear; end else edt_Nome.SetFocus; end else begin SHowMessage('Campos Inválidos'); end; end; -------------------------------------------------------- FIM --------------------------------------------------------- O único código que faltou é o Close que será colocado no OnClick do Botão Fechar. Veja figura: Cesar Rodrigo www.cseg.eng.br 11/2006 .CSEG Automation POO – Parte 01 Não podemos esquecer de acessar o Menu: Project -> Option Como mostra a figura: Para tirar o formulário frm_Vendedor do “Auto-create”, veja a figura de como deve ficar seu projeto: Cesar Rodrigo www.cseg.eng.br 11/2006 .CSEG Automation POO – Parte 01 Agora só falta colocar um componente MainMenu para criar um menu chamando o vendedor. Veja: Obs.: Esse componente foi colocado no Formulário Principal. E no evento OnClick desse menu vamos colocar esse código: para chamar o formulário de Vendedor. Obs.: Quando você compilar o projeto pode dar essa mensagem: Pode responder que “SIM”, isso significa que você vai usar uma referência de frm_Vendedor dentro do frm_Principal . Cesar Rodrigo www.cseg.eng.br 11/2006 .CSEG AutomationPOO – Parte 01 Para fazer o teste, cadastre uma matricula por exemplo “1234” com todos os dados. Clique em Salvar, depois digite novamente “1234” e você vai ver que o programa vai buscar as informações desse código cadastrado anteriormente. Para finalizar esse artigo vou passar alguns conceitos interessantes, veja logo abaixo: Conceitos básicos sobre o : Self É uma variável implícita, que está disponível dentro dos métodos de todos os objetos. Self é um apontador para a instância da classe que foi usada para chamar o método. Self é passada pelo compilador como um parâmetro oculto para todos os métodos. Apontador Um apontador é uma variável que contém uma posição de memória. No Delphi um apontador é chamado de Pointer (Ponteiro). Nota: Quando um apontador não aponta para nenhum lugar (seu valor é zero), seu valor é Nil , e é freqüentemente chamado de um apontador Nil ou Null . Com isso finalizo esse artigo sobre Programação Orientada a Objetos em 3 camadas utilizando a Linguagem Delphi . Aguarde o próximo Artigo. Obrigado! Artigo: Delphi – Programação Orientado a Objeto em 3 Camadas – Parte 01 Autor: Cesar Rodrigo Site: http://www.cseg.eng.br A u t o m a t i o n Cesar Rodrigo www.cseg.eng.br 11/2006
Compartilhar