quarta-feira, 2 de janeiro de 2013

Trabalhando com POO na prática


Depois de abrirmos o tema para que todos pudessem opinar, iremos começar a criar nossa série de artigos, segue abaixo a descrição de nosso sistema.

Peço a todos que pretendem colaborar de alguma forma que enviem um e-mail para mim para que possamos facilitar o contato e agilizarmos o processo de publicação dos artigos. Segue meu e-mail, rboaro@gmail.com.
 
Fica difícil mensurarmos quantos artigos iremos desenvolver sobre o tema, pois desenvolver uma aplicação por menor que seja requer bastante tempo ,muitas coisas precisam ser definidas. Sendo assim iniciamos descrevendo as funcionalidades básicas do sistema, por favor comentem (por e-mail) e sugiram alterações se acharem necessário.
 
Objetivo do Sistema: Processar vendas de um determinado estabelecimento, quando falo processar vendas, estou me referindo a controlar o estoque dos produtos, e ter as funcionalidades básicas de controle, como por exemplo, gerar títulos a receber , efetuar lançamentos no caixa, quando a venda for a vista etc.
 
Cadastros que serão criados:
> Cidades
> Clientes
> Produtos
> Pedidos
> Titulos a Receber
Seria interessante criarmos tambem outros cadastros, como por exemplo cadastro de Titulos a Pagar, mas nesse caso precisaríamos criar um cadastro de lançamento de notas fiscais de entrada o que pode ser feito baseado nos exemplos que iremos desenvolver.
 
Banco de dados utilizado: depois de muitas opiniões e como é de costume divergentes, pois cada um de nós simpatiza com um determinado banco de dados, como costumo dizer, "o melhor banco de dados é aquele que dominamos e sabemos utilizar o máximo das suas funcionalidades". Dessa forma pensei em criarmos classes de acesso ao Firebird e ao Sql Server Express (free).
 
Driver de acesso ao banco: esse não abro mão de usar dbExpress que é o que há de melhor nas ultimas versões do Delphi.
Versão do Delphi utilizada: Delphi XE2, mas me coloco a disposição para auxiliá-los a adaptar o fonte para outras versões.
 
Frequência dos artigos publicados: no mínimo um por semana, se possível mais, mas como todos temos nossos compromissos a cumprir, deixamos aqui acordado que não podemos passar uma semana sem publicar nada.
 
Acredito que os principais itens foram citados. Sendo assim mãos a obra.

Opção online para mpressão e Re-Impressão de DANFE

 
Alguma vez você já precisou imprimir ou re-imprimir um Documento Auxiliar de Nota Fiscal Eletrônica - DANFE?!

É claro que você pode entrar no seu sistema ERP e solicitar uma re-impressão... mas e se você não estiver na sua empresa?! e se o DANFE foi emitido por um fornecedor?!

Dois projetos interessantes e gratuitos estão disponíveis na internet para que possamos imprimir e re-imprimir DANFEs a partir do arquivo XML da NFe ou da chave de acesso da nota, são eles:

www.webdanfe.com.br/danfe/index.html
www.imprimirdanfe.com.br

Tipos Genéricos no Delphi


Hoje irei falar um pouco sobre tipos genéricos no delphi.
Um tipo genérico no Delphi pode ser definido por qualquer tipo padrão (string, integer, boolean) ou um tipo criado especificamente para sua aplicação.
Como isto é feito???

Defino uma classe Tvalor onde T é o tipo que a classe irá implementar.
Exemplo de Classe genérica:
TValor = class
FValor: T;
end;

Exemplo de utilização da classe:
Procedure teste();
Var
oTexto: Tvalor;
begin
oTexto := TValor.Create;
try
oTexto.Valor := ‘isto é um teste’;
finally
oTexto.Destroy;
oTexto := Nil;
end;
end;

Vamos pensar agora que nem sempre iremos ler o valor diretamente, como exemplo uma lista de objetos (não iremos implementar aqui, mas apenas como ajuda para interpretação OK?), como saberemos o tipo a ser tratado?

Simples, vamos mudar a implementação da classe!
Exemplo:

unit Model.ValorUnit;

interface

uses
System.TypInfo;

type
TValor = class
private
FValor: T;
FTipo: TTypeKind;
function GetValor: T;
procedure SetValor(const Value: T);
function GetTipo: TTypeKind;
public
procedure AfterConstruction; override;
property Valor: T read GetValor write SetValor;
property Tipo: TTypeKind read GetTipo;
end;

implementation

{ TValor }

procedure TValor.AfterConstruction;
var
Info: PTypeInfo;
begin
Info := System.TypeInfo(T);
try
if Info <> nil then
FTipo := Info^.Kind;
finally
Info := nil;
end;
end;

function TValor.GetTipo: TTypeKind;
begin
inherited;
result := FTipo;
end;

function TValor.GetValor: T;
begin
result := FValor;
end;

procedure TValor.SetValor(const Value: T);
begin
FValor := Value;
end;

end.

Nesta segunda implementação (ou alteração) a classe Tvalor agora possui dois campos, Fvalor e Ftipo.
Fvalor irá receber o valor própriamente dito, seja ele string integer ou qualquer outro, enquanto que Ftipo ira receber o tipo de dados que esta sendo utilizado dentro da classe e por consequencia no campo Fvalor.
Para definir o campo Ftipo, utilizei o procedimento AfterConstruction, este procedimento herdado da classe Tobject é chamado após o último construtor da classe ser executado. Segue abaixo o texto do Help do Delphi para melhor entendimento:
“Responds after the last constructor has executed.
AfterConstruction is called automatically after the object's last constructor has executed. Do not call it explicitly in your applications.
The AfterConstruction method implemented in TObject does nothing. Override this method when creating a class that performs an action after the object is created. For example, TCustomForm overrides AfterConstruction to generate an OnCreate event.”.

Neste procedimento, a nossa classe com o auxílio da System.TypInfo busca o tipo repassado ao criar um objeto do tipo Tvalor retornando o TtypeKind.
Tipos de TtypeKind:
TTypeKind = (tkUnknown, tkInteger, tkChar, tkEnumeration, tkFloat, tkString, tkSet, tkClass, tkMethod, tkWChar, tkLString, tkWString, tkVariant, tkArray, tkRecord, tkInterface, tkInt64, tkDynArray, tkUString, tkClassRef, tkPointer, tkProcedure).

Porque não usar a RTTI do Delphi?
No caso de Classes Genéricas, a RTTI não consegue achar a classe com o tipo especificado através da RTTI, não podendo retornar a classe e não retornando a classe, não se pode definir o tipo de dado da propriedade.