improving the quality of existing software

67
Improving the Quality of Existing Software Steve Smith Telerik ardalis.com @ardalis

Upload: steven-smith

Post on 10-May-2015

1.829 views

Category:

Technology


1 download

DESCRIPTION

Presented at DevReach 2013. As developers, most of our time is spent working on existing software. Sure, occasionally we get the chance to fire up a new Solution in Visual Studio, and that can be exciting. But after the first day, we find ourselves once more having to deal with the work we did yesterday. And today, we know more than we did yesterday, so there are things we’d do differently, if we had it to do over. Over time, software rots. If we’re not diligent, our beautiful code can degrade into a worthless mess. Keeping our code in working condition is no different than changing the oil in our car – it’s preventive maintenance. In this session, Steve will look at some common places to look for signs of degradation in existing applications, and steps to take to improve the code. Examples will use C# and primarily ASP.NET.

TRANSCRIPT

Page 1: Improving The Quality of Existing Software

Improving the Quality of Existing Software

Steve SmithTelerikardalis.com @ardalis

Page 2: Improving The Quality of Existing Software

Software Rots

Page 3: Improving The Quality of Existing Software
Page 4: Improving The Quality of Existing Software

Technical Debt

• Low quality code and shortcuts in our applications

• Technical debt, like real debt, has direct cost and interest

Page 5: Improving The Quality of Existing Software

http://www.jimhighsmith.com/

Page 6: Improving The Quality of Existing Software

Preventive Maintenance

• Refactoring– Eliminate Duplication– Simplify Design

• Automated Tests– Verify correctness– Avoid regressions– Increase Confidence

Page 7: Improving The Quality of Existing Software

When should you refactor?

• While delivering value

Page 8: Improving The Quality of Existing Software
Page 9: Improving The Quality of Existing Software

Refactoring Should Not Change System Behavior

Page 10: Improving The Quality of Existing Software

Refactoring Process

• Verify existing behavior• Write Characterization Tests if none

exist– Find test points– Break dependencies

• Apply Refactoring• Confirm existing behavior is

preserved

Page 11: Improving The Quality of Existing Software

Characterization Tests

Process1. Write a test you know will fail2. 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 pass

Page 12: Improving The Quality of Existing Software
Page 13: Improving The Quality of Existing Software
Page 14: Improving The Quality of Existing Software

S O L I DPrinciples

http://flickr.com/photos/kevinkemmerer/2772526725/

Page 15: Improving The Quality of Existing Software

Principles of OO Design

0. Don’t Repeat Yourself (DRY)

1.Single Responsibility2.Open/Closed3.Liskov Substitution4.Interface Segregation5.Dependency Inversion

Page 16: Improving The Quality of Existing Software
Page 17: Improving The Quality of Existing Software

Don’t RepeatRepeat Yourself

• Duplication in logic calls for abstraction

• Duplication in process calls for automation

Page 18: Improving The Quality of Existing Software

Common Refactorings

• Replace Magic Number/String• Parameterize Method• Pull Up Field• Pull Up Method• Replace Conditional With

Polymorphism• Introduce Method

Page 19: Improving The Quality of Existing Software

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}

Page 20: Improving The Quality of Existing Software
Page 21: Improving The Quality of Existing Software

Single Responsibility PrincipleThe 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

Page 22: Improving The Quality of Existing Software

Example Responsibilities

• Persistence• Validation• Notification• Error Handling• Logging• Class Selection / Construction• Formatting• Parsing• Mapping

Page 23: Improving The Quality of Existing Software

Dependency and Coupling

• Excessive coupling makes changing legacy software difficult

• Breaking apart responsibilities and dependencies is a large part of working with existing code

Page 24: Improving The Quality of Existing Software

Common Refactorings

• Extract Class• Extract Method• Move Method

Page 25: Improving The Quality of Existing Software

Heuristics and Code Smells

• Visual Studio Metrics

Page 26: Improving The Quality of Existing Software

Code Smell: Regions

?More on Regions: http://ardalis.com/regional-differences

Page 27: Improving The Quality of Existing Software
Page 28: Improving The Quality of Existing Software

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

Page 29: Improving The Quality of Existing Software

Open / Closed Principle

Open to ExtensionNew behavior can be added in the future

Closed to ModificationChanges to source or binary code are not required

Dr. Bertrand Meyer originated the OCP term in his 1988 book, Object Oriented Software Construction

Page 30: Improving The Quality of Existing Software

Common Refactorings

• Extract Interface / Apply Strategy Pattern

• Parameterize Method• Form Template Method

Page 31: Improving The Quality of Existing Software

OCP Fail

Page 32: Improving The Quality of Existing Software

OCP OK

Page 33: Improving The Quality of Existing Software

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;}

Page 34: Improving The Quality of Existing Software

OCP OK

private IEnumerable<ICustomerRule> _rules;

public bool IsSpecialCustomer(Customer c){ foreach(var rule in _rules) { if(rule.Evaluate(c) == false) return false; } return true;}

Page 35: Improving The Quality of Existing Software
Page 36: Improving The Quality of Existing Software

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.

Page 37: Improving The Quality of Existing Software

Common Refactorings

• Collapse Hierarchy• Pull Up / Push Down Field• Pull Up / Push Down Method

Page 38: Improving The Quality of Existing Software

Liskov Substitution Fail

foreach(var employee in employees){ if(employee is Manager) { Helpers.PrintManager(employee as Manager); break; } Helpers.PrintEmployee(employee);}

Page 39: Improving The Quality of Existing Software

Liskov Substitution OK

foreach(var employee in employees){ employee.Print(); // or Helpers.PrintEmployee(employee);}

Page 40: Improving The Quality of Existing Software
Page 41: Improving The Quality of Existing Software

Interface Segregation PrincipleThe 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

Page 42: Improving The Quality of Existing Software

Common Refactorings

• Extract Interface

Page 43: Improving The Quality of Existing Software

Keep Interfaces Small and Focused

Page 44: Improving The Quality of Existing Software

Membership Provider

Page 45: Improving The Quality of Existing Software

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);}

Page 46: Improving The Quality of Existing Software

ISP OK (for CQRS for example)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);}

Page 47: Improving The Quality of Existing Software
Page 48: Improving The Quality of Existing Software

Dependency Inversion PrincipleHigh-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#

Page 49: Improving The Quality of Existing Software

Dependency Inversion Principle• Depend on Abstractions– Interfaces, not concrete types

• Inject Dependencies into Classes

• Structure Solution so Dependencies Flow Toward Core– Onion Architecture (a.k.a. Ports and

Adapters)

Page 50: Improving The Quality of Existing Software

Application Layers

Page 51: Improving The Quality of Existing Software

Data Access EvolutionNo 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

Page 52: Improving The Quality of Existing Software

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

Page 53: Improving The Quality of Existing Software

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

CoreIFooRepository

InfrastructureSqlFooRepository

Page 54: Improving The Quality of Existing Software

DIP Architecture (aka Ports and Adapters)

Page 55: Improving The Quality of Existing Software

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

Page 56: Improving The Quality of Existing Software

Common Refactorings

• Extract Class• Extract Interface / Apply Strategy

Pattern• Extract Method• Introduce Service Locator / Container

Page 57: Improving The Quality of Existing Software

DIP Fail

Page 58: Improving The Quality of Existing Software

Some Improvement (Façade)

Page 59: Improving The Quality of Existing Software

DIP OK (Strategy)

Page 60: Improving The Quality of Existing Software

DIP OK (Strategy)

Page 61: Improving The Quality of Existing Software

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?

Page 62: Improving The Quality of Existing Software

Week 1 Week 2 Week 3 Week 4 Week 5 Week 6 Week 7 Week 8 Week 90

2

4

6

8

10

12

14

16

User Stories Completed

High Quality Low Quality Column1

Page 63: Improving The Quality of Existing Software

Week 1 Week 2 Week 3 Week 4 Week 5 Week 6 Week 7 Week 8 Week 90

2

4

6

8

10

12

14

16

18

20

User Stories Completed

High Quality Low Quality Column1

Page 64: Improving The Quality of Existing Software

Summary

• Maintain / Improve Application Code• Follow DRY/SOLID Principles• Use Characterization Tests to “fix”

behavior• Apply Common Refactorings• Re-run Tests After (and during)

Refactorings• Train and Practice to Write Better

Code Faster

Page 65: Improving The Quality of Existing Software

References

http://bit.ly/SFkpmq

Refactoring Catalog http://www.refactoring.com/catalog/index.html

Onion Architecture http://jeffreypalermo.com/blog/the-onion-architecture-pa

rt-1/

Page 66: Improving The Quality of Existing Software

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

Page 67: Improving The Quality of Existing Software

Thank you!

@ardalis

ardalis.com

http://facebook.com/stevenandrewsmith