As we are close to releasing our first version and we will have some time on our hands to do clean up on our sources, today we want to look at some of the things we would like to do in order to improve our codebase.
Well, I never thought this series of posts would last this long and have this many parts. We might even make it up to part 42 :-).
As I wrote above, we are close to releasing our first version to the client. If you’ve followed this series of posts, you may know that we’ve been working under the gun for the past eighteen months or so to actually get to this point. To actually have our team meet deadline after deadline, we had to take some shortcuts here and there.
“What?!”, I hear you scream, “Deadlines are never an excuse for shortcuts!”. Sure, in the academic world that’s true, but in the real world business of software, this doesn’t hold up. Even large software companies like Microsoft constantly make choices about if they can do without a certain workload before releasing the next version. We make these choices on a daily basis as well.
But now we are faced with a rare (or dare I say unique) opportunity. We are actually allowed to reserve time to go back and improve the quality of our codebase. We also are allowed to invest in improving our software development platform in order to improve quality or increase productivity.
This begs the question, what are we going to do with this time? I’ve composed a list of things we want to do and I’d like to dive into each of these points in this post. Please keep in mind that the following points are not in order of importance. They are in this order for different reasons.
- Remove any compiler warnings
- Do a complete code review, dealing with the following
- Make sure all code adheres to our coding standards
- Make sure all code can deal with multi language and culture differences
- Decide on what to do with TODO’s
- Check if workarounds for bugs in external code can be removed
- Deal with obvious performance killers
- Mark unclear code for refactoring
- Migrate our main web services to .NET 4.0
- Migrate to Entity Framework 4
- Analyze what code can be made more generic and refactor
- Improve our code generators
- Get automated testing
- Get nightly builds
Remove any compiler warnings
One might argue we should have removed compiler warnings as we went along. And when we started out we did, however as we were confronted with deadlines, this was one of the things we decided we could drop. The reason for this is that we don’t need this for our application to work correctly.
So why fix it? Well, some of these warnings can prevent bugs and some warn about inefficient code. In order to get all our code up to a higher standard it therefore is useful to adhere to these warnings and fix them as necessary.
Do a complete code review
We do this after we have fixed the compiler warnings as we then end up with code as it should be. We may have fixed things we otherwise would have to fix in the review. It also works the other way around. We also now have a codebase without compiler warnings, so we can actually keep it that way as we change code.
Make sure all code adheres to our coding standards
This is and obvious advantage to create. We want all code to follow some rules so we can make assumptions about it. This does not only make it easier to make changes or write new code. It also makes it easier to read, which makes up for around 80% of any developers workload.
Make sure all code can deal with multi language and culture differences
We have international customers who want to use our software in a different language (the default is Dutch). Also their culture settings may differ. We therefore need to make sure we check our existing code base to see if this is taken in account and if not, fix it.
Decide on what to do with TODO’s
During the development we have had times where we though “we should change this part of the code to work so and so.” As we where up against deadlines and most of these changes would have serious impact, we marked these spots with TODO comments.
Again, I can here you say, “well, execute them!”, however we will find TODO’s that are outdated, either because they ended up being implemented directly, because we had too, or because they are no longer relevant because of some decision or insight we had.
Check if workarounds for bugs in external code can be removed
As we work with some third party code, either written by Microsoft or bought from a third party, we encounter bugs in these parts every now and then. We found it good practice to mark any code that we use as a workaround with a comment, describing what we did to work around the bug. Over time these parts might have been updated and chances are we can remove some of these workarounds, benefitting both performance and maintainability of the source.
Deal with obvious performance killers
By this I mean we do a quick analysis of what is happening in a piece of code and see if we can find any obvious inefficiencies. If we do, we remove them on the spot.
We won’t do any performance measurements, so the inefficient code has to be obvious. For example, we might encounter code that uses two queries to retrieve data from the database, where we could have used only one. You don’t need a masters degree to figure out, that you should make this into a single query.
Migrate our web services to .NET 4.0
We’ve already migrated our client to Silverlight 4.0 and Visual Studio 2010. However, because we didn’t want to take any risks with our web services, we didn’t migrate them at the same time. Now that we have the change bringing our web services to .NET 4.0 (and obviously moving them to Visual Studio 2010 in the process) will make our lives a lot easier.
Migrate to Entity Framework 4.0
Right now we are still on Entity Framework 2.0, which was the latest version as we started development late 2008. We haven’t upgraded since, but because there are several improvements in both performance and functionality, we would like to move to Entity Framework 4.0.
Analyze what code can be made more generic and refactor
Right now we are not keeping it DRY all throughout the code base. Especially when it comes to implementing specific functionality we ended up solving the same problems more then once and sometimes even in different ways.
Also, although we tried to take as much care as possible to prevent repeating code, we still had some cases where there was no time to implement a proper generic solution for a recurring problem.
Now we have time to analyze these cases and refactor code as needed.
Improving our code generators
Some of you may know that we use code generators for several parts of our code. Currently we generate our business classes, their collections, XAML for our UI (including an empty code behind) and resource files to go with the XAML.
To create this code, we use metadata from our database models and metadata that’s supplied by our functional specialists. They supply us with information to generate the UI and the resource files.
In order to make this process more efficient we would like to redesign the user interface for the tool that the functional specialists use and change the way we bring all the metadata together. Then we can actually use the combination of this data to generate better and more source code.
Get automated testing
I know, we should have done this from the beginning. However, everyone knows this is one of the first things management will eliminate if time becomes an issue, especially if the team is not experienced in the field of TTD and needs some time to get used to it.
This does pose a problem right now, because it seems almost impossible to introduce actual unit testing after such a long time of development, because we would need to introduce dependency injection in such a large code base. We’ll have some research to do in this area and we’ll have to make some though choices.
Get nightly builds
This one will be a though one to realize, considering all the parts we have and the way we work together, but it does have some important value in integrating source and making sure all the parts keep working together.
A mistake or a consequence?
As you can see there is still a lot of improvement to make. So where did this come from? Well, most of the issues I addressed were results from conscious choices we made. We knew this would have consequences later down the line.
Other things, like the quality of the code generation and a need to rethink our approach was due to new insights and working with some of the concepts in our organization for the first time.
And some things, like code reviews have been a process to get implemented in the culture of our organization. Changes like these tend to take time (and lots of it).
Because of this I have to conclude that the fact we have to do all this work is a consequence of choices we made. And because we knew most of the consequences as we made those choices, I feel it’s a good thing, especially if you consider a lot of development teams do not get this chance.
Have you ever been in a similar situation? Let us know your experience by leaving a comment.