You should hard code the idea, not the value
I am reading NServiceBus' code at the moment, and I run into this idea:
[Serializable]
[Recoverable]
[TimeToBeReceived(“0:01:00.000")]
public class ScheduleInterviewMessage : IMessage
{
public Guid InterviewerId;
public Guid CandidateId;
public DateTime RequestedTime;
}
I don't like hard coding this value in the message. Obviously this is something that is tied very closed to the idea of the message. Time to live is certainly something that I would want to closely tie to the message itself. But hard coding the value goes against a lot of instincts.
A while ago I faced a similar issue, in that case, it was scheduling tasks. The timing of the task was tied to what it did. The last example that I had on that post is this:
[Occurances(OccureEvery.Day, At = "08:00", RunAtHolidays = false)] public class SendSmsTwoDaysBeforeEventStart : ScheduledTask
Notice the At = "08:00" ? It bothered me for a while, until I came to the conclusion that I was embedding the wrong piece of information in the code.
I didn't want this to run at 08:00, I want it to run in the morning. 08:00 was just a handy designation for that. That thought was quickly followed by:
public enum ScheduledTimes
{
Midnight,
EarlyMorning,
Morning,
Noon,
Afternoon,
Evening
}
And the code turned to:
[Occurances(OccureEvery.Day, At = ScheduledTimes.Morning, RunAtHolidays = false)]
public class SendSmsTwoDaysBeforeEventStart : ScheduledTask
The difference here is that I no longer hard code a specific value, I put the idea there. During deployment, I could have modified what morning meant, very easily.
Using the same approach, I would define something like:
public enum TimeToLive
{
Immediate,
Short,
Medium,
Long,
Forever
}
I would probably allow to configure the time that each of those values map to, as well.
This allows to do things like update them on the fly (imagine having to survive a burst of traffic that slows the entire system), so you can increase the time to process a message without losing it.
Comments
I agree that building in a TTL for a message would be something you probably want to avoid as system requirements might change quickly and recompiling to fix this seems a little over the top, but if you really needed to keep this flexible wouldn't you be better off having a default behavior but allowing it to be overridden in configuration?
That said, since the class just represents a message this is the equivalent of configuration if you just deploy a new version of the assembly that contains the message and re-start the application; no harm, no foul. A runtime change would require that you change your config and restart anyway.
And after re-reading my own comment I can't tell whether or not I agree with you... :)
This didn't seem natural to me, too. A job is a job, it should only have what it does and how it does, not when it does, because it can change. How would you change this without recompiling the code? Sending sms may disturb people so you may have to change it, right? I think there should be "scheduler" by which you can explicitly set occurance time/period etc, . Am I missing a point here?
By saying "sending sms", i actually meant "sending sms in the morning"
there's a great post by Nat Pryce on that, "Encapsulation is not Information Hiding":
http://nat.truemesh.com/archives/000498.html
The value isn't just for the service receiving it - clients need to know about it as well.
You see, this attribute is how we communicate to clients the value they should be passing to their infrastructure when sending a message to our service so that we take time into account end-to-end.
Also, you can't dictate how messages are going to come into your queue - are they going to have a TTL specified or not.
This is not something you can configure at runtime as clients will need to change their behavior too - otherwise its pointless.
So, for all these reasons, TTL is part of a service's contract - and publishing it means something. Therefore, the use of "hard coded attributes" is not only suitable, but probably the simplest solution that could possibly work.
Hope that clears it up.
Comment preview