Showing posts with label toilet paper. Show all posts
Showing posts with label toilet paper. Show all posts

Friday, January 09, 2009

The Toilet Paper (Installment 25): Single-Responsibility Principle (SOLID, part 2)

A class should have exactly one reason to change

The Single-Responsibility Principle (SRP) helps you create classes that are resilient in the face of requirements changes. Put more simply, the SRP guides you in creating individual classes that are highly focused on a single implementation concept, so that each individual class is less likely to be affected by each requirements change. Each class is very limited in what it knows how to do and what it knows about, so an individual requirement change is less likely to affect that class. As a result, classes that change less often and accumulate less code are less likely to accumulate bugs as well. They can be tested thoroughly and raise the overall quality of your application.

Let's look at an example. Suppose we have a Product class that models information and behavior associated with some widget we're selling. It might look something like this:
public class Product {
public String Name { get; private set; }
public String Sku { get; private set; }
public Money ShippingCharges(Destination dest) {…}
public Money CalculateDiscount(Contract contract){…}
}
Assuming that the implementations of how to calculate shipping charges and discounts are inside both of those methods, this class clearly has multiple responsibilities – three, in fact. First, it models a product, which has properties, shipping charges and discounts. But this class also charges shipping and calculates discounts. This may not seem that important, but it means that this particular class is harder to understand and changes more often than would otherwise be necessary. The biggest shortcoming, however, is that the logic for these calculations is hidden inside the Product class, making these non-trivial bits of code harder to find and harder to test independently.

To solve this, refactor this class so that it delegates the responsibility of how doing the calculations are done to two other, more specialized classes, such as ShippingChargeCalculator and PriceDiscounter. That would leave you with three classes, each of which has one reason to change, decreasing the complexity of the system and increasing maintainability, flexibility, and testability.

You can find much more on the SRP on Google. Try searching for "ActiveRecord Single-Responsibility Principle" for hours of enjoyment!

Tuesday, October 07, 2008

Finally-close your resources

You are a java programmer. Do you read from databases? Perhaps you write to files? If you aren't careful, you might be creating memory leaks and inadvertently leaving database connections open. Java is notorious for making simple things like file i/o complicated. Consider the try-catch block inside the finally block, which is necessary because the close() method throws an IOException; what is an application programmer supposed to do if the operating system won't allow him to close an open file? Witness the following code:

1 myFile.open();
2 contents = myFile.readContents();
3 myFile.close();
If an exception occurs while reading the file's contents on line 2, your program will skip over line 3 where the file is closed, as the exception interrupts normal execution flow and propagates up the stack, leaving the file ambiguously open. Fortunately, you can invoke this simple solution. Behold:
1 File file = new
File("/shared/home/richard.green/.bashrc");
2 BufferedReader reader = null;
try {
reader = new BufferedReader( new FileReader(file) );
String line = reader.readLine();
// Deal with line
}
catch (IOException e){
// Deal with exception ...
}
finally {
try {
reader.close();
} catch (IOException e) { /* ignored */ }
}
When execution leaves the try block (line 3), code inside the finally block (line 5) is executed under any circumstance. Therefore, in the above solution, if an exception occurs while reading the file's contents on line 3, the file will still be closed on line 5 before the exception propagates up the stack.

Frameworks like Commons IO from the Apache group ( http://commons/apache.org/io) take much of the pain out of dealing with Java I/O. Commons IO provides variety of utility classes which safely implement common I/O operations without dealing with the ugly Java Reader/Stream/Exception semantics.

Resource leaks due to exceptions are a problem in more-or-less every programming language. Each language has its own idioms for dealing with them. C++ coders wrap resources in their own classes and use the language's constructor-destructor semantics to allocate and de-allocate the resource. In Ruby, you use the IO::open method with a block; this automatically closes the resource when the block ends. Familiarize yourself with these idioms as part of learning a new language.

Tuesday, September 23, 2008

Standups and communication

Communication is the first core value of XP. So how does your team communicate with each other? How well do you do it?

One way that our development teams communicate is via daily standup meetings. But what is a standup meeting, anyway? How about this definition: a self-organizing daily gathering to gain shared understanding of the state of our team, focus our day and remind ourselves that we're all in this together. As one comment on Ward Cunningham's wiki puts it, "Our aim is modest: to identify short-term obstacles. The agenda is minimalist: What does the day look like?" Some teams eschew standups because they’re not helpful; perhaps understanding the objectives can help you reshape your standup. How do you know if your standup meetings are effective? Here are some possible outcomes:
  • Everyone knows what he or she is going to do -- and with whom -- as soon as the standup ends (rather than finding a pair partner or figuring out what to do after the meeting ends).
  • Everyone understands where the team is on all the stories -- if an outsider were to ask you about any story, you could answer (rather than merely “the story I'm working on”).
  • Everyone knows high-level problems facing the team for the day (rather than not knowing).
  • Everyone has a sense of how complete the iteration is, and what needs to be done to "make it" (rather than being surprised on the last day).
  • The team has decided to have breakout meetings to resolve specific problems (rather than try to solve bigger problems in the standup).
  • Everyone knows what the team is pledging to accomplish for the day (rather than being unfocused).
If you're not accomplishing these, check out the standups article on Martin Fowler's site, which provides useful patterns and identifies "smells" for standups. Now for some best practices that we’ve seen around Asynchrony:
  • Prompt start: The way a team starts its standup is indicative of the way the day will go; when everyone arrives on-time (or, heaven forbid, a minute early!) the meeting tends to have a snappier pace. Use a fun disincentive to cut down on lateness (e.g., tardy MFKR team members having to wear a PPE jumpsuit).
  • Story-based: Rather than focusing on individual check-ins, the team talks about its progress in terms of stories. Facing the story posters on the board, the team talks about the unfinished stories in order of priority and how to complete them. The team can set a goal by determining which stories it will attempt to finish that day.
  • Know what’s next: Before the standup meeting is over, know who your pair partner is (consult the pairing chart for help) and what task you’re going to work on, and go to it.