• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar
  • Skip to footer
Digital Caesar LLC Logo

Digital Caesar LLC

Bringing the digital world to life

  • Home
  • Blog
  • Resources
  • Products
    • Anticipation
    • Digital Results
    • Easy Grader
    • Being Catholic
  • Contact Us
  • About

Anticipation

You are here: Home / Products / Anticipation

Introduction

Anticipation is a library to promote proactive error management over reactive exception handling.

Exception Strategy

By default, an application will have an exception strategy. That is, when something goes wrong, an Exception will be thrown and the application will either handle it or fail. Typically, this starts by wrapping functions in try/catch blocks and then handling the various exceptions that are thrown. That normally involves a process of debugging, stopping on an exception, examining the state of the object that throws the exception, and then determining how to handle it either by returning a message to the user or correcting the state.

For example, the following code attempts to call a method that should return a value. If the method fails, then an exception is caught and message returned to the user.

try 
{ 
  decimal average = AverageCalculator.Calculate(values); 
  Console.WriteLine($"The average is {average}"); 
} 
catch (Exception ex) 
{ 
  Console.WriteLine(ex.Message); 
}

This can be effective, but the Exception messages are not always user friendly and it requires you to react when something goes wrong.

Error Strategy

The Error strategy attempts to move more of the logic and thought into the domain objects allowing the client code to focus more on user facing concerns.

var average = AverageCalculator.Calculate(values);

if (average.Error is not null)
  Console.WriteLine(average.Error.Message);
else
  Console.WriteLine($"The average is {average.Value}");

Here the user code has two possible outcomes – success or failure. Both return a message to the user. The concept here is to push more logic into the method where there is a better understanding of the object state and what is good and what is not good state.

How to use Anticipation

There are many ways you can make Anticipation work for you. To put Anticipation to the best use, the method you call should return a Result type that can return either a value or an Error. In the example above, you would create an AverageResult and refactor the method to return the AverageResult after checking for Error states.

Here we define a record type to encapsulate the possible return types

public record AverageResult(decimal Value, Error Error)

Then we adjust the method to return the new AverageResult type.

public static AverageResult Calculate(int[] values)
{
  decimal count = values.Length;
  if(count <= 0)
    return new AverageResult(0, new Error("2",""No values were provided.  At least one valid value must be provided."));  
    decimal total = 0;
  foreach (int value in values)
  {
    if (value > 100)
      return new AverageResult(0, new Error("1","The Value provided was too high.  Values must be below 100."));
    if (value < 0)
      return new AverageResult(0, new Error("0","The Value provided was too low.  Values must be zero or higher."));
      total += value;
  }
  decimal result = total / count;
  return new AverageResult(result, null);
}

This then allows you to use the method as demonstrated in the previous Error Strategy example. An even better implementation is to use the DigitalResult package to define a discriminated union result type that can return either a value or an error. You can find out more in the product page or in the blog post about using discriminated unions for results.

Defining Errors

Errors can be predefined. It is not required, but it does make your code a bit cleaner to define and reuse the possible Errors.

public static class AverageError
{
  public static Error ValueTooLow => new("0", "The Value provided was too low. Values must be zero or higher.");
  public static Error ValueTooHigh => new("1","The Value provided was too high. Values must be below 100.");
  public static Error NoValues => new("2","No values were provided. At least one valid value must be provided.");
}

Now, you simply reference the predefined error where ever you wish to return such an error in your code.

return new AverageResult(0, AverageError.ValueTooHigh(value));

This allows you to get more creative with your error responses. For example, it would be useful for the user to know what value they entered that caused the Error.

public static Error ValueTooLow(int value) => new("0", $"The Value provided '{value}' was too low. Values must be zero or higher.");

The example above allows you to pass the current value to the Error in order to provide a more meaningful response to the user.

Do you like what you see?

For more information, you can check out the code on GitHub. If you like it, give it a Star, consider Sponsoring us, and feel free to contribute.

Would you like to see more? Check out our blog and other products.

Primary Sidebar

Subscribe to Blog via Email

Donate

Footer

Follow along on Social Media

  • Email
  • Facebook
  • LinkedIn
  • Pinterest
  • RSS
  • Tumblr
  • Twitter
Copyright ©2025 · Digital Caesar LLC · All Rights Are Reserved
Powered by Business Pro Theme On Genesis Framework a WordPress Site · Log out
Privacy· Terms of Use

Copyright © 2025 · Business Pro Theme on Genesis Framework · WordPress · Log in

This website uses cookies to improve your experience. We'll assume you're ok with this, but you can opt-out if you wish.Accept Reject Read More
Privacy & Cookies Policy

Privacy Overview

This website uses cookies to improve your experience while you navigate through the website. Out of these, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may affect your browsing experience.
Necessary
Always Enabled
Necessary cookies are absolutely essential for the website to function properly. This category only includes cookies that ensures basic functionalities and security features of the website. These cookies do not store any personal information.
Non-necessary
Any cookies that may not be particularly necessary for the website to function and is used specifically to collect user personal data via analytics, ads, other embedded contents are termed as non-necessary cookies. It is mandatory to procure user consent prior to running these cookies on your website.
SAVE & ACCEPT