Writing quality code is important, right? 'But of course!' will be the response of pretty much everyone you'll ask in the software industry. And of course, quality code is very important. Especially for applications that perform business- and mission-criticial activities. But what exactly does it mean when we say that something is 'of high quality'? In most software development teams, the concept of quality is very important. This makes it all the more surprising that most developers will draw a blank face and shrug when you ask them what this actually means. In this blog post I will write a bit about my experiences with defining 'code quality' with teams. To finish off, and for those interested in concrete lists, I'll also add the definition (or the 11 rules) that one of my teams came up with. This post is of interest to those working with a Scrum or Agile approach which puts power to the team.
Defining quality: Ask the team!
When you work in or with a team, it is important to sit together and define what constitutes 'quality code'. Why? Because:
- You create shared understanding in the team of what quality code should be like;
- Members will become more aware of the quality of their code, and where they can improve their work;
- Code reviews can be grounded in a firmly defined defintion of quality;
- A definition can be communicated to those working with the team, to manage expectations;
- A good definition will motivate teams and make them more proud of their work (they can now explain why they are proud of their code);
A short sessions (say an hour) can give you a good start to set up a working definition of quality. The most important thing to keep in mind is that the definition should come from, and be supported by, the team. No matter how good the definition, forcing one down a team's throat will greatly increase the chance that the team's support will be mostly superficial. The best way to get a team motivated about the definition (or pretty much anything) is to allow them to come up with one themselves. This is in the spirit of Scrum/Agile. Of course, the team can be advised and suggestions can be given. But the ultimate definition is up to the team. To organize the meeting, the following approach can be used:
- Ask all the members to prepare. Ask them to write down the aspects they consider to be important for 'quality code'. But also ask them what they consider to be aspects of 'bad code'. Examples really help. Allow them to do some research first;
- Kick off the meeting by stating the goal and the intent of the meeting, which is to discuss what consistutes quality code and that this meeting is supposed to result in at least a working definition;
- Make sure the team understands that the definition is a discussion piece, and can and will evolve over time;
- Ask every individual member to describe the aspects they consider to be important for 'quality code' in turn. Give the team room and time to discuss the aspects;
- As the team discusses the aspects, summarize the aspects (preferably in short 'rules') on a whiteboard or a laptop connected to a beamer;
- When the team runs out of ideas, ask them to explain the aspects of 'bad code' and how these can be inverted into aspects of good code. For example; bad code can be code that is not documented properly. In that case, good code is code that is documented well (of course, what 'well documented' means should be described by the team);
- A good definition should be SMART (specific, measurable, acceptable by the team, realistic, timely). If the teams subscribes to a very vague definition of 'quality code', it will be very hard for them to work with it;
- When the meeting is over, summarize the rules and ask them team if they are ok with the (working) definition;
- Print the definition and share it with the members. Preferably, put it somewhere visible. We have a copy of the definition on the wall of the developer rooms. You could even frame it and put in on the wall or put it in the wallpaper;
Got a (good) definition? Keep it alive!
Once you have a definition of quality that the team feels comfortable with, make sure to embed it in the daily going-ons of the team. For example:
- Integrate the definition in code reviews, periodically (say weekly) held by the team to review (as a team) as piece of code that was written by one of the members;
- Use the definition to evaluate the performance of the team or it's members. If the team considers good testing as essential to quality code, evaluate members on how well they test their code;
- Use the definition when hiring new developers. Ask them questions to gauge if they have the skillset that is important for the definition as formulated;
- When new members join the team, ask the team to explain their definition to the new member. Also allow for sufficient room for the new member to add their own insights;
- When you are working closely with a product owner, involve them as well. It is a good idea to allow the team to communicate their definition of quality with the product owner;
- When investing in the growth of teams and their members, for example through courses, lectures or books, hook into the definition and explain this to the team;
- Periodically re-evaluate the definition with the entire team to keep it alive in the mind of the individual members. We do this every 3 months;
An example of a definition of code quality
'Ok,' you might think, 'but what about an actual example?'. Up to this point I've been (intentionally) vague about what a definition of 'quality code' should be like. Primarily because what exactly constitutes quality code is something that depends on the context. For example, for NASA it will be important to excessively test every tiny detail of the code. Otherwise they'll have a very expensive Mars Rover running in a circles on another planet. If your team is building small-scale websites, testing is still important. But it does not have to be that thorough. The size of the team is also important. Documenting code becomes increasingly more important when the teamsize increases, as sharing knowledge becomes harder. The same goes for the complexity of the application or the overall experience of the team.
One of my teams can up with the following definition, narrowed down to 11 'short rules'. Quality code ....:
- Generates business value for the product owner. This means that the team writes code from the mindset that all code eventually has to generate business value. There is no point in writing code that does not generate business value. This stops teams from spending a lot of time on 'developer toys' in the codebase. This also means that the code works and conforms to specifications;
- Is documented for yourself and other developers so that it becomes easier to share sourcecode within the team and work on one project together. Documentation should be in the form of XML Comments for methods, classes and properties. But a data dictionary with terminology, a domain model description, a set of written down business rules and test scenarios are also important;
- Is documented for users so that they know how to use the application. Documentation can be in-line, within the application, or as a separate document. The team should work from the mindset that no application is of 'good quality' when users don't know how to use it;
- Is tested (manually and automatically) with the entire arsenal of testing options available to developers, including unit tests for crucial business rules, regression tests for interactions between subsystems, manual test cases for aspects that are hard to test automatically and testing instructions for testers;
- Is optimized for performance by using Visual Studio's profiler or custom profiler scripts to identify and eliminate bottlenecks to the point where they are not considered a nuisance by testers or end users (this needs to be defined more clearly per applicaton);
- Uses design patterns where possible to facilitate communication between teammembers and improve quality by conforming to well-known solutions to problems. For our team, the most useful patterns are Model-View-Controller, Dependancy Injection, (Abstract) Factory, Singleton and Repository;
- Is re-usable by seperating logical pieces of code into separate projects and classes within the solution. Using interfaces rather than concrete implementations facilitate re-using code. Writing code from the mindset that it will be re-used will improve it's overall design;
- Seperates responsibilities of code by splitting the application into tiers, each responsible for their own subset of tasks. This means that we have a UI, a controller layer responsible for fetching and receiving data to and from views, a provider layer for enforcing business logic, a data access layer for retrieving and persisting entities to a database and (finally) the database itself;
- Follows well-known coding standards by using Microsoft's C# coding guidelines as enforced by FxCop, StyleCop and Team Foundation Server;
- Is simple by doing what it needs to do in the most simple and verbose manner and should be understandeable by all members. This avoids code that is too clever (and therefore difficult);
Of course, this is just a example. A good definition can be shorter or longer. It all depends on the context, the team and their experience. But we find that the above definition works well for most of our projects. But i'll keep you up to date when the definition changes! After all, that's what Agile is all about: embrace change!