properties vs. fields… again


Eric Gunnerson just posted Properties vs public fields redux… It’s no secret that I agree with Eric whole-heartedly on this matter.  I’ve posted about this before as well: http://blogs.msdn.com/jaybaz_ms/archive/2004/04/29/123333.aspx.  Fundementally, the problem is one of “speculative generality”, where you are writing code today that has no use, because you think that it might be needed sometime in the future.  Of course, since you can’t predict whether it will be used, and you can’t predict how it will be used, your guesses are wrong most of the time.  That is, most public properties are trivial forever.


It’s interesting that the strongest objection some people have is that it requires a rethinking of some of the common naming conventions to adjust appropriately.  Such a minor issue, and so easily resolved.


Since my original post, I’ve come across a couple other reasons why the “always use properties” guidance is broken.  Specifically, if you are correct that you may need to maintain binary compatibility while changing implementation, then you’ll probably need it in other places:


1. Constructors lock you in to a type. If you really want binary  compatibility, you should stop providing ctors, and start providing factory methods:


    public class MyClass


    {


        MyClass() { }


        public static MyClass New() { return new MyClass(); }


    }



The purpose, of course, is to allow you to return a different object type that derives from MyClass in the future, while maintaining binary compatibility.


2. Types lock you in to a type.  If you really, really want binary compatibilty, you should stop providing types at all, and start dealing only with interfaces:


    public interface IMyInterface


    {


        void F();


    }


 


    public class MyClass : IMyInterface


    {


        MyClass() { }


 


        public static class Factory


        {


            public static IMyInterface New() { return new MyClass(); }


        }


 


        void IMyInterface.F()


        {


            // …


        }


    }


 



Now, I look at this code, and I think I’m writing a lot of lines for nothing.  That is, in my domain, this kind of generality is unnecessary.  That’s why I don’t generally use factories, interfaces, or properties.  I consider them to be kin. 


There are probably some other constructs that go along with these, for speculative generality.  These are just the 2 that come to mind.


If you still believe that you need to use properties in the trivial cases, I hope you will examine these constructs and consider them seriously in your own code.  I suspect you should be choosing all or nothing.

Comments (6)

  1. Miral says:

    The factory should probably be a standalone class, rather than a subclass of MyClass.  Then you can make the factory public and MyClass private, and then you’re free to do whatever the heck you want with MyClass (including renaming it or deleting it).

    At least as long as it’s not binary serializable, anyway.

  2. MSDNArchive says:

    Good call, Miral.

    This all fits in to the more general statement of "future proofing is hard". 🙂

  3. Bjørn Reppen says:

    Hooah!  The world is sane after all.

    Thanks man. Great post.

  4. I have to write too much code for my code to be future proof so therefore I write non future proof code because I have the foresight to see the future for this code?!?

    Or alternatively, you gamble on the odds of needing future proof code.

    Why can’t we have a language where we can write   simple code that is future proof?

    Then we don’t need to have these daft arguments about "good" code design / rules.

    I think its worth remembering these aren’t good design principles, these things are "hacks" around language difficulties.  Don’t get me wrong, It’s not that these ideas are without merit, they certainly help you work within the bounds of C#, but its worth keeping it in mind that they are simply hacks and the "rules/guidance" would disappear if the language allowed you to express what you wanted.

  5. Jeremy says:

    “Constructors lock you in to a type. If you really want binary  compatibility, you should stop providing ctors, and start providing factory methods:”

       public class MyClass

       {

           MyClass() { }

           public static MyClass New() { return new MyClass(); }

       }

    You don’t need to do this.  Just use Constructor Injection to push in IMyClass instances into the dependent classes, then use an IoC tool if you want to do the mechanical work.

    You’ll end up with potentially more flexibility without having to go out of your way when you’re building classes.