Archive for May, 2009

15
May
09

The ‘Always Valid Entity’ is not a fallacy

I had to comment on Jeffrey Palermo’s recent post entitled ‘The fallacy of the always-valid entity’ as I both disagreed with what he was suggesting and wonder if he has missed the point. I thought I’d follow up here with an example that demonstrates how I implement an always valid entity. Many other comments on the post allude to similar approaches also. If you haven’t already, read Jeffrey’s post before reading on.

Jeffrey’s UserProfile class initially throws exceptions in property setters if null values are supplied. These are invariants. I think he’s arguing against this approach. He then evolves the example to present a validation framework that allows a collection of rules to be asserted against an instance of the entity and reports back failed rules.  The rules are intended to be context specific validations, but the context is missing (at least from the example given).

He additionally talks about legacy data and the need to allow for invalid entities for unspecified reasons. He concludes with

“It is futile to attempt to keep entities always-valid.  Let bad things happen to them, and then validate”.

No! I disagree.

If we can’t know an entity is valid anywhere we use it then we can’t afford to trust it. We end up with code where, before we use an entity, we go and check that it is in a suitable state for us. These ‘entities’ are just data structures. They are missing behaviour that enforces internal consistency.

So, how can we build entities in C# that are always valid?

  1. No public property setters. This stops the entity being used as a data structure. It is no longer possible to break the internal state of an entity by abusing setters.
  2. The instance constructor leaves the entity in a valid initial state. It sets sensible defaults for fields, it takes parameters to override defaults and  other parameters to provide values for fields with no sensible default.
  3. Entities are updated by a context-specific ‘command’ method that acts atomically on the instance.

Let’s rework Jeffrey’s UserProfile class to make it an always valid entity, assuming that:

  • The user’s Name must not be empty,
  • The Gender can be one of male, female or unknown.
  • The JoinedDate cannot be null, but can (for now) contain any valid date. You might argue that future dates should be invalid or that the JoinedDate be optional—let’s just ignore this at the moment; is is immaterial for this example.
  • The LastLogin must not be earlier than the JoinedDate.
    public enum Gender
    {
        Unknown = 0,
        Male,
        Female
    }
 
    public class User
    {
        private string name;
 
        public string Name
        {
            get
            {
                return name;
            }
            private set
            {
                if (string.IsNullOrEmpty(value))
                    throw new ArgumentNullException("Name");
 
                name = value;
            }
        }
 
        public Gender Gender { get; private set; }
        public DateTime JoinedDate { get; private set; }
        public DateTime? LastLogin { get; private set; }
 
        public User(string name, Gender gender, DateTime joinedDate)
        {
            Name = name;
            Gender = gender;
            JoinedDate = joinedDate;
        }
 
        public void UpdateProfile(string name, Gender gender)
        {
            Name = name;
            Gender = gender;
        }
 
        public void RecordLogin(DateTime loginTime)
        {
            if (loginTime < JoinedDate)
                throw new InvalidOperationException("loginTime cannot be earlier than JoinedDate");
 
            LastLogin = loginTime;
        }
    }

Whilst I personally wouldn’t want this code in production, lets look at what it has achieved.

  • Gender is an enumeration. This restricts us to valid values at compile time. However, we explicitly recognise a business requirement that the gender may not be known, rather than allow an indeterminate null state.
  • I prefer the entity name User rather then UserProfile. We are modeling a domain with Users. A user’s profile is the properties of the User entity. UserProfile screams data structure.
  • I’ve opted for automatic properties with private setters for most properties. This means the presentation layer can read my entity to create a View Model or for direct binding, but updates through properties are not possible.
  • Where I have an invariant I wish to enforce, I’ve opted to use the private property setter to enforce this. This is a compromise and we must trust our developers not to short-circuit the setter, either by malice or ignorance. This is a pretty weak form of validation (but good enough for this example). Bear with me, I’ll blog on this shortly.
  • ‘Command’ methods update the entity in a controlled manner. They return void. They have atomic behaviour, by which I mean a logical update is made in one call to the instance.
    • The business has asked that the user can update their profile. The name must not be empty.
    • The business also wants to record the last login time for users. Note that we aren’t using DateTime.Now here, as this has two shortcomings: it hurts testability and explicitly ties the time of the execution of the RecordLogin method to the time of the executing server. RecordLogin might be at the end of an message queue that processed the message minutes after the login actually occurs.
  • The constructor and the UpdateProfile method both use the Name setter and therefore the non-empty name invariant is enforced.
  • Note that users of NHibernate or other ORM frameworks might require a default constructor. If so make the accessability as restrictive as possible (that’s ‘protected’ for NH).
  • We can use a validation framework that implements a notify pattern (as in Jeffrey’s example) if we wish. I kept it simple for this example.

Given the rules above, it is not possible to get this entity into an invalid state. As for bulk loads and legacy data, this entity will insist that the external data is correct. Use a data cleansing tool to make sure the data meets your domain models requirements.

In my next post I’ll look at how to improve this code further through the use of value objects.
kick it on DotNetKicks.com

10
May
09

Firefox: Always restore your previous session without the prompt

I often shutdown my machine without closing Firefox. Next time I restart the browser it asks me if I want to resume the previous session.

I always want to restore as the first 5 or 6 tabs are my ‘always open’ apps (GMail, Google Reader, etc,). Clicking ‘Resume Previous Session’ all the time really hacks me off.

Now a bit of Googling turns up innumerable posts about disabling session restore so you always start a new session, but finding information about the opposite behaviour, i.e. always restoring the previous session (without asking) is much harder to find.

In order to raise the profile of this feature, I’m linking to the only other post I know about that talks about this. Ironically I only found this after browsing the source and ‘reverse engineering’ my Google query.

The solution is a bit of a hack as the behaviour I require isn’t directly supported. However Firefox allows extensions to override the default prompt and we can exploit this.

Head to about:config and create a string key ‘browser.sessionstore.restore_prompt_uri‘ and give it a value of ‘javascript:window.close();‘. This tell Firefox that a custom session restore prompt has been provided… which is immediately terminated.

Luckily the session restore code assumes that we want to restore unless the prompt returns otherwise and the net result is no prompt and automatic session restoration.

I hope this takes a little bit of friction out of your day.