12 toward solid code

39
Moving toward SOLID code

Upload: rap-payne

Post on 10-May-2015

283 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: 12 toward solid code

Moving toward SOLID code

Page 2: 12 toward solid code

Refactoring is changing the internal implementation to make it more maintainable

�  If the user sees a change, it isn't refactoring

Page 3: 12 toward solid code

Agile projects advocate refactoring mercilessly

Page 4: 12 toward solid code

YAGNI You Aren't Going to Need It

Page 5: 12 toward solid code

SOLID Principles

Single Responsibility Principle Open Closed Principle Liskov Substitution Principle Interface Segregation Principle Dependency Inversion Principle

Page 6: 12 toward solid code

� asdf

Page 7: 12 toward solid code

Single Responsibility Principle “If a class has more then one responsibility, then the responsibilities become coupled. Changes to one responsibility may impair or inhibit the class’ ability to meet the others. This kind of coupling leads to fragile designs that break in unexpected ways when changed.”

- Robert C. Martin

Page 8: 12 toward solid code

Single Responsibility Principle � A class should have one and only one

reason to change � Maybe we should call it the Single

Change Reason Principle

Page 9: 12 toward solid code

Problem: We have a user interface that reads from/writes to the database. This is not cohesive

UI

Page 10: 12 toward solid code

Goal: To get the business logic out of the UI. Let the UI do what it does exclusively

Business Logic

UI

Page 11: 12 toward solid code

Problem: DB logic In the UI code public void Click(object o, EventArgs e) { var name = txtName.Text; var phone = txtPhone.Text; var db = new SqlConnection(); db.Open(); var sql ="insert into ... name ..."; var cmd = new SqlCommand(sql, db); cmd.ExecuteNonQuery(); }

Page 12: 12 toward solid code

Solution: Create a Person class public class Person { public string Name { get; set; } public string Phone { get; set; } public void Save() { //Write to database here //Connection, Command, ExecuteNonQuery } public Person Read(int Id) { //Read from database here //Connection, Command, ExecuteNonQuery } }

Page 13: 12 toward solid code

Problem: We still have db logic in the business logic

Business Logic

UI

Page 14: 12 toward solid code

Business Logic

Infrastructure

UI

Solution: Create a DB layer

Page 15: 12 toward solid code

Create a repository class Public class PersonRepository { public void Save(Person) { //Write to database here } public Person Read(int Id){ //Read from database here return thePerson; } }

Page 16: 12 toward solid code

New class w/o DB logic public class Person { public string Name { get; set; } public string Phone { get; set; } public void Save() { var r = new PersonRepository(); r.Save(this); } public Person Read(int Id) { var r = new PersonRepository(); return r.Read(Id); } }

Page 17: 12 toward solid code

� asdf

Page 18: 12 toward solid code

Open-Closed Principle Modules that conform to the open-closed principle have two primary attributes. 1.  They are “Open For Extension”.

This means that the behavior of the module can be extended. That we can make the module behave in new and different ways as the requirements of the application change, or to meet the needs of new applications.

2.  They are “Closed for Modification”. The source code of such a module is inviolate. No one is allowed to make source code changes to it.

- Robert C. Martin

Page 19: 12 toward solid code

Open-Closed Principle � Classes should be open for extension but

closed for modification � To properly change behavior, you should

inherit from it and add or override functionality in the child class

Page 20: 12 toward solid code

Examples � Physical world

�  Ryobi lawn tool

�  In the Matrix �  Visual inheritance in WinForms or WebForms �  Custom exceptions

Page 21: 12 toward solid code

�  sdfsd

Page 22: 12 toward solid code

Liskov Substitution Principle “If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.”

- Barbara Liskov “Functions that use pointers or references to base classes must be able to use objects of derived classes without knowing it.”

-Robert Martin

Page 23: 12 toward solid code

Liskov Substitution Principle in real-people words. � Any object must be semantically similar to

everything above it in the inheritance tree � No matter how poorly named they are � Semantically substituted, not syntactically

substituted

Page 24: 12 toward solid code

Example: Bike & Motorcycle public interface IBicycle !{! int speed;! void Brake();! void Accelerate();!}!public class Motorcycle : IBicycle!{! public Motor Engine { get; set; }!}!

Page 25: 12 toward solid code

�  sadf

Page 26: 12 toward solid code

Interface Segregation Principle “This principle deals with the disadvantages of ‘fat’ interfaces. Classes that have ‘fat’ interfaces are classes whose interfaces are not cohesive. In other words, the interfaces of the class can be broken up into groups of member functions. Each group serves a different set of clients. Thus some clients use one group of member functions, and other clients use the other groups.”

- Robert Martin

Page 27: 12 toward solid code

Interface Segregation Principle � An implementing class should not be

forced to depend on an interface that it doesn’t need

� Split fat interfaces up � Very much like SRP

Page 28: 12 toward solid code

Example: All-in-one printer

28

Page 29: 12 toward solid code

�  sadf

Page 30: 12 toward solid code

Dependency Inversion Principle “What is it that makes a design rigid, fragile and immobile? It is the interdependence of the modules within that design. A design is rigid if it cannot be easily changed. Such rigidity is due to the fact that a single change to heavily interdependent software begins a cascade of changes in dependent modules.”

- Robert Martin

Page 31: 12 toward solid code

Dependency Inversion Principle � Depend on interfaces, not concrete

implementations

Page 32: 12 toward solid code

Example Problem: The business classes are worthless without the DB logic. They're too tightly coupled.

Business Logic

Infrastructure

UI

Person Repository

Person

Page 33: 12 toward solid code

� Goal: Have a business object that maintains its state in the database

Business Logic

Infrastructure

UI

IPerson Repository

Person Repository

Person

Page 34: 12 toward solid code

Step 1: Create an interface public interface IPersonRepository { public void Save(); public Person Read(int Id); } public class PersonRepository : IPersonRepository { //Same concrete implementations }

Page 35: 12 toward solid code

Step 2: Using the interface public class Person { public string Name { get; set; } public string Phone { get; set; } public void Save() { IPersonRepository r = new PersonRepository(); r.Save(this); } public Person Read(int Id) { IPersonRepository r = new PersonRepository(); return r.Read(Id); } }

Page 36: 12 toward solid code

Step 3: Pass an IPersonRepository into the constructor public class Person { private IPersonRepository ipr; public string Name { get; set; } public string Phone { get; set; } public Person(IPersonRepository PersonRepo) { ipr = PersonRepo; } public void Save() { ipr.Save(this); } public Person Read(int Id) { return ipr.Read(Id); } }

Page 37: 12 toward solid code

Business Logic

Infrastructure

UI

Person Repository

Person

Step 4: Move the IPersonRepository to the Person Business Logic project

IPerson Repository

Page 38: 12 toward solid code

�  sdfgd

Page 39: 12 toward solid code

Summary �  We can't write perfect code and we shouldn't try �  It helps us to write faster if we use good design

patterns and know we'll be back later to refactor the code

�  We should use the SOLID design patterns to make more maintainable code �  S - Each class should do one only one thing �  O - Classes can be inherited, but not changed �  L - Design to Interfaces, not classes �  I - Classes shouldn't rely on things they don't use �  D - Code should depend on interfaces, not classes