<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Fabulous Adventures In Coding : Brittle Base Classes</title><link>http://blogs.msdn.com/ericlippert/archive/tags/Brittle+Base+Classes/default.aspx</link><description>Tags: Brittle Base Classes</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Future Breaking Changes, Part Three</title><link>http://blogs.msdn.com/ericlippert/archive/2007/09/04/future-breaking-changes-part-three.aspx</link><pubDate>Tue, 04 Sep 2007 17:30:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:4653830</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>21</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/4653830.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=4653830</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;As I said &lt;A class="" href="http://blogs.msdn.com/ericlippert/archive/2007/08/31/future-breaking-changes-part-two.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2007/08/31/future-breaking-changes-part-two.aspx"&gt;earlier&lt;/A&gt;, we hate causing breaking changes in our product, the C# compiler, because they cause our customers pain.&lt;/P&gt;
&lt;P&gt;Said customers are also software developers, and presumably they hate causing breaking changes for their customers as much as we do. We want to throw our customers into the &lt;A class="" href="http://www.codinghorror.com/blog/archives/000940.html" mce_href="http://www.codinghorror.com/blog/archives/000940.html"&gt;Pit of Success&lt;/A&gt; and give them tools which encourage them where possible to prevent breaking changes. This leads to some subtle issues in language design.&lt;/P&gt;
&lt;P&gt;Pop quiz. What does this program do?&lt;/P&gt;
&lt;HR&gt;
&lt;SPAN class=code&gt;// Alpha.DLL&lt;BR&gt;namespace Alpha {&lt;BR&gt;&amp;nbsp; public class Charlie {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void Frob(int i) { System.Console.WriteLine("int"); }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // etc.&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;} 
&lt;HR&gt;
// Bravo.EXE, references Alpha.DLL.&lt;BR&gt;namespace Bravo {&lt;BR&gt;&amp;nbsp; public class Delta : Alpha.Charlie {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void Frob(float f) { System.Console.WriteLine("float"); }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // etc.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static void Main() {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Delta d = new Delta();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; d.Frob(1);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp; }&lt;BR&gt;} 
&lt;HR&gt;
&lt;/SPAN&gt;
&lt;P&gt;Most people look at this program and say “clearly &lt;SPAN class=code&gt;Charlie.Frob(int)&lt;/SPAN&gt; is the best possible match for the call, so that is called.” A compelling argument, but wrong. As the standard says, “methods in a base class are not candidates if any method in a derived class is applicable". &lt;/P&gt;
&lt;P&gt;In other words, the overload resolution algorithm starts by searching the class for an applicable method. If it finds one then all the other applicable methods in deeper base classes are removed from the candidate set for overload resolution. Since &lt;SPAN class=code&gt;Delta.Frob(float)&lt;/SPAN&gt; is applicable, &lt;SPAN class=code&gt;Charlie.Frob(int)&lt;/SPAN&gt; is never even considered as a candidate. Only if no applicable candidates are found in the most derived type do we start looking at its base class.&lt;/P&gt;
&lt;P&gt;Why on earth would we do that? Clearly in this example the base class member is the far better match, so why wouldn’t we even consider it?&lt;/P&gt;
&lt;P&gt;It is instructive to consider what happens in a world where we do implement the rule “pick the best applicable candidate from any base”. Suppose we did that. &lt;/P&gt;
&lt;P&gt;In the previous version of Alpha.DLL, &lt;SPAN class=code&gt;Charlie&lt;/SPAN&gt; did not have a method &lt;SPAN class=code&gt;Frob(int)&lt;/SPAN&gt;.; When Bravo Corporation wrote Bravo.EXE, every call inside class &lt;SPAN class=code&gt;Delta&lt;/SPAN&gt; to method &lt;SPAN class=code&gt;Frob&lt;/SPAN&gt; was a call to &lt;SPAN class=code&gt;Delta.Frob(float)&lt;/SPAN&gt;. Then one day Alpha corporation did customer research and discovered that a lot of their customers like to frob integers. They added this feature in their latest version. Delta corporation gets the new version of Alpha.DLL, recompiles Bravo.EXE, and suddenly their carefully developed code is sometimes calling a method that they didn’t write, which does something subtly incompatible with their implementation. &lt;/P&gt;
&lt;P&gt;Alpha corporation has just pushed a breaking change onto Bravo corporation, which, if they don’t catch it in time, may now be pushing a subtly broken version onto their customers in turn, and hey! we’re in the Pit of Despair again!&lt;/P&gt;
&lt;P&gt;This particular family of breaking changes is called the "brittle base class problem"; there are many versions of it and &lt;A class="" href="http://blogs.msdn.com/ericlippert/archive/2004/01/07/48399.aspx" mce_href="http://blogs.msdn.com/ericlippert/archive/2004/01/07/48399.aspx"&gt;different languages deal with it in different ways.&lt;/A&gt; Lots of work went into the design of C# to try and make it harder for people to accidentally cause brittle base class problems. That is why we make you distinguish between the&amp;nbsp;original definition of a virtual method and an overriding method. That is why we make you put “new” on methods which shadow other methods. All these semantics are in part to help prevent, mitigate or diagnose brittle base class issues and thereby prevent accidental breaking changes in C# code.&lt;/P&gt;
&lt;P&gt;Next time on FAIC: some psychic debugging. Then a bit later I want to talk more about breaking changes, this time in the context of thinking about covariance and contravariance.&lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=4653830" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Breaking+Changes/default.aspx">Breaking Changes</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Brittle+Base+Classes/default.aspx">Brittle Base Classes</category></item><item><title>Virtual Methods and Brittle Base Classes</title><link>http://blogs.msdn.com/ericlippert/archive/2004/01/07/virtual-methods-and-brittle-base-classes.aspx</link><pubDate>Wed, 07 Jan 2004 23:28:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:48399</guid><dc:creator>Eric Lippert</dc:creator><slash:comments>10</slash:comments><comments>http://blogs.msdn.com/ericlippert/comments/48399.aspx</comments><wfw:commentRss>http://blogs.msdn.com/ericlippert/commentrss.aspx?PostID=48399</wfw:commentRss><description>&lt;DIV class=mine&gt;
&lt;P&gt;Hey, I'm back! And in my new location. 
&lt;P&gt;That was the longest and least relaxing vacation I've ever taken. Fun, yes. Relaxing, no. And to top it off, my kitchen is not done yet. We're shooting for being able to run water tonight and actually use appliances by tomorrow night, but we'll see how it goes. 
&lt;P&gt;Well, enough chit-chat. I wanted to talk a little about the brittle-base-class problem, and how JScript .NET deals with it. 
&lt;P&gt;&lt;U&gt;Virtual Methods and Brittle Base Classes&lt;/U&gt; 
&lt;P&gt;One of the challenges inherent in writing larger programs is managing change over time. Few large programs are written once and never updated. Usually new features are implemented for new versions. Class-based programming allows for clean, object-oriented design but there are still some pitfalls to be wary of. One of the more insidious object-oriented programming pitfalls is the &lt;B&gt;brittle base class problem&lt;/B&gt;. Here's how it usually goes: 
&lt;P&gt;You develop a very useful class for version one of your project. You have a "gadget" which can be "confusticated": 
&lt;P&gt;&lt;SPAN class=code&gt;// Project Juliet Version 1 &lt;BR&gt;class Gadget { &lt;BR&gt;&amp;nbsp; public function confusticate() { // . . . &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;Some coworkers working on another application at your company realize that their "widgets" are a special case of your gadgets, so they subclass. After all, code re-use is one of the benefits of object-oriented programming. These particular widgets need to be "garbled", so they add a new method: 
&lt;P&gt;&lt;SPAN class=code&gt;// Project Romeo Version 1 &lt;BR&gt;class Widget extends Gadget { &lt;BR&gt;&amp;nbsp; public function garble( ) { // . . . &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;A widget is confusticated the same as a gadget, thus they do not override the &lt;SPAN class=code&gt;confusticate&lt;/SPAN&gt; method. They get your library, compile up their code, test everything out and it is all good. 
&lt;P&gt;Six months after version one of your project ships you are hard at work developing the next version. In this version you have decided that gadgets can be garbled too. Furthermore, you decide that any confusticated gadget needs to also be garbled, so you modify your sources: 
&lt;P&gt;&lt;SPAN class=code&gt;// Project Juliet Version 2 &lt;BR&gt;class Gadget { &lt;BR&gt;&amp;nbsp; public function garble() { // . . . &lt;BR&gt;&amp;nbsp; public function confusticate() { &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; this.garble(); &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // . . . &lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;You have no idea that your coworkers have extended your class and already added a method to garble a widget. Furthermore, &lt;B&gt;they do not necessarily know that you have changed the base class.&lt;/B&gt; That could be a very small change amongst thousands of lines of code and many other changes. Now what happens when they call &lt;SPAN class=code&gt;confusticate&lt;/SPAN&gt; on one of their widgets? The base class's &lt;SPAN class=code&gt;confusticate&lt;/SPAN&gt; method is called, but because &lt;SPAN class=code&gt;garble&lt;/SPAN&gt; is virtual it then calls the derived class's &lt;SPAN class=code&gt;garble&lt;/SPAN&gt; method. 
&lt;P&gt;There are two ways that could be seriously wrong. First of all, you might have implemented the base class fully expecting that the &lt;I&gt;gadget&lt;/I&gt; garbling method would be called upon confustication, but now the &lt;I&gt;widget&lt;/I&gt; garbling is performed. Second, &lt;B&gt;the widget implementers have no idea that confusticating can cause garbling.&lt;/B&gt; From their perspective the only code that can call &lt;SPAN class=code&gt;garble&lt;/SPAN&gt; is &lt;I&gt;their&lt;/I&gt; code! &lt;B&gt;As far as they know they are the only ones who have written a garbling method.&lt;/B&gt; 
&lt;P&gt;"Base" classes are well-named -- the behaviour of the derived classes depends upon the base classes having rock-solid behaviour. If the base class implementations are brittle, then the derived classes will not be robust either. This is just one brittle base class scenario; there are many variations on this scenario. 
&lt;P&gt;One way to prevent the brittle base class problem is to use assembly manifests and config files to ensure that you always bind against the version you tested against. But in the spirit of providing the flexibility of multiple solutions, JScript .NET also affords some techniques to mitigate the rittle base class problem. 
&lt;P&gt;&lt;U&gt;Trapping the Error: The Versionsafe Switch&lt;/U&gt; 
&lt;P&gt;The lesson here is that every time you change a base class you have to test not only the base class but every single derived class. There really is no getting around that fundamental fact but there is a tool which can help in this particular situation. If you run the JSC compiler with &lt;SPAN class=code&gt;/versionsafe&lt;/SPAN&gt; then the potential disaster described above will not be &lt;I&gt;averted&lt;/I&gt; but it will at least be &lt;I&gt;brought to your attention&lt;/I&gt;. Specifying this flag makes it illegal to make a virtual function by accident. In other words, it changes the default behavior from "make a function with the same signature as a base class function an overriding virtual function" to " make a function with the same signature as a base class function an error." 
&lt;P&gt;That means that when the people working on Project Romeo version 2 go to compile up the Widget class using the new &lt;SPAN class=code&gt;Gadget&lt;/SPAN&gt; they will &lt;I&gt;immediately&lt;/I&gt; get an error. You have added a &lt;SPAN class=code&gt;garble&lt;/SPAN&gt; method which matches the signature in a base class and they must therefore explicitly say whether their matching method is a virtual (override) or a non-virtual (hide) method. Which solution is correct depends on the semantics of all the interacting methods; the point is to flag the potential problem automatically rather than using a default behavior which might be incorrect. 
&lt;P&gt;&lt;U&gt;Preventing the Subclassing&lt;/U&gt; 
&lt;P&gt;The crux of the brittle base class problem is that the providers of the base and derived classes each have no idea what the other is doing. It is extremely annoying to have bugs crop up that seem to be in your code because someone else did a poor job of writing a subclass. It is possible and indeed highly desirable to simply not let anyone subclass your classes without a compelling reason. 
&lt;P&gt;The attribute &lt;SPAN class=code&gt;final&lt;/SPAN&gt; is used to indicate that a class may not be subclassed in JScript .NET: 
&lt;P&gt;&lt;SPAN class=code&gt;final class Gadget &lt;BR&gt;{ /* . . . */ } &lt;/SPAN&gt;
&lt;P&gt;Now when your coworkers try this, they get an error: 
&lt;P&gt;&lt;SPAN class=code&gt;class Widget extends Gadget // Error, Type Gadget may not be extended &lt;BR&gt;{ /* . . . */ } &lt;/SPAN&gt;
&lt;P&gt;It might be the case that you do want &lt;SPAN class=code&gt;Gadget&lt;/SPAN&gt; to be extendible but do not want a particular method to be overridden. To do this you can make individual functions final: 
&lt;P&gt;&lt;SPAN class=code&gt;class Gadget { &lt;BR&gt;&amp;nbsp; final public function Garble() { // . . . &lt;BR&gt;} 
&lt;P&gt;class Widget extends Gadget&amp;nbsp;{&amp;nbsp;// OK, Gadget is not final&amp;nbsp;&lt;BR&gt;&amp;nbsp; override public function Garble() { // Error, Garble is final &lt;/SPAN&gt;
&lt;P&gt;Note that &lt;B&gt;it is legal to &lt;I&gt;hide&lt;/I&gt; a final base class method&lt;/B&gt;. It is only illegal to &lt;I&gt;override&lt;/I&gt; a final base class method. 
&lt;P&gt;Another technique would be to use inheritance demands, but that's a topic for another day. &lt;/P&gt;&lt;/DIV&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=48399" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/ericlippert/archive/tags/JScript+.NET/default.aspx">JScript .NET</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/JScript/default.aspx">JScript</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Scripting/default.aspx">Scripting</category><category domain="http://blogs.msdn.com/ericlippert/archive/tags/Brittle+Base+Classes/default.aspx">Brittle Base Classes</category></item></channel></rss>