Segunda-feira, Dezembro 20, 2004

Dialeto 3 com Interbase na BDE

Uma pergunta muito comum quando se trata de acessar bancos de dados Interbase com a BDE é como fazer para que não apareçam erros ao tentar conectar um banco de dados Interbase criado com o dialeto 3 (normalmente, erros de tipos de campos não suportados).
Esse problema é devido à configuração da BDE, que por padrão não tem a configuração SQLDialect.
O que deve ser feito para corrigir o peoblema é ir para o menu iniciar e selecionar a opção Executar e executar Regedit. No regedit, deve-se navegar para a chave HKEY_LOCAL_MACHINE\Software\Borland\Database Engine\Settings\DRIVERS\INTRBASE\DB OPEN.
Lá, deve-se clicar com o botão direito do mouse e escolher Novo/Valor da seqüência.
Ali, deve-se colocar SQLDIALECT e alterar o valor da seqüência para "3". Feche o editor de registro e reinicie a maquina. Ao abrir a configuração da BDE novamente, esta chave deve estar lá e o erro deve desaparecer.

Quarta-feira, Dezembro 15, 2004

Test driven development visual

Estou começando a usar Test Driven Development e estou gostando muito. Para quem não sabe o que é isso, a grosso modo é o seguinte: paralelamente a cada classe criada, criamos outra classe para testar os métodos da classe principal. Assim, a cada mudança que fazemos na classe principal, rodamos os testes para verificar se não introduzimos algum bug. Isto é muito rápido e fácil e, uma vez que os testes estão criados, podemos executá-los praticamente a cada mudança feita, não deixando que os erros se propaguem.
No Delphi 2005, o DUnit e NUnit (frameworks de teste para Win32 e para .NET) são incluídos na instalação e, para as outras versões, pode-se baixar gratuitamente o DUnit em http://dunit.sourceforge.net/.
Para ilustrar, a coisa é mais ou menos assim: vamos imaginar uma classe



TCalc = class
public
function Soma(a, b : Double) : Double;
function Subtrai(a, b : Double) : Double;
end;

Criamos uma classe de teste assim:


TTestaCalc = class(TTestCase)
published
procedure TestaSoma;
procedure TestaSubtrai;
end;

A implementação destes métodos chama a função Check, que faz o teste:


procedure TTestaCalc.TestaSoma;
var
Calc : TCalc;
begin
Calc := TCalc.Create;
Check(Calc.Soma(1,2) = 3,'Erro ao somar');
Calc.Free;
end;

Quando rodamos os testes, a procedure TestaSoma é executada, testando a função Soma. Se introduzimos um erro no código, o teste aponta o erro.
Até aqui, tudo bem. Mas, e se precisamos fazer uma verificação visual. No meu caso, tenho que testar o desenho de sinal biológico na tela. Os dados devem ser mostrados nos locais corretos quando um determinado método de minha classe é executada. Como fazer isso? A primeira idéia foi criar uma Form com 2 botões, Ok e Errado, checando a condição de retorno. Os dados seriam mostrados na tela e eu faria a inspeção visual, clicando no botão selecionado. A idéia parece funcionar, mas imaginem rodar os testes a cada 10 minutos, tendo de inspecionar e clicar no botão. A partir da terceira vez, com certeza, este teste estaria desabilitado :-).
A idéia seguinte foi usar um bitmap. A coisa funciona assim: crio um bitmap padrão. A cada teste, crio um novo bitmap, leio o bitmap padrão e comparo os dois. Se houver uma diferença, o teste falha. Desta maneira, consegui fazer um teste automatizado para uma rotina essencialmente visual. A chave da coisa é que a sua rotina desenhe para um Canvas genérico, assim dá para direcionar para a Form ou para o bitmap. A rotina de teste ficou assim:


procedure TVisualTests.TestDesenha;
var
Bitmap, Padrao : TBitmap;
begin
// Cria um bitmap de 1100 x 200
Bitmap := TBitmap.Create;
Bitmap.Width := 1100;
Bitmap.Height := 200;
// FVisual é a instância da classe que está sendo testada
// ela é criada em Setup e destruída em TearDown
FVisual.Desenha(Bitmap.Canvas);
// Lê o bitmap padrão
Padrao := TBitmap.Create;
Padrao.LoadFromFile('padrao.bmp');
// Compara os dois no mesmo formato
Padrao.PixelFormat := pf24Bit;
Bitmap.PixelFormat := pf24Bit;
// O bitmap tem 200 linhas
for i := 0 to 199 do
// No formato 24bits, cada pixel ocupa 3 bytes,
// assim a ScanLine tem 3300 bytes
for j := 0 to 1099*3 do
// Comparo as scanlines byte a byte
Check(Byte(Padrao.ScanLine[i]^) =
Byte(Bitmap.ScanLine[i]^),
'Bitmaps não conferem');
Bitmap.Free;
Padrao.Free;
end;

Sexta-feira, Dezembro 03, 2004

Migrando componentes para Delphi 2005

Recebi esta pergunta:

Gostaria de saber como faço com os componentes que usava em Delphi 7... Posso migrar para o Delphi 2005 e instalar os componentes (ex. eu uso Jedi, e alguns outros componentes) no 2005, ou tenho que substituir por itens do novo Delphi?

A resposta é: Depende. O Delphi 2005 é um programa de múltiplas personalidades e a utilização de componentes do Delphi 7 pode variar de "Sim, pode usar sem mudanças" até "Não dá mesmo".
Se você tiver os fontes dos componentes, a coisa fica mais fácil. Se não tiver, tem que conseguir os componentes atualizados para o Delphi 2005, pois não há maneira de usar os dcus do Delphi 7 no Delphi 2005.
Se tiver os fontes, pode instalá-los no Delphi 2005, na personalidade Win32, geralmente com poucas mudanças (componentes que visam diversas versões do Delphi, geralmente tem diretivas {$IFDEF} que visam as versões do Delphi. Temos que incluir nas diretivas o VER170, referente ao Delphi 2005, permitindo que o componente reconheça o Delphi 2005.
No caso específico dos componentes Jedi, as últimas versões estão sendo compatiblizadas para isso, mas ainda tive algumas dificuldades para instalá-los no Delphi 2005. Acredito que este problema estará superado em breve.
Para a personalidade VCL.NET, a coisa é um pouco mais complicada, pois algumas alterações devem ser feitas no fonte para compatiblizar com a plataforma .NET. O mesmo acontece na personalidade WinForms. Nesta personalidade, deve-se ter o cuidado de não incluir chamadas da VCL, como da units SysUtils, por exemplo. Isto faz com que a VCL deva ser adicionada ao aplicativo, aumentando-o significativamente.
A grande vantagem, aqui, é que podem ser usados componentes criados em outras linguagens .NET, como C# ou VB.NET, como se fossem componentes nativos Delphi.

Quinta-feira, Dezembro 02, 2004

Gravando os dados em Interbase com BDPProvider

Recebi a seguinte pergunta:

Fiz uma conexao com o banco e teste com o banco ele me retorna os registros efetados porém não comita no banco:
Estou usando ASP.NET com BDP e Firebird (Ja testei com Interbase) e no evento click do botão chamo a seguinte comando:

BdpConnection1.Open;
BdpCommand1.CommandText := TextBox1.Text;
r := BdpCommand1.ExecuteNonQuery();
TextBox2.Text := r.ToString + ' Registros Afetados';


Falta alguma coisa?


Verifiquei em minha máquina, em MS-SqlServer, o código funciona perfeitamente, ao executar uma Sql, os dados são gravados sem problemas, mas em Interbase, os dados não são gravados. O problema é a falta de uma transação e do respectivo commit. Modifiquei o código um pouco para incluir a transação, que ficou assim:



procedure TWebForm1.Button1_Click(sender: System.Object;
e: System.EventArgs);
var
r: Integer;
bdpTrans : BdpTransaction;
begin
BdpConnection1.Open;
bdpTrans := BdpConnection1.BeginTransaction();
BdpCommand1.CommandText := TextBox1.Text;

r := BdpCommand1.ExecuteNonQuery();
bdpTrans.Commit();

Label2.Text := r.ToString + ' Registros Afetados';
end;




Quarta-feira, Dezembro 01, 2004

Migração de um programa de Win32 para .NET

A edição número 57 da revista ClubeDelphi já está nas bancas, só sobre o Delphi 2005.
Além de uma série de artigos sobre esta nova ferramenta da Borland, há um artigo meu sobre a migração de um programa de Win32 para .NET, usando os dois frameworks disponíveis: VCL.NET e WinForms.
O programa faz a pesquisa de arquivos selecionados no disco, possibilitando encontrar os arquivos encontrados (ótimo para apagar backups de código fonte). Para converter para VCL.NET, o suficiente é recompilar o programa (foi tão fácil que eu até me espantei :-)). Para converter para WinForms, mostrei algumas dicas para a conversão de interface e de funcionalidade. O programa, que tinha 530K em Win32, ficou com 1.5Mb em VCL.NET e 37K (é isso mesmo, não é erro) em WinForms.
Vale a pena conferir.