In this post, and many I’ll be writing over the next few months, I’m going to discuss techniques to improve code quality.
For the beginner programmers reading, please follow these lessons. Higher-quality code has fewer bugs and is much easier to work with. The sooner you get into good programming habits, the better off you will be.
Some of the topics might be a little advanced, but I’ll try to explain them as simply as possible. If you have any questions, please ask. That will help both of us. As Albert Einstein supposedly said, “If you can’t explain it simply, you don’t understand it well enough.”
The other day, I was talking with the manager of an IT department. He said that 25% to 30% of their time was spent fixing bugs.
Unfortunately, from what I’ve seen at many companies, that number seems typical.
So, I’m going to try to find tools, techniques, and practices we can use to improve the quality of our C# code.
I’ll also look at ways to improve the project management process. I like Agile practices and principles, but I feel Lean principles go a little deeper. Lean also does not have all the preconceived opinions that often Agile has – which frequently causes problems when you try to implement Agile with programming teams.
But, in this post, I’ll talk about some of the coding practices I’ll test.
With Agile and Scrum becoming more common, many programmers use unit tests and continuous integration. However, I think there should be an earlier step in the quality process – creating a way to prevent certain errors from ever happening.
Here are the practices I’m implementing, in order of importance. I’ll give more details about them in future posts here.
- Use tools and techniques that make it impossible (or, extremely unlikely) to create a bug. Try to develop with poka-yoke
- Use tested libraries, when possible. Don’t re-write something, just because it’s “not invented here”. As a programmer, it’s fun to come up with my own framework. However, unless the purpose of my project is to create a framework, it’s often better to use someone else’s existing tools.
- Use tested in-house libraries, when possible.
- Use code quality tools in Visual Studio, while writing code – such as ReSharper, CodeRush, and StyleCop.
- Be very strict on eliminating code duplication. Run a tool to detect it, and move duplicated code to base classes or services. One friend even suggested writing a utility that would block me from doing more than ten copy/pastes per day.
- In XAML file, set the DataContext object, so we will have IntelliSense available when databinding.
- Applications should not depend on files being placed in a certain folder.
- Scope (public, internal, protected, private) should always be at the lowest (most-restrictive) level possible.
- Write real object-oriented code, using SOLID principles. Most of the C# code I see has several classes that are thousands of lines long, with functions that are hundreds of lines long. For my business objects, I will be using these rules:
- All property setters should be private (to enforce encapsulation).
- If the property needs to implement any restrictions on invalid values, that should be done in the setter.
- All setters should use IPropertyChanged to notify the UI of changes.
- Within the class, all access to a property’s backing variable should be done through the setter or getter. I constantly see class methods that directly modify backing variables, bypassing any validation and notification that might be done in the property’s setter.
- Methods should return void. Any communication that would be done by returning a value should be done through an event. I think this rule may have exceptions, but it will be in classes that process the business objects, not in the business objects themselves.
- There needs to be a separation of classes that represent real-world objects, and classes that perform work on them (“manager” and “service” classes). Object-oriented classes are good at representing a thing, and its state. However, if we use the real world as our programming paradigm, we have objects, processes, and services. Trying to fit everything into objects is where I see many problems. Some of this functionality may be best handled by procedural code – or some other method (maybe state machines, or workflow managers). Part of what I’m trying to do with a test project is find a good way to handle these process and service classes.
- Use tools and techniques to identify errors as quickly as possible.
- Put projects in continuous integration.
- Create unit tests, which are run at every check-in.
- Have unit tests check that the appropriate events have been raised, since our methods will be communicating with the UI by using events.
- Have non-programmer QA done on changes as quickly as possible. The more time between coding and testing, the more difficult it is to remember what you did – which means it will take longer to fix.
- When an error is found, the top priority should be to fix it.
- Use tools and techniques to identify areas that are likely to have errors (now, or in the future).
- Code quality tools, such as NDepend, to detect areas of the program with high cyclomatic complexity.
Where I’ll be testing the code quality techniques
This is what I’m going to be focusing on over the next several months, with the open-source RPG engine I’ve been working on. That project will be the test-bed for my code quality experiments.
Some of the ideas won’t work, or won’t create more quality than the effort is worth. But, that’s the idea behind these type of personal projects.
I’ll have several posts here, and videos on YouTube, showing how to setup the code quality tools I’ll be using.
I’ve also been re-reading some older books on improving processes and increasing quality. Many of them are for physical manufacturing processes. However, it’s easy to see how to apply their principles to software development. I’ll post here with summaries of these books.