lundi 8 octobre 2018

Methods for Guarding Values vs. Data?

Does anyone know of any techniques or methods for guarding against invalid data instead of invalid values? I know it seems like an odd distinction, but bear with me.

A question came up recently for me about better ways to handle guarding against invalid variable values. We're currently wrapping exceptions in a Guard class, but the suggestion came up to go farther and wrap those in Extensions. In other words, this:

int myVar = 0;

// Basic
if (myVar < 1) throw new InvalidArgumentException("myVar cannot be less than 1");

// Guard -- wraps the above exception
Guard.AgainstValuesLessThan(1, myVar, nameof(myVar), "Value cannot be less than 1");

// Extension -- wraps the above guard
myVar.EnsureValid();

My problem here is that it feels like turtles all the way down -- eventually we'll decide that extensions don't work and wrap extensions with something else. In addition, extensions on primitives make it hard to identify what you're guarding against and why -- imagine the following scenario:

int customerId = 1;
int employeeId = 1;

// How do I write an extension method that lets me say "Guard against invalid Customer 
// IDs" and "Guard against invalid Employee IDs"?  Both are ints.  This method allows a
// guard, but with no context.
public static void EnsureValidValue(this int actual, int expected, string msg);

employeeId.EnsureValidValue(1, "Employee ID can't be less than 1");
customerId.EnsureValidValue(1, "Customer ID can't be less than 1");

So I'm trying to find a better way here, and that's where I am tripping up. So far what I've landed on is that my problem is fundamentally the fact that I'm thinking of what to guard as data ("I need to guard against bad customer IDs") but I'm guarding values ("I need to make sure this integer is at least 1").

I'm not sure where to go from here. I feel like this could be one of those "I didn't know that exists, but that helps!" cases.

Does anyone have any suggestions for what to look at? So far I have three thoughts, and I'm not sure if one is better than the other, or if there's some way to combine them to hit what I'm aiming for:

  • Code Contracts
  • Some Design Pattern I'm missing
  • Some other technique or trick (e.g., Attributes? InvokerParameterName?)

One last note: I'm aware that ReSharper provides an Annotations library, but not everyone on my team uses ReSharper (including me), so I don't want to have to rely on it.

Aucun commentaire:

Enregistrer un commentaire