350 likes | 563 Views
Principles of Object Oriented Design. - John Teague & Mahendra Mavani. High Cohesion Low Coupling. Old Standards for Object Oriented Programming. Problems Solved. Maintainability Easier to Test Less Resistance to Change Fear to Change Code Leads to Old Stinky Code
E N D
Principles of Object Oriented Design - John Teague & MahendraMavani
High CohesionLow Coupling Old Standards for Object Oriented Programming
Problems Solved • Maintainability • Easier to Test • Less Resistance to Change • Fear to Change Code Leads to Old Stinky Code • Reduces Repetition (DRY) • Don’t Cut and Paste!!!! • Allows For Continuous Improvement • Essential for Agile Development
Topics To Discuss • Single Responsibility Principle • Dependency Inversion Principle • Open Closed Principle • Interface Segregation Principle • Law of Demeter • Liskov Substitution Principle
Single Responsibility Principle What is Responsibility? • Reason for change • Find how many reason you can think of for you class/method to change • If more than one, then your design violates SRP
Single Responsibility Principle Requirement : Send monthly account statement to the customer <demo>
Single Responsibility Principle Problem:- • we have more than one responsibility • reading transaction record • Formatting • Sending Email • Different user may want different email format • IT Dept. may decide to change how data is stored • Bank might want to start using third party email sending utility.
Single Responsibility Principle • Refactor • public class TransactionRepository {…. } • public class HTMLMailFormater {….} • public class EmailService {…….. } • Demo
Dependency Inversion • Depend upon abstraction • High level module should not depend upon low level module implementation, rather depend upon abstraction • Template pattern
Dependency Inversion • Naïve Example Demo
Dependency Inversion Problem:- • All the client must use text file to store transaction • Sends email in HTML format only • Code in BankAccount class, doesn’t depend upon storage but still can’t be tested in isolation.
Open Closed Principle • Classes should be Open to Extensibility and Closed to Modifications • To Change behavior, you want to add new code instead of modifying existing Code. • May not have access to code
Why Keep Code Closed To Modifications • Changing Existing Code is Risky. • Can be Time Consuming in a Non-Refactored code base.
Code Not Designed on OCP private string SetDefaultEditableText() { StringBuilder editableText = new StringBuilder(); switch ( SurveyManager.CurrentSurvey.TypeID ) { case 1: editableText.Append("<p>Text for Survey Type 2 Goes Here</p>"); case 2: editableText.Append("<p>Text for Survey Type 2 Goes Here</p>"); case 3: default: editableText.Append("<p>Text for Survey Type 3 Goes Here</p>"); } return editableText.ToString(); }
Desigined For Extensibility Strategy Pattern (Composition focused) interface ISurveyEmailFormatter{ string GetDefaultEditableText(); } public SurveyType1EmailFormatter : ISurveyEmailFormatter{ public string GetDefaultEditableText(){ return "<p>Text for Survey Type 1 Goes Here</p>"; } } public SurveyType2EmailFormatter : ISurveyEmailFormatter{ public string GetDefaultEditableText(){ return "<p>Text for Survey Type 2 Goes Here</p>"; } } public SurveyType3EmailFormatter : ISurveyEmailFormatter{ public string GetDefaultEditableText(){ return "<p>Text for Survey Type 3 Goes Here</p>"; } }
Strategy Pattern Cont’d public class Survey{ IEmailFormatter _emailFormatter; public Survey(IEmailFormmater emailFormater){ _emailFormatter = emailFormatter; } public string GetEmailDefaultText(){ return _emailFormatter.GetDefaultEditableText(); } }
Designed for ExtensibilityTemplate Pattern (Inheritance) public abstract Survey{ protected abstract string GetDefaultEditableText(); public string GetEmailText() { … string defaultText = GetDefaultEditableText(); … return somthingHere; } } public SurveyType1{ protected string GetDefaultEditableText() { return "<p>Text for Survey Type 1 Goes Here</p>"; } }
Extensibility Only Goes So far • Change is going to occur and you can’t keep everything from changing • Must use judgment on which parts of your application are more likely to change and focus extensibility there.
Law of Demeter • Don’t Talk To Strangers • Methods Should Only Talk To: • Methods and fields on the Object • Parameters passed into the method • Objects Created within the method • Only one “dot” • foo.bar.baz (bad)
Demeter • Breaking this principle breaks encapsulation, and tightens coupling. • Refactoring much more difficult • Test Setup becomes much more difficult
Demeter public class Wallet { double Cash{get;set;} } public class Customer { Wallet Wallet{get;set;} } public class Paperboy { public double AmountCollected{get;set} public void CollectMoney(Customer customer, double amount){ if(customer.Wallet.Cash < amount) throw new InsufficientFundsException(); customer.Wallet.Cash -= amount; AmountCollected += customer.Wallet.Cash; } }
Demeter • The fix: public class Wallet { double Cash{get;set;} public double Withdraw(double amount){ if(Cash < amount) throw new InsufficientFundsException(); Cash -= amount; return amount; } } public class Customer { Wallet Wallet{get;set;} public double Pay(double amount) { Wallet.Withdraw(amount); } } public class Paperboy { public double AmountCollected{get;set} public void CollectMoney(Customer customer, double amount) { AmountCollected += customer.Pay(amount); } } http://www.ccs.neu.edu/research/demeter/demeter-method/LawOfDemeter/paper-boy/demeter.pdf
Interface Segregation Princple • Clients shouldn't be forced to implement interfaces they don't use
Interface Segregation Princple • Example of FAT or Polluted Interface • Try implementing custom Membership Provider in ASP.NET 2.0. • You just need to implement 27 methods/properties
Interface Segregation Princple Interface Idoor { void Lock(); void UnLock(); bool IsOpen(); } Public Class Door : Idoor { public void Lock() {} public void UnLock(){} bool IsOpen(){} } <Demo>
Interface Segregation Princple • Consider one implementation as security door which need to ring alarm if door is kept open for longer duration. Interface Idoor { void Lock(); void UnLock(); bool IsOpen(); void Timeout(); } public class SecurityDoor : Idoor { void Lock() {} void UnLock() {} bool IsOpen() {} void Timeout() {} } <Demo>
Interface Segregation Princple Problem • All type of door are not timed • By adding Timeout into IDoor we are polluting our interface
Interface Segregation Princple public interface ITimerClient { void TimeOut(); } public class SecurityDoor : IDoor, ITimerClient { public void TimeOut() {…….} }
Liskov Substitution Principle • All sub-classes must be substitutable for their base class.
Liskov violation • Structural • You should not have to explicitly cast a base object to it’s subclass to do something. • Behavior • Subtypes should behave in a consistent manner in terms of their clients
Liskov Example public class LinkedList { public void copyInto(LinkedListdest) { dest.clear(); int n = getLength(); for(inti = 0; i < n; ++i){ dest.addElement(getElementAt(i)); } } } public class Set : LinkedList { ... /** * Adds element to this set, provided * element is not already in the set */ public void addElement(Object element) { if(!hasElement(element)) { super.addElement(element); } } }
Liskov • Behavior of CopyInto will not always be consistent • Set To Set is okay • LinkedList to LinkedList is okay • Set to LinkedList is okay • LinkedList to Set behaves differently • Linked List with {1, 2, 3, 2, 1} becomes {1, 2, 3} http://doodleproject.sourceforge.net/articles/2000/liskovSubstitutionPrinciple.html
Bottom line … • SRP • Only one reason to change • DIP • “Don’t call me, I’ll call you” • OCP • Open for extension, Closed for modification • LSP • Sub types should be substitutable for their bases types • LoD • “Don’t talk to strangers” • ISP • Clients should not be forced to depend on methods they do not use
Remember… Always code as if the guy maintaining your code would be a violent psychopath and he knows where you live.
References • Uncle Bob’s blog • http://butunclebob.com/ArticleS.UncleBob.PrinciplesOfOod • Los Techies Topic of the Month • http://www.lostechies.com/blogs/chad_myers/archive/2008/03/07/pablo-s-topic-of-the-month-march-solid-principles.aspx