Você está na página 1de 3

Aplicaes Robustas

O tratamento de exceo um mecanismo capaz de dar robustez a uma aplicao, permitindo que os erros sejam manipulados de uma maneira consistente e fazendo com que a aplicao possa se recuperar de erros, se possvel, ou finalizar a execuo quando necessrio, sem perda de dados ou recursos. Para que uma aplicao seja segura, seu cdigo necessita reconhecer uma exceo quando esta ocorrer e responder adequadamente a essa exceo. Se no houver tratamento para uma exceo, ser exibida uma mensagem padro descrevendo o erro e todos os processamentos pendentes no sero executados. Uma exceo deve ser respondida sempre que houver perigo de perda de dados ou de recursos do sistema.

Excees
Excees so classes definidas pelo Delphi para o tratamento de erros. Quando uma exceo criada, todos os procedimentos pendentes so cancelados e, geralmente mostrada uma mensagem de erro para o usurio. As mensagens padro nem sempre so claras, por isso indicado criar seus prprios blocos protegidos.

Blocos Protegidos
Um bloco protegido um grupo de comandos com uma seo de tratamento de excees.
try A := StrToFloat(EdtA.Text); B := StrToFloat(EdtB.Text); ShowMessage(Format('%f / %f = %f', [A, B, A + B])); except ShowMessage('Nmeros invlidos.'); end;

Algumas vezes voc pode precisar especificar quais excees quer tratar, como mostrado abaixo.
try Soma := StrToFloat(EdtSoma.Text); NumAlunos := StrToInt(EdtNum.Text); ShowMessage(Format('Mdia igual a %f.', [Soma / NumAlunos])); except on EConvertError do ShowMessage('Valor invlido para soma ou nmero de alunos.'); on EZeroDivide do ShowMessage('O nmero de alunos tem que ser maior que zero.'); else ShowMessage('Erro na operao, verifique os valores digitados.'); end;

Principais Excees
O Delphi define muitas excees, para cada erro existe uma exceo correspondente.
Classe Exception EAbort EAccessViolation EConvertError EDivByZero EInOutError EIntOverFlow EInvalidCast EInvalidOp EOutOfMemory EOverflow ERangeError EUnderflow EVariantError EZeroDivide EDatabaseError EDBEngineError Descrio Exceo genrica, usada apenas como ancestral de todas as outras excees Exceo silenciosa, pode ser gerada pelo procedimento Abort e no mostra nenhuma mensagem Acesso invlido memria, geralmente ocorre com objetos no inicializados Erro de converso de tipos Diviso de inteiro por zero Erro de Entrada ou Sada reportado pelo sistema operacional Resultado de um clculo inteiro excedeu o limite TypeCast invlido com o operador as Operao invlida com nmero de ponto flutuante Memria insuficiente Resultado de um clculo com nmero real excedeu o limite Valor excede o limite do tipo inteiro ao qual foi atribuda Resultado de um clculo com nmero real menor que a faixa vlida Erro em operao com variant Diviso de real por zero Erro genrico de banco de dados, geralmente no usado diretamente Erro da BDE, descende de EDatabaseError e traz dados que podem identificar o erro

Blocos de Finalizao
Blocos de finalizao so executados sempre, haja ou no uma exceo. Geralmente os blocos de finalizao so usados para liberar recursos.
FrmSobre := TFrmSobre.Create(Application); try FrmSobre.Img.LoadFromFile('Delphi.bmp'); FrmSobre.ShowModal; finally FrmSobre.Release; end;

Voc pode usar blocos de proteo e finalizao aninhados


FrmOptions := TFrmOptions.Create(Application); try FrmOptions.ShowModal; try Tbl.Edit; TblValor.AsString := EdtValor.Text; except on EDBEngineError do ShowMessage('Alterao no permitida.'); on EConvertError do ShowMessage('Valor invlido.'); end; finally FrmOptions.Release; end;

Gerao de Excees
Voc pode provocar uma exceo usando a clusula raise.
raise EDatabaseError.Create('Erro ao alterar registro.');

Tambm possvel criar seus prprios tipos de excees.


type EInvalidUser = class (Exception); raise EInvalidUser.Create('Voc no tem acesso a essa operao.');

Se voc quiser que uma exceo continue ativa, mesmo depois de tratada, use a clusula raise dentro do bloco de tratamento da exceo. Geralmente isso feito com excees aninhadas.
try Tbl.Edit; TblContador.Value := TblContador.Value + 1; Tbl.Post; except ShowMessage('Erro ao alterar contador.'); raise; end;

Erros de Bancos de Dados


A exceo EDBEngineError permite a identificao de erros de bancos de dados gerados pela BDE.
try TblCli.Post; except on E: EDBEngineError do if E.Errors[0].ErrorCode = DBIERR_KEYVIOL then ShowMessage('Cliente j cadastrado.'); end;

Note que a varivel E, que vai identificar o erro, s precisa ser declarada no bloco de tratamento da exceo. No help voc pode consultar outras propriedades de EDBEngineError que podem ser importantes. Voc tambm pode usar os eventos de erro do componente Table, sem precisar de blocos de tratamento.
procedure TFrmCadCli.TblCliPostError(DataSet: TDataSet; E: EDatabaseError; var Action: TDataAction); begin if(E is EDBEngineError) then with EDBEngineError(E) do case Errors[0].ErrorCode of DBIERR_KEYVIOL: ShowMessage('Cliente j cadastrado.'); DBIERR_REQDERR: ShowMessage('Campo obrigatrio no preenchido.'); end else ShowMessage('Erro no banco de dados:' + #13#13 + E.Message); Action := daAbort; end;

Alguns cdigos de erro da BDE esto listados abaixo. Todas as constantes e funes relacionadas API da BDE no Delphi 3 esto na Unit BDE, que deve ser adicionada clusula uses. No BDE API Help voc pode encontrar referncia sobre as funes nativas da BDE, como tambm alguns exemplos em Delphi.
Constante DBIERR_KEYVIOL DBIERR_MAXVALERR DBIERR_FORIEGNKEYERR DBIERR_LOCKED DBIERR_FILELOCKED DBIERR_NETMULTIPLE Descrio Violao de chave primria Valor mximo excedido Erro de chave externa, como em integridade referencial Registro travado Arquivo travado Mais de um diretrio usado como NetFileDir

DBIERR_MINVALERR DBIERR_REQDERR DBIERR_LOOKUPTABLEERR

Campo com valor mais baixo que valor mnimo Campo obrigatrio faltando Erro em tabela Lookup

Se voc quiser mais informaes a respeito do erro pode usar o procedimento DBIGetErrorContext, como na funo mostrada abaixo que retorna determinadas informaes sobre o erro.
function GetErrorInfo(Context: SmallInt): string; begin SetLength(Result, DBIMAXMSGLEN + 1); try DbiGetErrorContext(Context, PChar(Result)); SetLength(Result, StrLen(PChar(Result))); except Result := ''; end; end;

No evento OnEditError, usado no exemplo abaixo, se ocorrer um erro ao tentar alterar um registro, podemos identificar o usurio da rede que est alterando esse registro usando a funo criada anteriormente.
if Pos('locked', E.Message) > 0 then ShowMessage('Usurio ''' + GetErrorInfo(ecUSERNAME) + ''' est alterando o registro.');

Note que foi usada uma outra tcnica de identificao do erro, usando a prpria mensagem de erro e no o cdigo, como mostrado anteriormente. Voc pode usar a funo criada acima mandando como parmetro os valores mostrados abaixo, que podem ser encontrados no help da BDE.
Constante ecTABLENAME ecFIELDNAME ecUSERNAME ecFILENAME ecINDEXNAME ecDIRNAME ecKEYNAME ecALIAS ecDRIVENAME ecNATIVECODE ecNATIVEMSG ecLINENUMBER Descrio Nome da Tabela Nome do campo Nome do usurio, muito usado para identificar qual usurio travou o registro Nome do arquivo Nome do ndice Pasta Chave primria Alias Drive Cdigo de erro nativo Mensagem de erro nativa Nmero da linha, usado em instrues SQL

Para desenvolver um sistema genrico de tratamento de erros, considere a opo de criar esse tratamento em um DataModule genrico para ser usado como ancestral por todos os DataModules do sistema, utilizando a herana visual. Se o nico problema for traduzir as mensagens, localize os arquivos CONSTS.INT e DBCONSTS.INT e crie uma nova Unit de definio de strings com uma estrutura semelhante a mostrada abaixo e juntando todas as definies das constantes das duas Units devidamente traduzidas. Depois, basta usar essa Unit em seus projetos que as novas mensagens iro sobrepor as anteriores.
unit NewConsts; interface resourcestring SAssignError = 'No possvel atribuir %s a %s'; SFCreateError = 'No possvel criar arquivo %s'; SFOpenError = 'No possvel abrir arquivo %s'; SInvalidFieldSize = 'Tamanho de campo invlido'; SInvalidFieldRegistration = 'Registro de campo invlido'; SUnknownFieldType = 'Campo ''%s'' tem um tipo desconhecido'; implementation end.

Uma outra opo seria criar um mtodo para o evento OnException do objeto Application, esse mtodo seria chamado sempre que houvesse uma exceo em qualquer parte do sistema.