Minor update to the base class guidelines


Fairly minor update — as always, let me know if there are questions or
comments.


———————————————————


Consider using abstract classes (even if there are no abstract
members) if the class is designed to be a root in an inheritance hierarchy make
this clear by not allowing it to be directly used.  


style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 4pt; BACKGROUND: #e9fdf3; PADDING-BOTTOM: 1pt; MARGIN-LEFT: 0.25in; BORDER-LEFT: windowtext 1pt solid; MARGIN-RIGHT: 0in; PADDING-TOP: 1pt; BORDER-BOTTOM: windowtext 1pt solid">

size=1>Annotation (Brad style="FONT-WEIGHT: bold; FONT-STYLE: italic"> Abrams): In
retrospect we should have made System.Exception an abstract
class.    System.Exception was meant to be used as a root in the
inheritance hierarchy but because we allowed it to be constructable lazy
developers tend to throw it rather than using a more meaningful exception.


style="FONT-SIZE: 10pt; FONT-FAMILY: Symbol"> size=1> style="FONT: 7pt 'Times New Roman'">  Avoid
prefixing or postfixing “Base”, “Root” or other such words as this type is
likely to show up in public APIs.  In general base classes have simple,
meaningful, pretty names because they are commonly used in public APIs.  In
some cases differentiation is unavoidable because the base class is really an
implementation detail and not a key design point. For example in
System.Windows.Forms, the ButtonBase class is the base class for Buttons,
CheckBoxes, etc.  In these cases use the XxxBase pattern. 


Do prefer using base types in public signatures
rather than concrete types. This provides better opportunity for substitution
and more flexibility in changing the implementation in the future.


face=Verdana size=2>Consider the following
method:


style="FONT-SIZE: 9pt">public FileStream GetDataStream() {}


face=Verdana size=2>The implementation of
GetDataStream is not locked into being backed by a File.  If the
implementation changes to use any other type of stream (such as a NetworkStream)
a breaking change will have to be made.  It would be better to use the base
class Stream to gain greater flexibility.


size=1>public Stream GetDataStream()
{}


size=1> 


style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 4pt; BACKGROUND: #e9fdf3; PADDING-BOTTOM: 1pt; MARGIN-LEFT: 0.25in; BORDER-LEFT: windowtext 1pt solid; MARGIN-RIGHT: 0in; PADDING-TOP: 1pt; BORDER-BOTTOM: windowtext 1pt solid">

size=1>Annotation (Brad Abrams) This guideline
could be easily abused to create overly complicated designs.  If you have
an API that is meant to only work with files, using a FileStream is the right
thing to do.  Don’t push in abstraction unless it is called for.


style="FONT-SIZE: 12pt"> 


 

Comments (8)

  1. Keith Patrick says:

    Sorry for being nitpicky (hey, I *did* say I was systematic rather than pragmatic), but the return type is not part of the signature 🙂

  2. Shane King says:

    The ability to just throw Exception is useful. If I’m just doing something quick and dirty, I’d rather not have to make my own exception class, and just throwing an Exception is perfect. Or if I’m in the middle of building some code, I’ll throw an Exception and put a TODO note against it so I can come back later and add in the proper exception without having to do it right now.

    Taking away convenience for the sake of trying to force people to do the "right thing" is a bad design choice, IMO. Sometimes what you think is the right thing isn’t the right thing for every situation!

  3. Ken Brubaker says:

    Brad, thank you for these insightful updates. I am especially pleased that you explicitly reserve the Base suffix for implementation inheritance. I knew that the FCL already followed this pattern, but I had a hard time convincing my staff not to use base for public inheritance.

    I have used, quite unapologetically, the Class Library Design Guidelines as my code review standard. I would LOVE to pay for an annotated reference, such as this post, in book form. Do you have any plans for publishing your Code and UI guidelines?

    In response to Shane: The FCL team clearly denominates the guidelines as Class Library guidelines, not hack coding guidelines. I’m sure Brad has no problems with you using Exception in your one-off code. Just don’t use it in a commercial class library. (However, you should at least use ApplicationException)

  4. Ken Brubaker says:

    For my own reference, I thought I’d compile a quick list of design guidelines added by Brad Abrams, et al.

  5. Kevin Dente says:

    Brad, I was just reading through Rob Howard’s discussion of the ASP.NET provider model in Whidbey. It looks like the provider classes he describes use the Base suffix, seemingly contradicting the guideline listed in this posting. Is there a particular reason for this?