Search

Thank you Mimi

Posted by Andres on April 1st, 2007

This is a personal post. Nothing agile or technical about it.

I’ve been writing articles and blog posts for about six years now. During all this time, my wife has helped me tremendously. She has read and commented on my writings since the start. She has helped me sharpen my writing skills, and focus on getting the point across. When I have doubts, she pushes me on.

Mimi

Thank you Mimi. I owe you.

Three strikes and you’re out

Posted by Andres on March 24th, 2007

Imagine that you’re starting on a new project. It’s all very exciting. The team meets, and together you plan your attack. You start working away, and you’re having a good time. Pretty soon though, you find all compromises, misunderstandings and bad decisions made in the code you’re there to build on. Welcome to the real world – you are working with legacy code.

A patched up old car

You can decide that there’s just too much untested, hard to understand code. There’s no way the project can rewrite it and still produce the new features that the business wants. The team will have to live with it. Besides, this code has been tested by real users for years, and you can’t just throw that away.

On the other hand, past shortcomings are slowing you down to a crawl.

Some of the enhancements planned for the project require changes in the old code, and that’s a pain to do. Also, the project has to fix a number of bugs, and you don’t even know where to start looking for those. You realize that if you don’t rewrite the code, there’s no way the project can deliver on time. You are stuck between a rock and untested code.

The trick is, of course, to rewrite just enough to give the necessary velocity. The hard part is to know what and how much to rewrite. In the last project I worked on, my colleague Jim Arnold showed us one way of keeping track of what is hurting us at the moment. We took a flip chart and every time we’d find that we where struggling, we’d write the name of the class that was giving us a hard time on an index card. We would add a line on the card, and then we stuck the card up on the flip chart.

If the class caused problems again, it gets a second strike.

Two strikes

By now, you’ve probably already figured out what happens next. Whenever a class gets a third strike, it was time for reworking. We would spend time working on the test coverage. We would take out anything that wasn’t used. Taking baby steps we would improve the design until the change we wanted to do became easy and safe. A few times we found that it as faster to just rewrite a bunch of classes from scratch than take lots of small steps.

Of course this is not a perfect system. But it helped us to be a bit more objective about what actually needed to be fixed, and what could wait. Some people lean towards patching the code until it does what he wants, and a some always want to chuck the whole thing and start fresh. This system was a compromise between the two.

Most projects are not greenfield projects. Working with legacy code (even if it’s something you wrote yourself, when you didn’t know better) is something you should expect to do. So building on your set of tools for doing this effectively is essential for you to become a kick ass developer. It’s not enough to learn the latest frameworks or the new cool dynamic language.

I was reading this top ten list yesterday, and I thought I can problably come up with my own list of things no-one told me before I started developing software for money. This is my list.

  1. Object orientation is much harder than you think
    Maybe it’s just me, but coming from Computer Science class I thought that OO was easy. I mean, how hard can it be to create classes that mimic the real world? It turns out that it’s pretty hard. Ten years later, I’m still learning how to model properly. I wish I spent more time reading up on OO and design patterns. Good modeling skills are worth a lot to every development team.
  2. The difficult part of software development is communication
    And that’s communication with persons, not socket programming. Now and then you do run into a tricky technical problem, but it’s not at all that common. Much more common is misunderstandings between you and the project manager, between you and the customer and finally between you and the other developers. Work on your soft skills.
  3. Learn to say no
    When I started working, I was very eager to please. This meant that I had a hard time saying no to things people asked of me. I worked a lot of overtime, and still didn’t finish everything that was asked of me. The result was disappointment from their side, and almost burning out on my part. If you never say no, your yes is worth very little. Commit to what you can handle, and if people keep asking you for more, make it very explicit that this would mean not doing something else. What I did was to have a list of stuff that I needed to do on a piece of paper with me. When someone asked for something, I showed them the list and asked what I should bump to have time to help them. This allowed me to say no in a nice way.
  4. If everything is equally important, then nothing is important
    The business likes to say that all the features are as crucial. They are not. Push back and make them commit. It’s easier if you don’t force them to pick what to do and what not to do. Instead, let them choose what you should do this week. This will let you produce the stuff that brings value first. If all else goes haywire, at least you’ve done that.
  5. Don’t over-think a problem
    I can spend whole days designing things in front of the white board. That doesn’t mean it will be any better, it just means it will be more complicated. I don’t mean to say you shouldn’t design at all, just that the implementation will quickly show me stuff I didn’t think of anyway, so why try to make it perfect? Like Dave Farell says: “The devil is in the details, but exorcism is in implementation, not theory.”
  6. Dive really deep into something, but don’t get hung up
    Chris and I spent a lot of time getting into the real deep parts of SQL Server. It was great fun and I learned a lot from it, but after some time I realized that knowing that much didn’t really help me solve the business’ problems. An example: I know that at the table level, SQL Server will not take an IU lock – it will only take a IX lock. This is a performance tweak, since most of the time, the IU lock will have to be escalated into a IX lock anyway. To find this, I spent countless days experimenting, I read loads of material and talked to Microsoft people at conferences. Have I ever had any use of this knowledge. Nope.
  7. Learn about the other parts of the software development machine
    It’s really important to be a great developer. But to be a great part of the system that produces software, you need to understand what the rest of the system does. How do the QA people work? What does the project manager do? What drives the business analyst? This knowledge will help you connect with the rest of the people, and will grease interactions with them. Ask the people around you for help in learning more. What books are good? Most people will be flattered that you care, and willingly help you out. A little time on this goes a really long way.
  8. Your colleagues are your best teachers
    A year after I started on my first job, we merged with another company. Suddenly I had a lot of much more talented and experienced people around me. I remember distinctly how this made me feel inferior and stupid. I studied hard, reading book after book but I still didn’t catch up. They had too much of an advantage on me, I figured.
    Nowadays, working with great people doesn’t make me feel bad at all. I just feel I have the chance of a lifetime to learn. I ask questions and I try really hard to understand how my colleagues come to the conclusions they do. This is why I joined ThoughtWorks. See your peers as an asset, not competition.
  9. It all comes down to working software
    No matter how cool your algorithms are, no matter how brilliant your database schema is, no matter how fabulous your whatever is, if it doesn’t scratch the clients’ itch, it’s not worth anything. Focus on delivering working software, and at the same time prepare to continue delivering software using that code base and you’re on the right path.
  10. Some people are assholes
    Most of the time, most of the people around you are great. You learn from them, and they learn from you. Accomplishing something together is a good feeling. Unfortunately, you will probably run into the exceptions. People that because of something or other are plain old mean. Demeaning bosses. Lying colleagues. Stupid, ignorant customers. Don’t take this too hard. Try to work around them and do what you can to minimize the pain and effort they cause, but don’t blame yourself. As long as you stay honest and do your best, you’ve done your part.

Today I had an interesting discussion with a colleague. He was upset over some technical detail in his last project, and I said that it wasn’t a technical problem, it was a people problem. This ticked him off, and we got into a big debate about what are people problems and what are technical problems.

My take on this is that most often, we as techies focus a lot on the technical problems, and work hard to solve these. But as Jerry Weinberg tells us, “No matter how it looks at first, it’s always a people problem”.

What does that mean? It basically means that technical problems are symptoms of people problems. And solving the techie problem is like taking pain killers for a brain tumor. Maybe it will give you a bit of relief in the short run, but you’re still far from well.

So how can you as a consultant/developer/concerned party get to the cause of the problem? I like using the “5 whys“. This will lead you to the root cause of the problem you’ve encountered. Solving this will prevent whatever symptom you ran into from recurring. Let me show you an example:

Our customers are complaining that our software has lots of bugs.

Now, instead of just sitting down and fixing the bugs, let’s try to find the core.

1: Why are we shipping a product with lots of bugs? Because our code base is really hard to change and verify.
2: Why is our code base hard to change and verify? Because the regression tests (lots of them) are all manual.
3: Why are the regression tests manual? Because we have no time to automate it.
4. Why don’t we have any time to automate it? Because our project deadlines puts a lot of pressure on us.
5. Why do we have so tight dead lines? Because our product owner believes that putting the team under pressure produces better software.

We have now gotten to the real issue. Fixing any of the intermediate steps might help, but as long as the product owner has this attitude, new problems will crop up.

To me as a developer, it is always easier to stay close to the computer. That’s my comfort zone. But taking a step back, asking a few questions and not immediately firing up the IDE allows me to be a lot more effective. It helps me and the rest of the business more than trying to solve the incident. The underlying issue is probably harder to change than the symptom, but the rewards are also bigger.

If you find that the root cause is actually a process problem, Kevin Rutherford has a nice write up about this interesting discussion. Maybe I’ll share my feelings on the topic in some future post. Suffice to say is that it’s not very easy to tell the two apart.

Edit: I stumbled upon this after writing this post. Ken talks about how people problems are very common in software projects, still no-one spends any time or effort training software people on the soft-skills required to solve these problems.

Applications I wish I had time to write

Posted by Andres on February 20th, 2007

I have two daughters and I like to read a lot, so I don’t feel I have the time to do any serious coding on any pet projects. If I mysteriously found a couple of weeks with nothing to do under my pillow, this is what I’d hack together.

1. iCrash
I went so far as to register a SF project, but I didn’t work on it enough to do any real progress. The idea is simple – whenever your application finds itself in a state it shouldn’t end up in, it can report this to a central bug database. A bit like Gnome’s bug-buddy, and Microsofts crash reporting system, but it would be called from inside your application and not from the outside. I worked for a while on MediaPortal, and something like this would have really helped us target the problems most users run into. The reports would include stack traces, crash dumps, .NET versions, and more, to help the developers fix problems easily.

2. Continuous Unit Testing
Continuous Unit Testing is an old dream of mine. This is to unit testing, like CC is to continuous integration – the chance to make asynchronous. The idea is that whenever your typing away, and you pause for more than a couple of seconds, the CUT-system would fire of a background job that compiles the code and runs the tests. A systray alerter would let you know if the system is in a red or green mode, and when a test fails, it would maybe show a little tool tip saying which test that failed and the exception. Of course, it would be clickable, and that would take you to the failing test. I know Eclipse has something like this, but for us in .NET land this is just a dream so far. A few weeks ago I got so far that I now have some bits that run on my laptop, but not enough to be useful to anyone else.

3. Dead Lock Inspector
I’m kind of proud that I still hold the Google #1 for “sql locking“. At one point in my career, I focused a lot on the internals of SQL Server, and specially the locking. Doing that, I learned a lot about locking as a concurrency control mechanism in general, and I know that there is a least one way to find possible dead locks without having to actually run into them. So I envision a system that would take a NUnit assembly, and inspect it, and point out possible dead locks. What you would do is to create one test fixture for every test you wanted to run. The individual tests in the fixture would then represent work that runs in separate threads. The inspector would log any locks taken and released, and use this information to find problems.

I love consulting, but I wish Thoughtworks would give me a week or two between projects to play around with stuff like this.

Debugging on client machines

Posted by Andres on February 1st, 2007

We deliver working software every week. That’s important in agile. It creates a lot of trust when our stakeholders can download the bits and try stuff out.

Unfortunately, this also means that they run into more, let’s say unpolished areas of our code. This is great news for us – we get high quality feedback early in the process, which helps us iron out the problems in the code earlier rather than later. But sometimes, the people running our software do stuff that we can’t reproduce. Since the users doesn’t have any debuggers installed, we don’t get enough debug information.

To counter this frustration, I’ve downloaded Debugging Tools for Windows, installed it and copied the folder in Program Files down to a USB key. Now I can run windbg from the USB key with no installation hassle. I thought I’d share the simple steps needed to see an exception.

  1. Start windbg and load the executable (Ctrl-E)
  2. Set up windbg to automatically download needed symbol files by writing !symfix
  3. Load SOS by writing !load C:\WINDOWS\Microsoft.NET\Framework\<version number>\SOS.dll
  4. Now run the application (F5)
  5. When your application throws an unhandled exception, you’ll end up in windbg again. Now run !pe to see information about the exception

You can get a lot more information than that. I usually do a !threads and !clrstack to get an overview of what’s going on. !help gives you a list of what available SOS commands you have.

Debugging makes me feel a bit like a detective sometimes, and like a I want to tear my arm of and hit me over the head until I pass out at other times. But good debug sessions are really enjoyable.

Want to learn more about debugging .NET applications in windbg? Go here or there.

    Levels of competence

    Posted by Andres on December 22nd, 2006

    A singing guyWhen I first met my wife, I thought I was an OK singer. I mean, I could sing along most pop-songs, and it sounded OK in the shower. I actually once tried out for the yearly school musical.

    It was me and another guy in a room with the music teacher sitting in front of a big piano. The other guy was up first. The music teacher asked him to hold a C, and then plinked on the piano. My combatant sang, and the teacher nodded a bit. She then asked for the same note, but one octave lower this time. Again, the other guy sang a bit. At this, the music teacher seemed satisfied. She then turned to me, and asked me to sing a C note. Plink on the piano. I sang and tried to use the same tone that she had plinked on the piano. She looked at me with a slight frown, and said “No, I mean a C. Like this.” And she plinked again. I tried to sing using the note, but could see it in her face that I was failing miserably. I didn’t land the part, and the school was better of because of it.

    I didn’t think much about it, until years later when my wife taught me a little about singing. Mostly she’d point out to me when I wasn’t doing it right. Slowly, I started learning enough to notice myself when I made a mistake. It took lots of training to realize that I sucked.

    A lot of people have been speaking about Shu-Ha-Ri lately, and all the time, I didn’t feel quite right about it. Then, I saw in an NLP book something about the four stages of learning:

    1. Unconscious Incompetence
    2. Conscious Incompetence
    3. Conscious Competence
    4. Unconscious Competence

    The stages look like the Sha-Ha-Ri stages, but has the added first level, where the person learning doesn’t even realize that he needs to learn something. It was this part that was missing. All too often, you’ll meet people that are in that first level, which makes teaching them something extremely difficult.

    The last couple of years, most of the projects I’ve been on have had the ingredient of teaching agile practices to the development group, and most of the problems I’ve encountered is when I try (stubbornly and not always nicely) to teach someone something they themselves aren’t even aware they need to learn.

    One very interesting suggestion I’ve heard on this was on an internal ThoughtWorks mailing list, when someone suggested starting the engagement by doing a retrospective, to find pain points in their current way of working. That way, instead of teaching agile practices because they are the “right” way to do things, you can say that you’d like to try CI, since they said that a big problem was integrating code.

    I imagine a good agile coach having a bag of good practices to pick from. He would start by showing how their most immediate problems can be alleviated. The coach would not to preach, and would stay clear of name-dropping or using any books as references. Everything that is proposed is because personal experience has shown that it works, not because someone else has written a book about it. Listening to the team, he can advocate what to do for specific problems. It’s very important to learn to back off. If the team doesn’t like something, pushing for it will only lessen their trust in you. If they are not ready, wait, and try something else.

    Why optimizing without profiling is inefficient

    Posted by Andres on November 22nd, 2006

    I recently moved from Malmö, Sweden to London, England. Today I did some major groceryA cashier doing her thing shopping. When I put my items on the checkout counter, I did what I always do in Sweden – I try to make things as easy as possible for the cashier. You see, in a typical Swedish grocery shop, what slows down the line is the cashier. She/he can’t scan the items fast enough, and so helping him do a faster job helps the line flow more efficiently.

    Today I made sure that the EAN-codes were all facing the cashier, and no items were piled on top of each other, trying to make the cashiers job easier. I looked at the people on the other lines, piling stuff without concern on top of each other and felt good that I had cracked the system and would get serviced faster than the rest. Unfortunately, very soon I saw that my cashier was working very slowly. I realized that in England, the cashier will start to put the goods in bags if you don’t, something that a Swedish cashier will never do. Most of her time was now spent packing stuff in bags instead of scanning items. I felt stupid, piled the rest of my stuff on one big heap, and moved over and started packing goods into the plastic bags. Presto, everything was running fast again.

    This is exactly what happens in software systems too. A developer, having the best intentions in the world, will optimize his code based on his experience of what will be slow. Measuring of the live system will show that the actual bottleneck is somewhere else, and the optimization was naught.

    In the last PDC, Rico Mariani, Performace Architect for the whole Developer Division in Microsoft, stated his ten rules for optimization. They where:

    1. Measure
    2. Measure
    3. Measure
    4. Measure
    5. Measure
    6. Measure
    7. Measure
    8. Measure
    9. Measure
    10. Measure

    The problem was not that the optimization didn’t help. The problem was that the optimization made the code harder to read. And reading code is very important. When I see weird code, and the defense for it is “it’s faster that way”, I cringe. Most of the time, insignificant performance gain has come from that tweak, but understanding the code has now become more work.

    Think of it this way. In a project, you are turning resources and time into runnable software. The time you spend time optimizing code costs you is time you won’t use on other parts of the project. Also, you are taking time away from the other developers of the team, because they will have a harder time understanding your code. The gain from you optimization is neglectible, and the cost is very real.

    My suggestion is not that you totally ignore the performance of the system, but that you direct your efforts where it’s needed. Schedule a couple of hours every other iteration or so, and find out, first hand, where the bottlenecks are for the important uses of your system, and then act on that information.

    Calm down!

    Posted by Andres on November 16th, 2006

    People (like Jonas, Magnus and Marcus) have told me that I can be frustrating to work with. That’s because I’m a stubborn know-it-all that likes to push my “better” knowing on everyone else.

    That’s not the person I want to be. I still think that I have a few good ideas I should share, but being aggravating while doing it is not very productive. Another thing is that I’m realizing as I get older that I care more and more about people enjoying working with me, and less and less about being right.

    I recently went to a two week ThoughtWorks course in India. When my coach on the course told me that he thought I had done very well, but that I had been a bit confrontational a few occasions, I realized that something has to change.

    So what I have done is this:

    By my laptop, I now keep a little Buddha statue. I’m not a buddhist. I just use this powerful symbol as a reminder to myself that humble and calm goes a long way. Whenever I find that I’m getting annoyed or I get the urge to prove someone wrong, I reach out and touch the statue.

    So far it has worked better than I hoped it would. I’m by no means a totally changed man, but it’s helping me relate to colleagues in a more constructive and efficient way. Another good thing is that people ask me about it, and I can bring the subject up naturally. It allows me to warn the person that I have a problem I’m working on, and what they can do to help me (let me know when I’m being an ass).

    Software Architects

    Posted by Andres on November 7th, 2006

    One of my favourite games to play with my oldest daughter is where I pretend that I don’t understand something really basic – like how to put on socks. I put them on my ears and ask her if I got it right, and she reprimends me and tells me I should have them on my feet. “Like this?” I ask, and tie them around my ankles. Lot’s of giggling, and she tries to help me to get it right. It’s great fun for a three year old to teach her big stupid dad how to dress himself.

    An architectWith my daughter, I play stupid to amuse her. Sometimes though, I feel just that stupid in my workplace. Something that seems very basic to people around me just doesn’t compile in my brain. One of these things is the role of the software architect. Software architects (or even worse, capital Architects) don’t make sense to me in general, but specifically in an agile environment I don’t understand what they are supposed to do.

    From Wikipedia:

    [A] software architect is responsible for:

    • Interfacing with the user(s) and sponsor(s) and all other stakeholders in order to determine their (evolving) needs to be realized in software. [---]
    • Generating the highest level of software requirements, based on the user’s needs and other constraints such as cost and schedule.
    • Ensuring that this set of high level requirements is consistent, complete, correct, and operationally defined.
    • Ensuring that a maximally robust software architecture is developed.

    [---]

    • Generating a set of acceptance test requirements, together with the designers, test engineers, and the user, which determine that all of the high level software requirements have been met, especially for the computer-human-interface.
    • Ensuring that a maximally robust software architecture is developed.

    It’s not that these activities are not important. It just seems to me that these are the tasks of other roles in a project – specifically the business analysts, and for the acceptance tests BAs together with QA.

    Even the name itself is confusing. Software architect? The code I write is several steps away from actually runnable bits. Layers and layers of abstraction exists between the source code and the executables. The sourcecode goes through a build to become executable. Doesn’t that make the source code the blueprints the compiler uses to build the executable? And if that is the case, couldn’t the person writing the code be called the architect? To me, every developer is an architect. It’s every developers task to see that “a maximally robust software architecture is developed”. That’s not something you can do in UML. It’s the thousands of small and sometimes seemingly unimportant choices that each developer (pair) makes that creates a robust, smooth system, or a unusable hack.

    The term architect in this context makes no sense to me. It’s a leftover from when we thought that software development should be like constructing buildings; with the architects making the blueprints and the construction workers carrying out their plans. Software development is all about the design, and nothing at all about the actual building. So it doesn’t make any sense to split the tech team into developers and architects. The developers are the architects.