Saturday, July 22, 2006

Programming a Sudoku Solver

I programmed a Sudoku solver the other weekend. I was going to blog as I went, but there were too many interrupts and as the coding gets more interesting I forget to blog. I end up with a blog of the boring parts :-) The key thing is what did I learn about my little exercise?

The first thing I learned was how important discipline is. I started by slicing my problem into small slices with tests driving the code until I got to my first tough part...solving for a cell. I thought "Hey I can code this in no time and get this test to pass". An hour later I was running the debugger and asking myself "How did I get here?" when my wife called to help puts the kids in bed. In disgust, I killed the IDE and didn't return till the following morning. My own hubris caused me to abandon discipline! Once I got back into the habit of slicing the problem and driving the development with tests I was able to get the solver working and in no time I was able to solve all but the "wicked" level of Sudoku's.

The second lesson was the power of TDD. I had not programmed in over a year and the process drove me through to a solution in roughly 8 hours. I honestly believe that when we look back on this time for the history books, TDD will be the first true productivity catalyst since second order languages. If you did it right OO gets you 5-10%, Pair 10-15%, but I think TDD will get you 50-100%.

The third lesson happened when I got into a discussion with a co-worker. He is a fairly smart guy with out any experience in TDD. When I brought the subject up his face literally changes to one of disdain. He thought the idea of writing tests for each line of code was absolutely stupid. He assured me that code coverage tools would lead me to a better use of my testing time; good developers obviously shouldn't be spending too much time writing tests! I then remembered the lesson I learned from my last job...change is evil...even for smart people! People have strong beliefs that have been re-enforced as they live life and develop patterns to deal with this world. Therefore most experienced developers have a long list of things that must be done and things that should be avoided. For this one developer, and probably many like him, one of the things to avoid was writing too many tests. Maybe a programmers ego is threatened by tests. Maybe the thinking is "If I am good then I don't need some stupid test to double check my work and tell me I am doing a good job!" I have to admit, when I was a full-time developer I wrote the least amount of unit test code among my team. I wonder what I would have thought about TDD then? Hmm, whatever the thinking I find it interesting that I think TDD is the best thing to happen since iterative delivery and other equally intelligent people think it is a waste of time.

The fourth lesson revolves around feature splitting. The Sudoku solver feature set was pretty simple. It only allowed for a few methods (load, solve, check solution and print), but 90% of the code revolved around one feature (solve). It required thinking to break it down into its parts - something I call design. Lacking discipline, I chose the simpler method of just trying to code it and then refactor it into a decent design. I realize now that stopping to design and TDD were working in tandem to point me to doing the right thing! Of course you only learn these things by doing the wrong thing :-)

My last lesson has little to do with my coding exercise and more to do with several different posts and blogs I have read about TDD. Many people think they know how to write software. I have learned that we really don't "know", but we are uncovering better ways of doing it. Once we figure it out then we can automate the whole process and put us all out of work. So many people cling to simple minded beliefs that we have actually figured it out and all we need to do is to follow the age old wisdom of define it, design it, write it and test it! SEI seems to collect people with this mindset. In my opinion we must constantly question our preconceived notions about software development because just when you think it's truly a given, technology or some one smart shows you just how wrong you are.

Friday, June 9, 2006

Good Software Engineering Reading Material

I was going to send this as an email, but decided I wanted it to be more persentent...

Brad appleton on simplicity (again):

Jim Grenning on embedded TDD:

Kent Beck on Appreciative Inquiry (as applicable in stand-ups, but I like the idea in general):

Ron Jefferies being himself (entertaining and educational at the same time):

A TDD example for non programmers (I didn't take the time to read it, but some people I respect liked it):

And I leave you with this quote:
The intelligent man finds almost everything ridiculous, the sensible man hardly anything.
-- Johann Wolfgang von Goethe

Wednesday, May 24, 2006

Why Time Management is Important

Like most people my age, I have dabbled in many forms of self improvement. Once I tried Franklin Quest (now Franklin Covey) and eventually gave up on it. Once Outlook became the first thing I did everyday, I would say to myself, "How can they still be in business? Outlook does everything I need." Well, I think I now know why they still do business.

There are roughly three types of workers on software projects:
A - those that take on too much
B - those that take on the right amount
C - those that take on as little as possible

Type A workers alternate between type A and C if they are not well managed. Type B workers are great, but can't step up in a moment of crisis (gotta love those type As then!). Type C workers (those that aren't just recovering type As) are usually unmotivated for reasons beyond your control...not that you should give up on them. It should be obvious that your most valuable resource are your type As (If you don't know this then you shouldn't be in management :-)

Let's see if I can get to my point with a personal story. One of the unseen advantages of my current job is I get to do more work than I can possibly do. This has led me to go through the typical type A overwork cycle:

1. Work all the time until one of two things happen: A. Someone who cares and that you trust(my wife usually plays this role) tells you to stop or B. You check out
2. Work as little as possible to recover (or quit...never done this one but I know people that have)
3. Go to 1.

As you can see it is never ending. So in a short moment of clarity I stumbled on (remembered) a way to stop:

1. Write down all known tasks (if you are just starting 2 as I am it might take a while) - meetings are tasks!
Each Day:
1. Set a hard stop to your day (5pm is mine for now)
2. Block off the last 30 minutes (so now we are at 4:30; 30 minutes might not be enough for some of you)
3. Start each day by prioritizing all known tasks
4. Work on the most important tasks until the day is done (4:30 for me)
5. As new tasks are added; put them on the list and do a quick and dirty prioritization (today...not today) If it is today then add it at the top and see if all Top priority items can be done. If not then the last one on the list just got bumped!
7. During the last 30 minutes make sure you have have all known tasks (usually this means reading email)

In other words - Time Management. Other than being cathartic for me what was my point? Well if you remember my last post, I am trying to find the principles of software engineering. I have been pondering this for a while and haven't had anything worth saying until now (you judge its worth).

What is the most important thing in a software project? This answer is easy - the people on the project. I know this sounds like a cliche. When I taught agile software development people would always scoff and say something to the effect of "Well I don't know where you come from, but were I work I get the people I get!" A team of talented software engineers will succeed no matter how many stupid decisions are made by the uninformed, but a misaligned team of unmotivated and mismanaged software engineers will fail not matter how good decisions are made. It all comes down to the people. I have never been on a team, seen a team or even heard of a team that couldn't succeed. I have been, seen and heard of plenty of failures. I think you have two choices: be a victim or do something about it.

Well the people on most software projects are a mix of the three types above. If you don't manage them accordingly then you will wind up failing no matter what else you do. Given that the type As are the most valuable resource and managing them should be priority one. One thing type As do poorly is....Time Management!

Thus my circle of logic is complete...kind of.

Sunday, April 30, 2006

What is Software Engineering?

Earlier in my career, I would say my career was software engineering. Then one day an interviewer asked "What do you mean by that?" This simple question was the beginning of my search to really understand what software engineering meant. My first answer was
awkward and used thoughts that can be found in the CMM. After thinking about it for a few years I began to believe that Software Engineering was an oxymoron. I used the term software development. Wasn't I clever ;-) Then I discovered Agile Software Development and I was hooked. I wrote about it, taught it, practiced it, loved it. This lasted for a few years, but the more I saw the more I realized there are lots of ways to be "Agile". Some were sound and others weren't, but they all could say (without lying) that they were Agile! I knew what worked for me, but did that always work? Off the shelf agile methods (like XP) work great in some places, but not so great in others. Many projects had constraints that most agile practitioners hadn't even considered (let alone little ole me).

My approach to new problems is to go back to first principles. In this case what were those principles. The agile alliance has these, but they seem more like good ideas from experience rather than principles. This got me thinking. Maybe there is something in that old term Software Engineering. Maybe it would help to dissect the term:

Software: Coded instructions (programs) that make a computer do useful work. (from

Engineering: Engineering is the application of science to the needs of humanity. This is accomplished through the application of knowledge, mathematics, and practical experience to the design of useful objects or processes. (From wikipedia)

Let's see if I can munge the above definitions to create something I like...

Software Engineering: The application of knowledge, techniques, and practical experience to make a computer do work deemed useful.

This still doesn't get me to the principles. Civil Engineers have a wealth of physical principles (Newtonian physics and all that). The best Software Engineering can counter with is Computer Science. It hasn't really progressed since second order programming languages and the best I can figure it's principles boil down to logic and some rule about a Turing machine. So I have just alienated my CS doctorate crowd. One less reader won't hurt me ;-o

I have thought on this and in the past the best I could come up with was to steal principles from other disciplines. I would rationalize it like the definition for software engineering found in the wikipedia. This defintion makes Software Engineering nothing more than a mutt grown from other more pure fields (science, management, physiology and my favorite the generic "engineering"). Well that just doesn't cut it for me. There are some rules behind this activity called Software Engineering and if you break them it causes you pain. Let see if I can find them....