10 Years of Framework Design Guidelines	Brad Abrams	Product Unit Manager	Microsoft Corporationhttp://blogs.msdn.com/brada	Twitter: @brada
Happy 10 Year Birthday
Happy 10 Year BirthdayJoyeuxAnniversaire
Happy 10 Year BirthdayProficiat met je verjaardag
Member Design
10 years ago….
Communicate via leaving artifacts Framework Design Artifacts:Properties
 Methods
 Events
 ConstructorsConstructors arelazy public XmlFile(string filename) {this.filename = filename; }public class XmlFile { string filename; Stream data; public XmlFile(string filename) {   this.data = DownloadData(filename); }}Do minimal work in the constructorBe Lazy! Only capture the parameters9
Propertiespublic class ArrayList { public int Count {get;}}Property getters should be simple and therefore unlikely to throw exceptionsProperties should not have dependencies on each otherSetting one property should not affect other propertiesProperties should be settable in any order
Properties versus MethodsUse a Property:If the member logical attribute of the typeUse a method: If the operation is a conversion,such as ToString()If the getter has an observableside effectIf order of execution is importantIf the method might not return immediatelyIf the member returns an array
Properties and returning arrayspublic Employee[] All {get{}}public Employee[] GetAll() {}Calling CodeEmployeeList l = FillList();for (int i = 0; i < l.Length; i++){   if (l.All[i] == x){...}} if (l.GetAll()[i]== x) {...}Moral: Use method if the operation is expensive
Today…
Extension Methodsnamespace MyCompany.StringManipulation {     public static class StringExtensions{public static bool IsNullOrEmpty(this string s){ 		return String.IsNullOrEmpty(s);		  }     }}…using MyCompany.StringManipulation;string message= “hello world”;if(message.IsNullOrEmpty()){ 	Console.WriteLine(“EMPTY”);}
Extension methods marry the usability offered by object-oriented APIs with the flexibility of functional APIs.
CONSIDER using extension methods to "add" methods to interfacespublic interface IFoo{    void Bar(string x, bool y);    void Bar(string x);}public static class IFooExtensions{    public static void Bar(this IFoo foo, string x){        foo.Bar(x,false);    }} …IFoo foo = …;foo.Bar(“Hi!”);
CONSIDER using extension methods to manage dependenciesUri uri = “ftp://some.ftp.uri”.ToUri(); // higher level assembly (not mscorlib) namespace System.Net {    public static class StringExtensions{        public static Uri ToUri(this string s){ … }     } }
AVOID frivolously defining extension methods, especially on types you don’t own Might add clutterChoose namespaces for sponsor types carefullyRemember that not all languages support extension methodsUsers will have to use static method call syntax
AVOID defining extension methods on System.Object// C# declaration of the extension methodpublic static class SomeExtensions{    static void SomeMethod(this object o){…}} ‘ VB will try to find the method at runtime‘ … but extension methods are resolved at‘ compile time.Dim o As Object = …o.SomeMethod() ‘ THIS WILL THROW‘ VB users will have to call the method using the regular static method call syntax.SomeExtensions.SomeMethod(o)
Type Design
10 years ago….
Framework Design Theater The Main Character:Bright young developerThe Setting:Her first big projectThe Setup:Create a class that models a carActions required: Start and Drive
Design Pass One: Meets Requirements   Pass one: meets requirements
Design Pass Two: More than Enough
Design Pass Three: Way too much25
Time to Ship…Time to cut…
What we ship: Too much and not enough…27
V.Next: Worse YetNow we want to add Color and Model, and we know exactly howBut it is much harder because the design is half done and mostly wrong
The moralDo as little as possible now (but no less) to ensure room for extensibility in the future
Abstract and Base classesPrefer broad, shallow hierarchiesLess than or equal to 2 additional levels – Rough rule!Contracts and responsibilities are difficult to maintain and explain in deep complex hierarchiesConsider making base classes not constructible (that is, use abstract classes)Make it clear what the class is forProvide a protected constructor for subclasses to callSystem.Exception should not have had a public constructor
Virtual Method Examplepublic class TheBase : Object {   public override string ToString() {      return “Hello from the Base";   }}public class Derived : TheBase {   public override string ToString() {      return “Hello from Derived";   }}
Virtual MethodsWhat 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());
Virtual MethodsThey all output “Hello from Derived”. Why?Method call virtualizes at runtimeThe static type doesn’t matterThis is the danger and power of virtual methodsDanger: Owner of base classes cannot control what subclasses doPower: Base class does not have to change as new subclasses are created
Overriding: Follow the ContractDon’t change the semantics of memberFollow the contract defined on the base classAll Virtual members should define a contractDon’t require clients to have knowledge of your overridingShould you call the base?
Virtual and non-virtualUse non-virtual members unless you have specifically designed for specializationHave a concrete scenario in mindWrite the code!Follow the Liskov Substitution PrincipleReferences to base types must work with derived types without knowing the difference Must continue to call in the sameorder and frequencyCannot increase or decrease range of inputs or outputBarbara Liskov
Interface Usagepublic interface IComparable {    int CompareTo(object obj);}No common implementation (the ActiveX problem)Challenging to version over releasesThe smaller, more focused the interface the better1-2 members are bestBut interfaces can be defined in terms of other simpler interfaces
	The great proof of madness is the disproportion of one's designs to one's means.Napoleon Bonaparte
Today…
Type Dependency ManagementCareful dependency management is the necessary ingredient to successful evolution of frameworks. Without it, frameworks quickly deteriorate and are forced out of relevance prematurely.
Framework Layering
DO NOThave upward dependencies Avoidhorizontal dependenciesWPFXMLBCLReflection
Libraries , Primitives, Abstractions
CONSIDER placing library types higher on the dependency stack Definition:Library types are types that are not passed between componentsExamplesEventLog, Debug, Easy to EvolveLeave old in, add new oneBeware of duplication!
DOkeep primitives policy free (i.e. simple)Definition:Primitive types are types that are passed between components and have very restricted extensibility (i.e. no subtype can override any members)ExamplesInt32, String, Uri.Hard to EvolveLittle need to EvolveTypically in lower layers
DO NOTcreate abstractions unless you know what you are doingDefinition:Abstractions are interfaces or classes with unsealed members that are passed between components.ExamplesStream, IComponentHard to EvolveUnfortunately, pressure to evolve
Trends
10 years ago….
The Secret of Achiving Great Productivty A Pit!!
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
Is using your framework correctly like…Climbing a mountain?50
Is using your framework correctly like…Scaling a peak?51
Is using your framework correctly like…Running across a desert?52
Is using your framework correctly like…Falling into a pit?
Make using your framework as easy as falling into a pit – then you have achived great productivity
Today…
Test Driven DevelopmentWrite tests first, design laterRequires reusable APIs to be testable:Avoid heavy dependencies, consider inversion of control.
Consider designing for dependency injection. Heavy Dependencies and Testability// your APIpublic class Tracer {MessageQueue mq = new MessageQueue(…);	public void Trace(string message){ 	mq.Send(message);	}} // your customer’s program that is hard to testTracer tracer = new Tracer();public void ProcessOrder(Order order){	tracer.Trace(order.Id);	…}
Inversion of Control// your better APIpublic abstract class TraceListener {	public abstract void Trace(string message);} public class Tracer {TraceListener listener;	public Tracer(TraceListener listener){		this.listener = listener; 	}	public void Trace(string message){ 			listener.Trace(message);	}}
Dependency Injection// your customer’s program that is easier to testTracer tracer = new Tracer(new FileListener());public void ProcessOrder(Order order){	tracer.Trace(order.Id);	…}
Dependency Injection Containers// customer’s program that is even easier to testTracer tracer = container.Resolve<Tracer>();public void ProcessOrder(Order order){	tracer.Trace(order.Id);	…}Check outDI Containers (a.k.a. IoC Containers):autofac, Castle Windsor, PicoContainer.NET, Spring.NET, StructureMap, Unity, and others.
Tools
10 years ago….
 Read the manual??When you pick up your rental car….Push the seat all the way backFind an NPR stationFind the exit
Oh, down to lock…
How to use a key…
Oh, you push the PRESS button…
Who actually needs this data?
Why you don’t read rental car manuals ???You know how to drive your carAll cars work basically the same wayYour rental car is a carTherefore, you can drive your rental carThat is…The Power of Sameness
Naming ConventionsPascalCasing – Each word starts with an uppercase lettercamelCasing – First word lower case, others uppercaseSCREAMING_CAPS – All upper case with underscores
Naming ConventionsAll types and publicly exposed members are PascalCasedParameters are camelCasedpublic class MemberDoc{   public int CompareTo(object value)    public string Name { get;}}
Hungarian NotationDo not use Hungarian notation in publicly exposed APIs and parameter namespublic class CMyClass {   int CompareTo (object objValue) {..}   string lpstrName {get;}   int iValue {get;}}
On Abbreviations, acronym, initialism and the like…Avoid them!  They are a classic JLT (jargon loaded term)OK to use them once they become wordsHtml, Xaml, etcDon’t just spell them outUse a meaningful nameAbbreviations of more than 2 letters are cased as words, otherwise ALLUPPERIO vs. Html
While we are on naming…Good naming is hard—it takes timeBe meaningful but briefUse US-EnglishColour vs. ColorPrinciple of least surprise Look for prior-artNumberOfElements vs. Count
FxCop – Keeping the "power of sameness"http://blogs.msdn.com/fxcop
Today…
Framework Design Studiohttp://code.msdn.microsoft.com/fds
Dependency Management Toolshttp://code.msdn.microsoft.com/fxarchDefine Components<Group ID=“Component1”>		<Bin Name=“MyCompany.FeatureA.dll”/>		<Bin Name=“MyCompany.FeatureB.dll”/>	</Group>Define Rules 		<Allow From=“Component1" To=“WPF"/>		<Deny To=“XMLDOM”>Run and Get Output:From group Component1:   MyCompany.FeatureA.dll should not depend on:	SomeOtherComponent	   SomeOtherComponent.dllAlso check out NDepend – a tool for visualizing dependencies.
Summary 10 years of Framework design..Core Principles of Framework design have stayed the sameThere are some significant new advancesCheck out the new book!Brad Abramshttp://blogs.msdn.com/bradaTwitter: @brada
Q&A
© 2008 Microsoft Corporation. All rights reserved. Microsoft, Windows, Windows Vista and other product names are or may be registered trademarks and/or trademarks in the U.S. and/or other countries.The information herein is for informational purposes only and represents the current view of Microsoft Corporation as of the date of this presentation.  Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information provided after the date of this presentation.   MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS PRESENTATION.

Framework Design Guidelines For Brussels Users Group

  • 1.
    10 Years ofFramework Design Guidelines Brad Abrams Product Unit Manager Microsoft Corporationhttp://blogs.msdn.com/brada Twitter: @brada
  • 3.
  • 4.
    Happy 10 YearBirthdayJoyeuxAnniversaire
  • 5.
    Happy 10 YearBirthdayProficiat met je verjaardag
  • 6.
  • 7.
  • 8.
    Communicate via leavingartifacts Framework Design Artifacts:Properties
  • 9.
  • 10.
  • 11.
    ConstructorsConstructors arelazypublic XmlFile(string filename) {this.filename = filename; }public class XmlFile { string filename; Stream data; public XmlFile(string filename) { this.data = DownloadData(filename); }}Do minimal work in the constructorBe Lazy! Only capture the parameters9
  • 12.
    Propertiespublic class ArrayList{ public int Count {get;}}Property getters should be simple and therefore unlikely to throw exceptionsProperties should not have dependencies on each otherSetting one property should not affect other propertiesProperties should be settable in any order
  • 13.
    Properties versus MethodsUsea Property:If the member logical attribute of the typeUse a method: If the operation is a conversion,such as ToString()If the getter has an observableside effectIf order of execution is importantIf the method might not return immediatelyIf the member returns an array
  • 14.
    Properties and returningarrayspublic Employee[] All {get{}}public Employee[] GetAll() {}Calling CodeEmployeeList l = FillList();for (int i = 0; i < l.Length; i++){ if (l.All[i] == x){...}} if (l.GetAll()[i]== x) {...}Moral: Use method if the operation is expensive
  • 15.
  • 16.
    Extension Methodsnamespace MyCompany.StringManipulation{ public static class StringExtensions{public static bool IsNullOrEmpty(this string s){ return String.IsNullOrEmpty(s); } }}…using MyCompany.StringManipulation;string message= “hello world”;if(message.IsNullOrEmpty()){ Console.WriteLine(“EMPTY”);}
  • 17.
    Extension methods marrythe usability offered by object-oriented APIs with the flexibility of functional APIs.
  • 18.
    CONSIDER using extensionmethods to "add" methods to interfacespublic interface IFoo{ void Bar(string x, bool y); void Bar(string x);}public static class IFooExtensions{ public static void Bar(this IFoo foo, string x){ foo.Bar(x,false); }} …IFoo foo = …;foo.Bar(“Hi!”);
  • 19.
    CONSIDER using extensionmethods to manage dependenciesUri uri = “ftp://some.ftp.uri”.ToUri(); // higher level assembly (not mscorlib) namespace System.Net { public static class StringExtensions{ public static Uri ToUri(this string s){ … } } }
  • 20.
    AVOID frivolously definingextension methods, especially on types you don’t own Might add clutterChoose namespaces for sponsor types carefullyRemember that not all languages support extension methodsUsers will have to use static method call syntax
  • 21.
    AVOID defining extensionmethods on System.Object// C# declaration of the extension methodpublic static class SomeExtensions{ static void SomeMethod(this object o){…}} ‘ VB will try to find the method at runtime‘ … but extension methods are resolved at‘ compile time.Dim o As Object = …o.SomeMethod() ‘ THIS WILL THROW‘ VB users will have to call the method using the regular static method call syntax.SomeExtensions.SomeMethod(o)
  • 22.
  • 23.
  • 24.
    Framework Design TheaterThe Main Character:Bright young developerThe Setting:Her first big projectThe Setup:Create a class that models a carActions required: Start and Drive
  • 25.
    Design Pass One:Meets Requirements Pass one: meets requirements
  • 26.
    Design Pass Two:More than Enough
  • 27.
    Design Pass Three:Way too much25
  • 28.
  • 29.
    What we ship:Too much and not enough…27
  • 30.
    V.Next: Worse YetNowwe want to add Color and Model, and we know exactly howBut it is much harder because the design is half done and mostly wrong
  • 31.
    The moralDo aslittle as possible now (but no less) to ensure room for extensibility in the future
  • 32.
    Abstract and BaseclassesPrefer broad, shallow hierarchiesLess than or equal to 2 additional levels – Rough rule!Contracts and responsibilities are difficult to maintain and explain in deep complex hierarchiesConsider making base classes not constructible (that is, use abstract classes)Make it clear what the class is forProvide a protected constructor for subclasses to callSystem.Exception should not have had a public constructor
  • 33.
    Virtual Method Examplepublicclass TheBase : Object { public override string ToString() { return “Hello from the Base"; }}public class Derived : TheBase { public override string ToString() { return “Hello from Derived"; }}
  • 34.
    Virtual MethodsWhat isprinted out?Derived d = new Derived();Console.WriteLine (d.ToString());TheBase tb = d;Console.WriteLine (tb.ToString());Object o = tb;Console.WriteLine (o.ToString());
  • 35.
    Virtual MethodsThey alloutput “Hello from Derived”. Why?Method call virtualizes at runtimeThe static type doesn’t matterThis is the danger and power of virtual methodsDanger: Owner of base classes cannot control what subclasses doPower: Base class does not have to change as new subclasses are created
  • 36.
    Overriding: Follow theContractDon’t change the semantics of memberFollow the contract defined on the base classAll Virtual members should define a contractDon’t require clients to have knowledge of your overridingShould you call the base?
  • 37.
    Virtual and non-virtualUsenon-virtual members unless you have specifically designed for specializationHave a concrete scenario in mindWrite the code!Follow the Liskov Substitution PrincipleReferences to base types must work with derived types without knowing the difference Must continue to call in the sameorder and frequencyCannot increase or decrease range of inputs or outputBarbara Liskov
  • 38.
    Interface Usagepublic interfaceIComparable { int CompareTo(object obj);}No common implementation (the ActiveX problem)Challenging to version over releasesThe smaller, more focused the interface the better1-2 members are bestBut interfaces can be defined in terms of other simpler interfaces
  • 39.
    The great proofof madness is the disproportion of one's designs to one's means.Napoleon Bonaparte
  • 40.
  • 41.
    Type Dependency ManagementCarefuldependency management is the necessary ingredient to successful evolution of frameworks. Without it, frameworks quickly deteriorate and are forced out of relevance prematurely.
  • 42.
  • 43.
    DO NOThave upwarddependencies Avoidhorizontal dependenciesWPFXMLBCLReflection
  • 44.
  • 45.
    CONSIDER placing librarytypes higher on the dependency stack Definition:Library types are types that are not passed between componentsExamplesEventLog, Debug, Easy to EvolveLeave old in, add new oneBeware of duplication!
  • 46.
    DOkeep primitives policyfree (i.e. simple)Definition:Primitive types are types that are passed between components and have very restricted extensibility (i.e. no subtype can override any members)ExamplesInt32, String, Uri.Hard to EvolveLittle need to EvolveTypically in lower layers
  • 47.
    DO NOTcreate abstractionsunless you know what you are doingDefinition:Abstractions are interfaces or classes with unsealed members that are passed between components.ExamplesStream, IComponentHard to EvolveUnfortunately, pressure to evolve
  • 48.
  • 49.
  • 50.
    The Secret ofAchiving Great Productivty A Pit!!
  • 51.
    The Pit ofSuccess: 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
  • 52.
    Is using yourframework correctly like…Climbing a mountain?50
  • 53.
    Is using yourframework correctly like…Scaling a peak?51
  • 54.
    Is using yourframework correctly like…Running across a desert?52
  • 55.
    Is using yourframework correctly like…Falling into a pit?
  • 56.
    Make using yourframework as easy as falling into a pit – then you have achived great productivity
  • 57.
  • 58.
    Test Driven DevelopmentWritetests first, design laterRequires reusable APIs to be testable:Avoid heavy dependencies, consider inversion of control.
  • 59.
    Consider designing fordependency injection. Heavy Dependencies and Testability// your APIpublic class Tracer {MessageQueue mq = new MessageQueue(…); public void Trace(string message){ mq.Send(message); }} // your customer’s program that is hard to testTracer tracer = new Tracer();public void ProcessOrder(Order order){ tracer.Trace(order.Id); …}
  • 60.
    Inversion of Control//your better APIpublic abstract class TraceListener { public abstract void Trace(string message);} public class Tracer {TraceListener listener; public Tracer(TraceListener listener){ this.listener = listener; } public void Trace(string message){ listener.Trace(message); }}
  • 61.
    Dependency Injection// yourcustomer’s program that is easier to testTracer tracer = new Tracer(new FileListener());public void ProcessOrder(Order order){ tracer.Trace(order.Id); …}
  • 62.
    Dependency Injection Containers//customer’s program that is even easier to testTracer tracer = container.Resolve<Tracer>();public void ProcessOrder(Order order){ tracer.Trace(order.Id); …}Check outDI Containers (a.k.a. IoC Containers):autofac, Castle Windsor, PicoContainer.NET, Spring.NET, StructureMap, Unity, and others.
  • 63.
  • 64.
  • 65.
    Read themanual??When you pick up your rental car….Push the seat all the way backFind an NPR stationFind the exit
  • 66.
  • 67.
    How to usea key…
  • 68.
    Oh, you pushthe PRESS button…
  • 69.
  • 70.
    Why you don’tread rental car manuals ???You know how to drive your carAll cars work basically the same wayYour rental car is a carTherefore, you can drive your rental carThat is…The Power of Sameness
  • 71.
    Naming ConventionsPascalCasing –Each word starts with an uppercase lettercamelCasing – First word lower case, others uppercaseSCREAMING_CAPS – All upper case with underscores
  • 72.
    Naming ConventionsAll typesand publicly exposed members are PascalCasedParameters are camelCasedpublic class MemberDoc{ public int CompareTo(object value) public string Name { get;}}
  • 73.
    Hungarian NotationDo notuse Hungarian notation in publicly exposed APIs and parameter namespublic class CMyClass { int CompareTo (object objValue) {..} string lpstrName {get;} int iValue {get;}}
  • 74.
    On Abbreviations, acronym,initialism and the like…Avoid them! They are a classic JLT (jargon loaded term)OK to use them once they become wordsHtml, Xaml, etcDon’t just spell them outUse a meaningful nameAbbreviations of more than 2 letters are cased as words, otherwise ALLUPPERIO vs. Html
  • 75.
    While we areon naming…Good naming is hard—it takes timeBe meaningful but briefUse US-EnglishColour vs. ColorPrinciple of least surprise Look for prior-artNumberOfElements vs. Count
  • 76.
    FxCop – Keepingthe "power of sameness"http://blogs.msdn.com/fxcop
  • 77.
  • 78.
  • 79.
    Dependency Management Toolshttp://code.msdn.microsoft.com/fxarchDefineComponents<Group ID=“Component1”> <Bin Name=“MyCompany.FeatureA.dll”/> <Bin Name=“MyCompany.FeatureB.dll”/> </Group>Define Rules <Allow From=“Component1" To=“WPF"/> <Deny To=“XMLDOM”>Run and Get Output:From group Component1: MyCompany.FeatureA.dll should not depend on: SomeOtherComponent SomeOtherComponent.dllAlso check out NDepend – a tool for visualizing dependencies.
  • 80.
    Summary 10 yearsof Framework design..Core Principles of Framework design have stayed the sameThere are some significant new advancesCheck out the new book!Brad Abramshttp://blogs.msdn.com/bradaTwitter: @brada
  • 81.
  • 82.
    © 2008 MicrosoftCorporation. All rights reserved. Microsoft, Windows, Windows Vista and other product names are or may be registered trademarks and/or trademarks in the U.S. and/or other countries.The information herein is for informational purposes only and represents the current view of Microsoft Corporation as of the date of this presentation. Because Microsoft must respond to changing market conditions, it should not be interpreted to be a commitment on the part of Microsoft, and Microsoft cannot guarantee the accuracy of any information provided after the date of this presentation. MICROSOFT MAKES NO WARRANTIES, EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS PRESENTATION.