Buscar

Criando um componente para gerenciar estoque.

nome

Ivo Nascimento

Colunista ainda sem descrição. Caro colunista, por favor envie-nos sua descrição.

   Olá amigos. Após um tempo afastado devido a compormissos estou retomando minha colaboração aqui no site.
  
Agradeço a todos que leram e comentaram minhas matérias porque é muito prazeroso encontrar eco nas nossas idéias.
  
Dessa vez vou falar de um assunto batido pra caramba mas que esta sempre sendo discutido. Programação com Orientação a objeto.
  
Calma, antes de deixar de ler esse texto ou porque voce já leu o suficiente sobre isso ou porque todo texto sobre isso é repetitivo leia minha proposta.
  
O delphi é inteiramente feito orientado a objeto e deve ter um motivo para que a maioria de seus 'pedaços' aparecerem para gente em forma de componentes na vcl. Mesmo porque os programadores de lá são muito bons .
  
Ok. Não sei para os outros mas pra mim é porque dessa forma fica mais claro que existe algo para resolver aquele seu problema e também porque assim fica mais facil de utilizar. Tem lá o objetc inspector dando uma força para trabalhar com o tal componente que executa com uma precisão muito interessante a tarefa a que se destina.
  
Quando eu penso em programar a coisa mais pornográfica(pra não dizer explícita) que aparece na minha mente é : " Dá pra transformar isso num componente da vcl?"
  
E digo com certeza... na maioria dos casos isso não só tem se mostrado possível como, na minha visão... recomendavel.
  
Mãos a obra então. Vamos construir um componente diferente do que eu vejo sempre por ai sendo construído para ilustrar melhor o que penso(resumidamente) sobre orientação a objetos.
  
A situação: Tenho um Cliente A, uma empresa do ramo metalúrgico, que precisa controlar seu estoque(outra vez o estoque) de forma a saber quais as peças disponíveis, quanto delas esta disponível, além claro de controlar a movimentação deste estoque.
  
Este tipo de problema normalmente é solucionado na base do file -> new -> project e programação na sequencia.
  
E acho isso incorreto, eis minha explicação:
  
Programar de forma monolítica é uma das formas de fazer com que você tenha mais trabalho na manutenção de software, como disse em um dos meus artigos anteriores.
  
Por que então, gerar um programa extenso com no mínimo de 1mb para controlar o estoque e ter que reescrever as coisas ali feitas toda vez que precisar da mesma solução em algum outro aplicativo ao invés de gerar uma interface para essas informações na forma de um componente que basta clicar, colocar no form e "setar" as informações para que ele esteja pronto para trabalhar.
  
Interface.... pô, mas esse papo de interface não tem form e tal? 
  
Por interface podemos indicar tudo aquilo que dá acesso a informação de uma forma prática e passivel de utilização sem grandes segredos(isso numa boa interface).
  
Interface então pode ser para o porgramador ou para o cliente.
  
Interface para o programador por exemplo seria um objeto herado de Ttable que já traz imbutido todas as rotinas básicas que precisamos como (next, prior, post, delete, insert).
  
Esse métodos, previamente programados, facilitaram o trabalho do programador na medida em que não necessitam ser reescritos toda vez que são utilizados, basta chamar:

Ttableinstancia.post;
e pronto, esta gravado(lembra dessa época?)
  
Esse seria um exemplo até que saudoso de uma interface pois hoje na programação cliente/servidor procura-se ao máximo trabalhar com objetos Tquery ou assemelhados por normalmente o acesso com melhor performance ser aquele disponibilizado.
  
O que proponho é um objeto exatamente como o Tquery ou Ttable, que forneca as funcoes e rotinas mais importantes ou porque não todas, que sejam necessárias para interagir com problema/solução sugerido.
  
Todo componente então, por este pensamento, deve ser imaginado como uma interface apra acesso a um tipo de programação ora desenvolvida pela nossa querida(mesmo!!!) borland ou por outro programador amigo que deixando o componente free ou cobrando por ele(alguém ai vive de luz?) esta facilitando o nosso trabalho.
  
Vamos ao componente.
  
Gerar um novo componente é fácil.
  
Vamos em file -> new -> other -> Component(na guia new) e pronto surge a tela de instruções básicas para criação do código básico do componente que alegremente o Delphi cria pra gente.
  
O primeiro problema vem neste ponto.
  
Ancestor type: De quem esse componente será descendente, ou melhor, quem será o pai desse cara... de quem ele herdará um monte de características hereditárias e que podem ser mudadas e melhoradas como na genética.
  
Eu decidi por herdar de Tcomponent por que assim podia utilizar-me de algumas funçõe sjá implementadas nesta classe que considero a base elementar do Delphi( para acessar as abaixo dessa e saber colocar nelas tudo que é necessário precisamos estudar mais... eu pelo menos).
  
Class Name: Solta a imaginação agora e chama a classe do teu componente de TCoisaLEgaldoEstoque????? Nãããããããoo...Uffa. Dê a ele um nome claro, de fácil associação e que os outros programadores possam ligar ao que ele faz de cara... então o nome é TEstoque.
  
Existe uma coisa a mais nos nomes de componentes que criamos que deve ser respeitada que é, no nome, colocarmos alguma forma de identificação pessoal que não impeça a gente de achar um outro componente de estoque na internet melhor que o nosso e poder instala-lo na nossa vcl pelo fato de terem o mesmo nome explicitamente direto TEstoque e acabarem sendo sobrescritos... então fica assim TIannEstoque.
  
Pallete name: Em qual das guias da vcl voce quer ver seu componente? Junto dos samples então deixa samples ai, junto dos componentes standart sem aquele troço, como é mesmo... dataware, então escreve standart, quer criar sua própria guia então digita ai "Eu". Mas eu acho que fica melhor como bussinesSolution.
  
Unit file name e search path tá na cara. Onde o Delphi vai gravar teu código e qual o caminho(path) será inserido no options enviroments para poder achar o dcu(credo... isso mais parece sopa de letrinhas).
  
Favor, senhoras e senhores, clique em ok e não em install, afinal, ainda não presta pra nada esse tal de TIannEstoque.
  
Código, finalmente, agora chegou a hora.
  
Uma interface deve implementar toda forma de acesso qeu se façca nessecário para basicamente acessar as informações a que se destina.
  
Vamos pensar neste problema:

1- Qual o nome da tabela que tem os produtos cadastrados?
2- Quais as operações que desejo que a interface tenha?

respotas:

1- a tabela pode ter qualquer nome e desejo informar isso a minhas sqls.
2 - Basicamente, e pra não alongar, iremos oferecer as seguinte funções

function InsereProduto(Nome:String;ERe:integer=0;EMi:integer=0;Ema:integer=0):boolean;
//essa função vai ter a tarefa de inserir um produto na tabela de estoque.

function operavalores(Indice, quantidade:integer; Op:shortstring): boolean;
//essa função vai ter a tarefa de editar a quantidade do campo estoqueR(estoqueReal).

procedure GetEstoque();
//essa função irá resgatar o resultset geral da tabela pois não usa where em seu sql. Dessa forma trazendo todo o estoque, mas baseando-se nela poderiamos escrever muitas outras coisas legais.

As seguinte seções de decalração aparecem pra gente:

private : tudo que é declarado aqui poderá ser visto somente nesta unit ou através da técnica de "hack de class"

protected : os que herdarem dessa classe(que a tiverem como pai) poderam acessar as declarações feitas aqui.

public : qualquer lugar onde este componente for declarado tera acesso as declarações feitas neste local.

published: as delcarações feitas aqui são visíveis em qualquer lugar como public e aqui se declaram as propriedades, que apareceram no object inspector
   
  
Resumindo bem, é isso ai que aquelas um milhão de linhas sobre o assunto querem dizer(claro que tem mais sobre o assunto, mas não faz parte do escopo... bem, você já sabe).

Na seção published declare:

property tblestoquename :string read Ftblestoquename write Settblestoquename;
//aqui sera digitado o nome da tabela paradox para a montagem dos sql.

property GEstoque: Tquery read FGEstoque write SetGEstoque;
//Essa declaração acima nos permitirá acessar os resultsets do nosso componente sem termos que alongar esse artigo, mas poderíamos fazer de forma diferente que não necessitasse de uma referência a um tquery externo,bastando lembrar que existe o TclientDataSet que grava em xml(se quisermos), levanta e mantém dados na memória do PC.

ob.: utilize da seguinte forma:
property GEstoque: Tquery;(digite Crtl+Shift +C e o Delphi vai autocompletar a criação da propriedade)
   Criaremos a tabela produto apenas. Notem que não estamos discutindo aqui a modelagem de tabelas para sistema de controle de estoque e sim apenas criando uma tabela da forma mais deireta possivel para ilustrar o uso de nosso componente.

   A tabela estoque tera os campos

   idestoque autoincremet primary key;
  
nomestoque alfa;
  
estoqueR number;(para guardar o valor real de estoque)
  
estoqueMin number;(para guardar o valor mínimo de estoque)
  
estoqueMax number;(para guardar o valor maximo de estoque)

Com a tabela criada e gravada em qualquer lugar vamos continuar o componente.
  
Estarei criando um componente com somente funcoes simples e que operará somente sobre a tabela que tiver a mesma estrutura de campos que foi dita acima, faço isso neste artigo para facilitar a compreensão e num próximo podemos até escrever um generico(que demanda mais trabalho). Aqui desejo somente demonstrar tecnicas de criação de componente.
  
Quando você criou o componente e digitou todas as infomormações necessárias para tanto o delphi criou a seguinte procedure, que tem a função de registrar na vcl o seu componente e apontar em que tab ele irá aparecer:

procedure Register;
begin
RegisterComponents('bussinesSolution', [TIannEstoque]);
end;

As tres rotinas que escreveremos estarão com acesso public, portanto, deve ser declaradas logo abaixo dessa palavra.

procedure GetEstoque();
function InsereProduto(Nome:String;ERe:integer=0;EMi:integer=0;Ema:integer=0):boolean;
function operavalores(Indice, quantidade:integer; Op:shortstring): boolean;

O código delas fica assim:

procedure TIannEstoque.GetEstoque;
begin
//Gestoque esta referenciando o query que esta no seu formulário que esta lá sem código nenhum, você não precisa definir nada nele por que as suas propriedades estão definidas em nosso componente.
GEstoque.close;
GEstoque.SQL.Clear;
GEstoque.SQL.Add('select * from '+tblestoquename);
GEstoque.Open;
end;

function TIannEstoque.InsereProduto(Nome:String;ERe:integer=0;EMi:integer=0;Ema:integer=0):boolean;
var
Qinsert:Tquery;
begin
//criamos uma query aqui para podemos executar um sql sem necessidade de um query no formulário apra isso. dizemos que o proprietário é nil por não haver necessidade de um proprietário para ele pois nenhuma de suas propriedades são referenciadas de outro lugar.
Qinsert := Tquery.Create(nil);
Qinsert.DatabaseName := GEstoque.DatabaseName;
Qinsert.SQL.Add('insert into '+ tblestoquename + '(Nomestoque, estoqueR,EstoqueMin, estoqueMax) values (');
//usei uma querystring concatenada mas poderia ser utilizado parambyname como Qinsert.parabyname(nome).asstring := Nome;
Qinsert.SQL.Add(#39+nome+#39+',' +inttostr(Ere)+','+inttostr(Emi)+','+inttostr(Ema)+');');
try
Qinsert.ExecSQL;
GetEstoque;
Qinsert.Free;
InsereProduto := true;
except
Qinsert.Free;
InsereProduto := false;
end;
// como retorno indico se a tarefa foi realizada com sucesso ou não setando InsereProduto como true ou false, isso facilitaria em caso de confirmar ao usuário que a operação ocorreu com sucesso.
end;

function TIannEstoque.operavalores(Indice, quantidade:integer; Op:shortstring): boolean;
var
Qopera:Tquery;
straux:string;
begin
if op = 'venda' then straux := 'update '+ tblestoquename + ' set estoqueR= estoqueR-'+inttostr(quantidade) + ' where idestoque='+ inttostr(indice)
else if op = 'compra' then straux := 'update '+ tblestoquename + ' set estoqueR= estoqueR+'+inttostr(quantidade) + ' where idestoque='+ inttostr(indice);
Qopera := Tquery.Create(nil);
Qopera.DatabaseName := GEstoque.DatabaseName;
Qopera.SQL.Add(straux);
try
Qopera.ExecSQL;
//uso da função GetEstoque para atualizar a grid que esta na aplicação, mostrando o resultado modificado.
GetEstoque;
//libero a memória utilizada pela instancia de Tquery Qopera.
Qopera.Free;
operavalores := true;
except
Qopera.Free;
operavalores := false;
end;
end;

Utilizando o componente que acabamos de criar.

File > New > Application.

Adicione no formulário uma instância de TIannEstoque
Adicione também o Tquery, TdataaSource, TDBGrid e dois Button
Adicione também quatro Tedits.
RGVC: TRadioGroup;//adicione os itens venda e compra.
O código da unit do formulário deverá parecer com:
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, IannEstoque, DB, DBTables, StdCtrls, Grids, DBGrids, ExtCtrls;

type

TForm1 = class(TForm)
IEstoque: TIannEstoque;
Query1: TQuery;
DBGESTOQUE: TDBGrid;
DataSource1: TDataSource;
Button1: TButton;
Enome: TEdit;
Ereal: TEdit;
Emin: TEdit;
Emax: TEdit;
Button2: TButton;
RGVC: TRadioGroup;

procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure DBGESTOQUEDblClick(Sender: TObject);
private

{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;

implementation
{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
IEstoque.GetEstoque;
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
//chama afunção responsável por inserir dados e passa os parametros que foram digitdos pelo usuário.
IEstoque.InsereProduto(Enome.text,strtoint(Ereal.text),strtoint(Emin.text),strtoint(Emax.text));
end;
procedure TForm1.DBGESTOQUEDblClick(Sender: TObject);
VAR
valor : string;
numero:integer;
begin
//pega valor que será utilizado na operação ou de venda ou compra.
valor:= InputBox('Digite a Quantidade',RGVC.Items[RGVC.ItemIndex] , '0');
//testa se é um inteiro válido e se for realiza a operção que foi marcada no radiogroup.
if trystrtoint(valor,numero) then
IEstoque.operavalores(DBGESTOQUE.fields[0].AsInteger,numero,RGVC.Items[RGVC.ItemIndex]);
end;
end.
   Este componente foi criado para mostrar que muito além de se criar componentes descendentes de objetos visíveis em formulário para depois especializa-los, a criação de componente também pode ser muito útil para resolver problrmas de programação e centralização de código.
   Solucionar problemas de sua empresa utilizando para isso componentes criados especificamente para suas necessidades é uma prática louvável e facilita a manutenção do código.
   Para facilitar a distribuição de atualizações o ideal seria uma dll que espero falar em breve.
   Para se ter eficiência neste tipo de codificação a melhor coisa que se pode fazer é observar o código da própria borland, dentro dos componentes nativos do Delphi. Lê-los é uma boa dica para quem quer avançar cada vez mais.
   Enfim, espero que tenham gostado e que eu possa ter colaborado para, de alguma forma, esclarecer alguma dúvida.

Abraços
ob.:Quem quiser um aplicativo demonstrando o uso do componente e também seu código direitinho só mandar um email que eu envio.

Publicidade

Vote no artigo




Quantidade de votos: 0 votos
Aceitação: 0%


Detalhes do artigo

Categoria: Outros
Adicionado dia: 05/01/05
Por: Ivo Nascimento
Visualizado: 24803 vezes

Planeta Delphi - Tudo sobre programação Delphi Planeta Delphi - www.planetadelphi.com.br - Todos os direitos reservados | Copyright 2001-2009