I'm currently revising code from 3 years ago. The result is a replica of the old stuff – updating isn't worth the effort, it's written in Swift 3 and the code base is small, so I rewrite it and copy useful parts over. The public interface already differs from what I wrote 3 years ago.
In the first step, I translated the old code but took what was there. For example, back then I had a
DateRange type. Swift
Ranges were less powerful back then, so I added a couple of convenient methods that I can now replace with the standard library protocols instead. So I demoted the type to
typealias DateRange = Range<Date>. I also had a
Date type (this was before
NSDate dropped the "NS") that I renamed to
NormalizedDate. In the domain I work on, a date isn't a date-time-combination, but just the year, month, and day. Confusingly, this type was a mere wrapper for
NSDate that dropped the time information for quick comparisons.
Later, as I worked on the protocols that this module would expose, I figured that the notion of a "range of days" is missing. Sure,
Range<NormalizedDate> did the job, but a
DayRange type was better. It's became a
RawRepresentable, backed by
After this change, though, I found the name "normalized date" too general. Sure, I am normalizing the date-time to drop the time information completely. But I really want to work with a
Day-date type. So I introduced
Day, which is backed by a
NormalizedDate and specifies its own normalization rules. This is oddly satisfying. The
Day type knows the normalization rules to create a
NormalizedDate from a regular old
As I write about all this, I notice that I should've made an additional step and replaced
Day with a struct that has
day only and constructs
NSDates where needed, instead of relying on that type to represent its values. Excuse me for a bit while I change the domain to accommodate this insights.
Browse the blog archive