The most annoying and frustrating thing on refactoring is that you loose track midway in the process. Right after you start refactoring you usually face a tremendously growing bunch of open topics and you struggle with a lot of things to keep in mind and/or to predict. How shall I do the basic structure? How do I split up the responsibilities within my software? How do I put this all together in the aftermath? And the most fearful question: Will it all work like before? Or even more pessimistic: How long will it take to test it, to find and to fix all defects? How will I be sure that everything fits together in the end?
Unfortunately in much too much cases this leads to a dead end where you capitulate heavily frustrated, roll back all development and a) never touch it again or b) start from scratch with the same problems.
How to avoid this frustrating situation
You can avoid the dead-end-situation by answering the questions above in advance to your refactoring. Instead of starting as fast as possible with chopping down your running sourcecode with an axe, step back for a second and invest one to two hours in planning your approach. This will safe a lot of time and frustration in the actual development process. So let’s start and answer some of the questions above:
- “How to keep track of all open topics?”
Technical support #1: Use a task tracker that is integrated into your IDE. For Eclipse the best solution at hand is MyLyn with a task tracker like Bugzilla or Jira. In order to relieve your mind from tracking all open topics, you must add every single idea, every question and every open topic to this task tracker.
Technical support #2: Use a version control system. Here I use Subversion. This will give you all opportunities to roll back, work on different paths / branches of the software, find out about the changes already done etc.
Strategy and Mindset: There are lots of references on the Web how to set up the technical support noted above properly, but the most important success factor is that you use it as frequently as possible adding all little sparks and hints rushing through your mind to the task tracker and adding every single successful development to the version control. Whenever there is a new idea, question or open topic while you are actually developing part of your software, put it into the task tracker to safe it for the future and to get rid of it while you are developing. Whenever there is some development done (even an intermediate work-around), check it in into your version control system to fix it for the future and to get rid of checked-out-and-changed files while you are working on the next topic.
Thus “divide et impera” is very important. Chop your big project down in small ideas and small steps. You don’t know how? Read on.
- “How to structure my approach even if I’m not sure about all details?”
Make use of a framework (in this case: extbase). It provides you a structure and it can also provide you a route to setup the structure and develop your software step by step. Make yourself familiar with the basic principles of this framework. This means that you have to do some research work on the Web or in some books. While you are reading this, you are actually doing exactly what I am talking about right now. This blog is exactly the result of a process like this: Research, get ideas, structure your ideas, find out about the challenges in the real world of development. Start with simple questions / tasks where you know the background quite well (e.g. the domain model) and proceed to the complex topics (error handling on the GUI) at the end. Be sure: The project’s complexity will increase with every step you take, but your experience will increase as well to solve this. Don’t let the project’s complexity rule your way of working, do it the other way around. Use the tools and small steps noted above to keep control of the project and of the complexity.
- “How do I know, if everything will fit together / if I am on the right way?”
It is not a good idea to refactor for weeks, do a big-bang deployment, start testing and getting frustrated by a not-at-all-working software. Refactoring actually means small steps in each of these development steps: Small changes, small deployments, small tests leading to small and easy-to-find defects. This leads to a very large amount of very small and easy (even trivial) tests. Doing a lot of trivial tests a lot of times is not a very satisfying job, so let’s make the computer do this annoying job. This means: Automatic unit testing. And to do it right, you shall (I strongly recommend this!!!) do it in the first place. I.e. “Test Driven Development” or “Test First Approach”. Start by writing the unit test and do the actual functionality inside the software afterwards. Yes, I know that developers want to develop functionality and don’t want to develop stupid tests telling them stupidly that the stupid implementation wasn’t done right now. And a developer doesn’t want to write a test for a stupid getter or setter method at all. That’s annoying stuff for a well trained developer’s mind. But take it the other way around: Whenever you run all these simple tests, they provide you the very good feeling that everything works like expected. This is the most important feeling while you are refactoring a software. This lets you be sure that you are on the right track. And be sure as well: Tests will be more complex and meaningful while you are progressing your refactoring job. The better the test, the more stable your software, the less annoying search for the root cause of complex defects. You will see the effect in the later posts while I am using the Test-First-Approach on my project as well. And please keep in mind: If you start with the test first, you also start with thinking of your expectation / requirements before you start developing the software. That keeps things simple: You will define what you want to achieve by developing a test and afterwards you will just invest as much effort es really necessary in implementing the solution to meet these requirements. That’s efficient and it reduces the complexity of your project, because you don’t implement functionalities that you might use in the future, but that you are not sure about in the moment. There is no test for it, thus you don’t implement it.
Now you’ve got it all together to do a successful refactoring: Small steps handled by a task tracker under full version control, a framework to structure your software and your mind and a Test Driven Development to reduce complexity and to be sure about the correct result. Got it!
“Check in on successful test”
I strongly recommend to “check in” into the version control system only, if all tests are “green” (i.e. successful). In a lot of software projects this is a basic rule for all developers in order to ensure, that at least everything is consistently running in the test environment. This is a very basic requirement, I totally support, even if you are – like me – working on the project completely alone.
This requirement works in both directions:
- Don’t check in as long as at least one test is failing.
- Check in as soon as all tests are successful.
There is a prerequisite to do a successful collaboration using these rules: Do proper tests! (See topic 3 above.) This reduces the risk of unusable software tremendously. It will result in a) a lot of check-ins b) small changes within each check-in. And this is good, because it reduces complexity and supports your (and your team’s) understanding of each iteration. “Keep it small and simple” is the basic rule to avoid frustration. 😉