Archive for August, 2008

Uncategorized

Getting Certified in Scrum

Last week I spent 2 days with Jens Østergaard getting up to speed with Scrum. Having been using Scrum for a while I thought it was about time to actually get certified in it and make sure those books I've read on the topic were leading me in the right direction.

Overall the course was excellent. The theory backed-up what I'd previously read on Scrum and the classroom exercises were insightful to say the least. The most disappointing thing was the number of the people in the class - not because the student:teacher ratio was poor (it was fine), but rather that so many folks were keen to learn Scrum. I was a bit surprised by that. Clearly it's way more popular than I imagined.

It's hard to understand why organizations still don't get it. Scrum is not perfect by any stretch of the imagination, and it's not easily to do, but it is eons better than waterfall. Why? Because:

  1. there will always be emerging requirements which need to be accommodated;
  2. written specifications are highly ineffective forms of capturing system details (verbal instructions and regular reviews of working software are far more productive);
  3. prioritisation of the features that offer the greatest immediate business value ensure the ROI of the system is maximized over the development life cycle;
  4. frequent, releasable deliverables means the customer can cut the project the minute they consider the system good enough - which can reduce the cost of the system;
  5. self-organizing, cross-functional, leaderless teams have proven to be effective in decision making;
  6. Project risk is lower because Scrum advocates visibility and honesty so last minute surprises and far less prevalent.

What appeals to me most is the fact that Scrum is based on empirical evidence more so than theories. Take for instance the task estimation process. Scrum advocates planning poker which is in effect an endorsement of the Wisdom of Crowds . By giving all the programmers who have knowledge of what's required an independent vote in the estimation phase, and reiterating this process until convergence, or agreement is reached ensures that task estimates include all collective input from the team and constitute a best-guess given that information.

With regard to written specifications Jens gave the class a series of insightful exercises where each team was divided into "programmers" and "spec-writers". The programmers then left the room whilst Jens presented the spec-writers with several diagrams that had numerous shapes on it - a few crosses, a series of congruent triangles, a rotated 5 point star, etc. You can see these diagrams here.  The spec-writers had to write written specifications and pass them to the programmers who were waiting outside and who hadn't seen what the image was suppose to look like. All communication was written and the programmers had pen and paper to implement the specifications given. At the end of the alloted time, very few teams had a finished diagram from their programmers that looked particularly similar to the original. After a few attempts it became obvious to our team that detailed, unambiguous instructions were damn hard to do. Our team resorted to frequent short instructions based on what we had seen the programmers do on earlier instructions. If you were clinging to the belief that detailed written specifications were all that was required to successfully implement a system this exercise blew that notion out of the water in about 15 minutes!

All in all I have to say that the Certified Scrum Master course through the Agile Alliance is well worth it. And now....woohooo...I'm a Certified Scrum Master :-)

Uncategorized

Design Guidelines Part.2: Open-Closed Principle

After discussing the Single Responsibility Principle I'd like to talk about the Open-Closed Principle. Let's start with a definition...

Definition

First touted by Bertrand Meyer PhD in the late 80s, the Open-Closed principle (OCP) states:

Software entities should be open for extension, but closed for modification.

"Open for extension" means the software module can have its behaviour extended and "closed for modification" means that these enhancements don't change existing code. How is that possible? Meyer's original notion, aimed at C++ development where multiple implementation inheritance is allowed, was to use derived classes and inheritance. Given the popularity of languages like Java that don't support multiple (implementation) inheritance the recognised practice, as espoused by Robert Martin, to adhere to OCP was redefined to use immutable abstract base classes or interfaces, and polymorphic concrete classes.

Sometimes such an approach is referred to as a "pluggable architecture".

Rationale

Why would we want to do this? Because change is inevitable so we should plan for it. Let me explain...

Software systems are often broken down into small components. This divide-and-conquer approach allows developers to focus on writing a number of discrete pieces of code that can be assembled into a working system. By focusing on smaller chunks of functionality we can keep our focus narrow and re-usability high. However, given the investment we make in developing such components, and the realistic expectation that changes in requirements are inevitable, it is prudent to design system components in such a way as to minimise the system impact of changes to these components in the face of new or altered requirements. This is the ultimate goal of OCP - being able to add new code without screwing up what we know already works.

The benefits of making code OCP-compliant are several:

  • the component can be extended as requirements change, yet the impact of such changes are more predictable.
  • maintainability is easier
  • previous testing routines/code can be re-used
  • the risk associated with system changes is lower

If enhancements or changes are required at a later time, it only requires the developer to add new code, not change exisiting code.  This means that maintaing software in the future should be considerably easier as you don't have to worry as much about breaking existing code! That drastically reduces your risk profile for code changes, and makes it more predictable in terms of system impact.

Consider the following example: you need to develop an analytics library for Front Office applications and quickly bang out some code like this...

using System;

namespace OptionPricing.BadCodeExample
{
    public enum OptionType
    {
        Vanilla,
        Currency,
        Lookback,
        Binary,
        Barrier,
        ForwardStart,
    }

    public class ExoticOptionsPricingCalculator
    {
        // other functionality elided...

        public static double GetPrice(IOption option)
        {
            switch (option.type)
            {
                case(OptionType.Vanilla):
                    return BlackScholesPrice(option);

                case(OptionType.Currency):
                    return GeneralizedBlackScholes(option);

                case(OptionType.Barrier):
                    return StandardBarrierPrice(option);

                case(OptionType.Binary):
                    return ReinerRubinsteinPrice(option);

                case(OptionType.ForwardStart):
                    return RubinsteinPrice(option);

                case(OptionType.Lookback):
                    return FloatingStrikeLookbackPrice(option);

                default:
                    throw new Exception("Don't know how to price this type of option");

            }
        }
    }
}

As you can see we have a large switch statement around the optionType to pick a pricing algorithm depending on the option type. The above code doesn't conform to the OCP. The problem is that when new pricing methods and options types come along, which they inevitably will, we need to bust open this method and make changes. We'd rather isolate our changes to just new functionality being added.

So with that in mind, we refactor the code to use something like this:

Here we use a common interface (or an abstract base class if you prefer that) to hold common details of each option type. We then use a number of concrete classes to model case-specific behaviour. In this case that means pricing algorithms that our Analytics engine uses which now becomes considerably cleaner...

namespace OptionPricing
{
    public class AnalyticsEngine
    {
        // Method to find out the price of the option specified
        public static double GetPrice(IOption option)
        {
            return option.CalculatePrice();
        }
    }
}

What this subtle refactoring has done is make your analytics engine OCP-compliant with respect to new option types. When new exotic option types, like a Cliquet/Rachet option, come along that you need to price, you will not need to change the GetPrice() method in the AnalyticsEngine. Instead all your changes will be contained inside a new class. By consolidating code in this fashion, it means you don't have to keep massive switch statements around the codebase and more importantly you don't have to manually track them all down when a new option variant enters the picture. Furthermore, you'll be safe in the knowledge that you aren't causing unnecessary side effects because your changes are isolated to the new functionality being introduced. That is the essence of the OCP.

Other Parts in the Series
Design Guidelines Part.1: Single Responsibility
Design Guidelines Part.3: The Liskov Substitution Principle

Books, Technical Design, Uncategorized

Design Guidelines Part.1: Single Responsibility

Given a group of programmers and a defined problem you are guaranteed to get different opinions about the correct way to code the solution to the problem. This is natural and is to be encouraged. You can leverage the Wisdom of Crowd (a recommended read by the way!) and give your team the best chance of success if you hear out everyones ideas and evaluate the pros/cons of each offering - time-boxed of course since we need to eventually deliver something to the client. Of course, even in a meritocracy it comes down to a trade-off but when faced with such decisions I usually fall back on known and proven principles to guide me to what is "good design". So what are these principles?

As far as object model design goes, the widely-known principles that I prefer to follow are:

  1. The Single Responsibility Principle
  2. The Open-Closed Principle
  3. The Liskov Substitution Principle
  4. The Dependency Inversion Principle
  5. The Interface Segregation Principle
  6. The Principle of Least Astonishment

As far as overall architecture goes, some principles which I advocate following are:

  1. Don't Repeat Yourself (DRY)
  2. Keep It Simple Stupid (KISS)

Let's dive into some details...

The Single Responsibility Principle (SRP)

First, lets start with some definitions. Quoting from Wikipedia, the SRP states that:

"every object should have a single responsibility, and that all its services should be narrowly aligned with that responsibility."

An alternate, but less clear definition is: "a class should have one, and only one reason to change."

It is also referred to as the "Do One Thing" rule. What is important to understand here is that a "responsibility" is a purpose. People new to this concept often get the (incorrect) impression that it means single member function because they reason each member function does something different. SRP is about responsibilities, not methods.

But wait. Does this mean I can't have persistence logic in my Business objects? According to SRP that would be the case, but as always these are guidelines. It's not officially stated but I interpret the word responsibilities as realistically meaning "responsibilities that are likely to change". Although this requires some insight into how your objects will evolve over time.

Why do we need to consider SRP? Because:

  • It makes testing the class easier if it only has one responsibility;
  • Classes are easier to read since they have a narrower focus;
  • Classes are likely to have fewer LOC;
  • You'll get greater re-use of the component since the component wasn't bundled with several other responsibilities the upstream consumer doesn't want or need;
  • There is less tendency to resort to copy-and-paste programming (which is really, really bad) to reuse functionality because it was made atomic, and therefore highly reusable, in the first place;
  • You'll naturally tend toward greater cohesion (how strongly-related and focused the responsibilities of a single class are) - which is a good thing because it makes code more maintainable;
  • You'll avoid building in tight coupling across your classes (I'll explain this further in a moment...)

So what nasty things await if we disregard the SRP? Well if you have objects with multiple responsibilities then you are creating more than one reason for that object to change - which is bad because in classes with multiple responsibilities the responsibilities can't help but become coupled making it hard for the object to undergo changes to one responsibility without affecting the coupled responsibilities. It is far more preferable to have modular, single-responsibility classes that change independently of each other, and change less frequently because they are single-purpose. As well, ignoring SRP makes it more likely that you will develop object anti-patterns such as God Objects where individual objects know too much or do too much.

In summary, following the SRP makes life easier in the long run for the developers...Reading the code is easier. Maintaining the code is easier. Making changes to the code is easier. And re-using the code is easier.

As Martin Fowler says,"Programs should be structured in such a way that we can make changes easily. When we make a change we want to be able to jump to a single clear point in the system and make the change." He calls these divergent changes in a section called "Code Smells". Say no more!

SRP is a simple concept but invariably it is much harder to implement. You have to be vigilant and force yourself to take things out of your class moving them to separate classes. Sure there are going to be cases where you happily violate this principle but be aware of the ramifications when you make that trade-off.

Other Parts in the Series
Design Guidelines Part.2: Open-Closed Principle
Design Guidelines Part.3: The Liskov Substitution Principle

Next »