Blake Caraway

March 2006 Entries

Team Smells...Refactoring For A Better Tomorrow (Part Two)

In a previous post I detailed some conditions existing on development teams that would suggest some changes need to be made in order to bring about better performance and ultimately higher quality software. In this post I will identify a couple more Team Smells and discuss how these issues can be remedied and why these conditions should be addressed in the first place.

Smell: Developers Spent Way Too Much In The Debugger (AKA Debugger Junkies)
A good feature-rich debugger like the one that comes with Microsoft Visual Studio is a nice tool. It allows you to easily get a view into the runtime state of your code. Unfortunately, developers can use this tool as the sole form of verification that the code they wrote is functioning properly. There should be one obvious, overriding reason to step through code using the debugger: tracking down a bug (duh!). A valid debugging scenario would entail watching a particular piece of code execute to determine why it’s behaving in an unexpected manner. A Debugger Junkie commonly works in this way:

  • 1. * fingers crossed *
  • 2. Hit F5 and see if the solution compiles
  • 3. Wait for the entire application to load up
  • 4. Navigate to the specific point in the application where the breakpoint or breakpoints are ready and waiting
  • 5. Interact with the application to try and re-create the unexpected behavior
  • 6. When Step 5 uncovers some indication as to where the problem might be, investigate the objects’ state in and around the perceived problem area to uncover the root cause
  • 7. Devise a plan for where the code should be modified to make the feature behave as expected
  • 8. Make code change and GoTo Step 1

  • Not only is this an unbelievably inefficient way to work, it can often make for a confusing and miserable work experience. No wonder developers on a team that exhibit these smells don’t want/are afraid to modify their code – they are sick of looking at it! Because of the dependency on the debugger to validate their efforts, by the time these junkies have completed a couple medium-sized application features, they are experiencing no small amount of frustration from the debugging monotony they have put themselves through. There _is_ a better way…

    Refactor: The key to ridding your team of this poor habit is to implement measures that help developers gain confidence in the code they are producing. Getting a development team to change the way they work and weaning them from the perceived security of the debugger can be a rough ride in the beginning. J. Peterman, of Seinfeld fame, said it best when demanding Elaine help her office ‘boyfriend’ Zach break his drug habit –

    PETERMAN: … Uh, P.S., the first twenty-four hours are the worst. Better bring a pancho.

    Yep, it can get messy. There will be no limit to the number of excuses offered up as to why this new approach won’t work. But Test Driven Development (TDD) is perfectly suited for ridding a development team of their debugger dependency. The very process of creating a unit test before writing any live code provides the developer with an accurate measurement of how the code should work. When code is written to make a unit test pass, there should be a large amount of confidence that the code is doing exactly what it needs to do. When all requirements for an application feature are satisfied by a battery of unit tests – THE FEATURE IS COMPLETE. Some other things have to change in order to for this approach to work. Separation of concerns among application layers and coding to interfaces across these layer boundaries must occur so that isolating code for unit testing can take place. Doing this effectively also allows developers to work without having every layer functioning – i.e. no need for a working, populated database, web services, or active directory services.

    When these dependency endpoints can be ‘faked’ through some sort of abstraction (like an interface), application logic can be created and tested effectively – one test at a time. When the time comes for a true build process and deployment to an integrated, end-to-end environment, there should be fewer surprises as to how the code works when it’s all put together – all because of the effort taken to develop test first and receive feedback from the very beginning regarding how the code is behaving. See Scott Bellware’s excellent post on TDD and failing tests meaningfully for a much more elaborate discussion surrounding the benefits of good unit tests.

    That’s it for now.

    Oh, and for no apparent reason, here are a few more Seinfeld quotes talking about Zach’s drug problem:

    PETERMAN: I'm afraid the problem with Zach is more serious. He's back on the horse, Elaine. Smack. White palace. The Chinaman's nightcap.

    PETERMAN: And, in a tiny way, I almost feel responsible. I'm the one who sent him to Thailand - in search of low-cost whistles. Filled his head with pseudoerotic tales of my own Opium excursions. Plus, I have him some phone numbers of places he could score near the hotel.

    PETERMAN: Damn it, Elaine. That wasn't Zach. That was the yam-yam. Now, he is going cold turkey. (Ordering) And you will be at his side.

    FireFox SessionSaver

    I've been looking for a FireFox extension that will remember what tab/web pages I had opened after closing and re-opening browser instances. I found one yesterday after searching, again, (I've looked for something like this for sometime now) through the myriad of extensions - in the Navigation, Tabbed Browsing sections. I give you...

    SessionSaver. This extension seems to do exactly what I've been looking for. I have not experienced any issues with installing subsequent extensions like a couple of the comments I read on the extension download page. Give it a shot.

    Team Smells...Refactoring For A Better Tomorrow (Part One)

    Just like any project you work on, there are signs and behaviors within a development team that indicate a need for refactoring as well. Before a development team can get to the job of developing quality code, the definition of "quality code" has to be addressed, identified, and agreed upon. I believe this is the most difficult step in evolving a development team's skill set away from the 'slap it together and fix it later' mindset. Why do I think this? Because this is exactly what I'm attempting to do with my current team.

    In order to convince an entire team of developers to change the way they code, you have to establish a case for _why_ this big change has to occur. Point out where the inefficiencies in the current methods (or lack thereof) are. Make everyone realize that there is a better way. Security is a _huge_ factor because you are asking someone to step out of their comfort zone and learn something new. In fact, many take offense to this notion of improving the way they do things. This brings us to our first Team Smell:

    Smell: Hubris
    There are two things to consider here: 1) the industry of software development is full of bright, intelligent people, and 2) almost every person in the industry thinks they are one of these bright, intelligent beings. This is a potential team killer because the person that thinks he or she knows everything they need to know to develop good code – all too often doesn’t. I don’t want to work with someone that thinks they have nothing left to learn. This is the type of person that eschews Agile practices like TDD because he claims he can create solid, object oriented, sustainable code on his own, without some crazy process to help him along.

    Refactor: This might be the most difficult symptom to battle because of the inherent human nature involved. The good part about working with someone afflicted with this condition is that they will often jump into management ;-) . Of course, you know the downside to this - they could become your manager ;-( If this smell is too widespread on a team that you are trying to change for the better, the best choice is probably to find another team and/or place to work. The point of all this improvement is to write higher quality software through better methods. If the vast majority of team members are just too full of themselves to change, then wish them the best as they continue to pump in 70-hour weeks and seek out a place where your peers will be more like-minded.

    Smell: Developers Are Afraid To Modify Their Own Code
    This may seem silly and unbelievable to you, but during my current project I constantly hear fellow developers say, “Yeah, but I finally got this working. If I change this now, it might break, and I just don’t have time for that”. Translation: “I have no idea how my code even compiled, much less how I would go about modifying or moving pieces of it around for the sake of refactoring, especially since the deadline is next week.” If a developer is afraid to dig into the code he or she spent a lot of time producing, chances are the code 1) sucks – in that it resembles a large plate of spaghetti – at best, and 2) has little or no chance of becoming testable without many large, risky refactorings.

    Refactor: Defunkifying this smell should be easier to address because it’s simply based on a lack of understanding. Where there’s a lack of understanding, there’s usually a hidden desire to understand because the uncertainty of the work he or she is doing is somewhat unsettling. Many developers in this position simply don’t know how to shed this uncertainty. This is where preaching the value of test driven design should find an eager audience. By working in small, testable chunks, a code base evolves bit by bit, thereby reducing the chance of it becoming too large and fragile. When code is just slammed into place in order to ‘get it working’, what should have been prototype code usually becomes production code b/c the developer is just happy that the junk he or she produced compiles. All too often this type of developer knows the code should be at the very least cleaned up and modularized, much less refactored to patterns and made testable, but he or she knows the trouble they will be in when they try this – so they just let it lie.

    One of the greatest bi-products of designing test-first is that when a feature is completed (i.e. all uses cases or stories are satisfied) there is a compliment of unit tests that can be run at any time to verify the code is doing the job it’s supposed to. Another great thing about code that is designed test first is the resulting structure is typically _much_ easier to 1) understand, 2) extend, and 3) if necessary, modify. I can’t start any new piece of application functionality now without beginning in a test method. I feel quite secure coding one test-case at a time, constantly thinking about the responsibilities of a class and how it should operate with its dependencies. Working in this way I know that the code was created thoughtfully and with care (as opposed to entire features crammed into 80-line methods that can do 20 things, depending on another 20 possible conditions). And thusly, when the code goes live, it will run as intended with very few surprises.


    In part two, I’ll identify one or two more Team Smells and how to expunge their foul stench from your working environment.