The Story of None: Part 3 - Handling It
part 1 part 2 part 3 part 4 part 5 part 6
Last time...
In part 1 of the Story of None we've seen this validation function:
def validate_end_date_later_than_start(start_date, end_date):
if end_date <= start_date:
raise ValidationError(
"The end date should be later than the start date.")
We've determined start_date
and end_date
may be None
. In part
2 we've seen that we can recognize this case by using is None
or
is not None
.
So:
- we should consider whether
None
is possibility. - we should use
value is None
orvalue is not None
to check.
Once we know that we're not out of the woods yet though: we still need
to decide what to do when either of the arguments is None
. This will
need to be thought about and depends on the circumstances.
Requirements
So what would make sense in this case? If either start_date
or
end_date
are None
, does it make sense to validate this at all? What
does an omitted date
mean in this case? This depends on the
application's requirements.
For the sake of the example I will make up a few simple requirements here:
- Let's say that in this application the start and end dates define a period when a product is on the market.
- If a
start_date
isNone
, we don't have a start date, and we'll interpret this as as far as we know now, the product has been in the market from the indefinite past, until the end date. - If an end date is
None
, we interpret this as as as we know now, the product will be on the market from the start date until the indefinite future. - If both are
None
, we assume the product has been on the market from the indefinite past to the indefinite future.
Something like that. The specification doesn't have to be perfect and it often won't be. If it isn't clear it'll be your job to find out what it should be, generally by asking someone (and perhaps giving them a few suggestions).
start_date is None
Given these requirements, how would we handle None
for start_date
?
If the start_date
is in the indefinite past, we don't have to check
whether end_date
is earlier than it, because we'll say the indefinite
past is always earlier. (If you're not sure about this, ask someone,
but in this case we are sure as we make it up ourselves.)
Let's express that in code:
def validate_end_date_later_than_start(start_date, end_date):
if start_date is None:
return
if end_date <= start_date:
raise ValidationError(
"The end date should be later than the start date.")
end_date is None
If end_date
is None
, it's in the indefinite future. start_date
can
not be later than a date in the indefinite future, so we don't need to
check then either. Let's express this in code too:
def validate_end_date_later_than_start(start_date, end_date):
if start_date is None:
return
if end_date is None:
return
if end_date <= start_date:
raise ValidationError(
"The end date should be later than the start date.")
start_date is None and end_date is None
Now what if both end_date
and start_date
are None
? A date in the
indefinite past is always earlier than the indefinite future, so we're
safe too and don't need to compare dates either. We can express this in
code too:
def validate_end_date_later_than_start(start_date, end_date):
if start_date is None and end_date is None:
return
if start_date is None:
return
if end_date is None:
return
if end_date <= start_date:
raise ValidationError(
"The end date should be later than the start date.")
It turns out the last bit was superfluous as turn out to handle this case correctly already anyway. That's fine and will often be the case, but not always so we do need to briefly think about this case before we stop worrying about it.
Next time we'll talk about what this pattern really is.