Defensive Programming Vs Fail Fast · How it works
1 min readRapid overview
How it works
A comprehensive guide to two fundamental error handling philosophies in software development.
Real-World Trading System Example
public class TradingSystem
{
// Defensive: External market data feed
public async Task<MarketPrice> GetMarketPriceAsync(string symbol)
{
try
{
var rawData = await _marketDataFeed.GetPriceAsync(symbol);
// Defensive: validate external data
if (rawData == null || string.IsNullOrEmpty(rawData.Price))
{
_logger.LogWarning("Invalid market data for {Symbol}", symbol);
return await GetCachedPriceAsync(symbol); // Fallback
}
if (!decimal.TryParse(rawData.Price, out var price) || price <= 0)
{
_logger.LogWarning("Invalid price format: {Price}", rawData.Price);
return await GetCachedPriceAsync(symbol); // Fallback
}
return new MarketPrice(symbol, price, DateTime.UtcNow);
}
catch (Exception ex)
{
_logger.LogError(ex, "Market data feed error for {Symbol}", symbol);
return await GetCachedPriceAsync(symbol); // Fallback
}
}
// Fail-Fast: Internal order execution
public async Task ExecuteOrderAsync(Order order, decimal executionPrice)
{
// Fail-fast: validate preconditions
if (order == null)
throw new ArgumentNullException(nameof(order));
if (order.Status != OrderStatus.Pending)
throw new InvalidOperationException(
$"Cannot execute order in {order.Status} status");
if (executionPrice <= 0)
throw new ArgumentException(
"Execution price must be positive", nameof(executionPrice));
// Fail-fast: check risk limits
var account = await _accountRepository.GetByIdAsync(order.AccountId);
if (account == null)
throw new InvalidOperationException(
$"Account {order.AccountId} not found");
_riskValidator.ValidateExecution(order, account, executionPrice);
// Execute
order.Execute(executionPrice);
account.UpdatePosition(order);
await _unitOfWork.CommitAsync();
}
}