Framework Design Guidelines For Brussels Users Group


Published on

Belgium Visual Studio User’s Group on 10 Years of Framework Design Guidelines

Published in: Technology
  • Be the first to comment

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Framework Design Guidelines For Brussels Users Group

  1. 1. 10 Years of Framework Design Guidelines<br /> Brad Abrams<br /> Product Unit Manager<br /> Microsoft Corporation<br /> Twitter: @brada<br />
  2. 2.
  3. 3. Happy 10 Year Birthday<br />
  4. 4. Happy 10 Year Birthday<br />JoyeuxAnniversaire<br />
  5. 5. Happy 10 Year Birthday<br />Proficiat met je verjaardag<br />
  6. 6. Member Design<br />
  7. 7. 10 years ago…. <br />
  8. 8. Communicate via leaving artifacts <br />Framework Design Artifacts:<br /><ul><li>Properties
  9. 9. Methods
  10. 10. Events
  11. 11. Constructors</li></li></ul><li>Constructors are<br />lazy<br /> public XmlFile(string filename) {this.filename = filename; }<br />public class XmlFile { string filename; Stream data; public XmlFile(string filename) { = DownloadData(filename);<br /> }<br />}<br />Do minimal work in the constructor<br />Be Lazy! <br />Only capture the parameters<br />9<br />
  12. 12. Properties<br />public class ArrayList { public int Count {get;}}<br />Property getters should be simple and therefore unlikely to throw exceptions<br />Properties should not have dependencies on each other<br />Setting one property should not affect other properties<br />Properties should be settable in any order<br />
  13. 13. Properties versus Methods<br />Use a Property:<br />If the member logical attribute of the type<br />Use a method: <br />If the operation is a conversion,such as ToString()<br />If the getter has an observableside effect<br />If order of execution is important<br />If the method might not return immediately<br />If the member returns an array<br />
  14. 14. Properties and returning arrays<br />public Employee[] All {get{}}<br />public Employee[] GetAll() {}<br />Calling Code<br />EmployeeList l = FillList();<br />for (int i = 0; i &lt; l.Length; i++){<br /> if (l.All[i] == x){...}<br />}<br /> if (l.GetAll()[i]== x) {...}<br />Moral: Use method if the operation is expensive <br />
  15. 15. Today…<br />
  16. 16. Extension Methods<br />namespace MyCompany.StringManipulation { <br /> public static class StringExtensions{<br />public static bool IsNullOrEmpty(this string s){ return String.IsNullOrEmpty(s);<br /> } <br /> }<br />}<br />…<br />using MyCompany.StringManipulation;<br />string message= “hello world”;<br />if(message.IsNullOrEmpty()){ <br /> Console.WriteLine(“EMPTY”);<br />}<br />
  17. 17. Extension methods marry the usability offered by object-oriented APIs with the flexibility of functional APIs.<br />
  18. 18. CONSIDER using extension methods to &quot;add&quot; methods to interfaces<br />public interface IFoo{<br /> void Bar(string x, bool y);<br /> void Bar(string x);<br />}<br />public static class IFooExtensions{<br /> public static void Bar(this IFoo foo, string x){<br /> foo.Bar(x,false);<br /> }<br />} <br />…<br />IFoo foo = …;<br />foo.Bar(“Hi!”);<br />
  19. 19. CONSIDER using extension methods to manage dependencies<br />Uri uri = “ftp://some.ftp.uri”.ToUri(); <br />// higher level assembly (not mscorlib) <br />namespace System.Net {<br /> public static class StringExtensions{<br /> public static Uri ToUri(this string s){ … } <br /> } <br />}<br />
  20. 20. AVOID frivolously defining extension methods, especially on types you don’t own <br />Might add clutter<br />Choose namespaces for sponsor types carefully<br />Remember that not all languages support extension methods<br />Users will have to use static method call syntax<br />
  21. 21. AVOID defining extension methods on System.Object<br />// C# declaration of the extension method<br />public static class SomeExtensions{<br /> static void SomeMethod(this object o){…}<br />}<br /> <br />‘ VB will try to find the method at runtime<br />‘ … but extension methods are resolved at<br />‘ compile time.<br />Dim o As Object = …<br />o.SomeMethod() ‘ THIS WILL THROW<br />‘ VB users will have to call the method using the regular static method call syntax.<br />SomeExtensions.SomeMethod(o)<br />
  22. 22. Type Design<br />
  23. 23. 10 years ago…. <br />
  24. 24. Framework Design Theater <br />The Main Character:<br />Bright young developer<br />The Setting:<br />Her first big project<br />The Setup:<br />Create a class that models a car<br />Actions required: Start and Drive<br />
  25. 25. Design Pass One: Meets Requirements <br />Pass one: meets requirements<br />
  26. 26. Design Pass Two: More than Enough<br />
  27. 27. Design Pass Three: Way too much<br />25<br />
  28. 28. Time to Ship…<br />Time to cut…<br />
  29. 29. What we ship: Too much and not enough…<br />27<br />
  30. 30. V.Next: Worse Yet<br />Now we want to add Color and Model, and we know exactly how<br />But it is much harder because the design is half done and mostly wrong<br />
  31. 31. The moral<br />Do as little as possible now (but no less) to ensure room for extensibility in the future<br />
  32. 32. Abstract and Base classes<br />Prefer broad, shallow hierarchies<br />Less than or equal to 2 additional levels – Rough rule!<br />Contracts and responsibilities are difficult to maintain and explain in deep complex hierarchies<br />Consider making base classes not constructible (that is, use abstract classes)<br />Make it clear what the class is for<br />Provide a protected constructor for subclasses to call<br />System.Exception should not have had a public constructor<br />
  33. 33. Virtual Method Example<br />public class TheBase : Object {<br /> public override string ToString() {<br /> return “Hello from the Base&quot;;<br /> }<br />}<br />public class Derived : TheBase {<br /> public override string ToString() {<br /> return “Hello from Derived&quot;;<br /> }<br />}<br />
  34. 34. Virtual Methods<br />What is printed out?<br />Derived d = new Derived();Console.WriteLine (d.ToString());<br />TheBase tb = d;Console.WriteLine (tb.ToString());<br />Object o = tb;Console.WriteLine (o.ToString());<br />
  35. 35. Virtual Methods<br />They all output “Hello from Derived”. Why?<br />Method call virtualizes at runtime<br />The static type doesn’t matter<br />This is the danger and power of virtual methods<br />Danger: Owner of base classes cannot control what subclasses do<br />Power: Base class does not have to change as new subclasses are created<br />
  36. 36. Overriding: Follow the Contract<br />Don’t change the semantics of member<br />Follow the contract defined on the base class<br />All Virtual members should define a contract<br />Don’t require clients to have knowledge of your overriding<br />Should you call the base?<br />
  37. 37. Virtual and non-virtual<br />Use non-virtual members unless you have specifically designed for specialization<br />Have a concrete scenario in mind<br />Write the code!<br />Follow the Liskov Substitution Principle<br />References to base types must work with derived types without knowing the difference <br />Must continue to call in the sameorder and frequency<br />Cannot increase or decrease range of inputs or output<br />Barbara Liskov<br />
  38. 38. Interface Usage<br />public interface IComparable { int CompareTo(object obj);}<br />No common implementation (the ActiveX problem)<br />Challenging to version over releases<br />The smaller, more focused the interface the better<br />1-2 members are best<br />But interfaces can be defined in terms of other simpler interfaces<br />
  39. 39. The great proof of madness is the disproportion of one&apos;s designs to one&apos;s means.Napoleon Bonaparte<br />
  40. 40. Today…<br />
  41. 41. Type Dependency Management<br />Careful dependency management is the necessary ingredient to successful evolution of frameworks. Without it, frameworks quickly deteriorate and are forced out of relevance prematurely.<br />
  42. 42. Framework Layering<br />
  43. 43. DO NOThave upward dependencies <br />Avoidhorizontal dependencies<br />WPF<br />XML<br /><br /><br /><br />BCL<br />Reflection<br />
  44. 44. Libraries , Primitives, Abstractions<br />
  45. 45. CONSIDER placing library types higher on the dependency stack <br />Definition:<br />Library types are types that are not passed between components<br />Examples<br />EventLog, Debug, <br />Easy to Evolve<br />Leave old in, add new one<br />Beware of duplication!<br />
  46. 46. DOkeep primitives policy free (i.e. simple)<br />Definition:<br />Primitive types are types that are passed between components and have very restricted extensibility (i.e. no subtype can override any members)<br />Examples<br />Int32, String, Uri.<br />Hard to Evolve<br />Little need to Evolve<br />Typically in lower layers<br />
  47. 47. DO NOTcreate abstractions unless you know what you are doing<br />Definition:<br />Abstractions are interfaces or classes with unsealed members that are passed between components.<br />Examples<br />Stream, IComponent<br />Hard to Evolve<br />Unfortunately, pressure to evolve<br />
  48. 48. Trends<br />
  49. 49. 10 years ago…. <br />
  50. 50. The Secret of Achiving Great Productivty <br />A Pit!!<br />
  51. 51. 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<br />
  52. 52. Is using your framework correctly like…<br />Climbing a mountain?<br />50<br />
  53. 53. Is using your framework correctly like…<br />Scaling a peak?<br />51<br />
  54. 54. Is using your framework correctly like…<br />Running across a desert?<br />52<br />
  55. 55. Is using your framework correctly like…<br />Falling into a pit?<br />
  56. 56. Make using your framework as easy as falling into a pit – then you have achived great productivity<br />
  57. 57. Today…<br />
  58. 58. Test Driven Development<br />Write tests first, design later<br />Requires reusable APIs to be testable:<br /><ul><li>Avoid heavy dependencies, consider inversion of control.
  59. 59. Consider designing for dependency injection. </li></li></ul><li>Heavy Dependencies and Testability<br />// your API<br />public class Tracer {<br />MessageQueue mq = new MessageQueue(…);<br /> public void Trace(string message){ mq.Send(message);<br /> }<br />} <br />// your customer’s program that is hard to test<br />Tracer tracer = new Tracer();<br />public void ProcessOrder(Order order){<br /> tracer.Trace(order.Id);<br /> …<br />}<br />
  60. 60. Inversion of Control<br />// your better API<br />public abstract class TraceListener {<br /> public abstract void Trace(string message);<br />} <br />public class Tracer {<br />TraceListener listener;<br /> public Tracer(TraceListener listener){<br /> this.listener = listener;<br /> }<br /> public void Trace(string message){ <br /> listener.Trace(message);<br /> }<br />} <br />
  61. 61. Dependency Injection<br />// your customer’s program that is easier to test<br />Tracer tracer = new Tracer(new FileListener());<br />public void ProcessOrder(Order order){<br /> tracer.Trace(order.Id);<br /> …<br />}<br />
  62. 62. Dependency Injection Containers<br />// customer’s program that is even easier to test<br />Tracer tracer = container.Resolve&lt;Tracer&gt;();<br />public void ProcessOrder(Order order){<br /> tracer.Trace(order.Id);<br /> …<br />}<br />Check outDI Containers (a.k.a. IoC Containers):autofac, Castle Windsor, PicoContainer.NET, Spring.NET, StructureMap, Unity, and others.<br />
  63. 63. Tools<br />
  64. 64. 10 years ago…. <br />
  65. 65. Read the manual??<br />When you pick up your rental car….<br />Push the seat all the way back<br />Find an NPR station<br />Find the exit<br />
  66. 66. Oh, down to lock…<br />
  67. 67. How to use a key…<br />
  68. 68. Oh, you push the PRESS button…<br />
  69. 69. Who actually needs this data?<br />
  70. 70. Why you don’t read rental car manuals ???<br />You know how to drive your car<br />All cars work basically the same way<br />Your rental car is a car<br />Therefore, you can drive your rental car<br />That is…<br />The Power of Sameness<br />
  71. 71. Naming Conventions<br />PascalCasing – Each word starts with an uppercase letter<br />camelCasing – First word lower case, others uppercase<br />SCREAMING_CAPS – All upper case with underscores<br />
  72. 72. Naming Conventions<br />All types and publicly exposed members are PascalCased<br />Parameters are camelCased<br />public class MemberDoc<br />{<br /> public int CompareTo(object value) <br /> public string Name { get;}<br />}<br />
  73. 73. Hungarian Notation<br />Do not use Hungarian notation in publicly exposed APIs and parameter names<br />public class CMyClass { int CompareTo (object objValue) {..} string lpstrName {get;} int iValue {get;}<br />}<br />
  74. 74. On Abbreviations, acronym, initialism and the like…<br />Avoid them! <br />They are a classic JLT (jargon loaded term)<br />OK to use them once they become words<br />Html, Xaml, etc<br />Don’t just spell them out<br />Use a meaningful name<br />Abbreviations of more than 2 letters are cased as words, otherwise ALLUPPER<br />IO vs. Html<br />
  75. 75. While we are on naming…<br />Good naming is hard—it takes time<br />Be meaningful but brief<br />Use US-English<br />Colour vs. Color<br />Principle of least surprise <br />Look for prior-art<br />NumberOfElements vs. Count<br />
  76. 76. FxCop – Keeping the &quot;power of sameness&quot;<br /><br />
  77. 77. Today…<br />
  78. 78. Framework Design Studio<br /><br />
  79. 79. Dependency Management Tools<br /><br />Define Components<br />&lt;Group ID=“Component1”&gt;<br /> &lt;Bin Name=“MyCompany.FeatureA.dll”/&gt;<br /> &lt;Bin Name=“MyCompany.FeatureB.dll”/&gt;<br /> &lt;/Group&gt;<br />Define Rules <br /> &lt;Allow From=“Component1&quot; To=“WPF&quot;/&gt;<br /> &lt;Deny To=“XMLDOM”&gt;<br />Run and Get Output:<br />From group Component1:<br /> MyCompany.FeatureA.dll should not depend on:<br /> SomeOtherComponent<br /> SomeOtherComponent.dll<br />Also check out NDepend – a tool for visualizing dependencies.<br />
  80. 80. Summary <br />10 years of Framework design..<br />Core Principles of Framework design have stayed the same<br />There are some significant new advances<br />Check out the new book!<br />Brad Abrams<br /><br />Twitter: @brada<br />
  81. 81. Q&A<br />
  82. 82. © 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.<br />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.<br />
  83. 83.
  84. 84. Some images of movie posters sourced from<br />