Quantity vs Quality Dichotomy

I have been following Simple Programmer for a few months now, and he recently posted a vlog entitled Quantity vs Quality is an Illusion.  This got me thinking about my beliefs on this subject.

Practice makes perfect, right?

That depends on how you are practicing.  Let’s take a look at the following two stories to illustrate my point.

Blind Repetition and the Pie Maker

Let’s take a look at Joe.  Joe is a pie maker.  He decided to open up a shop selling pies and gets up every morning and makes 10 apple pies.  Joe doesn’t taste the pies, he simply ships them off to some remote part of the world and gets the money.  Joe has no way to get feedback on the quality of his pies, but he stays in business by shipping them off to the pie-less scientists of Antarctica.

As Joe continues to make more pies, he may become more and more efficient at making pies as the movements become second nature, but his first pie is no different than his 100th which is no different than his 100,000th.

Deliberate Practice and the Pie Maker

Now, let’s meet Jane.  Jane is also a pie maker.  She decided to open up a shop selling pies and gets up every morning and makes 10 apple pies.  Jane tries a slice of one of the pies every morning to make sure they are coming out good.  She also asks her customers to give her feedback on her pies.

Jane takes the feedback from her tastings and from her customers and tweaks the recipe. She repeats this process over and over.

As Jane continues to make more pies, she may become more efficient at making pies as the movements become second nature.  Her 100th pie is certainly better than her first, and her 100,000th pie is even better.

As you can see, Jane’s work quality is improving and Joe’s is not.  Jane is looking at what she has done and trying new things in order to make her pies better and better.  Joe may be getting faster, and will likely have improved his speed more than Jane, but that is not the same thing as quality.

Programmer practice

A lot of people have been pushing the idea of code katas, or koans for a while now. While I haven’t taken the time to do any of these (I know, shame on me), I can see a lot of value in them.

These exercises are small problems that we should be able to solve in a couple of hours time.  After completing the exercise, you should take time to reflect on what worked well, and what didn’t.  Think about how you could have solved it differently, and then throw it all away.

Doing these exercises help build up our level of expertise and can make some things become second nature (thus increasing our speed).  Some studies suggest that it takes 10,000 hours of practice (deliberate practice) to become an expert.  Doing these allows us to get more time in toward that, and allows us to try out some new technologies that we don’t dare try in production!

Pushing quantity impacts quality

I agree, that as we practice a skill, be it a knowledge skill or a manual skill, we will get faster at it.  Our quantity will go up and our quality can stay the same, or even improve.  This takes time.

However, I believe that when we are pushed to do something faster than normal, quality will suffer.  We will pay less attention to the small details, less time polishing that new feature, less time testing the edge cases, less time thinking about side effects.

There will be times when we are pushed to do things more quickly than we would like.  When that happens, we should have a serious discussion with the business to understand what the minimal feature set needs to be.  It is our responsibility, as professionals, to ensure that the business understands the cost of doing things more quickly, and try to negotiate some time after the release to go back and ensure that the corners that were cut are repaired before moving forward.

Improving Code Quality: Quick Tip – April 17, 2015

I am starting a series of quick tips that I hope to publish weekly.  These are intended to be very short posts giving you some quick advice.

Commented out code

First of all, don’t do it.  If you have a bit of dead code, delete it.  If you are using source control (and you should…I’ll have a post about that later), you can always go back in time and get that code back.

If you find some commented out code, delete it.

Commented out code is dead code.  It does nothing for the program, and is harmful to developers.  It only serves to clutter the file and make it harder to read the code.  Or, even worse, it tempts other developers to reuse that code for other things (that it may not have originally been intended for).

If you need that functionality again, I suggest rewriting it.  We are all getting better (or should be) as we continue our careers, so you can probably write it better the second time anyway.

 

Loose coupling

When I first started learning about object oriented programming, and really digging into the best practices, loose coupling and high cohesion kept cropping up.  I had a hard time trying to keep them straight and remember which one I wanted more of and which one I wanted to reduce.  My biggest difficulty was I couldn’t keep the definitions of coupling vs cohesion straight!

Coupling refers to how much a set of classes rely on one another.  If we have two classes, A and B that each use methods from the other, these classes would be tightly coupled.  If we have those same two classes and only one needs methods from the other, then those are more loosely coupled.

The little metal ends on a garden hose that you can twist together are called couplings.  You use them to join two pieces of hose together.  I like to use this to help me remember that coupling is about how two (or more) classes interact with one another.

Cohesion refers to how much the methods in a particular class belong together.  For example, let’s say we have a class representing a soup can.  The soup can should know about how big it is, what it is made out of, what shape it is and what color it is.  If we start adding information about the soup that is stored inside the can, then we are breaking the cohesion.  Information about the soup is not important to the actual can.  The information about the soup should be contained in a separate class that the can could know about.

Thinking about a cohesive group of people helps me remember what this means.  A cohesive group of people are people that work very well together and really seem to belong together, much the same way as a cohesive class design has methods that really belong together.

Loose Coupling

Today we are only going to talk about coupling.  We will save the discussion about cohesion for another day.

Now that we know that coupling refers to how much classes know about each other, let’s dive into why we want loose coupling in the first place.  Why do we want our classes to know as little as possible about each other?

Let’s pretend for a moment that we are trying to capture, in code, a peanut butter sandwich.  The simplest way to represent this would be to have a Sandwich class that contains an instance of a CreamyPeanutButter class and two instances of Bread.

public class CreamyPeanutButter {
    private int amount;
    public CreamyPeanutButter(int amount) {
        this.amount = amount;
    }
}

public class Bread {
    private CreamyPeanutButter creamyPeanutButter;
    public void addPeanutButter(int amount) {
        creamyPeanutButter = new CreamyPeanutButter(amount);
    }
}

This is very straightforward, right?  Now, let’s add a new type of peanut butter into the mix.  CrunchyPeanutButter.  We want to be able to add either Creamy or Crunch peanut butter to our sandwich.  One way to accomplish this might look something like this:

public class CreamyPeanutButter {
    private int amount;
    public CreamyPeanutButter(int amount) {
        this.amount = amount;
    }
}

public class CrunchyPeanutButter {
    private int amount;
    public CrunchyPeanutButter(int amount) {
        this.amount = amount;
    }
}

public class Bread {
    private CreamyPeanutButter creamyPeanutButter;
    private CrunchPeanutButter crunchyPeanutButter;
    public void addPeanutButter(String type, int amount) {
        if ("creamy".equals(type)) {
            creamyPeanutButter = new CreamyPeanutButter(amount);
        } else if ("crunchy".equals(type)) {
            crunchyPeanutButter = new CrunchyPeanutButter(amount);
        }
    }
}

If you compare our new Bread class to our previous one, you can see that the new one is a lot more complex, and really has to understand a lot about peanut butter.  This is a code smell telling us that these two classes are too tightly coupled.  Bread should know about bread, and not about peanut butter if it can avoid it.

What can we do?

The code above has a lot of code smells.  The first one, I noted above, was that any change to add a new type of peanut butter, or change the peanut butter classes is going to cause us to have to change our bread class.  This is what tight coupling does, and what we want to avoid.

Another code smell, however, is the duplicated code between the two peanut butter classes, they both have the same constructor.  We could remedy this by creating an ancestor that they inherit from.  This step will also allow us some additional refactorings on our Bread class.

public abstract class PeanutButter {
    private int amount;
    public void setAmount(int amount) {
        this.amount = amount;
    }
}

public class CrunchyPeanutButter extends PeanutButter {
}

public class CreamyPeanutButter extends PeanutButter {
}

We changed the two classes to use default constructors, and instead added a setter to set the amount.  Now, we only have one place where we keep track of the amount, rather than duplicating the code across all of our peanut butter instances.

This change can now allow us to make some updates to our Bread class to reduce the coupling there.

public class Bread {
    private PeanutButter peanutButter;
    public void addPeanutButter(PeanutButter peanutButter, int amount) {
        this.peanutButter = peanutButter;
        this.peanutButter.setAmount(amount);
    }
}

We’ve made several simplifications to the Bread class here.  First, we changed our method signature for “addPeanutButter” to take in the type of peanut butter we want to add.  This allows us to get rid of the ugly if/else clause we had in there before, and allows us to have a single instance variable to hold the peanut butter.  Then, we simply set the amount that is passed in, and make sure that our instance variable is set to the type that is passed in.

With this change, we could easily add new types of peanut butters, as long as they inherit from the PeanutButter class without having to touch our Bread class.

Summary

Of course there are additional steps we could take to reduce the coupling of the above classes even further, and allow our Bread class to be used in sandwiches of different types.  But, hopefully this simple illustration is enough to show some of the power behind keeping our classes loosely coupled.