In large engineering teams without strict error handling conventions, systems quickly degrade:
- Error Code Collisions: Multiple modules define conflicting error codes;
- Arbitrary Runtime Exceptions: Throwing untyped
new Exception("Insufficient Balance"), preventing callers from distinguishing between transient network faults and business rule rejections; - Hardcoded Error Text: Free-text backend messages preventing localized UI rendering.
BitzOrcas.Modern enforces a typed, compile-time static Error + Result<T> flow control model:
Error Type Hierarchy and Resolution
Step 1: Defining Domain Errors via Standard Factories
Define module errors using standard factories instead of throwing exceptions:
using BitzOrcas.Domain.Results;
namespace BitzOrcas.Customer.Domain.Errors;
public static class CustomerErrors{ // 404: Target customer record does not exist public static readonly Error NotFound = Error.NotFound( code: "Customer.NotFound", description: "The specified customer record was not found.");
// 409: Customer phone collision public static readonly Error PhoneAlreadyExists = Error.Conflict( code: "Customer.PhoneAlreadyExists", description: "The phone number is already bound to another customer.");
// 400: Dynamic parameter validation error public static Error InvalidCreditLimit(decimal limit) => Error.Validation( code: "Customer.InvalidCreditLimit", description: $"Customer credit limit {limit} cannot be negative.");}Step 2: Propagating Results in Aggregates and Handlers
// Domain aggregate method: evaluates credit limit adjustmentspublic Result AdjustCreditLimit(decimal newLimit){ // 1. Check if credit limit is non-negative if (newLimit < 0) { // 2. Return typed validation error without throwing exceptions return Result.Failure(CustomerErrors.InvalidCreditLimit(newLimit)); }
// 3. Invariant satisfied: mutate state and return success CreditLimit = newLimit; return Result.Success();}Summary
Typed domain errors streamline team collaboration:
- Zero Exception Overhead: Microsecond execution without GC spikes;
- Namespaced Errors: Prefixing codes (e.g.
Customer.) prevents collisions; - Automated HTTP Mapping:
Validation$ maps to HTTP 400,NotFoundmaps to HTTP 404, andConflictmaps to HTTP 409.