SlideShare une entreprise Scribd logo
1  sur  28
ASP.NET MVC Solution Best Practices
               or,
   a Solution to the Solution Problem
            Steve Smith
        @ardalis | ardalis.com
            Telerik, Inc.
http://about.me/stevenasmith
The Problem
Solution Level Pain
• Too Many Projects

• Too Few Projects

• Incorrect Abstraction

• The “Goldilocks” Solution
  – “Just right”
Relevant Principles
•   Common Closure Principle
•   Common Reuse Principle
•   Stable Dependencies Principle
•   Stable Abstractions Principle
•   Separation of Concerns
•   Dependency Inversion Principle
Principles
• Common Closure
Classes that change together are packaged
together.
Principles
• Common Reuse
Classes that are used together are packaged
together.
Principles
• Stable Dependencies
Depend in the direction of stability.
Principles
• Stable Abstractions
Abstractness increases with stability.
           Abstractness




                          Stability
Principles
• Separation of Concerns
Establish boundaries to separate behaviors and
responsibilities within a system.

• Dependency Inversion
Depend on abstractions, not concrete
implementations.
A Simple Guestbook Application

DEMO
Testability
• Testability correlates with:
  – Loose coupling
  – Separation of Concerns
  – Maintainability


• You don’t have to have unit tests to have
  testable code!
  – Unit tests prove (or disprove) testability
Adding “Unit” Tests

DEMO
http://smtp4dev.codeplex.com/

SMTP4DEV
Incremental Improvement
• From a Single Project
  – Separate responsibilities using folders
  – Add Project(s)


• From Many Projects
  – Create a new Solution with only what you need
  – Spin off separate applications into own solutions
Separation via Folders (still 1 project)

DEMO
Problems
• Tests are still not unit tests
   – Tight coupling
   – Static Cling
   – Dependence on Data and Email Infrastructure concerns

• Nothing to prevent improper referencing of classes
   – e.g. UI code can call DAL code directly and bypass business
     logic

• UI Content Folders mixed with Application Code
  Folders
Onion Architecture
• aka Ports and Adapters,
• aka Hexagonal Architecture

• Core models and interfaces at center
• Infrastructure and Implementation depends
  on Core
• UI depends on Core and has access to
  Infrastructure
Onion Architecture
Introduce Abstractions and Invert Dependencies (in folders)

DEMO
Results
• Yay! Unit Tests that work!

• Boo! Still nothing to prevent improper
  referencing of classes
  – e.g. UI code can call DAL code directly and bypass
    business logic


• Boo! Still mixing content and code folders
Refactor into Projects

DEMO
Results
•   Testable Code
•   Separation of Concerns
•   Loose Coupling
•   Minimal logic in UI layer



         A solid foundation for a
        maintainable application!
Automate
• One Click Build
• One Click Test
Solution Automation – Build Scripts

DEMO
More Tests

DEMO
References
•   Separation of Concerns - http://bit.ly/zWujRe
•   Hexagonal Architecture - http://bit.ly/8Uxl5
•   Onion Architecture - http://bit.ly/4tWMT3
•   More Onion Architecture - http://bit.ly/NzF2Sz
•   New is Glue - http://bit.ly/Ijn98e

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
Thanks!
• Find me at http://ardalis.com

• We’re hiring developers and trainers at
  Telerik!
• http://telerik.com/company/careers.aspx

Contenu connexe

En vedette

Tips and Tricks For Faster Asp.NET and MVC Applications
Tips and Tricks For Faster Asp.NET and MVC ApplicationsTips and Tricks For Faster Asp.NET and MVC Applications
Tips and Tricks For Faster Asp.NET and MVC ApplicationsSarvesh Kushwaha
 
Architecting ASP.NET MVC Applications
Architecting ASP.NET MVC ApplicationsArchitecting ASP.NET MVC Applications
Architecting ASP.NET MVC ApplicationsGunnar Peipman
 
Scaling asp.net websites to millions of users
Scaling asp.net websites to millions of usersScaling asp.net websites to millions of users
Scaling asp.net websites to millions of usersoazabir
 
Query Handling System
Query Handling SystemQuery Handling System
Query Handling Systemhimabindu54
 
ASP.NET Session 1
ASP.NET Session 1ASP.NET Session 1
ASP.NET Session 1Sisir Ghosh
 
Domain-Driven Design with ASP.NET MVC
Domain-Driven Design with ASP.NET MVCDomain-Driven Design with ASP.NET MVC
Domain-Driven Design with ASP.NET MVCSteven Smith
 
50 ideas for using beacons
50 ideas for using beacons50 ideas for using beacons
50 ideas for using beaconsSinergia Labs
 
Beacons: The Retail Revolution
Beacons: The Retail RevolutionBeacons: The Retail Revolution
Beacons: The Retail Revolutionkontakt.io
 
BEACON TECHNOLOGY OVERVIEW
BEACON TECHNOLOGY OVERVIEWBEACON TECHNOLOGY OVERVIEW
BEACON TECHNOLOGY OVERVIEWDonnovan Andrews
 
In-Store Marketing via Micro-Location: Beacon
In-Store Marketing via Micro-Location: BeaconIn-Store Marketing via Micro-Location: Beacon
In-Store Marketing via Micro-Location: BeaconDigitasLBi Paris
 
10 performance and scalability secrets of ASP.NET websites
10 performance and scalability secrets of ASP.NET websites10 performance and scalability secrets of ASP.NET websites
10 performance and scalability secrets of ASP.NET websitesoazabir
 

En vedette (11)

Tips and Tricks For Faster Asp.NET and MVC Applications
Tips and Tricks For Faster Asp.NET and MVC ApplicationsTips and Tricks For Faster Asp.NET and MVC Applications
Tips and Tricks For Faster Asp.NET and MVC Applications
 
Architecting ASP.NET MVC Applications
Architecting ASP.NET MVC ApplicationsArchitecting ASP.NET MVC Applications
Architecting ASP.NET MVC Applications
 
Scaling asp.net websites to millions of users
Scaling asp.net websites to millions of usersScaling asp.net websites to millions of users
Scaling asp.net websites to millions of users
 
Query Handling System
Query Handling SystemQuery Handling System
Query Handling System
 
ASP.NET Session 1
ASP.NET Session 1ASP.NET Session 1
ASP.NET Session 1
 
Domain-Driven Design with ASP.NET MVC
Domain-Driven Design with ASP.NET MVCDomain-Driven Design with ASP.NET MVC
Domain-Driven Design with ASP.NET MVC
 
50 ideas for using beacons
50 ideas for using beacons50 ideas for using beacons
50 ideas for using beacons
 
Beacons: The Retail Revolution
Beacons: The Retail RevolutionBeacons: The Retail Revolution
Beacons: The Retail Revolution
 
BEACON TECHNOLOGY OVERVIEW
BEACON TECHNOLOGY OVERVIEWBEACON TECHNOLOGY OVERVIEW
BEACON TECHNOLOGY OVERVIEW
 
In-Store Marketing via Micro-Location: Beacon
In-Store Marketing via Micro-Location: BeaconIn-Store Marketing via Micro-Location: Beacon
In-Store Marketing via Micro-Location: Beacon
 
10 performance and scalability secrets of ASP.NET websites
10 performance and scalability secrets of ASP.NET websites10 performance and scalability secrets of ASP.NET websites
10 performance and scalability secrets of ASP.NET websites
 

Plus de Steven Smith

Clean architecture with asp.net core by Ardalis
Clean architecture with asp.net core by ArdalisClean architecture with asp.net core by Ardalis
Clean architecture with asp.net core by ArdalisSteven Smith
 
Finding Patterns in the Clouds - Cloud Design Patterns
Finding Patterns in the Clouds - Cloud Design PatternsFinding Patterns in the Clouds - Cloud Design Patterns
Finding Patterns in the Clouds - Cloud Design PatternsSteven Smith
 
Introducing domain driven design - dogfood con 2018
Introducing domain driven design - dogfood con 2018Introducing domain driven design - dogfood con 2018
Introducing domain driven design - dogfood con 2018Steven Smith
 
Design Pattern Mastery - Momentum Dev Con 19 Apr 2018
Design Pattern Mastery - Momentum Dev Con 19 Apr 2018Design Pattern Mastery - Momentum Dev Con 19 Apr 2018
Design Pattern Mastery - Momentum Dev Con 19 Apr 2018Steven Smith
 
Introducing Domain Driven Design - codemash
Introducing Domain Driven Design - codemashIntroducing Domain Driven Design - codemash
Introducing Domain Driven Design - codemashSteven Smith
 
Most Useful Design Patterns
Most Useful Design PatternsMost Useful Design Patterns
Most Useful Design PatternsSteven Smith
 
Improving the Design of Existing Software
Improving the Design of Existing SoftwareImproving the Design of Existing Software
Improving the Design of Existing SoftwareSteven Smith
 
Introducing ASP.NET Core 2.0
Introducing ASP.NET Core 2.0Introducing ASP.NET Core 2.0
Introducing ASP.NET Core 2.0Steven Smith
 
Decoupling with Domain Events
Decoupling with Domain EventsDecoupling with Domain Events
Decoupling with Domain EventsSteven Smith
 
Improving the Quality of Existing Software
Improving the Quality of Existing SoftwareImproving the Quality of Existing Software
Improving the Quality of Existing SoftwareSteven Smith
 
Breaking Dependencies to Allow Unit Testing - DevIntersection Spring 2016
Breaking Dependencies to Allow Unit Testing - DevIntersection Spring 2016Breaking Dependencies to Allow Unit Testing - DevIntersection Spring 2016
Breaking Dependencies to Allow Unit Testing - DevIntersection Spring 2016Steven Smith
 
Improving the Quality of Existing Software - DevIntersection April 2016
Improving the Quality of Existing Software - DevIntersection April 2016Improving the Quality of Existing Software - DevIntersection April 2016
Improving the Quality of Existing Software - DevIntersection April 2016Steven Smith
 
Breaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingBreaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingSteven Smith
 
Improving the Quality of Existing Software
Improving the Quality of Existing SoftwareImproving the Quality of Existing Software
Improving the Quality of Existing SoftwareSteven Smith
 
A Whirldwind Tour of ASP.NET 5
A Whirldwind Tour of ASP.NET 5A Whirldwind Tour of ASP.NET 5
A Whirldwind Tour of ASP.NET 5Steven Smith
 
My Iraq Experience
My Iraq ExperienceMy Iraq Experience
My Iraq ExperienceSteven Smith
 
Add Some DDD to Your ASP.NET MVC, OK?
Add Some DDD to Your ASP.NET MVC, OK?Add Some DDD to Your ASP.NET MVC, OK?
Add Some DDD to Your ASP.NET MVC, OK?Steven Smith
 
Breaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingBreaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingSteven Smith
 
Improving The Quality of Existing Software
Improving The Quality of Existing SoftwareImproving The Quality of Existing Software
Improving The Quality of Existing SoftwareSteven Smith
 

Plus de Steven Smith (20)

Clean architecture with asp.net core by Ardalis
Clean architecture with asp.net core by ArdalisClean architecture with asp.net core by Ardalis
Clean architecture with asp.net core by Ardalis
 
Finding Patterns in the Clouds - Cloud Design Patterns
Finding Patterns in the Clouds - Cloud Design PatternsFinding Patterns in the Clouds - Cloud Design Patterns
Finding Patterns in the Clouds - Cloud Design Patterns
 
Introducing domain driven design - dogfood con 2018
Introducing domain driven design - dogfood con 2018Introducing domain driven design - dogfood con 2018
Introducing domain driven design - dogfood con 2018
 
Design Pattern Mastery - Momentum Dev Con 19 Apr 2018
Design Pattern Mastery - Momentum Dev Con 19 Apr 2018Design Pattern Mastery - Momentum Dev Con 19 Apr 2018
Design Pattern Mastery - Momentum Dev Con 19 Apr 2018
 
Introducing Domain Driven Design - codemash
Introducing Domain Driven Design - codemashIntroducing Domain Driven Design - codemash
Introducing Domain Driven Design - codemash
 
Most Useful Design Patterns
Most Useful Design PatternsMost Useful Design Patterns
Most Useful Design Patterns
 
Improving the Design of Existing Software
Improving the Design of Existing SoftwareImproving the Design of Existing Software
Improving the Design of Existing Software
 
Introducing ASP.NET Core 2.0
Introducing ASP.NET Core 2.0Introducing ASP.NET Core 2.0
Introducing ASP.NET Core 2.0
 
Decoupling with Domain Events
Decoupling with Domain EventsDecoupling with Domain Events
Decoupling with Domain Events
 
Improving the Quality of Existing Software
Improving the Quality of Existing SoftwareImproving the Quality of Existing Software
Improving the Quality of Existing Software
 
Breaking Dependencies to Allow Unit Testing - DevIntersection Spring 2016
Breaking Dependencies to Allow Unit Testing - DevIntersection Spring 2016Breaking Dependencies to Allow Unit Testing - DevIntersection Spring 2016
Breaking Dependencies to Allow Unit Testing - DevIntersection Spring 2016
 
Improving the Quality of Existing Software - DevIntersection April 2016
Improving the Quality of Existing Software - DevIntersection April 2016Improving the Quality of Existing Software - DevIntersection April 2016
Improving the Quality of Existing Software - DevIntersection April 2016
 
Breaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingBreaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit Testing
 
Improving the Quality of Existing Software
Improving the Quality of Existing SoftwareImproving the Quality of Existing Software
Improving the Quality of Existing Software
 
A Whirldwind Tour of ASP.NET 5
A Whirldwind Tour of ASP.NET 5A Whirldwind Tour of ASP.NET 5
A Whirldwind Tour of ASP.NET 5
 
Domain events
Domain eventsDomain events
Domain events
 
My Iraq Experience
My Iraq ExperienceMy Iraq Experience
My Iraq Experience
 
Add Some DDD to Your ASP.NET MVC, OK?
Add Some DDD to Your ASP.NET MVC, OK?Add Some DDD to Your ASP.NET MVC, OK?
Add Some DDD to Your ASP.NET MVC, OK?
 
Breaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit TestingBreaking Dependencies to Allow Unit Testing
Breaking Dependencies to Allow Unit Testing
 
Improving The Quality of Existing Software
Improving The Quality of Existing SoftwareImproving The Quality of Existing Software
Improving The Quality of Existing Software
 

Dernier

Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embeddingZilliz
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostZilliz
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsMark Billinghurst
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationSafe Software
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machinePadma Pradeep
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):comworks
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Wonjun Hwang
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 

Dernier (20)

Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
DMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special EditionDMCC Future of Trade Web3 - Special Edition
DMCC Future of Trade Web3 - Special Edition
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embedding
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage CostLeverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
Leverage Zilliz Serverless - Up to 50X Saving for Your Vector Storage Cost
 
Human Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR SystemsHuman Factors of XR: Using Human Factors to Design XR Systems
Human Factors of XR: Using Human Factors to Design XR Systems
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry InnovationBeyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
Beyond Boundaries: Leveraging No-Code Solutions for Industry Innovation
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Install Stable Diffusion in windows machine
Install Stable Diffusion in windows machineInstall Stable Diffusion in windows machine
Install Stable Diffusion in windows machine
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):CloudStudio User manual (basic edition):
CloudStudio User manual (basic edition):
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
Bun (KitWorks Team Study 노별마루 발표 2024.4.22)
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 

ASP.NET MVC Solution Best Practices aspConf2012

Notes de l'éditeur

  1. You can learn more about me on about.me/stevenasmith. I’ve been working with ASP.NET and ASP.NET MVC in both cases since before they were released, and I’ve been involved as a developer or reviewer of many projects built with these technologies.
  2. This image represents the problem, or at least one of the major contributors to the problem. Visual Studio’s getting started experience is entirely focused on projects – there are 3.2 trillion project templates installed with Visual Studio – and one solution template.Visual Studio offers absolutely no guidance when it comes to structuring Solutions. As a result, there is a great deal of variation in the way different individuals, teams, and organizations approach this problem. In some cases, choices made at the solution level can have a significant impact on the maintainability of the resulting application and its structure.This is not just an ASP.NET or MVC concern, but we’ll look at a solution to the Solution problem in the context of ASP.NET MVC 4.
  3. Sometimes improper solution organization results in too many projects. The problem with too many projects are slower build times, slower load times, issues with some analysis and plug-in tools (usually perf issues), and difficulty finding where the actual code relevant to the issue at hand is located.I’ve seen organizations that have ten years’ and dozens of separate applications, from web sites to web projects to console apps to winforms apps, all in the same solution. The result is a solution with around 100 projects that if you ever accidentally Build, you better go get a cup of coffee, because VS isn’t coming back for at least 5 minutes.The problem with too few projects is that there isn’t enough separation of concerns, and frequently the result is greater coupling within the codebase and frequently a big-ball-of-mud or spaghetti code style of coding with insufficient abstraction.For those solutions that do make use of multiple projects, sometimes a lack of abstraction and application of principles can result in tightly coupled code despite separation into separate projects.The ideal or “goldilocks” solution has not too many, and not too few, but just the right number of projects.
  4. These are some of the principles to keep in mind when considering how to organize the projects within your solution. Some of these should be familiar to you. Many of these can be found in more detail in the book, Agile Principles, Patterns, and Practices in C#.It’s important to remember that Projects are not simply high-level folders for organizing your code, but also correspond to deliverables in the form of .NET assemblies. In larger software systems, if they are well-composed, it should be possible to deploy a bug fix or add a feature by replacing just those components that have changed, without having to redeploy the entire application. This reduces the impact of the change on the system and the likelihood that bugs are introduced by the change.
  5. Common ClosureThe classes in a component should be closed together (see also the Open/Closed Principle) against the same kinds of changes. A change that affects a component affects all the classes in that component and no other components.If we must change the code in an application, we would prefer that the change occur in a single assembly, rather than being deployed across many assemblies. Thus, this principle suggests that if two classes are tightly bound, either physically or conceptually, they’re likely to always change together, and thus should belong in the same component.
  6. Common ReuseClasses tend to collaborate with other classes. It makes sense to package a class and those it always or frequently collaborates with together.
  7. A module (or class) that you have designed to be easy to change can suddenly be made difficult to change by someone else hanging a dependency on it from a hard-to-change component. Now, any time you make a change, the dependent code must also be updated, and your easy-to-change class just got harder.How do we define stability? Essentially if a class or component has many incoming dependencies, it is very stable, because it requires a great deal of work to reconcile any changes among all the dependent components. We can measure stability in terms of the number of inbound and outbound dependencies a class or component has (also known as afferent and efferent couplings).Some software in the system should not change very often, such as high level architecture and design decisions and core business rules. These should live in stable components, meaning they ideally should have no outbound dependencies and many inbound dependencies.Of course, we also want these rules and decisions to be flexible, and we can achieve this via the Open/Closed Principle and the use of abstractions.
  8. A component should be as abstract as it is stable.That is, stable components should be abstract; instable components should be concrete. Thus, assemblies with many inbound dependencies should be more abstract, while those with few dependencies should be concrete.We can graph the relationship between abstractness and stability as shown here (click).In the top left, we have components that are maximally abstract (nothing but abstract classes and interfaces) but have no packages depending upon them. By definition such packages cannot do anything.In the bottom right, we have components that are very stable, thus they have many dependencies upon them, but they are not abstract at all. This is known as the zone of pain. These components are difficult to change because of their incoming dependencies, and cannot be extended because of their lack of abstractness. A very common example of a component that would fall into this area would be a set of classes that represent database schema. Database schemas tend to be very volatile, very concrete, and highly depended upon, and this is one reason why schema updates are often so painful for software applications.
  9. Separation of concerns is a more general principle that applies both to components and packages as well as to classes and methods. It’s somewhat related to the Single Responsibility Principle, in that if we have multiple responsibilities or concerns comingled together, it’s best to separate them. How we separate them will vary depending on context, and might be anything from creating a new method, a new class, or even a new assembly.The Dependency Inversion principle is the object-oriented design principle that the Stable Dependencies and Stable Abstractions principles derive from. It suggests that your dependencies should point toward abstractions, not concrete implementations. A related technique with a similar name is Dependency Injection, which is also related to the Strategy design pattern, and we’ll see this in action in a few moments.
  10. Demo Script:Hg up 10 --clean0) Make sure Smtp4Dev is running/listeningRun the GuestBookMvc4 ApplicationAdd a couple of entriesShow the HomeControllermethodsAsk the audience what’s wrong with this setup? What would you change and why?
  11. Let’s try and add some unit tests to this simple solution and see how well that works for us. Remember that a unit test should be able to just test the logic of the class or method under test in isolation. It shouldn’t need to talk to a database, file system, network, or other infrastructure. If it does do these things, it’s a different kind of test, it’s an integration test.Demo Script:Open the unit tests projectWalk through the first test and run it (SetMessageAndInitialViewModel)Walk through the second test and run it (make sure Smtp4Dev is not running)It should fail with an SmtpExceptionLook at the code where it failed – sigh…Run Smtp4Dev to get it to work.
  12. A useful free tool for doing integration testing with email sending is smtp4dev, which you can grab at codeplex at this URL.
  13. Assuming that you have an existing solution that is causing you pain because of its organization, there are incremental baby steps you can take to improve the situation. In this way you can avoid a complete reorganization of the codebase, but still follow the Boy Scout Rule and leave the code better than you found it.If you have a single project without any separation of concerns (like my Guestbook currently), you can start to separate responsibilities into different folders within the project. Eventually, you can move the classes from these folders into their own projects.If you’re at the opposite end of the spectrum and you find that you have too many projects in your solution, the simplest way to move forward is to create a new blank solution and add in just those projects you’re actively working with for a given unit of deployment (typically, an application). Generally I’ve found it’s best to have a separate solution per unit of deployment, though it’s perfectly acceptable to share code and projects between such solutions. If you worry that a breaking change in a shared project will go undetected in a separate dependent front-end application, that’s what your automated build server is there for. Lacking one of these, you could easily write a script that verifies all solutions work with the latest code and run this whenever you feel the need to do so, without cluttering Visual Studio with dozens of projects and slowing down every build in your IDE. We’ll look at writing such scripts in a few moments.
  14. Hg up 12Demo Script:Show BLL folder and contents – Guestbook and static methodsShow DAL folder and contents – just the DbContext class, no need to open itNote that BLL RecordEntry still has mixed layers of abstractionDeals directly with DbContext internals twiceRequires multiple steps to save an entryRequires a bunch of low-level code to send emails in a loopFix by creating a new Data Layer abstractionMove Email to a Static UtilityHg up 13 (has these changes)
  15. We’ve separated some concerns and made the code at all layers easier to read. The code is definitely better organized than when we started.However, we still have some problems. We have our two tests, but they’re still integration tests that rely on infrastructure, not unit tests. We’re still depending on implementations. We still don’t have any abstractions at all to speak of. We have a lot of tight coupling as a result of our use of static method calls and instantiating classes directly in our methods (remember, New is Glue).There’s also nothing to prevent our UI layer from doing an end-run around our Business Logic Layer aside from programmer discipline or manual code reviews. Ideally we would like to make it difficult for code at one layer to depend on code at another layer that it shouldn’t. One way to achieve this is to minimize how much code is in the UI layer, do as much work as possible in our business logic classes, but avoid having these depend on implementation details and infrastructure. We’ll see how to do this in a moment.Finally, if we look at our project’s folder structure (click), we have all kinds of concerns mixed at the same level of hierarchy. Some of the folders are server-side code, others are client-side resources, etc. We always have some of this in an ASP.NET MVC project, since it has a folder for Controllers, and frequently for Models, but we don’t need to make the problem worse if we can avoid it.
  16. The design we’re going to consider now that follows the principles we’ve discussed and the problems we’ve encountered goes by several names. I tend to refer to it as Onion Architecture, because it is frequently depicted as a cross-section of an onion, with many concentric layers (as anyone who has seen Shrek knows, Onions and Ogres have layers. However, the Ogre Architecture name didn’t get much traction).
  17. Move BLL.Guestbook to Core.Services.GuestBookServiceRemove StaticsAdd Interfaces for Getting list of emails to notifySending notificationsPersisting the entryALTERNATE DESIGN:Expose an event that fires whenever a notification needs to be madeHave a Notifier subscribe to this event or pass in a Listener to the classHg up 15Show HomeController and Dependency Injection via StrategyRun unit tests – they still send email to smtp4dev (or fail)Hg up 16Show fake email implementation in tests
  18. Hg up 17BUILD – Tests failing because they are talking to infrastructure (remove namespace and ResetData())Note that HomeController.Index() is still talking to Infrastructure (fix on line 31)Hg up 18
  19. Hg up 19Show build.proj, build.bat, clicktobuild.bat
  20. Hg up 20Actual unit tests of the logic of each component.Refactored NotificationService to extract the filter policy to make it easier to test on its own.Hg up 21 – add a test for the date range in the NotificationPolicyIt failsFix it.Hg up 22