237
1 The Art of Building a The Art of Building a Reusable Class Library Reusable Class Library Brad Abrams – Brad Abrams – [email protected] [email protected] Krzysztof Cwalina - Krzysztof Cwalina - [email protected] [email protected] Microsoft Corporation Microsoft Corporation

1 The Art of Building a Reusable Class Library Brad Abrams – [email protected] Krzysztof Cwalina - [email protected] [email protected] [email protected]

Embed Size (px)

Citation preview

1

The Art of Building a The Art of Building a Reusable Class LibraryReusable Class Library

Brad Abrams – Brad Abrams – [email protected]@Microsoft.com Krzysztof Cwalina - Krzysztof Cwalina - [email protected]@Microsoft.com Microsoft CorporationMicrosoft Corporation

2

Turn frustrated developersTurn frustrated developers

… … into happy developersinto happy developers

3

GoalsGoals

Understand that API design mattersUnderstand that API design matters

Recognize good API designRecognize good API designLots of good and bad examplesLots of good and bad examples

Learn the API design processLearn the API design process

4

Who is this precon for?Who is this precon for?

1 10 100 1,000 10,000 100,000

Number of consumers

Val

ue

of th

is c

lass

1. Developers building reusable 1. Developers building reusable library or componentlibrary or component

2. Developer building apps to 2. Developer building apps to explicitly understand the rules of explicitly understand the rules of the .NET Framework and WinFXthe .NET Framework and WinFX

5

Quote of the dayQuote of the dayI have yet to see any I have yet to see any

problem, however problem, however complicated, which, complicated, which,

when looked at the right when looked at the right way did not become still way did not become still

more complicated. more complicated. Poul Anderson Poul Anderson

Being complex is Being complex is easy, being simple easy, being simple

is hardis hard

6

Labor79%

Software10%

Hardware11%

Project Cost ModelProject Cost Model

Source: Gartner, May 2002: “The Cost and Risk of Application Development Decisions”Joseph Feiman, Tom Berg

7

Four Keys of Framework Four Keys of Framework DesignDesign

Tools for CommunicationTools for Communication

The Power of SamenessThe Power of Sameness

Framework Design Framework Design MattersMatters

The Pit of SuccessThe Pit of Success

8

The Power of SamenessThe Power of Sameness

Brad AbramsBrad Abrams

9

When you pick up your When you pick up your rental car….rental car….

Push the seat all the way backPush the seat all the way back

Find an NPR stationFind an NPR station

Find the exitFind the exit

Read the Read the manual??manual??

10

Oh, down to lock…Oh, down to lock…

11

How to use a key…How to use a key…

12

Oh, you Oh, you pushpush the PRESS the PRESS button…button…

13

Who Who actually actually needs needs this this data?data?

14

Why you don’t read rental Why you don’t read rental car manuals car manuals

You know how to drive your carYou know how to drive your car

All cars work basically the same wayAll cars work basically the same way

Your rental car is a carYour rental car is a car

Therefore, you can drive your rental Therefore, you can drive your rental carcar

That is…That is…

15

Producers Producers and and

SamenesSameness s

Market Potential Market Potential

Standard SystemStandard System

New SystemNew System

16

Are things equally as Are things equally as obvious in your framework obvious in your framework designs? designs?

Maybe you are missing….Maybe you are missing….

17

Naming ConventionsNaming ConventionsPPascalascalCCasing – asing – Each word starts Each word starts with an with an uppercase letteruppercase letterccamelamelCCasing – asing – First word lower First word lower case, others case, others uppercaseuppercase

SCREAMING_CAPSCREAMING_CAPSS – All upper – All upper case with case with underscoresunderscores

18

““Blink” Quiz IBlink” Quiz I

class1 MyClass;;

Blink : The Power of Thinking Without Thinking

19

““Blink” Quiz IBlink” Quiz IAt-a-glance, first impressions… what At-a-glance, first impressions… what does this likely do?does this likely do?

A: Compiler errorA: Compiler error

B: Class declaration B: Class declaration

C: Variable declarationC: Variable declaration

D: OtherD: Other

class1 MyClass;;

Change the casing to match the Change the casing to match the pattern, is it easier to tell what this pattern, is it easier to tell what this is?is?Class1 myClass;;

20

Naming ConventionsNaming Conventions

All types and publicly exposed All types and publicly exposed members are PascalCasedmembers are PascalCased

Parameters are camelCasedParameters are camelCased

public class MemberDoc{ public int CompareTo(object value) public string Name { get;}}

Section 4.1, “Naming Conventions”Section 4.1, “Naming Conventions”

21

Hungarian NotationHungarian Notation

Do not use Hungarian notation in publicly Do not use Hungarian notation in publicly exposed APIs and parameter namesexposed APIs and parameter names

public class CMyClass {public class CMyClass { int CompareTo (object objValue) {..} int CompareTo (object objValue) {..} string lpstrName {get;} string lpstrName {get;} int iValue {get;} int iValue {get;}}}

22

Hungarian Notation Hungarian Notation (continued)(continued)

The prefix codes are arbitrary and The prefix codes are arbitrary and difficult to learndifficult to learn

They make it harder to read an They make it harder to read an identifier nameidentifier name

Hungarian was developed for a time Hungarian was developed for a time when languages were loosely typed when languages were loosely typed and IDEs were not as powerfuland IDEs were not as powerful

E.g. “out” and “ref” parameters E.g. “out” and “ref” parameters information now conveyed at the call information now conveyed at the call site.site.

Interlocked.Increment(ref i)Interlocked.Increment(ref i)

23

On Abbreviations, On Abbreviations, acronym, initialism and acronym, initialism and the like…the like…Avoid them! Avoid them!

They are a classic JLT (jargon loaded They are a classic JLT (jargon loaded term)term)

OK to use them once they become OK to use them once they become wordswords

Html, Xaml, etcHtml, Xaml, etc

Don’t just spell them outDon’t just spell them outUse a meaningful nameUse a meaningful name

Abbreviations of more than 2 letters Abbreviations of more than 2 letters are cased as words, otherwise are cased as words, otherwise ALLUPPERALLUPPER

IO vs. HtmlIO vs. Html

24

While we are on naming…While we are on naming…

Good naming is hard—it takes timeGood naming is hard—it takes timeBe meaningful but briefBe meaningful but brief

Use US-EnglishUse US-EnglishColourColour vs. vs. ColorColor

Principle of least surprise Principle of least surprise

Look for prior-artLook for prior-art NumberOfElementsNumberOfElements vs. vs. CountCount

25

““Blink” Quiz IIBlink” Quiz IIDoes this compile?Does this compile?

IFoo foo = new IFoo();IFoo foo = new IFoo();

““No” because you can’t create No” because you can’t create instances of interfacesinstances of interfaces

Why do we assume IFoo is an Why do we assume IFoo is an interface?interface?

26

Suffixes and PrefixesSuffixes and Prefixes

Interfaces prefix with “I”Interfaces prefix with “I”A tribute to COMA tribute to COM

Exceptions and Attributes suffixed Exceptions and Attributes suffixed

public interface IFormattable {}

Public class NameAttribute : Attribute {}

Public class PrinterOnFireException: Exception {}

Section 4.1, “Naming Conventions”Section 4.1, “Naming Conventions”

27

Quick QuizQuick Quiz

What is wrong this this type?What is wrong this this type?

public class ArgumentNullException : ArgumentException {

public ArgumentNullException () {} public ArgumentNullException (string paramName) {} public ArgumentNullException (string paramName,

string message) {}}

Section 7.3.4, “ArgumentNullException”Section 7.3.4, “ArgumentNullException”

28

Common Exception UsageCommon Exception Usage

Developers expect all exceptions to Developers expect all exceptions to work this way…work this way…

Make your exception meet Make your exception meet expectations…expectations…

throw new throw new IOException();IOException();

throw new throw new FormatException();FormatException();

throw new throw new ArgumentException();ArgumentException();

throw new throw new InvalidOperationException();InvalidOperationException();

29

Exception Constructor Exception Constructor PatternPattern

Every exception should have at Every exception should have at least the top three constructorsleast 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) {}

}

Section 7.4, “Designing Custom Exceptions”Section 7.4, “Designing Custom Exceptions”

30

Remember this type…. Remember this type….

What is wrong this this type?What is wrong this this type?

public class ArgumentNullException : ArgumentException {

public ArgumentNullException () {} public ArgumentNullException (string paramName) {} public ArgumentNullException (string paramName,

string message) {}}

Section 7.3.4, “ArgumentNullException”Section 7.3.4, “ArgumentNullException”

31

API design theater…API design theater…

The Developer The Architect

Why didn’t you follow the exception pattern?

Why didn’t you follow the exception pattern?

It doesn’t apply in this case

It doesn’t apply in this case

I see… why not?I see… why not?90% of the time

the message is not used, the param name is what is important

90% of the time the message is not used, the param name is what is important

You are optimizing locally, you are making the right

decision if developers only use your type, but if they use others as

well….

You are optimizing locally, you are making the right

decision if developers only use your type, but if they use others as

well….

32

Missing the power of Missing the power of samenesssameness

Result: Habit wins out and people Result: Habit wins out and people commonly type:commonly type:

• We end up with odd error messages such as:

• Moral: Just follow the pattern!

throw new ArgumentNullException ("the value must pass an employee name");

Unhandled Exception: System.ArgumentNullException: Value cannot be null.Parameter name: the value must pass an employee name

33

Method Overloading:Method Overloading:Abusing the Power of Abusing the Power of Sameness Sameness Overloaded: Method on the same Overloaded: Method on the same

type with the same name, but type with the same name, but different number or type of different number or type of arguments arguments

public static string ToString(int value) {}

public static string ToString(double value) {}

34

Dangers of Method Dangers of Method OverloadingOverloading

Meyer: A single operation Meyer: A single operation should do a single thing.. should do a single thing..

Bertrand Meyer

Why does this man dislike Why does this man dislike method overloading? method overloading?

Abrams: Good method Abrams: Good method overloading is a single thing overloading is a single thing – all overloads are – all overloads are semantically the samesemantically the same

35

Method OverloadingMethod OverloadingString.IndexOf(string value) {}

String.IndexOf(char[] anyOf) {}

string s = "brad abrams";s.IndexOf("ab"); // == 5s.IndexOf('ab'); // == 0

Cobol actually does allow Cobol actually does allow syntax like thissyntax like this

Moral: Don’t overload when the Moral: Don’t overload when the methods are semantically methods are semantically differentdifferentSection 5.1.1, “Method Overloading”Section 5.1.1, “Method Overloading”

36

String.IndexOf(string value) {}

String.IndexOf(char[] anyOf) {}

Convert.ToString(int value) {}

Convert.ToString(double value) {}

Method OverloadingMethod OverloadingUse overloading only when the Use overloading only when the overloads do semantically the overloads do semantically the same thingsame thing

Incorrect overload:Incorrect overload:

Correct overload:Correct overload:

Section 5.1.1, “Method Overloading”Section 5.1.1, “Method Overloading”

37

Method Overloading: Method Overloading: DefaultsDefaults

Use appropriate default valuesUse appropriate default valuesSimple method assumes default Simple method assumes default statestate

More complex methods indicate More complex methods indicate changes from the default statechanges from the default state

Use a zeroed state for the default Use a zeroed state for the default value (such as: 0, 0.0, false, null, value (such as: 0, 0.0, false, null, etc.etc.))

MethodInfo Type.GetMethod (string name); //ignoreCase = false

MethodInfo Type.GetMethod (string name, boolean ignoreCase);

Section 5.1.1, “Method Overloading”Section 5.1.1, “Method Overloading”

38

Constructors and Constructors and PropertiesPropertiesConstructor’s parameters are Constructor’s parameters are

shortcuts for setting propertiesshortcuts for setting propertiesNo difference in semantics between No difference in semantics between these code snippetsthese code snippets

EventLog log = new EventLog();log.MachineName = “kcwalina0”;log.Log = “Security”;

EventLog log = new EventLog(“Security”);log.MachineName = “kcwalina0”;

EventLog log = new EventLog(“Security”,”kcwalina0”);

Section 5.3, “Constructor Design”Section 5.3, “Constructor Design”

39

Exercises…Exercises…

40

Exercise: Code ReviewExercise: 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 ConventionsExercise: Naming Conventions

What are good reasons to What are good reasons to violate naming violate naming conventions?conventions?

A.A. ““I used to work in [C++, I used to work in [C++, Java, COBOL]”Java, COBOL]”

B.B. ““Our previous version used Our previous version used SCREAMING_CAP”SCREAMING_CAP”

C.C. ““These are initials from These are initials from someone’s name, they someone’s name, they have to be all upper case”have to be all upper case”

42

Exercise: Code ReviewExercise: Code Review

public interface Convertible {}

Public class CodeReviewer : Attribute {}

Public class InputInvalidError: Exception {}

43

Exercise: Code ReviewExercise: Code Review

public static int MaxValue = 9999999;

public void Withdraw () { Withdraw (MaxValue)}

public void Withdraw (int amount) { …}

44

SummarySummary

The Power of Sameness Teaches usInfluence of expectationsInfluence of expectations

Naming conventions and common suffixes\prefixes

Habits win out over the special Habits win out over the special casescases

Common Exception pattern

With great power comes great With great power comes great responsibilityresponsibility

Method overloading

Meet developers where they areMeet developers where they areconstructors and properties pattern teaches us to

meet developers’ expectations

45

Questions?Questions?

46

Framework Design MattersFramework Design Matters

The role of a framework designer in the The role of a framework designer in the development processdevelopment process

Krzysztof CwalinaKrzysztof CwalinaMicrosoftMicrosoft

47

The process of framework The process of framework design is very different from design is very different from

prototyping and prototyping and implementationimplementation

48

Developers focus on a Developers focus on a different leveldifferent level

49

Similarly to Similarly to implementations implementations framework design must be framework design must be ……

SimpleSimple

IntegratedIntegrated

ConsistentConsistent

EvolvableEvolvable

... but the similarities are ... but the similarities are superficialsuperficial

50

Well-designed framework Well-designed framework must be must be simplesimple

51

Focus on Top ScenariosFocus on Top Scenarios DoDo define top usage scenarios for define top usage scenarios for

each major feature area.each major feature area. DoDo design APIs by first writing code design APIs by first writing code

samples for the main scenarios and samples for the main scenarios and then defining the object model to then defining the object model to support the code samples.support the code samples.

Do notDo not require users to explicitly require users to explicitly instantiate more than one type in the instantiate more than one type in the most basic scenarios.most basic scenarios.

Section 2.2.1, “The Principle of Scenario-Driven Design”Section 2.2.1, “The Principle of Scenario-Driven Design”

52

Example: Scenario Example: Scenario SamplesSamples

Appendix C, “Sample API Specification”Appendix C, “Sample API Specification”

53

Namespace FactoringNamespace Factoring AvoidAvoid having types designed for having types designed for

advanced scenarios in the same advanced scenarios in the same namespace as types intended for namespace as types intended for common programming tasks.common programming tasks.

DoDo ensure that each main feature ensure that each main feature area namespace contains only types area namespace contains only types that are used in the most common that are used in the most common scenarios. Types used in advanced scenarios. Types used in advanced scenarios should be placed in scenarios should be placed in subnamespaces.subnamespaces.

Section 4.1, “Types and Namespaces”Section 4.1, “Types and Namespaces”

54

Example: Namespace Example: Namespace FactoringFactoring

55

NamingNaming DoDo favor readability over brevity. The favor readability over brevity. The

property name CanScrollHorizontally is property name CanScrollHorizontally is better than ScrollableX (an obscure better than ScrollableX (an obscure reference to the X-axis).reference to the X-axis).

Do notDo not use abbreviations or contractions use abbreviations or contractions as parts of identifier names. as parts of identifier names.

Do notDo not use any acronyms that are not use any acronyms that are not widely accepted, and then, only when widely accepted, and then, only when necessary. necessary.

DoDo reserve the best type names for the reserve the best type names for the most commonly used types.most commonly used types.

Section 3.2, “General Naming Conventions”Section 3.2, “General Naming Conventions”

56

Example : NamingExample : Naming

57

ExceptionsExceptions DoDo use exception messages to use exception messages to

communicate framework usage communicate framework usage mistakes to the developer. mistakes to the developer.

Section 7.1, “Exception Throwing”Section 7.1, “Exception Throwing”

58

Example: ExceptionsExample: ExceptionsEventLog log = new EventLog();EventLog log = new EventLog();Log.WriteEntry(“Hello World”);Log.WriteEntry(“Hello World”);

59

Well-designed framework Well-designed framework must be must be explicitly explicitly

designeddesigned

60

Create API SpecificationCreate API Specification

Appendix C, “Sample API Specification”Appendix C, “Sample API Specification”

61

Review Scenario SamplesReview Scenario Samples

Solicit feedback on the scenario Solicit feedback on the scenario samplessamples

Feedback from non-expertsFeedback from non-experts

62

Review API DesignReview API Design

63

Well-designed framework Well-designed framework is a part of an is a part of an ecosystemecosystem

64

IntellisenseIntellisense

65

EditorBrowsableAttributeEditorBrowsableAttributepublic class MyComponent {public class MyComponent { [EditorBrowsable(EditorBrowsableState.Always)][EditorBrowsable(EditorBrowsableState.Always)] public void CommonlyUsedMethod() {public void CommonlyUsedMethod() { … … }}

[EditorBrowsable(EditorBrowsableState.Never)][EditorBrowsable(EditorBrowsableState.Never)] public void RarelyUsedMethod() {public void RarelyUsedMethod() { … … }}

[EditorBrowsable(EditorBrowsableState.Never)][EditorBrowsable(EditorBrowsableState.Never)] public override int GetHashCode() {public override int GetHashCode() { return base.GetHashCode();return base.GetHashCode(); }}}}

66

Naming Related MembersNaming Related Members

67

Naming Related Members Naming Related Members FixedFixed

68

DebuggerDebugger

69

Debugger AttributesDebugger Attributes[DebuggerTypeProxy(typeof(LinkedListDebugger[DebuggerTypeProxy(typeof(LinkedListDebuggerView<>))]View<>))]public class LinkedList<T> {public class LinkedList<T> {……}}

internal class LinkedListDebuggerView<T> {internal class LinkedListDebuggerView<T> { public LinkedListDebuggerView(LinkedList<T> list) public LinkedListDebuggerView(LinkedList<T> list) { … }{ … } [DebuggerBrowsable(DebuggerBrowsableState.RootHid[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]den)] public T[] Items { public T[] Items { get { … }get { … } } } } }

70

Debugger Attributes Debugger Attributes ResultResult

71

CLS ComplianceCLS Compliance DoDo apply CLSCompliantAttribute to apply CLSCompliantAttribute to

framework assemblies.framework assemblies.

[assembly:CLSCompliant(true)][assembly:CLSCompliant(true)]

72

Example: CLS ComplianceExample: CLS Compliance

73

Well-designed framework Well-designed framework must be must be integratedintegrated

74

Using Common Using Common AbstractionsAbstractions DoDo use the least derived parameter use the least derived parameter

type that provides the functionality type that provides the functionality required by the member. required by the member.

DoDo use the least specialized type use the least specialized type possible as a parameter type. Most possible as a parameter type. Most members taking collections as members taking collections as parameters use IEnumerable<T> parameters use IEnumerable<T> interface.interface.

DoDo implement IEquatable<T> on implement IEquatable<T> on value types.value types.

Section 5.7, “Parameter Design” (among others)Section 5.7, “Parameter Design” (among others)

75

Collection AbstractionsCollection Abstractions

76

Collection Abstractions Collection Abstractions FixedFixed

77

Type Name ConflictsType Name Conflicts

Do notDo not introduce generic type introduce generic type names such as ‘Element’, ‘Node’, names such as ‘Element’, ‘Node’, ‘Log, and ‘Message’. ‘Log, and ‘Message’.

Section 3.4.1, “Namespaces and Type Name Conflicts”Section 3.4.1, “Namespaces and Type Name Conflicts”

78

Example: Type Name Example: Type Name ConflictsConflicts

79

Type Name Conflicts – Type Name Conflicts – Fixed by UserFixed by User

80

Type Name Conflicts – Type Name Conflicts – Fixed by Framework Fixed by Framework DesignerDesigner

81

Well-designed framework Well-designed framework must be must be designed to designed to

evolveevolve

82

Interfaces vs. Abstract Interfaces vs. Abstract ClassesClasses DoDo favor defining classes over favor defining classes over

interfaces. interfaces.

Section 4.3, “Choosing Between Class and Interface”Section 4.3, “Choosing Between Class and Interface”

83

Example: Adding Members Example: Adding Members to Abstractionsto Abstractionspublic abstract class Stream {public abstract class Stream { // new Stream members to support timeouts// new Stream members to support timeouts public virtual int ReadTimeout{public virtual int ReadTimeout{ get{get{ throw new throw new NotSupportedException(…);NotSupportedException(…); } } set{set{ throw new throw new NotSupportedException(…);NotSupportedException(…); } } }} public virtual bool CanTimeout {public virtual bool CanTimeout { get { return false; }get { return false; } }} // other Stream members that shipped // other Stream members that shipped previouslypreviously … …}}

84

Example: Adding Example: Adding Functionality in Functionality in SubclassesSubclassespublic class FileStream : Stream {public class FileStream : Stream { public override bool CanTimeout {public override bool CanTimeout { get { return true; }get { return true; } }} public override int ReadTimeout{public override int ReadTimeout{ get{ … }get{ … } set{ … }set{ … } }}}}

85

Example: Interface Based Example: Interface Based DesignDesign

public interface IStream {public interface IStream { … …}}

public class FileStream : IStream {public class FileStream : IStream { … …}}

86

Example: Interface Based Example: Interface Based Design – Adding TimeoutDesign – Adding Timeoutpublic interface ITimeoutEnabledStream : public interface ITimeoutEnabledStream : IStream {IStream { int ReadTimeout{ get; set; }int ReadTimeout{ get; set; }}}

public class FileStream : public class FileStream : ITimeoutEnabledStream {ITimeoutEnabledStream { public int ReadTimeout{public int ReadTimeout{ get{ … }get{ … } set{ … }set{ … } }}}}

87

Example: Interface Based Example: Interface Based Design – ProblemDesign – ProblemStreamReader reader = GetSomeReader();StreamReader reader = GetSomeReader();

// dynamic cast (BaseStream returns Stream)// dynamic cast (BaseStream returns Stream)ITimeoutEnabledStream stream = ITimeoutEnabledStream stream = reader.BaseStream as ITimeoutEnabledStream;reader.BaseStream as ITimeoutEnabledStream;

if(stream != null){if(stream != null){ stream.ReadTimout = 100;stream.ReadTimout = 100;}}

88

Example: Abstract Class is Example: Abstract Class is BetterBetter

StreamReader reader = GetSomeReader();StreamReader reader = GetSomeReader();if(reader.BaseStream.CanTimeout){if(reader.BaseStream.CanTimeout){ reader.BaseStream.ReadTimeout = 100;reader.BaseStream.ReadTimeout = 100;}}

89

Control ExtensibilityControl Extensibility Do notDo not make members virtual unless make members virtual unless

you have a good reason to do so and you have a good reason to do so and you are aware of all the costs related you are aware of all the costs related to designing, testing, and maintaining to designing, testing, and maintaining virtual members. virtual members.

Section 6.1.4, “Virtual Members”Section 6.1.4, “Virtual Members”

90

Test AbstractionsTest Abstractions

DoDo provide at least one type that is provide at least one type that is an implementation of an interface. an implementation of an interface.

DoDo provide at least one API provide at least one API consuming each interface you define consuming each interface you define (a method taking the interface as a (a method taking the interface as a parameter or a property typed as the parameter or a property typed as the interface). interface).

Section 5.6, “Interface Design”Section 5.6, “Interface Design”

91

Well-designed framework Well-designed framework must be must be consistentconsistent

92

Naming ConsistencyNaming ConsistencyBase 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.

Section 3.5.2, “Names of Common Types”Section 3.5.2, “Names of Common Types”

93

Common Patterns and Common Patterns and IdiomsIdioms

Attribute DesignAttribute Design

Collection UsageCollection Usage

XML UsageXML Usage

The Async PatternThe Async Pattern

Dispose PatternDispose Pattern

Sections 8 and 9, “Usage Guidelines” and “Common Design Patterns”Sections 8 and 9, “Usage Guidelines” and “Common Design Patterns”

94

Exercise: API Design ProcessExercise: API Design Process

Which of the following is the Which of the following is the best way to start API design?best way to start API design?

A)A) Sit in front of a computer and Sit in front of a computer and start coding.start coding.

B)B) Use class diagrams to discover Use class diagrams to discover main entities of the system.main entities of the system.

C)C) Create a list of most common Create a list of most common scenarios and write code scenarios and write code samples corresponding to the samples corresponding to the scenarios.scenarios.

95

Exercise: EcosystemExercise: Ecosystem

What parts of the What parts of the development environment development environment need to be considered when need to be considered when designing APIs?designing APIs?

A)A) IntellisenseIntellisense

B)B) DebuggersDebuggers

C)C) DocumentationDocumentation

D)D) All of the aboveAll of the above

96

Exercise: Simplicity and Exercise: Simplicity and UsabilityUsability

What is the main contributor What is the main contributor to framework usability?to framework usability?

A)A) How easy it is to find the right How easy it is to find the right type to use.type to use.

B)B) How easy it is to find the right How easy it is to find the right member to use.member to use.

C)C) Clear exception messages.Clear exception messages.

97

SummarySummary

Framework design does not happen Framework design does not happen magicallymagically

Best frameworks are designed Best frameworks are designed upfront by framework designersupfront by framework designers

There are several qualities of a well-There are several qualities of a well-designed framework that require designed framework that require focused framework design processfocused framework design process

98

Questions?Questions?

99

API Design Experience:API Design Experience:The API reviewThe API review

Krzysztof CwalinaKrzysztof CwalinaBrad AbramsBrad Abrams

100

Goals for this ExerciseGoals for this Exercise

Demonstrate how the API design Demonstrate how the API design experience really goes experience really goes

Show you some common mistakes Show you some common mistakes and common fixesand common fixes

Laugh with us as we roll play this.. Laugh with us as we roll play this..

101

Comment [KC1]:Why use an interface rather than a base class?

102

Comment [KC1]:Why is this sealed?

103

Comment [KC1]:Should it be a value type?

104

Comment [KC1]:Make this a static class?

105

Comment [KC2]:Why not throw an exception?

106

107

What we showed you… What we showed you…

Demonstrated a few examples of how Demonstrated a few examples of how the API design experience really goes the API design experience really goes

Show you some common mistakes Show you some common mistakes and common fixesand common fixes

108

Tools for CommunicationTools for Communication

Brad AbramsBrad Abrams

109

Focus on developer, not Focus on developer, not yourselfyourself

110

Your developers can’t Your developers can’t read your mindread your mind

111

You must communicate… You must communicate…

Examples of what consumers need to Examples of what consumers need to know… know…

• Will this operation block?Will this operation block?

• How do I customize this type?How do I customize this type?

• How should I use this class?How should I use this class?

112

Wouldn’t it be great… Wouldn’t it be great…

Luckily, there are Tools for CommunicatingLuckily, there are Tools for Communicating

113

Documentation alone is Documentation alone is not enoughnot enough

114

Good documentation on a Good documentation on a bad API is…bad API is…

like lipstick on a pig…like lipstick on a pig…

115

Communicate via leaving Communicate via leaving artifacts artifacts

Framework Framework Design Artifacts:Design Artifacts:• TypesTypes• MethodsMethods• PropertiesProperties• EventsEvents• ConstructorsConstructors

116

Why is Archeology so Why is Archeology so hard?hard?

All we have is All we have is what they left uswhat they left us

We can’t directly We can’t directly talk to anyone that talk to anyone that built thembuilt them

Hard to find pieces Hard to find pieces of fragments that of fragments that fit togetherfit together

Bottom line: Bottom line: ancient ancient civilizations were civilizations were not intentional not intentional about what they about what they left behind left behind

Rosetta StoneRosetta Stone

117Follow a common Follow a common

vocabulary vocabulary

Don’t force consumers to Don’t force consumers to become archeologists of become archeologists of

your framework… your framework…

118

Follow a Common Follow a Common VocabularyVocabulary

Pre-School level vocabulary for Pre-School level vocabulary for EnglishEnglish

What is the common vocabulary for What is the common vocabulary for API design?API design?

119

Define: NamespaceDefine: Namespace

Organizational principle to allow Organizational principle to allow consumers to:consumers to:

Find relevant functionality quicklyFind relevant functionality quickly

Exclude less relevant functionality Exclude less relevant functionality

Not about implementation issues Not about implementation issues Security, identity, size, perf Security, identity, size, perf

Not a billboard to advertise your Not a billboard to advertise your organizationalorganizational

namespace System.IO {}

Section 4.1, “Types and Namespaces”Section 4.1, “Types and Namespaces”

120

Define: ClassDefine: Class

A conceptual model for a A conceptual model for a thingthing which which can hold state, perform actions, etccan hold state, perform actions, etc

Common API design problemsCommon API design problemsGrab bag types (lack of cohesion)Grab bag types (lack of cohesion)

Example: Example: System.Runtime.InteropServices.MarshalSystem.Runtime.InteropServices.Marshal

Modeling overly abstractModeling overly abstractExample: StreamReader vs. File Example: StreamReader vs. File

public class Object {}

Section 4.1, “Types and Namespaces”Section 4.1, “Types and Namespaces”

121

Define: StructDefine: Struct

A domain specific extension of the intrinsic A domain specific extension of the intrinsic type systemtype system

Example: Point, Complex, etcExample: Point, Complex, etc

Expert use: perf optimization when GC-Expert use: perf optimization when GC-Heap allocated objects not warrantedHeap allocated objects not warranted

Example : an EnumeratorExample : an Enumerator

Common API design problems:Common API design problems:Overuse to avoid GCOveruse to avoid GC

instance size over 16 bytesinstance size over 16 bytes

Are not immutableAre not immutable

public struct Int32 : IComparable,public struct Int32 : IComparable, IFormattable {} IFormattable {}

Section 4.2, “Choosing between class and struct”Section 4.2, “Choosing between class and struct”

122

Quick Quiz Quick Quiz What is wrong with this type?What is wrong with this type?

public sealed class Environment {public sealed class Environment {private Environment () { }private Environment () { }

public bool HasShutDownStarted { public bool HasShutDownStarted { get {} get {}

}}}}

Section 4.5, “Static Class DesignSection 4.5, “Static Class Design

123

Define: Static ClassDefine: Static ClassContainer for a set of highly related Container for a set of highly related static members. Commonly used for:static members. Commonly used for:

Full OO encapsulation not warrantedFull OO encapsulation not warrantedExample: System.MathExample: System.Math

Convenience methods for a more Convenience methods for a more complex designcomplex design

Example: System.IO.FileExample: System.IO.File

Common API design problemsCommon API design problems

Doing it “by hand” and getting it wrong Doing it “by hand” and getting it wrong

Loose cohesion Loose cohesion

Section 4.5, “Static Class DesignSection 4.5, “Static Class Design

124

Static Classes: Under the Static Classes: Under the CoversCoverspublic 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: ExceptionsDefine: Exceptions

Encapsulation of error details used in a Encapsulation of error details used in a structured exception handling systemstructured exception handling system

Common API Design MistakesCommon API Design MistakesUsing error codes rather the exceptionsUsing error codes rather the exceptions

Creating far too many exceptionsCreating far too many exceptionsOnly create new exceptions if callers will handle them Only create new exceptions if callers will handle them differentlydifferently

Section 7, “Exception”Section 7, “Exception”

public class FileNotFoundException : IOException

126

Define: EnumDefine: Enum

Container for Container for named constantsnamed constants

public enum Colors public enum Colors { { Red = 0, Red = 0, Green = 1, Green = 1, Blue = 2 Blue = 2}}

Common API Design MistakesCommon API Design MistakesAccepting the default valuesAccepting the default values

Using “magic” constants insteadUsing “magic” constants instead

SetColor(Colors.Red);SetColor(Colors.Red);SetColor(1);SetColor(1);

Section 4.8, “Enum DesignSection 4.8, “Enum Design

127

Enums: Under the CoversEnums: Under the Covers

Enum values default to 0..NEnum values default to 0..N

public enum Compression {public enum Compression { Zip, SuperZip, NoneZip, SuperZip, None }}

public struct Compression : Enum {public struct Compression : Enum { public int value__;public int value__; public const Compression Zip = 0; public const Compression Zip = 0; public const Compression SuperZip = 1;public const Compression SuperZip = 1; public const Compression None = 2;public const Compression None = 2;}}

128

Define: Flags EnumsDefine: Flags EnumsCombinable Combinable enumenum

FlagsAttibutFlagsAttibutee

powers of 2powers of 2

[Flags] [Flags] public enum AttributeTargets public enum AttributeTargets { { Assembly = 0x0001, Assembly = 0x0001, Module = 0x0002, Module = 0x0002, Class = 0x0004, Class = 0x0004, Struct = 0x0008, Struct = 0x0008, Type = Class | Struct, Type = Class | Struct,}}

Use plural namesUse plural namesAttributeTargetAttributeTargetss rather than rather than AttributeTargetAttributeTarget

Provide named constants for Provide named constants for common flagscommon flags

129

Flag Enums: Common Flag Enums: Common MistakesMistakes

Only use Flag enums when they Only use Flag enums when they represent a single conceptrepresent a single concept

AttributeTargets is good example AttributeTargets is good example

The Reflection BindingFlags is an The Reflection BindingFlags is an example of what example of what notnot to do to do

Contains many different concepts in a single Contains many different concepts in a single value (visibility, static-ness, member kind, value (visibility, static-ness, member kind, etc.etc.))

Should not be suffixed in “Flags”Should not be suffixed in “Flags”

130

Define: ConstructorDefine: Constructor

Facility to capture state for an Facility to capture state for an instance at time of instantiation instance at time of instantiation

Common API design problemCommon API design problemDoing too much work in the constructorDoing too much work in the constructor

public class Employee {public class Employee { public Employee (string name) {} public Employee (string name) {}}}

Section 5.3, “Constructor Design”Section 5.3, “Constructor Design”

131

Constructors areConstructors are

Do minimal work in Do minimal work in the constructorthe constructor

Be Lazy! Be Lazy!

Only capture the Only capture the parametersparameters

public class XmlFile {public class XmlFile { string fileName; string fileName; Stream data; Stream data; public XmlFile(string fileName) { public XmlFile(string fileName) { this.data = DownloadData(fileName); this.data = DownloadData(fileName); }}}}

public XmlFile(string fileName) {public XmlFile(string fileName) { this.fileName = fileName; this.fileName = fileName; } }

lazylazy

132

Define: MethodsDefine: Methods

Used to expose actions or operationsUsed to expose actions or operations

Common API Design ProblemCommon API Design ProblemUsing properties where methods should Using properties where methods should be usedbe used

public sealed class String {public sealed class String { public string Insert (string value, public string Insert (string value,

int position) int position)}}

Section 5.1, “General Member Design”Section 5.1, “General Member Design”

133

Properties versus MethodsProperties versus Methods

Use a Property:Use a Property:If the member logical attribute of the If the member logical attribute of the typetype

Use a method: Use a method: If the operation is a conversion, such as If the operation is a conversion, such as ToString()ToString()

If the getter has an observable side If the getter has an observable side effecteffect

If order of execution is importantIf order of execution is important

If the method might not return If the method might not return immediatelyimmediately

If the member returns an arrayIf the member returns an array

134

EmployeeList l = FillList();EmployeeList l = FillList();for (int i = 0; i < l.Length; i++) for (int i = 0; i < l.Length; i++) {{ if (l.All[i] == x){...}if (l.All[i] == x){...}}} if (l.GetAll()[i]== x) {...}if (l.GetAll()[i]== x) {...}

public Employee[] All {get{}}public Employee[] All {get{}}

public Employee[] GetAll() {}public Employee[] GetAll() {}

Moral: Use method if the operation is expensive Moral: Use method if the operation is expensive

Calling CodeCalling Code creates 2n+1 copies of creates 2n+1 copies of the arraysthe arrays

Properties and returning Properties and returning arraysarrays

Section 5.1, “General Member Design”Section 5.1, “General Member Design”

135

Define: FieldsDefine: FieldsUseful for exposing implementation Useful for exposing implementation details thereby constraining your details thereby constraining your ability to evolve the frameworkability to evolve the framework

Or, just use properties… Or, just use properties…

Section 4.5, “Field Design”Section 4.5, “Field Design”

public String FileName;public String FileName;

private String fileName;private String fileName;public String FileName{public String FileName{ get { return fileName; } get { return fileName; } set { fileName = value; } set { fileName = value; }}}

136

Const versus ReadonlyConst versus Readonlyconstconst

Compile-time Compile-time evaluationevaluation

Stable across Stable across versionsversions

readonlyreadonlyRun-time Run-time evaluationevaluation

Unstable across Unstable across versionsversionsclass Math {class Math {

public const double Pi = 3.14;public const double Pi = 3.14;}}

class Color {class Color { public static readonly Color Red = new public static readonly Color Red = new Color(...);Color(...); public static readonly Color Blue = new public static readonly Color Blue = new Color(...);Color(...); public static readonly Color Green = new public static readonly Color Green = new Color(...);Color(...);}}

137

Define: PropertiesDefine: Properties

Logical backing field. Useful to Logical backing field. Useful to encapsulate access to state allowing encapsulate access to state allowing a degree of flexibility in a degree of flexibility in implementationimplementation

Common API Design ProblemCommon API Design ProblemProperty vs. Method confusionProperty vs. Method confusion

public class ArrayList {public class ArrayList { public int Count {get{}} public int Count {get{}}}}

Section 5.2, “Property Design”Section 5.2, “Property Design”

138

PropertiesPropertiesUse read only properties where Use read only properties where appropriateappropriate

Do not use write-only propertiesDo not use write-only properties

Property getters should be simple Property getters should be simple and therefore unlikely to throw and therefore unlikely to throw exceptionsexceptions

Properties should not have Properties should not have dependencies on each otherdependencies on each other

Setting one property should not affect Setting one property should not affect other propertiesother properties

Properties should be settable in any Properties should be settable in any orderorder

139

public delegate void EventHandler(object sender,public delegate void EventHandler(object sender, EventArgs e);EventArgs e);

public class Button: Control {public class Button: Control { public event EventHandler Click; public event EventHandler Click;

protected void OnClick(EventArgs e) {protected void OnClick(EventArgs e) { if (Click != null) if (Click != null) Click(this, e);Click(this, e); } }}}

Define: EventsDefine: Events

Expose callback operationExpose callback operation

Event Event

HandlerHandler

EventEvent

Raise Raise

MethodMethod

Section 5.4, “Event Design”Section 5.4, “Event Design”

140

Common Design Problem Common Design Problem with Events with Events

Using bad terminologyUsing bad terminologyEvents are not “fired” or “triggered”, Events are not “fired” or “triggered”, they are “raised”they are “raised”

Not using verbsNot using verbsE.g.E.g.: Click, Paint, DrawItem, DropDown: Click, Paint, DrawItem, DropDown

Not using strongly typed EventArgs Not using strongly typed EventArgs to allow for extensibility to allow for extensibility public class MouseEventArgs :public class MouseEventArgs : EventArgs { } EventArgs { }

Section 5.4, “Event Design”Section 5.4, “Event Design”

141

Static MembersStatic MembersStatics are the .NET equivalent of Statics are the .NET equivalent of global variables or global functionsglobal variables or global functions

Not object orientedNot object oriented

Same evils as globalSame evils as global

But can be very usefulBut can be very useful System.Math– Full modeling not requiredSystem.Math– Full modeling not required

public class Int32 {public class Int32 { public static int Parse (string value) {..}public static int Parse (string value) {..}}}

int i = Int32.Parse ("42");int i = Int32.Parse ("42");

142

Exercises…Exercises…

143

Exercise: NamespacesExercise: Namespaces

What is a good reason to split What is a good reason to split some related functionality some related functionality across two namespaces?across two namespaces?

A.A. Two different orgs create Two different orgs create themthem

B.B. They are in two different They are in two different assembliesassemblies

C.C. One is the 90% usage case One is the 90% usage case the other in the 10% usage the other in the 10% usage casecase

144

Exercise: class or struct? Exercise: class or struct?

public public ??? ??? DataValues {DataValues { decimal d1; decimal d1; decimal d2; decimal d2; decimal d3; decimal d3; decimal d4; decimal d4; public void SetValue (decimal d) {} public void SetValue (decimal d) {}}}

145

Exercise: ExceptionsExercise: Exceptions

What are good reasons to What are good reasons to create a new exception create a new exception type?type?

A.A. I get paid by number of I get paid by number of typestypes

B.B. The underlying system call The underlying system call returns two different valuesreturns two different values

C.C. Users handle the two cases Users handle the two cases differentlydifferently

146

Exercise: EnumsExercise: Enums

Code review: Code review:

public enum Fruits { Banana, Apple, Peach, Blueberry}

147

SummarySummary

Don’t force your consumers to be Don’t force your consumers to be archeologists digging for how to use archeologists digging for how to use your frameworkyour framework

Every element in your design has a Every element in your design has a specific meaning – Know them and specific meaning – Know them and use them correctlyuse them correctly

Avoid the common mistakesAvoid the common mistakesMake brand new mistakes Make brand new mistakes

148

QuestionsQuestions

149

API Design Experience:API Design Experience:Designing From Scratch Designing From Scratch

Krzysztof CwalinaKrzysztof CwalinaBrad AbramsBrad Abrams

150

Goals for this ExerciseGoals for this Exercise

Demonstrate how the API design Demonstrate how the API design experience really goes experience really goes

Show you some common mistakes Show you some common mistakes and common fixesand common fixes

How to identify a complex designHow to identify a complex design

How to use scenarios to fix the designHow to use scenarios to fix the design

Laugh at with us as we roll play this.. Laugh at with us as we roll play this..

151

Assignment:

Design Design a Serial a Serial Port Port APIAPI

Assignment:

Design Design a Serial a Serial Port Port APIAPI

152

SerialPort

SerialCommunicationsPipeline

«implementation class»Ports

«metaclass»PortsBase

CommunicationPipe

ZeroWayCommunicationPipe OneWayCommunicationPipe

N_WayCommunicationPipe

ByteUnpacker

«metaclass»AbstractUnpacker

DoubleUnpacker

BytePacker

«metaclass»AbstractPacker

DoublePacker

«metaclass»PackerBase

AdopterRoot

AsyncAdopterRoot

BufferedReadAdopterRoot

BufferAdopterRoot

BufferedWriteAdopterRoot

TranscatedAdopterRoot

153

if(value != handshake) {if(value != handshake) {// in the DCB, handshake affects the fRtsControl, fOutxCtsFlow, and fInX, fOutX // in the DCB, handshake affects the fRtsControl, fOutxCtsFlow, and fInX, fOutX fields,fields,// so we must save everything in that closure before making any changes.// so we must save everything in that closure before making any changes.Handshake handshakeOld = handshake;Handshake handshakeOld = handshake;int fInOutXOld = GetDcbFlag(NativeMethods.FINX);int fInOutXOld = GetDcbFlag(NativeMethods.FINX);int fOutxCtsFlowOld = GetDcbFlag(NativeMethods.FOUTXCTSFLOW);int fOutxCtsFlowOld = GetDcbFlag(NativeMethods.FOUTXCTSFLOW);int fRtsControlOld = GetDcbFlag(NativeMethods.FRTSCONTROL);int fRtsControlOld = GetDcbFlag(NativeMethods.FRTSCONTROL);handshake = value;handshake = value;int fInXOutXFlag = (handshake == Handshake.XOnXOff || handshake == int fInXOutXFlag = (handshake == Handshake.XOnXOff || handshake == Handshake.RequestToSendXOnXOff) ? 1 : 0;Handshake.RequestToSendXOnXOff) ? 1 : 0;SetDcbFlag(NativeMethods.FINX, fInXOutXFlag);SetDcbFlag(NativeMethods.FINX, fInXOutXFlag);SetDcbFlag(NativeMethods.FOUTX, fInXOutXFlag);SetDcbFlag(NativeMethods.FOUTX, fInXOutXFlag);SetDcbFlag(NativeMethods.FOUTXCTSFLOW, (handshake == Handshake.RequestToSend ||SetDcbFlag(NativeMethods.FOUTXCTSFLOW, (handshake == Handshake.RequestToSend || handshake == Handshake.RequestToSendXOnXOff) ? 1 : 0);handshake == Handshake.RequestToSendXOnXOff) ? 1 : 0);if ((handshake == Handshake.RequestToSend ||if ((handshake == Handshake.RequestToSend || handshake == Handshake.RequestToSendXOnXOff)){handshake == Handshake.RequestToSendXOnXOff)){SetDcbFlag(NativeMethods.FRTSCONTROL) }SetDcbFlag(NativeMethods.FRTSCONTROL) }} } if (SetCommState(_handle, ref dcb) == false) {if (SetCommState(_handle, ref dcb) == false) { handshake = handshakeOld;handshake = handshakeOld; SetDcbFlag(NativeMethods.FINX, fInOutXOld);SetDcbFlag(NativeMethods.FINX, fInOutXOld); SetDcbFlag(NativeMethods.FOUTX, fInOutXOld);SetDcbFlag(NativeMethods.FOUTX, fInOutXOld); SetDcbFlag(NativeMethods.FOUTXCTSFLOW, fOutxCtsFlowOld);SetDcbFlag(NativeMethods.FOUTXCTSFLOW, fOutxCtsFlowOld); SetDcbFlag(NativeMethods.FRTSCONTROL, fRtsControlOld);SetDcbFlag(NativeMethods.FRTSCONTROL, fRtsControlOld); InternalResources.WinIOError();InternalResources.WinIOError();} }} }

154

string num = “234-567-8901”;string num = “234-567-8901”;using (SerialPort mySerialPort = new SerialPort(“COM1”, 14400)) using (SerialPort mySerialPort = new SerialPort(“COM1”, 14400)) {{

mySerialPort.DtrEnable = true;mySerialPort.DtrEnable = true;mySerialPort.Open();mySerialPort.Open();mySerialPort.Write(“ATDT” + num + Environment.NewLine);mySerialPort.Write(“ATDT” + num + Environment.NewLine);mySerialPort.Close();mySerialPort.Close();

}}

Dim Incoming as StringDim Incoming as StringUsing (Dim sp As New SerialPort (“COM1”, 14400))Using (Dim sp As New SerialPort (“COM1”, 14400))

Incoming = sp.Read()Incoming = sp.Read()End UsingEnd Using

155

public sealed class SerialPort : Component {public sealed class SerialPort : Component {public int InfiniteTimeOut = -1;public int InfiniteTimeOut = -1;public int BaudRate { get; set; }public int BaudRate { get; set; }public int PortName { get; set; }public int PortName { get; set; }public int DataBits { get; set; }public int DataBits { get; set; }public StopBits StopBits { get; set; }public StopBits StopBits { get; set; }public Encoding Encoding { get; set; }public Encoding Encoding { get; set; }public int ReadTimeout { get; set; }public int ReadTimeout { get; set; }public int WriteTimeout { get; set; }public int WriteTimeout { get; set; }public Stream BaseStream { get; }public Stream BaseStream { get; }public int ReceivedBytesThreshold { get; set; }public int ReceivedBytesThreshold { get; set; }public bool CDHolding { get; }public bool CDHolding { get; }public bool CtsHolding { get; }public bool CtsHolding { get; }public bool DsrHolding { get; }public bool DsrHolding { get; }public SerialPort ();public SerialPort ();public SerialPort (string port);public SerialPort (string port);public SerialPort (string port, int baudRate);public SerialPort (string port, int baudRate);public void Open();public void Open();public void Close();public void Close();public int ReadChar();public int ReadChar();public void Write(string value);public void Write(string value);public event SerialPinChangedEventHandler PinChangedEvent;public event SerialPinChangedEventHandler PinChangedEvent;public event SerialErrorEventHandler ErrorEvent;public event SerialErrorEventHandler ErrorEvent;

}}

156

157

What we showed you…What we showed you…

How to identify a complex designHow to identify a complex design

How to use scenarios to fix the How to use scenarios to fix the designdesign

158

The Pit of SuccessThe Pit of Success

Brad AbramsBrad Abrams

159

The Pit of SuccessThe Pit of Success: in stark : in stark contrast to a summit, a peak, or contrast to a summit, a peak, or

a journey across a desert to a journey across a desert to find victory through many trialsfind victory through many trials

and surprises, we want our and surprises, we want our customers to customers to simply fall into simply fall into

winning practiceswinning practices by using our by using our platform and frameworks. To platform and frameworks. To

the extent that the extent that we make it easy we make it easy to get into trouble we failto get into trouble we fail..

- Rico Mariani- Rico Mariani

160

Is using your framework correctly Is using your framework correctly like…like…

Climbing a mountain?Climbing a mountain?

161

Is using your framework correctly Is using your framework correctly like…like…

Scaling a Scaling a peak?peak?

162

Is using your framework correctly Is using your framework correctly like…like…

Running across a desert?Running across a desert?

163

Is using your framework correctly Is using your framework correctly like…like…

Falling into a Falling into a pit?pit?

164

Enable the Pit of Success Enable the Pit of Success byby

Avoiding the Avoiding the perilous perilous summit of summit of complexity… complexity…

And the desert And the desert of confusionof confusion

165

Make the Make the simple simple things things simple simple and the and the

hard hard things things

possiblepossible

166

Exceptions and Exceptions and the Pit of Successthe Pit of Success

““Cleaner, more elegant, and wrong.” Cleaner, more elegant, and wrong.” Raymond Chen Raymond Chen ((http://blogs.msdn.com/oldnewthing/)http://blogs.msdn.com/oldnewthing/)

167

When to throw an When to throw an Exception?Exception?

Exceptions rather than error codesExceptions rather than error codesRobust: failures get noticedRobust: failures get noticed

Your method is defined to do Your method is defined to do something…something…

If it succeeds in performing its purpose, If it succeeds in performing its purpose, returnreturn

If it fails to do what it was written to do, If it fails to do what it was written to do, throw an exceptionthrow an exception

Section 7, “Exceptions”Section 7, “Exceptions”

168

What Exception to What Exception to throw?throw?Use or subclass existing exceptions Use or subclass existing exceptions

if at all possibleif at all possible

Only create separate classes if you Only create separate classes if you think developers will handle the think developers will handle the exception differentlyexception differently

try { //some operation}catch (FileNotFoundException fe) { //do some set of work}catch (DriveNotFoundException be) { //do some other set of work}

Section 7.1, “Exception Section 7.1, “Exception ThrowingThrowing””

169

Throwing an ExceptionThrowing an Exception

Do not just map error codes onto a Do not just map error codes onto a single exception with an error code single exception with an error code property (property (e.g.e.g., the WMIException), the WMIException)

Use separate exception typesUse separate exception types

Error MessagesError MessagesConsider localization Consider localization

Use a complete sentence (end in a Use a complete sentence (end in a period)period)

Don’t expose privacy related information Don’t expose privacy related information (such as file paths)(such as file paths)

Section 7.1, “Exception Section 7.1, “Exception ThrowingThrowing””

170

PerformancePerformance

Minimize the number of exceptions you Minimize the number of exceptions you throw in your API’s success code-pathsthrow in your API’s success code-paths

You don’t pay for exceptions until you You don’t pay for exceptions until you throw in managed codethrow in managed code

Throwing exceptions degrades Throwing exceptions degrades performanceperformance

Perf counters tell you exactly how many Perf counters tell you exactly how many exceptions your application is throwingexceptions your application is throwing

Only an issue when using exceptions as a Only an issue when using exceptions as a means of control flowmeans of control flow

Consider providing a way to avoid an Consider providing a way to avoid an exception being thrownexception being thrown

Section 7.1, “Exception Section 7.1, “Exception ThrowingThrowing””

171

Performance (continued)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 Managing Resources during Exception Handlingduring Exception Handling

You should use try..finally 10 times as You should use try..finally 10 times as often as try..catchoften as try..catch

Catches eat exceptions making it hard to Catches eat exceptions making it hard to debugdebug

Finally allows you to clean up, but let the Finally allows you to clean up, but let the exception continueexception continue

Section 7.2, “Choosing the Right Exception”Section 7.2, “Choosing the Right Exception”

173

Managing Resources Managing Resources during Exception during Exception HandlingHandling

You may catch exceptions to re-throw them You may catch exceptions to re-throw them with a clearer namewith a clearer name

Typical at an “API” boundaryTypical at an “API” boundary

Always nest the underlying exceptionAlways nest the underlying exceptionCatch-and-rethrow has many of the benefits Catch-and-rethrow has many of the benefits as try..finallyas try..finally

But, be aware of debugging issues with catch..throw But, be aware of debugging issues with catch..throw new() and catch..throw;new() and catch..throw;Generally, cleanup code should go in finalizerGenerally, cleanup code should go in finalizer

try {. . .}catch (DivisionByZeroException e) { // do clean up work throw new BetterException (message, e);}

174

Catching ExceptionsCatching Exceptions

Do not catch and eat exceptionsDo not catch and eat exceptionsExceptions should be handled only where there Exceptions should be handled only where there is enough context to do the right thingis enough context to do the right thing

That generally means exceptions should be That generally means exceptions should be caught as high in the application as possiblecaught as high in the application as possible

Mistake – catch the exception, report the Mistake – catch the exception, report the error and rethrow it. error and rethrow it.

Only catch where you can handle itOnly catch where you can handle it

Mistake – catch the exception, turn it into a Mistake – catch the exception, turn it into a bool pass/fail and return the bool  bool pass/fail and return the bool 

Section 7.2, “Choosing the Right Exception”Section 7.2, “Choosing the Right Exception”

175

Catching ExceptionsCatching Exceptions

Consider including a try/catch at the Consider including a try/catch at the top of a thread’s stack if the error can top of a thread’s stack if the error can be handled properlybe handled properly

Unhandled exceptions at the top of the Unhandled exceptions at the top of the main thread will terminate the appmain thread will terminate the app

In 2.0, unhandled exceptions at the top In 2.0, unhandled exceptions at the top of the stack on any thread will terminate of the stack on any thread will terminate the appthe app

But avoid catch blocks in finalizersBut avoid catch blocks in finalizers

Be aware: In many cases it is Be aware: In many cases it is “appropriate” to let the app terminate “appropriate” to let the app terminate

176

Catching ExceptionsCatching Exceptions

Be aware of (but ignore) exceptions Be aware of (but ignore) exceptions that don’t inherit from that don’t inherit from System.ExceptionSystem.Exception

Allowed in V1.0\V1.1, addressed in V2.0Allowed in V1.0\V1.1, addressed in V2.0

See UnhandledException event See UnhandledException event on AppDomainon AppDomain

177

The perilous summit of The perilous summit of complexity complexity by exampleby example

178

How do I How do I read all read all the lines the lines from a from a file?file?

How do I How do I read all read all the lines the lines from a from a file?file?

179

VS7 EraVS7 Era “IO” seems like a

reasonable place to start

“IO” seems like a

reasonable place to start

180

Why did they make it

inaccessible

Backup, and try again…

Why did they make it

inaccessible

Backup, and try again…

181

Open.. Looks like a good first step…

Open.. Looks like a good first step…

182

Hmm… OK, what do I do with a FileStream

?

Hmm… OK, what do I do with a FileStream

?

183

Ok good, synchronous

and asynchronous operations.. What the heck is that?

Ok good, synchronous

and asynchronous operations.. What the heck is that?

184

I think I am in the wrong place..

I think I am in the wrong place..

185

Back up, let’s try a Back up, let’s try a different typedifferent type

186

Ahh, ReadLine(), this looks

more promising..

Ahh, ReadLine(), this looks

more promising..

187

OK, How do you find the end?

OK, How do you find the end?

188

Thanks goodness

there was a sample

Thanks goodness

there was a sample

189

The pit of success wayThe pit of success way

developers fall developers fall into doing into doing things the things the right wayright way

190

Just what I need…

Just what I need…

191

Ah, a string[] I know just what to do with that…

Ah, a string[] I know just what to do with that…

192

How simple!How

simple!

193

Enable the Pit of Success Enable the Pit of Success byby

And the And the desert of desert of confusionconfusion

Avoiding the Avoiding the perilous summit perilous summit of complexity…of complexity…

194

Addition Through Addition Through SubtractionSubtraction

1100

1155

55

195

Addition Through Addition Through SubtractionSubtractionAdd value by subtracting Add value by subtracting

featuresfeatures

And the corollary:And the corollary:Remove value by adding featuresRemove value by adding features

More features != More ValueMore features != More Value

Section 2.2.2, “The Law of Low Barrier to Entry”Section 2.2.2, “The Law of Low Barrier to Entry”

196

Addition Through Addition Through Subtraction Subtraction By ExampleBy Example

CLR does not support multiple CLR does not support multiple inheritanceinheritance

No Set class in System.CollectionsNo Set class in System.Collections

No String.OpenFile() method No String.OpenFile() method

What can you cut from your API to What can you cut from your API to make it more valuable?make it more valuable?

197

Addition Through Addition Through SubtractionSubtraction

and and Danger of over-design Danger of over-design

198

API Design Theater IIAPI Design Theater II

The Main Character:The Main Character:Bright young developerBright young developer

The Setting:The Setting:Her first big projectHer first big project

The Setup:The Setup:Create a class that Create a class that models a carmodels a car

Actions required: Start Actions required: Start and Driveand Drive

199

Design Pass One: Meets Design Pass One: Meets Requirements Requirements

Pass one: meets requirementsPass one: meets requirements

200

Design Pass Two: More than Design Pass Two: More than EnoughEnough

201

Design Pass Three: Way too muchDesign Pass Three: Way too much

202

Time to Time to Ship…Ship…

Time to cut…Time to cut…

203

What we ship: Too much and not What we ship: Too much and not enough…enough…

204

V.Next: Worse YetV.Next: Worse Yet

Now we want to add Color and Model, Now we want to add Color and Model, and we know exactly howand we know exactly how

But it is much harder because the But it is much harder because the design is ½ done and mostly wrongdesign is ½ done and mostly wrong

205

The moralThe moral

Do as little as possible now (but Do as little as possible now (but no less) to ensure room for no less) to ensure room for extensibility in the futureextensibility in the future

206

Some Specifics Guidelines Some Specifics Guidelines on Designing for on Designing for Extensibility Extensibility

207

Abstract and Base classesAbstract and Base classes

Prefer broad, shallow hierarchiesPrefer broad, shallow hierarchiesLess than or equal to 2 additional levels – Less than or equal to 2 additional levels – Rough rule!Rough rule!

Contracts and responsibilities are difficult Contracts and responsibilities are difficult to maintain and explain in deep complex to maintain and explain in deep complex hierarchieshierarchies

Consider making base classes not Consider making base classes not constructible (i.e. use Abstract classes)constructible (i.e. use Abstract classes)

Make it clear what the class is forMake it clear what the class is for

Provide a protected constructor for subclasses Provide a protected constructor for subclasses to callto call

System.Exception should not have had a public System.Exception should not have had a public constructorconstructor

208

Virtual Method ExampleVirtual 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 MethodsVirtual Methods

What is printed out?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 MethodsVirtual Methods

They all output “Hello from Derived”. They all output “Hello from Derived”. Why?Why?

Method call virtualizes at runtimeMethod call virtualizes at runtime

The static type doesn’t matterThe static type doesn’t matter

This is the danger and power of This is the danger and power of virtual methodsvirtual methods

Danger: Owner of base classes cannot Danger: Owner of base classes cannot control what subclasses docontrol what subclasses do

Power: Base class does not have to Power: Base class does not have to change as new subclasses are createdchange as new subclasses are created

211

OverridingOverriding

Don’t change the Don’t change the semantics of semantics of membermember

Follow the contract Follow the contract defined on the base defined on the base classclass

All Virtual members should define a All Virtual members should define a contractcontract

Don’t require clients to have Don’t require clients to have knowledge of your overridingknowledge of your overriding

Should you call the base?Should you call the base?

212

Virtual and non-virtualVirtual and non-virtual

Use non-virtual members unless you Use non-virtual members unless you have specifically designed for have specifically designed for specializationspecialization

Have a concrete scenario in mindHave a concrete scenario in mind

Write the code!Write the code!

Think before you virtualize membersThink before you virtualize membersReferences to base types must work References to base types must work with derived types without knowing the with derived types without knowing the difference difference

Must continue to call in the same order Must continue to call in the same order and frequencyand frequency

Cannot increase or decrease range of Cannot increase or decrease range of inputs or outputinputs or output

See the Liskov Substitution PrincipleSee the Liskov Substitution Principle

213

Interfaces versus Base Interfaces versus Base ClassesClasses

Favor using base classes over Favor using base classes over interfacesinterfaces

Base classes version better in generalBase classes version better in generalAllows adding membersAllows adding members

Members can be added with aMembers can be added with a default implementationdefault implementation

Avoids incompatibilities common in ActiveXAvoids incompatibilities common in ActiveX

Interfaces are good for versioning Interfaces are good for versioning behavior (changing semantics)behavior (changing semantics)

214

Interface UsageInterface Usage

Interfaces are useful!Interfaces are useful!Solves the multiple root problemSolves the multiple root problem

The smaller, more focused the The smaller, more focused the interface the betterinterface the better

1-2 members are best1-2 members are bestBut interfaces can be defined in But interfaces can be defined in terms of other simpler interfacesterms of other simpler interfacesExamples: IComparable, IFormattableExamples: IComparable, IFormattable

public interface IComparable { int CompareTo(object obj);}

215

The great The great proof of proof of

madness is madness is the the

disproportion disproportion of one's of one's

designs to designs to one's means.one's means.

Napoleon BonaparteNapoleon Bonaparte

216

Exercises…Exercises…

217

Exercise: Why Exceptions?Exercise: Why Exceptions?

Which of the following are Which of the following are good reasons to use error good reasons to use error codes rather than codes rather than exceptions?exceptions?

A)A) To avoid the base level To avoid the base level overhead exceptions add to overhead exceptions add to the systemthe system

B)B) I have always used error codesI have always used error codes

C)C) It is easier to ignore errors It is easier to ignore errors when dealing with error codeswhen dealing with error codes

D)D) Error codes are easier to Error codes are easier to localize than exceptionslocalize than exceptions

218

Exercise: Creating your Exercise: Creating your own Exceptionsown Exceptions

What is wrong with this What is wrong with this picture?picture?

PrinterOutOfRedTonerExceptionPrinterOutOfRedTonerExceptionPrinterOutOfBlackAndWhiteTonerExceptionPrinterOutOfBlackAndWhiteTonerExceptionPrinterOutOfBlueTonerExceptionPrinterOutOfBlueTonerExceptionPrinterOutOfGreenTonerExceptionPrinterOutOfGreenTonerExceptionPrinterOnFireExceptionPrinterOnFireExceptionPrinterOutOfPaperInTrayOneExceptionPrinterOutOfPaperInTrayOneExceptionPrinterOutOfPaperInTrayTwoExceptionPrinterOutOfPaperInTrayTwoExceptionPrinterOutOfPaperInTrayThreeExceptionPrinterOutOfPaperInTrayThreeExceptionPrinterOutOfPaperInTrayFourExceptionPrinterOutOfPaperInTrayFourExceptionPrinterOutOfPaperInTrayFiveExceptionPrinterOutOfPaperInTrayFiveException

219

Exercise: Handling Exercise: Handling ExceptionsExceptions

Where is the best place to Where is the best place to handle exceptions?handle exceptions?

1.1. Close to where it is thrownClose to where it is thrown

2.2. At the top level, where you At the top level, where you have the most context to have the most context to handlehandle

3.3. No where, exceptions are No where, exceptions are scaryscary

4.4. Early and oftenEarly and often

220

Exercise: Handling Exercise: Handling ExceptionsExceptions

What is the main exception What is the main exception handling problem with this handling problem with this code?code?

try { CallAMethod(); CallAnotherMethod();} catch (Exception ) {}CallAThirdMethod();

221

Exercise: Virtual MethodsExercise: Virtual Methods

Mark the following Mark the following statements true or falsestatements true or false

1.1. (True/False) Implementations (True/False) Implementations of virtual methods can be of virtual methods can be effectively replaced by effectively replaced by subclassessubclasses

2.2. (True/False) The Runtime (True/False) The Runtime insures that overridden insures that overridden methods call their base methods call their base implementations implementations

3.3. (True/False) Make as many (True/False) Make as many members virtual as possible to members virtual as possible to allow for easy extensibility and allow for easy extensibility and versioningversioning

222

SummarySummaryAllow developers to fall into Allow developers to fall into the pit of success using your the pit of success using your framework by avoiding framework by avoiding

The Perilous Summit of The Perilous Summit of complexitycomplexity

Have the right things get noticedHave the right things get noticed

Create the right levels of Create the right levels of abstractionabstraction

The Desert of ConfusionThe Desert of ConfusionAdd value by removing featuresAdd value by removing features

Danger of over designDanger of over design

Simple contracts are betterSimple contracts are better

223

API Design Experience:API Design Experience:Design your Own…Design your Own…

Krzysztof CwalinaKrzysztof CwalinaBrad AbramsBrad Abrams

224

Design E-Mail ComponentDesign E-Mail Component

RequirementsRequirementsSend simple text messagesSend simple text messages

Send messages with attachmentsSend messages with attachments

Simplicity is the main objectiveSimplicity is the main objective

225

Logistics Logistics

Work in pairsWork in pairs

Write the design on a piece of paper Write the design on a piece of paper or on your laptopor on your laptop

If you want feedbackIf you want feedbackSend the design to Send the design to [email protected] or …[email protected] or …

Write your email above the design and Write your email above the design and leave the paper on your chair.leave the paper on your chair.

You have 20 minutesYou have 20 minutes

226

Design ProcessDesign Process

Remember Design ProcessRemember Design ProcessSamplesSamples

API SpecificationAPI Specification

227

Example: Scenario Example: Scenario SamplesSamples

Appendix C, “Sample API Specification”Appendix C, “Sample API Specification”

228

Example: API SpecificationExample: API Specification

Appendix C, “Sample API Specification”Appendix C, “Sample API Specification”

229

Design Experience Design Experience SummarySummaryDesign an e-mail componentDesign an e-mail component

Send simple text messagesSend simple text messagesSend messages with attachmentsSend messages with attachmentsSimplicity is the main objectiveSimplicity is the main objective

Work in pairsWork in pairsWrite on a piece of paper or your Write on a piece of paper or your laptoplaptop

Scenario SamplesScenario SamplesAPI SpecificationAPI Specification

If you want feedbackIf you want feedbackemail us at [email protected] email us at [email protected] Write your email above the design and Write your email above the design and leave the paper on your chair.leave the paper on your chair.

230

In Closing…In Closing…

Brad Abrams Brad Abrams Krzysztof CwalinaKrzysztof Cwalina

231

Four Keys of Framework Four Keys of Framework DesignDesign

Tools for CommunicationTools for Communication

The Power of SamenessThe Power of Sameness

Framework Design Framework Design MattersMatters

The Pit of SuccessThe Pit of Success

232

The Power of Sameness

Influence of expectationsInfluence of expectationsNaming conventions and common suffixes\

prefixes

Habits win out over the special Habits win out over the special casescases

Common Exception pattern

With great power comes great With great power comes great responsibilityresponsibility

Method overloading

Meet developers where they areMeet developers where they areconstructors and properties pattern teaches us

to meet developers’ expectations

233

Framework Design Framework Design MattersMatters

Framework design does not happen Framework design does not happen magicallymagically

Best frameworks are designed Best frameworks are designed upfront by framework designersupfront by framework designers

There are several qualities of a well-There are several qualities of a well-designed framework that require designed framework that require focused framework design processfocused framework design process

234

Tools for CommunicationTools for Communication

Don’t force your consumers to be Don’t force your consumers to be archeologists digging for how to use archeologists digging for how to use your frameworkyour framework

Every element in your design has a Every element in your design has a specific meaning – Know them and specific meaning – Know them and use them correctlyuse them correctly

Avoid the common mistakesAvoid the common mistakesMake brand new mistakes Make brand new mistakes

235

The Pit Of SuccessThe Pit Of SuccessAllow developers to fall into Allow developers to fall into the pit of success using your the pit of success using your framework by avoiding framework by avoiding

The Perilous Summit of The Perilous Summit of complexitycomplexity

Have the right things get noticedHave the right things get noticed

Create the right levels of Create the right levels of abstractionabstraction

The Desert of ConfusionThe Desert of ConfusionAdd value by removing featuresAdd value by removing features

Danger of over designDanger of over design

Simple contracts are betterSimple contracts are better

236

Feedback…Feedback…

We want your feedback, please take We want your feedback, please take time to fill out the survey…time to fill out the survey…

And… please blog…And… please blog…