Tests revealing design problems

Within last few months I was introducing tests into untested code. It was not old code, just some code that was not Unit Tested. As much as I was eager to do so, I found myself getting in a bit of a pickle.

 

Code complexity

Code was actually quite complex and difficult (smell) to understand. I was also a little scared that I will misunderstand the code and its intention. I assume that I will not be the only person facing this problem while working on the piece of code.

Fortunately there was some testing coverage in a form of a higher level Acceptance tests (not sufficient though).

I decided to refactor the code a little to make it more manageable. Extract few methods, rename few variables, remove unnecessary conditions and loops, etc.

When I finished refactoring and made sure build was still successful, I checked in the code and off I go to write some Unit Test. That was the point when I hit another brick wall.

Instantiated dependencies

Necessary dependencies in a class that I wanted to test were not provided to an object upon creation, but were instantiated internally. This means that code is not flexible to changes in a future and is impossible to test (smell). Making all the dependencies passed through constructor will make it more obvious to what the class will do, and make it possible to unit test.

So, after some refactoring again, building and submitting the code, I had my dependencies all wired up through constructor, just the way I like (mmmm, delicious).

Concrete classes

Many of the dependencies were still concrete classes. Pity, actually you don’t care what’s in the guts of your collaborators (most of the time) as long as they do what they indicate. This could be replaced by interfaces (or some abstract types in worst case) as dependencies. They also make it easy and simple to stub or mock your collaborators, so the testing is simpler to setup and you’ll be testing only the correct object.

Another refactoring session ended in a bunch of new interfaces.

So I started to write a test. I created my object and started to pass some dependencies. The problem was that I had to pass some other dependencies to those dependencies, and dependencies of dependencies and even more dependencies and … you know where this is going.

This great monster had too much setup code than the one I was going to test.

Too many collaborators

This got me into thinking that something was not right. The thing was that the tested class was trying to do too much. This was the main reason of mentioned previously code complexity. Testing was not easy and possibility of introducing new bugs during future changes was great.

So, extracting few methods here and there (around same functional area) and I was able to pull those methods into new object. This new class was very simple and was responsible for one area of functionality only. I could unit test that new class.

Last problem during the tests was that I got some unexpected behaviour. As I looked into the code it turned out that there was one more smelly thing left.

Static methods

There was some code that was calling to a static method of another class. It was impossible to mock or stub it. What’s even more horrible, it was using some internal static variables. That caused some un-expected behaviour.

Summary

As it turned out, I found problems in a code even before I started to write a single line of test. Just thinking about the ways to test, revealed first issues. More of the issues appeared while testing. The work I had to do in order to make code tidy, simple and testable could be avoided by writing it in TDD/BDD way.

I’m convinced there could be more problems revealed. Here are these that I found once again:

  • complex code
  • instantiated (new Foo()) dependencies inside tested class
  • concrete classes with no interfaces
  • too many collaborators (class was doing too much)
  • static methods (brrrr)

Greg

How can Pomodore help you shave a Yak?

Two terms in the title that needs clarification.  Pomodoro is a technique for managing a task completion, or simply time. Yak shaving is a situation that everyone finds himself every now and than when we are trying to solve a problem in a wrong way. Usually it happens when we create a chain of tasks that will lead to a solution and we keep on repeating it until we get somewhere. Eventually we could end up with a very crazy solution after a long period of time.

Yak shaving

An example of Yak shaving I found myself in not too long ago.

I found myself doing a Ruby on Rails development on a Mac box. As I used older version of MacOS I had an older version of Ruby compiler. To use latest version of Rails I had to get newer version of Ruby. To get that I needed to install that via Mac Ports or something similar. While trying to install Mac Ports I found myself missing some of the development files that stopped Mac Ports from installation. It turned out that those files where in XCode. I had to find XCode that is going to work on my machine. Turned out that older version is available on Apple Dev website, all I need is to sign-in. I had an account, but forgot the password. Then I tried to retrieve a password and that didn’t work. After some battles I finally got a XCode on my box.  It was still Mac Ports impossible to install Mac Ports thought. That took me along time. Eventually I ended up installing VM image of Ubuntu and developing on Linux VM.

I think that being developer, the Yak Shaving problem is very irritating and could lead into a lot of wasted hours. When working in a pair,  the Yak issue will not appear that often. There is always a second pair of eyes to validate the sanity of the task in progress. It doesn’t eliminate the Yak entirely as I found out with some peers 🙂

When working alone that is entirely different story. Because there is no one to run you ideas by, sometime I make a decisions that lead me into “the shaving“. I found myself wasting hours before realizing that it doesn’t make sense and taking step back.

Pomodoro, mmm, delicious

Not to long ago on a project I was working on, we used Pomodoro to keep us focus for a period of time. This simple technique combines 25 minutes of un-distractable time of work and a 5 minutes break. After 4 successful Pomodoros (25 minutes + 5 minutes break) we had a little longer break. While working in a pairs, Pomodoro was keeping us focus and safe from emails, phone calls and coffee breaks. The 5 minutes break gave us a lot of time to discuss the issues around the task/problem.

When working alone the 5 minutes break could be the excellent opportunity to talk with someone else about the problem or just take a step back and reflect on a solution. This eventually could lead into new ideas and most importantly into STOP shaving a Yak.

There is more to Pomodoro technique than just a sanity check from a yak shaving. There is a free PDF book that can be downloaded for free http://www.pomodorotechnique.com/resources/cirillo/ThePomodoroTechnique_v1-3.pdf and some other resources on the Pomodoro Technique web site.

Cheers, Gregster

Coder, programmer or developer

Scratch headCoder, programmer or developer

Today I had a conversation with my Wife about the stuff I do at work. I was trying to explain what is my role. After few minutes I got into a pickle. Am I a coder, programmer, developer. Does all those terms mean different things or they all the same?

Taking a step back in my life I tried to analyze all those words according to what I was doing.

Coder

When I left university I was full of theory. Empty words and concepts that I never tried in life. I knew few programming languages and some technics. I had no experience how to deal with people though. Whenever I was in a conversation about next project, feature I was thinking only in technical terms. When I found something impossible to do (as I just never done it before), I said that it is impossible to do. These were old days, and I think I was a coder at that point in my life.

Programmer

When I started my first job, every simple task was a problem. I was asking a million questions all guys that were working there for long time. Needed guidance on everything. After a while I was capable to make some simple technical decisions and not ask anybody. This is when I still was in my little world of code and I didn’t care about reasons behind it.

Developer

This is few years after university. This is the moment when I stopped thinking about programming languages (they are just another tool) and focused on software as a whole. A big role in this was played by people from the company I work for at the moment (ThoughtWorks). As a developer I need to know what is the driver behind the need for feature/software. Why? I need to understand system as a whole, to make proper decisions. It is also possible that the feature or functionality is not really needed or hard (impossible) to implement.

So, coder, programmer, developer. This is how I believe I evolved through my technical life. The labels are still a labels but I find them very useful explaining or just understanding what I was doing.

I believe it is natural for next question to appear, what’s next?

We’ll see 😉

Greg