Monday, 27 August 2012

The object-oriected TDD journey

When you start practicing TDD for real, one of the first problems you'll come across is dependency management. Chances are, that before you were TDDing, whenever you needed to use class A from class B, B would create it's own instance of A or A might be a singleton.

class B
{
    private A instanceA = new A();
}

You soon find that you want to mock A and the best way to get the mock of A into an instance of B (your SUT), is to pass it into the constructor. This is called Dependency Injection:

class B
{
    public B(A a)
    {
        instanceA = a;
    }

    private readonly A instanceA;
}

You also find that you don't want a dependency on A because creating an instance of the mock of A is going to call the constructor of A. So you solve that by having A implement an interface IA and pass IA to B instead.

class B
{
    public B(IA a)
    {
        instanceA = a;
    }

    private readonly IA instanceA;
}

Your next problem comes along when you actually want to create an instance of B. Say the constructor of A takes an instance of IC, you will need to do the following when you want a new B:

B instanceB = new B(new A(new C))

For a large application, this step will be a horror of nested news. So you will then learn about Inversion Of Control and this will help you manage your dependencies:

IocContainer container = new IocContainer();
container.Register<B>();
container.Register<IA>().ImplementedBy<A>();
container.Register<IC>().ImplementedBy<C>();
B instanceB = container.Resolve<B>();

Here the IOC framework is responsible for figuring out the dependencies of B and creating the required instances recursively.

Now you find that you're making a mess becase your IOC framework is letting you create a dependency from any class in your system to any other. You now pay attention to group your classes into modules with small, well-defined interfaces between them.

When working on a piece of code you will try and break it down into small coherent modules that look like stand-alone libraries. They will ideally have a very small set of public interfaces. The IOC registration will be done by the module itself and classes external to the module should only use the public interfaces. This prevents a spaghetti of inter-class dependencies.

Sunday, 26 August 2012

Rich Hickey on Debugging

I was reading Micheal Fogus' interview with Rich Hickey, the man behind Clojure. When asked why he is considered an excellent debugger, his answer was fantastic. It often surprises me that this isn't how many programmers approach debugging.

Fogus: I’ve spoken with a few of your former co-workers, and they described you as a trouble-shooting and debugging master. How do you debug? 
Hickey: I guess I use the scientific method. Analyze the situation given the available information, possibly gathering more facts. Formulate a hypothesis about what is wrong that fits the known facts. Find the smallest possible thing that could test the hypothesis. Try that. Often this will involve constructing an isolated reproducing case, if possible. If and only if the hypothesis is confirmed by the small test, look for that problem in the bigger application. If not, get more or better facts and come up with a different idea. I try to avoid attempting to solve the problem in the larger context, running in the debugger, just changing things to see effects, etc.
Ideally, you know you have solved the problem before you touch the computer, because you have a hypothesis that uniquely fits the facts.

Saturday, 4 August 2012

Scala first impressions

In the last year or two I've been practicing TDD and the things that come naturally from it: dependency injection, inversion of control and data / behaviour separation. All these techniques complement each other and encourage you to write code that is actually quite functional. This lead me to start looking at functional languages to see if there was a better way to build software; OO paradigms were starting to look a little unnecessary. I started with Haskell, it being one of the most pure functional languages. I then tried F# and now I'm playing with Scala.

Scala is interesting because it is a full object-oriented language, in some ways going further than Java, and is also a functional language providing most of the things you'd expect from a functional language. For example:

  • Pattern matching
  • Higher order functions
  • Anonymous functions / lambdas
  • Type inference
  • Currying

Traits

One of the more interesting features of Scala is traits. These are similar to interfaces in Java and C# except that they allow implementations of the methods they describe. I find this a bit scary but also fascinating because a very common code smell I see is people deriving from base classes in order to re-use code between classes and not because of an inherent 'is-a' relationship. Traits let you re-use code between classes without a cumbersome inheritance relationship. I'm only starting to get the hang of them though, for example they can be stacked.

Pattern matching

Pattern matching in Scala is very similar to F# and Haskell. It's one of those features that you find yourself missing from other languages once you've learnt about it.

Type inference

The type inference in Scala is not as good as in F#, this is apparently because of Scala's OO features. That said it's still much better than Java or C#, although that's probably an unfair judgement).

Anonymous functions

This isn't really exclusively the domain of functional languages anymore, C# and even C++ support it now. I think the Java committee have really let themselves down by not including this in Java 7. They are extremely useful and pop up in all sorts of places. They also allow library writers to design great APIs.

JVM

I really like that Scala compiles to bytecode and can be run on lots of platforms. I love C# and the .NET framework, but I hate that it doesn't have first class support on non-windows platforms. The mono framework is an amazing piece of kit, but I'm always going to trust the JVM on Linux over Mono. That's perhaps unfair, but you really don't want to worry about bugs in your runtime environment and there's always a manager you're going to need to convince.

Tooling

One of the things that I found a little disappointing about the Haskell eco-system is that there is a distinct lack of decent tools. The only proper Haskell IDE is Leksah which is a step in the right direction, but is still in its infancy. Haskell is the perfect target for auto-refactoring tools because it has proper strong typing, but there isn't anything serious, no re-sharper or eclipse for Haskell. F# is better but still limited (you can't organise your code in folders in Visual Studio for example).

I've been really impressed with the tools available for Scala. There is decent support available in Intellij and Eclipse (through plugins). They're still a little rough, but are definitely usable.

I think Maven is fantastic and being able to use it to build Scala and pull in maven dependencies is wonderful. Also, SBT is an alternative to Maven for Scala which is easier to get started with (not being XML based helps), which I also quite like. SBT can pull in maven dependencies which means getting an SBT project started is very quick.

Conclusion

I'm clearly becoming a fan of Scala, but I can't help worry that the reason I'm getting on with it is because it's not actually very different from the languages I'm comfortable with (C#, C++, Python, Java etc). I think I still need to keep learning Haskell to try and get around some of my problems with it (like how to build a large system TDDing as I go along - I can't rely on IOC to help me out like I do with C# and Java). However, right now I would be happy to start a production project using Scala. Though I would love to do one in Haskell as an experiment, it would be a risky proposition.