Jump to content

  • Log In with Google      Sign In   
  • Create Account


Should one refactor while writing?


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
19 replies to this topic

#1 Shaquil   Members   -  Reputation: 815

Like
0Likes
Like

Posted 22 September 2012 - 04:08 PM

Sometimes I'm in a situation where I have an idea that I want to roll out immediately. I want to implement it, see how it feels, and make design edits from there. This is when I'm thinking about user experience instead of actual code. Unfortunately, when you know exactly how to do something, you often know multiple ways of doing it. There's a quick, ugly, embarrassing way, which can be done in 15 minutes, or the slightly more elegant, less embarrassing way that will make you think a little bit.

My first question is, do you guys often do the quick and dirty thing, and then go back to fix it later; or do you get a hold of yourself and make sure you get the job done well, first and foremost?

My second question is, what is your attitude about refactoring? I've heard Code Complete is good, and I've been recommended Refactoring by Martin Fowler, but I won't have the money for those books for a little while, and I think my question is specific enough to ask and expect reasonable answers. To narrow it down: Do you refactor while coding, or do you refactor after everything's done? I've always thought it might be good to take breaks during long projects to fix up what's there already before moving on, but I dunno. Could you guys share a little on that? Thanks.

Sponsor:

#2 jwezorek   Crossbones+   -  Reputation: 1651

Like
4Likes
Like

Posted 22 September 2012 - 05:16 PM

The answer to your question depends on a lot of things but mostly
1. How big a job or time-consuming of a job is the re-factoring going to be?
2. Where are you in terms of deadlines and external commitments to getting stuff done.
3. How bad is what you have without re-factoring and how bad is it going to be to continue with it without re-factoring.

Generally, for hobbyist or personal projects you can do whatever you want but just be wary of the fact that constantly rewriting stuff in an attempt to make everything perfect and beautiful is a good way to never actually finish anything.

For non-hobbyist / stuff you are doing professionally, it's a different situation -- often the choice isn't yours to make when dates need to be hit and so forth.

Edited by jwezorek, 22 September 2012 - 05:16 PM.


#3 Geometrian   Crossbones+   -  Reputation: 1432

Like
0Likes
Like

Posted 22 September 2012 - 07:12 PM

Ideal solution: write up the perfectly designed code the first time in fifteen minutes.

It's half a jest, but seriously, good design is not very hard, and provides enormous returns for your effort. Good design is all about making your life easier. If you're spending more time designing and coding something "elegant" versus only coding something crufty, you're not doing it right.
And a Unix user said rm -rf *.* and all was null and void...|There's no place like 127.0.0.1|The Application "Programmer" has unexpectedly quit. An error of type A.M. has occurred.

#4 wqking   Members   -  Reputation: 756

Like
0Likes
Like

Posted 22 September 2012 - 08:51 PM

Anything is NOT done before you refactor your code.
I usually split coding to small tasks, after each task, I refactor for it.
Or I will refactor if there is enough code, eg. 1000 lines of code.
The small refactor is lower cost than big one (refactor after whole project is done).

http://www.cpgf.org/
cpgf library -- free C++ open source library for reflection, serialization, script binding, callbacks, and meta data for OpenGL Box2D, SFML and Irrlicht.
v1.5.5 was released. Now supports tween and timeline for ease animation.


#5 Servant of the Lord   Crossbones+   -  Reputation: 17281

Like
4Likes
Like

Posted 22 September 2012 - 09:32 PM

I don't refactor while in the middle of making changes, but yeah, I refactor when needed between changes or after changes.
I don't refactor for refactoring's sake, but only when the code is messy or will soon become messy through changes that refactoring could prevent.

As Geometrian says, it's best to write it clean the first time. My code usually is clean the first time, and only accumulates cruft over time from additions - that's when I refactor. Occasionally (but not too commonly), I need to refactor after writing it the first time because I had difficulty comprehending the first time through. I'm talking function-level refactoring, not architecture-level refactoring. I have to do architectural refactoring every so often because I'm still learning good architecture and make alot of mistakes there.

Code Complete is worth the money when you can get it.

Edited by Servant of the Lord, 22 September 2012 - 09:36 PM.

It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.

[Fly with me on Twitter] [Google+] [My broken website]

All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.                                                                                                                                                       [Need free cloud storage? I personally like DropBox]

Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal


#6 jbadams   Senior Staff   -  Reputation: 17320

Like
1Likes
Like

Posted 22 September 2012 - 10:42 PM

My first question is, do you guys often do the quick and dirty thing, and then go back to fix it later; or do you get a hold of yourself and make sure you get the job done well, first and foremost?

This really depends on a number of factors:
  • Why are you writing the code?
    • Is this just a quick disposable test to find out if an idea works, or is it production code? If it's just a quick test that will be thrown away it's often best to simply get it working as quickly as possible, but production code should always be as clean as you're able to manage within any other constraints
    • Is the code part of a larger project and/or likely to be reused? Are you likely to need to adapt the code for other uses? When writing code that will be re-used, which you might need to re-purpose, or which will be part of a larger system it's important that you design it as well as possible. If you're writing a little script to automate a one-off task it really doesn't matter as long as it gets the job done properly.
  • Are you time limited? If you have a deadline to meet you might not have time to formulate and implement a better solution. Obviously if the "quick and dirty" solution is too dirty and will cause extensive additional problems or might not work correctly you'll need to try your best to get the deadline extended, but if it's going to work fine and won't cause a massive blow-out in some other area or at a later stage then it can sometimes be necessary to simply choose the solution that allows you to meet your deadline.
  • How "dirty" is the "quick and dirty" solution? As above, is it just a sub-optimal solution that will otherwise work alright, or are there serious problems with it?
  • Who will have to work with the code? If it will never be touched again it probably isn't overly important. If you're the only one who will have to work with it you might be comfortable with the less optimal solution for now. If others will have to work with your code then you probably want to put your best effort into the best/clearest design you are able to implement.

Do you refactor while coding, or do you refactor after everything's done?

A bit of both if needed, although refactoring while coding can normally be kept to a minimum -- almost entirely eliminated once you're more experienced -- by designing properly in the first place.



Do the best you can, but expect to make mistakes as you learn and grow as a programmer. It won't always be practical to fix all your mistakes if you want to continue to progress, but as long as you recognise and learn from them that's fine -- save perfection for when you're writing important code.


...and just to re-enforce what others have said, Code Complete is well worth the money once you've saved up.

#7 mrbastard   Members   -  Reputation: 1573

Like
2Likes
Like

Posted 23 September 2012 - 03:39 AM

Refactoring and feature additions should be in separate commits. This allows the definition of refactoring as a "behaviour preserving transformation" to be useful in a practical way beyond the immediate point of use - it's helpful information to have while regressing to find the source of a bug, for instance. If the refactoring is mixed with other changes it becomes much less useful.

Ideally, I'd like refactoring tools in IDEs to work with version control to check in and revert as I refactor/undo - and potentially even branch when I start refactoring then merge when I'm done and the tests pass.


#8 Wyrframe   Members   -  Reputation: 730

Like
0Likes
Like

Posted 23 September 2012 - 12:18 PM

When not working to a defined interface or protocol, I'll code a bit, get a good result, then analyze and (usually) re-write what I've written in an effort to make it easier to expand or to maintain, usually by identifying the generalizations that will make it flow better. Just as often, once I have something working, I'll then design a cleaner architecture that produces the same work, but with less spaghetti-coding. This holds true whether I'm working on terrain generators, machine-code assemblers, or data processing.

I mostly work in Java these days, so Eclipse's refactoring tools are often leveraged to re-organize my namespace, especially moving inner classes out into their own files with just two clicks. Moving classes from one namespace to another with all references kept intact is always nice.

When I do have to arrive at a specific interface, though, which is about half the time at work, I naturally have to work the same way we arrived at that interface spec in the first place; start at the goal, and problem-solve my way to the implementation that achieves it. This is generally actually faster than the other way, but because I won't always have progressively implemented versions along the way to the final product, it usually feels slower.

(( This email has been quad-ROT13 encrypted. Reading it violates the DMCA. ))
(( 我说很少的汉语,还我的语法平庸, but at least I'm UNICODE-compliant. ))


#9 GeneralQuery   Crossbones+   -  Reputation: 1263

Like
0Likes
Like

Posted 23 September 2012 - 12:38 PM

I think that it's about striking the balance between being pragmatic enough to get things done to meet the deadlines and being disciplined enough to not sack clarity and good coding practices in favour of "I'll refactor this later" (which, of course, rarely happens when one has external forces dictating how much time one has to get things done).

I'm a researcher myself so whilst I do work to external deadlines they are no of the frequency of, say, a professional programmer. The shelf life of my code (almost exclusively prototype applications) is very short so it's all to easy to write disposable "fire and forget" code as one is lulled into the false sense of security that such code is "one use only" and not worth exercising some discipline over. This lax attitude had cost me unnecessary (and precious) time on more than one occasion when an important deadline gets dumped on me at short notice.

#10 Postie   Members   -  Reputation: 867

Like
0Likes
Like

Posted 23 September 2012 - 07:35 PM

I've learnt through bitter experience that you should always start from a working, committed code base before attempting refactoring. As to the question of when to do refactoring... whenever it feels right. Seriously. If the codebase is all messed up and its eating away at you, spend some time cleaning it up. If its "ok", but not as elegant as it could be, but you're ok with that, then ignore it and work on other features.

Sometimes refactoring adds nothing to the codebase other than piece of mind. Other times it spawns useful ideas you might not have had otherwise.
Currently working on an open world survival RPG - For info check out my Development blog: ByteWrangler

#11 doeme   Members   -  Reputation: 685

Like
0Likes
Like

Posted 24 September 2012 - 03:03 AM

I usually start out with a pretty clean design which gets messy as its accumulating new features, which I refactor out whenever it feels to cumbersome or inflexible to use. In this sense I'm refactoring while writing, but not while actually implementing a feature. Often I also try to refactor before implementing a feature as this might save me work later on. I also get more joy from working in a clean environment and I love the moment when I realize that I designed/refactored something in such a way that the addition of new functionality doesn't require a lot of work at all.

I found "Refactoring: Improving the Design of Exisiting Code" By Martin Fowler et. al. a good book about how and when to refactor. It not just covers some technical aspects but also a lot about increasing productivity and code-stability from refactoring.

#12 Olof Hedman   Crossbones+   -  Reputation: 2665

Like
1Likes
Like

Posted 24 September 2012 - 04:29 AM

I have found that the "quick and dirty way" is an illusion, and isn't really quick at all, it just means you put off work until later, and produce less useful code with more bugs that haunt you later.
Sure, for some prototyping it can be motivated, but it should be cleaned up before commit to the trunk.
For longer prototyping, a branch might be motivated.

That doesn't have to mean you have to do a _refactor_ every time, if your design is sensible to begin with, it shouldn't be very hard to add functionality in a graceful manner, no matter what this functionality might be.

Though, of course your design is never perfect, and sometimes needs a slight refactor.
As others have pointed out, these should be done on a stable code base, so you can verify it works as it should both before and after.

Edited by Olof Hedman, 24 September 2012 - 04:30 AM.


#13 L. Spiro   Crossbones+   -  Reputation: 12338

Like
0Likes
Like

Posted 24 September 2012 - 05:22 AM

My first question is, do you guys often do the quick and dirty thing, and then go back to fix it later; or do you get a hold of yourself and make sure you get the job done well, first and foremost?

Do it right the first time. If you can’t figure out exactly how it should be done, don’t do it. Keep planning. Writing algorithms you are not sure how to implement is the best way to create bugs.

Do you refactor while coding, or do you refactor after everything's done?

The only reason to ever refactor is if you simply made a mistake (but you had put enough thought into it that you believed you were doing it correctly originally), or you gained experience and realized a new way to organize code and have the time to do so.
So the general answer is that I refactor on my own projects as soon as I realize a need for it, and in professional settings I refactor based on the weighted sums of the need for refactoring vs. how much time is available for it.
In no cases is refactoring done after everything else is done. Not only do most projects have no end (for example, will there ever be a day when there is not a new feature I could add to my game engine?), but those projects that do have an end…end. They get shipped and you move on. You never think, “I could put this amazing app on the App Store right now! But naw I better spend another week just moving code around, even though the resulting product will be the same.” It doesn’t happen.


When it comes to my own projects, however, I allow myself one exception specifically to accommodate a personality “flaw” of mine.
Sometimes I am in the mood to do nothing but simple and mundane tasks, and if there aren’t any I simply won’t code anything. I will watch a cartoon or something and wast time.
But if there are some to do, I will start doing them, and once I get started I get in the mood to do more and more, and end up adding or at least starting new features.

When I get excited about the end result, sometimes I intentionally copy-paste code instead of moving it into a function (for example) specifically to give me a mundane task that will ultimately end up making me more productive.

Obviously, if you are a normal human being this will not apply to you, and I recommend being strict on the structure of your code at all times.


L. Spiro

Edited by L. Spiro, 24 September 2012 - 05:23 AM.

It is amazing how often people try to be unique, and yet they are always trying to make others be like them. - L. Spiro 2011
I spent most of my life learning the courage it takes to go out and get what I want. Now that I have it, I am not sure exactly what it is that I want. - L. Spiro 2013
I went to my local Subway once to find some guy yelling at the staff. When someone finally came to take my order and asked, “May I help you?”, I replied, “Yeah, I’ll have one asshole to go.”
L. Spiro Engine: http://lspiroengine.com
L. Spiro Engine Forums: http://lspiroengine.com/forums

#14 larspensjo   Members   -  Reputation: 1526

Like
0Likes
Like

Posted 24 September 2012 - 12:27 PM

There are two typical scenarios I find myself in frequently. The first is when I find I do something again I already did elsewhere. Maybe not exactly the same, but with a commonality that depends on each other. Then I usually refactor the design into using common code. The simplest example is using a constant, which is so simple to fix that I make an alias (#define/enum/const) even if it is only used once (avoiding naked constants). When a few lines of algorithm is "copied" first time, it is a sign to make a common subroutine. Etc, up to class inheritance.

The second scenario I frequently find myself in, is when a class gets too big (with a fat interface), or a subroutine gets too big. That is usually a sign that some refactoring is needed. This case can be harder, however.

Doing a refactoring mostly leaves me with a very pleasant feeling. I can stare at the source code and feel pride. If I show it to my friends, they say "of course, how else could it be done?". Lots of effort has been used to find the obvious solution. But I know it is far from easy to find the obvious solution the first time you try. A good refactoring opens up new possibilities and opportunities that were not foreseen.

I like the advice above from mrbastard, to separate the commits from refactoring from commits that add functionality. The change should have no effects on validation. That way, when you find something is broken, it is easy to go back afterwards and test the refactoring to see if it was the root cause.

Do you refactor while coding, or do you refactor after everything's done?


That never happens. Unless someone pays your explicitly for it. The curse of having a limited budget or deadline is the usual thing, unfortunately. I think it is common that the "next project/budget" will have to take the consequences of imperfect design. And as this is a limited budget also, it is not unusual to end up in a patch work. If this goes too far, the solution will eventually to start from scratch. Kind of an ultimate refactoring.
Current project: Ephenation.
Sharing OpenGL experiences: http://ephenationopengl.blogspot.com/

#15 frob   Moderators   -  Reputation: 19023

Like
3Likes
Like

Posted 24 September 2012 - 02:56 PM

For me it is just a part of development, not a separate step. After all the years of "red-green-refactor-submit", it has become completely automatic.

You write code. You consolidate, clarify, and clean up. Then you submit.

It should be included as a part of the estimates, and in practice is just a very small amount of time. When you see something that needs to be cleaned up, you simply do it. You also tidy up after yourself as you make changes and before you submit.

Much like a woodworker must clean up scraps as part of the task, so do programmers also need to clean up as they go along. They don't need to allocate extra time "sweep up the scraps and sawdust", it is just a known automatic task that must get done both during development.

If the wood shop doesn't get swept frequently it becomes dangerous for both injury to the workers and also for disasters like fires. Similarly if code is not regularly cleaned up during development it becomes more difficult to maintain and at risk for disastrous problems.

Edited by frob, 24 September 2012 - 03:02 PM.

Check out my personal indie blog at bryanwagstaff.com.

#16 ATC   Members   -  Reputation: 551

Like
0Likes
Like

Posted 24 September 2012 - 07:20 PM

As I'm a major perfectionist in programming (though oddly not always in other things) I always try to make everything "perfect" from jump-street. My brain simply will not even let me write code if I dont have a nicely formatted file with code separation blocks (made of comment lines) to separate constructors, fields/properties, methods, event system, etc. I've turned this into a Visual Studio template so every new class file I create in C#, C or C++ is properly formatted for work. Here's my format for C# class files:

[source lang="csharp"]#region Description/* * * * * * */#endregion#region Using Statements/* System References :: */using System;/* Internal References :: */#endregionnamespace MyNamespace{ public class AClass1 { /*----------------------------------------------------------------------------- * CONSTRUCTORS & INITIALIZATION :: *-----------------------------------------------------------------------------*/ public AClass1() { } /*----------------------------------------------------------------------------- * FIELDS & PROPERTIES :: *-----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------- * METHODS & IMPLEMENTATIONS :: *-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------* ******************************************************************************* *-----------------------------------------------------------------------------*/ } // <-- End of class...} // <------ End of namespace...[/source]

You probably either love it or hate it... For some reason I've never liked the convention of putting fields/properties first in a class, followed by constructors followed by methods. Since constructors are the first part of a class to run it only seems logical that they should appear first in the file (to me at least). That's why I do it this way. Every single file in my engine's code base follows this formatting conventions. The only exception is really small types (small classes and structures, enums and "helper" types/files). For me, this just makes things very, very organized and highly readable. I also typically refuse to save and close a file with properly documenting everything of any importance (every publicly exposed member) with XML documentation.

As for the actual code I try to do things right from the beginning. I try to avoid any sloppy/ugly code. In my opinion, poorly written and sloppy code is not a timer saver...it's a time-waster. Something major is going to break and you're going to have hell sorting it out. If your sloppiness gets too out of control you might end up with a situation where you're better off starting an entirely new solutions and copying over only the good bits of working code and rewriting everything else. And I HATE doing that because it takes forever on a project as large as my engine.
_______________________________________________________________________________
CEO & Lead Developer at ATCWARE™
"Project X-1"; a 100% managed, platform-agnostic game & simulation engine


Please visit our new forums and help us test them and break the ice!
___________________________________________________________________________________

#17 mrbastard   Members   -  Reputation: 1573

Like
0Likes
Like

Posted 25 September 2012 - 05:35 AM

There's a popular misconception being perpetuated in this thread - that refactoring is 'tidying up code'. It's not. It's a specific term, related to the term 'factor' from mathematics.

Most of the above advice is arguably correct when talking about 'tidying up code' but very little of it is about refactoring.

I like the advice above from mrbastard, to separate the commits from refactoring from commits that add functionality. The change should have no effects on validation. That way, when you find something is broken, it is easy to go back afterwards and test the refactoring to see if it was the root cause.

Actually, I meant that if your refactoring is behaviour-preserving, you can discount it during regression. If the behaviour really didn't change, the bug didn't originate here. Of course, for that to be the case you have to have automated refactoring tools (to ensure the change is a reversible transformation, not just moving code around) and enough test coverage to detect behavioural changes that sneak in through leaky abstractions or under-specified invariants.

Seriously, look into refactoring as a rigorous systematic process. It's worth it.


#18 frob   Moderators   -  Reputation: 19023

Like
2Likes
Like

Posted 25 September 2012 - 11:21 AM

There's a popular misconception being perpetuated in this thread - that refactoring is 'tidying up code'. It's not. It's a specific term, related to the term 'factor' from mathematics.

Most of the above advice is arguably correct when talking about 'tidying up code' but very little of it is about refactoring.

Depends on your definition of "tidying up".

For me that includes all the major steps; removing duplicate code to functions, pushing up to base classes, generalizing code, extracting classes and methods for clarity, etc. To me, that is simply tidying up. All of these are refactorings that don't modify the behavior, but that dramatically clean up the code for future use.
Check out my personal indie blog at bryanwagstaff.com.

#19 Telastyn   Crossbones+   -  Reputation: 3724

Like
2Likes
Like

Posted 25 September 2012 - 03:01 PM

My first question is, do you guys often do the quick and dirty thing, and then go back to fix it later; or do you get a hold of yourself and make sure you get the job done well, first and foremost?


I often do the thing right the first time. Or essentially right. Sometimes doing all the nitty gritty details is counter-productive because of unknowns, risk of change, etc.

My second question is, what is your attitude about refactoring?


It is an essential practice to limit code rot.

Do you refactor while coding, or do you refactor after everything's done?

  • If I'm coding and encounter something that sucks, I'll occasionally take a tangent to refactor it.
  • If I'm coding and encounter something I want to re-use, but it's not quite abstract enough, I'll usually refactor it to handle the new case as well.
  • If I'm fixing a bug, and encounter some root cause that would cause a similar bug to be caused in the future, I'll refactor to fix the root cause rather than just the line that caused the bug.
  • Rarely, I'll go back and clean up something I wrote that isn't related to new development or bugfixing. If it works, leave it be.
  • I will frequently go through and refactor something other people wrote that will assuredly cause bugs in the future, is untestable, or otherwise needs it.


#20 mrbastard   Members   -  Reputation: 1573

Like
1Likes
Like

Posted 26 September 2012 - 10:31 AM

removing duplicate code to functions, pushing up to base classes, generalizing code, extracting classes and methods for clarity, etc. To me, that is simply tidying up.


You can use refactorings to tidy up, sure. But you can also tidy up in ways that are not refactorings, and do refactorings that are nothing to do with tidying up. So I think having a separate specific term is quite useful :)

For example: requirements change and you decide to parameterise a function or class further - that's not tidying up, it's preparing the ground for a new feature without changing external behaviour.

I was prompted to respond to L Spiro's comment that "The only reason to ever refactor is if you simply made a mistake". That's absolutely not true - requirements change. Of course it is perfectly reasonably to argue that the only reason to need to tidy up is if you made a mess. But not all refactoring is tidying up!

Not just being pedantic, I hope!





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS