While the described problem is objectively real, this is, overall, an emotional rant. Adjust expectations & interpretation accordingly.
It started with Microsoft .NET’s MVC model binding (if you don’t know what model binding is, here is a short and simple explanation). Localization in a business application is not a luxury, or an extra, it is a fundamental, non-negotiable requirement. Do you know how to localize the error message that .NET’s DefaultModelBinder throws if you enter “Owl” in a text field that’s bound to an int? No, you don’t, and good luck finding out. If you dig deep enough in the source code for DefaultModelBinder, you will find the magic string that you need to put in your resources to make it work. Oh, you also wanted to localize the error message for when the value is missing (null) for a non-null variable? Dive right back in and look for the other magic string.
Mind, these are not some 1% edge cases, missing and wrong values are one of the most common errors in web data input. And if you want the error messages to say anything other than the default English text, you need to hunt through the source code for a hard-coded magic string that you then have to put in your resource (eliminating any custom localization mechanisms that don’t rely on the resource provider pattern). That’s not even insane, that’s just evil.
“Oh, I know”, you say, “I’ll just extend & override …” No. You will not. Because the part that generates the error message is buried so deep inside non-virtual and private methods that if you try, you will end up either giving up and wrangling with the resources, or giving up and re-writing the whole ModelBinder (or using mine, once I finish it and put it up on GitHub & NuGet) just so that you would have something that can actually be extended where it matters. And, quite possibly, murdering some kittens, in which you would be totally justified at that point.
Then came HtmlTags from the FubuMVC project. It’s a beautiful, elegant little library for generating HTML tags and passing them around as objects, thus allowing further modification by other parts of the code before output. This is opposite of the .NET’s MvcHtmlString, which is just that — a string (that’s protected from double-encoding).
And I was happily using it for a while, until I stumbled upon a seemingly trivial need that turned out to be an insurmountable challenge. What was this decadent, arrogant and completely unreasonable demand that I had the gall to expect from this humble little piece of code? I wanted *two* tags. Specifically, I wanted to take a HtmlTag and make a copy of it. And again, my evening was filled with one “can’t” after another. I can’t Clone() it because it’s not ICloneable. I can’t use a constructor that takes another HtmlTag and creates a copy of it, because there is no such constructor. I can’t use AutoMapper, because the tag’s attributes are of type HtmlTag.HtmlAttribute, which is a private class. And I can’t extend and override it because everything that isn’t already public, is private.
Why? Why do good programmers hate other programmers so much? I understand that making convenient extensibility points isn’t trivial, but what’s wrong with “protected”?
You know what? I’m just going to shortcut all this and declare — “private” is evil. “sealed” is evil. Unless you have a nuclear-bunker-rock-solid reason, every time I see “private” in someone’s code I will read it as “I hope whoever uses this gets cancer and dies”. Because that’s how it feels. Declaring private members in your code feels like you’re wishing cancer on me.
Please, “public/protected virtual” everything by default.