Code must be formatted to agree to coding standards. It’s these coding standards that keep the code consistent and easy for the entire team to read and refactor. Code that looks the same also helps to encourage collective code ownership. It used to be quite common for a team to have a coding standards document that defined how the code should look, including the team’s best practices for styling and formatting. The problem with this is that people rarely read them, let alone follow them. These days, it’s much more common to use a developer productivity tool to automatically guide the user in best practices.
Popular tools in use today, certainly from a .NET perspective, are ReSharper from JetBrains, CodeRush from Dev Express, and JustCode from Telerik. These are all paid-for solutions, though. If you want to use a free alternative, then you can look at StyleCop for the .NET platform. Visual Studio also has its own versions of some of these tools built in, but it’s quite common to supplement Visual Studio with an additional add-on.
Other development platforms will have their own variants of these tools, either as separate additions to their environments, or built in to their IDEs. These tools are so unbelievably powerful that it really makes it frictionless to write code that conforms to a set of coding standards.
When you create a unit test before writing out your code, you’ll find it much easier and faster to create the code. The combined time it takes to create a unit test, and then create some code to make it pass that test, is about the same as just coding it out straightaway. Creating unit tests helps the developer to really consider what needs to be done, and then the system’s requirements are firmly nailed down by the tests. There can be no misunderstanding the specification written in the form of executable code, and you have immediate feedback while you work.
It’s often not clear when a developer has finished all the necessary functionality, and scope creep can occur as extensions and error conditions are considered, but if you create your unit tests first, then you know when you are done.
A common way of working while pairing with another developer is to have one developer write a failing test, and then the other developer to write just enough code to make that test pass. Then, the second developer writes the next failing test, and the first programmer writes just enough code to make that test pass. It almost feels like a game when you work in this way. I worked this way for quite a while when I was working for an internet bank, and once you get a good pace with your programming pair, you can become really productive really quickly.
Under XP, all code to be sent to production should be created by two people working together at a single computer. Pair programming increases software quality without impacting delivery time. It can feel counter-intuitive at first, but two people working at a single computer will add as much functionality as two people working separately, except that it will be much higher in quality, and with increased code quality comes big savings later on. The best way to pair programming is just to sit side-by-side in front of the monitor, and slide the keyboard back and forth between the two. Both programmers concentrate on the code being written.
Pair programming is a social skill that takes time to learn when you’re striving for a cooperative way to work that includes give and take from both partners, regardless of corporate status.
Without force-controlling the integration of code, developers test their code and integrate on their machines, believing all is well. But because of parallel integration with other programming pairs, there’s a combination of source code that has not been tested together, which means integration problems can happen without detection. If there are problems, and there is no clear-cut, latest version of the entire source tree, this applies not only to the source code, but to the unit test suite, which must verify the source code’s correctness.
If you cannot get your hands on a complete, correct, and consistent test suite, you’ll be chasing bugs that do not exist and overlooking bugs that do. It is now common practice to use some form of continuous integration system integrated with your source control repository. When a developer checks in some code, the code is integrated with the main source code tree and built, and the tests are executed. If any part of this process fails, the development team will be notified immediately so that the issue can be resolved.
It’s also common to have a source control system fail at check-in if the compile and test run fails. In Team Foundation Server, for example, this is called a gated build. Once you submit your code to the repository, the code is compiled on a build server and the tests are executed. If this process fails for any reason, the developer would not be able to check-in their code. This process helps to ensure your code base is in a continual working state, and of high quality. Developers should be integrating and committing code into the source code repository at least every few hours, or when they have written enough code to make their whole unit test pass. In any case, you should never hold onto changes for more than a day.
Continuous integration often avoids diverging or fragmented development methods, where developers are not communicating with each other about what can be reused or can be shared. Everyone needs to work with the latest version, and changes should not be made to obsolete code, which causes integration headaches. Each development pair is responsible for integrating their own code whenever a reasonable break presents itself.
A single machine dedicated to sequential releases works really well when the development team is co-located. Generally, this will be a build server that is controlled by checking commits from a source control repository like Team Foundation Server. This machine acts as a physical token to control releasing, and also serves as an objective last word on what the common build contains. The latest combined unit test suite can be run before releasing, when the code is integrated on the build machine, and because a single machine is used, the test suite is always up-to-date. If unit tests pass 100 percent, the changes are committed. If they fail for any reason, then the check-in is rejected, and the developers have to fix the problem.
Collective code ownership encourages everyone to contribute new ideas to all segments of the project. Any developer can change any line of code to add functionality, fix bugs, improve designs, or refactor. No one person becomes a bottleneck for changes. This can seem hard to understand at first, and it can feel inconceivable that an entire team can be responsible for systems design, but it really makes sense not to have developers partitioned their own particular silos. For starters, if you have developers who only own their part of the system, what happens if that developer decides to leave the company? You have a situation where you have to try and cram a transfer of a lot of knowledge into a short space of time, which in my experience never works out too well, as the developers taking over are not building up a good level of experience in the new area.
By spreading knowledge throughout the team, regularly swapping pairs, and encouraging developers to work on different parts of the system, you minimize risks associated with staff member unavailability.