Do not use private if you write frameworks

Posted: June 24, 2010 in candlepin, geek stuff, work

If you write a framework, please do not use private. You may think that you know how I am going to use it. I promise, if it works as it should I will not try and override the basic functionality. However, if I am looking at the code to know it is private then I have a use case you did not expect.

My current example is rails active resource. This is a great framework if you are planning to use it to talk to another rails app. If your url does not end in .json then you have to override / reimplement many high level methods because of one or two private methods.

I know they teach you this in school. I know it makes you feel smart. Stop it. Private methods makes your frameworks less usable and less extensible.

  1. Juank says:

    Thats why you should always implement an architecture based on interfaces…. period.

  2. Ddd says:

    Errm… Private is for stuff that isn’t guaranteed to stay the same for future versions. If you don’t mind that, then go for it!

    you can always define your own headers and force a cast…

  3. David says:

    Alternatively, one writes code such that all code normally marked private is made public (or even protected), and it is impossible to change anything for the next release, be it to fix bugs or add new features. (Or the framework changes things in spite of that, and then you complain that your code broke.) You may think that overriding some method does what you want now, but the author never guaranteed that method would be called as a hook in the contexts you wanted, and the next release could very easily change that.

    Don’t confuse encapsulation and well-designed interfaces. If you find yourself needing to alter a private method, it’s a sign that the framework’s interface was poorly designed, not that the framework shouldn’t have labelled something private.

  4. brabuhr says:

    If you really do know better than the author ;-), Ruby has your back:

    class A
    def one; 1; end
    def two; 2; end
    def three; 3; end
    private :two
    #=> A
    a =
    #=> #
    #=> 1
    #NoMethodError: private method `two’ called for #

    # from (irb):10
    # from :0
    #NoMethodError: private method `three’ called for #

    # from (irb):11
    # from :0
    class A
    public :three
    #=> A
    #=> 3

  5. Jeff says:

    I have to disagree. If I were writing a framework and left everything public, I’d expect a zillion questions from frustrated users who hung themselves by accessing members that should have been private. When they see that they’re public, they assume they can mess with it, and for good reason.

    You’re using the framework in a way that the developer hadn’t intended. He has no way of knowing whether your way of using it will blow up in your face or not. For encapsulation purposes he should assume it will, and keep you from shooting yourself in the foot.

    I always thought that either a) you are a user and you accept the framework as-written because you don’t know it well enough to screw with it, or b) you know it well enough and you screw with it by forking the source.

    Can you tell I’m a QA guy?

    • bryankearney says:

      My issue is this.. subsclass is a “Is A” relationship. If the parent can do it, so should the child. If you want to hide it, model it so you are not subclassing. The issue I had was trying to get Ruby Active Resource to talk to a non ruby back end. Everything was public except for one line where the url is constructed. If they wanted to protect me from it.. they would have set up a service I could call or not.

  6. mpdehaan says:

    I can see why you are now a manager.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s