.. title: The Story of None: Part 3 - Handling It .. slug: none_03_handling_it .. date: 2013/01/31 10:30 .. tags: python, patterns, pythonic, planetpython .. description: 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`` or ``value 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 ommitted ``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`` is ``None``, 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. .. _`Next time`: http://blog.startifact.com/posts/none_04_guard_clauses.html `part 1 `_ `part 2 `_ `part 3 `_ `part 4 `_ `part 5 `_ `part 6 `_