Update: I accidently published an old draft of this. Sorry about that.
One thing that gets a lot of debate in .NET is Sealed Classes.
Nick Hodges just posted More on Sealed Classes. He says they are "irritating and silly". Do sealed classes serve a purpose beyond annoying developers? How much of the .NET Framework is sealed? Is the sealing justified?
In object orientated programming (OOP) a developer can extend a class created by another developer adding additional functionality. This functionality can be to create a more specialized version of the class, or to add more generally useful functionality that the original developer didn't think of. Either way, this ability to reuse and extend is a great advantage of OOP. There are things a developer can do to make it easier to extend their base class, like declaring a method virtual to allow future versions to override that behavior.
This functionality of OOP is actually similar to what has been going on in botany and agriculture for ages. Seeds are planted, and when the plants come to maturity they produce new seeds. The seeds of the best plants are then taken and replanted. This selection of only the best plants by the farmer / botanist is similar to a programmer extending a class, except it is done through natural genetic variations. The farmer just chooses which of the variations is most desirable and re-uses those seeds. You see the same thing in animal husbandry too.
Along comes .NET with its sealed class. When a class is sealed then future developers are prevented from extending the base class defined by the original developer. So if a developer wants to create a more specialized version of a class, or add functionality not conceived of by the original developer they are out of luck. Instead they must recreate all the original functionality of that base class, or create a helper class which performs the new functionality on the base class. Both options are less then optimal.
Unfortunately many of the classes in the .NET framework are sealed. Just within the System namespace and mscorlib assembly (the main part of .NET CLR) there are well over 300 sealed classes. (If someone else has better data please let me know!) That is compared to just over 450 public classes. Almost half (40%) of the classes are sealed. Many developers complained about all the sealed classes. It seemed like every time a developer wanted to extend a class they only discovered it was sealed.
Again we can compare this to field of botany. Monsanto is a company that makes specialized and engineered seeds. They were researching what they called the "terminator gene." Any seed that contained this gene would grow a plant like normal, but any seeds that plant produced would be sterile and would not grow. This would prevent any farmers from leveraging their crop for future crops. When the public discovered their plans there was a huge outrage. In India, where Monsanto was testing crops, the local villagers would sneak onto the field and burn the entire crop. Eventually Monsanto announced that they would not include the terminator gene.
Many developers complained about the sealed classes. It was hoped that Microsoft would feel the pain of the developer community and unseal many of the classes in the .NET 2.0 release. Unfortunately the number of public sealed classes jumped to well over 500 in .NET 2.0
(Beta 2). When we compare this to the number of public classes we see the gap narrowing as there are only just over 600 of those. Putting sealed public classes at 45%, an
approximate 5% increase over .NET 1.1. So instead of improving the situation things only got worse.
So why would Microsoft want to seal their classes and stifle the ability of developers to innovate and leverage the the framework? Consulting
The C# Programming Language by Anders Hejlsberg, Scott Wiltamuth and Peter Golde (Anders lead the team to develop C#) it says the following about Sealed Classes (page 275):
10.1.1.2 Sealed Classes
The sealed modifier is used to prevent derivation from a class. [. . .]
The sealed modifier is primarily used to prevent unintended derivation, but it also enables certain run-time optimizations. In particular, because a sealed class is known to never have any derived classes, it is possible to transform virtual function member invocations on sealed class instances to nonvirtual invocations.
So sealing a class can provide some performance enhancements when a class has a number of virtual methods. It would seem if that is the case then a well designed framework would have a sealed version of classes that did not introduce any functionality over the non-sealed ancestor, but only provided a sealed version for speed. Then future developers could leverage all the functionality by descending from the non-sealed ancestor, later creating a sealed version of their derived class for the speed improvement.
This would be similar to how Borland designed the VCL. There is a "Custom" version of each control. The Custom version has all the properties as protected. Then there is a version that descends from the Custom version that only publishes the necessary properties. Then if
someone wants to expand on the control they simple descend from the Custom
version and they can then choose which properties to make public (this is
significant since it is a hack to un-publish a published property, and you
cannot move something to a lower visibility level (e.g., move from Public to
Protected).
I wonder what advice
Krzysztof Cwalina and
Brad Abrams (who are involved with the internal .Net framework design at Microsoft) have to say about the use of sealed classes. If we look in their book
Framework Design Guidelines under the section on sealed classes (6.4 on page 174 - 177) we see the following:
DO NOT seal
classes without having a good reason to do so.
Sealing a class because you cannot think of an extensibility scenario is not a good idea. [. . .]
Good reasons for sealing a class include the following:
- The class is a static class. [. . .]
- The class stores security-sensitive secrets in inherited protected members.
- The class inherits many
virtual members and the cost of sealing them individually would outweigh the benefits of leaving the class unsealed.
- The class is an attribute [. . .]
In the book Brad also points out the advantages of an open and customizable framework over the Win32API where there is no ability to extend an API call. In a discussion on
Designing .NET Framework Class Libraries Krzysztof also said "The general guidelines say not to seal types but rather try to seal individual (all) methods."
Brad also published portions of the
internal Design Guidelines document to his blog, where it says the
following:
FxCop Rule (draft): Flag non-sealed public types that introduce virtual
members with the message: "Virtual members represent points of
specialization in your type. Great care should be taken in exposing virtual
members, please see the design guidelines document on this topic and fully
consider the ramifications."
It goes on to basically to encourage sealing to prevent extensibility.
So it encourages a non-extensible framework. This seems to fly in the face
of the advice given in the book that says "Sealing a class because you cannot
think of an extensibility scenario is not a good idea."
Monsanto claimed similar reasons to include the terminator gene. If one of their genetically modified strains was to cross with another strain then the results could be
undesirable and at least unexpected. By ensuring that all genetically modified plants cannot reproduce then they eliminate this
possibility. The other reason was that it protected the intellectual property of the companies engineering improved seeds. By protecting their intellectual property it would encourage greater innovation which benefits everyone.
Since Microsoft did not adopt the obvious course of action of only sealing classes that do not introduce new functionality
therefore providing the speed boost of a sealed class without the restriction then we must assume speed was not their primary motivator. Should we then assume that it was for security? Is this part of their move to more secure code?
My opinion is that Microsoft sealed classes because they could, and not
because it was a good idea.
Subject Tags:
[Microsoft]
[DotNet]
[CSharp]
[Programming]
[Software]
[Sealed Classes]
[Framework]