improving the quality of existing software - devintersection april 2016

Post on 15-Jan-2017

767 Views

Category:

Software

1 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Improving the Quality of Existing Software

Steve SmithArdalis Services

@ardalis | ardalis.com

Tweet Away

• Live Tweeting 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

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

• Automated Tests• 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.

Refactoring Should Not Change System Behavior

The Refactoring Process

• Verify existing behavior• Write Characterization Tests if none exist• Find test points• Break dependencies

• Apply Refactoring• Confirm existing behavior is preserved

Characterization Tests

Process1. Write a test you know will fail2. Use the output of the failing test to determine the existing

behavior to assert3. Update the test with the new value/behavior4. Run the test again – it should now pass

S O L I D

Principleshttp://flickr.com/photos/kevinkemmerer/

2772526725/

Principles of OO Design

0. Don’t Repeat Yourself (DRY)

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

Don’t RepeatRepeat Yourself

• 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 in VS2015 Premium and Ultimate

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

Code Smell: Regions

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

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

Common Refactorings

• Extract Interface / Apply Strategy Pattern• Parameterize Method• Form Template Method

OCP Fail

OCP OK

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

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

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!

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 Flow Toward 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 UIASP.NET Data Source ControlsClassic ASP scripts

Data access logic in UI layer via codebehindASP.NET Page_Load eventASP.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 implementationsWhat should we call such

interfaces? Repositories!

User Interface

Database

Compile Time

Runtime

CoreIFooRepository

InfrastructureSqlFooRepository

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?

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

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

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•Be Explicit About Class Dependencies• Train and Practice to Write Better Code

Faster

Learn More• DevIQ.com – Take Pride in Your Code• Ardalis.com• @ardalis• Pluralsight:• SOLID Principles of OO Design• N-Tier Architecture 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!

top related