Refactoring - Sometimes it gets messy before it gets clean
Recently I tweeted.
I am still working on this little side project and it has been pretty fun so far. One thing for sure is that just like many cleaning projects it always seems like it gets a bit dirtier as you throw stuff around before the project gets cleaner. Right now if I just checked in my code it would be bad, very bad. The code is brittle at best and the coupling between modules is so high it might reach into space. But hey it is just a first step and what does this first step look like?
It follows the general advice to look for similar functions and put them in their own code files. Note I did not say class. Since I have so much code to wade through I did not want to figure out on my first step all of the places I had to instantiate a new object and call it, plus I would have probably gotten the class wrongly designed in the first place. So, I mainly just referenced the different code files in the main class and made them static methods for the time being. Some of the code files turned into what would be expected like file utilities (deleting temporary files, writing to common locations, etc..), HTML utility methods, etc... I am not a huge fan of utility "classes" but wading through 800 lines of utility code and figuring out a design for common items is tons easier than wading through the gigantic mud-ball that currently exists.
Once I moved a few of these general functions around I started on something that would make a bigger impact and would be a little tougher. You have to understand one thing about Delphi is that it is a RAD language I don't mean it is cool I mean it is a Rapid Application Development language, what does that really mean? It means it turns into a huge event-driven mess that makes grown men cry when a button event, updates a field, which fires an update event, which updates a field which updates some dataset which then fires another event, you get the idea. All of these reports had events tied to them which meant a lot of code to move and a lot of interdependencies that would be "fun" to move, but hey I was up the challenge :). I did what any sane code-junky would do I copied the report objects into a new class and then leaned on the compiler like I had just finished a fifth of vodka on my own. To get the code to compile and be functional I had to pass in a reference to the monster class. This means there was now a recursive dependency between the two which is not prime but like said earlier it is a start and this was one of the messy parts of the code. To give you an idea on the interdependencies I tried to pass in the needed parameters for a method but I gave up after the parameter list grew to 15! Once I got this area to compile I then did some quick functional testing to make sure the program was you know still usable.
At this point I had shuffled around 4,000+ lines of code and things where looking slightly better and there was at least a glimmer of hope. What are my future steps? I plan to continue to look at the methods in the monster class and bucket them out to code files. After that I will start to move them into classes, implementing interfaces and hopefully writing some tests. I will write about my progress at each step of the way. If there are any questions on how I am doing something or advice from other people who have tackled similar monster classes that would be awesome.
About to put my refactoring skillz to the test. The challenge a 27,000+ line "class" for a delphi CGI.
I am still working on this little side project and it has been pretty fun so far. One thing for sure is that just like many cleaning projects it always seems like it gets a bit dirtier as you throw stuff around before the project gets cleaner. Right now if I just checked in my code it would be bad, very bad. The code is brittle at best and the coupling between modules is so high it might reach into space. But hey it is just a first step and what does this first step look like?
It follows the general advice to look for similar functions and put them in their own code files. Note I did not say class. Since I have so much code to wade through I did not want to figure out on my first step all of the places I had to instantiate a new object and call it, plus I would have probably gotten the class wrongly designed in the first place. So, I mainly just referenced the different code files in the main class and made them static methods for the time being. Some of the code files turned into what would be expected like file utilities (deleting temporary files, writing to common locations, etc..), HTML utility methods, etc... I am not a huge fan of utility "classes" but wading through 800 lines of utility code and figuring out a design for common items is tons easier than wading through the gigantic mud-ball that currently exists.
Once I moved a few of these general functions around I started on something that would make a bigger impact and would be a little tougher. You have to understand one thing about Delphi is that it is a RAD language I don't mean it is cool I mean it is a Rapid Application Development language, what does that really mean? It means it turns into a huge event-driven mess that makes grown men cry when a button event, updates a field, which fires an update event, which updates a field which updates some dataset which then fires another event, you get the idea. All of these reports had events tied to them which meant a lot of code to move and a lot of interdependencies that would be "fun" to move, but hey I was up the challenge :). I did what any sane code-junky would do I copied the report objects into a new class and then leaned on the compiler like I had just finished a fifth of vodka on my own. To get the code to compile and be functional I had to pass in a reference to the monster class. This means there was now a recursive dependency between the two which is not prime but like said earlier it is a start and this was one of the messy parts of the code. To give you an idea on the interdependencies I tried to pass in the needed parameters for a method but I gave up after the parameter list grew to 15! Once I got this area to compile I then did some quick functional testing to make sure the program was you know still usable.
At this point I had shuffled around 4,000+ lines of code and things where looking slightly better and there was at least a glimmer of hope. What are my future steps? I plan to continue to look at the methods in the monster class and bucket them out to code files. After that I will start to move them into classes, implementing interfaces and hopefully writing some tests. I will write about my progress at each step of the way. If there are any questions on how I am doing something or advice from other people who have tackled similar monster classes that would be awesome.
Labels: coding