Clipcode Snippets for C# Refactoring

// Refactoring is the process of improving code after it has been
// written, with the goal of achieving a better design.
//
// The seminal work in this area is:
// "Refactoring: Improving the Design of Existing Code",
// by Martin Fowler, ISBN: 0-201-48567-2, published by Addison-Wesley.
//
// Fowler's book includes examples of refactoring in Java. Clipcode
// Snippets For Refactoring below complements Fowler's book by
// providing examples of the same refactorings in C#. We have quoted
// the brief problem/solution statement from each of Fowler's
// refactorings, along with the page number in his book where you will
// find his detailed discussion of the motiviation and mechanics of
// each type of refactoring. While reading the C# examples below,
// we recommend having Fowler's book open beside you and learning
// about the background to each refactoring.

Composing Methods
Moving Features Between Objects
Organizing Data
Simplifying Conditional Expressions
Making Method Calls Simpler
Dealing with Generalization
Big Refactorings

Composing Methods

Extract Method (page 110)
Inline Method (page 117)
Inline Temp (page 119)
Replace Temp with Query (page 120)
Introduce Explaining Variable (page 124)
Split Temporary Variable (page 128)
Remove Assignment to Parameters (page 131)
Replace Method with Method Object (page 135)
Substitute Algorithm (page 139)

Extract Method (page 110)

		// "Problem: You have a code fragment that can be grouped together. 
		// Solution: Turn the fragment into a method whose name explains the purpose of the method."
		Int32 ProductListPrice = 10;
		Int32 TaxRate = 10;
		Int32 ShippingPrice = 20;
		// BEFORE
		// ------
		void GenerateQuote(Customer customerX)
		{
			if (!CanWeExportToThisCountry(customerX.Country))
				// handle failed export licensing issue
				// ...
				return;		
			// Calculate price
			Int32 price = ProductListPrice - AvailableDiscount(customerX.Category);
			price += TaxRate * price;
			price += ShippingPrice; 
			MakeQuote(customerX, price);		
		}
		void MakeQuote(Customer x, Int32 p){}
		Boolean CanWeExportToThisCountry(String c){return true;}
		Int32 AvailableDiscount(Int32 c) { return 4;}
		// AFTER
		// -----
		void GenerateQuote2(Customer customerX)
		{
			if (!CanWeExportToThisCountry(customerX.Country))
				// handle failed export licensing issue
				// ...
				return;		
			Int32 fullPrice = CalculatePrice(customerX);
			MakeQuote(customerX, fullPrice);		
		}
		Int32 CalculatePrice(Customer customerX)
		{
			Int32 price = ProductListPrice - AvailableDiscount(customerX.Category);
			price += TaxRate * price;
			price += ShippingPrice; 
			return price;
		}

Inline Method (page 117)

		// "Problem: A method's body is just as clear as its name.
		// Solution: Put the method's body into the body of its callers and remove the method."
		// BEFORE
		// ------
		void DisplayBookPopularity()
		{
			DumpSalesCount();
		}
		void DumpSalesCount()
		{
			Console.WriteLine("This month's sales = " + volume);
		}
		// AFTER
		// -----
		void DisplayBookPopularity2()
		{
			Console.WriteLine("This month's sales = " + volume);
		}

Inline Temp (page 119)

		// "Problem: You have a temp that is assigned to once with a simple expression, and 
		// the temp is getting in the way of other refactorings. 
		// Solution; Replace all references to that temp with the expression."
		// BEFORE
		// ------
		void ShowFees()
		{
			Int32 x = CalculateOutstandingFees();
			Console.WriteLine("Outstanding Fees = " + x);
		}
		// AFTER
		// -----
		void ShowFees2()
		{
			Console.WriteLine("Outstanding Fees = " + CalculateOutstandingFees());
		}

Replace Temp with Query (page 120)

		// "Problem: You are using a temporary variable to hold the result of an expression. 
		// Solution: Extract the expression into a method. Replace all references to the temp with the expression. 
		// The new method can then be used in other methods. "
		// BEFORE
		// ------
		void ChargeInterest()
		{
			Int32 interestDue = loanAmount * interestRate;
			BankBalance -= interestDue;
		}
		void GenerateReport()
		{
			Int32 interestDue = loanAmount * interestRate;
			Console.WriteLine("Interest This month = " + interestDue);
		}
		
		// AFTER
		// -----
		Int32 CalcInterest()
		{
			return loanAmount * interestRate;
		}
		void ChargeInterest2()
		{
			BankBalance -= CalcInterest();
		}
		void GenerateReport2()
		{
			Console.WriteLine("Interest This month = " + CalcInterest());
		}
		

Introduce Explaining Variable (page 124)

		// "Problem: You have a complicated expression. 
		// Solution: Put the result of the expression, or parts of the expression, in a temporary variable with a 
		// name that explains the purpose."
		
		// BEFORE
		// ------
		void AtmProcessWithdrawal()
		{
			if ((Card.GetCard(Machine.CurrentReading).Validate()) &&
				(Card.GetCard(Machine.CurrentReading).CheckPin(Machine.EnteredPin)) &&
				(Account.Check()))
			{
				// allow withdrawal
				// ...
			}
		}
		// AFTER
		// -----
		void AtmProcessWithdrawal2()
		{
			Boolean IsCardValid = Card.GetCard(Machine.CurrentReading).Validate();
			Boolean IsPinCodeRecognised = Card.GetCard(Machine.CurrentReading).CheckPin(Machine.EnteredPin);
			Boolean IsAccountInCredit = Account.Check();
			if (IsCardValid && IsPinCodeRecognised && IsAccountInCredit)
			{
				// allow withdrawal
				// ...
			}
		}

Split Temporary Variable (page 128)

		// "Problem: You have a temporary variable assigned to more than once, but it is not a loop variable
		// nor a collecting temporary variable. 
		// Solution: Make a separate temporary variable for each assignment."
		
		// BEFORE
		// ------
		void MoneyMatters()
		{
			Int32 sumOfMoney;
			sumOfMoney = Account.CurrentBalance();
			// use 'value'
			sumOfMoney = MoneyInVault();
			// use 'sumOfMoney'
		}
		
		// AFTER
		// -----
		void MoneyMatters2()
		{
			Int32 balance;
			Int32 reserve;
			balance = Account.CurrentBalance();
			// use 'balance'
			reserve = MoneyInVault();
			// use 'reserve'
		}

Remove Assignment to Parameters (page 131)

		// "Problem: The code assigns to a parameter.
		// Solution: Use a temporary variable instead." 
	
		// BEFORE
		// ------
		void ProcessCustomer(Customer c)
		{
			c.OutputDetails();
			c = GetAnotherCustomer();
			// ...
			// later in code, could easily get confused about what c represents
		}
		// AFTER
		// -----
		void ProcessCustomer2(Customer c)
		{
			c.OutputDetails();
			Customer anotherCustomer;
			anotherCustomer = GetAnotherCustomer();
			// ...
			// later in code, there can be no confusion over parameters
		}

Replace Method with Method Object (page 135)

		// "Problem: You have a long method that uses local variables in such a way that you cannot applied Extract Method (110).
		// Solution: Turn the method into its own object so that all the local variables becomne fields on that object. 
		// You can then decompose the method into other methods on the same object." 
		
		// BEFORE
		// ------
		Int32 LongComplicatedMethod()
		{
			Int32 x = 3;
			Int32 y = 5;
			Int32 z = 7;
			// do something complicated
			x += 1;
			// do something complicated
			y += x;
			// do something complicated
			z = y * x;
			return 42;
		}
        		
		// AFTER
		// -----
		class MethodObject
		{
			Int32 x;
			Int32 y;
			Int32 z;
			public MethodObject(Int32 x, Int32 y, Int32 z)
			{
				this.x = x; this.y = y; this.z = z;
			}
			
			public Int32 Compute()
			{
				// do something complicated
				x += 1;
				// do something complicated
				y += x;
				// do something complicated
				z = y * x;
				return 42;
			}
		}
		Int32 ShortSimpleMethod()
		{
			return new MethodObject(3,5,7).Compute();
		}
		// Note: The real goal of a method object is to refactor a complicated
		// method, so we might later get:
		class MethodObject2
		{
			Int32 x = 3;
			Int32 y = 5;
			Int32 z = 7;
			public MethodObject2(Int32 x, Int32 y, Int32 z)
			{
				this.x = x; this.y = y; this.z = z;
			}
			
			void Compute()
			{
				// do something complicated
				x += 1;
				// do something complicated
				y += x;
			}
			void SimpleCompute()
			{
				// do something complicated
				z = y * x;
				// since the parameters are part of the class, it is easy to
				// access them from any method of the class (but not externally)
				// hence method extraction is much simpler
			}
		}
		//

Substitute Algorithm (page 139)

		// Problem: You want to replace an algorithm with one that is clearer. 
		// Solution: Replace the body of the method with the new algorithm. 
		
		// BEFORE
		// ------
		static Double CalculateAverage(Double x, Double y, Double z)
		{
			Double avg;
			avg = x/3.0 + y/3.0 + z/3.0;
			return avg;
		}
		
		// AFTER
		// -----
		static Double CalculateAverage2(Double x, Double y, Double z)
		{
			Double avg;
			avg = (x + y + z) / 3.0;
			return avg;
		}
		// Note: The important point with SubstituteAlgorithm is to maintain the method signature. All 
		// you unit tests that worked with teh previous algorithm should continue to work with the new
		// algorithm - if not, the either the new or the old algorithm is incorrect. If engaging in 
		// changing algorithms, should also consider use of interfaces, and allow algorithms to be 
		// pluggable. 

Moving Features Between Objects

Move Method (page 142)
Move Field (page 146)
Extract Class (page 149)
Inline Class (page 154)
Hide Delegate (page 157)
Remove Middle Man (page 160)
Introduce Foreign Method (page 162)
Introduce Local Extension (page 164)

Move Method (page 142)

		// Problem: A method is, or will be, using or used by more features of another class than by the class on which 
		// it is defined. 
		// Solution: Create a new method with a similar body in the class it uses most. Either turn the old method 
		// into a simple delegation, or remove it altogether.  
		
		// BEFORE
		// ------
		class ClassA 
		{
			static public void Method1()
			{
				// important functionality
			}
			// rest of FirstClass
			// ..
		}	
		class ClassB
		{
			void XMethod()
			{
				// do some work
				// ...
				ClassA.Method1();
			}
			void YMethod()
			{
				// do some work
				// ...
				ClassA.Method1();
			}
		}
		// AFTER
		// -----
		class ClassA_2 
		{
			// rest of FirstClass
			// ..
		}	
		class ClassB_2
		{
			static public void Method1()
			{
				// important functionality
			}
			void XMethod()
			{
				// do some work
				// ...
				Method1();
			}
			void YMethod()
			{
				// do some work
				// ...
				Method1();
			}
		}

Move Field (page 146)

		// Problem: A field is, or will be, used by another class more than the class on which it is defined. 
		// Solution: Create a new field in the target class, and change all its users. 
		
		// BEFORE
		// ------
		class ClassC
		{
			public const Int32 UsefulInfo = 4;
		}
		class ClassD
		{
			void DoSomething()
			{
				Int32 val = ClassC.UsefulInfo;
				// use val
				Console.WriteLine("val = " + val);
			}
		}
        
		// AFTER
		// -----
		class ClassC_2
		{
		}
		class ClassD_2
		{
			// Another benefit of moving the field closer to where it will
			// be used is that we can remove the public (or internal) declaration
			// - a design goal is to have shy objects, that communicate as little 
			// as possible with other objects (hence are much easier to evolve in 
			// future, and when changed, will not cause ripple effects throughout
			// our framework. 
			const Int32 UsefulInfo = 4;
			void DoSomething()
			{
				Int32 val = UsefulInfo;
				// use val
				Console.WriteLine("val = " + val);
			}
		}
 

Extract Class (page 149)

		// "Problem: You have one class doing work that should be done by two. 
		// Solution: Create a new class and move the relevant fields and methods from the old class into the new class."
		
		// BEFORE
		// ------
		class Book
		{
			String isbn="123";
			String title="ABC";
			String authorName="ZYX";
			Int32 authorYearOfBirth=2100;
			void DisplayBookInfo()
			{
				Console.WriteLine("Book's Title = " + title);
				Console.WriteLine("ISBN = " + isbn);
			}
			void DisplayAuthorInfo()
			{
				Console.WriteLine("Book's Author = " + authorName);
				Console.WriteLine("Author's year of birth = " + authorYearOfBirth);
			}
		}
		// AFTER
		// -----
		class Book2
		{
			String isbn="123";
			String title="ABC";
			void DisplayBookInfo()
			{
				Console.WriteLine("Book's Title = " + title);
				Console.WriteLine("ISBN = " + isbn);
			}
		}
		class Author
		{
			String authorName="ZYX";
			Int32 authorYearOfBirth=2100;
			void DisplayAuthorInfo()
			{
				Console.WriteLine("Book's Author = " + authorName);
				Console.WriteLine("Author's year of birth = " + authorYearOfBirth);
			}
		}
		// Also need to consider how to expose author to client's og the Book class
		// Perhaps expose Author as a public property of the Book class, or have author 
		// as a private field in Book, and maintain Book.DisplayAuthorInfo, which 
		// internally calls Author.DisplayAuthorInfo().

Inline Class (page 154)

		// "Problem: A class isn't doing much. 
		// Solution: Move all its features into another class and delete it." 
		
		// BEFORE
		// ------
		class Big
		{
			Int32 Subtract (Int32 x, Int32 y)
			{
				return x - y;
			}
			Int32 Multiply (Int32 x, Int32 y)
			{
				return x * y;
			}
			Int32 Add (Int32 x, Int32 y)
			{
				return Little.AddNumbers(x, y);
			}
		}
		class Little
		{
			public static Int32 AddNumbers(Int32 x, Int32 y)
			{
				return x + y;
			}
		}
		// If classes tryly represent distinguishable constructs, even if small,
		// they it still makes sense to have them exist. However, there is a certain
		// amount of leaway, and this refactoring is saying that in cases where there 
		// does not seem a great need for a small class to exist, its fields/methods 
		// can be added to another class (usually the caling class). 
		// AFTER
		// -----
		class Big2
		{
			Int32 Subtract (Int32 x, Int32 y)
			{
				return x - y;
			}
			Int32 Multiply (Int32 x, Int32 y)
			{
				return x * y;
			}
			Int32 Add (Int32 x, Int32 y)
			{
				return x + y;
			}
		}

Hide Delegate (page 157)

		// "Problem: A client is calling a delegate class of an object. 
		// Solution: Create methods on the server to hide the delegate." 
		
		// BEFORE
		// ------
		public class Client
		{
			// somehow get MarketingRegion
			MarketingRegion region = new MarketingRegion("Australia");
			void DisplayDetails()
			{
				Console.WriteLine("regionName = " + region.RegionName);
				Console.WriteLine("Sales figure = " + region.SalesManager.CalculateMonthlySales());
				// the problem here is that the client is now tied to both the 
				// MarketingRegion and SalesManager classes. 
			}
		}
		public class MarketingRegion
		{
			SalesManager salesManager = new SalesManager();
			String regionName;
			public String RegionName
			{
				get{ return regionName;}
			}
			public SalesManager SalesManager
			{
				get{return salesManager;}
			}
			
			public MarketingRegion(String regionName)
			{
				this.regionName = regionName;
			}
		}
		public class SalesManager
		{
			public Int32 CalculateMonthlySales()
			{
				// do calculation here
				return 42;
			}
		}
		
		// AFTER
		// -----
		public class Client2
		{
			// somehow get MarketingRegion
			MarketingRegion2 region = new MarketingRegion2("Australia");
			void DisplayDetails()
			{
				Console.WriteLine("regionName = " + region.RegionName);
				Console.WriteLine("Sales figure = " + region.GetSalesFigure());
				// Now the SalesManager classe can change without having to 
				// alter the Client2 class
			}
		}
		public class MarketingRegion2
		{
			SalesManager2 salesManager = new SalesManager2();
			String regionName;
			public String RegionName
			{
				get{ return regionName;}
			}
			public MarketingRegion2(String regionName)
			{
				this.regionName = regionName;
			}
			// As part of the publically accessible class, MarketingRegion2,
			// we provide a method that delegates the real work to a method
			// in the internal class, SalesManager. 
			public Int32 GetSalesFigure()
			{
				return salesManager.CalculateMonthlySales();
			}
		}
		// note we mark SalesManager as internal, as it
		// no longe needs to be acceisble from outside
		internal class SalesManager2
		{
			public Int32 CalculateMonthlySales()
			{
				// do calculation here
				return 42;
			}
		}	

Remove Middle Man (page 160)

		// "Problem: A class is doing too much simple delegation. 
		// Solution: Get the client to call the delegate directly." 
		
		// BEFORE
		// ------
		// Remove Middle Man is the inverse of Hide Delegate. If you have
		// too much delegation, as some point you need to simply expose the 
		// delegated class directly. 
		public class Client3
		{
			// somehow get MarketingRegion
			MarketingRegion3 region = new MarketingRegion3("Australia");
			void DisplayDetails()
			{
				Console.WriteLine("regionName = " + region.RegionName);
				Console.WriteLine("Sales figure = " + region.GetSalesFigure());
			}
		}
		public class MarketingRegion3
		{
			SalesManager3 salesManager = new SalesManager3();
			String regionName;
			public String RegionName
			{
				get{ return regionName;}
			}
			public MarketingRegion3(String regionName)
			{
				this.regionName = regionName;
			}
			public Int32 GetSalesFigure()
			{
				return salesManager.CalculateMonthlySales();
			}
		}
		internal class SalesManager3
		{
			public Int32 CalculateMonthlySales()
			{
				// do calculation here
				return 42;
			}
		}
		
		// AFTER
		// -----
		public class Client4
		{
			// somehow get MarketingRegion
			MarketingRegion4 region = new MarketingRegion4("Australia");
			void DisplayDetails()
			{
				Console.WriteLine("regionName = " + region.RegionName);
				Console.WriteLine("Sales figure = " + region.SalesManager.CalculateMonthlySales());
			}
		}
		public class MarketingRegion4
		{
			SalesManager4 salesManager = new SalesManager4();
			String regionName;
			public String RegionName
			{
				get{ return regionName;}
			}
			public SalesManager4 SalesManager
			{
				get{return salesManager;}
			}
			
			public MarketingRegion4(String regionName)
			{
				this.regionName = regionName;
			}
		}
		public class SalesManager4
		{
			public Int32 CalculateMonthlySales()
			{
				// do calculation here
				return 42;
			}
		}

Introduce Foreign Method (page 162)

		// "Problem: A server class you are using needs an additional method, but you can't modify the class. 
		// Solution: Create a method in the client class with an instance of the server class as its first argument." 
		
		// BEFORE
		// ------
		class Caller
		{
			Caller()
			{
				Callee callee = new Callee(Int32.MaxValue, Int32.MinValue);			
			}
		}
		class Callee
		{
			// For some reason, e.g. it is someone else's code, cannot change callee class
			public Callee(){}
			public Callee(Int32 x, Int32 y){ /* do something */ }			
		}
		
		// AFTER
		// -----
		class Caller2
		{
			Caller2()
			{
				Callee callee = MakeNewBoundaryCallee();
			}
			
			Callee MakeNewBoundaryCallee()
			{
				// This is a foreign method that should be in Callee
				return new Callee(Int32.MaxValue, Int32.MinValue);			
			}
		}
		class Callee2
		{
			// For some reason, e.g. it is someone else's code, cannot change callee class
			Callee2(){}
			Callee2(Int32 x, Int32 y){ /* do something */ }			
		}

Introduce Local Extension (page 164)

		// "Problem: A server class you are using needs several additional methods, but you can't modify the class. 
		// Solution: Create a new class that contains these additional methods. Make this extension class a 
		// subclass or a wrapper of the original." 
		
		// BEFORE
		// ------
		class Caller3
		{
			Caller3()
			{
				Callee3 callee = MakeNewBoundaryCallee();
			}
			
			Callee3 MakeNewBoundaryCallee()
			{
				// This is a foreign method that should be in Callee
				return new Callee3(Int32.MaxValue, Int32.MinValue);			
			}
		}
		class Callee3
		{
			// For some reason, e.g. it is someone else's code, cannot change callee class
			public Callee3(){}
			public Callee3(Int32 x, Int32 y){ /* do something */ }			
		}
		
		// AFTER
		// -----
		class Caller4
		{
			Caller4()
			{
				Callee4 callee4 = ExtensionClass.MakeNewBoundaryCallee();
			}
		}
		class ExtensionClass : Callee4
		{
			static public Callee4 MakeNewBoundaryCallee()
			{
				// This is a foreign method that should be in Callee
				return new Callee4(Int32.MaxValue, Int32.MinValue);			
			}
		}
        
		class Callee4
		{
			// For some reason, e.g. it is someone else's code, cannot change callee class
			public Callee4(){}
			public Callee4(Int32 x, Int32 y){ /* do something */ }			
		}

Organizing Data

Self Encapsulate Field (page 171)
Replace Data Value with Object (page 175)
Change Value to Reference (page 179)
Change Reference to Value (page 183)
Replace Array with Object (page 186)
Duplicate Observed Data (page 189)
Change Unidirectional Association to Bidirectional (page 197)
Change Bidirectional Association to Unidirectional (page 200)
Replace Magic Number with Symbolic Constant (page 204)
Encapsulate Field (page 206)
Encapsulate Collection (page 208)
Replace Record with Data Class (page 217)
Replace Type Code with Class (page 218)
Replace Type Code with Subclasses (page 223)
Replace Type Code with State/Strategy (page 227)
Replace Subclass with fields (page 232)

Self Encapsulate Field (page 171)

		// "Problem: You are accessing a field directly, but the coupling to the field is becoming awkward. 
		// Solution: Create getting and setting methods for the field and use only those to access the field." 
		
		// BEFORE
		// ------
		class ShowMe
		{
			Double pi = 3.1416;
			public void Print()
			{
				Console.WriteLine("value = " + pi);
			}
		}
		
		// AFTER
		// -----
		class ShowMe2
		{
			Double pi = 3.1416;
			public Double PI
			{
				get {return pi;}
			}
			public void Print()
			{
				Console.WriteLine("value = " + PI);
			}
		}
		// This is useful when a property may be computed, and may be different in subclass
		// Hence using the Property, and not the field, inside the class methods. 

Replace Data Value with Object (page 175)

		// "Problem: You have a data item that needs additional data or behaviour. 
		// Solution: Turn the data item into an object." 
		
		// BEFORE
		// ------
		class PupilInfo
		{
			String pupilGivenName=" ";
			String pupilFamilyName=" ";
			Int32 classId=4;
			String streetAddress=" ";
			String town=" ";
			void ShowName()
			{
				Console.WriteLine("Name = " + pupilGivenName + " " + pupilFamilyName + " (class = " + classId + ")");
			}
			void ShowAddress()
			{
				Console.WriteLine(streetAddress + " " + town);
			}
		}
		
		// AFTER
		// -----
		class PupilInfo2
		{
			String pupilGivenName=" ";
			String pupilFamilyName=" ";
			Int32 classId=4;
			void ShowName()
			{
				Console.WriteLine("Name = " + pupilGivenName + " " + pupilFamilyName + " (class = " + classId + ")");
			}
		}
		class Address 
		{
			String streetAddress=" ";
			String town=" ";
				
			void ShowAddress()
			{
				Console.WriteLine(streetAddress + " " + town);
			}
		}

Change Value to Reference (page 179)

		// "Problem: You have a class with many equal instances that you want to replace with a single object. 
		// Solution: Turn the object into a reference object."
		
		// BEFORE
		// ------
		class CastleSecuritySystem
		{
			CastleGate gateUsedByKing;
			CastleGate gateUsedByCommoners;
			CastleGate gateUsedBySlaves;
			
			CastleSecuritySystem()
			{
				// different objects are created for each, though in
				// reality the same object can serve multiples times
				gateUsedByKing = new CastleGate("right");
				gateUsedByCommoners = new CastleGate("left");
				gateUsedBySlaves = new CastleGate("left");
			}	
		}
	
		class CastleGate
		{
			String name;
			
			public CastleGate(String name)
			{
				this.name = name;
			}
		}
		
		// AFTER
		// -----
		class CastleSecuritySystem2
		{
			CastleGate2 gateUsedByKing;
			CastleGate2 gateUsedByCommoners;
			CastleGate2 gateUsedBySlaves;
			
			CastleSecuritySystem2()
			{
				gateUsedByKing = CastleGate2.GateFactory("right");
				gateUsedByCommoners = CastleGate2.GateFactory("left");
				gateUsedBySlaves = CastleGate2.GateFactory("left");
			}	
		}
	
		class CastleGate2
		{
			String name;
			static Hashtable h = new Hashtable();
			String gateColor;
			// Note it is when the object becomes editable that we really
			// need to make it into a reference object - so that the changes
			// are available to all users of this instance
			public String GateColor
			{
				get { return gateColor;}
				set {gateColor = value;}
			}
			
			public static CastleGate2 GateFactory(String name)
			{
				// search hashtable for existing object
				CastleGate2 gate = (CastleGate2) h[name]; 
				if (gate != null)
				{
					gate = new CastleGate2(name);
					h[name] = gate;
				}
				return gate;
			}
			// Note we make the constructor private - all external access is via the factory method
			private CastleGate2(String name)
			{
				this.name = name;
			}
		}

Change Reference to Value (page 183)

		// "Problem: You have a reference object that is small, immutable, and awkward to manage. 
		// Solution: Turn it into a value object." 
		
		// BEFORE
		// ------
		class GridPosition
		{
			Int32 x;
			Int32 y;
			public Int32 X
			{
				get { return x;}
			}
			public Int32 Y 
			{
				get {return y;}
			}
			private GridPosition (Int32 x, Int32 y)
			{
				this.x = x; 
				this.y = y;
			}
			// factory to create
		}
		// AFTER
		// -----
		class GridPosition2
		{
			Int32 x;
			Int32 y;
			public Int32 X
			{
				get { return x;}
			}
			public Int32 Y 
			{
				get {return y;}
			}
			public GridPosition2 (Int32 x, Int32 y)
			{
				this.x = x; 
				this.y = y;
			}
			public override bool Equals(object obj)
			{
				if (obj.GetType() != this.GetType())
					return false;
				GridPosition2 grid2 = (GridPosition2)obj;
				if (x == grid2.X && y == grid2.y)
					return true;
				else
					return false;
			}
			public override int GetHashCode()
			{
				return x.GetHashCode() 
 y.GetHashCode();
			}
		}

Replace Array with Object (page 186)

		// "Problem: You have an array in which certain elements mean different things. 
		// Solution: Replace the array with an object that has a field for each element." 
		
		// BEFORE
		// ------
		class Dog
		{
			// fields and methods for Dog
		}
		class Car
		{
			// fields and methods for Car
		}
		class MyProperty
		{
			object[] things = new object[2];
			MyProperty()
			{
				things[0]= new Dog();
				things[1] = new Car();
			}
			// it is very dangerous to have different types stored in the same array, and having
			// to use special indices to access them - we are strongly in favour of strong-typing
		}
		
		// AFTER
		// -----
		// car, dog as before
		class MyProperty2
		{
			Dog dog = new Dog();
			Car car = new Car();
			MyProperty2()
			{
			}
		}

Duplicate Observed Data (page 189)

		// "Problem: You have domain data available only in a GUI control, and domain methods need access. 
		// Solution: Copy the data to a domain object. Set up an observer to synchronise the two pieces of data." 
		
		// BEFORE
		// ------
		class UIWidget
		{
			// A major area where this refactoring is applicable is user interfaces - to keep the code snippet here 
			// simple, we do not load in a windowsing library - we invent our own - UIWidget. 
		}
		class UIForm 
		{
			Int32 length=0;
			Int32 width=0;
			UIWidget lengthTextBox=new UIWidget();
			UIWidget widthTextBox=new UIWidget();
			public void Display()
			{
				// use length and width here
				Console.WriteLine(length + width + lengthTextBox.ToString() + widthTextBox.ToString());
			}
		}
		// AFTER
		// -----
		class UIForm2 
		{
			Int32 length=0;
			Int32 width=0;
			UIWidget lengthTextBox = new UIWidget();
			UIWidget widthTextBox = new UIWidget();
			DomainObject domainObject = new DomainObject();
			public void Display()
			{
				// use length and width here
			}
			void EventHandler(Int32 newLength)
			{
				// called when widget is changed (e.g. text edited)
				length = newLength;
				domainObject.Update(length*width);
			}
		}
		class DomainObject
		{
			Int32 area;
			// Often the data in the UI widgets is in some way processed before 
			// being provided to the DOmian Object. Here we assume the UI is 
			// handle length of width, whereas the domain object is only interested in area
			public void Update(Int32 area)
			{
				this.area = area;
			}
		}

Change Unidirectional Association to Bidirectional (page 197)

		// "Problem: You have two classes that need to use each other's features, but there is only a one-way link. 
		// Solution: Add back pointers, and change modifiers to update both sets." 
		
		// BEFORE
		// ------
		// the following is fine if we only need to decide who author wrote a book, but
		// what happens when we wish to discover which book an author wrote? 
		class Book3
		{
			Author1 author = new Author1();
		}
		class Author1
		{
		}
		// AFTER
		// -----
		class Book4
		{
			Author2 author = new Author2();
		}
		class Author2
		{
			Book4 book = new Book4();
		}
		// One often will have multiples of each - a book can by written by multiple authors, and each author 
		// can write multiple books, hence a hashtable is often used here. 

Change Bidirectional Association to Unidirectional (page 200)

		// "Problem: You have a two-way association but one class no longer needs features from the other. 
		// Solution: Drop the un-needed end of the association."
	
		// BEFORE
		// ------
		class Book5
		{
			Page[] pages = new Page[3];
		}
		class Page
		{
			Int32 pageNumber=0;
			Book5 book=null;
			void Display()
			{
				Console.WriteLine(pageNumber);
				if (book != null)
					Console.WriteLine(book.ToString());
			}
		}
		
		// Every page must be part of one book, and in most cases can be accessed via a book 
		// reference,. so we can remove the bidirectional association
		// AFTER
		// -----
		class Book6
		{
			Page2[] pages=null;
			void Display()
			{
				if (pages != null)
					Console.WriteLine(pages[0].ToString());
			}
		}
		class Page2
		{
			Int32 pageNumber=0;
			void Display()
			{
				Console.WriteLine(pageNumber);
			}
		}

Replace Magic Number with Symbolic Constant (page 204)

		// "Problem: You have a literal number with a particular meaning. 
		// Solution: Create a constant, name it after the meaning, and replace the number with it." 
		
		// BEFORE
		// ------
		class BufferManager
		{
			char[] myBuffer=new char[1024];
		}
		
		// AFTER
		// -----
		class BufferManager2
		{
			public const Int32 MaxPathLength = 1024;
			char[] myBuffer = new char[MaxPathLength];
		}

Encapsulate Field (page 206)

		// "Problem: There is a public field. 
		// Solution: Make it private and provide accessors." 
		
		// BEFORE
		// ------
		class Footballer
		{
			public String GivenName=null;
		}
		
		// AFTER
		// -----
		class Footballer2
		{
			// note: when no visibility indicator given, it defaults to private. 
			String givenName=null;
			public String GivenName
			{
				get {return givenName;}
			}
		}
		// An Aside: the package visibility indicator, internal, is not use often enough
		// We are in favour of packages exposing as little surface area as possible
		// If needed later, it is easy to open up more - it is much more difficult to 
		// do the reverse later.

Encapsulate Collection (page 208)

		// "Problem: A method returns a collection. 
		// Solution: Make it return a read-only view and provide add/remove methods." 
		
		// BEFORE
		// ------
		class Car2
		{
			// car details
		}
		class MyGarage
		{
			Car2[] cars = new Car2[10];
			public Car2[] GetCars()
			{
				return cars;
			}
		}
		
		// AFTER
		// -----
		class MyGarage2
		{
			CarCollection carCollection = new CarCollection();
			public CarCollection Cars
			{
				get{ return carCollection;}
			}
		}
		class CarCollection
		{
			Car2[] cars = new Car2[10];
			public void Add(Car2 car){/* logic for add */}
			public void Remove(String name){ /* logic for remove */ }
			// other methods for access etc.
		}
		// see Clipcode Knowledge Platform for examples of complete collection classes
		// .NET v2 will add generics - when available, we stringly recommend their use. 

Replace Record with Data Class (page 217)

		// "Problem: You need to interface with a record structure in a traditional programming environment. 
		// Solution: Make a dumb data object for the record." 
		
		// BEFORE
		// ------
		[StructLayout(LayoutKind.Sequential, Pack=1)]
			public struct SYSTEM_INFO
		{
			public ushort wProcessorArchitecture;
			public ushort wReserved;
			public uint dwPageSize;
			public IntPtr lpMinimumApplicationAddress;
			public IntPtr lpMaximumApplicationAddress;
			public IntPtr dwActiveProcessorMask;
			public uint dwNumberOfProcessors;
			public uint dwProcessorType;
			public uint dwAllocationGranularity;
			public ushort wProcessorLevel;
			public ushort wProcessorRevision;
		};
		[DllImport("KERNEL32", CharSet=CharSet.Auto)]
		public static extern void GetSystemInfo(out SYSTEM_INFO si);
		
		class GetNumberOfProcesses
		{
			void func()
			{
				SYSTEM_INFO si;
				GetSystemInfo(out si);
				uint numberOfProcessors = si.dwNumberOfProcessors;
				Console.WriteLine("Number Of Processors = "+numberOfProcessors.ToString());
			}			
		}
		
		// AFTER
		// -----
		class SysInfo
		{
			SYSTEM_INFO si;
			public UInt32 NumberOfProcessors
			{
				get{return si.dwNumberOfProcessors;}
			}
			public UInt32 PageSize
			{
				get{return si.dwPageSize;}
			}
			internal SysInfo()
			{
				// makes sense to populate date here
				GetSystemInfo(out si);
			}
		}
		
		class GetNumberOfProcesses2
		{
			void func()
			{
				SysInfo sysInfo = new SysInfo();
				Console.WriteLine("Number Of Processors = "+sysInfo.NumberOfProcessors.ToString());
			}			
		}

Replace Type Code with Class (page 218)

		// "Problem: A class has a numeric type code that does not affect its behaviour. 
		// Solution: Replace the number with a new class." 
		// Comment: In our example below, we start with an enumeration (we defined the numeric value of each field), 
		// and evolve it into a new class. Fowler has these values as numeric fields in the main class, but 
		// some people might think the problem is solved simply by using an enumeration - it is not. 
		// In C#, with the exception of the number 0 (zero), conversion between an enumeration and its underlying type 
		// requires an explicit cast. The compiler does not check to see that the value used actually represents a enumeration value. 
		
		// BEFORE
		// ------
		enum OfficeFloor 
		{
			GroundFloor=0,
			FirstFloor=1,
			SecondFloor=2
		}
		class Office
		{
			OfficeFloor floor;
			public Office(OfficeFloor floor)
			{
				this.floor = floor;
			}
			void BuggyCode()
			{
				floor = (OfficeFloor) 45; // this floor des not exist!
			}
		}
		// AFTER
		// -----
		class OfficeFloor2
		{
			const Int32 GroundFloor=0;
			const Int32 FirstFloor=1;
			const Int32 SecondFloor=2;
			const Int32 MinCode=GroundFloor;
			const Int32 MaxCode=SecondFloor;
			Int32 code;
			public Int32 Code
			{
				get{return code;}
				set{code = value;}
			}
			OfficeFloor2(Int32 code)
			{
				if (code>= MinCode && code <= MaxCode)
					this.code = code;
				else
					throw new ArgumentOutOfRangeException("code provided = " + code.ToString() + 
						" ; was invalid. Code must be between " + MinCode + " and " + MaxCode + ".");
			}
		}
		class Office2
		{
			OfficeFloor2 floor;
			public Office2(OfficeFloor2 floor)
			{
				this.floor = floor;
			}
			public static Office2 BuggyCode()
			{
				Office2 office = null;
				// compiler catches this error!
				// new Office2(OfficeFloor2)3); // 3 cannot be converted to an instance of OfficeFloor2
				return office;
			}
		}

Replace Type Code with Subclasses (page 223)

		// "Problem: You have an immutable type code that affects the behaviour of a class. 
		// Solution: Replace the type code with subclasses." 
		
		// BEFORE
		// ------
		class Vehicle
		{
			public const Int32 Car = 0;
			public const Int32 Truck = 1;
			public const Int32 SUV = 2;
			Int32 vehicleCode;
			public Vehicle(Int32 code)
			{
				vehicleCode = code;
			}
			public void DisplayType()
			{
				switch (vehicleCode)
				{
					case Car:
						Console.WriteLine("VEHICLE = CAR");
						break;
					case Truck:
						Console.WriteLine("VEHICLE = TRUCK");
						break;
					case SUV:
						Console.WriteLine("VEHICLE = SUV");
						break;
					default:
						throw new Exception("Unexpected switch type");
				}
			}
		}		
		// AFTER
		// -----
		abstract class Vehicle2
		{
			public const Int32 Car = 0;
			public const Int32 Truck = 1;
			public const Int32 SUV = 2;
			abstract public void DisplayType();
			//Int32 vehicleType;
			// Factory method
			public Vehicle2 GetVehicle(Int32 code)
			{
				switch (code)
				{
					case Car:
						return new CarType();
					case Truck:
						return new TruckType();
					case SUV:
						return new SUVType();
					default:
						throw new Exception("Unexpected switch type");
				}
			}
			// could also think about using Replace Conditional With Polymorphism (255).
		}
		class CarType : Vehicle2
		{
			override public void DisplayType()
			{
				Console.WriteLine("VEHICLE = CAR");
			}
		}
		class TruckType : Vehicle2
		{
			override public void DisplayType()
			{
				Console.WriteLine("VEHICLE = Truck");
			}
		}
		class SUVType : Vehicle2
		{
			override public void DisplayType()
			{
				Console.WriteLine("VEHICLE = SUV");
			}
		}

Replace Type Code with State/Strategy (page 227)

		// "Problem: You have a type code that affects the behaviour of a class, but you cannot use subclassing. 
		// Solution: Replace the type code with a state object." 
		
		// BEFORE
		// ------
		class Vehicle3
		{
			public const Int32 Car = 0;
			public const Int32 Truck = 1;
			public const Int32 SUV = 2;
			Int32 vehicleCode;
			public Vehicle3(Int32 code)
			{
				vehicleCode = code;
			}
			public void DisplayType()
			{
				switch (vehicleCode)
				{
					case Car:
						Console.WriteLine("VEHICLE = CAR");
						break;
					case Truck:
						Console.WriteLine("VEHICLE = TRUCK");
						break;
					case SUV:
						Console.WriteLine("VEHICLE = SUV");
						break;
					default:
						throw new Exception("Unexpected switch type");
				}
			}
		}		
		
		// AFTER
		// -----
		class Vehicle4
		{
			VehicleType vehicleType;
			public Vehicle4()
			{
				vehicleType = new SUVType2();
				vehicleType.Display();
			}
		}
		abstract class VehicleType
		{
			public const Int32 Car = 0;
			public const Int32 Truck = 1;
			public const Int32 SUV = 2;
			abstract public Int32 GetCode();
			// Factory method
			public void Display()
			{
				switch (GetCode())
				{
					case Car:
						Console.WriteLine("CAR");
						break;
					case Truck:
						Console.WriteLine("TRUCK");
						break;
					case SUV:
						Console.WriteLine("SUV");
						break;
					default:
						throw new Exception("Unexpected switch type");
				}
				// Now need to think about using Replace Conditional With Polymorphism (255).
			}
		}
		class CarType2 : VehicleType
		{
			override public Int32 GetCode()
			{
				return VehicleType.Car;
			}
		}
		class TruckType2 : VehicleType
		{
			override public Int32 GetCode()
			{
				return VehicleType.Truck;
			}
		}
		class SUVType2 : VehicleType
		{
			override public Int32 GetCode()
			{
				return VehicleType.SUV;
			}
		}

Replace Subclass with fields (page 232)

		// "Problem: You have subclasses that vary only in methods that return constant data. 
		// Solution: Change the methods to superclass fields and eliminate the subclasses." 
		
		// BEFORE
		// ------
		abstract class Customer2
		{
			abstract public String GetCustomerTypeDescriptor();
		}
		class CorporateCustomer: Customer2
		{
			override public String  GetCustomerTypeDescriptor()
			{
				return "CORPORATE";
			}
		}
		class ResidentialCustomer : Customer2
		{
			override public String GetCustomerTypeDescriptor()
			{
				return "RESIDENTIAL";
			}
		}
		
		// AFTER
		// -----
		class Customer3
		{
			String customerType;
			private Customer3(String customerType)
			{
				this.customerType = customerType;
			}
			public String GetCustomerTypeDescriptor()
			{
				return customerType;
			}
			// factory methods
			static public Customer3 CreateResidentialCustomer()
			{
				return new Customer3("RESIDENTIAL");
			}
			static public Customer3 CreateCorporateCustomer()
			{
				return new Customer3("CORPORATE");
			}
		}
        

Simplifying Conditional Expressions

Decompose Conditional (page 238)
Consolidate Conditional Expression (page 240)
Consolidate Duplicate Conditional Fragments (page 243)
Remove Control Flag (page 245)
Replace Nested Conditional with Guard Clauses (page 250)
Replace Conditional with Polymorphism (page 255)
Introduce Null Object (page 260)
Introduce Assertion (page 267)

Decompose Conditional (page 238)

		// "Problem: You have a complicated conditional (if-then-else) statement. 
		// Solution: Extract methods from the condition, then part and else parts." 
		
		// BEFORE
		// ------
		class Complicated
		{
			const Int32 MaxPermittedThickness = 100;
			const Int32 MinPermittedThickness = 10;
			Int32 maxMeasuredThickness;
			Int32 minMeasuredThickness;
			public Complicated(Int32 maxMeasuredThickness, Int32 minMeasuredThickness)
			{
				this.maxMeasuredThickness = maxMeasuredThickness;
				this.minMeasuredThickness = minMeasuredThickness;
			}
			void DoSomething()
			{
				if ((maxMeasuredThickness < MaxPermittedThickness) && (minMeasuredThickness > MinPermittedThickness))
					Console.WriteLine("something complicated");
				else
					Console.WriteLine("something complicated");
			}
		}
		// AFTER
		// -----
		class Simple
		{
			const Int32 MaxPermittedThickness = 100;
			const Int32 MinPermittedThickness = 10;
			Int32 maxMeasuredThickness;
			Int32 minMeasuredThickness;
			void DoSomething()
			{
				// A goal is to make top-level methods almost read like comments
				if (WithinTolerances())
					PassDownAssemblyLine();
				else
					Rework();
			}
			public Simple(Int32 maxMeasuredThickness, Int32 minMeasuredThickness)
			{
				this.maxMeasuredThickness = maxMeasuredThickness;
				this.minMeasuredThickness = minMeasuredThickness;
			}
			Boolean WithinTolerances()
			{
				return ((maxMeasuredThickness < MaxPermittedThickness) && (minMeasuredThickness > MinPermittedThickness));
			}
			void PassDownAssemblyLine()
			{
				Console.WriteLine("something complicated");
			}
			void Rework()
			{
				Console.WriteLine("something complicated");
			}
		}
				

Consolidate Conditional Expression (page 240)

		// "Problem: You have a sequence of conditional tests with teh same result. 
		// Solution: Combine them into a single conditional expression and extract it." 
		
		// BEFORE
		// ------
		class MultiConditionWorker
		{
			Boolean OnHolidays = false;
			Boolean IsSick = false;
			Boolean OnTrainingCourse = false;
			Int32 HoursAvailableForWorkToday()
			{
				if (OnHolidays) return 0;
				if (IsSick) return 0;
				if (OnTrainingCourse) return 0;
				return 8;
			}
		}
				
		// AFTER
		// -----
		class SingleConditionWorker
		{
			Boolean OnHolidays = false;
			Boolean IsSick = false;
			Boolean OnTrainingCourse = false;
			Boolean AtWork()
			{
				return (OnHolidays || IsSick || OnTrainingCourse);
			}
			
			Int32 HoursAvailableForWorkToday()
			{
				if (AtWork())
					return 0;
				else
					return 8;
			}
		}
				

Consolidate Duplicate Conditional Fragments (page 243)

		// "Problem: The same fragment of code is in all branches of a conditional expression. 
		// Solution: Move it outside of the expression." 
		
		// BEFORE
		// ------
		class MapEngine
		{
			static public String TownFinder(Double longitude, Double latitude)
			{
				// complicate map searching here ...
				return "North Pole";
			}
		}
		class WhereAmI
		{
			String nearestTown;
			void Display(Boolean InOuterSpace, Double longitude, Double latitude)
			{
				if (InOuterSpace)
				{
					nearestTown = "NONE";
					Console.WriteLine("Nearest Town = " + nearestTown);
				} 
				else 
				{
					nearestTown = MapEngine.TownFinder(longitude, latitude);
					Console.WriteLine("Nearest Town = " + nearestTown);
				}
			}
		}
				
		// AFTER
		// -----
		class WhereAmI2
		{
			String nearestTown;
			void Display(Boolean InOuterSpace, Double longitude, Double latitude)
			{
				if (InOuterSpace)
					nearestTown = "NONE";
				else
					nearestTown = MapEngine.TownFinder(longitude, latitude);
				Console.WriteLine("Nearest Town = " + nearestTown);
			}
		}

Remove Control Flag (page 245)

		// "Problem: You have a variable that is acting as a control flag for a series of boolean expressions. 
		// Solution: Use a break or return instead." 
		
		// BEFORE
		// ------
		class Room
		{
			Boolean isAvailable;
			Int32 roomNumber;
			public Boolean IsAvailable
			{
				get{return isAvailable;}
			}
			public Int32 RoomNumber
			{
				get{return roomNumber;}
			}
			public Room(Boolean isAvailable, Int32 roomNumber)
			{
				this.isAvailable = isAvailable;
				this.roomNumber = roomNumber;
			}
		}
		class TrainingLab
		{
			Room[] rooms;
			Int32 roomCount=0;
			public TrainingLab()
			{
				roomCount = 3;
				rooms = new Room[roomCount];
				rooms[0] = new Room(true, 10);
				rooms[1] = new Room(false, 23);
				rooms[2] = new Room(true, 43);
			}
			Int32 DisplayFreeTrainingRoom()
			{
				Boolean found=false;
				Int32 freeRoomNum=-1;
				for(Int32 i=0; i < roomCount; i++)
				{
					if (!found)
						if (rooms[i].IsAvailable)
						{
							found = true;
							freeRoomNum = rooms[i].RoomNumber;
							// other work for found room
						}
				}
				return freeRoomNum;
			}
						
			// AFTER
			// -----
			class TrainingLab2
			{
				Room[] rooms;
				Int32 roomCount=0;
				public TrainingLab2()
				{
					roomCount = 3;
					rooms = new Room[roomCount];
					rooms[0] = new Room(true, 10);
					rooms[1] = new Room(false, 23);
					rooms[2] = new Room(true, 43);
				}
				Int32 FindFreeTrainingRoom()
				{
					Int32 freeRoomNum=-1;
					for(Int32 i=0; i < roomCount; i++)
					{
						if (rooms[i].IsAvailable)
						{
							freeRoomNum = rooms[i].RoomNumber;
							// other work for found room
							break;
						}
					}
					return freeRoomNum;
				}
			}
		}

Replace Nested Conditional with Guard Clauses (page 250)

		// "Problem: A method has conditional behavior that does not make clear the normal path of execution. 
		// Solution: Use guard clauses for all the special cases." 
		
		// BEFORE
		// ------
		class Unclear
		{
			const String Usa = "Usa";
			const String EuropeanUnion = "European Union";
			const String RestOfWorld = "Rest of World";
			String AmericanWay() { return "A"; }
			String EuropeanWay() { return "B"; }
			String RestOfWorldWay() {return "C"; }
			String Evaluate(String area)
			{
				String data=null;
				if (area == Usa)
					data = AmericanWay();
				else
				{
					if (area == EuropeanUnion)
						data = EuropeanWay();
					else
						data = RestOfWorldWay();
				}
				return data;
			}
		}
		// AFTER
		// -----
		class Clear
		{
			const String Usa = "Usa";
			const String EuropeanUnion = "European Union";
			const String RestOfWorld = "Rest of World";
			String AmericanWay() { return "A"; }
			String EuropeanWay() { return "B"; }
			String RestOfWorldWay() {return "C"; }
			String Evaluate(String area)
			{
				// flow of control is much clearer here
				if (area == Usa) return AmericanWay();
				if (area == EuropeanUnion) return EuropeanWay();
				return RestOfWorldWay();
			}
		}
		

Replace Conditional with Polymorphism (page 255)

		// "Problem: You have a conditional that chooses different behaviour depending on the type of the object. 
		// Solution: Move each leg of the conditional to an overriding method in a subclass. Make the original method abstract." 
		
		// BEFORE
		// ------
		// The BEFORE for this sample is the AFTER code from State/Strategy (227).
		// It contains a switch conditional statement, and in the following refactoring we wish to remove it using polymorphism. 
				
		// AFTER
		// -----
		class Vehicle5
		{
			VehicleType2 vehicleType;
			public Vehicle5()
			{
				vehicleType = new SUVType3();
				vehicleType.Display();
			}
		}
		abstract class VehicleType2
		{
			public const Int32 Car = 0;
			public const Int32 Truck = 1;
			public const Int32 SUV = 2;
			abstract public Int32 GetCode();
			// Factory method
			abstract public void Display();
		}
		class CarType3 : VehicleType2
		{
			override public Int32 GetCode()
			{
				return VehicleType.Car;
			}
			override public void Display()
			{
				Console.WriteLine("CAR");
			}
		}
		class TruckType3 : VehicleType2
		{
			override public Int32 GetCode()
			{
				return VehicleType.Truck;
			}
			override public void Display()
			{
				Console.WriteLine("TRUCK");
			}
		}
		class SUVType3 : VehicleType2
		{
			override public Int32 GetCode()
			{
				return VehicleType.SUV;
			}
			override public void Display()
			{
				Console.WriteLine("SUV");
			}
		}

Introduce Null Object (page 260)

		// "Problem: You have repeated checks for a null object. 
		// Solution: Replace the null value with the null object." 
		
		// BEFORE
		// ------
		class NewCar
		{
			public void DisplayBrand(){Console.WriteLine("BWW");}
		}
		class CarDealer
		{
			void DisplayDetails(NewCar car)
			{
				if (car != null)
				{
					car.DisplayBrand();
				}
			}
		}
				
		// AFTER
		// -----
		// Note: System.Data.SQLTypes.INullable does exist in the .NET Framework, but it requires the System.Data assembly.
		// This is really a core interface, not tied to SQL, and so would be more useful within System. Too late t ochange now. 
		// Therefore we define uor own. 
		interface INullable
		{
			Boolean IsNull();
		}
		class NewCar2 : INullable
		{
			static NullNewCar nullCar=null;
			public virtual void DisplayBrand(){Console.WriteLine("BWW");}
			static public NewCar2 NewNull()
			{
				// We use the Singleton design pattern here - we only need one instance
				if (nullCar == null)
					nullCar = new NullNewCar();
				return nullCar;
			}
			public Boolean IsNull(){return false;}
		}
		class NullNewCar : NewCar2
		{
			new public Boolean IsNull(){return true;}
			public override void DisplayBrand(){Console.WriteLine("    ");}
		}
		class CarDealer2
		{
			void DisplayDetails(NewCar2 car)
			{
				// now we can remove the if from here
				car.DisplayBrand();
			}
		}
		

Introduce Assertion (page 267)

		// "Problem: A section of code assumes something about the state of the program. 
		// Solution: Make the assumption explicit with an assertion." 
		
		// BEFORE
		// ------
		class Rectangle
		{
			Int32 x1;
			Int32 y1;
			Int32 x2;
			Int32 y2;
			public Rectangle(Int32 x1, Int32 y1, Int32 x2, Int32 y2)
			{
				this.x1 = x1;
				this.y1 = y1;
				this.x2 = x2;
				this.y2 = y2;
			}
		}
		// AFTER
		// -----
		class Rectangle2
		{
			Int32 x1;
			Int32 y1;
			Int32 x2;
			Int32 y2;
			public Rectangle2(Int32 x1, Int32 y1, Int32 x2, Int32 y2)
			{
				Debug.Assert(x2 > x1);
				Debug.Assert(y2 > y1);
				this.x1 = x1;
				this.y1 = y1;
				this.x2 = x2;
				this.y2 = y2;
			}
		}

Making Method Calls Simpler

Rename Method (page 273)
Add Parameter (page 275)
Remove Parameter (page 277)
Separate Query from Modifier (page 279)
Parameterize Method (page 283)
Replace Parameter with Explicit Methods (page 285)
Preserve Whole Object (page 288)
Replace Parameter with Method (page 292)
Introduce Parameter Object (page 295)
Remove Setting Method (page 300)
Hide Method (page 303)
Replace Constructor with Factory Method (page 304)
Encapsulate Downcast (page 308)
Replace Error Code with Exception (page 310)
Replace Exception with Test (page 315)

Rename Method (page 273)

		// "Problem: The name of a method does not reveal its purpose. 
		// Solution: Change the name of the method." 
		
		// BEFORE
		// ------
		class Sq
		{
			Int32 l;
			Sq(Int32 l)
			{
				this.l = l;
			}
			Int32 GetA()
			{
				return l*l;
			}
		}
				
		// AFTER
		// -----
		class Square
		{
			Int32 length;
			Square(Int32 length)
			{
				this.length = length;
			}
			Int32 GetArea()
			{
				return length*length;
			}
		}

Add Parameter (page 275)

		// "Problem: A method needs more information from its caller. 
		// Solution: Add a paraemter for an object that can pass this information." 
		
		// BEFORE
		// ------
		class Color
		{
			public void MyFavoriteColor()
			{
				Console.WriteLine("RED");
			}
		}
		
		// AFTER
		// -----
		class Color2
		{
			public void MyFavoriteSeasonalColor(String season)
			{
				if (season == "WINTER")
					Console.WriteLine("RED");
				else
					Console.WriteLine("GREEN");
			}
		}

Remove Parameter (page 277)

		// "Problem: A parameter is no longer used by the method body. 
		// Solution: Remove it." 
		
		// this refactoring is the reverse of Add Parameter. 

Separate Query from Modifier (page 279)

		// "Problem: You have a method that returns a value but also changes the state of the object. 
		// Solution: Create two methods, one for the query and one for the modification." 
		// If you are using descriptive names (as recommended), often the method name will contain And. 
		
		// BEFORE
		// ------
		class MySquare
		{
			const Int32 MinBigSquare=10;
			Int32 area = 4;
			public Boolean SetSizeAndDetermineIfBig(Int32 length)
			{
				this.area = length * length;
				return (area > MinBigSquare); 
			}
		}
				
		// AFTER
		// -----
		class MySquare2
		{
			const Int32 MinBigSquare=10;
			Int32 area = 4;
			public void SetSize(Int32 length)
			{
				this.area = length * length;
			}
			public Boolean DetermineIfBig()
			{
				return (area > MinBigSquare); 
			}
		}

Parameterize Method (page 283)

		// "Problem: Several methods do similar things but with different values contained in the method body. 
		// Solution: Create one method that uses a parameter for the different values." 
		
		// BEFORE
		// ------
		class StringManager
		{
			String data;	
			public StringManager(String data){this.data = data;}
			public void AppendLargeSuffix(String suffix){data += suffix;}
			public void AppendShortSuffix(String suffix){data += suffix;}
		}
		
		// AFTER
		// -----
		class StringManager2
		{
			String data;
			public StringManager2(String data){this.data = data;}
			public void AppendSuffix(String suffix){data += suffix;}
		}

Replace Parameter with Explicit Methods (page 285)

		// "Problem: You have a method that runs different code depending on the values of an enumerated parameter. 
		// Solution: Create a separate method for each value of the parameter." 
		
		// BEFORE
		// ------
		class MyCar
		{
			String brand;
			String manufacturer;
		
			public MyCar(String brand, String manufacturer)
			{
				this.brand = brand;
				this.manufacturer = manufacturer;
			}
			
			public void SetDescriptor(String category, String newDescriptor)
			{
				if (category == "BRAND")
					brand = newDescriptor;
				else if (category == "MANUFACTURER")
					manufacturer = newDescriptor;
			}
		}
				
		// AFTER
		// -----
		class MyCar2
		{
			String brand;
			String manufacturer;
		
			public MyCar2(String brand, String manufacturer)
			{
				this.brand = brand;
				this.manufacturer = manufacturer;
			}
			
			public void SetBrnad(String brand)
			{
				this.brand = brand;
			}
			public void SetManufacturer(String manufacturer)
			{
				this.manufacturer = manufacturer;
			}
		}
				

Preserve Whole Object (page 288)

		// "Problem: You are getting several values from an object and passing these values as parameters in a method call. 
		// Solution: Send the whole object instead." 
		
		// BEFORE
		// ------
		class MyCar3
		{
			public String Brand="SMART";
			public String Manufacturer="Mercedes";
			public String CoolnessFactor="Ultra";
		}
		class ReportGenerator
		{
			public void Demo()
			{
				MyCar3 myCar = new MyCar3();
				Display(myCar.Brand, myCar.Manufacturer, myCar.CoolnessFactor);
			}
			public void Display(String brand, String manufacturer, String coolnessFactor)
			{
				Console.WriteLine("brand = " + brand 
					+ "; manufacturer = " + manufacturer
					+ "; coolness factor = " + coolnessFactor);
			}
		}
				
		// AFTER
		// -----
		class ReportGenerator2
		{
			public void Demo()
			{
				MyCar3 myCar = new MyCar3();
				Display(myCar);
			}
			public void Display(MyCar3 myCar)
			{
				Console.WriteLine("brand = " + myCar.Brand 
					+ "; manufacturer = " + myCar.Manufacturer
					+ "; coolness factor = " + myCar.CoolnessFactor);
			}
		}

Replace Parameter with Method (page 292)

		// "Problem: An object invokes a method, then passes the result as a parameter for a method. The receiver 
		// can also invoke this method. 
		// Solution: Remove the parameter and let the receiver invoke the method." 
		
		// BEFORE
		// ------
		class CarDealer3
		{
			String brand = "PRIUS";
			String manufacturer = "Toyota";
			String GetIdentifier()
			{
				return brand+manufacturer;
			}
			public void Display(String title)
			{
				DateTime today = DateTime.Today;
				String identifier = GetIdentifier();
				Int32 price = 10; // complicated code
				PrintReport(today.ToShortTimeString(), identifier, price);
			}
			void PrintReport(String dateToday, String carIdentifier, Int32 price)
			{
				// do something
			}
		}
				
		// AFTER
		// -----
		class CarDealer4
		{
			String brand = "PRIUS";
			String manufacturer = "Toyota";
			String GetIdentifier()
			{
				return brand+manufacturer;
			}
			public void Display(String title)
			{
				Int32 price = 10; // complicated code
				PrintReport(price);
			}
			// note much shorter parameter list
			// you may be wondering why have the Display method at all - it is 
			// needed if there is some complicated code in there and it simplfies
			// if we separate that from PrintReport. 
			void PrintReport(Int32 price)
			{
				DateTime today = DateTime.Today;
				String identifier = GetIdentifier();
				// do something
			}
		}
			

Introduce Parameter Object (page 295)

		// "Problem: You have a group of parameters that naturally go together. 
		// Solution: Replace them with an object." 
		
		// BEFORE
		// ------
		class CarDealer5
		{
			void Display(String carBrand, String carManufacturer)
			{
				Console.WriteLine("brand = " + carBrand + "; Manufacturer = " + carManufacturer);
			}
		}
				
		// AFTER
		// -----
		class Car3
		{
			String brand;
			String manufacturer;
			public String Brand
			{
				get{return brand;}
			}
			public String Manufacturer
			{
				get{return manufacturer;}
			}
			public Car3(String brand, String manufacturer)
			{
				this.brand = brand;
				this.manufacturer = manufacturer;
			}
		}
		
		class CarDealer6
		{
			void Display(Car3 car)
			{
				Console.WriteLine("brand = " + car.Brand + "; Manufacturer = " + car.Manufacturer);
			}
		}

Remove Setting Method (page 300)

		// "Problem: A field should be set at creation time and never altered. 
		// Solution: Remove any setting method for that field." 
		
		// BEFORE
		// ------
		class MyCar7
		{
			String brand;
			public String Brand
			{
				get{return brand;}
				set{brand = value;}
			}
		}
				
		// AFTER
		// -----
		class MyCar8
		{
			String brand;
			public String Brand
			{
				// remove setters when not needed
				get{return brand;}
			}
			public MyCar8(String brand)
			{
				this.brand = brand;
			}
		}

Hide Method (page 303)

		// "Problem: A method is not used by any other class. 
		// Solution: Make the method private." 
		
		// BEFORE
		// ------
		class Plane
		{
			public void StartPlane()
			{
				OpenFuelPump();
				// rest of work to start plane
			}
			public void OpenFuelPump()
			{
				// only called from within the Plane class!
			}
		}
				
		// AFTER
		// -----
		class Plane2
		{
			public void StartPlane()
			{
				OpenFuelPump();
				// rest of work to start plane
			}
			private void OpenFuelPump()
			{
				// only called from within the Plane class!
			}
		}

Replace Constructor with Factory Method (page 304)

		// "Problem: You want to do more than simple construction when you create an object. 
		// Solution: Replace the constructor with a factory method." 
		
		// BEFORE
		// ------
		class CastleSecuritySystem3
		{
			CastleGate3 gateUsedByKing;
			CastleGate3 gateUsedByCommoners;
			CastleGate3 gateUsedBySlaves;
			
			CastleSecuritySystem3()
			{
				// different objects are created for each, though in
				// reality the same object can serve multiples times
				gateUsedByKing = new CastleGate3("right");
				gateUsedByCommoners = new CastleGate3("left");
				gateUsedBySlaves = new CastleGate3("left");
			}	
		}
	
		class CastleGate3
		{
			String name;
			
			public CastleGate3(String name)
			{
				this.name = name;
			}
		}
		
		// AFTER
		// -----
		class CastleSecuritySystem4
		{
			CastleGate4 gateUsedByKing;
			CastleGate4 gateUsedByCommoners;
			CastleGate4 gateUsedBySlaves;
			
			CastleSecuritySystem4()
			{
				gateUsedByKing = CastleGate4.GateFactory("right");
				gateUsedByCommoners = CastleGate4.GateFactory("left");
				gateUsedBySlaves = CastleGate4.GateFactory("left");
			}	
		}
	
		class CastleGate4
		{
			String name;
			static Hashtable h = new Hashtable();
			
			public static CastleGate4 GateFactory(String name)
			{
				// search hashtable for existing object
				CastleGate4 gate = (CastleGate4) h[name]; 
				if (gate != null)
				{
					gate = new CastleGate4(name);
					h[name] = gate;
				}
				return gate;
			}
			// Note we make the constructor private - all external access is via the factory method
			private CastleGate4(String name)
			{
				this.name = name;
			}
		}

Encapsulate Downcast (page 308)

		// "Problem: A method returns an object that needs to be downcasted by its callers. 
		// Solution: Move the downcast to within the method." 
		
		// BEFORE
		// ------
		class SpaceTransporter
		{
			// fields + methods
		}
		class TroopCarrier : SpaceTransporter
		{
			// fields + methods
		}
		class LogisticsCarrier : SpaceTransporter
		{
			// fields + methods
		}
		class SpacePort
		{
			// collection of transporter types attached to docking pods
			protected object[] transporters = new object[10]; // should use System.Collections for a growable array
			// When generics arrive (in C# v2), use them!
		}
		class MiltarySpacePort : SpacePort
		{
			// assume MiltartySpacePort only allows TroopCarriers
			public MiltarySpacePort()
			{
				transporters[0] = new TroopCarrier();
			}
			public object GetFirst()
			{
				return transporters[0];
			}
			void DisplayMapOfAttachedTransporters()
			{
				TroopCarrier t= (TroopCarrier) GetFirst();
				// do something with t
			}
		}
				
		// AFTER
		// -----
		class MiltarySpacePort2 : SpacePort
		{
			// assume MiltartySpacePort only allows TroopCarriers
			public MiltarySpacePort2()
			{
				transporters[0] = new TroopCarrier();
			}
			public TroopCarrier GetFirst()
			{
				return (TroopCarrier)(transporters[0]);
			}
			void DisplayMapOfAttachedTransporters()
			{
				TroopCarrier t= GetFirst();
				// do something with t
			}
		}

Replace Error Code with Exception (page 310)

		// "Problem: A method returns a special code to indicate an error. 
		// Solution: Throw an exception instead." 
		
		// BEFORE
		// ------
		class Engine
		{
			// fields + methods
			public void Start(){ /* do something */ }
		}
		class ZeroEnergyConceptSpaceMachine
		{
			Engine engine=null;
			public Int32 StartEngine()
			{
				// engine should have been installed before here
				if (engine == null)
					return -1;
				engine.Start();
				return 1;
			}
		}
				
		// AFTER
		// -----
		class EngineException : Exception
		{
			public EngineException(String message): base(message)
			{
			}
		}
		
		class ZeroEnergyConceptSpaceMachine2
		{
			Engine engine=null;
			public void StartEngine()
			{
				if (engine == null)
					throw new EngineException("engine should have been installed before here");
				engine.Start();
			}
		}

Replace Exception with Test (page 315)

		// "Problem: You are throwing a checked exception on a condition the caller could have checked first. 
		// Solution: Change the caller to make the test first." 
		// Note: File IO is a classic case where exceptions are definitely not recommended at EOF. 
		// This condition will always happen in teh course of normal operation, and hence the caller
		// should be checking the return value against an EOF constant, not expecting an exception. 
		
		// BEFORE
		// ------
		class DiskManager
		{
			static public Int32 AvailableBytes(){/* do disk sector buffering etc. */ return 10;}
			static public Int32 ReadBytes(Byte[] data, Int32 offset, Int32 count){ return 0; }
		}
		class File
		{
			// exceptions should be reserved for genuine error conditions
			// by using an if statement, we can often avoid the exception
			public Int32 Read(Byte[] buffer, Int32 offset, Int32 count)
			{
				Int32 availableBytes = DiskManager.AvailableBytes();
				if (availableBytes == 0)
					throw new Exception("End Of File");
				Int32 bytesToRead = (availableBytes > count) ? count : availableBytes;
				DiskManager.ReadBytes(buffer, offset, availableBytes);
				return bytesToRead;
			}
		}
		// AFTER
		// -----
		class File2
		{
			public const Int32 EOF = -1;
			public Int32 Read(Byte[] buffer, Int32 offset, Int32 count)
			{
				Int32 availableBytes = DiskManager.AvailableBytes();
				if (availableBytes == 0) return EOF;
				Int32 bytesToRead = (availableBytes > count) ? count : availableBytes;
				DiskManager.ReadBytes(buffer, offset, availableBytes);
				return bytesToRead;
			}
		}

Dealing with Generalization

Pull Up Field (page 320)
Pull Up Method (page 322)
Pull Up Constructor Body (page 325)
Push Down Method (328)
Push Down Field (page 329)
Extract Subclass (page 330)
Extract Superclass (page 336)
Extract Interface (page 341)
Collapse Hierarchy (page 344)
Form Template Method (page 345)
Replace Inheritance with Delegation (page 352)
Replace Delegation with Inheritance (page 355)

Pull Up Field (page 320)

		// "Problem: Two subclasses have the same field. 
		// Solution: Move the field to the superclass." 
		
		// BEFORE
		// ------
		class Movie
		{
			String title=null;
			public override String ToString()
			{
				return "title = " + title;
			}
		}
		class SciFi : Movie
		{
			Int32 duration=0;
			String jetPropulsionSystem="StringTheory";
			public override String ToString()
			{
				return "duration = " + duration + "propulsion = " + jetPropulsionSystem;
			}
		}
		class Historical : Movie
		{
			Int32 duration=100;
			Boolean isBC=true;
			public override String ToString()
			{
				return "duration = " + duration + "Set in a year Before Christ (BC) = " + isBC.ToString();
			}
		}
				
		// AFTER
		// -----
		class Movie2
		{
			String title="The Day After Tomorrow";
			Int32 duration=10;
			public override String ToString()
			{
				return "title = " + title + "duration = " + duration;
			}
		}
		class SciFi2 : Movie2
		{
			String jetPropulsionSystem="ZeroPointEnergy";
			public override String ToString()
			{
				return "propulsion = " + jetPropulsionSystem;
			}
		}
		class Historical2 : Movie2
		{
			Boolean isBC=true;
			public override String ToString()
			{
				return "Set in a year Before Christ 9BC) = " + isBC.ToString();
			}
		}

Pull Up Method (page 322)

		// "Problem: You have methods with identical results on subclasses. 
		// Solution: Move them to the superclass." 
		
		// BEFORE
		// ------
		class Movie3
		{
			String title="Intermission";
			protected Int32 duration=120;
			public override String ToString()
			{
				return "title = " + title + "duration = " + duration;
			}
		}
		class SciFi3 : Movie3
		{
			String jetPropulsionSystem="NuclearFusion";
			public void DisplayDuration()
			{
				Console.WriteLine("Duration = " + duration);
			}
			public override String ToString()
			{
				return "propulsion = " + jetPropulsionSystem;
			}
		}
		class Historical3 : Movie3
		{
			Boolean isBC=true;
			public void DisplayDuration()
			{
				Console.WriteLine("Duration = " + duration);
			}
			public override String ToString()
			{
				return "Set in a year Before Christ (BC) = " + isBC.ToString();
			}
		}
		
		// AFTER
		// -----
		class Movie4
		{
			String title="Alexandar";
			Int32 duration=203;
			public void DisplayDuration()
			{
				Console.WriteLine("Duration = " + duration);
			}
			public override String ToString()
			{
				return "title = " + title + "duration = " + duration;
			}
		}
		class SciFi4 : Movie4
		{
			String jetPropulsionSystem="TopSecret";
			public override String ToString()
			{
				return "propulsion = " + jetPropulsionSystem;
			}
		}
		class Historical4 : Movie4
		{
			Boolean isBC=true;
			public override String ToString()
			{
				return "Set in a year Before Christ (BC) = " + isBC.ToString();
			}
		}

Pull Up Constructor Body (page 325)

		// "Problem: You have constructors on subclasses with mostly identical bodies. 
		// Solution: Create a superclass constructor, call this from the subclass method." 
		
		// BEFORE
		// ------
		class Clock
		{
			protected Int32 hours;
			protected Int32 minutes;
		}
		class DigitalClock : Clock
		{
			Boolean display24Hours;
			public DigitalClock(Int32 hours, Int32 minutes, Boolean display24Hours)
			{
				this.hours = hours; this.minutes = minutes; this.display24Hours = display24Hours;
				DisplayWhetherDuringRegularOpeningHours();
			}
			void DisplayWhetherDuringRegularOpeningHours()
			{
				Int32 openingTime = 8;
				Int32 closingTime = 20;
				if (hours > openingTime && hours < closingTime)
					Console.WriteLine("Shop is open");
				else
					Console.WriteLine("Shop is closed");
			}
		}
				
		// AFTER
		// -----
		class Clock2
		{
			protected Int32 hours;
			protected Int32 minutes;
			public Clock2(Int32 hours, Int32 minutes)
			{
				this.hours = hours; this.minutes = minutes; 
			}
			protected void DisplayWhetherDuringRegularOpeningHours()
			{
				Int32 openingTime = 8;
				Int32 closingTime = 20;
				if (hours > openingTime && hours < closingTime)
					Console.WriteLine("Shop is open");
				else
					Console.WriteLine("Shop is closed");
			}
		}
		class DigitalClock2 : Clock2
		{
			Boolean display24Hours;
			public DigitalClock2(Int32 hours, Int32 minutes, Boolean display24Hours)
				: base(hours, minutes)
			{
				this.display24Hours = display24Hours;
				DisplayWhetherDuringRegularOpeningHours();
			}
		}

Push Down Method (328)

		// "Problem: Behaviour on a superclass is relevant only for some of its subclasses. 
		// Solution: Move it to those subclasses." 
		
		// BEFORE
		// ------
		class Movie5
		{
			public void StartPropulsionEngine(){}
		}
		class SciFi5 : Movie5
		{
		}
		class Historical5 : Movie5
		{
		}
		// AFTER
		// -----
		class Movie6
		{
		}
		class SciFi6 : Movie6
		{
			public void StartPropulsionEngine(){}
		}
		class Historical6 : Movie6
		{
		}

Push Down Field (page 329)

		// "Problem: A field is used only by some subclasses. 
		// Solution: Move the field to those subclasses." 
		
		// BEFORE
		// ------
		class Movie7
		{
			String jetPropulsionSystem="ZeroPointEnergy";
			public override string ToString()
			{
				return jetPropulsionSystem;
			}
		}
		class SciFi7 : Movie7
		{
		}
		class Historical7 : Movie7
		{
		}
				
		// AFTER
		// -----
		class Movie8
		{
		}
		class SciFi8 : Movie8
		{
			String jetPropulsionSystem="ZeroPointEnergy";
			public override string ToString()
			{
				return jetPropulsionSystem;
			}
		}
		class Historical8 : Movie8
		{
		}

Extract Subclass (page 330)

		// "Problem: A class has features that are used only in some instances. 
		// Solution: Create a subclass for that subset of features." 
		
		// BEFORE
		// ------
		class Movie9
		{
			// fields + methods common to all movices
			// ...
 
			// field+method specific to one type of movie
			String jetPropulsionSystem="ZeroPointEnergy";
			public override string ToString()
			{
				return jetPropulsionSystem;
			}
		}
				
		// AFTER
		// -----
		class Movie10
		{
			// fields + methods common to all movices
			// ...
		}
		class SciFi10 : Movie10
		{
			// put fields+methods specific to one type of 
			// movie into a subclass
			String jetPropulsionSystem="ZeroPointEnergy";
			public override string ToString()
			{
				return jetPropulsionSystem;
			}
		}

Extract Superclass (page 336)

		// "Problem: You have two classes with similar features. 
		// Solution: Create a superclass and move the common features to the superclass." 
		
		// BEFORE
		// ------
		class Apple
		{
			String color=null;
			override public String ToString(){return color;}
		}
		class Orange
		{
			String color=null;
			override public String ToString(){return color;}
		}
				
		// AFTER
		// -----
		class Fruit
		{
			String color=null;
			override public String ToString(){return color;}
		}
		class Apple2 : Fruit
		{
		}
		class Orange2 : Fruit
		{
		}

Extract Interface (page 341)

		// "Problem: Several clients use the same subset of a class' interface, or two classes have part of their interface in common. 
		// Solution: Extract the subset into an interface." 
		
		// BEFORE
		// ------
		class Bike
		{
			public void Start(){}
			public void Stop(){}
			public void TurnCorner(){}
		}
		class Skateboard
		{
			public void Start(){}
			public void Stop(){}
			public void TurnCorner(){}
		}	
		// AFTER
		// -----
		interface IModeOfTransport
		{
			void Start();
			void Stop();
			void TurnCorner();
		}
		class Bike2 : IModeOfTransport
		{
			public void Start(){}
			public void Stop(){}
			public void TurnCorner(){}
		}
		class Skateboard2 : IModeOfTransport
		{
			public void Start(){}
			public void Stop(){}
			public void TurnCorner(){}
		}

Collapse Hierarchy (page 344)

		// "Problem: A superclass and subclass are not very different. 
		// Solution: Merge them together." 
		
		// BEFORE
		// ------
		class Worker
		{
		}
		class DiligentWorker : Worker
		{
			DiligentWorker()
			{
			}
		}
				
		// AFTER
		// -----
		class Worker2
		{
			Boolean isDiligent;
			Worker2 (Boolean isDiligent)
			{
				this.isDiligent = isDiligent;
			}
		}

Form Template Method (page 345)

		// "Problem: You have two methods in subclasses that perform similar steps in the same order; yet the steps are different. 
		// Solution: Get the steps into methods with the same signature, so that the original methods become the same. 
		// Then you can pull them up." 
		
		// BEFORE
		// ------
		class House
		{
			protected String color="red";
		}
		class SuburbanHouse : House
		{
			Int32 groundFloorSize;
			Int32 firstFloorSize;
			SuburbanHouse(Int32 groundFloorSize, Int32 firstFloorSize)
			{
				this.groundFloorSize = groundFloorSize;
				this.firstFloorSize = firstFloorSize;
			}
			public void DisplayDetails()
			{
				Int32 area = groundFloorSize + firstFloorSize;
				Console.WriteLine("area = " + area  + "color = " + color);
			}
		}
		class BoatHouse : House
		{
			Int32 wheelHouseArea;
			Int32 exposedDeckArea;
			Int32 belowDeckArea;
			
			public BoatHouse(Int32 wheelHouseArea, Int32 exposedDeckArea, Int32 belowDeckArea)
			{
				this.wheelHouseArea = wheelHouseArea;
				this.exposedDeckArea = exposedDeckArea;
				this.belowDeckArea = belowDeckArea;
			}
			
			public void DisplayDetails()
			{
				Int32 area = wheelHouseArea + belowDeckArea + exposedDeckArea /2; //assume we only count half of exposed deck area
				Console.WriteLine("area = " + area  + "color = " + color);
			}
		}
				
		// AFTER
		// -----
		abstract class House2
		{
			protected String color="red";
			public abstract Int32 CalculateArea();
			public void DisplayDetails()
			{
				Int32 area = CalculateArea();
				Console.WriteLine("area = " + area  + "color = " + color);
			}
		}
		class SuburbanHouse2 : House2
		{
			Int32 groundFloorSize;
			Int32 firstFloorSize;
			SuburbanHouse2(Int32 groundFloorSize, Int32 firstFloorSize)
			{
				this.groundFloorSize = groundFloorSize;
				this.firstFloorSize = firstFloorSize;
			}
			override public Int32 CalculateArea()
			{
				return groundFloorSize + firstFloorSize;
			}
		}
		class BoatHouse2 : House2
		{
			Int32 wheelHouseArea;
			Int32 exposedDeckArea;
			Int32 belowDeckArea;
			
			public BoatHouse2(Int32 wheelHouseArea, Int32 exposedDeckArea, Int32 belowDeckArea)
			{
				this.wheelHouseArea = wheelHouseArea;
				this.exposedDeckArea = exposedDeckArea;
				this.belowDeckArea = belowDeckArea;
			}
			
			override public Int32 CalculateArea()
			{
				return wheelHouseArea + belowDeckArea + exposedDeckArea /2;
			}
		}

Replace Inheritance with Delegation (page 352)

		// "Problem: A subclass uses only part of a superclass' interface or does not want to inherit data. 
		// Solution: Create a field for a method for the superclass, adjust methods to delegate to the superclass, 
		// and remove the subclassing." 
		
		// BEFORE
		// ------
		class ModeOfTransport
		{
			public String metalWorkDescription(){return "steel";}
			Int32 costPerKilometer;
			Int32 kilometersPerHour; 
			public ModeOfTransport(Int32 costPerKilometer, Int32 kilometersPerHour)
			{
				this.costPerKilometer = costPerKilometer;
				this.kilometersPerHour = kilometersPerHour;
			}
			public Int32 OperatingCostsPerHour()
			{
				return costPerKilometer * kilometersPerHour;
			}
		}
		class MyOwnTwoFeet : ModeOfTransport
		{
			// shoe-specific fields + methods
			public MyOwnTwoFeet(Int32 costPerKilometer, Int32 kilometersPerHour): base(costPerKilometer, kilometersPerHour) {}
			// note:MyOwnTwoFeet is a healthy mode of transport, and some fields (e.g. kilometersPerHour) and 
			// methods (OperatingCostsPerHour) from the superclass are applicable but others 
			// (metalWorkDescription) simply do not make sense. 
		}
				
		// AFTER
		// -----
		class MyOwnTwoFeet2 // Note: no inheritance!
		{
			// shoe-specific fields + methods
			ModeOfTransport modeOfTransport = new ModeOfTransport(20, 10);
			public Int32 OperatingCostsPerHour()
			{
				return modeOfTransport.OperatingCostsPerHour();
			}
		}	
		// another solution might be to use Extract Interface and re-arrange the hierarchy

Replace Delegation with Inheritance (page 355)

		// "Problem: You're using delegation and are often writing many simple delegations for the entire interface. 
		// Solution: Make the delegating class a subclass of the delegate." 
		
		// BEFORE
		// ------
		class Uri
		{
			String resource;
			public Uri(String resource)
			{
				this.resource = resource;
			}
			
			public String GetAuthority(){/* parse */ return null;}
			public String GetHost(){/* parse */ return null;}
			public String GetPort(){/* parse */ return null;}
		}
		class MailToUri
		{
			Uri localUri = null;
			MailToUri(String resource)
			{
				localUri = new Uri(resource);
			}
			// many methods are delegating to Uri class
			public String GetAuthority(){return localUri.GetAuthority();}
			public String GetHost(){return localUri.GetHost();}
			public String GetPort(){return localUri.GetPort();}
			public void SendEMail(String subject, String message){/*send email*/}
		}
				
		// AFTER
		// -----
		class MailToUri2 : Uri
		{
			MailToUri2(String resource) : base (resource)
			{
			}
			public void SendEMail(String subject, String message){/*send email*/}
		}

Big Refactorings

// Big refactorings can be considered the point where changes to the
// code expand from simple localised alterations to more significant
// changes to the architecture of the application.

Tease Apart Inheritance (page 362)
Convert Procedural Design To Objects (page 368)
Separate Domain From Presentation (370)
Extract Hierarchy (page 375)

Tease Apart Inheritance (page 362)

		// "Problem: You have an inheritance hierarchy that is doing two jobs at once. 
		// Solution: Create two hierarchies and use delegation to invoke one 
		// from the other." 
		// 
		// Our commentary
		// Though inheritance hierarchies often start out with a well-defined 
		// purpose, over time they can accumulate disparate tasks, and it 
		// becomes clear that they do not all need to be part of the same 
		// hierarchy. By separating them out, we have smaller hierarchies that
		// more focused and that are much easier to evolve at their own pace 
		// into the future. Also, calling code can use one but not the other
		// hierarchy when needed.  
		// When designing hierarchies, do judiciously use both interface and 
		// implementation inheritance. .NET does support multiple interface 
		// inheritance but not support multiple implementation inheritance 
		// (neither in .NET v1.1 not .NET v2.0). When an object needs to 
		//  expose multiple behaviours, then interfaces are a good option. 
		// When there may be multiple types of base classes, then interfaces
		// provided the needed flexibility. Also consider the use of 
		// delegates. Framework designers should be very cautious about 
		// mandating specific base classes – a base interface is often 
		// more appropriate. The framework can (and often should) provide
		// a default implementation class for interfaces. Finally, pay 
		// attention to versioning issues with .NET interfaces. 
 

Convert Procedural Design To Objects (page 368)

		// "Problem: You have code written in a procedural style. 
		// Solution: Turn the data records into objects, break up the behaviour, 
		// and move the behaviour to the objects." 
		//
		// Our commentary
		// Procedural coding consists of long intertwined methods, with data 
		// and behaviour spread everywhere. It is a style of programming that
		// exhibit brittleness in large projects. Such code is very difficult
		// to maintain and to evolve. Ultimately it leads to a re-write. It has
		// gone out of fashion for modern programming, but you may still 
		// encounter it in old code and unfortunately all to often in recent 
		// code that was developed without enough attention having being paid
		// to object concepts. Excuses range from the developers being in too 
		// much of a hurry (but it takes longer!) to not having a solid 
		// understanding of OO. Often this code grew over several iterations, 
		// and now is much longer than original.
		// When confronted with procedural coding, you need to convert it to 
		// objects. You can start by creating data objects. These are objects 
		// that store and provide protected access to data items. (Sometimes 
		// this will be your starting point, as intermediate OO developers at
		// least got this part right). 
		// Your next step is assuring behaviour is where it should be. If you
		// have objects that merely store data, but does not expose methods 
		// that operate on that data, you need to ask where is that data 
		// manipulated. A golden rule is that data and the behaviour that 
		// operates on it should become co-located in the same objects as 
		// much as possible. If behaviours need to talk a lot with a 
		// particular piece of data, that that combination is a good 
		// candidate for an object. 

Separate Domain From Presentation (370)

		// "Problem: You have GUI classes than contain domain logic. 
		// Solution: Separate the domain logic into separate domain classes." 
		//
		// Our commentary:
		// For non-trivial projects, it is advisable to separate the user 
		// interface from the core logic. Working against this are wizards 
		// in the development environment, that make it seemingly so easy to 
		// directly hook up between UI controls and data. However, this leads
		// to inflexibility and problems in the longer term. Separation brings
		// a number of advantages:
		// * Developers with the appropriate skills can can work on the 
		// different sections - someone skilled in UI user interface design 
		// skills and a different person skilled in the domain logic 
		// * Developers can work in parallel
		// * The domain logic and UI code will change at a different pace 
		// (the user interface will need to be updated often, whereas the 
		// domain code should be more stable)
		// * The test harness needed for each type of functionality is different
		// * There may be a single implementation of the domain logic, but 
		// multiple implementations of the user interface (ASP.NET, Longhorn’s
		// “Avalon”, WinForms, MONO’s Gtk#)
		// * Allows non-UI access to logic (e.g. via web service)

Extract Hierarchy (page 375)

		// "Problem: You have a class that is doing too much work, at least in 
		// part through many conditional statements. 
		// Solution: Create a hierarchy of classes in which each subclass 
		// represents a special case." 
		// 
		// Our commentary:
		// We use the term “octopus class” to identify the root of this problem.
		// When we spot a class that has its tentacles going all over the place
		// it is clear that it is ripe for refactoring.  
		// A method in a class with a large switch statements often indicate a 
		// hierarchy that needs to surface as classes. If multiple methods in 
		// the same class each have large switch statements, with the same, or 
		// almost the same, list of conditionals are present, this is especially
		// so. Another telling sign is to see widely different functionality
		// appear within the same class. The class simply looks cluttered. 
		// Such classes are often found at high-throughput junction-points – 
		// places in the code which are traversed very often, and it is just 
		// expedient to place new functionality there during a rush to meet 
		// a deadline. Later upon reflection, it is clear that we really need
		// to rebalance the architecture – by teasing out the independent 
		// classes and working on the optimum hierarchy. Each class should 
		// be small and focused on provides a largely independent set of 
		// services.