Archive for August 29th, 2008
-
Extract Class & the Single Responsibility Principle
Last week we talked about Extract Method and why it is so important to know and love. This week, we are going to discuss another very important principle in object-oriented design and how Extract Class can help us build and maintain better code.
If you are familiar with Robert Martin’s book Agile Software Development: Principles, Patterns and Practices, you will recall he recast a very powerful concept (the Single-Responsiblity Principle or SRP) know from the “old days”, aka 1979,: a class should have one, and only one, reason to change. Or as I like to add my own spin to it: a class should only do one thing. The reasoning behind the SRP is if your class has two responsibilities, invariably they become coupled (coupled code == bad) and changes in one will impair or inhibit the ability of the class to meet the other responsibilities – and this is only in the case where you have just two responsibilities. Imagine the confusion when we have three or four responsibilities in a single class!!!
If SRP is so important, then why are talking about Extract Class refactoring? This is the refactoring you use when you want to apply the SRP and applying the SRP is key to writing good code, i.e. code that is testable, decoupled, maintainable, etc., etc.
How Do I Find It?: You have one class doing the work that should be done by two.
What Do I Do Once I Find It?: Create a new class and move the relevant fields and methods from the old class into the new class.
Any guidelines you care to share? I am glad that you asked because I do have a few tell tale signs that a new class is waiting to bust out of your old one:
- Find your big classes -> any class with more than a 1000 lines is probably doing more than one thing.
- Classes that have “too many” methods or fields\properties -> if class has more than 10 to 15 methods or fields\properties, you are probably missing an abstraction.
- Methods that don’t belong -> every class has a reason for existence, or a theme, that unifies the method and data. Methods or data that don’t “fit in” with the theme are likely candidates for a new class.
In an application I am working on, we have a real simple Bus class that shepherds messages between simulated hardware and simulated devices (in our case we are talking about drawers, buttons, LED, etc.). When you examine the class you see it is about 250 lines, has three fields, a number of events around connecting and disconnecting devices and some private methods. Looking further, you can find two methods which stick out and don’t match the theme of the class:
45 private IBusMessage BytesToBusMessage(byte[] bytes) 46 { 47 // convert to string 48 string msg = Encoding.ASCII.GetString(bytes, 0, bytes.Length); 49 // split the msg into address and actual command 50 string[] splits = msg.Split(new char[] { '|' }); 51 BusMessage message = new BusMessage(); 52 message.Address = long.Parse(splits[0]); 53 message.Message = splits[1]; 54 if (splits.Length > 2) 55 { 56 message.SequenceNumber = int.Parse(splits[2]); 57 } 58 return message; 59 } 60 61 public static byte[] BusMessageToBytes(IBusMessage message) 62 { 63 // form the message 64 string msg = message.Address + "|" + message.Message + "|" + message.SequenceNumber; 65 return Encoding.ASCII.GetBytes(msg); 66 } 67So we have a class which is responsible for event registration AND parsing messages. My question is this: why in the world does a class which mostly deals with event registration have anything to do with parsing? Why would this class even care how we parse messages back-and-forth? It sounds like a class doing more than one thing – that is a violation of the SRP – and we will use Extract Class to apply the SRP to Bus.
Next week, we will talk about the Move Method refactoring, which is how you extract your class from the old one.
Frequent Topics
Agile Agile SD Certified ScrumMaster Coaching Collaboration Communication Conferences Daily Scrum Design Excellence Design for Six Sigma Extreme Programming Games Innovation Games Lean Legacy Code Links of the Week Measures Movies Pair Programming Personal Planning PMI Practices Presentations Product Owner Quality Refactoring Retrospectives Rugby Scrum ScrumMaster SIMSOC Spain Team Test-Driven Development Testing Tools Training Transitions Travel Voice of the Customer
Calendar
Recent Comments
- Kenneth van Rumste on Scrum Roles Defined
- Carlton on Scrum Roles Defined
- Kenneth van Rumste on Scrum Roles Defined
User Groups
Archives
- May 2011 (1)
- February 2011 (1)
- January 2011 (5)
- November 2010 (3)
- October 2010 (6)
- September 2010 (5)
- August 2010 (4)
- July 2010 (6)
- June 2010 (2)
- May 2010 (2)
- April 2010 (5)
- March 2010 (3)
- February 2010 (5)
- January 2010 (7)
- December 2009 (8)
- November 2009 (2)
- October 2009 (6)
- September 2009 (9)
- August 2009 (7)
- July 2009 (4)
- June 2009 (3)
- May 2009 (3)
- April 2009 (5)
- March 2009 (6)
- February 2009 (6)
- January 2009 (7)
- December 2008 (10)
- November 2008 (11)
- October 2008 (10)
- September 2008 (4)
- August 2008 (5)
- July 2008 (5)
- June 2008 (8)
- May 2008 (5)
- April 2008 (3)
