7

I'm in the process of designing an API, part of which involves writing POCOs to a database.

In C#, we have the DateTime structure. The "default" value for this (DateTime.MinValue) is 01/01/0001.

Part of the API serializes POCOs to the database. If a date field is optional, it should really be nullable (in C# syntax, this would be defined as DateTime?). What I'd like to avoid, is programmers falling in to the trap of writing DateTime.MinValue to the database at all. It's a valid date, for sure - but smells of something. So I am debating implementing a BestPracticeException class that would be thrown in circumstances such as this.

If the user of the API really needs to deal with that date, they probably also need to deal with dates prior to that and need an entirely different structure (e.g comparing how many months have occurred between 500 BC and today).

Do you think preventing writing 01/01/0001 to the database, on the whole, is a good thing to do? One might argue that you need to differentiate between being no date entered, and the user entering nothing. My answer to that would be it is the function of a more broader auditing process that would pick that up, rather than attempting to ascertain intent from a field being null, or not null.

Moo-Juice
  • 1,378
  • 4
    is there any reason to invent a new exception BestPracticeException instead of using existing c# ArgumentOutOfRangeException or ArgumentException – k3b Jul 15 '14 at 12:29
  • @k3b, yes because both of those exceptions are geared towards arguments. Whilst some best-practices might involve arguments, some may be buried deep within logic. I was not intending to derive any more superfluous exceptions from it - just something that stood out from the rest of the more "generic" exceptions. The two you mention are great for nulls/invalid parameters in a general-coding sense, but not so much use when there is more meaning to the cause. – Moo-Juice Jul 15 '14 at 12:35
  • 1
    If you make 1/1/1 not work, the first wiseguy to hit that fence will use 2/1/1 instead. Or 1/2/3. Or 1/1/1900. Or whatever they need to to fix "the error that's stopping their program working". You've heard that old saying about making things idiot-proof, right? – AakashM Jul 15 '14 at 14:21
  • @AakashM, absolutely... Of course, anyone can work around the limitation - but it's there to catch the obvious, 95% case. :) – Moo-Juice Jul 15 '14 at 15:53

2 Answers2

8

Violating a best practice is not an exceptional condition. If you want to declare that 01/01/0001 is an invalid value, then throw an exception for that, specifically.

Looking forward to the day when my IDE throws an InvalidBraceStyleException.

Robert Harvey
  • 199,517
  • 2
    Yeah, if I was consuming your API and get a generic "BestPracticeException" I'm going to go... What the hell did I not do right? (or you depending on how much or little the call stack gives me) Now if you sent me DateValidationException I immediately go... oh... something is wrong with a date... what dates do I send? ... – Eric J Fisher Jul 15 '14 at 20:17
  • Good point! @RualStorge, if I was going to go ahead with it - the text would tell you what specifically it was for. You'd not be left head-scratching :) – Moo-Juice Jul 16 '14 at 06:57
0

A date of 01/01/0001 would usually indicate a bug. Someone probably has used a default-initialized variable.

Your intention basically is to have a runtime assert to guard against a specific class of bugs. That's a valid thing to do. In fact it is done all the time.

Consider having this validation as a layer between the client and the storage API. Like this:

var date = GetDate();
Validate(date);
Store(date);

Instead of:

void Store(DateTime dateTime) {
 Validate(dateTime);
 StoreImpl(dateTime);
}

Let callers choose whether they want this validation or not. By convention, have most or even all callers perform the validation. This keeps the validation out of the storage system.

usr
  • 2,764