A common need in domain modelling is to specify a range - of dates, of prices, or some other numeric measure. Typically, we model this with a pair of properties, as in this example:
To go along with these properties, there is typically a bunch of minor logic used to ensure the range remains valid.
One way is to throw an exception if an invalid range would be formed (say, if EffectiveFrom
was set to a date after
EffectiveUntil
); another is to potentially update both ends of the range to ensure it remains valid (setting
EffectiveDate
to a date after EffectiveUntil
would also update EffectiveUntil
to the new date).
An alternative that provides more functionality and more reuse is to use an explicit Range<T>
struct to declare the
property:
Of course, the interesting bits are in the Range
struct:
The Range
struct is pretty conventional, but has a couple of features worthy of note.
Either bound may be omitted if no limit is required in that direction. In our MarketingCampaign
example, To
can be
omitted if the end date of the campaign has not yet been determined.
Also, the sequence of the bounds is maintained - setting the value of From
lower than To
will update To
to ensure
the Range is legal, and vice versa, as follows:
As you can see, Range
is a simple helper - but one that makes our properties just that bit more expressive, capturing
our domain semantics more accurately.
There are possible extensions of course. Perhaps the most obvious would be for Range
to properly implement the
INotifyPropertyChanged
interface, exposing a PropertyChanged
event for subscription. In all likelihood, the parent
class would end up subscribing to this property itself in order to correctly trigger it’s own PropertyChanged
events.
Another, more complicated approach would be to create a RangeProperty
helper similar in intent to the Property
helper discussed in my recent post Improving on POCO Properties.
Comments
blog comments powered by Disqus