views:

1887

answers:

21

This is humbling, but probably something most can relate to. I am currently adding functionality to a PHP application I wrote for a client 2 years ago. In the interest of full disclosure, this was the first "real" application I ever built from the ground up, in the sense that I actually met with clients to determine and write a spec. I then built the application by myself, learning SQL as I went (I had some prior rudimentary PHP experience).

The client contacted me this week to make modifications to existing functionality as well as add new modules to the application. I realize now that I did a poor job of modularizing the application from the start to make additions easier. Currently, the code base is almost 20,000 lines of code (it is a fairly sophisticated, if narrow application).

I'm struggling with whether or not to "rewrite" the application to make future changes easier and more efficient. I should point out that the nature of my agreement with the client is one in which I will be the only person making modifications in the future. They will not seek another developer for this app.

The budding programmer in me always wants to do things in the cleanest and most efficient way in order to satisfy my own OCD, but I do intend to bill the client for any time I spend rewriting. Morally, I feel fine with this because the initial rate that I charged them was low - they got a stable, working app which has been performing without any intervention from me for 2 years, and I got my first real development project on my resume. My dilemma is about when to decide to rewrite an application for the sake of future development.

Please weigh in with your thoughts. I'm sure I'm not the only one who has ever had this problem.

If anybody has any questions for me that will help them with an answer, I'm now addicted to this site and will respond quickly :)

Thanks,

KN

+20  A: 

When do you know it’s time to rewrite an application

When the client will pay for it.

Ryan Farley
I don't see how this comment is helping anyone to make a decision.
Ilja Preuß
When have you ever built an application that you didn't think you could have done better if you could do it all over again? Getting rid of technical debt, moving to an easier to use or more up to date architecture, or just using all the "lessons learned" the first time around. Fact is, the time and cost involved in rewriting it is the only reason not to. So, if that isn't a factor, why wouldn't you? This is the only way things move forward and we're not all using ancient technologies anymore. All comes back to "when" client is ready to pay.
Ryan Farley
Beware the http://en.wikipedia.org/wiki/Second-system_effect.
MadKeithV
LOL!!!!!!!!!!!!!!!!!
Andrei Rinea
+5  A: 

This is fairly relative to me. My first application was also freelance, and was a 60,000 line classic ASP monster.

I still get calls to maintain it every so often, and while I've toyed with rewriting it, the truth is that it works (though times have changed), and that my client's confidence is worth having me pull a few hairs out when modifying it.

99% of all applications are crap, it just depends on how experienced you are when you look at them :)

FlySwat
+5  A: 

The time to rewrite an application is when the time/cost involved to fix it is greater than the time or cost to rewrite the application. It might be worth to look at only rewriting certain aspects of the application.

I would say it doesn't seem like you need to rewrite your application as you say it is stable and works fine. But ultimately the decision is on how often do you think you will be required or needed to make changes or additions to the application. If you are going to be adding to the app once every couple of years, doesn't seem to be worth the time depending on how long a rewrite will take again versus the time involved to write changes into the application.

I can understand the desire to rewrite is a strong one, but not always a smart one.

jtyost2
+1  A: 

I'm in a similar situation currently (interestingly enough also including PHP). My approach is to add best practices which I've learned about in the mean time (like tests) on an "as we go" basis (so I add one for each new feature and add for old features only when I touch the code). This seems to be a pretty lightweight solution currently.

Cd-MaN
+5  A: 

I have learned that it is very easy to make the decision to rewrite something... especially if it isn't your code (and code from 2 years ago is essentially someone else's code).

The problem is, when you get done with rewriting, I've found things can just as easily end up not quite as smooth as you imagine they will become.

It might be better to smooth out the areas needed to add the new modules, which will improve the system for further additions, but not waste the time to rewrite the entire app. This saves money for who you are working for, and saves you from ending up back where you started.

I am of this opinion because I took the route once to rewrite a particular control for an app (not the same as a whole application, but still)... the existing implementation had many things I felt I could improve upon, including better encapsulation, more DRY, and better performance. I ended up achieving the goal, but there was still performance problems and though I improved some of the modularization, it still ended up a lot more messy than I had envisioned.

I feel I learned the hard way that re-implementing is something you should take seriously, and only use this when there is design flaws that really warrant such an action (and to be honest, I don't know what kind of design flaws can require this, short of finding GOTO all over your codebase). Deciding to re-implement is an easy quick decision if you haven't delved deep into the code to really understand what it was you (or whoever wrote it) had been thinking.

Especially think what gains who you wrote it for will get out of a rewrite... and make sure they are fully aware of what is going on, and agree to it.

Mike Stone
+1  A: 

I agree with Jonathan Holland... I, too am often tempted to rewrite everything I do and I often give in to this instinct of cleanness but for me it is not a problem since coding is - at the moment - only a hobby. This is the reason my client does not care wether something is delivered this or next week/month - I am my client and the client is not satisfied if he does not like his code. On the other hand in your position I would rather not rewrite my whole program since I have experience with these things. What would you really do differently? You often need to come up with a new Object Relation Model to have (really) different code patterns. I would strongly recommend you to

  1. Talk to the client about this problem
  2. refactor your code

Refactoring your code should be much faster than a complete rewrite and since I predict you would not go that much differently about it codewise this is the way to go.

Resume: Refactor - not recode.

niklasfi
+2  A: 

I agree with Ryan. If the reasons for a re-write are strong enough and provide value to your client, they should pay. Really, it all comes down to dollars and cents. Are you saving them money with a re-write? It sounds hard to justify in your situation if you haven't had a call in 2 years. Heck, that is quite an accomplishment on your first app, or any app for that matter.

One measure I use is if the time to re-write would be less than or close to the time to make the change - hardly ever happens unless you are adding major features or refactoring something complex. If the app is going to be in a continual state of change and a re-write would ease the pain of those changes, then it could make sense in that situation as well.

I think most good developers are somewhat OCD, but we have to be pragmatic too.

JasonS
A: 

I'm also of the opinion that your should have a real strong technical reason to rewrite a piece of code that works well. When you rewrite you tend to focus on what you didn't like in the previous version and overlook other details in the new version. So even though the result is usually better, it is also usually not perfect, and more often than not it is not really worth the time.

Besides, it's always tempting to think in terms of "making future improvements easier", but in that kind of professional relationship, you never really know what the future looks like.

So in your situation, refactoring the parts that are really in the way of the work you know you have to do is probably a safer approach.

Carl Seleborg
+1  A: 

Thanks for all the quick responses.

I should make the following distinctions:

  1. This is a mission critical app for this client. A very large portion of their business depends on the ability for "untrained" staff to plug numbers and measurements into this application and produce a product for their clients. It essentially allows them to hire one or two engineers to make actual measurements and decisions, and a dozen temps to do data entry to run the calculations and reporting. In short, this application is very important to them.

  2. I know that rewriting the app will take longer than bolting on new modules. My concern is that if I force the new modules into this iteration, I may not be able to do it the next time around. At that point I would be rewriting a 40,000 line application instead of a 20,000 line application

  3. I think they would benefit from my better understanding of SQL at this point, and I would implement features like transactions, automated backups, and better security and maintenance procedures.

I know I sound like I've already made my decision, but trust me, I have not. I love programming, so money aside, this is not a chore to me. The client trusts me and will pay for whatever I decide is the best approach. I'm just looking for feedback on how to make a good decision on the technical side.

Thanks,

KN

Kyle Noland
+58  A: 

There's a secret 3rd option to the rewrite / don't rewrite decision: rewrite it a bit at a time continuously. This is the genius of refactoring, you don't have to make a monolithic decision to blow the whole works to smithereens and start from scratch, you can approach things piecemeal and work towards a better design as an ongoing goal. Don't rebuild the house from the ground up, instead paint the living room, then remodel the kitchen, then rewire the den, then redo the window, then landscape the yard, then fix the roof, etc. Eventually you end up in a Grandfather's Axe situation, allowing you to change more over time than you probably ever feasibly could in one huge chunk.

You can do this at many different levels, making little improvements with most every checkin (using extract method, rename variable/method, etc.) to make chunks of code more readable and more maintainable. Or making big improvements using dedicated budgets, still working incrementally from point A to point B but having the firm goal of reaching point B (the improved design). You can still make breaking changes but you need to be smart about making them. Rather than just replacing some bit of functionality with some completely new way (i.e. API) of doing things you can keep the old bits in place and add new stuff in addition to it, then you can flag the old bits as obsolete and then later delete them, after people have been given enough time to make a graceful transition to the new way of doing things.

Wedge
A: 

Whenever you feel resistance towards extending, maintaining or fixing bugs in the application take it as a sign that it's time for some serious cleaning. That doesn't necessarily mean you must rewrite everything from scratch. Most of the time some refactoring will go a long way.

Anders Sandvig
+16  A: 

See Things You Should Never Do.

grom
+1  A: 

When you are asking yourself if you should

Juan Manuel
+1  A: 

The general consensus in the answers seems to agree with me; Don't rewrite the application.

Years ago I inherited a similar application. It's large, in PHP, very old, and difficult to add new functionality to. About 18 months ago I was able to switch out most of the "framework" with a new version and that solved lots of my problems. It only took about a year of tweaking calls to a handful of page template and library calls to make it fairly easy to swap the older bad code for some better stuff.

The app is mostly just very custom reports and forms and there are some really old pages. To give you and idea, one of the oldest reports has a page id of 3 while the login page has a page id of about 100.

To date I've probably added 25k lines but I'd bet that 80% of the original 6000 or so lines are still there (more or less)

I can get away with slowly evolving the program because I spend an hour or two every day working on it. The other approach that comes to mind would be to make new, fancy, modules that sit beside the existing code and operate on the same data. All you have to do then is tie into some session and permission data but otherwise those pages are separate. If that's the better framework to work in then future updates will all be made in the new "side" of the app possibly eventually leading to a migration.

But even if you eventually migrate to a new framework you should be able to preserve most of older pages.. ideally you'd just replace the files & functions loaded at the top and bottom of a file while leaving the rest almost unchanged.

Good luck.

Eric Goodwin
+2  A: 

Refactor as you go. Learn from netscape, don't rewrite.

paan
A: 

Hi Kyle,

I've got a similar situation in front of me: continue using a difficult to use custom built code generation/ORM tool that drives most of the tools we write around this shop or use something like Ruby on Rails or symfony (basically Rails for PHP). We spend so much time trying to make the existing framework work for us and previous developers have done horrific workarounds. I'm the newest developer and am pushing hard for a rewrite. Modularity is the key here. The current code base is no longer modular enough and it's like taking a square peg and making it fit into a round hole. They keep shaving the damn sides off the square peg instead of using a round one. ;)

Good luck and let us know what you've decided and how it works for you.

beaudetious

beaudetious
+2  A: 

Trying to rewrite a 20kloc app singlehandedly in onw go is professional sucide. Refactor as you add new features, change the stuff you find most painfull to work with first.

I've seen bigger than 20kloc CLASSES. *sigh*
Matt Cruikshank
+2  A: 

I realise I'm a bit behind here, but I guess that's the beauty of the web - everything's current until you bother to check the date of the post! ;-)

Anyway, I wanted to post my thoughts (and possibly kick-start the thread again) because your post struck a chord with me. I have an application almost exactly like yours, albeit it a bit smaller: PHP + SQL, ~5KLoC, first "real" app I wrote, first web app I wrote, etc., etc. I was young and innocent, and after I handed off on it, I had something I was proud of (hey, I'd got it working!), and a relatively fat wad of cash in my back pocket.

A few months later, I got a couple of bug reports. I went back to the project and found a horrible mess of PHP and SQL intertwined. The admin part of the site was one ~2.5KLoC file, with duplication all over the place. The database was possibly the best-designed bit, and that was only partially normalised. It was truly ghastly, and very quickly I realised it was going to be a nightmare to maintain. I fixed up the bugs and moved on.

A couple more bugs came in. I fixed these up, and the sinking feeling got worse. The last time some bugs came in, I mentioned re-writing it (I was still young and innocent and hadn't heard the Netscape story), that the code was effectively unmaintainable. Luckily, it seems I'd ironed out the remaining major flaws; I haven't had any bugs in since (I'm still in touch with the client!). I never did start re-writing that particular application.

And, to be honest, I'm glad of that. Like most other projects I work on, this was a hobby/spare-time project. I got paid for it, which put a bit more of a fire under my ass. The original project was a kind of content management system, so as I learned more, I tried starting it again twice. The second version (for a University orchestra) is still used, and was a vast improvement over the original one. I used multiple files, functions, templates (of a sort)... Good times :-) But still it was a bit rubbish. The third version used object orientation and all the associated goodness, the Smarty templating system... Even better times :-D This one never got finished. The complexity of the system's requirements started to overwhelm me, and I eventually just stopped working on it. I quickly found that there were a number of other content management systems around that would do what I wanted, one way or another, and I haven't turned away from Drupal since taking that step two years ago!

When is it time to re-write an application? Hardly ever; I agree that re-factoring is nearly always the way forward. Even my monster original version could have been re-factored relatively easily and painlessly. Only if you're wanting to do something radically different from before should you really consider it.

alastairs
+1  A: 

Rewriting a piece at a time seems like the best thing to me. Try to find functionality that can be consolidated into a function or class (static or instantiated) and move things around piece by piece, simplifying the code as you go.

Voyagerfan5761
+1  A: 

The time to rewrite is when you notice that you have to change the same thing is several places in the code. That is, when you are adding a new piece of functionality and you end up adding that in more than one place.

I've been working on a legacy code base that contains some 600.000 lines of code, and I suspect that maybe 90% of that code is duplicated (seriously!).To add something new, I have to add that in 60 different places (seriously!). In this case, refactoring is not an option as it would take longer to remove those 90% than starting from scratch.

Martin Wickman
A: 

There might be an option that is somewhere between rewriting and refactoring. If the data model is salvageable, you can graft on a web application in a framework such as Ruby on Rails to do the new functionality and just put links between the new site and the old site, gradually replacing the PHP components that are difficult to maintain or malfunctioning. Since it's a web application, you should be able to integrate a new framework without too many headaches other than managing passing authentication credentials back and forth.

If writing in another language/platform is not an option, then refactoring is going to be the way to go. It's painful to our computer scientist, everything-in-its-place minds to not go back and just do it the way we would have if we had known what we know now, but it's better than risking breaking the whole app and creating more pain for the client (and more late night calls for you).

brokenbeatnik