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: https://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

  • Anonymous
    February 08, 2007
    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.

  • Anonymous
    February 08, 2007
    Good call, Miral. This all fits in to the more general statement of "future proofing is hard". :-)

  • Anonymous
    February 08, 2007
    Hooah!  The world is sane after all. Thanks man. Great post.

  • Anonymous
    February 11, 2007
    The comment has been removed

  • Anonymous
    February 20, 2007
    http://codebetter.com/blogs/jeremy.miller/archive/2007/01/08/Orthogonal-Code.aspx http://codebetter.com/blogs/jeremy.miller/archive/2006/12/06/On-Writing-Maintainable-Code.aspx

  • Anonymous
    February 20, 2007
    "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.