Successfully reported this slideshow.

Design Pattern Mastery - Momentum Dev Con 19 Apr 2018

5

Share

Upcoming SlideShare
Most Useful Design Patterns
Most Useful Design Patterns
Loading in …3
×
1 of 59
1 of 59

Design Pattern Mastery - Momentum Dev Con 19 Apr 2018

5

Share

Download to read offline

Description

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!

Transcript

  1. 1. Design Pattern Mastery Steve Smith (@ardalis) steve@ardalis.com Ardalis.com Podcast: WeeklyDevTips.com
  2. 2. Design Patterns http://flic.kr/p/8XgqKu
  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 http://flic.kr/p/6StgW5
  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 http://flic.kr/p/6UpMt9
  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: http://csharpindepth.com/Articles/General/Singleton.aspx
  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 http://flic.kr/p/6spkwo
  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:  https://www.pluralsight.com/courses/principles-oo-design
  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 http://flic.kr/p/aN4Zv “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> } https://ardalis.com/avoid-lazy-loading-entities-in-asp-net-applications 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, http://amzn.to/95q9ux  Design Patterns Explained, http://amzn.to/cr8Vxb  Design Patterns in C#, http://amzn.to/bqJgdU  Head First Design Patterns, http://amzn.to/aA4RS6 Pluralsight Resources  N-Tier Application Design in C# http://bit.ly/Msrwig  Design Patterns Library http://bit.ly/vyPEgK  SOLID Principles of OO Design http://bit.ly/OWF4la  My Blog  https://ardalis.com  Podcast  https://weeklydevtips.com
  54. 54. Discuss Contact steve@ardalis.com Twitter: @ardalis Web: ardalis.com http://about.me/stevenasmith

Editor's Notes

  • Contact me if you’d like a 30-day pass to Pluralsight. Please consider some of my courses on design patterns, architecture, and domain-driven design.

  • General, reusable solutions to common problems

    Not a complete, finished solution

    A template, recipe, or approach to solving certain problems

    Each has a specific name, so we can discuss common elements of design using a common vocabulary
  • Published in 1977, this book is cited as the inspiration for the classic, Design Patterns book, by the Gang of Four.
  • Published in 1994, this book is still in its first edition after almost 25 years. Though you can find much of the concepts online, the book is a great reference and if nothing else look great on your bookshelf to impress visitors.
  • Here are some images of programmer bookshelves I found with a quick google search…
  • Learning anything – a musical chord, a martial arts technique, etc.

    Zero: You used a what? Never heard of it.

    Awakening: Wow, I just learned how XYZ pattern can improve my design. I’m not really sure where it would work in my code, but I’m definitely looking.

    Overzealous: I totally “get” the XYZ pattern; I’m adding it everywhere I can shoehorn it into my code. My design’s gonna be better now, for sure!

    Mastery: In response to some specific design pain points, the XYZ pattern was a logical next step and was achieved through a simple refactoring.
  • Design pattern names provide placeholders or complex abstractions and sets of refactorings.
  • This is where a lot of people work. Don’t be these guys. When you have a lot of wood to cut, it pays off to periodically sharpen the saw. Sharpening the saw is one of the seven habits of highly effective people. Take time to improve your skills, and practice, and in the long run you will be more effective.
  • It’s possible for the new Singleton(); line to be called more than once.
  • Jon Skeet lays out several different ways to implement the Singleton pattern in C#, with different performance and thread safety considerations.
  • Add Kragle slide next
  • In my own career as a developer, I’ve seen an evolution in how most data access is performed. I started with classic ASP and soon after, the first version of ASP.NET. In both cases, there was typically little separation of concerns between UI, business rules, and data access. This tended to result in a lot of duplicate concepts and code, as well as direct dependence on a database.
  • To address the duplication, helper classes were often created to take repetitive tasks and centralize them. However, in this case the runtime program flow still mirrored the compile time dependency tree, in both cases targeting a database. This made testing such applications difficult.
  • The problem with these approaches is that there is no abstraction layer between the application and its infrastructure – in this case the database.
  • Consider grabbing repository image from DDD slide here
    Split into two slides
  • Consider grabbing repository image from DDD slide here
    Split into two slides
  • Note – this cannot easily be tested without an actual database instance in place.
  • Add image showing Onion Architecture and/or a simple solution with Core, Infrastructure, and Web.
  • http://en.wikipedia.org/wiki/File:Proxy_concept_en.svg
  • Note that the structure of the Proxy is very similar to the Strategy pattern, which we already saw (click). The key difference between the two is in the intent. Note that this is just one Proxy implementation – it can also be achieved with a proxy class that inherits from the subject class, rather than sharing a common interface implementation.
  • TODO: Show an example of adding caching logic to a repository without any separation of concerns.
    Consider starting with an MVC method that does direct data access without any repository, uses caching, etc, and lament its lack of testability. Perhaps a Music Store method, maybe with some modification.
  • Don’t try to apply every pattern you know up front.
  • Update PS links to use referral links
  • Maybe look for an image representing military orders being received
  • Ask about Amazon and what actually happens when you place an order there, compared to with most other online stores.
  • The background for this slide is the FirstOrDefault image I liked for the Null Object pattern
  • Some polymorphic code
  • Change this to something that isn’t displayed in the UI layer, such as a function that must be called or a number to be summed.

  • Apply patterns via refactoring,
    Not Big Design Up Front


  • Show the MvcMusicStore application
    Hg clone https://hg.codeplex.com/forks/ssmith/mvcmusicstorerepositorypattern 
  • Talk about the CacheDependencyBug in AdSignia and how it was introduced by moving a hard-coded instantiation to a parameter, and then fixed by replacing the parameter with a Factory (lambda).
  • Update with imagery and review of patterns and when to use them. Fewer words.
    Don’t be too busy to improve
    Avoid adding coupling to your system with Singleton
    Decouple specific implementation from use with Strategy
    Avoid hidden dependencies; remember New is Glue!
    Decouple your database with Repository
    Decouple caching, lazy loading, and other access concerns with Proxy
    Decouple execution of other actions with Commands
    Decouple construction with Factory – remember Lazy<T> and lambda as factory shortcuts
    Cut down on prolific null checks with the Null Object Pattern
    Don’t try to use every pattern up front – practice Pain Driven Development
  • Update with imagery and review of patterns and when to use them. Fewer words.
    Don’t be too busy to improve
    Avoid adding coupling to your system with Singleton
    Decouple specific implementation from use with Strategy
    Avoid hidden dependencies; remember New is Glue!
    Decouple your database with Repository
    Decouple caching, lazy loading, and other access concerns with Proxy
    Decouple execution of other actions with Commands
    Decouple construction with Factory – remember Lazy<T> and lambda as factory shortcuts
    Cut down on prolific null checks with the Null Object Pattern
    Don’t try to use every pattern up front – practice Pain Driven Development
  • Update with imagery and review of patterns and when to use them. Fewer words.
    Don’t be too busy to improve
    Avoid adding coupling to your system with Singleton
    Decouple specific implementation from use with Strategy
    Avoid hidden dependencies; remember New is Glue!
    Decouple your database with Repository
    Decouple caching, lazy loading, and other access concerns with Proxy
    Decouple execution of other actions with Commands
    Decouple construction with Factory – remember Lazy<T> and lambda as factory shortcuts
    Cut down on prolific null checks with the Null Object Pattern
    Don’t try to use every pattern up front – practice Pain Driven Development
  • Update with imagery and review of patterns and when to use them. Fewer words.
    Don’t be too busy to improve
    Avoid adding coupling to your system with Singleton
    Decouple specific implementation from use with Strategy
    Avoid hidden dependencies; remember New is Glue!
    Decouple your database with Repository
    Decouple caching, lazy loading, and other access concerns with Proxy
    Decouple execution of other actions with Commands
    Decouple construction with Factory – remember Lazy<T> and lambda as factory shortcuts
    Cut down on prolific null checks with the Null Object Pattern
    Don’t try to use every pattern up front – practice Pain Driven Development
  • Update with imagery and review of patterns and when to use them. Fewer words.
    Don’t be too busy to improve
    Avoid adding coupling to your system with Singleton
    Decouple specific implementation from use with Strategy
    Avoid hidden dependencies; remember New is Glue!
    Decouple your database with Repository
    Decouple caching, lazy loading, and other access concerns with Proxy
    Decouple execution of other actions with Commands
    Decouple construction with Factory – remember Lazy<T> and lambda as factory shortcuts
    Cut down on prolific null checks with the Null Object Pattern
    Don’t try to use every pattern up front – practice Pain Driven Development
  • Update with imagery and review of patterns and when to use them. Fewer words.
    Don’t be too busy to improve
    Avoid adding coupling to your system with Singleton
    Decouple specific implementation from use with Strategy
    Avoid hidden dependencies; remember New is Glue!
    Decouple your database with Repository
    Decouple caching, lazy loading, and other access concerns with Proxy
    Decouple execution of other actions with Commands
    Decouple construction with Factory – remember Lazy<T> and lambda as factory shortcuts
    Cut down on prolific null checks with the Null Object Pattern
    Don’t try to use every pattern up front – practice Pain Driven Development
  • Update with imagery and review of patterns and when to use them. Fewer words.
    Don’t be too busy to improve
    Avoid adding coupling to your system with Singleton
    Decouple specific implementation from use with Strategy
    Avoid hidden dependencies; remember New is Glue!
    Decouple your database with Repository
    Decouple caching, lazy loading, and other access concerns with Proxy
    Decouple execution of other actions with Commands
    Decouple construction with Factory – remember Lazy<T> and lambda as factory shortcuts
    Cut down on prolific null checks with the Null Object Pattern
    Don’t try to use every pattern up front – practice Pain Driven Development
  • Decouple construction with Factory
    Remember Lazy<T> and lambda as factory shortcuts
    Remember IOC containers are factories on steroids
  • Decouple construction with Factory
    Remember Lazy<T> and lambda as factory shortcuts
    Remember IOC containers are factories on steroids
  • Don’t try to apply every pattern you know up front.
  • Update PS links to use referral links
  • Description

    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!

    Transcript

    1. 1. Design Pattern Mastery Steve Smith (@ardalis) steve@ardalis.com Ardalis.com Podcast: WeeklyDevTips.com
    2. 2. Design Patterns http://flic.kr/p/8XgqKu
    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 http://flic.kr/p/6StgW5
    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 http://flic.kr/p/6UpMt9
    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: http://csharpindepth.com/Articles/General/Singleton.aspx
    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 http://flic.kr/p/6spkwo
    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:  https://www.pluralsight.com/courses/principles-oo-design
    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 http://flic.kr/p/aN4Zv “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> } https://ardalis.com/avoid-lazy-loading-entities-in-asp-net-applications 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, http://amzn.to/95q9ux  Design Patterns Explained, http://amzn.to/cr8Vxb  Design Patterns in C#, http://amzn.to/bqJgdU  Head First Design Patterns, http://amzn.to/aA4RS6 Pluralsight Resources  N-Tier Application Design in C# http://bit.ly/Msrwig  Design Patterns Library http://bit.ly/vyPEgK  SOLID Principles of OO Design http://bit.ly/OWF4la  My Blog  https://ardalis.com  Podcast  https://weeklydevtips.com
    54. 54. Discuss Contact steve@ardalis.com Twitter: @ardalis Web: ardalis.com http://about.me/stevenasmith

    Editor's Notes

  • Contact me if you’d like a 30-day pass to Pluralsight. Please consider some of my courses on design patterns, architecture, and domain-driven design.

  • General, reusable solutions to common problems

    Not a complete, finished solution

    A template, recipe, or approach to solving certain problems

    Each has a specific name, so we can discuss common elements of design using a common vocabulary
  • Published in 1977, this book is cited as the inspiration for the classic, Design Patterns book, by the Gang of Four.
  • Published in 1994, this book is still in its first edition after almost 25 years. Though you can find much of the concepts online, the book is a great reference and if nothing else look great on your bookshelf to impress visitors.
  • Here are some images of programmer bookshelves I found with a quick google search…
  • Learning anything – a musical chord, a martial arts technique, etc.

    Zero: You used a what? Never heard of it.

    Awakening: Wow, I just learned how XYZ pattern can improve my design. I’m not really sure where it would work in my code, but I’m definitely looking.

    Overzealous: I totally “get” the XYZ pattern; I’m adding it everywhere I can shoehorn it into my code. My design’s gonna be better now, for sure!

    Mastery: In response to some specific design pain points, the XYZ pattern was a logical next step and was achieved through a simple refactoring.
  • Design pattern names provide placeholders or complex abstractions and sets of refactorings.
  • This is where a lot of people work. Don’t be these guys. When you have a lot of wood to cut, it pays off to periodically sharpen the saw. Sharpening the saw is one of the seven habits of highly effective people. Take time to improve your skills, and practice, and in the long run you will be more effective.
  • It’s possible for the new Singleton(); line to be called more than once.
  • Jon Skeet lays out several different ways to implement the Singleton pattern in C#, with different performance and thread safety considerations.
  • Add Kragle slide next
  • In my own career as a developer, I’ve seen an evolution in how most data access is performed. I started with classic ASP and soon after, the first version of ASP.NET. In both cases, there was typically little separation of concerns between UI, business rules, and data access. This tended to result in a lot of duplicate concepts and code, as well as direct dependence on a database.
  • To address the duplication, helper classes were often created to take repetitive tasks and centralize them. However, in this case the runtime program flow still mirrored the compile time dependency tree, in both cases targeting a database. This made testing such applications difficult.
  • The problem with these approaches is that there is no abstraction layer between the application and its infrastructure – in this case the database.
  • Consider grabbing repository image from DDD slide here
    Split into two slides
  • Consider grabbing repository image from DDD slide here
    Split into two slides
  • Note – this cannot easily be tested without an actual database instance in place.
  • Add image showing Onion Architecture and/or a simple solution with Core, Infrastructure, and Web.
  • http://en.wikipedia.org/wiki/File:Proxy_concept_en.svg
  • Note that the structure of the Proxy is very similar to the Strategy pattern, which we already saw (click). The key difference between the two is in the intent. Note that this is just one Proxy implementation – it can also be achieved with a proxy class that inherits from the subject class, rather than sharing a common interface implementation.
  • TODO: Show an example of adding caching logic to a repository without any separation of concerns.
    Consider starting with an MVC method that does direct data access without any repository, uses caching, etc, and lament its lack of testability. Perhaps a Music Store method, maybe with some modification.
  • Don’t try to apply every pattern you know up front.
  • Update PS links to use referral links
  • Maybe look for an image representing military orders being received
  • Ask about Amazon and what actually happens when you place an order there, compared to with most other online stores.
  • The background for this slide is the FirstOrDefault image I liked for the Null Object pattern
  • Some polymorphic code
  • Change this to something that isn’t displayed in the UI layer, such as a function that must be called or a number to be summed.

  • Apply patterns via refactoring,
    Not Big Design Up Front


  • Show the MvcMusicStore application
    Hg clone https://hg.codeplex.com/forks/ssmith/mvcmusicstorerepositorypattern 
  • Talk about the CacheDependencyBug in AdSignia and how it was introduced by moving a hard-coded instantiation to a parameter, and then fixed by replacing the parameter with a Factory (lambda).
  • Update with imagery and review of patterns and when to use them. Fewer words.
    Don’t be too busy to improve
    Avoid adding coupling to your system with Singleton
    Decouple specific implementation from use with Strategy
    Avoid hidden dependencies; remember New is Glue!
    Decouple your database with Repository
    Decouple caching, lazy loading, and other access concerns with Proxy
    Decouple execution of other actions with Commands
    Decouple construction with Factory – remember Lazy<T> and lambda as factory shortcuts
    Cut down on prolific null checks with the Null Object Pattern
    Don’t try to use every pattern up front – practice Pain Driven Development
  • Update with imagery and review of patterns and when to use them. Fewer words.
    Don’t be too busy to improve
    Avoid adding coupling to your system with Singleton
    Decouple specific implementation from use with Strategy
    Avoid hidden dependencies; remember New is Glue!
    Decouple your database with Repository
    Decouple caching, lazy loading, and other access concerns with Proxy
    Decouple execution of other actions with Commands
    Decouple construction with Factory – remember Lazy<T> and lambda as factory shortcuts
    Cut down on prolific null checks with the Null Object Pattern
    Don’t try to use every pattern up front – practice Pain Driven Development
  • Update with imagery and review of patterns and when to use them. Fewer words.
    Don’t be too busy to improve
    Avoid adding coupling to your system with Singleton
    Decouple specific implementation from use with Strategy
    Avoid hidden dependencies; remember New is Glue!
    Decouple your database with Repository
    Decouple caching, lazy loading, and other access concerns with Proxy
    Decouple execution of other actions with Commands
    Decouple construction with Factory – remember Lazy<T> and lambda as factory shortcuts
    Cut down on prolific null checks with the Null Object Pattern
    Don’t try to use every pattern up front – practice Pain Driven Development
  • Update with imagery and review of patterns and when to use them. Fewer words.
    Don’t be too busy to improve
    Avoid adding coupling to your system with Singleton
    Decouple specific implementation from use with Strategy
    Avoid hidden dependencies; remember New is Glue!
    Decouple your database with Repository
    Decouple caching, lazy loading, and other access concerns with Proxy
    Decouple execution of other actions with Commands
    Decouple construction with Factory – remember Lazy<T> and lambda as factory shortcuts
    Cut down on prolific null checks with the Null Object Pattern
    Don’t try to use every pattern up front – practice Pain Driven Development
  • Update with imagery and review of patterns and when to use them. Fewer words.
    Don’t be too busy to improve
    Avoid adding coupling to your system with Singleton
    Decouple specific implementation from use with Strategy
    Avoid hidden dependencies; remember New is Glue!
    Decouple your database with Repository
    Decouple caching, lazy loading, and other access concerns with Proxy
    Decouple execution of other actions with Commands
    Decouple construction with Factory – remember Lazy<T> and lambda as factory shortcuts
    Cut down on prolific null checks with the Null Object Pattern
    Don’t try to use every pattern up front – practice Pain Driven Development
  • Update with imagery and review of patterns and when to use them. Fewer words.
    Don’t be too busy to improve
    Avoid adding coupling to your system with Singleton
    Decouple specific implementation from use with Strategy
    Avoid hidden dependencies; remember New is Glue!
    Decouple your database with Repository
    Decouple caching, lazy loading, and other access concerns with Proxy
    Decouple execution of other actions with Commands
    Decouple construction with Factory – remember Lazy<T> and lambda as factory shortcuts
    Cut down on prolific null checks with the Null Object Pattern
    Don’t try to use every pattern up front – practice Pain Driven Development
  • Update with imagery and review of patterns and when to use them. Fewer words.
    Don’t be too busy to improve
    Avoid adding coupling to your system with Singleton
    Decouple specific implementation from use with Strategy
    Avoid hidden dependencies; remember New is Glue!
    Decouple your database with Repository
    Decouple caching, lazy loading, and other access concerns with Proxy
    Decouple execution of other actions with Commands
    Decouple construction with Factory – remember Lazy<T> and lambda as factory shortcuts
    Cut down on prolific null checks with the Null Object Pattern
    Don’t try to use every pattern up front – practice Pain Driven Development
  • Decouple construction with Factory
    Remember Lazy<T> and lambda as factory shortcuts
    Remember IOC containers are factories on steroids
  • Decouple construction with Factory
    Remember Lazy<T> and lambda as factory shortcuts
    Remember IOC containers are factories on steroids
  • Don’t try to apply every pattern you know up front.
  • Update PS links to use referral links
  • More Related Content

    Related Books

    Free with a 30 day trial from Scribd

    See all

    ×