My answer to this question is twofold. The first and hardest answer to swallow is that you need to “Be Prepared to Unlearn.” Over the years you may have picked up some negative developer habits. In my opinion, people find it harder to unlearn bad practices and ideas than to start adopting potentially beneficial practices. You may need to come to terms with the fact that you might not yet be as effective at object-oriented programming as you think. Most developers truly believe that they are taking advantage of OO programming, when in reality the majority of their code is just procedural code utilizing objects. My gentle suggestion to overcome this hurdle, along with the others that are going to be thrown at you as you learn to adopt agile development skills, is be humble. Regardless of what your position is on your team or what “skillz” you think you may have, humility is the shortest path to accelerated learning. Once you can let go of your need to “keep up with the Joneses” you are free to chart your own path and practice JITL (just in time learning) to increase your development skills.
Looking at the mountain of practices, tools, and techniques that you can choose to learn can be a little overwhelming: object-oriented programming, design patterns, test-driven development, behavior-driven development, interaction-based testing, state-based testing ……… The trick to scaling this mountain of learning is to attack it in an agile fashion, incrementally, and iteratively.
The following list outlines an approach that I use to teach people about agile development techniques. My approach suggests not tearing into your existing development with your new “hammer” but rather to take a blending approach to introduce new techniques, patterns, and practices:
- Read The Pragmatic Programmer by Andrew Hunt and David Thomas. If you can absorb and apply the information in this book, you will gain a set of habits and practices that will fuel you for the duration of your software development career.
- If you’re not using source code control, stop reading this right now and go and get your code into a source control repository. Hopefully this point is moot because regardless of how you are currently developing, you are setting yourself up for a big fall if you don’t have a source code management (SCM) system in place. A couple of options you can look at are: CVS (http://www.nongnu.org/cvs/), Subversion (http://subversion.tigris.org/), and Team Foundation Server (http://msdn2.microsoft.com/en-us/teamsystem/aa718934.aspx).
- Get a continuous integration server in place. This is essential if you want to get yourself working in a more agile fashion. Some of the tools that you can look at are: CruiseControl .Net (http://sourceforge.net/projects/ccnet/), TeamCity (http://www.jetbrains.com/teamcity/), or Team Foundation Server (http://msdn2.microsoft.com/en-us/teamsystem/aa718934.aspx).
- Set up automated build scripts to work in conjunction with your continuous integration server. As a small victory, see if you can set up a build that will automatically deploy new builds of your application for you. This alone is a huge time saver that will allow you to focus your efforts on other things. Some of the tools that you can look at in this arena are: NAnt (http://nant.sourceforge.net/), Rake (http://rake.rubyforge.org/), and FinalBuilder (http://www.finalbuilder.com/).
- If you are in the camp that realizes that you are not completely up to speed on applying object-oriented programming, spend a bit of time reading some good material that will help you get an idea of what OOP is all about. My personal recommendations include: Applying UML and Patterns by Craig Larman and Head First Design Patterns by Eric Freeman, Elisabeth Freeman, Kathy Sierra, and Bert Bates.
- Start learning an automated unit testing framework. My current favorite is MbUnit (http://www.mbunit.com/). You can also check out NUnit (http://www.nunit.org/index.php) and xUnit (http://www.codeplex.com/xunit).
- Now that you have a handle on unit testing, it is unrealistic to think that you can allocate the time to retrofit what may be a completely untested codebase with unit tests. Instead, identify hot spots in your application that cause you headaches (lots of bug tickets), and make a strong effort to get some automated unit testing around those areas. Again, utilize frameworks like MbUnit or NUnit, or XUnit to accomplish this.
- If step 5 (object-oriented programming) is proving problematic because of a highly coupled system, you may need to start breaking apart dependencies and refactoring for a bit more testability. Again, only focus on the hotspots. If you are unsure about how to proceed, pick up the following awesome resources:
.Working Effectively with Legacy Code by Michael C. Feathers will introduce you to a host of techniques for getting yourself out of tangled messes in your application.
.Refactoring: Improving the Design of Existing Code by Martin Fowler, Kent Beck, John Brant, William Opdyke, and Don Roberts is the seminal work on cleaning up messy codebases.
. ReSharper (http://www.jetbrains.com/resharper/) from JetBrains is an invaluable Visual Studio plug-in that will aid you in the process of refactoring your code.
- Get into the habit of unit testing new code that you write. This is not test-driven development, but it will get you in the habit of ensuring that to the best of your knowledge, new functionality you are working on has a safety net of testing around it. Forming this habit alone will give you unsurpassed confidence when you go to make changes to your code base, as you will now be working with a safety net. If it isn’t green, you broke it!!
- Get some design patterns knowledge. It will allow you to speak a lot more concisely with your team members, as well as help you think about ways to build more cohesive objects. If you are starting down the patterns path, beware of patternitis. In reality, when you are learning, you will rush to try and find a way to apply design patterns; with experience you will realize that leveraging a design pattern may not be the best solution to the problem at hand.
- Start introducing the concept of interface-based programming into your applications. By coding to contracts (interfaces), you will allow for systems that are far more loosely coupled as well as extremely testable.
- By this point you should be comfortable with the concepts of unit testing and interface-based programming, and all of the new development you have done sticks out like a bright light surrounded by the darkness that is your old code. Now is the time to start getting into the habit of doing test-driven development (TDD).
- Getting into TDD is a bigger shift than the jump you will have already made to object-oriented programming. The best piece of advice I can give is to stick with it. Code your tests and imagine that the pieces you want to exist are already there and you can use them as you would want to, simply and easily. The nice thing about TDD is that you are designing your object from the perspective of a consumer of that object; this inherently will constrain you to keep the design as simple as possible. It is definitely beneficial if you are able to pair with someone who can help you get stared down the TDD path. I recommend that you read the book called Test-Driven Development: By Example by Kent Beckwhile you are going through this portion of learning.
- So you are now comfortable with state-based test-driven development. It is now time to add a new tool to your TDD arsenal, a mock object framework. By utilizing mock objects, you will be able to focus on writing tests for only one class at a time while simulating any dependencies the class you are testing may have. My current favorite mock object framework is Rhino Mocks (http://www.ayende.com/projects/rhino-mocks.aspx). By the time you introduce a mock object framework, you should already be comfortable with interface-based programming, which will allow you to start integrating it into your tests very quickly.
- At this point you now have a very solid foundation of core skills built up. You are now in a place where you have climbed the steep learning curve and you can now look forward to a steady growth in your development skill set.
- Now let me make the last and most important point: Become a student of your profession. Most of the people who embark down this style of development do so because they have a passion to want to deliver applications that both please the user as well as please other developers who maintain the code. Like anything else in life, if you want to excel in anything you have to be willing to sacrifice a little. What does this mean? Make a commitment to read a book a month. Take time to download a tool you have no idea about and start spiking it. Speak at a user group. Write a magazine article about your learning. Passion breeds passion. If you get infected, more often than not, others around you will want to take part in the learning that you are going through!!
Note that it is unrealistic to expect that you can drive through the above 16 points in a short amount of time. I propose this plan of attack for starting down a new path of development. It could take six months, one year, two years, or more before you feel comfortable with all of the new techniques and practices you will be utilizing. Speaking from personal experience, it will be one of the best investments you make for your career.
Enjoy the journey!!