You've worked somewhere for 3 years. At the beginning of the second year you were involved in what you thought would be a small project. You foolishly decided to take some risks with the choice of tools, you got slightly out of your depth, you ended up writing some nasty hacky code in the end as delays kicked in.
The client loved it, your boss loved it so much he started white-labeling it, and selling it on to other clients.
You've been the lead developer on this code that you can't bear looking at for over a year. It goes against all your programming morals. You are scared of refactoring it because it's been live for ages, everybody is happy with it except you. You're not quite prepared to squeeze in the refactoring in work time, because there is always more important things to be done.
Do you take it upon yourself and decide that it must be refactored, let it eat into your spare time because you deserve it?!
Do you carry on and hope nobody else notices what an awful mess the project is?
Do you leave your job and hope your work friends don't phone you, curse you forever more?
"You are scared of refactoring". That's the key here - don't be. No one noticed yet, it is all working, take the time (your time) to get it where you think it should be. Start carefully with source control as safety net and start digging out of the hole.
In my mind there is no better way of becoming a real architect than that. Good luck.
You are scared of refactoring it because it's been live for ages
So what you're saying is that there aren't any unit tests.
If you have sufficient coverage and high enough quality tests you could refactor with some confidence. As long as you moved slowly and didn't break any tests you'd be fine.
Start by generating unit tests. Create that safety net before you start.
Do you take it upon yourself and decide that it must be refactored...
Yes!
... let it eat into your spare time because you deserve it?!
No! You don't deserve it. You've done a great job. Now, continue doing a great job by explaining how design is a learning process, you've made some mistakes, and you need to go back and do some housekeeping so that the project can flourish.
Trying to be a hero and silently burning yourself out is not good for your company and not good for your career.
I have just 50% re-factored a monster child of a very brilliant programmer (he moved on to greener pastures); his problem is that he was usually stuck in the first gear - making progress very fast, being able to keep a lot of stuff in his head at once, but not paying much attention to details. If he was a soccer player, he would be the guy who scores the most. I would be a defender I guess.
Not trying to sound cocky, but I think I was the perfect complement - someone who prefers to work in second gear, loves small but sure changes, loves unit-testing, etc. If only I had more time, I would polish this bugger until it shines.
I guess it might take a programmer with certain personality - loves to simplify, like to move cautiously, someone who over-asserts and over-logs (within a reason).
The thing is that before you build something, you do not know what it should look like exactly. A working prototype is better than any spec. You might want to have someone else polish it. Their job is easier - they know what it should do, they just need to remove rough edges. Plus, a fresh pair of eyes is always good. As long as that someone is as good coder as you are - you should be ok.
I usually try to hold myself to high coding standards, but some of my colleagues are more relaxed than that, so I have less of perfection paralysis now as well.
But then again, it could be you who re-factors it. Your problem may be that you know the design all too well.
I'm an idealist - I'll always side with re factoring. As long as you are careful and have good testing mechanisms in place you should be able to very gradual refcator the code fairly safely. The key is to make gradual changes rather than sweeping changes.
If you don't have reliable unit testing then work on that first - you should be able to make changes to your code and still sleep comfortably at night!
You should also consider that if everyone else (including clients) think its so awesome, perhaps its not as bad as you think it is. I've found that we programmers tend to be very idealistic about clean code and architecture - its easy to lose sight of the fact that what really matters is the compiled software.
Of course this is all only relevant if this is what you want to be doing - don't feel tied into maintaining a piece of software you wrote out of guilt.
I think the question becomes: is it a maintenance nightmare?
If it works, the client is happy and it's not hard to maintain, has a crime been committed? Yes we like to structure it properly, but we need to make sure that's to deliver better ROI to the business and not to satisfy our own OCD.
Definately do NOT refactor it in your own time. If you've done the best you can with the constraints imposed on you by the business, how can it be your "fault"?
You need to be able to refactor any code you touch. It should not take a lot of extra time to do so, If you do not have time at the moment add some comments on what you would like to do within the code.
On another note: What is your career goal ? Do maintenance work on this until it is useless ? I would tell my boss that you want to move on to other projects. If not you will end up being the maintainer of this one project until it is no longer useful. At that point you will be so antiquated that you will become useless to the company you work for.
Another option - move to management :)
If you're the lead on the project and it's your only responsibility you should appropriately schedule time to re-factor parts of the project (it doesn't have to be done all at once does it?..). If you have more responsibilities that you are not the lead for you should explain to your CTO why the re-factor is required and again schedule the time. CTOs/CEOs understand technical debt [1].
You should also start by just doing unit tests (I assume the quick hacky codebase didnt include full unit tests :P). Make sure that your re-factor doesn't change behavior.
[1] http://en.wikipedia.org/wiki/Technical_debtAs you go through, refactor what you're working on anyways, and realize that:
If you can't hack it, find a new job; three years is a pretty long stint in technology. You'll take lessons with you, you'll get a raise for doing it, and you'll get to work on a brand-new project.
As a strong suggestion, spend at least a month documenting every last hack you can remember, so that you're not leaving the next guy a terrible mess; do not burn your bridges with your replacement.
I'd mix the strategies; refactor what you touch to be right. Do not spend overtime on it, but slow your estimates down to allow yourself time to do things in a sustainable way. While you refactor, if something can't be refactored right then - or at all - document it heavily. In two or three months, start looking for new work, and take at least a month to transition out of the role when you do find new work.
I would highly recommend Michael Feathers' book, Working Effectively with Legacy Code [1]. It addresses exactly this issue - how to take a large, unwieldly, badly-written codebase, and clean it up.
The point that Michael makes over and over is that you have to get your code under test, wherever it's reasonable to do so. He gives refactorings that you can use to help introduce unit tests to clunky modules, and break dependencies. You can start to build unit test coverage for small, safe pieces of your code, as you go through. Create unit tests covering a section of code as much as is feasible before you change it, so you can determine whether your changes have unintended consequences.
[1] http://rads.stackoverflow.com/amzn/click/0131177052There is a good book about this, Working Effectively With Legacy Code [1]. Where legacy code is defined as code without tests.
The gist is what the scouts say when camping, "leave the site cleaner than your found it." You don't have to boil the whole ocean at once, which would probably break things anyway. If you see a quick fix make it. As you add or modify put a test in. As the tests build up and you start to pull out duplication,the changes can snowball and it will become less intimidating and of higher quality.
At the highest level it's working, don't mess with it unless you're sure you can make it better or you need to dig in for some other reason.
[1] http://rads.stackoverflow.com/amzn/click/0131177052Do you take it upon yourself and decide that it must be refactored, let it eat into your spare time because you deserve it?!
Spare time? What's this?
I've inherited several monsters over the years. I sometimes describe them as houses of cards made of tissue. Every now and then, I buck up, look at one, and think "If X did this, how would he/she do it?" with X being the appropriate role model for the job (coworker, Dijkstra, etc).
A lot of the refactoring can be done by encapsulating current functions into separate units. Sometimes, much clarity can be gained by simply restructuring what seems to have grown haphazardly (new namespaces in C# come to mind).
When I feel guilty over time potentially lost refactoring, I tell my self: "No, at least I made it simpler."
From the description of the problem it sounds to me not that the author is scared to refactor but that he knows intuitively that refactoring while continuing to add features might be biting off more than he can chew.
Refactoring a large project like that will take some time and thought and a lot of focus which isn't something that can be easily done while continuing to fix bugs and add new features.
I'd suggest talking to your boss and convincing him that a refactor is needed and you will need 3-6 months to do it. You could also suggest getting someone else on your team and split the code into two branches, you can work on refactoring while your new team mate(s) adds additional functionality.
Basically like any difficult problem its best to divide and conquer.
Remember this is a successful product for your company so I wouldn't think of it as a failure in anyway. This happens all the time with small projects. Anything that grows seriously beyond its original scope is going to need some deep refactoring.
You are scared of refactoring it because it's been live for ages, everybody is happy with it except you. You're not quite prepared to squeeze in the refactoring in work time, because there is always more important things to be done.
If everybody is happy about it, then don't touch it, unless you're getting paid for refactoring.
Do you take it upon yourself and decide that it must be refactored, let it eat into your spare time because you deserve it?!
No. You know what should be top priority for a good programmer? family/relatives/wife/girlfriend. If you hate the project, you definitely shouldn't do it in your spare time. Your spare time should be more valuable than the project.
Do you carry on and hope nobody else notices what an awful mess the project is?
I would wait till they notice and ask me to refactor it. Once I'm done, I would ask for raise.
Do you leave your job and hope your work friends don't phone you, curse you forever more?
Now that sounds plain paranoid. I'd recommend to take a vacation. Friends are called "friends" because they're supposed to understand that you hate this thing with passion.
Leaving your job because of "monster you created" makes sense only if you really hate that project, and there is no other way to deal with the problem. Few things you should think about:
I've been in this situation many times, both because of crap I wrote myself and because of crap that other people wrote and then dropped in my lap. My advice years ago would have been to use your powers of communication and persuasion to get your bosses to understand that it would be cheaper in the long run to toss your duct-tape-and-chewing-gum-special in the trash and start over.
The reality is, unfortunately, that your position is hopeless. If your bosses had any technical capacity whatsoever, they would already know what a piece of junk it is. Since they don't know that, you instead become a person who is insisting that this valuable program (which they've already made money off of and which has already substantially enhanced your boss' standing in the company) is in fact worthless.
If you stick to your guns and insist that the program should be rewritten from scratch, you create a situation where the company has two options: 1) take the hit of the rewrite; or 2) allow you to resign so you can "spend more time with your family".
I have to vote for your second choice (carry on and hope nobody notices), because it's in everybody's best interests (except your clients, of course) to not notice.
You should learn to master the skill to sell small refactoring improvement in the feature package. I'm not saying to lie to your bosses or trick them, don't. Just tell them that the feature "A" takes At + Rt time where Rt is the refactoring time (a small percent added to the feature "A" time. I second every good advise above about having either automated unit tests or regression ones. I duly note that writing unittests after is quite boring (even more if the code is actually yours). I'd start with solid functional/regression tests for the overall functionalities and picking up the single unit of codes with not-so-deep unit tests. What I mean is: do not spend the whole lot of your time writing tests for each and every case during the refactoring session.
Keep in mind that also the tests needs to be refactored.
At
:) In my experience, it's 3 times bigger than you expect, even when you take this rule into consideration. - Mark
Answer for me is always: rewrite. Rewrites are fun because they reflect on the knowledge you've gained since you last started working on the project, and they also give you an opportunity to make the code as clean and efficient as possible.