The Fusion domain kitResult<T>: errors as values
No narration yet
Module 8 · Lesson 115 min

Result<T>: errors as values

Fusion domain code does not throw for validation. It returns a Result<T>: either a success carrying a value, or a failure carrying a list of EjError. Exceptions are reserved for the genuinely unexpected (a bug, a torn network). A flight number that's blank isn't exceptional; it's an expected invalid input, so it comes back as a failed Result, not a thrown exception.

The Result primitives (real domain/Result.cs)
public record EjError(string Field, string Message);
public sealed record EntityNotFound(string Field, string Message) : EjError(Field, Message);

public sealed class Result<T>
{
    public bool IsSuccess { get; }
    public bool IsFailure => !IsSuccess;
    public T Value { get; }                     // throws if you read it on a failure
    public IReadOnlyList<EjError> Errors { get; }
    public static Result<T> Success(T value);
    public static Result<T> Failure(params EjError[] errors);
}

The building idiom is a fluent guard chain. FailIf(condition, error) starts a builder; you chain more FailIf calls; OrSuccess(...) builds the value only if nothing failed. The important detail: FailIf accumulates. It doesn't stop at the first broken rule; it collects them all, so the caller gets every problem at once instead of fixing them one round-trip at a time.

The FailIf / OrSuccess chain (real DisruptionDelayVo)
public static Result<DisruptionDelayVo> Create(bool isCancellation, int? delayInMinutes) =>
    Result<DisruptionDelayVo>
        .FailIf(isCancellation && delayInMinutes is not null,
            new EjError(nameof(DelayInMinutes), "Delay must be null for a cancellation."))
        .FailIf(!isCancellation && delayInMinutes is null,
            new EjError(nameof(DelayInMinutes), "Delay is required when not a cancellation."))
        .OrSuccess(() => new DisruptionDelayVo(isCancellation, delayInMinutes));
Practice

Try it yourself

Do

Trace an accumulating validation

Prove to yourself that FailIf collects, not short-circuits.

Tick every step to confirm you did it.

Quiz

Throw or Result

A caller passes a blank flight number to a domain factory. What should the factory do?