Freigeben über


Intellisense : What properties are required?

Yesterday I was talking to a Simon, another super smart dev on the EF team, and he raised a big concern, one that I am sure you can all relate too:

We've all seen something like this:

Intellisense

And thought: "What is the bare minimum I can do here to save a Whatever ?"

This "What properties are required ?" problem is particularly tricky when working with database Entities, because very often lots of the properties are nullable or server generated, but intellisense provides no clues.

Now my conversation with Simon reminded me of a couple of posts about intellisense planning I wrote on my old blog.

The basic idea was writing code with the aim of streamlining the programmers intellisense experience.

So yesterday Simon and I started having a think, and realised that perhaps Intellisense planning is the answer to this "What properties are required ?" problem too.

In fact all you need to do is this:

1) Create an interface for each entity called something like IRequiredForX, and then add only the properties you need to that interface:

i.e. something like this:

public interface IRequiredForPerson
{
     string Firstname {get;set;}
     string Surname {get;set;}
     Gender Gender {get;set;}
}

2) Make your class implement that interface, and (this is the key piece) add a property to return itself cast to the interface:

public class Person: IRequiredForPerson
{
    public IRequiredForPerson Required
    {
        get { return this; }
    }

Now the programmer can use intellisense to see only what is required:

BetterIntellisense

This is the sort of thing you could easily do in partial classes that extend the classes the Entity Framework creates for you. In fact, you could even write your own CodeGen to do this for you.

Never underestimate the power of intellisense, it can make all the difference.

Nifty huh?

Thanks for the idea Simon.

PS:
In case you're wondering, no I haven't forgotten about my statement of intent! I am working through a big list of possible 'real world' applications at the moment.

Expect some action on that front soon...

Comments

  • Anonymous
    April 09, 2008
    Pretty nice! Thanks for the tip :)
  • Anonymous
    April 09, 2008
    Alex, I wonder if you might discuss why you chose person.Required to group the required properties, rather than say using person.Optional for optionals, thereby leaving required props at the root level and hiding the rest?I guess you could write an IOptionalForPerson in the same way as IRequiredForPerson, and require Person to implement both?
  • Anonymous
    April 09, 2008
    Well I suppose you could do that but, then you would have trouble filtering on the Optional Properties in LINQ. I.e.var f = from p in ctx.People       where p.Mother.Firstname == "Wendy"       select p;wouldn't be possible because Mother is optional and hence would be hidden...and this:var f = from p in ctx.People       where p.Optional.Mother.Firstname == "Wendy"       select p;Wouldn't work in things like Entities or Linq to Sql.And if you then said you would leave the optional properties on the root, you would be back at square one again!As for having both interfaces, I suppose that is an option but the question is it worth the hassle?Make sense?
  • Anonymous
    April 09, 2008
    Since the question begs to be asked, but hasn't been asked just yet: If these properties are required, why are you allowing the object to be constructed without them?I know that the Framework Design Guidelines suggest that one should use a "create-set-call" approach, but there are plenty of people who feel that "create-set-call" is actually an anti-pattern and that discussions/"solutions" like this are a smell.
  • Anonymous
    April 09, 2008
    I think it is a non-trivial practice. Do we really need to complicate the design and do an extra overhead for such questionable advantage? Usually I use BrowsableAttribute and EditorBrowsableAttribute, but this approach is not compatible with auto generated code.
  • Anonymous
    April 10, 2008
    The comment has been removed
  • Anonymous
    April 10, 2008
    Yup, I hear ya. What we need now is for the ORMs to jump onto parameterized constructors in a manner not unlike how the IoC containers did long ago. Doing so would let us start reducing the accessibility of default constructors and push people towards the instantiation of fully-formed objects.
  • Anonymous
    April 14, 2008
    Another option would be to create a static factory method named "CreateWithRequiredData" and have it take parameters for all of the necessary values.  The downside to the interface approach is hard to verify it's used correctly.  There is nothing stopping the user from only setting a subset of the data.  In addition as time goes on the values may be built up over a set of function calls making it difficult to verify the developer set all of the necessary values.Using a factory method allows to enforce that all values are present and makes the pattern extremely easy to grep for.