About the author

Steven Harmansteven harman :: makes sweet software with computers!

For recent posts and more about me, scroll to the bottom.

Subscribe

  • Subscribe to my feed. via RSS
  • Subscribe via email via email

News

Badges

  • Subtext Project
  • Support Subtext

A New Year's Resolution for Developers

Your Resolution this year should be:

If you aren’t sure, make it public... and make everything virtual (or overridable, depending on your language) by default.

Of course this primarily applies to those folks building frameworks for statically typed languages... <cough> Microsoft <cough>, but it also holds weight for the rest of us. After all, we all want other people to use our code - even if other people is your customers, your team, or yourself. The point is, we want our code to be (re)used.

And I don’t know about you, but I’d much rather use code that enabled me rather than code that was constantly getting in my way.

Sorry for the tangent, I seem to be doing that a lot lately. Darn, there I go again. Let’s get back on track...

Why public and virtual?

I think a short story explains it best... and Eilon Lipton, lead developer on the mvc.net offering, has just such a story. (emphasis mine)

Several weeks ago we invited several customers for a top secret sneak preview of the CTP, including the MVC framework. Jeffrey Palermo was attending and trying to build some samples with the MVC framework. [...] I sat with Jeffrey for about half an hour and we managed to use many of the extensibility points in the framework to work around the bugs he encountered. The whole time I kept thinking (and probably saying aloud) that I was so glad I made those methods public or virtual or whatever! Without them Jeffrey would have been stuck.

The moral of the story: If you aren’t sure, make it public. If we have to use a method, chances are, someone else does too.

Marking methods as public and virtual helps other help themselves when working with, or working around, your code. Don’t make the classic mistake of assuming you know every possible way in which your code will be used, because you don’t. You can’t!

Don’t forget testing

I’m a rabid fan of Rhino.Mocks and the power it brings my unit tests. And while being able to dynamically mock am interface is awesome in its own right, I think one of the nicest features of Rhino.Mocks is the ability to do partial mocking.

Partial mocks are useful when you want to mock a part of a class. This allows you to test abstract methods in isolation, for instance.

public-virtual-method Distilled, that it means that you can mock individual methods of a real, concrete, class while letting the other methods use their actual implementation. The only caveat is that it can only mock publicly available abstract or virtual methods.

So, as long as an object’s methods are marked as public and virtual you can dynamically override them in your unit tests. Doing so allows you to narrow the focus of your tests to just the behavior under test. This also often leads to shorter, more cohesive tests. :)

So remember, enable others to use your code by enabling your code from the start. Public and virtual are your friends... use them when you can. ;)

What others are saying.

# re: A New Year's Resolution for Developers
Gravatar Joe Brinkman
Dec 17, 2007
I would suggest that you would be well advised to read the framework design guidelines by Abrams and Cwalina. Specifically section 6.1.4. To summarize "DO NOT make members virtual unless you have a good reason to do so and are aware of all the costs related to designing, testing and maintaining virtual members"

When building frameworks, you must always keep in mind that you will have to live with Public and Virtual decisions for a long time. To the same degree that someone may need to use a Virtual method or public method for some purpose, you might have an equal requirement to change the implementation to fix some bug or provide some new feature. Compatability becomes much more difficult to maintain as the API gets larger.
# re: A New Year's Resolution for Developers
Gravatar Steve Horn
Dec 17, 2007
If you're putting your code in the hands of a stranger you gotta expect that they're going to pervert your logic to some degree. Keeping implementation details private protects the intent of the object's behavior.

Although I'm sure there are times when giving the consumer flexibility comes in handy.

I'm of the opinion that members and methods should be kept private by default unless you have a very compelling reason to open them further.
# re: A New Year's Resolution for Developers
Gravatar Steven Harman
Dec 17, 2007
@Steve Horn, I know where you're coming from, and to be honest I was of the same school of thought for a long time. Its totally sound reasoning as far as solid Object Oriented Design goes.

However, I'm also tired of coding with the kiddie gloves on. I'm a firm believer in giving sharp tools to sharp people. We need to stop trying to protect developers from them selves and instead empower them when we can and where it makes sense.

I'm certainly not saying that we should make _everything_ public and/or virtual, but rather that we shift our view. So rather than always assuming everyone is going to do something stupid or harmful, assume the consumer of your code has a brain and is capable of doing something smart.

Keep up with the feedback... I like hearing other's thoughts and opinions and love the discussion! :)
# re: A New Year's Resolution for Developers
Gravatar Steven Harman
Dec 17, 2007
@Joe, Thanks for the advice... and believe it or not I've actually read much of the guide.

However, one thing to remember - these are guidelines, not hard and fast rules.

OK, OK... I know that's a cop-out. :)

But in all seriousness I understand your point about the longevity of decisions made around the API of a framework. That said, I'm not willing to say that just b/c you might (and in all likelihood will) need to change your code down the road that you should lock everything down in hopes of avoiding future change.

Yes, maintaining a large API is tough and not for the faint of heart. But if it's wrong it's going to need to change anyhow.

And while the consumer of your API shouldn't be relying on any specific implementation details... making a method private vs. protected vs. public won't change the fact that they can, especially in the .NET world. (Hello Reflector!)

Btw... you going to be at CodeMash this year? If so what do say we get another "Developing Open Source Software on .NET" open spaces event together?
# re: A New Year's Resolution for Developers
Gravatar Damien Guard
Dec 18, 2007
This was one of my biggest disagreements with Code Complete which also advocated marking everything internal/private/sealed.

I agree that a class should be robustly designed for use... but open and breakable for reuse.

In other words if you inherit from an object you personally take responsibility for keeping the contract enforced - not the original class designer.

For some time I've been thinking much of .NET Framework could do with a advanced, extensible and powerful classes, perhaps in a separate assembly, that are normally then exposed through simple-use facade's.

That way when you need more than the typical Facade has to offer you can switch to the advanced building-blocks they use too.

[)amien
# re: A New Year's Resolution for Developers
Gravatar Joe Brinkman
Dec 18, 2007
My experience comes from years of supporting DotNetNuke where almost everything was public. There are many places in DotNetNuke where that has limited our ability to add new features because to do so would break an existing API, even though it was never our intent to support that API. Someone made the method public and now we are stuck with it. In this day and age, with more frequent releases, and agile approaches, it is easier to open up an API if needed than it is to work around a broken API that should never have been public to begin with. Your users will forgive you for making them wait a release to get an method made public, but they take a very dim view of breaking changes.
# re: A New Year's Resolution for Developers
Gravatar Steven Harman
Dec 18, 2007
@Joe,
In this day and age, with more frequent releases, and agile approaches, it is easier to open up an API if needed than it is to work around a broken API [...] users will forgive you for making them wait a release to get an method made public, but they take a very dim view of breaking changes


Surely you are speaking of some foreign and futuristic world where all development shops, especially those headquartered along the North-Western U.S. Seaboard, have taken on agile methodologies. ;)

I kid, I kid... well I half kid anyhow.

I think there is a bit of an impedance mismatch going on here:

a) The applications that you and I, and many of our colleagues, develop have rather short release cycles and we're fairly adaptive to change.

b) The technology stack that many of us rely, .NET, is far less agile and it's often years between major revs. During all of that time we're often forced to use a API that is broken and/or working against us because of the pessimistic gotta-protect-the-developer-from-himself view that caused the API to be so restrictive to begin with.

But in the end, I'm pickin' up what you're puttin' down... I just hate it when I get bit by such decisions and I long for the power and flexibility that a dynamic language might offer me.

Ruby (and Python) on the CLR, FTW!
# re: A New Year's Resolution for Developers
Gravatar Joe Brinkman
Dec 21, 2007
@Steve - The difference between APIs which have short release cycles and those like .Net which have long release cycles is that with those long release cycles comes long CTP/Beta/RC periods during which time we should be excercising the API to make sure it really provides the needed extensibility points. Do you honestly believe that if Eilon and Jeff couldn't have made the extensibility model work, that it wouldn't have been fixed by the release date?
# re: A New Year's Resolution for Developers
Gravatar Steven Harman
Dec 21, 2007
@Joe, Umm... exactly what extensibility points are you talking about?

Have you ever tried to extend, test, or mock the ASP.NET runtime? It's a freaking nightmare because everything is private, protected, sealed, internal, non-virtual, etc...

Even with the help of tools like DuckTyping.Net we've got to jump through all kinds of hoops just to eek some testability out of the Request and Response objects. Think about how much easier that would have been if those objects had exposed some public virtual methods.

I'm just sayin'. :)

At any rate, I didn't mean for this post to devolve into a .net-bashing-rant... I'd have posted to altnetconf if I wanted that. So I apologize.
# re: A New Year's Resolution for Developers
Gravatar Steven Harman
Dec 21, 2007
Oh, and to clarify... when I'm picking on the ASP.NET runtime I'm really talking about everything up to and including .net 3.5. However, it seems the MVC team has finally gotten a handle on the problem (Thanks ScottGu, Eilon, Phil, etc...) as they are providing interfaces for nearly everything.

I for one welcome our new Interface-based overlords - IHttpRequest, IHttpResponse, IHttpContext, IHttpServerUtility, and IHttpSessionState.
# re: A New Year's Resolution for Developers
Gravatar Jim Holmes
Dec 23, 2007
(Finally catching up on blog reading...)

One part of me (the testing geek), is all over the Everything Public aspect. The rest of my brain falls into Scott Meyers' and others' view of make something easy to fall in to and hard to climb out of.

Meaning, make it easy for your API's consumers to use it right, and make it hard for them to use it wrong. Expose a small bit of functionality and don't give your API's consumers the easy ability to misunderstandimate how to use your bits. Which of those six methods do I need to call first? Which of those methods have dependencies on something else having occurred first?

I think enabling everything to be extended or overwritten carries its own risks for the same set of reasons.

Additionally, Joe's points about breaking changes are well-made, IMO.

At the very least, if you're going to make everything public and virtual, then you should provide some sort of a service wrapper or facade that clearly and cleanly exposes the proper usage of the underlying classes/methods.

This all falls into the great ongoing discussion on designing for testability. What's the right balance between testability and correctness of use? Dunno. I ain't smart enough to answer that...
# re: A New Year's Resolution for Developers
Gravatar Krishna Reddy Yerram
Dec 31, 2007
Wish you happy new year 2008.
Wish you happy coding with visual studio 2008..
# 
Gravatar CodeThinked
Feb 27, 2008
To close or not to close, that is the question.
Comments have been closed on this topic.