The%20Art%20of%20Building%20a%20Reusable%20Class%20Library - PowerPoint PPT Presentation

View by Category
About This Presentation
Title:

The%20Art%20of%20Building%20a%20Reusable%20Class%20Library

Description:

Brad Abrams BradA_at_Microsoft.com Krzysztof Cwalina - KCWalina_at_Microsoft.com Microsoft Corporation – PowerPoint PPT presentation

Number of Views:238
Avg rating:3.0/5.0
Slides: 238
Provided by: BradA154
Category:

less

Write a Comment
User Comments (0)
Transcript and Presenter's Notes

Title: The%20Art%20of%20Building%20a%20Reusable%20Class%20Library


1
The Art of Building a Reusable Class Library
  • Brad Abrams BradA_at_Microsoft.com Krzysztof
    Cwalina - KCWalina_at_Microsoft.com
  • Microsoft Corporation

2
Turn frustrated developers
into happy developers
3
Goals
  • Understand that API design matters
  • Recognize good API design
  • Lots of good and bad examples
  • Learn the API design process

4
Who is this precon for?
  • 1. Developers building reusable library or
    component
  • 2. Developer building apps to explicitly
    understand the rules of the .NET Framework and
    WinFX

5
Quote of the day
  • I have yet to see any problem, however
    complicated, which, when looked at the right way
    did not become still more complicated.
  • Poul Anderson

6
Project Cost Model
Source Gartner, May 2002 The Cost and Risk of
Application Development Decisions Joseph Feiman,
Tom Berg
7
Four Keys of Framework Design
  • The Power of Sameness
  • Framework Design Matters
  • Tools for Communication
  • The Pit of Success

8
The Power of Sameness
Brad Abrams
9
When you pick up your rental car.
  • Push the seat all the way back
  • Find an NPR station
  • Find the exit

10
Oh, down to lock
11
How to use a key
12
Oh, you push the PRESS button
13
Who actually needs this data?
14
Why you dont read rental car manuals
  • You know how to drive your car
  • All cars work basically the same way
  • Your rental car is a car
  • Therefore, you can drive your rental car
  • That is

The Power of Sameness
15
Producers and Sameness
New System
Market Potential
Standard System
16
Are things equally as obvious in your framework
designs? Maybe you are missing.
The Power of Sameness
17
Naming Conventions
  • PascalCasing Each word starts with an uppercase
    letter
  • camelCasing First word lower case, others
    uppercase
  • SCREAMING_CAPS All upper case with underscores

18
Blink Quiz I
class1 MyClass
Blink The Power of Thinking Without Thinking
19
Blink Quiz I
  • At-a-glance, first impressions what does this
    likely do?
  • A Compiler error
  • B Class declaration
  • C Variable declaration
  • D Other

class1 MyClass
  • Change the casing to match the pattern, is it
    easier to tell what this is?

Class1 myClass
20
Naming Conventions
  • All types and publicly exposed members are
    PascalCased
  • Parameters are camelCased

public class MemberDoc public int
CompareTo(object value) public string Name
get
Section 4.1, Naming Conventions
21
Hungarian Notation
  • Do not use Hungarian notation in publicly exposed
    APIs and parameter names

public class CMyClass int CompareTo (object
objValue) .. string lpstrName get int
iValue get
22
Hungarian Notation (continued)
  • The prefix codes are arbitrary and difficult to
    learn
  • They make it harder to read an identifier name
  • Hungarian was developed for a time when languages
    were loosely typed and IDEs were not as powerful
  • E.g. out and ref parameters information now
    conveyed at the call site.
  • Interlocked.Increment(ref i)

23
On Abbreviations, acronym, initialism and the
like
  • Avoid them!
  • They are a classic JLT (jargon loaded term)
  • OK to use them once they become words
  • Html, Xaml, etc
  • Dont just spell them out
  • Use a meaningful name
  • Abbreviations of more than 2 letters are cased as
    words, otherwise ALLUPPER
  • IO vs. Html

24
While we are on naming
  • Good naming is hardit takes time
  • Be meaningful but brief
  • Use US-English
  • Colour vs. Color
  • Principle of least surprise
  • Look for prior-art
  • NumberOfElements vs. Count

25
Blink Quiz II
  • Does this compile?

IFoo foo new IFoo()
  • No because you cant create instances of
    interfaces
  • Why do we assume IFoo is an interface?

The Power of Sameness
26
Suffixes and Prefixes
  • Interfaces prefix with I
  • A tribute to COM
  • Exceptions and Attributes suffixed

public interface IFormattable Public class
NameAttribute Attribute Public class
PrinterOnFireException Exception
27
Quick Quiz
  • What is wrong this this type?

public class ArgumentNullException
ArgumentException public
ArgumentNullException () public
ArgumentNullException (string paramName)
public ArgumentNullException (string paramName,
string message)
28
Common Exception Usage
throw new IOException()
throw new FormatException()
throw new ArgumentException()
throw new InvalidOperationException()
  • Developers expect all exceptions to work this
    way
  • Make your exception meet expectations

29
Exception Constructor Pattern
  • Every exception should have at least the top
    three constructors

public class XxxException YyyException
public XxxException () public XxxException
(string message) public XxxException
(string message, Exception inner)
protected XxxException ( SerializationInfo
info, StreamingContext context)
30
Remember this type.
  • What is wrong this this type?

public class ArgumentNullException
ArgumentException public
ArgumentNullException () public
ArgumentNullException (string paramName)
public ArgumentNullException (string paramName,
string message)
31
API design theater
You are optimizing locally, you are making the
right decision if developers only use your type,
but if they use others as well.
I see why not?
90 of the time the message is not used, the
param name is what is important
It doesnt apply in this case
Why didnt you follow the exception pattern?
The Developer
The Architect
32
Missing the power of sameness
  • Result Habit wins out and people commonly type

throw new ArgumentNullException ("the value must
pass an employee name")
  • We end up with odd error messages such as

Unhandled Exception System.ArgumentNullException
Value cannot be null. Parameter name the value
must pass an employee name
  • Moral Just follow the pattern!

throw new ArgumentNullException ("Name", "the
value must pass an employee name")
33
Method Overloading Abusing the Power of Sameness
  • Overloaded Method on the same type with the same
    name, but different number or type of arguments

public static string ToString(int value)
public static string ToString(double value)
34
Dangers of Method Overloading
  • Why does this man dislike method overloading?
  • Meyer A single operation should do a single
    thing..
  • Abrams Good method overloading is a single thing
    all overloads are semantically the same

35
Method Overloading
String.IndexOf(string value) String.IndexOf(cha
r anyOf)
string s "brad abrams" s.IndexOf("ab") //
5 s.IndexOf('ab') // 0
  • Cobol actually does allow syntax like this
  • Moral Dont overload when the methods are
    semantically different

36
Method Overloading
  • Use overloading only when the overloads do
    semantically the same thing
  • Incorrect overload
  • Correct overload

String.IndexOf(string value) String.IndexOf(cha
r anyOf)
Convert.ToString(int value) Convert.ToString(do
uble value)
37
Method Overloading Defaults
  • Use appropriate default values
  • Simple method assumes default state
  • More complex methods indicate changes from the
    default state
  • Use a zeroed state for the default value (such
    as 0, 0.0, false, null, etc.)

MethodInfo Type.GetMethod (string name)
//ignoreCase false MethodInfo Type.GetMethod
(string name, boolean ignoreCase)
38
Constructors and Properties
  • Constructors parameters are shortcuts for
    setting properties
  • No difference in semantics between these code
    snippets

EventLog log new EventLog() log.MachineName
kcwalina0 log.Log Security
EventLog log new EventLog(Security) log.Machi
neName kcwalina0
EventLog log new EventLog(Security,kcwalina0
)
39
Exercises
40
Exercise Code Review
public class HtmlEncoding public const
string DEFAULT_NAME "Html3.2" public
HtmlEncoding (int iCount) .. public string
Tagname get .. public bool
UseIoCompletionPort get .. protected void
_coreSetValue (double value) .. private
IntPtr ptrValue
41
Exercise Naming Conventions
  • What are good reasons to violate naming
    conventions?
  • I used to work in C, Java, COBOL
  • Our previous version used SCREAMING_CAP
  • These are initials from someones name, they
    have to be all upper case

42
Exercise Code Review
public interface Convertible Public class
CodeReviewer Attribute Public class
InputInvalidError Exception
43
Exercise Code Review
public static int MaxValue 9999999 public void
Withdraw () Withdraw (MaxValue) public
void Withdraw (int amount)
44
Summary
  • The Power of Sameness Teaches us
  • Influence of expectations
  • Naming conventions and common suffixes\prefixes
  • Habits win out over the special cases
  • Common Exception pattern
  • With great power comes great responsibility
  • Method overloading
  • Meet developers where they are
  • constructors and properties pattern teaches us to
    meet developers expectations

45
Questions?
46
Framework Design Matters
  • The role of a framework designer in the
    development process
  • Krzysztof Cwalina
  • Microsoft

47
The process of framework design is very different
from prototyping and implementation
48
Developers focus on a different level
49
Similarly to implementations framework design
must be
  • Simple
  • Integrated
  • Consistent
  • Evolvable

... but the similarities are superficial
50
Well-designed framework must be simple
51
Focus on Top Scenarios
  • Do define top usage scenarios for each major
    feature area.
  • Do design APIs by first writing code samples for
    the main scenarios and then defining the object
    model to support the code samples.
  • Do not require users to explicitly instantiate
    more than one type in the most basic scenarios.

52
Example Scenario Samples
53
Namespace Factoring
  • Avoid having types designed for advanced
    scenarios in the same namespace as types intended
    for common programming tasks.
  • Do ensure that each main feature area namespace
    contains only types that are used in the most
    common scenarios. Types used in advanced
    scenarios should be placed in subnamespaces.

54
Example Namespace Factoring
55
Naming
  • Do favor readability over brevity. The property
    name CanScrollHorizontally is better than
    ScrollableX (an obscure reference to the X-axis).
  • Do not use abbreviations or contractions as parts
    of identifier names.
  • Do not use any acronyms that are not widely
    accepted, and then, only when necessary.
  • Do reserve the best type names for the most
    commonly used types.

56
Example Naming
57
Exceptions
  • Do use exception messages to communicate
    framework usage mistakes to the developer.

58
Example Exceptions
EventLog log new EventLog() Log.WriteEntry(Hel
lo World)
59
Well-designed framework must be explicitly
designed
60
Create API Specification
61
Review Scenario Samples
  • Solicit feedback on the scenario samples
  • Feedback from non-experts

62
Review API Design
63
Well-designed framework is a part of an ecosystem
64
Intellisense
65
EditorBrowsableAttribute
public class MyComponent EditorBrowsable(Ed
itorBrowsableState.Always) public void
CommonlyUsedMethod()
EditorBrowsable(EditorBrowsableState.Never)
public void RarelyUsedMethod()
EditorBrowsable(EditorBrowsableState.Never
) public override int GetHashCode()
return base.GetHashCode()
66
Naming Related Members
67
Naming Related Members Fixed
68
Debugger
69
Debugger Attributes
DebuggerTypeProxy(typeof(LinkedListDebuggerViewltgt
)) public class LinkedListltTgt internal
class LinkedListDebuggerViewltTgt public
LinkedListDebuggerView(LinkedListltTgt list)
DebuggerBrowsable(DebuggerBrowsableState.R
ootHidden) public T Items get

70
Debugger Attributes Result
71
CLS Compliance
  • Do apply CLSCompliantAttribute to framework
    assemblies.

assemblyCLSCompliant(true)
72
Example CLS Compliance
73
Well-designed framework must be integrated
74
Using Common Abstractions
  • Do use the least derived parameter type that
    provides the functionality required by the
    member.
  • Do use the least specialized type possible as a
    parameter type. Most members taking collections
    as parameters use IEnumerableltTgt interface.
  • Do implement IEquatableltTgt on value types.

75
Collection Abstractions
76
Collection Abstractions Fixed
77
Type Name Conflicts
  • Do not introduce generic type names such as
    Element, Node, Log, and Message.

78
Example Type Name Conflicts
79
Type Name Conflicts Fixed by User
80
Type Name Conflicts Fixed by Framework Designer
81
Well-designed framework must be designed to
evolve
82
Interfaces vs. Abstract Classes
  • Do favor defining classes over interfaces.

83
Example Adding Members to Abstractions
public abstract class Stream // new Stream
members to support timeouts public virtual
int ReadTimeout get throw new
NotSupportedException() set throw
new NotSupportedException()
public virtual bool CanTimeout get
return false // other Stream members
that shipped previously
84
Example Adding Functionality in Subclasses
public class FileStream Stream public
override bool CanTimeout get return
true public override int
ReadTimeout get set

85
Example Interface Based Design
public interface IStream public class
FileStream IStream
86
Example Interface Based Design Adding Timeout
public interface ITimeoutEnabledStream IStream
int ReadTimeout get set public
class FileStream ITimeoutEnabledStream
public int ReadTimeout get
set
87
Example Interface Based Design Problem
StreamReader reader GetSomeReader() //
dynamic cast (BaseStream returns
Stream) ITimeoutEnabledStream stream
reader.BaseStream as ITimeoutEnabledStream if(st
ream ! null) stream.ReadTimout 100
88
Example Abstract Class is Better
StreamReader reader GetSomeReader() if(reader.B
aseStream.CanTimeout) reader.BaseStream.ReadT
imeout 100
89
Control Extensibility
  • Do not make members virtual unless you have a
    good reason to do so and you are aware of all the
    costs related to designing, testing, and
    maintaining virtual members.

90
Test Abstractions
  • Do provide at least one type that is an
    implementation of an interface.
  • Do provide at least one API consuming each
    interface you define (a method taking the
    interface as a parameter or a property typed as
    the interface).

91
Well-designed framework must be consistent
92
Naming Consistency
Base Type Derived/Implementing Type Guideline
System.Attribute Do add the suffix Attribute to custom attribute classes, as in this example.
System.Delegate Do add the suffix EventHandler to names of delegates that are used in events. Do add the suffix Callback to names of delegates other than those used as event handlers.
System.EventArgs Do add the suffix EventArgs
System.Exception Do add the suffix Exception
CodeAccessPermission IPermission Do add the suffix Permission.
93
Common Patterns and Idioms
  • Attribute Design
  • Collection Usage
  • XML Usage
  • The Async Pattern
  • Dispose Pattern

94
Exercise API Design Process
  • Which of the following is the best way to start
    API design?
  • Sit in front of a computer and start coding.
  • Use class diagrams to discover main entities of
    the system.
  • Create a list of most common scenarios and write
    code samples corresponding to the scenarios.

95
Exercise Ecosystem
  • What parts of the development environment need to
    be considered when designing APIs?
  • Intellisense
  • Debuggers
  • Documentation
  • All of the above

96
Exercise Simplicity and Usability
  • What is the main contributor to framework
    usability?
  • How easy it is to find the right type to use.
  • How easy it is to find the right member to use.
  • Clear exception messages.

97
Summary
  • Framework design does not happen magically
  • Best frameworks are designed upfront by framework
    designers
  • There are several qualities of a well-designed
    framework that require focused framework design
    process

98
Questions?
99
API Design Experience The API review
  • Krzysztof Cwalina
  • Brad Abrams

100
Goals for this Exercise
  • Demonstrate how the API design experience really
    goes
  • Show you some common mistakes and common fixes
  • Laugh with us as we roll play this..

101
Comment KC1Why use an interface rather than a
base class?
102
Comment KC1Why is this sealed?
103
Comment KC1Should it be a value type?
104
Comment KC1Make this a static class?
105
Comment KC2Why not throw an exception?
106
(No Transcript)
107
What we showed you
  • Demonstrated a few examples of how the API design
    experience really goes
  • Show you some common mistakes and common fixes

108
Tools for Communication
Brad Abrams
109
Focus on developer, not yourself
110
Your developers cant read your mind
111
You must communicate
  • Examples of what consumers need to know
  • Will this operation block?
  • How do I customize this type?
  • How should I use this class?

112
Wouldnt it be great
Luckily, there are Tools for Communicating
113
Documentation alone is not enough
114
Good documentation on a bad API is
like lipstick on a pig
115
Communicate via leaving artifacts
  • Framework Design Artifacts
  • Types
  • Methods
  • Properties
  • Events
  • Constructors

116
Why is Archeology so hard?
  • All we have is what they left us
  • We cant directly talk to anyone that built them
  • Hard to find pieces of fragments that fit
    together
  • Bottom line ancient civilizations were not
    intentional about what they left behind

Sound Familiar?
Rosetta Stone
117
Follow a common vocabulary
Dont force consumers to become archeologists of
your framework
118
Follow a Common Vocabulary
  • Pre-School level vocabulary for English
  • What is the common vocabulary for API design?

119
Define Namespace
namespace System.IO
  • Organizational principle to allow consumers to
  • Find relevant functionality quickly
  • Exclude less relevant functionality
  • Not about implementation issues
  • Security, identity, size, perf
  • Not a billboard to advertise your organizational

namespace System.IO.Readers namespace
System.IO.Writters namespace System.IO.Streams

120
Define Class
public class Object
  • A conceptual model for a thing which can hold
    state, perform actions, etc
  • Common API design problems
  • Grab bag types (lack of cohesion)
  • Example System.Runtime.InteropServices.Marshal
  • Modeling overly abstract
  • Example StreamReader vs. File

public static class Marshal
  • Avoid grab bag types

121
Define Struct
public struct Int32 IComparable,
IFormattable
  • A domain specific extension of the intrinsic type
    system
  • Example Point, Complex, etc
  • Expert use perf optimization when GC-Heap
    allocated objects not warranted
  • Example an Enumerator
  • Common API design problems
  • Overuse to avoid GC
  • instance size over 16 bytes
  • Are not immutable

122
Quick Quiz
  • What is wrong with this type?

public sealed class Environment private
Environment () public bool
HasShutDownStarted get
123
Define Static Class
  • Container for a set of highly related static
    members. Commonly used for
  • Full OO encapsulation not warranted
  • Example System.Math
  • Convenience methods for a more complex design
  • Example System.IO.File
  • Common API design problems
  • Doing it by hand and getting it wrong
  • Loose cohesion

124
Static Classes Under the Covers
public static class Environment public static
string CommandLine get ..
public abstract sealed class Environment
public static void Exit(int exitCode) ..
public static string CommandLine get ..

125
Define Exceptions
public class FileNotFoundException IOException
  • Encapsulation of error details used in a
    structured exception handling system
  • Common API Design Mistakes
  • Using error codes rather the exceptions
  • Creating far too many exceptions
  • Only create new exceptions if callers will handle
    them differently

126
Define Enum
public enum Colors Red 0, Green
1, Blue 2
  • Container for named constants
  • Common API Design Mistakes
  • Accepting the default values
  • Using magic constants instead

SetColor(Colors.Red) SetColor(1)
127
Enums Under the Covers
  • Enum values default to 0..N

public enum Compression Zip, SuperZip,
None
public struct Compression Enum public int
value__ public const Compression Zip 0
public const Compression SuperZip 1 public
const Compression None 2
128
Define Flags Enums
Flags public enum AttributeTargets
Assembly 0x0001, Module 0x0002,
Class 0x0004, Struct 0x0008, Type
Class Struct,
  • Combinable enum
  • FlagsAttibute
  • powers of 2
  • Use plural names
  • AttributeTargets rather than AttributeTarget
  • Provide named constants for common flags

129
Flag Enums Common Mistakes
  • Only use Flag enums when they represent a single
    concept
  • AttributeTargets is good example
  • The Reflection BindingFlags is an example of what
    not to do
  • Contains many different concepts in a single
    value (visibility, static-ness, member kind,
    etc.)
  • Should not be suffixed in Flags

130
Define Constructor
public class Employee public Employee (string
name)
  • Facility to capture state for an instance at time
    of instantiation
  • Common API design problem
  • Doing too much work in the constructor

131
Constructors are
public class XmlFile string fileName Stream
data public XmlFile(string fileName)
this.data DownloadData(fileName)
  • Do minimal work in the constructor
  • Be Lazy!
  • Only capture the parameters

132
Define Methods
public sealed class String public string
Insert (string value, int position)
  • Used to expose actions or operations
  • Common API Design Problem
  • Using properties where methods should be used

133
Properties versus Methods
  • Use a Property
  • If the member logical attribute of the type
  • Use a method
  • If the operation is a conversion, such as
    ToString()
  • If the getter has an observable side effect
  • If order of execution is important
  • If the method might not return immediately
  • If the member returns an array

134
Properties and returning arrays
public Employee All get
public Employee GetAll()
Calling Code
creates 2n1 copies of the arrays
EmployeeList l FillList() for (int i 0 i lt
l.Length i) if (l.Alli x)...
if (l.GetAll()i x) ...
Moral Use method if the operation is expensive
135
Define Fields
  • Useful for exposing implementation details
    thereby constraining your ability to evolve the
    framework
  • Or, just use properties ?

public String FileName
private String fileName public String FileName
get return fileName set fileName
value
136
Const versus Readonly
  • const
  • Compile-time evaluation
  • Stable across versions
  • readonly
  • Run-time evaluation
  • Unstable across versions

class Math public const double Pi
3.14 class Color public static readonly
Color Red new Color(...) public static
readonly Color Blue new Color(...) public
static readonly Color Green new Color(...)
137
Define Properties
public class ArrayList public int Count
get
  • Logical backing field. Useful to encapsulate
    access to state allowing a degree of flexibility
    in implementation
  • Common API Design Problem
  • Property vs. Method confusion

138
Properties
  • Use read only properties where appropriate
  • Do not use write-only properties
  • Property getters should be simple and therefore
    unlikely to throw exceptions
  • Properties should not have dependencies on each
    other
  • Setting one property should not affect other
    properties
  • Properties should be settable in any order

139
Define Events
public delegate void EventHandler(object sender,
EventArgs e) public class Button Control
public event EventHandler Click protected
void OnClick(EventArgs e) if (Click !
null) Click(this, e)
Event Handler
Event
Raise Method
  • Expose callback operation

140
Common Design Problem with Events
  • Using bad terminology
  • Events are not fired or triggered, they are
    raised
  • Not using verbs
  • E.g. Click, Paint, DrawItem, DropDown
  • Not using strongly typed EventArgs to allow for
    extensibility

public class MouseEventArgs
EventArgs
141
Static Members
  • Statics are the .NET equivalent of global
    variables or global functions
  • Not object oriented
  • Same evils as global
  • But can be very useful
  • System.Math Full modeling not required

public class Int32 public static int Parse
(string value) ..
int i Int32.Parse ("42")
142
Exercises
143
Exercise Namespaces
  • What is a good reason to split some related
    functionality across two namespaces?
  • Two different orgs create them
  • They are in two different assemblies
  • One is the 90 usage case the other in the 10
    usage case

144
Exercise class or struct?
public ??? DataValues decimal d1
decimal d2 decimal d3 decimal d4
public void SetValue (decimal d)
145
Exercise Exceptions
  • What are good reasons to create a new exception
    type?
  • I get paid by number of types
  • The underlying system call returns two different
    values
  • Users handle the two cases differently

146
Exercise Enums
  • Code review

public enum Fruits Banana, Apple,
Peach, Blueberry
147
Summary
  • Dont force your consumers to be archeologists
    digging for how to use your framework
  • Every element in your design has a specific
    meaning Know them and use them correctly
  • Avoid the common mistakes
  • Make brand new mistakes

148
Questions
149
API Design Experience Designing From Scratch
  • Krzysztof Cwalina
  • Brad Abrams

150
Goals for this Exercise
  • Demonstrate how the API design experience really
    goes
  • Show you some common mistakes and common fixes
  • How to identify a complex design
  • How to use scenarios to fix the design
  • Laugh at with us as we roll play this..

151
Assignment Design a Serial Port API
152
(No Transcript)
153
if(value ! handshake) // in the DCB,
handshake affects the fRtsControl, fOutxCtsFlow,
and fInX, fOutX fields, // so we must save
everything in that closure before making any
changes. Handshake handshakeOld handshake int
fInOutXOld GetDcbFlag(NativeMethods.FINX) int
fOutxCtsFlowOld GetDcbFlag(NativeMethods.FOUTXCT
SFLOW) int fRtsControlOld GetDcbFlag(NativeMeth
ods.FRTSCONTROL) handshake value int
fInXOutXFlag (handshake Handshake.XOnXOff
handshake Handshake.RequestToSendXOnXOff) ? 1
0 SetDcbFlag(NativeMethods.FINX,
fInXOutXFlag) SetDcbFlag(NativeMethods.FOUTX,
fInXOutXFlag) SetDcbFlag(NativeMethods.FOUTXCTSFL
OW, (handshake Handshake.RequestToSend
handshake Handshake.RequestToSendXOnXOff) ? 1
0) if ((handshake Handshake.RequestToSend
handshake Handshake.RequestToSendXOnXOff)
) SetDcbFlag(NativeMethods.FRTSCONTROL)
if (SetCommState(_handle, ref
dcb) false) handshake handshakeOld
SetDcbFlag(NativeMethods.FINX, fInOutXOld)
SetDcbFlag(NativeMethods.FOUTX, fInOutXOld)
SetDcbFlag(NativeMethods.FOUTXCTSFLOW,
fOutxCtsFlowOld) SetDcbFlag(NativeMethods.FRTS
CONTROL, fRtsControlOld) InternalResources.Win
IOError()
154
string num 234-567-8901 using (SerialPort
mySerialPort new SerialPort(COM1, 14400))
mySerialPort.DtrEnable true mySerialPort.Op
en() mySerialPort.Write(ATDT num
Environment.NewLine) mySerialPort.Close()
Dim Incoming as String Using (Dim sp As New
SerialPort (COM1, 14400)) Incoming
sp.Read() End Using
155
public sealed class SerialPort Component
public int InfiniteTimeOut -1 public int
BaudRate get set public int PortName
get set public int DataBits get set
public StopBits StopBits get set public
Encoding Encoding get set public int
ReadTimeout get set public int
WriteTimeout get set public Stream
BaseStream get public int
ReceivedBytesThreshold get set public
bool CDHolding get public bool CtsHolding
get public bool DsrHolding get public
SerialPort () public SerialPort (string
port) public SerialPort (string port, int
baudRate) public void Open() public void
Close() public int ReadChar() public void
Write(string value) public event
SerialPinChangedEventHandler PinChangedEvent pub
lic event SerialErrorEventHandler ErrorEvent
156
(No Transcript)
157
What we showed you
  • How to identify a complex design
  • How to use scenarios to fix the design

158
The Pit of Success
Brad Abrams
159
The Pit of Success in stark contrast to a
summit, a peak, or a journey across a desert to
find victory through many trials and surprises,
we want our customers to simply fall into winning
practices by using our platform and frameworks.
To the extent that we make it easy to get into
trouble we fail. - Rico Mariani
160
Is using your framework correctly like
Climbing a mountain?
161
Is using your framework correctly like
Scaling a peak?
162
Is using your framework correctly like
Running across a desert?
163
Is using your framework correctly like
Falling into a pit?
164
Enable the Pit of Success by
  • Avoiding the perilous summit of complexity
  • And the desert of confusion

165
  • Make the simple things simple and the hard things
    possible

166
Exceptions and the Pit of Success
  • Cleaner, more elegant, and wrong.
  • Raymond Chen (http//blogs.msdn.com/oldnewthing/)

167
When to throw an Exception?
  • Exceptions rather than error codes
  • Robust failures get noticed
  • Your method is defined to do something
  • If it succeeds in performing its purpose, return
  • If it fails to do what it was written to do,
    throw an exception

168
What Exception to throw?
  • Use or subclass existing exceptions if at all
    possible
  • Only create separate classes if you think
    developers will handle the exception differently

try //some operation catch
(FileNotFoundException fe) //do some set of
work catch (DriveNotFoundException be)
//do some other set of work
169
Throwing an Exception
  • Do not just map error codes onto a single
    exception with an error code property (e.g., the
    WMIException)
  • Use separate exception types
  • Error Messages
  • Consider localization
  • Use a complete sentence (end in a period)
  • Dont expose privacy related information (such as
    file paths)

170
Performance
  • Minimize the number of exceptions you throw in
    your APIs success code-paths
  • You dont pay for exceptions until you throw in
    managed code
  • Throwing exceptions degrades performance
  • Perf counters tell you exactly how many
    exceptions your application is throwing
  • Only an issue when using exceptions as a means of
    control flow
  • Consider providing a way to avoid an exception
    being thrown

171
Performance (continued)
int i try i Int32.Parse(123) catch
(FormatException ) Console.WriteLine
(Invalid)
int i if (!Int32.TryParse (123, out i))
Console.Writeline(Invalid)
172
Managing Resources during Exception Handling
  • You should use try..finally 10 times as often as
    try..catch
  • Catches eat exceptions making it hard to debug
  • Finally allows you to clean up, but let the
    exception continue

173
Managing Resources during Exception Handling
try . . . catch (DivisionByZeroException e)
// do clean up work throw new
BetterException (message, e)
  • You may catch exceptions to re-throw them with a
    clearer name
  • Typical at an API boundary
  • Always nest the underlying exception
  • Catch-and-rethrow has many of the benefits as
    try..finally
  • But, be aware of debugging issues with
    catch..throw new() and catch..throw
  • Generally, cleanup code should go in finalizer

174
Catching Exceptions
  • Do not catch and eat exceptions
  • Exceptions should be handled only where there is
    enough context to do the right thing
  • That generally means exceptions should be caught
    as high in the application as possible
  • Mistake catch the exception, report the error
    and rethrow it.
  • Only catch where you can handle it
  • Mistake catch the exception, turn it into a
    bool pass/fail and return the bool 

175
Catching Exceptions
  • Consider including a try/catch at the top of a
    threads stack if the error can be handled
    properly
  • Unhandled exceptions at the top of the main
    thread will terminate the app
  • In 2.0, unhandled exceptions at the top of the
    stack on any thread will terminate the app
  • But avoid catch blocks in finalizers
  • Be aware In many cases it is appropriate to
    let the app terminate

176
Catching Exceptions
  • Be aware of (but ignore) exceptions that dont
    inherit from System.Exception
  • Allowed in V1.0\V1.1, addressed in V2.0
  • See UnhandledException event on AppDomain

177
The perilous summit of complexity by example
178
How do I read all the lines from a file?
179
VS7 Era
IO seems like a reasonable place to start
180
Why did they make it inaccessible Backup, and try
again
181
Open.. Looks like a good first step
182
Hmm OK, what do I do with a FileStream?
183
Ok good, synchronous and asynchronous
operations.. What the heck is that?
184
I think I am in the wrong place..
185
Back up, lets try a different type
186
Ahh, ReadLine(), this looks more promising..
187
OK, How do you find the end?
188
Thanks goodness there was a sample
189
The pit of success way
  • developers fall into doing things the right way

190
Just what I need
191
Ah, a string I know just what to do with that
192
How simple!
193
Enable the Pit of Success by
  • Avoiding the perilous summit of complexity
  • And the desert of confusion

194
Addition Through Subtraction
10
5
15
195
Addition Through Subtraction
  • Add value by subtracting features
  • And the corollary
  • Remove value by adding features
  • More features ! More Value

196
Addition Through Subtraction By Example
  • CLR does not support multiple inheritance
  • No Set class in System.Collections
  • No String.OpenFile() method
  • What can you cut from your API to make it more
    valuable?

197
Addition Through Subtraction and Danger of
over-design
198
API Design Theater II
  • The Main Character
  • Bright young developer
  • The Setting
  • Her first big project
  • The Setup
  • Create a class that models a car
  • Actions required Start and Drive

199
Design Pass One Meets Requirements
  • Pass one meets requirements

200
Design Pass Two More than Enough
201
Design Pass Three Way too much
202
Time to Ship
Time to cut
203
What we ship Too much and not enough
204
V.Next Worse Yet
  • Now we want to add Color and Model, and we know
    exactly how
  • But it is much harder because the design is ½
    done and mostly wrong

205
The moral
  • Do as little as possible now (but no less) to
    ensure room for extensibility in the future

206
Some Specifics Guidelines on Designing for
Extensibility
207
Abstract and Base classes
  • Prefer broad, shallow hierarchies
  • Less than or equal to 2 additional levels Rough
    rule!
  • Contracts and responsibilities are difficult to
    maintain and explain in deep complex hierarchies
  • Consider making base classes not constructible
    (i.e. use Abstract classes)
  • Make it clear what the class is for
  • Provide a protected constructor for subclasses to
    call
  • System.Exception should not have had a public
    constructor

208
Virtual Method Example
public class TheBase Object public
override string ToString() return Hello
from the Base"
public class Derived TheBase public
override string ToString() return Hello
from Derived"
209
Virtual Methods
  • What is printed out?

Derived d new Derived() Console.WriteLine
(d.ToString())
TheBase tb d Console.WriteLine (tb.ToString())
Object o tb Console.WriteLine (o.ToString())
210
Virtual Methods
  • They all output Hello from Derived. Why?
  • Method call virtualizes at runtime
  • The static type doesnt matter
  • This is the danger and power of virtual methods
  • Danger Owner of base classes cannot control what
    subclasses do
  • Power Base class does not have to change as new
    subclasses are created

211
Overriding
  • Dont change the semantics of member
  • Follow the contract defined on the base class
  • All Virtual members should define a contract
  • Dont require clients to have knowledge of your
    overriding
  • Should you call the base?

212
Virtual and non-virtual
  • Use non-virtual members unless you have
    specifically designed for specialization
  • Have a concrete scenario in mind
  • Write the code!
  • Think before you virtualize members
  • References to base types must work with derived
    types without knowing the difference
  • Must continue to call in the same order and
    frequency
  • Cannot increase or decrease range of inputs or
    output
  • See the Liskov Substitution Principle

213
Interfaces versus Base Classes
  • Favor using base classes over interfaces
  • Base classes version better in general
  • Allows adding members
  • Members can be added with a default
    implementation
  • Avoids incompatibilities common in ActiveX
  • Interfaces are good for versioning behavior
    (changing semantics)

214
Interface Usage
public interface IComparable int
CompareTo(object obj)
  • Interfaces are useful!
  • Solves the multiple root problem
  • The smaller, more focused the interface the
    better
  • 1-2 members are best
  • But interfaces can be defined in terms of other
    simpler interfaces
  • Examples IComparable, IFormattable

215
  • The great proof of madness is the disproportion
    of one's designs to one's means. Napoleon
    Bonaparte

216
Exercises
217
Exercise Why Exceptions?
  • Which of the following are good reasons to use
    error codes rather than exceptions?
  • To avoid the base level overhead exceptions add
    to the system
  • I have always used error codes
  • It is easier to ignore errors when dealing with
    error codes
  • Error codes are easier to localize than exceptions

218
Exercise Creating your own Exceptions
  • What is wrong with this picture?

PrinterOutOfRedTonerException PrinterOutOfBlackAnd
WhiteTonerException PrinterOutOfBlueTonerException
PrinterOutOfGreenTonerException PrinterOnFireExce
ption PrinterOutOfPaperInTrayOneException PrinterO
utOfPaperInTrayTwoException PrinterOutOfPaperInTra
yThreeException PrinterOutOfPaperInTrayFourExcepti
on PrinterOutOfPaperInTrayFiveException
219
Exercise Handling Exceptions
  • Where is the best place to handle exceptions?
  • Close to where it is thrown
  • At the top level, where you have the most context
    to handle
  • No where, exceptions are scary
  • Early and often

220
Exercise Handling Exceptions
  • What is the main exception handling problem with
    this code?

try CallAMethod() CallAnotherMethod()
catch (Exception ) CallAThirdMethod()
221
Exercise Virtual Methods
  • Mark the following statements true or false
  • (True/False) Implementations of virtual methods
    can be effectively replaced by subclasses
  • (True/False) The Runtime insures that overridden
    methods call their base implementations
  • (True/False) Make as many members virtual as
    possible to allow for easy extensibility and
    versioning

222
Summary
  • Allow developers to fall into the pit of success
    using your framework by avoiding
  • The Perilous Summit of complexity
  • Have the right things get noticed
  • Create the right levels of abstraction
  • The Desert of Confusion
  • Add value by removing features
  • Danger of over design
  • Simple contracts are better

223
API Design Experience Design your Own
  • Krzysztof Cwalina
  • Brad Abrams

224
Design E-Mail Component
  • Requirements
  • Send simple text messages
  • Send messages with attachments
  • Simplicity is the main objective

225
Logistics
  • Work in pairs
  • Write the design on a piece of paper or on your
    laptop
  • If you want feedback
  • Send the design to kcwalina_at_microsoft.com or
  • Write your email above the design and leave the
    paper on your chair.
  • You have 20 minutes

226
Design Process
  • Remember Design Process
  • Samples
  • API Specification

227
Example Scenario Samples
228
Example API Specification
229
Design Experience Summary
  • Design an e-mail component
  • Send simple text messages
  • Send messages with attachments
  • Simplicity is the main objective
  • Work in pairs
  • Write on a piece of paper or your laptop
  • Scenario Samples
  • API Specification
  • If you want feedback
  • email us at kcwalina_at_microsoft.com
  • Write your email above the design and leave the
    paper on your chair.

230
In Closing
  • Brad Abrams
  • Krzysztof Cwalina

231
Four Keys of Framework Design
  • The Power of Sameness
  • Framework Design Matters
  • Tools for Communication
  • The Pit of Success

232
The Power of Sameness
  • Influence of expectations
  • Naming conventions and common suffixes\prefixes
  • Habits win out over the special cases
  • Common Exception pattern
  • With great power comes great responsibility
  • Method overloading
  • Meet developers where they are
  • constructors and properties pattern teaches us to
    meet developers expectations

233
Framework Design Matters
  • Framework design does not happen magically
  • Best frameworks are designed upfront by framework
    designers
  • There are several qualities of a well-designed
    framework that require focused framework design
    process

234
Tools for Communication
  • Dont force your consumers to be archeologists
    digging for how to use your framework
  • Every element in your design has a specific
    meaning Know them and use them correctly
  • Avoid the common mistakes
  • Make brand new mistakes

235
The Pit Of Success
  • Allow developers to fall into the pit of success
    using your framework by avoiding
  • The Perilous Summit of complexity
  • Have the right things get noticed
  • Create the right levels of abstraction
  • The Desert of Confusion
  • Add value by removing features
  • Danger of over design
  • Simple contracts are better

236
Feedback
  • We want your feedback, please take time to fill
    out the survey

And please blog
237
Resources
Framework Design Guidelines Conventions, Idioms,
and Patterns for Reusable .NET
Libraries Krzysztof Cwalina, Brad Abrams Signing
now or at the bookstore Wed 115-145
  • http//www.gotdotnet.com/team/fxcop/
  • Brad Abrams
  • brada_at_microsoft.com
  • http//blogs.msdn.com/brada
  • Krzysztof Cwalina
  • kcwalina_at_microsoft.com
  • http//blogs.msdn.com/kcwalina
About PowerShow.com