Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Design Pattern Mastery - Momentum Dev Con 19 Apr 2018


Published on

Design patterns help developers and teams solve problems using proven approaches. In this talk, you'll learn how to solve a series of real world problems by applying patterns. Not only do patterns help individual developers solve particular problems, but they also enable teams to discuss design decisions using a richer, more descriptive language. By the end, you'll have some concrete tools you can apply, and hopefully the desire to master more patterns as you continue to improve!

Published in: Technology
  • Be the first to comment

Design Pattern Mastery - Momentum Dev Con 19 Apr 2018

  1. 1. Design Pattern Mastery Steve Smith (@ardalis) Podcast:
  2. 2. Design Patterns
  3. 3. Industry Agnostic Patterns exist in all industries.
  4. 4. Design Patterns By the Gang of Four (GoF).
  5. 5. Literally The First 3 Results… Search “programmer bookshelf”
  6. 6. Stages of Learning Stage Zero - Ignorance Stage One - Awakening Stage Two - Overzealous Stage Three – Mastery
  7. 7. Goal After This Presentation At least Stage One – Awakening for a number of useful patterns Armed with resources to dive deeper into patterns of interest
  8. 8. Language
  9. 9. Overheard during a code review… “We have some tight coupling to the database here. We can probably fix it if we apply some refactorings. Maybe we can start by extracting an interface. Then we can extract a method that contains the persistence code. After that, we can extract that method into its own class that implements the interface we created. Then, we should be able to replace the local instantiation of the class with a parameter we can pass in and assign to a field.”
  10. 10. Consider instead… “We have some tight coupling to the database here. Let’s use the Repository Pattern to eliminate it.”
  11. 11. Design Patterns Composite Iterator Specification Unit of Work
  12. 12. A Few Especially Helpful Patterns  (Singleton)  Strategy  Repository  Proxy / Decorator
  13. 13. Singleton: Intent  Ensure a class has only one instance  Make the class itself responsible for keeping track of its sole instance  “There can be only one”
  14. 14. Singleton Structure (not thread-safe)
  15. 15. Singleton Structure (thread-safe and fast) Source:
  16. 16. Singleton Consequences  The default implementation is not thread-safe  Avoid in multi-threaded environments  Avoid in web server scenarios (e.g. ASP.NET)  Introduce tight coupling among collaborating classes  Singletons are notoriously difficult to test  Commonly regarded as an anti-pattern Some commercial tools can be used to mock and test Singletons But why would you intentionally write code you can only test with certain premium tools?
  17. 17. Singleton Consequences  Violates the Single Responsibility Principle  Whatever the class does AND  Lifetime Management  Using an IOC/DI Container it is straightforward to avoid the coupling and testability issues
  18. 18. Object Lifetime (in ASP.NET Core) public void ConfigureServices(IServiceCollection services) { services.AddMvc(); // you don’t need to implement singleton behavior in class! services.AddSingleton<ISomeService>(); }
  19. 19. Singleton behavior is fine and often desirable. Implementing this behavior using the Singleton Pattern on the class itself is usually not ideal.
  20. 20. Strategy
  21. 21. Strategy: Intent  Encapsulate a family of related algorithms  Let the algorithm vary and evolve independently from the class(es) that use it  Allow a class to maintain a single purpose  Single Responsibility Principle (SRP)  Also enables Open/Closed Principle (OCP)  Learn more about SRP and OCP in my Pluralsight course: 
  22. 22. Strategy : Structure
  23. 23. Strategy : Common Usage  Dependency Inversion and Dependency Injection  Decouple class dependencies and responsibilities Refactoring Steps  Create interfaces for each responsibility  Inject the implementation of the interface via the constructor  Move the implementation to a new class that implements the interface
  24. 24. Hidden Dependencies  Classes should declare their dependencies via their constructor  Follow the Explicit Dependencies Principle  Avoid hidden dependencies  Anything the class needs but which is not passed into constructor  Avoid making non-stateless static calls  Avoid directly instantiating classes (except those with no dependencies, like strings)  Instead, move these calls to an interface, and call a local instance of the interface
  25. 25. “New is Glue” Be conscious of the consequences of using “new” If you need loose coupling, replace “new” with Strategy Pattern “new” creates tight coupling between classes
  26. 26. Repository
  27. 27. Data Access Evolution Initially no separation of concerns  Data access logic baked directly into UI ASP.NET Data Source Controls Classic ASP scripts  Data access logic in UI layer via codebehind ASP.NET Page_Load event ASP.NET Button_Click event User Interface Database Compile Time Runtime
  28. 28. Data Access : Helper Classes  Calls to data made through a utility  Example: Data Access Application Block (SqlHelper)  Logic may still live in UI layer  Or a Business Logic Layer may make calls to a Data Access Layer which might then call the helper User Interface Database Compile Time Runtime Helper Class
  29. 29. What’s Missing? Abstraction!  No way to abstract away data access  Tight coupling  Leads to Big Ball of Mud system  Solution: Depend on interfaces, not concrete implementations What should we call such interfaces? Repositories! User Interface Database Compile Time Runtime Core IFooRepository Infrastructure SqlFooRepository
  30. 30. Repository  A Data Access Pattern  Introduced as part of Domain-Driven Design  Very popular outside of DDD  Separates persistence responsibility from business and UI classes
  31. 31. Repository Benefits  Enables Single Responsibility Principle  Promotes Separation of Concerns  Reduces coupling to persistence details  Improves testability
  32. 32. Repository Approaches  Per Entity  CustomerRepository  OrderRepository  ProductRepository
  33. 33. Repository Approaches  Generic Implementation  IRepository<TEntity>  EfRepository<TEntity>  With specific implementations where necessary  ProductRepository (with special product-specific methods added)
  34. 34. Repository Approaches  Organize by Reads vs. Writes (CQRS)  IReadRepository<T>  IWriteRepository<T>  Organize per Bounded Context  Organize per Aggregate  Prevent ability to persist any entity outside of its aggregate
  35. 35. Repository Considerations  Repositories should return domain objects  Don’t Return  Persistence-Specific Types (SqlDataReader, etc.)  View-Specific Types (OrderPageViewModel)
  36. 36. What should List methods return?  IEnumerable<T>  IQueryable<T>  What about deferred execution?  How (and where) to define custom queries?  What about lazy loading?
  37. 37. Avoid Lazy Loading in Web Apps  3 Sessions  2 Speakers  2 Tags
  38. 38. Avoid Lazy Loading in Web Apps @{ ViewBag.Title = "Home Page"; } @model IEnumerable<LazyLoadingMvc5.Models.Session> <h2>Sessions</h2> @foreach (var session in Model) { <div class="row"> <h3>@session.Name</h3> <h4>@string.Join(",", session.SpeakerSessions?.Select(ss => ss.Speaker.Name).ToArray())</h4> <h4>@string.Join(",", session.SessionTags?.Select(st => st.Tag.Name).ToArray())</h4> <p>@session.Description</p> </div> } 22 Queries!
  39. 39. Stacking Patterns
  40. 40. Repository and Strategy Example Refactoring
  41. 41. (1) Create/extend an interface to represent the data access you need (2) Copy the implementation from your class into a new class implementing this interface. (3) Inject the interface using the Strategy Pattern. Use the local field of this interface type in place of previous implementation code.
  42. 42. Where do Repositories Live?  Place interfaces in Core  Core includes Model classes and most business logic  Core has no dependencies (ideally)  Place implementation in Infrastructure  Infrastructure references Core  UI layer (app entry point) references Core  Accesses Infrastructure at runtime  Responsible for creating object graph, either manually or via an IOC Container
  43. 43. Proxy
  44. 44. Proxy  A class that controls access to another  Implemented via subclass or via delegation using a common interface  Frequent use cases: Remote Proxy for web services / network calls Lazy loading implementations Security / access control
  45. 45. Proxy - Structure
  46. 46. Bonus Pattern: Decorator!
  47. 47. Adding Caching to a Repository  Caching is frequently added to query methods in repositories  Caching logic is a separate concern and should live in a separate class from the main data access logic
  48. 48. Proxy or Decorator? Proxy pattern provides a straightforward means to control access to the “real” data, versus the cache. Decorator pattern adds additional functionality or behavior: caching.
  49. 49. Proxy – CachedRepository Implementation
  50. 50. Implementing with IOC (StructureMap) // Strategy Pattern with Proxy Pattern (using composition) x.For<IAlbumRepository>().Use<CachedAlbumRepository>() .Ctor<IAlbumRepository>().Is<EfAlbumRepository>( ); // Doesn’t work: x.For<IAlbumRepository>().Use<CachedAlbumRepository>();
  51. 51. Implementing with IOC (.NET Core) services.AddTransient<IDataService, DataService>((ctx) => { IOtherService svc = ctx.GetService<IOtherService>(); return new DataService(svc); });
  52. 52. Practice Pain Driven Development (PDD)
  53. 53. References  Design Patterns,  Design Patterns Explained,  Design Patterns in C#,  Head First Design Patterns, Pluralsight Resources  N-Tier Application Design in C#  Design Patterns Library  SOLID Principles of OO Design  My Blog   Podcast 
  54. 54. Discuss Contact Twitter: @ardalis Web: