Download - Refactoring with SOLID Principles (FalafelCon 2013)

Transcript
Page 1: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

Refactoring Applicationsusing SOLID Principles

Steve SmithTelerik

ardalis.com @ardalis

Page 2: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

More on this topic

Coming Soon: Refactoring Fundamentals

Page 3: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

Software Rots

How? Duplication Excess Coupling Quick Fixes Hacks

Page 4: Refactoring with SOLID Principles (FalafelCon 2013)
Page 5: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

Preventive Maintenance

• Refactoring– Eliminate Duplication– Simplify Design

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

Page 6: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

Refactoring Process

• Verify existing behavior• Write Characterization Tests if none

exist– Find test points– Break dependencies

• Apply Refactoring• Confirm existing behavior is

preserved

Page 7: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

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 8: Refactoring with SOLID Principles (FalafelCon 2013)
Page 9: Refactoring with SOLID Principles (FalafelCon 2013)
Page 10: Refactoring with SOLID Principles (FalafelCon 2013)

S O L I DPrinciples

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

Page 11: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

Principles of OO Design

0. Don’t Repeat Yourself (DRY)

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

Page 12: Refactoring with SOLID Principles (FalafelCon 2013)
Page 13: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

Don’t RepeatRepeat Yourself

• Duplication in logic calls for abstraction

• Duplication in process calls for automation

Page 14: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

Common Refactorings

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

Polymorphism• Introduce Method

Page 15: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

Role Checksif(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 16: Refactoring with SOLID Principles (FalafelCon 2013)
Page 17: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

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 18: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

Example Responsibilities

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

Page 19: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

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 20: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

Common Refactorings

• Extract Class• Move Method

Page 21: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

Heuristics and Code Smells

• Visual Studio Metrics

Page 22: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

Code Smell: Regions

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

Page 23: Refactoring with SOLID Principles (FalafelCon 2013)
Page 24: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

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 25: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

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 26: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

Common Refactorings

• Extract Interface / Apply Strategy Pattern

• Parameterize Method• Form Template Method

Page 27: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

OCP Fail

Page 28: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

OCP OK

Page 29: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

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

Page 30: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

OCP OKprivate IEnumerable<ICustomerRule> _rules;

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

Page 31: Refactoring with SOLID Principles (FalafelCon 2013)
Page 32: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

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 33: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

Common Refactorings

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

Page 34: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

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

Page 35: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

Liskov Substitution OKforeach(var employee in employees){ employee.Print(); // or Helpers.PrintEmployee(employee);}

Page 36: Refactoring with SOLID Principles (FalafelCon 2013)
Page 37: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

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 38: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

Common Refactorings

• Extract Interface

Page 39: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

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 40: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

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 41: Refactoring with SOLID Principles (FalafelCon 2013)
Page 42: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

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 43: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

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

• Inject Dependencies into Classes

• Structure Solution so Dependencies Flow Toward Core– Onion Architecture

Page 44: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

Application Layers

Page 45: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

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 46: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

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 47: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

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 48: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

DIP “Onion” Architecture

Page 49: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

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 50: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

Common Refactorings

• Extract Class• Extract Interface / Apply Strategy

Pattern• Extract Method• Introduce Service Locator / Container

Page 51: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

DIP Fail

Page 52: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

Some Improvement (Façade)

Page 53: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

DIP OK (Strategy)

Page 54: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

DIP OK (Strategy)

Page 55: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

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

Page 56: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

References

Principles of Object Oriented Design (Pluralsight) 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 57: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

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 58: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

Thank You!

Find Me Online:Blog: http://ardalis.comTwitter: @ardalishttp://facebook.com/StevenAndrewSmith

Page 59: Refactoring with SOLID Principles (FalafelCon 2013)

Follow me at twitter.com/ardalis

Discussion