Zentient Results Api Reference Glossary - ulfbou/Zentient.Results GitHub Wiki
This glossary defines key terms and concepts used throughout the Zentient.Results documentation. It aims to clarify terminology and ensure a shared understanding of the library's components and patterns.
The non-generic Result
struct. It represents the outcome of an operation that does not produce a specific return value upon success. It indicates either a successful completion (with optional messages) or a failure (with one or more associated ErrorInfo
objects). It is an immutable Value Object.
The generic Result<T>
struct. It represents the outcome of an operation that does produce a specific value of type T
upon success. Like Result
, it also encapsulates failure with one or more ErrorInfo
objects. It is an immutable Value Object.
An immutable readonly struct
that encapsulates detailed, structured information about a specific error or validation problem. It includes properties such as Category
(ErrorCategory
), Code
, Message
, and optional Parameters
. It functions as a Value Object for error details.
An enum
that provides broad classifications for errors (e.g., Validation
, NotFound
, BusinessLogic
, InternalError
). It helps in categorizing and generalizing error handling strategies, often mapping conceptually to HTTP status codes.
An interface that defines the semantic outcome of an operation, typically including a numeric Code
(often mapping to HTTP status codes), a Description
, and an IsSuccess
indicator. It standardizes the reporting of success or failure states beyond just a boolean flag.
A creational design pattern where an object is created by calling a static method (the "factory method") on a class, rather than directly using a constructor (e.g., new MyClass()
). In Zentient.Results, Result.Success()
, Result.Failure()
, and their overloads are prime examples of factory methods, simplifying the creation and proper initialization of immutable Result
instances.
A programming paradigm where functions or operations are combined to build more complex ones, emphasizing the use of pure functions (functions without side-effects) and immutability. In Zentient.Results, methods like Map
, Bind
, and Then
facilitate functional composition by allowing you to chain operations on Result
types in a fluent, pipeline-like manner, automatically propagating success or failure.
In functional programming, a Monad is a design pattern that provides a way to sequence computations that involve wrapped values (or "contextual" values) while managing side-effects or additional behaviors (like error handling, nullability, or asynchronous operations). It's essentially a container that provides methods to chain operations on the value inside the container, without having to "unwrap" it manually at each step.
In the context of Zentient.Results:
The IResult
and IResult<T>
types in Zentient.Results can be understood as monads. They wrap a potential successful value or a collection of errors, providing a context for operations that might succeed or fail.
Key characteristics of Result
as a Monad:
-
Wrapped Value: A
Result<T>
instance either holds a value of typeT
(in the success case) or a collection ofErrorInfo
objects (in the failure case). It never holds both simultaneously. -
Chainable Operations:
Result
provides specific extension methods that allow you to chain operations:-
Map
(Functor): Allows you to transform the value inside a successfulResult
from one type to another (T
toU
). If theResult
is a failure,Map
bypasses the transformation and simply propagates the failure. -
Bind
(Monadic Bind /flatMap
): Allows you to chain operations where each step itself returns anotherResult
. If a step fails, the entire chain short-circuits and propagates the failure. This prevents "nested"Result
types (e.g.,IResult<IResult<T>>
becomesIResult<T>
). -
Then
: Similar toBind
, but used when the subsequent operation returns a non-genericIResult
.
-
Why it matters for Result
:
Understanding Result
as a monad helps you leverage its full power for robust error handling and cleaner code:
-
Fluent Composition: It enables building pipelines of fallible operations using
Map
,Bind
, andThen
, significantly reducing nestedif/else
checks. - Error Propagation: Failures are automatically propagated through the chain, so you only need to handle the final outcome.
- Separation of Concerns: Your core business logic can focus on the successful path, while the monad handles the complexity of error flow.
- Explicitness: The API design naturally guides developers to consider both success and failure paths.
In essence, Result
provides a structured, functional approach to dealing with operations that can fail, making your code more readable, maintainable, and less prone to unhandled error conditions.
An action performed by a function or method that affects anything outside its local scope (i.e., beyond its return value or local variables). Examples include writing to a database, sending a network request, printing to the console, or modifying a global variable. In functional programming (and with Zentient.Results' functional utilities), minimizing or isolating side-effects is a common goal for building predictable and testable code.
The property of an object whose state cannot be modified after it is created. Once an immutable object is initialized, its internal data remains constant. Both Result
and Result<T>
structs in Zentient.Results are readonly struct
types, ensuring their immutability. This characteristic contributes to thread safety, predictability, and easier reasoning about program state.
An object that is defined by its attributes rather than its identity. Two value objects are considered equal if all their respective attributes are equal, regardless of whether they are the exact same instance in memory. In Zentient.Results, ErrorInfo
and ResultStatus
are designed as Value Objects, meaning you compare them based on their content, not their reference.