12 toward solid code

Post on 10-May-2015

283 views 0 download

Tags:

Transcript of 12 toward solid code

Moving toward SOLID code

Refactoring is changing the internal implementation to make it more maintainable

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

Agile projects advocate refactoring mercilessly

YAGNI You Aren't Going to Need It

SOLID Principles

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

� asdf

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

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

reason to change � Maybe we should call it the Single

Change Reason Principle

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

UI

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

Business Logic

UI

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

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

Problem: We still have db logic in the business logic

Business Logic

UI

Business Logic

Infrastructure

UI

Solution: Create a DB layer

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

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

� asdf

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

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

Examples � Physical world

�  Ryobi lawn tool

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

�  sdfsd

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

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

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

�  sadf

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

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

Example: All-in-one printer

28

�  sadf

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

Dependency Inversion Principle � Depend on interfaces, not concrete

implementations

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

Business Logic

Infrastructure

UI

Person Repository

Person

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

Business Logic

Infrastructure

UI

IPerson Repository

Person Repository

Person

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

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

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

Business Logic

Infrastructure

UI

Person Repository

Person

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

IPerson Repository

�  sdfgd

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