SlideShare a Scribd company logo
Improving the Quality of
Existing Software
Steve Smith
Ardalis Services
@ardalis | ardalis.com
Tweet Away
• LiveTweeting and Photos are encouraged
• Questions and Feedback are welcome
• Use #DevIntersection and/or #ImproveSoftware
• Or #DevIntersectionImprovingTheQualityOfExistingSoftware
Pluralsight
I have some 1-month free
passes; see me after if
you’d like one
Software Rots
Improving the Quality of Existing Software - DevIntersection April 2016
Technical Debt
• Low quality code and shortcuts in our applications
• Technical debt, like real debt, has direct cost to pay off as well as interest
http://www.jimhighsmith.com/
Preventive Maintenance
• Refactoring
• Eliminate Duplication
• Simplify Design
• AutomatedTests
• Verify correctness
• Avoid regressions
• Increase Confidence
When should you refactor?
• While delivering value
“
”
You don’t need permission to practice basic hygiene
when you write software.
http://ardalis.com/when-should-you-refactor/
Make cleaning up your code something you do as part of writing code.
Improving the Quality of Existing Software - DevIntersection April 2016
Refactoring Should Not Change System
Behavior
The Refactoring Process
• Verify existing behavior
• Write CharacterizationTests if none exist
• Find test points
• Break dependencies
• Apply Refactoring
• Confirm existing behavior is preserved
CharacterizationTests
Process
1. Write a test you know will fail
2. Use the output of the failing test to determine the existing behavior to
assert
3. Update the test with the new value/behavior
4. Run the test again – it should now pass
Improving the Quality of Existing Software - DevIntersection April 2016
Improving the Quality of Existing Software - DevIntersection April 2016
S O L I DPrinciples
http://flickr.com/photos/kevinkemmerer/2772526725/
Principles of OO Design
0. Don’t RepeatYourself (DRY)
1. Single Responsibility
2. Open/Closed
3. Liskov Substitution
4. Interface Segregation
5. Dependency Inversion
Improving the Quality of Existing Software - DevIntersection April 2016
Improving the Quality of Existing Software - DevIntersection April 2016
Don’t Repeat
RepeatYourself
• Duplication in logic calls for abstraction
• Duplication in process calls for automation
Common Refactorings
• Replace Magic Number/String
• Parameterize Method
• Pull Up Field
• Pull Up Method
• Replace Conditional With Polymorphism
• Introduce Method
Common Source of Repetition: Role Checks
if(user.IsInRole(“Admins”)
{
// allow access to resource
}
// favor privileges over role checks
// ardalis.com/Favor-Privileges-over-Role-Checks
var priv = new ContentPrivilege(user, article);
if(priv.CanEdit())
{
// allow access
}
Visual Studio Code Clones
• Find similar blocks of code in your projects/solution
• Can detect matches that are similar but vary in small ways (like variable
names)
• Available inVS2015 Premium and Ultimate
Improving the Quality of Existing Software - DevIntersection April 2016
Single Responsibility Principle
The Single Responsibility Principle states that every object should have a single
responsibility, and that responsibility should be entirely encapsulated by the
class.
Wikipedia
There should never be more than one reason for a class to change.
Robert C. “Uncle Bob” Martin
What is a responsibility?
“My CustomerManager class is only responsible for
anything to do with a Customer.That follows SRP, right?”
Examples of Responsibilities
• Persistence
• Validation
• Notification
• Error Handling
• Logging
• Class Selection / Construction
• Formatting
• Parsing
• Mapping
Dependency and Coupling
• Excessive coupling makes changing legacy software difficult
• Breaking apart responsibilities and dependencies is a large part of working
with existing code
Common Refactorings
• Extract Class
• Extract Method
• Move Method
Heuristics and Code Smells
• Visual Studio Metrics
Cyclomatic Complexity
https://en.wikipedia.org/wiki/Cyclomatic_complexity
Improving the Quality of Existing Software - DevIntersection April 2016
Code Smell: Regions
More on Regions: http://ardalis.com/regional-differences
Improving the Quality of Existing Software - DevIntersection April 2016
Open / Closed Principle
The Open / Closed Principle states that software entities (classes, modules,
functions, etc.) should be open for extension, but closed for modification.
Wikipedia
Open / Closed Principle
Open to Extension
New behavior can be added in the future
Closed to Modification
Changes to source or binary code are not required
Dr. Bertrand Meyer originated the OCP term in his 1988 book, ObjectOrientedSoftwareConstruction
Common Refactorings
• Extract Interface / Apply Strategy Pattern
• Parameterize Method
• FormTemplate Method
OCP Fail
OCP OK
OCP Fail
public bool IsSpecialCustomer(Customer c)
{
if(c.Country == “US” && c.Balance < 50) return false;
if(c.Country == “DE” && c.Balance < 25) return false;
if(c.Country == “UK” && c.Balance < 35) return false;
if(c.Country == “FR” && c.Balance < 27) return false;
if(c.Country == “BG” && c.Balance < 29) return false;
if(c.Age < 18 || c.Age > 65) return false;
if(c.Income < 50000 && c.Age < 30) return false;
return true;
}
OCP OK
private IEnumerable<ICustomerRule> _rules;
public bool IsSpecialCustomer(Customer customer)
{
foreach(var rule in _rules)
{
if(rule.Evaluate(customer) == false) return false;
}
return true;
}
Improving the Quality of Existing Software - DevIntersection April 2016
Liskov Substitution Principle
The Liskov Substitution Principle states that Subtypes must be substitutable for
their base types.
Agile Principles, Patterns, and Practices in C#
Named for Barbara Liskov, who first described the principle in 1988.
Common Refactorings
• Collapse Hierarchy
• Pull Up / Push Down Field
• Pull Up / Push Down Method
Liskov Substitution Fail
foreach(var employee in employees)
{
if(employee is Manager)
{
Helpers.PrintManager(employee as Manager);
break;
}
Helpers.PrintEmployee(employee);
}
Liskov Substitution OK
foreach(var employee in employees)
{
employee.Print();
// or
Helpers.PrintEmployee(employee);
}
Nulls Break Polymorphism
foreach(var employee in employees)
{
if(employee == null)
{
// print not found message
break;
}
Helpers.PrintEmployee(employee);
} http://ardalis.com/nulls-break-polymorphism
Improving the Quality of Existing Software - DevIntersection April 2016
Interface Segregation Principle
The Interface Segregation Principle states that Clients should not be
forced to depend on methods they do not use.
Agile Principles, Patterns, and Practices in C#
Corollary:
Prefer small, cohesive interfaces to “fat” interfaces
Common Refactorings
• Extract Interface
Keep Interfaces Small and Focused
Membership Provider
ISP Fail (sometimes)
public IRepository<T>
{
T GetById(int id);
IEnumerable<T> List();
void Create(T item);
void Update(T item);
void Delete(T item);
}
ISP OK (i.e. to support CQRS)
public IRepository<T> : IReadRepository<T>,
IWriteRepository<T>
{ }
public IReadRepository<T>
{
T GetById(int id);
IEnumerable<T> List();
}
public IWriteRepository<T>
void Create(T item);
void Update(T item);
void Delete(T item);
}
Existing implementations of
IRepository<T> are
unaffected by pulling out
smaller interfaces!
No existing code breaks!
Improving the Quality of Existing Software - DevIntersection April 2016
Dependency Inversion Principle
High-level modules should not depend on low-level modules. Both
should depend on abstractions.
Abstractions should not depend on details. Details should depend on
abstractions.
Agile Principles, Patterns, and Practices in C#
Dependency Inversion Principle
• Depend on Abstractions
• Interfaces, not concrete types
• Inject Dependencies into Classes
• Structure Solution so Dependencies FlowToward Core
• Onion Architecture (a.k.a. Ports and Adapters, a.k.a. Hexagonal Architecture)
Application Layers
Data Access Evolution
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
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
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
DIP Architecture (aka Ports and Adapters)
Common Dependencies
• Framework
• Third Party Libraries
• Database
• File System
• Email
• Web Services
• System Resources (Clock)
• Configuration
• The new Keyword
• Static methods
• Thread.Sleep
• Random
See also responsibilities:
• Persistence
• Validation
• Notification
• Error Handling
• Logging
• Class Selection /
Construction
• Formatting
• Parsing
• Mapping
Common Refactorings
• Extract Class
• Extract Interface / Apply Strategy Pattern
• Extract Method
• Introduce Service Locator / Container
DIP Fail
Hidden Dependencies
• Checkout Depends on an available SMTP server, but the class doesn’t reflect
this
• Follow the Explicit Dependencies Principle
• http://deviq.com/explicit-dependencies-principle/
Some Improvement (Façade)
DIP OK (Strategy Pattern / DI)
DIP OK (Strategy Pattern / DI)
Improving Quality Across the Industry
Self-Improvement and Quality
• How fast can you produce:
• Code you believe to be of high quality
• Code that maybe gets the job done, but you believe to be of low quality
• Which one can you produce more quickly?
• Why?
• How can we develop our skills and our tools so that building quality is
natural and easier than not doing so?
0
2
4
6
8
10
12
14
16
Week 1 Week 2 Week 3 Week 4 Week 5 Week 6 Week 7 Week 8 Week 9
User Stories Completed
High Quality Low Quality
0
2
4
6
8
10
12
14
16
18
20
Week 1 Week 2 Week 3 Week 4 Week 5 Week 6 Week 7 Week 8 Week 9
User Stories Completed
High Quality Low Quality
Summary
•Maintain / Improve ApplicationCode
•Follow DRY/SOLID Principles
•Use CharacterizationTests to “fix” behavior
•Apply Common Refactorings
•Re-runTests After (and during) Refactorings
•Be ExplicitAbout Class Dependencies
•Train and Practice to Write Better Code Faster
Learn More
• DevIQ.com –Take Pride inYour Code
• Ardalis.com
• @ardalis
• Pluralsight:
• SOLID Principles of OO Design
• N-TierArchitecture in C#
• Refactoring Fundamentals
• Domain-Driven Design Fundamentals
• Design Pattern Library
• Pair Programming
Books
 Refactoring http://amzn.to/110tscA
 Refactoring to Patterns http://amzn.to/Vq5Rj2
 Working Effectively with Legacy Code http://amzn.to/VFFYbn
 Code Complete http://amzn.to/Vq5YLv
 Clean Code http://amzn.to/YjUDI0
© DEVintersection. All rights reserved.
http://www.DEVintersection.com
Please use Event Board
to fill out a session evaluation.
Questions?
Thank you!

More Related Content

PPTX
Improving the Quality of Existing Software
PPTX
Breaking Dependencies to Allow Unit Testing - DevIntersection Spring 2016
PPTX
Improving The Quality of Existing Software
PPTX
Improving the Quality of Existing Software
PPTX
Breaking Dependencies to Allow Unit Testing
PPTX
Improving the Quality of Existing Software
PDF
Breaking Dependencies to Allow Unit Testing
PPTX
Principles and patterns for test driven development
Improving the Quality of Existing Software
Breaking Dependencies to Allow Unit Testing - DevIntersection Spring 2016
Improving The Quality of Existing Software
Improving the Quality of Existing Software
Breaking Dependencies to Allow Unit Testing
Improving the Quality of Existing Software
Breaking Dependencies to Allow Unit Testing
Principles and patterns for test driven development

What's hot (20)

PPTX
Automated Acceptance Tests in .NET
PPTX
Building unit tests correctly with visual studio 2013
PDF
Getting Started with Selenium
PDF
How To Use Selenium Successfully
PPTX
Battle of The Mocking Frameworks
PPTX
Design Pattern Mastery - Momentum Dev Con 19 Apr 2018
PPTX
Working Effectively With Legacy Code
PPTX
Power-Up Your Test Suite with OLE Automation by Joshua Russell
PDF
Practical Test Automation Deep Dive
PPTX
Improving the Design of Existing Software
PPTX
Testing Rapidly Changing Applications With Self-Testing Object-Oriented Selen...
PPTX
Introducing domain driven design - dogfood con 2018
PPTX
Как стать синьором
PPTX
Системный взгляд на параллельный запуск Selenium тестов
PDF
How To Find Information On Your Own
PPTX
Bdd and spec flow
PDF
From Good to Great: Functional and Acceptance Testing in WordPress.
PDF
Getting Ahead of Delivery Issues with Deep SDLC Analysis by Donald Belcham
PDF
Dave Haeffner's Proven Method to Grading the Quality of Selenium Tests
PDF
Introduction To Web Application Testing
Automated Acceptance Tests in .NET
Building unit tests correctly with visual studio 2013
Getting Started with Selenium
How To Use Selenium Successfully
Battle of The Mocking Frameworks
Design Pattern Mastery - Momentum Dev Con 19 Apr 2018
Working Effectively With Legacy Code
Power-Up Your Test Suite with OLE Automation by Joshua Russell
Practical Test Automation Deep Dive
Improving the Design of Existing Software
Testing Rapidly Changing Applications With Self-Testing Object-Oriented Selen...
Introducing domain driven design - dogfood con 2018
Как стать синьором
Системный взгляд на параллельный запуск Selenium тестов
How To Find Information On Your Own
Bdd and spec flow
From Good to Great: Functional and Acceptance Testing in WordPress.
Getting Ahead of Delivery Issues with Deep SDLC Analysis by Donald Belcham
Dave Haeffner's Proven Method to Grading the Quality of Selenium Tests
Introduction To Web Application Testing
Ad

Similar to Improving the Quality of Existing Software - DevIntersection April 2016 (20)

PPTX
Refactoring with SOLID Principles (FalafelCon 2013)
PPTX
Refactoring Applications using SOLID Principles
PPTX
Refactoring with SOLID - Telerik India DevCon 2013
PDF
Inversion of Control
PPTX
C:\Fakepath\Combating Software Entropy 2
PPTX
C:\Fakepath\Combating Software Entropy 2
PDF
Solid principle
PPTX
Establishing a SOLID Foundation
PPTX
2009 Dotnet Information Day: More effective c#
PPTX
¿Qué tan s.o.l.i.d. es tú código
PPTX
SOLID Principles of Refactoring Presentation - Inland Empire User Group
PPTX
Soild principles
PPTX
Learning solid principles using c#
PPTX
Becoming a better developer by using the SOLID design principles
PDF
Commonly used design patterns
PPTX
PPTX
Most Useful Design Patterns
PDF
Software design principles - jinal desai
PPTX
An Introduction to the SOLID Principles
Refactoring with SOLID Principles (FalafelCon 2013)
Refactoring Applications using SOLID Principles
Refactoring with SOLID - Telerik India DevCon 2013
Inversion of Control
C:\Fakepath\Combating Software Entropy 2
C:\Fakepath\Combating Software Entropy 2
Solid principle
Establishing a SOLID Foundation
2009 Dotnet Information Day: More effective c#
¿Qué tan s.o.l.i.d. es tú código
SOLID Principles of Refactoring Presentation - Inland Empire User Group
Soild principles
Learning solid principles using c#
Becoming a better developer by using the SOLID design principles
Commonly used design patterns
Most Useful Design Patterns
Software design principles - jinal desai
An Introduction to the SOLID Principles
Ad

More from Steven Smith (15)

PPTX
Clean architecture with asp.net core by Ardalis
PDF
Finding Patterns in the Clouds - Cloud Design Patterns
PPTX
Introducing Domain Driven Design - codemash
PPTX
Introducing ASP.NET Core 2.0
PPTX
Decoupling with Domain Events
PPTX
A Whirldwind Tour of ASP.NET 5
PPTX
Domain events
PPTX
My Iraq Experience
PDF
Add Some DDD to Your ASP.NET MVC, OK?
PDF
Domain-Driven Design with ASP.NET MVC
PPTX
Common ASP.NET Design Patterns - Telerik India DevCon 2013
PPTX
Common asp.net design patterns aspconf2012
PPTX
Common design patterns (migang 16 May 2012)
PDF
Introducing Pair Programming
PPTX
Cinci ug-january2011-anti-patterns
Clean architecture with asp.net core by Ardalis
Finding Patterns in the Clouds - Cloud Design Patterns
Introducing Domain Driven Design - codemash
Introducing ASP.NET Core 2.0
Decoupling with Domain Events
A Whirldwind Tour of ASP.NET 5
Domain events
My Iraq Experience
Add Some DDD to Your ASP.NET MVC, OK?
Domain-Driven Design with ASP.NET MVC
Common ASP.NET Design Patterns - Telerik India DevCon 2013
Common asp.net design patterns aspconf2012
Common design patterns (migang 16 May 2012)
Introducing Pair Programming
Cinci ug-january2011-anti-patterns

Recently uploaded (20)

PDF
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
PDF
Adobe Illustrator 28.6 Crack My Vision of Vector Design
PDF
Design an Analysis of Algorithms I-SECS-1021-03
PPTX
VVF-Customer-Presentation2025-Ver1.9.pptx
PDF
Internet Downloader Manager (IDM) Crack 6.42 Build 41
PPTX
ai tools demonstartion for schools and inter college
PPTX
CHAPTER 2 - PM Management and IT Context
PDF
Nekopoi APK 2025 free lastest update
PDF
Upgrade and Innovation Strategies for SAP ERP Customers
PDF
Softaken Excel to vCard Converter Software.pdf
PDF
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
PDF
Understanding Forklifts - TECH EHS Solution
PPTX
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
PPT
Introduction Database Management System for Course Database
PDF
Which alternative to Crystal Reports is best for small or large businesses.pdf
PDF
PTS Company Brochure 2025 (1).pdf.......
PDF
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
PDF
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
PPTX
L1 - Introduction to python Backend.pptx
PDF
How Creative Agencies Leverage Project Management Software.pdf
Claude Code: Everyone is a 10x Developer - A Comprehensive AI-Powered CLI Tool
Adobe Illustrator 28.6 Crack My Vision of Vector Design
Design an Analysis of Algorithms I-SECS-1021-03
VVF-Customer-Presentation2025-Ver1.9.pptx
Internet Downloader Manager (IDM) Crack 6.42 Build 41
ai tools demonstartion for schools and inter college
CHAPTER 2 - PM Management and IT Context
Nekopoi APK 2025 free lastest update
Upgrade and Innovation Strategies for SAP ERP Customers
Softaken Excel to vCard Converter Software.pdf
T3DD25 TYPO3 Content Blocks - Deep Dive by André Kraus
Understanding Forklifts - TECH EHS Solution
Oracle E-Business Suite: A Comprehensive Guide for Modern Enterprises
Introduction Database Management System for Course Database
Which alternative to Crystal Reports is best for small or large businesses.pdf
PTS Company Brochure 2025 (1).pdf.......
Audit Checklist Design Aligning with ISO, IATF, and Industry Standards — Omne...
Raksha Bandhan Grocery Pricing Trends in India 2025.pdf
L1 - Introduction to python Backend.pptx
How Creative Agencies Leverage Project Management Software.pdf

Improving the Quality of Existing Software - DevIntersection April 2016

  • 1. Improving the Quality of Existing Software Steve Smith Ardalis Services @ardalis | ardalis.com
  • 2. Tweet Away • LiveTweeting and Photos are encouraged • Questions and Feedback are welcome • Use #DevIntersection and/or #ImproveSoftware • Or #DevIntersectionImprovingTheQualityOfExistingSoftware
  • 3. Pluralsight I have some 1-month free passes; see me after if you’d like one
  • 6. Technical Debt • Low quality code and shortcuts in our applications • Technical debt, like real debt, has direct cost to pay off as well as interest
  • 8. Preventive Maintenance • Refactoring • Eliminate Duplication • Simplify Design • AutomatedTests • Verify correctness • Avoid regressions • Increase Confidence
  • 9. When should you refactor? • While delivering value
  • 10. “ ” You don’t need permission to practice basic hygiene when you write software. http://ardalis.com/when-should-you-refactor/ Make cleaning up your code something you do as part of writing code.
  • 12. Refactoring Should Not Change System Behavior
  • 13. The Refactoring Process • Verify existing behavior • Write CharacterizationTests if none exist • Find test points • Break dependencies • Apply Refactoring • Confirm existing behavior is preserved
  • 14. CharacterizationTests Process 1. Write a test you know will fail 2. Use the output of the failing test to determine the existing behavior to assert 3. Update the test with the new value/behavior 4. Run the test again – it should now pass
  • 17. S O L I DPrinciples http://flickr.com/photos/kevinkemmerer/2772526725/
  • 18. Principles of OO Design 0. Don’t RepeatYourself (DRY) 1. Single Responsibility 2. Open/Closed 3. Liskov Substitution 4. Interface Segregation 5. Dependency Inversion
  • 21. Don’t Repeat RepeatYourself • Duplication in logic calls for abstraction • Duplication in process calls for automation
  • 22. Common Refactorings • Replace Magic Number/String • Parameterize Method • Pull Up Field • Pull Up Method • Replace Conditional With Polymorphism • Introduce Method
  • 23. Common Source of Repetition: Role Checks if(user.IsInRole(“Admins”) { // allow access to resource } // favor privileges over role checks // ardalis.com/Favor-Privileges-over-Role-Checks var priv = new ContentPrivilege(user, article); if(priv.CanEdit()) { // allow access }
  • 24. Visual Studio Code Clones • Find similar blocks of code in your projects/solution • Can detect matches that are similar but vary in small ways (like variable names) • Available inVS2015 Premium and Ultimate
  • 26. Single Responsibility Principle The Single Responsibility Principle states that every object should have a single responsibility, and that responsibility should be entirely encapsulated by the class. Wikipedia There should never be more than one reason for a class to change. Robert C. “Uncle Bob” Martin
  • 27. What is a responsibility? “My CustomerManager class is only responsible for anything to do with a Customer.That follows SRP, right?”
  • 28. Examples of Responsibilities • Persistence • Validation • Notification • Error Handling • Logging • Class Selection / Construction • Formatting • Parsing • Mapping
  • 29. Dependency and Coupling • Excessive coupling makes changing legacy software difficult • Breaking apart responsibilities and dependencies is a large part of working with existing code
  • 30. Common Refactorings • Extract Class • Extract Method • Move Method
  • 31. Heuristics and Code Smells • Visual Studio Metrics
  • 34. Code Smell: Regions More on Regions: http://ardalis.com/regional-differences
  • 36. Open / Closed Principle The Open / Closed Principle states that software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification. Wikipedia
  • 37. Open / Closed Principle Open to Extension New behavior can be added in the future Closed to Modification Changes to source or binary code are not required Dr. Bertrand Meyer originated the OCP term in his 1988 book, ObjectOrientedSoftwareConstruction
  • 38. Common Refactorings • Extract Interface / Apply Strategy Pattern • Parameterize Method • FormTemplate Method
  • 41. OCP Fail public bool IsSpecialCustomer(Customer c) { if(c.Country == “US” && c.Balance < 50) return false; if(c.Country == “DE” && c.Balance < 25) return false; if(c.Country == “UK” && c.Balance < 35) return false; if(c.Country == “FR” && c.Balance < 27) return false; if(c.Country == “BG” && c.Balance < 29) return false; if(c.Age < 18 || c.Age > 65) return false; if(c.Income < 50000 && c.Age < 30) return false; return true; }
  • 42. OCP OK private IEnumerable<ICustomerRule> _rules; public bool IsSpecialCustomer(Customer customer) { foreach(var rule in _rules) { if(rule.Evaluate(customer) == false) return false; } return true; }
  • 44. Liskov Substitution Principle The Liskov Substitution Principle states that Subtypes must be substitutable for their base types. Agile Principles, Patterns, and Practices in C# Named for Barbara Liskov, who first described the principle in 1988.
  • 45. Common Refactorings • Collapse Hierarchy • Pull Up / Push Down Field • Pull Up / Push Down Method
  • 46. Liskov Substitution Fail foreach(var employee in employees) { if(employee is Manager) { Helpers.PrintManager(employee as Manager); break; } Helpers.PrintEmployee(employee); }
  • 47. Liskov Substitution OK foreach(var employee in employees) { employee.Print(); // or Helpers.PrintEmployee(employee); }
  • 48. Nulls Break Polymorphism foreach(var employee in employees) { if(employee == null) { // print not found message break; } Helpers.PrintEmployee(employee); } http://ardalis.com/nulls-break-polymorphism
  • 50. Interface Segregation Principle The Interface Segregation Principle states that Clients should not be forced to depend on methods they do not use. Agile Principles, Patterns, and Practices in C# Corollary: Prefer small, cohesive interfaces to “fat” interfaces
  • 52. Keep Interfaces Small and Focused
  • 54. ISP Fail (sometimes) public IRepository<T> { T GetById(int id); IEnumerable<T> List(); void Create(T item); void Update(T item); void Delete(T item); }
  • 55. ISP OK (i.e. to support CQRS) public IRepository<T> : IReadRepository<T>, IWriteRepository<T> { } public IReadRepository<T> { T GetById(int id); IEnumerable<T> List(); } public IWriteRepository<T> void Create(T item); void Update(T item); void Delete(T item); } Existing implementations of IRepository<T> are unaffected by pulling out smaller interfaces! No existing code breaks!
  • 57. Dependency Inversion Principle High-level modules should not depend on low-level modules. Both should depend on abstractions. Abstractions should not depend on details. Details should depend on abstractions. Agile Principles, Patterns, and Practices in C#
  • 58. Dependency Inversion Principle • Depend on Abstractions • Interfaces, not concrete types • Inject Dependencies into Classes • Structure Solution so Dependencies FlowToward Core • Onion Architecture (a.k.a. Ports and Adapters, a.k.a. Hexagonal Architecture)
  • 60. Data Access Evolution 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
  • 61. 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
  • 62. 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
  • 63. DIP Architecture (aka Ports and Adapters)
  • 64. Common Dependencies • Framework • Third Party Libraries • Database • File System • Email • Web Services • System Resources (Clock) • Configuration • The new Keyword • Static methods • Thread.Sleep • Random See also responsibilities: • Persistence • Validation • Notification • Error Handling • Logging • Class Selection / Construction • Formatting • Parsing • Mapping
  • 65. Common Refactorings • Extract Class • Extract Interface / Apply Strategy Pattern • Extract Method • Introduce Service Locator / Container
  • 67. Hidden Dependencies • Checkout Depends on an available SMTP server, but the class doesn’t reflect this • Follow the Explicit Dependencies Principle • http://deviq.com/explicit-dependencies-principle/
  • 69. DIP OK (Strategy Pattern / DI)
  • 70. DIP OK (Strategy Pattern / DI)
  • 71. Improving Quality Across the Industry
  • 72. Self-Improvement and Quality • How fast can you produce: • Code you believe to be of high quality • Code that maybe gets the job done, but you believe to be of low quality • Which one can you produce more quickly? • Why? • How can we develop our skills and our tools so that building quality is natural and easier than not doing so?
  • 73. 0 2 4 6 8 10 12 14 16 Week 1 Week 2 Week 3 Week 4 Week 5 Week 6 Week 7 Week 8 Week 9 User Stories Completed High Quality Low Quality
  • 74. 0 2 4 6 8 10 12 14 16 18 20 Week 1 Week 2 Week 3 Week 4 Week 5 Week 6 Week 7 Week 8 Week 9 User Stories Completed High Quality Low Quality
  • 75. Summary •Maintain / Improve ApplicationCode •Follow DRY/SOLID Principles •Use CharacterizationTests to “fix” behavior •Apply Common Refactorings •Re-runTests After (and during) Refactorings •Be ExplicitAbout Class Dependencies •Train and Practice to Write Better Code Faster
  • 76. Learn More • DevIQ.com –Take Pride inYour Code • Ardalis.com • @ardalis • Pluralsight: • SOLID Principles of OO Design • N-TierArchitecture in C# • Refactoring Fundamentals • Domain-Driven Design Fundamentals • Design Pattern Library • Pair Programming
  • 77. Books  Refactoring http://amzn.to/110tscA  Refactoring to Patterns http://amzn.to/Vq5Rj2  Working Effectively with Legacy Code http://amzn.to/VFFYbn  Code Complete http://amzn.to/Vq5YLv  Clean Code http://amzn.to/YjUDI0
  • 78. © DEVintersection. All rights reserved. http://www.DEVintersection.com Please use Event Board to fill out a session evaluation. Questions? Thank you!

Editor's Notes

  • #3: https://twitter.com/hashtag/devintersection https://twitter.com/hashtag/improvesoftware
  • #5: How? Duplication Excess Coupling Quick Fixes Hacks
  • #6: Over time, neglect can turn software from well-oiled machinery into heaps of useless junk.
  • #7: Typically the low quality code was left because of the need to meet deadlines, but once in place, the justification for having put it there no longer matters. Whenever you are forced to work around the hacks, bad code, etc, in your application, the decrease in your productivity represents interest on technical debt. If you spend time refactoring the code to improve its quality, you are paying down the principal of the technical debt (and thus reducing future interest costs).
  • #10: Should we spend an iteration or a month just trying to improve the quality of the system, and pay down technical debt? What would you think if you went to your favorite restaurant, only to find that it was closed for a month, with a sign explaining that it needed to clean up things that had gotten out of hand due to neglect. Would you feel as confident about eating the product of that kitchen, knowing it had let things go so wrong that it now needed a month without producing food just to clean up the mess it had created. How do you think our customers should feel if we request time to clean up our code instead of fixing bugs or delivering new features?
  • #13: By definition, refactoring attempts to improve the quality of a software application without changing its behavior. If you’re changing behavior, you’re not refactoring, you’re fixing a bug or adding a feature (hopefully – or adding a bug).
  • #14: Only refactor code while your tests are passing. Make sure they still pass when you are done. Break large refactorings into small steps and test after each step.
  • #15: Note that characterization tests, though they should be automated, are often not what we would think of as unit tests, or perhaps even integration tests. For instance, you could dump a log file showing the relevant state of the application, and then use that as the basis for your characterization test by comparing against it after your changes.
  • #16: Avoid creating a big ball of mud system, where tracing through your code and its dependencies is like trying to unwind a tangled mess of spaghetti.
  • #17: Water break
  • #19: Principles provide guidance for refactoring. They provide a consistent target to aim toward.
  • #24: A very common source of repetition of code is role checks. These often describe different scenarios in different circumstances. For instance, maybe administrators can do anything, but managers can access resources within their division, etc. Encapsulating the logic of CanView, CanCreate, CanEdit, etc. in privilege objects makes these rules explicit, easier to test, and gives them a single location to live in the application.
  • #32: Visual Studio can quickly analyze a project and show statistics for the classes and methods in the project. The maintainability index, cyclomatic complexity, and lines of code are all great metrics to pay attention to. The ideal maintainability index is 100, but don’t expect to hit that with any code that’s doing real work. However, you should certainly able to keep it above 50. Demo GildedRose.
  • #34: Using Excel
  • #35: I’m not a fan of regions. They mainly exist because at one time they were a reasonable means of hiding generated code, before we had support for partial classes and other language features to deal with this. The worst offense with regions is when they’re used within a method, like this: (click) They’re also bad when used at the class level for “standard” formatting of code, making it impossible to actually see what the code does, like this: (click) Can someone tell me what this class does? (click) I have a whole article devoted to why using regions is a bad habit, anti-pattern, code smell, whatever you prefer. It includes some survey results on the most common ways people use them as well. (click)
  • #36: Open-Closed Principle
  • #38: Software can only be open to extension in a few different axes, and each additional bit of flexibility adds complexity to the software. Thus, this flexibility should be added only when needed, not simply anticipated.
  • #42: What happens when we need to add another country? What happens when we must add another rule? How can we refactor this so this method no longer needs to change?
  • #43: Define a type to describe a rule. Move each rule into its own type. Create a collection of rules to apply and apply them. Pass the set of rules into the IsSpecialCustomer() method’s class (or even the method itself).
  • #47: Any time you find that you need to check the type of an object within a polymorphic block of code (such as a foreach), this is a sign that you are breaking LSP.
  • #49: Nulls break polymorphism and violate LSP just as much as other subtypes that aren’t substitutable! Try to avoid the possibility of dealing with nulls in polymorphic code like foreach loops – consider using Null Object Pattern to address.
  • #55: This is an extemely common example of the Repository design pattern. In fact, I use this exact pattern in quite a few production applications today. There’s nothing inherently wrong with this implementation on its own. However, sometimes it does violate ISP if you need to separate Commands from Queries
  • #56: You can create small interfaces and compose the larger interfaces from the smaller ones if you control all of the code and you can’t simply do away with the larger interfaces. In this case, the separation of interfaces would allow us to do something like implement caching only on the read operations, and implement delayed writes using some kind of queue or message bus for the write operations.
  • #60: “Legacy” N-Tier Logical Architecture
  • #67: Hidden Dependencies
  • #70: Extract interface Implement interface with tightly coupled original code
  • #71: Mention Explicit Dependencies Principle
  • #73: Get them excited.