I am a 23-year-old living in Blacksburg, Virginia (Virginia Tech). I have been working with the web since I learned HTML in 7th grade and have been having a lot of fun with it ever since. I work for a local design and development company called New City Media as a PHP programmer and database developer. My work-load consists of mainly writing PHP code, designing database tables in MySQL 4/5 or MSSQL 2005, general tech support for our hosting, DNS, and database servers and also the occasional tech support call for a client. Mike is a DZone MVB and is not an employee of DZone and has posted 16 posts at DZone. You can read more from them at their website. View Full User Profile

Code Refactoring - Freaking Awesome

01.16.2009
| 21528 views |
  • submit to reddit

We have all gone back and looked at code we wrote in the past and thought "Wow, this is ugly.", or "wtf was I thinking?", or even "I wrote this yesterday, and I have no idea what it does." Refactoring is the process of going back over already-working code and cleaning it up for the sole purpose of understandability, maintainability, and preserving your self-worth if anyone else were to take a peak. No one likes to be humiliated by their own code.

Refactoring is one of those ideas that has always floated around in my head but I never knew what to call it, or how to handle it. For me, it makes a huge difference to give a loose process like refactoring a name because it solidifies its usefulness. Sameer Borate wrote a nice introduction in a series of refactoring articles on his website. He describes refactoring as an idea similar to design patterns and unit-testing which, on the surface may seem to be a waste of time but in the end, saves a lot of frustration and grief.

Refactoring is a process of changing code to make it more understandable and structured without changing the code functionality or introducing additional bugs. Informally it is known as ‘cleaning up code’. Refactoring is based on the tenet that the written code is more important to the human reader than it is to the machine. Many programmers write code with the idea that once the program is complete and working the code will not be touched again. But this seldom happens. Features need to be added, bug issues need to be fixed. This may happen tomorrow or months from now; wherein you need to really remember what a particular function did. Comments in the code may be useful, but not much if the code written is not differentiable from the half eaten spaghetti bowl sitting beside.

In a nutshell, here is a snippet of an script that is completed and working:

<?php  
if (date('L', strtotime('+1 year'))) {
// some code..
}
?>

I sure as hell can never seem to remember what some of the more obscure date format characters like capital L represent. If I were to look at this if statement I might have to take a few moments to look up what it's doing. L of course, returns 1 if i is a leap year, and 0 if not. You can quickly and easily make this code more readable by throwing that in a function and give it a descriptive name.

<?php
if (nextYearIsLeap()) {
// some code..
}
?>

This is a pretty crude example but I think it gets the point across. The big thing for me is to realize that you should not waste your time by trying to code in this fasion from the beginning. Rather, get the application working then go back and tidy things up. Just don't forget :p

References
Published at DZone with permission of Mike Bernat, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Arek Stryjski replied on Fri, 2009/01/16 - 12:08pm

I think it will be nice to mention Martin Fowler when talking about refactoring http://martinfowler.com/books.html#refactoring

I also believe you got refactiring wrong. It is not an excuse for coding in a bad style.

I was never refactoring because I had too much time, so I could play with aesthetic aspect of the code. If you are coding something in the ugly way, I'm sure it will stay this way till someone will need to understand this code and change it out of frustration and anger at you. 

Sometimes we need to refactor even if the code was made in correct way (to our knowledge at the time of writing it). But we should never excuse our laziness because someone invented the ways to corect bad writen code.

 

Tracy Nelson replied on Fri, 2009/01/16 - 12:38pm

Refactoring is NOT about "cleaning up code".  Cleaning up code is what you do before you check your code in to a repository.  Refactoring is taking working code and breaking it down to either make it more manageable (like changing all your logging statements to use a proper logging facility rather than spewing everything to the console) or to adapt to some changing requirements (like if your application supports an abstract class Vehicles with concrete subclasses Car, Truck and Motorcycle, and then you get a requirement to support Boats as well: you'll probably wind up creating new abstract subclasses of Vehicle called LandVehicle and WaterVehicle, with Car, Truck and Motorcycle inheriting from LandVehicle).

Ronald Miura replied on Fri, 2009/01/16 - 2:39pm

"The big thing for me is to realize that you should not waste your time by trying to code in this fasion from the beginning."

It's impressive how people can distort others' words to fit to what they want to hear. Just like translating "agile" to "we don't need documentation".

Mike Bernat replied on Fri, 2009/01/16 - 4:33pm

Thanks for the comments everyone :)

@Arek

I certainly don't recommend coding in a bad style. In fact I don't think I did that. However, doing things like simplifying conditional statements by putting them in a function simply isn't necessary. The point I was trying to make was to not get caught up in making beautiful, understandable, code from the very beginning. This is NOT to say that you should give a rat's ass about comments, readability, and absolutely not functionality. If you are a lazy coder, refactoring is not for you because you have bigger problems to deal with.

 

@Tracy

I would agree with you that refactoring is definitely a more serious degree of 'cleaning up your code'. However, I'm not so sure that enhancements or additions qualifies as refactoring. Correcting possible bugs or creating extra cases for something also, imho, falls outside of refactoring.

 

@Ronald

I'm not sure if you are defending or attacking my words. Either way, read my above comments to Arek. I guess I have to get used to people interpreting my statements as being absolute.. I'm more of a middle of the road kinda guy.  

 

The topic  I did not touch on but should have, in this small, quick post, is the importance of unit-testing. As we all should know by now is that when we go back and touch code, in any respect, you risk breaking some part of your site. Hopefully it's obvious, but what if you broke a fringe case? Unit-testing is critical.

 

Evgeny Zislis replied on Fri, 2009/01/16 - 5:46pm

You write about it like you never read Martin Fowler's book, like you are trying to invent refactoring from scratch. Stop. Just go and read the book, and then come back and write a proper article.

Sean McArthur replied on Fri, 2009/01/16 - 6:40pm

Perhaps its your example, but I would actually recommend against refactoring that if statement into a function that you are only going to use once.  Maybe if you will use it multiple times...

Instead, I would just put a comment right about the if statement:

//if next year is leap year

If, instead, it just reads a function, and you're debugging, you could see that function and wonder: Is that function causing the error? Now you have to place bookmark, and do a Search in files for that function and double check it's doing everything properly.

I would say refactoring code is more for when you've written a process, and since realize that you could do so more efficiently with a better query, or a recursive function, or some such.  Properly commenting if and for statements makes my code readable in the above situations.

Remigijus Bauzys replied on Sat, 2009/01/17 - 10:03am

Everyone going too far on commenting this article should remember that even variable, method, function renaming is considered as refactoring. Even duplicate code extraction to an external method is aldo refactoring. Nevertheless sample code is too primitive, but raised problem is still a valid, how many developers can understand their code after some time. Some coders have to respect other people who will take code after them, clean, easy understandable code should be valued as top priority.

Tracy Nelson replied on Sat, 2009/01/17 - 11:30am in response to: Sean McArthur

I would actually recommend against refactoring that if statement into a function that you are only going to use once.

 

I used to think that way, but now I feel that with TDD it's not unreasonable to have lots of small utility functions that may only be used once or twice.  That's one of the things about refactoring the author actually got right: if you've got a piece of code that does something that's not necessarily related to the task at hand, isolate it and put it someplace else.  If it's just a complex expression you're simplifying, add the code right after the code you're refactoring.  If it's a general-purpose routine, put it in its own class.  After all, just because you're only using it in one place today doesn't mean you won't need it somewhere else tomorrow. And part of the refactoring should be writing proper unit tests for the function, so you shouldn't have to worry about it causing errors.  You might also wind up discovering you have several date-related functions, so it might make sense to collect them into a single (library/assembly/jar file), so now it's easier to find them and you have a defined place to put new ones as you write them.

Tracy Nelson replied on Sat, 2009/01/17 - 11:39am in response to: Mike Bernat

It almost sounds like you've got refactoring somehow confused with prototyping.  When you're prototyping something, you can get away with sloppy/lazy coding, because all you're doing is proving a concept.  If the idea doesn't pan out, then you haven't wasted a lot of time.  If it does work, then you go back and clean up the code.  That said, prototyping is what you do when you don't know what to do (i.e., you don't have a design), it shouldn't be the way you write code in general.

Adam Conover replied on Sun, 2009/01/18 - 4:45am

I think that a point being overlooked by the "write it correctly first" comments is that time constraints often force you into a "it has to work now" situation.  Sure, proper design from the outset is always preferable, but logistics often create a situation where a something functional is preferable over something well designed.

Since all good programmers know there is no such thing as code that will never be revisited, "refactoring" the hasty design decisions out of the code after the fact is often your only reasonable choice.   Having good tools to assist in this endeavor can be a real time saver... if used as soon as possible, and before the customer starts requesting new features.  (Of course, good unit testing is also critical these situations.)

As an aside: I've also completly given up on the idea a prototype ever being something that is eventually scrapped.  Unless you are dealing with a customer (or boss) who really understands the issues involved in developing quality software from the outset, your prototype code is destined to become production code (due to the afore mentioned reasons)... but I guess that's a seperate discussion.

Franz Wong replied on Sun, 2009/01/25 - 3:26pm

Comment tells lie most of the time. Programmer always forget to update the comment after he makes a change on the code. However, the method name is part of the code, programmer has a less chance to forget to modify the method name.

Only when the method is called by many times and peroformance is a critical issue, change back to the original form.

Also, code inside a single method should be in the same abstraction level. You won't read the story of one chapter in table of contents.

Scott Herndon replied on Thu, 2009/02/12 - 6:09am

Tracy,

 

Excellent comments. I could not agree more. As someone with more than 20 years of OO behind me it is often amazes me how how these concepts which are as old, if not older, and most formulated around Smalltalk, have suddenly become brand new.

Refactoring is an essential part of any OOP, and bascially inidcates you know more today than yesterday. Often I find the refactoring flag being raised as my objects become too complex or take on too many behaviors or roles. Refactoring for clarification, such as method or class names is also important to later code managment. Still the author makes a legitimate point, and that is programming in a straight jacket or being paranoid about ones code is not good for one's health. Refactoring does give one a chance to make mistakes and go back and fix them, not so much bad code as naive. After all the more one becomes familiar with a problem space the more they should have learned how to manage it.

-Scott

Chief Architect

TrustBased Software, Inc.

 

 

Ash Mughal replied on Thu, 2012/01/26 - 3:52am

Unit testing is good when refactoring, ok. But it shouldn't be an excuse for you to be sloppy and write unreadable code. In fact, unit testing is best used when you have functions/methods with good (readable) names, that represents its intent, not some 'yadayada()' method that for some reason should return 'true' when you pass '0'.

advanced java

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.