PC SOFT

GRUPOS DE DISCUSSÃO PROFISSIONAL
WINDEVWEBDEV e WINDEV Mobile

Inicio → WINDEV 25 → Programação Defensiva no WLangage
Programação Defensiva no WLangage
Iniciado por Boller, ago., 05 2025 2:36 AM - Sem resposta
Membro registado
4.618 mensagems
Publicado em agosto, 05 2025 - 2:36 AM
Programação Defensiva no WLangage

O que é?

A programação defensiva consiste em verificar dentro do próprio código as entradas e saídas de cada procedimento, de modo a antecipar e tratar possíveis erros. Esses problemas são sinalizados apenas em modo de depuração (debug), garantindo que o software funcione de forma mais segura .

Ferramentas disponíveis

O WLangage inclui funções específicas para auxiliar na programação defensiva, tais como:
• dbgAssertion, dbgVérifieVrai, dbgVérifieFaux, dbgVérifieEgalité, dbgVérifieDifférence, dbgVérifieNonNull, dbgVérifieNull.
• dbgErreurProvoque e dbgSurErreur: permitem lançar erros ou chamar rotinas específicas em caso de falha   .

Testes automáticos integrados

No WLangage, funções como TestVérifieEgalité, TestVérifieDifférence, TestVérifieVrai, etc., são usadas em testes unitários. Elas possuem comportamento semelhante às funções dbg…, mas são executadas em modo automático de teste, gerando relatórios ou falhas conforme o caso  .

Como funciona
• Em modo execução normal, se as assertions não estiverem ativas, nenhum teste é avaliado.
• Em modo depuração ou modo de teste, os testes são avaliados e, se falharem, resultam em erros ou assertivas dependendo do modo .



📋 Resumo em tabela

Conceito Objetivo Modo de execução
Verificação de entradas e saídas Antecipar erros em procedimentos Sempre (em modo de depuração)
dbgVérifie… Avaliações no ambiente de depuração ou testes Produz assert ou erro
TestVérifie… Avaliações em testes unitários automáticos Gera relatórios ou falhas





// ==================================================
// EXEMPLO 1: Verificar se um valor não é nulo
// ==================================================
PROCEDURE GetCustomerName(customerID)

dbgVérifieNonNull(customerID, "O ID do cliente não pode ser nulo")

IF NOT HReadSeekFirst(Customer, CustomerID, customerID) THEN
dbgErreurProvoque("Cliente não encontrado no banco de dados")
RETURN ""
END

RETURN Customer.Name


// ==================================================
// EXEMPLO 2: Verificar igualdade entre valores esperados
// ==================================================
PROCEDURE CalculateDiscount(price, discount)

dbgVérifieVrai(price > 0, "Preço inválido")
dbgVérifieVrai(discount >= 0 AND discount <= 100, "Desconto fora da faixa")

nFinalPrice IS real = price - (price * discount / 100)

// Verificação fictícia de consistência (apenas para debug)
dbgVérifieEgalité(nFinalPrice <= price, True, "O preço final não pode ser maior que o original")

RETURN nFinalPrice


// ==================================================
// EXEMPLO 3: Testes automatizados com TestVérifie...
// ==================================================
TestVérifieEgalité(CalculateDiscount(100, 10), 90)
TestVérifieDifférence(CalculateDiscount(100, 5), 94.99) // Deve falhar
TestVérifieVrai(CalculateDiscount(200, 20) = 160)


// ==================================================
// EXEMPLO 4: Múltiplas verificações com dbgVérifie...
// ==================================================
PROCEDURE TransferBalance(senderID, receiverID, amount)

dbgVérifieNonNull(senderID)
dbgVérifieNonNull(receiverID)
dbgVérifieVrai(amount > 0, "O valor da transferência deve ser positivo")

IF NOT HReadSeekFirst(Account, AccountID, senderID) THEN
dbgErreurProvoque("Remetente inválido")
END

IF Account.Balance < amount THEN
dbgErreurProvoque("Saldo insuficiente")
END

Account.Balance -= amount
HModify(Account)

IF NOT HReadSeekFirst(Account, AccountID, receiverID) THEN
dbgErreurProvoque("Destinatário inválido")
END

Account.Balance += amount
HModify(Account)

RETURN True


// ==================================================
// DICA EXTRA: Ativando ou desativando assertions
// ==================================================

// No código de inicialização do projeto:
dbgActive(True) // Ativa assertions em desenvolvimento

// Em produção:
dbgActive(False) // Desativa para evitar impacto no desempenho

Claro! Abaixo está um texto explicativo completo, com base nos exemplos que criamos, utilizando situações reais do dia a dia de um sistema empresarial. O objetivo é mostrar como e por que usar cada comando de programação defensiva do WLanguage para garantir segurança, estabilidade e rastreabilidade dos erros em tempo de desenvolvimento.



🛡️ Programação Defensiva em WLanguage: Como usar e por quê?

A programação defensiva é uma prática essencial para garantir que seu sistema não quebre silenciosamente durante a execução. No universo WX (WinDev, WebDev e WinDev Mobile), temos um arsenal de comandos como dbgVérifie..., dbgErreurProvoque, TestVérifie... e dbgActive que permitem aplicar essa estratégia de forma elegante.

A seguir, vamos explorar cada um desses comandos em situações reais:



✅ dbgVérifieNonNull: Garantir que o valor obrigatório foi informado

Situação real: Você está desenvolvendo uma procedure que busca o nome do cliente a partir do ID recebido como parâmetro. Mas e se esse ID vier nulo?

dbgVérifieNonNull(customerID, "O ID do cliente não pode ser nulo")

Se o customerID for nulo durante o desenvolvimento, o sistema irá parar e mostrar uma mensagem clara, evitando bugs difíceis de rastrear mais tarde. Isso é vital em sistemas com múltiplos pontos de entrada, como APIs REST, que podem receber dados malformados.



✅ dbgVérifieVrai: Validar se uma condição foi satisfeita

Situação real: Antes de aplicar um desconto em uma compra, precisamos ter certeza de que o valor do desconto é válido (por exemplo, entre 0% e 100%).

dbgVérifieVrai(discount >= 0 AND discount <= 100, "Desconto fora da faixa")

Durante o desenvolvimento, se alguém tentar dar um desconto de 110%, o sistema avisa o programador imediatamente. Isso protege a lógica de negócio desde o início e evita falhas financeiras.



✅ dbgVérifieEgalité: Confirmar resultados esperados

Situação real: Após aplicar o desconto, o valor final não pode ser maior que o original. Parece óbvio, mas isso precisa ser testado.

dbgVérifieEgalité(nFinalPrice <= price, True, "O preço final não pode ser maior que o original")

Esse tipo de verificação é excelente para garantir que fórmulas matemáticas estejam corretas — principalmente em áreas críticas como faturamento ou cálculo de impostos.



✅ dbgErreurProvoque: Forçar uma interrupção com mensagem específica

Situação real: Você está buscando um cliente ou conta no banco de dados. Se o ID informado não existe, é melhor abortar o processo imediatamente.

IF NOT HReadSeekFirst(Customer, CustomerID, customerID) THEN
dbgErreurProvoque("Cliente não encontrado no banco de dados")
END

O uso de dbgErreurProvoque impede que o código continue com variáveis vazias ou dados inválidos, o que poderia causar erros difíceis de identificar em produção. É uma forma de aplicar o princípio do fail fast: falhar o quanto antes.



✅ TestVérifieEgalité, TestVérifieDifférence, TestVérifieVrai: Testes automatizados

Situação real: Você quer garantir que a função de cálculo de desconto está retornando os valores esperados. Para isso, criamos testes automáticos.

TestVérifieEgalité(CalculateDiscount(100, 10), 90)
TestVérifieDifférence(CalculateDiscount(100, 5), 94.99) // Deve falhar
TestVérifieVrai(CalculateDiscount(200, 20) = 160)

Esses comandos são usados fora do código principal, em scripts de teste. Eles são ideais para validar módulos críticos e manter uma base de regressão para futuras alterações.



✅ dbgActive(True/False): Ativar ou desativar verificações

Situação real: Você está desenvolvendo um sistema novo e quer garantir máxima validação enquanto escreve o código. Mas, ao colocar o sistema em produção, deseja desligar essas verificações para ganhar performance.

// Em desenvolvimento
dbgActive(True)

// Em produção
dbgActive(False)

Essa função te dá controle total para ativar ou desativar as verificações, permitindo um ciclo de desenvolvimento seguro e uma execução rápida no cliente.



✅ Conclusão: Segurança e rastreabilidade com código limpo

A programação defensiva não é frescura, é prevenção ativa. Quando bem aplicada com as funções do WLanguage, ela:
• Reduz erros em produção
• Facilita a manutenção
• Aumenta a confiança no código
• Torna o comportamento do sistema mais previsível

Em sistemas empresariais, principalmente em áreas como financeiro, contratos, estoque e comunicações, essas práticas não são opcionais — são essenciais.


// ==================================================
// EXEMPLO 5: Validação de e-mail com dbgVérifieFaux
// ==================================================
PROCEDURE ValidateEmail(email)

dbgVérifieFaux(email = "", "E-mail não pode ser vazio")

bIsValid IS boolean = StringCount(email, "@") = 1 AND StringCount(email, ".") > 0
dbgVérifieVrai(bIsValid, "E-mail inválido")

RETURN True


// ==================================================
// EXEMPLO 6: Verificação de senha forte com dbgVérifieVrai
// ==================================================
PROCEDURE CheckPasswordStrength(password)

dbgVérifieVrai(Length(password) >= 8, "Senha muito curta")
dbgVérifieVrai(StringCount(password, "0") + StringCount(password, "1") > 0, "Senha precisa conter números")
dbgVérifieVrai(Upper(password) <> password, "Senha precisa conter letras minúsculas")
dbgVérifieVrai(password <> Lower(password), "Senha precisa conter letras maiúsculas")

RETURN True


// ==================================================
// EXEMPLO 7: Testes automatizados com valores calculados
// ==================================================
TestVérifieEgalité(ValidateEmail("teste@exemplo.com"), True)
TestVérifieFaux(ValidateEmail("invalido.com"))
TestVérifieEgalité(CheckPasswordStrength("Abc12345"), True)
TestVérifieFaux(CheckPasswordStrength("abc"))


// ==================================================
// EXEMPLO 8: Verificar se um campo obrigatório está preenchido
// ==================================================
PROCEDURE SaveProduct(productName, price)

dbgVérifieFaux(productName = "", "O nome do produto é obrigatório")

dbgVérifieVrai(price > 0, "Preço deve ser maior que zero")

// Simular gravação
Trace("Produto salvo: " + productName + " - R$ " + NumToString(price))

RETURN True


// ==================================================
// EXEMPLO 9: Prevenção de divisão por zero
// ==================================================
PROCEDURE CalculateAverage(total, count)

dbgVérifieVrai(count > 0, "Divisão por zero ao calcular média")

RETURN total / count



// ==================================================
// EXAMPLE 1: Validate email using dbgVérifieFaux
// ==================================================
PROCEDURE ValidateEmail(email)

dbgVérifieFaux(email = "", "Email must not be empty")

bIsValid IS boolean = StringCount(email, "@") = 1 AND StringCount(email, ".") > 0
dbgVérifieVrai(bIsValid, "Invalid email format")

RETURN True


// ==================================================
// EXAMPLE 2: Check strong password using dbgVérifieVrai
// ==================================================
PROCEDURE CheckPasswordStrength(password)

dbgVérifieVrai(Length(password) >= 8, "Password is too short")
dbgVérifieVrai(StringCount(password, "0") + StringCount(password, "1") > 0, "Password must contain numbers")
dbgVérifieVrai(Upper(password) <> password, "Password must contain lowercase letters")
dbgVérifieVrai(password <> Lower(password), "Password must contain uppercase letters")

RETURN True


// ==================================================
// EXAMPLE 3: Automated tests using TestVérifie...
// ==================================================
TestVérifieEgalité(ValidateEmail("test@example.com"), True)
TestVérifieFaux(ValidateEmail("invalid-email.com"))
TestVérifieEgalité(CheckPasswordStrength("Abc12345"), True)
TestVérifieFaux(CheckPasswordStrength("abc"))


// ==================================================
// EXAMPLE 4: Check required fields before saving a product
// ==================================================
PROCEDURE SaveProduct(productName, price)

dbgVérifieFaux(productName = "", "Product name is required")
dbgVérifieVrai(price > 0, "Price must be greater than zero")

Trace("Product saved: " + productName + " - $" + NumToString(price))

RETURN True


// ==================================================
// EXAMPLE 5: Prevent division by zero using dbgVérifieVrai
// ==================================================
PROCEDURE CalculateAverage(total, count)

dbgVérifieVrai(count > 0, "Division by zero when calculating average")

RETURN total / count

--
Adriano José Boller
______________________________________________
Consultor e Representante Oficial da
PcSoft no Brasil
+55 (41) 99949 1800
adrianoboller@gmail.com
skype: adrianoboller
http://wxinformatica.com.br/