On Designing Good Libraries — Part IV


size=2>As
always, comments welcome!


size=2> style="FONT-WEIGHT: bold; FONT-SIZE: 10pt; FONT-FAMILY: Arial"> 


size=2> style="FONT-WEIGHT: bold; FONT-SIZE: 10pt; FONT-FAMILY: Arial">Object Oriented
Design
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> "urn:schemas-microsoft-com:office:office" />


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l5 level1 lfo1; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">This is not an OO Design
class


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l5 level1 lfo1; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">A type represents a set of
responsibilities


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l5 level2 lfo1; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Modeling the real
world


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l5 level2 lfo1; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Group related responsibilities
together in a class


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l5 level1 lfo1; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Only 5% of developers will ever
explicitly extend base classes


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l5 level2 lfo1; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">But 100% will use
classes


size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> 


style="FONT-WEIGHT: bold; FONT-SIZE: 10pt; FONT-FAMILY: Arial">Danger of over
design
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l5 level1 lfo1; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">The most common library design
mistake


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l5 level1 lfo1; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">A new dev/pm is designing the widget
feature


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l5 level2 lfo1; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> style="mso-spacerun: yes"> Wants it to be extensible and feature
rich


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l5 level1 lfo1; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">The reality of shipping
hits


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l5 level2 lfo1; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> style="mso-spacerun: yes"> Design only partly thought
out


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l5 level2 lfo1; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> style="mso-spacerun: yes"> Long bug tail


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l5 level2 lfo1; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> style="mso-spacerun: yes"> Forced hard
cuts


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l5 level2 lfo1; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> style="mso-spacerun: yes"> We ship it cumbersome and
broken


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l5 level1 lfo1; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">In V.next


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l5 level2 lfo1; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> style="mso-spacerun: yes"> We now we know the extensibility needed


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l5 level2 lfo1; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> style="mso-spacerun: yes"> But blocked by the broken design the
shipped


style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> 


style="FONT-WEIGHT: bold; FONT-SIZE: 10pt; FONT-FAMILY: Arial">Abstract and Base
classes
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l1 level1 lfo2; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Base classes serve as the root of an
inheritance hierarchy


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l1 level1 lfo2; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Abstract classes are a special kind
of base class that are non-instantiable and may contain members that aren’t
implemented


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l1 level1 lfo2; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Prefer broad, shallow
hierarchies


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l1 level2 lfo2; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Less than or equal to 2 levels –
Rough rule!


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l1 level1 lfo2; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Contracts and responsibilities are
difficult to maintain and explain in deep complex
hierarchies


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l1 level1 lfo2; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Consider making base classes not
constructible


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l1 level1 lfo2; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Make it clear what the class is
for


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l1 level1 lfo2; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Provide a protected constructor for
subclasses to call


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l1 level1 lfo2; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">System.Exception should not have had
a public constructor


size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> 


style="FONT-WEIGHT: bold; FONT-SIZE: 10pt; FONT-FAMILY: Arial">Virtual, Abstract
and Non-virtual
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">


size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> 


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l12 level1 lfo3; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-WEIGHT: bold; FONT-SIZE: 10pt; FONT-FAMILY: Arial">Virtual face=Arial size=2> members are
points of specialization or callbacks in your code


size=2> style="FONT-SIZE: 10pt; mso-bidi-font-family: 'Courier New'">public
virtual int Length { get {..} }


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l11 level1 lfo4; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-WEIGHT: bold; FONT-SIZE: 10pt; FONT-FAMILY: Arial">Abstract
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> style="mso-spacerun: yes"> members are required points of
specialization in your code


size=2> style="FONT-SIZE: 10pt; mso-bidi-font-family: 'Courier New'">public
abstract int Read() style="FONT-WEIGHT: bold">


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l0 level1 lfo5; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-WEIGHT: bold; FONT-SIZE: 10pt; FONT-FAMILY: Arial">Non-virtual face=Arial size=2> members
cannot be overridden in derived types


size=2> style="FONT-SIZE: 10pt; mso-bidi-font-family: 'Courier New'">public
string Remove (int index, int count)


size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> 


size=2> style="FONT-SIZE: 10pt; mso-bidi-font-family: 'Courier New'">public class
Foo {


size=2> style="mso-spacerun: yes">   public override string ToString()
{


size=2> style="mso-spacerun: yes">      return
“foo”;


size=2> style="mso-spacerun: yes">   }


size=2> style="FONT-SIZE: 10pt; mso-bidi-font-family: 'Courier New'">}


size=2> style="FONT-SIZE: 10pt; mso-bidi-font-family: 'Courier New'">public class
Bar : Foo {


size=2> style="mso-spacerun: yes">   public override string ToString()
{


size=2> style="mso-spacerun: yes">      return
“bar”;


size=2> style="mso-spacerun: yes">   }


size=2> style="FONT-SIZE: 10pt; mso-bidi-font-family: 'Courier New'">}


face="Times New Roman" size=3>What is printed
out?


size=2>Bar b
= new Bar ();
Console.WriteLine (b.ToString());


size=2> style="FONT-SIZE: 10pt; mso-bidi-font-family: 'Courier New'">Foo f =
b;
Console.WriteLine (f.ToString());


size=2>Object
o = b;
Console.WriteLine (o.ToString());


style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> 


style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> 


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l2 level1 lfo6; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">They all print “bar”.
Why?


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l2 level2 lfo6; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Method call virtualizes at
runtime


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l2 level2 lfo6; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">The static type doesn’t
matter


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l2 level1 lfo6; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">This is the danger and power of
virtual methods


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l2 level2 lfo6; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Danger: Owner of base classes cannot
control what subclasses do


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l2 level2 lfo6; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Power: Base class doesn’t have to
change as new subclasses are created


style="FONT-WEIGHT: bold; FONT-SIZE: 10pt; FONT-FAMILY: Arial">Overriding face=Arial size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l7 level1 lfo7; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Don’t change the semantics of
member


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l7 level2 lfo7; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Follow the contract defined on the
base class


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l7 level1 lfo7; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Don’t require clients to have
knowledge of your overriding


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l7 level1 lfo7; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Consider whether you should call the
base implementation


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l7 level2 lfo7; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Favor calling it unless you have
good reason not to


style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> 


style="FONT-WEIGHT: bold; FONT-SIZE: 10pt; FONT-FAMILY: Arial">Virtual and
non-virtual
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l10 level1 lfo8; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Use non-virtual members unless you
have specifically designed for specialization


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l10 level2 lfo8; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Have a concrete scenario in
mind


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l10 level2 lfo8; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Write the
code!


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l10 level1 lfo8; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Think before you virtualize
members


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l10 level2 lfo8; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Modules that use references to base
types must be able to use references to derived types without knowing the
difference


style="MARGIN: 0in 0in 0pt 1.5in; TEXT-INDENT: -0.25in; mso-list: l10 level3 lfo8; tab-stops: list 1.5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Must continue to call in the same
order and frequency


style="MARGIN: 0in 0in 0pt 1.5in; TEXT-INDENT: -0.25in; mso-list: l10 level3 lfo8; tab-stops: list 1.5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Cannot increase or decrease range of
inputs or output


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l10 level2 lfo8; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">See the Liskov Substitution
Principle ( href="http://www.brent.worden.org/tips/2000/liskovSubstitutionPrinciple.html"
target=_blank>http://www.brent.worden.org/tips/2000/liskovSubstitutionPrin href="http://www.brent.worden.org/tips/2000/liskovSubstitutionPrinciple.html"
target=_blank>ciple.html)


style="FONT-WEIGHT: bold; FONT-SIZE: 10pt; FONT-FAMILY: Arial"> 


style="FONT-WEIGHT: bold; FONT-SIZE: 10pt; FONT-FAMILY: Arial">Abstract
Members
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l4 level1 lfo9; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Methods, Properties and Events can
be abstract


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l4 level1 lfo9; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Use abstract members only where it
is absolutely required that subclasses provide a custom
implementation


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l4 level1 lfo9; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Only use when the base class cannot
have any meaningful default implementation


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l6 level1 lfo10; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Default to making members
non-virtual


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l6 level1 lfo10; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Make it virtual if it is designed to
be specialized by subclasses


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l6 level1 lfo10; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Make it abstract if no meaningful
default implementation is possible


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l6 level2 lfo10; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Unless versioning issues prohibit
it, in which case throw a NotImplementedException


style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> 


style="FONT-WEIGHT: bold; FONT-SIZE: 10pt; FONT-FAMILY: Arial">Interfaces versus
Base Classes
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l3 level1 lfo11; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Favor using base classes over
interfaces


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l3 level2 lfo11; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Base classes version better in
general


style="MARGIN: 0in 0in 0pt 1.5in; TEXT-INDENT: -0.25in; mso-list: l3 level3 lfo11; tab-stops: list 1.5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Allows adding
members


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l3 level2 lfo11; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Members can be added with a

default implementation


style="MARGIN: 0in 0in 0pt 1.5in; TEXT-INDENT: -0.25in; mso-list: l3 level3 lfo11; tab-stops: list 1.5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Avoids incompatibilities common in
ActiveX


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l3 level2 lfo11; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Interfaces are good for versioning
behavior (changing semantics)


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l3 level1 lfo11; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Avoid having both base class and
interfaces


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l3 level2 lfo11; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Adds confusion about which to
use


style="MARGIN: 0in 0in 0pt 1.5in; TEXT-INDENT: -0.25in; mso-list: l3 level3 lfo11; tab-stops: list 1.5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Component vs.
IComponent


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l3 level2 lfo11; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Little
advantage


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l3 level1 lfo11; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Consider using Aggregation


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l3 level1 lfo11; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Don’t use attributes where a
contract is needed


style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> 


style="FONT-WEIGHT: bold; FONT-SIZE: 10pt; FONT-FAMILY: Arial">Explicit method
implementations
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l3 level1 lfo11; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Implementing members of an interface
“privately”


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l3 level2 lfo11; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Not a security
boundary!


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l3 level1 lfo11; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Only accessible when cast to the
interface type


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l3 level1 lfo11; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Hides implementation
details


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l3 level2 lfo11; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Clean public interface


style="MARGIN: 0in 0in 0pt 1.5in; TEXT-INDENT: -0.25in; mso-list: l3 level3 lfo11; tab-stops: list 1.5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">IConvertible on Int32,
etc


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l3 level2 lfo11; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Differentiates
implementations


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l3 level2 lfo11; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Simpler strong
typing


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l3 level1 lfo11; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">The 19 ToXxx methods on IConvertible
don’t “pollute” the Int32 public view


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l3 level2 lfo11; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">But they are there when cast to
IConvertible


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l3 level2 lfo11; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Solution: Implement them
privately


size=2> style="FONT-SIZE: 10pt; mso-bidi-font-family: 'Courier New'">public
struct Int32 : IConvertible, IComparable {
style="mso-spacerun: yes">   public override string ToString ()
{..}
   int
ICovertible.ToInt32 () {..}
  

}


size=2> style="FONT-SIZE: 10pt; mso-bidi-font-family: 'Courier New'">int i =
42;
i.ToString();  //
works
i.ToInt32();   // does
not compile
((IConvertible) i).ToInt32(); style="mso-spacerun: yes">  // works


style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> 


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l8 level1 lfo12; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Interfaces developed by different
groups can have the same signature for different
meanings


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l8 level2 lfo12; tab-stops: list 1.0in"> face="Lucida Console" size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: 'Lucida Console'; mso-fareast-font-family: 'Lucida Console'; mso-bidi-font-family: 'Lucida Console'"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">       
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Draw() a picture and Draw() a
gun


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l8 level1 lfo12; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Frequently you want to differentiate
the implementation


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l8 level1 lfo12; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Explicit method implementations
enables this


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l8 level1 lfo12; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Avoids us recommending “unique”
names in interfaces


size=2> style="FONT-SIZE: 10pt; mso-bidi-font-family: 'Courier New'">interface
IGraphics {


size=2> style="mso-spacerun: yes">   void
Draw();


size=2> style="mso-spacerun: yes">   Brush Brush { get; set;
}


size=2> style="mso-spacerun: yes">   Pen Pen { get; set;
}


size=2> style="FONT-SIZE: 10pt; mso-bidi-font-family: 'Courier New'">}


size=2> style="FONT-SIZE: 10pt; mso-bidi-font-family: 'Courier New'">interface
IBandit {


size=2> style="mso-spacerun: yes">   void
Draw();


size=2> style="mso-spacerun: yes">   void Duel(IBandit
opponent);


size=2> style="mso-spacerun: yes">   void = st2 ns = "urn:schemas:contacts" /> w:st="on">Rob(Bank bank, IBandit[]
sidekicks);


size=2> style="FONT-SIZE: 10pt; mso-bidi-font-family: 'Courier New'">}


size=2> style="FONT-SIZE: 10pt; mso-bidi-font-family: 'Courier New'">class
Bandit: IBandit, IGraphics {


size=2> style="mso-spacerun: yes">   void IBandit.Draw()
{…}


size=2> style="mso-spacerun: yes">   void IGraphics.Draw()
{…}


size=2> style="FONT-SIZE: 10pt; mso-bidi-font-family: 'Courier New'">}


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l9 level1 lfo13; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">There is a natural tension between
generic typing and strong typing


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l9 level1 lfo13; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">List of Object vs. List of Employees


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l9 level2 lfo13; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Generic
typing


style="MARGIN: 0in 0in 0pt 1.5in; TEXT-INDENT: -0.25in; mso-list: l9 level3 lfo13; tab-stops: list 1.5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Polymorphism


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l9 level2 lfo13; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Strong
typing


style="MARGIN: 0in 0in 0pt 1.5in; TEXT-INDENT: -0.25in; mso-list: l9 level3 lfo13; tab-stops: list 1.5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">More “ ns = "urn:schemas-microsoft-com:office:smarttags" /> w:st="on">RAD” experience


style="MARGIN: 0in 0in 0pt 1.5in; TEXT-INDENT: -0.25in; mso-list: l9 level3 lfo13; tab-stops: list 1.5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Avoids boxing of value
types


style="MARGIN: 0in 0in 0pt 1.5in; TEXT-INDENT: -0.25in; mso-list: l9 level3 lfo13; tab-stops: list 1.5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Avoids ugly
casts


style="MARGIN: 0in 0in 0pt 0.5in; TEXT-INDENT: -0.25in; mso-list: l9 level1 lfo13; tab-stops: list .5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Often mutually
exclusive


style="MARGIN: 0in 0in 0pt 1in; TEXT-INDENT: -0.25in; mso-list: l9 level2 lfo13; tab-stops: list 1.0in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">You can’t have both of these in the
same class


style="MARGIN: 0in 0in 0pt 1.5in; TEXT-INDENT: -0.25in; mso-list: l9 level3 lfo13; tab-stops: list 1.5in"> face=Tahoma size=2> style="FONT-SIZE: 10pt; FONT-FAMILY: Tahoma; mso-fareast-font-family: Tahoma"> style="mso-list: Ignore">• style="FONT: 7pt 'Times New Roman'">        
style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">They differ only in return
type


size=2>This gives you a
compile time error


size=2> style="FONT-SIZE: 10pt; mso-bidi-font-family: 'Courier New'">public
object this [int index] {


size=2> style="mso-spacerun: yes">   get{..} style="mso-spacerun: yes">  set{..}
}
public string this [int
index] {
   get{..}
set{..}
}


style="FONT-SIZE: 10pt; FONT-FAMILY: Arial"> 


style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">This
works:


size=2> style="FONT-SIZE: 10pt; mso-bidi-font-family: 'Courier New'"> 


size=2> style="FONT-SIZE: 10pt; mso-bidi-font-family: 'Courier New'">public class
StringList : IList
   public
string this [int index] {
style="mso-spacerun: yes">      get{..}
set{..}
   }
style="mso-spacerun: yes">   object IList.this [int index]
{
   style="mso-spacerun: yes">   get{..} style="mso-spacerun: yes">  set{..}
style="mso-spacerun: yes">   }


size=2> style="FONT-SIZE: 10pt; mso-bidi-font-family: 'Courier New'">}


size=2> style="FONT-SIZE: 10pt; mso-bidi-font-family: 'Courier New'">StringList
slist = new StringList();
string s1 = slist[0];

IList genList =
slist;
string s2 = (string) genList[0];


size=2> style="FONT-SIZE: 10pt; mso-bidi-font-family: 'Courier New'"> 


style="FONT-SIZE: 10pt; FONT-FAMILY: Arial">Of course Generics are a better
solution


 

Comments (14)

  1. Frans Bouma says:

    "Use non-virtual members unless you have specifically designed for specialization"
    In VB.NET, afaik, all member methods are virtual. :)

    Furthermore I don’t agree on the favor base class over interface. If you read "Design patterns" by GoF, they say the opposite: favor interface over base class. What to believe? :)

  2. Ian Griffiths says:

    I’m always surprised by the de-emphasis on interfaces. (But then I did COM for years…)

    The thing is that I’ve done a lot of development in situations where the set of users of the class library has been relatively small, so we’ve had the luxury of being able to refactor frequently. I have found that given this flexibility, my designs often migrate towards interface-based designs over time even when I start out with base classes.

    Also, interface-based designs can be a lot easier to unit test: it’s much easier to plug a mock objects when the code under test doesn’t have too many preconceived ideas about the types it is dealing with. Of course you can achieve the same result with abstract base classes, but if the only reason for introducing an abstract base class was to decouple the client code from the concrete type, isn’t an interface a better choice anyway? I only use inheritance when there’s some implementation to inherit.

  3. Kevin Dente says:

    Question about explicit interface implimentation. It seems that when a base class implements an interface explicitly, there’s no way for a deriving class to override methods of the interface and chain to the base class implementation. For example, you can’t do this: ((IMyInterface)base).DoStuff(). As far as I can tell, the only option in this case is to completely reimplement the base class functionality. Is this by design?

  4. Rick Byers says:

    "Overriding: Don’t change the semantics of member, follow the contract defined on the base class".

    This is obviously a very important rule in OO design. What do you think of the reccomended practice of overriding Object.Equals to provide value equality when the default implementation only provides reference equality? Isn’t that changing the semantics of Equals?

  5. Andy Smith says:

    Kevin: There’s no built in way to call the base class’s explicitly defined interface method. If you want to completely override it, you can simply explicitly implement it yourself. But if you positively, absolutely need to also call the base class implementation… I found a way that uses reflection to do so:
    http://weblogs.asp.net/asmith/posts/10005.aspx
    It uses the System.Reflection.InterfaceMapping class.

  6. These are great articles please keep them coming.

    Regarding your recommendations on base classes vs Interfaces.
    “Avoid having both base class and interfaces
    • Adds confusion about which to use
    • Component vs. IComponent
    • Little advantage”

    My experience is that having a base class and an interface is almost required if you are developing extensible class libraries or frameworks.

    By encouraging end users of the framework to use the framework’s public interfaces to access objects a couple of nice benefits accrue; it gives you as the framework vendor more opportunity to protect them from implementation changes as the framework evolves, it also allows you to provide/encourage the use of interface friendly patterns Factory, etc.

    By providing both an interface and a base class you allow the extension of your framework by derivation if the specialization needs are small or a complete re-implementation of your interface by sophisticated extenders whose needs aren’t met by your existing implementation architecture.

    One nice thing about this approach is that it keeps the level of complexity appropriate to the level of customization.

    Cheers,

    Terence

  7. Kevin Hector says:

    Brad, great stuff. Are these guidelines going to make it into a revised design guidelines document in the public domain? I seem to remember you said you were preparing them for internal use only.

  8. Gerke Geurts says:

    I agree with Terence’s posting about base classes vs. interfaces. I prefer designing an interface so that framework users are not necessarily forced to use my base classes. Adding a base class with a default implementation of the interface provides an easy starting point for those who don’t need to use another base class.

  9. Frank Hileman says:

    I just want to log my vote against interfaces, in favor of base classes, for the same reasons Brad points out: versioning, ease-of-use. Excessive use of interfaces can be an indication of over-design: because they seem more flexible (choice of base class), and designers want to provide maximum flexibility, they go for the interface. But they are less flexible for the designer, since you cannot change the interface in a newer version. Unless you can think of a specific situation where someone will not be able to inherit from your base class, I think only the base class and not the interface should be provided.

    Regarding depth of class hierarchies. It would be nice if we could have arbitrary depth of inheritance within a class hierarchy, while only making certain base and leaf classes public. While I agree that the public classes in a library should correspond to "real world" (whatever that means) objects and concepts, within the library the internal classes are simply arbitrary units of code reuse. For example, I may wish to factor common code into several classes, four levels deep, but only expose some classes at the leaf level, or at the leaf and one above that. I don’t understand why we are prohibited from doing that. The internal inheritance hierarchy has nothing to do with the public api of a class library. We should be able to change it without affecting users of the library.

    I know that other do not agree with this, but inheritance is just a form of code reuse. Not "idea reuse".