Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Ask HN: How obsessive are you with your code?
37 points by mishmash on July 3, 2010 | hide | past | favorite | 36 comments
So.. realized today that I probably spend an hour a day refactoring code. It's usually towards the end of the day, and includes items such as renaming variables, creating/moving classes, enforcing stricter patterns, writing in-depth comments, checking and removing dead code, and other general upkeep issues.

My question: is this too much? too little? How much time do you spend on these activities? Should I spend more time upfront thinking before coding (gasp!)?



I've been called a perfectionist because of my coding maintenance. Dozens of my commits are "Source code formatting", where I try to make the code closer to PEP8 (Python).

But I don't go actively looking for things to "fix". While reading code, if only one line is separating functions, I add another. I add \ to line ends trying to limit width to 80 chars.

Lately my mantra has been "Shipping is a feature". Code working is my number one priority. But like most of the people, I like to think I'm above average, so I don't believe I write _bad_ code at the first time. I know it's not perfect. Just by saying this, I remember of things I know I should change to make the code better, but why bother?

What you must always pay attention is the balance between creating value for your customer, and for you as a professional. And even when you do things for yourself, always remember your main objective is to make things easier in the future to create value for your customers.

Caveats apply, of course. A refactoring to allow more modularity or whatever in the future might be good to do now, but honestly usually there are more pressing matters (unless the current pressure is to add some module functionality).

It's hard to give any straight answer. There are no hard rules, like "you should only refactor during one hour per-day". Maybe you're doing something where a big-design-upfront is not possible. Maybe not.

These things come with experience, tough. And where you want to keep your focus. If I was working on a 10 year code base where the original programmer has left the company, and didn't document anything, then I guess I would spend more time nurturing the code. But my job today is too fast paced, and "when it will be ready" is my customers/stakeholders number one priority. I negotiated and told them quality would suffer, and they are aware, but don't care much.


I stay happy as long as my black box continues to function as advertised. That keeps me from obsessing over internal details. Ugly code can stay ugly and I sleep fine at night.

But whenever I wade into the code for good reason, I reward myself by refactoring whatever areas I happen to touch. It's like throwing a fish to a seal. That way I always get a chance to do fun things like unifying similar code or making code more data-driven.

I'm still a perfectionist, but I'm also a strategic procrastinator. So while I'm working on code, whenever I think of anything, however small, that might improve it, I'll throw in a comment such as "TODO 0703 might want to tighten this up" or "TODO 0703 you need to test this case before releasing". I am so relentless and unforgiving that sometimes the TODOs multiply like rabbits.

Before I release anything, I grep on "TODO". As long as any TODOs show up, I can't release. If I need to put off something until later, I'll change that "TODO" to "LATER". Occasionally I'll make a point of revisiting my LATER entries, converting some of them back to TODO. That way perfection is an ongoing process, not an attained state.


We actually did this on one of our releases. There was a task to scan the entire code base and either fix all TODOs or write a justification for why it could safely be ignored.

Amazing what you can find when that happens :-)


The problem I have with refactoring todos is that after a time it's no longer clear to me why the refactoring was needed (unless it's obvious, but in that case I probably already did it).


To be clear, I usually add TODOs only for observable features and enhancements, rarely for internal issues like refactoring. My point is that I usually refactor only when I'm already in the code for other reasons, as a reward for doing the immediate observable changes. This helps focus my refactoring efforts only on code that is already changing for the customer's benefit.


Do you really find python easier to read when lines are broken with a slash at 80 chars. I don't bother until twice that.


I'm not so sure about 160 chars, but I do agree that 80 chars is a little ridiculous these days. I have not yet one good argument for 80 chars.

Most terminals and monitors today will easily go to 100 chars, which is typically where I prefer to break lines. This gives room for 3-4 levels of nesting (using 4 char tabs), which is about the max depth you'd want to nest. There are exceptions of course but for the most part any more than 3-4 levels deep and you should be looking at refactoring.


Not really. I was doing "whatever fits on my 22 widescreen monitor", but a teammate asked me to keep on 80, and I started to change my style to make him happy.

Then a new member came to the team, and his coding style was not very good. I told him to read and follow PEP8, he downloaded some script which checks source for PEP8 compliance, and he really made the effort to format his code.

So, it's not something that I would personally go insane trying to keep width to 80, but when two things happened: I was already doing most of the PEP and my teammate wanted me to keep 80 chars, and I had to eat my own dogfood :) when the new person came on board.

In the end, it's something easy to do, and keep my colleagues happy.


> What you must always pay attention is the balance between creating value for your customer, and for you as a professional.

Great point. By not having customers right now, I've likely started to overvalue my own development/investment.


There's a good balance of writing it right the first time, and spending too much time with the details and not the actual feature you're implementing.

With enough experience, you'll know how to start writing something such that it won't require extensive refactoring. Make sure it's good enough that if you don't have enough time, it's still good in these two major ways: as fast as possible with no redundancy, maintainable by someone else.


Should I spend more time upfront thinking before coding (gasp!)?

Probably. But anyone who reads my blog could have guessed that I would say that.

I tend to spend a long time writing code and then never look at it again. I even forget the implementation details. It makes my life much easier -- if I had to keep thinking about how btree_node.c calls proto_lbs_client.c which calls wire_requestqueue.c which calls wire_writequeue.c which calls network_buf.c which calls events_network.c I'd never get anything done. And if I can remember all that, I'm going to think about it whether I like it or not.

Just get the code right the first time. Then you can use it as a building block without needing to worry about implementation.


I often use code as a tool to think about code.

So my time spent upfront may actually look like coding. Depending on the problem I may use strange domain specific languages like scribbling equations on dead trees.

The artefacts of this upfront thinking may get re-used in implementing the solution. Than it can look like refactoring.


In answer to the headline, not very! I prefer to get something working, then I'll refactor, reformat and rewrite until reliability, readability and performance meet my needs. This process can take months, depending on the required balance between adding new features or improving existing ones.

This approach works quite well for me, since I generally plan code in my head before a coding / transcribing session.

An hour a day sounds high, but understandable if you are working on a scrappy code-base. It sounds like you are doing a good job, especially since you will be eliminating 'code-smells', fixing warnings etc.

I always like to plug it, but Code Complete was the book that transformed my attitude towards 'my craft'. Great book, should be mandatory reading.


Too much, probably. For me, its not usually not related to reorganizing my code around. But, I'll nitpick over whitespace or brackets. I won't fix formatting up if I'm in the middle of working on something, but I'll make a mental note to come back to it.

My justification (to myself, at least) is that when I encounter code thats badly formatted, I find that the flow doesn't tend to make much sense (either to read, or as its actually executed) and it needs refactoring anyway. So, I'll fix the formatting up and read the code to see what it does. And then refactor parts, if necessary.


I do almost the exact opposite: I see that fixing minor flaws in the whole code base is a temptation, but I do not have enough time to do it. So I just polish everything that my edits touch (i.e. every function that is affected).


...but I do not have enough time to do it.

Neither do I, really. I don't go back to change something around unless I do have time.


When I was employed as a developer, I was quite obsessive about refactoring my code to the point where I considered it elegant.

Now I run my own company and am the sole developer. So these days I tend to think if my code is well factored, I'm doing it wrong.

It's not quite that simple of course. The lower down the stack a chunk of code lies - the more things that depend it - the more I want it well factored and well tested. But I'm quite comfortable with code high up the stack being scrappy, hacky and untested.


I try to follow a simple rule.. Leave the code in a better state than I found it.

Every time I submit a revision I try to include a change which improves an area of the code outside of my main focus.

By doing this I am constantly improving and re-learning parts of the codebase that otherwise become moldy.

So, A typical checking might be something like...

Add ability for animation tracks to play in reverse. Add missing null reference check to CalculateWorldTransform Improve per of serializer by 10% (avoid string parse for main line case) BUGFIX #1087: Keyboard input delayed by one frame

Basically, I try to make refactoring/improvements an ongoing part of development rather than a chore.


For the last few months, I've been trying to enforce a discipline of Design, Code, Inspect Code for errors, Unit Test, repeat. I try to do this over relatively small increments like 1-2 functions at a time, maximum. The change from what I did previously is that before I didn't do much detailed design -- that happened as I was coding. And reading code for errors was only done if a test failed.

It gets tedious very quickly but at the same time the number of errors that persist to Unit Test has dropped considerably.

After spending a lot of time thinking about Software Process, I've concluded that the biggest gains come from engineering discipline, not heavier process, so yeah, I don't think you're doing too much. Although I wouldn't force code/design into patterns.

A lot of the code I'm modifying these days is legacy stuff with 300+ line methods!!! Although it was written by a pretty smart guy, I really wish he had heard of refactoring and removing dead code: I have a burning hatred of commented out code and code that never gets executed.


This really starts to matter when you're working with other programmers. There's always a fine line between too much refactoring and micromanaging, so I basically try to keep things to a level where I can quickly understand what's going on with one read-through. If I can't, there's a problem, and it's time to start cleaning things up.


> This really starts to matter when you're working with other programmers.

And see I've been solo for about two years which means I haven't had to manage any of those external expectations that you get from being on a team.


I ask myself two things: Will I remember this later? Will other developers be able to read or understand this?

Some code is obvious, no comments or naming is needed. Otherwise, be obvious or leave enough comments to make life easy for your team, or “future you.”


First make it work,

Then see if anyone uses it,

Then make it good.

The time to refractor is when you see a real time savings from doing so, not a hypothetical one. It works for me at least.


I refactor at one of two times. Its either after I get my unit test working or its a change to the structure of some code so I can add a feature. So its an activity I am constantly doing throughout the day to make sure the new functionality is put in relatively well.

In the same way I can't count how long writing tests takes I can't count how long refactoring takes as its simply part of the normal development process. I only ever account for work that includes these activities because after doing it for so many years I realise you can't split them without doing a hack job.


Are you perhaps doing that because at the end of the day, you are too tired to get real work done? Might be better to take a break...


This actually probably has something to do with it. I've been working on a new project lately and have been pretty jazzed up about it during day.


    -Wall -Werror -Wextra -pedantic
that's all you need


I guess you also need a way to suppress spurious warnings. And C compilers normally don't warn you about follies, like using global mutable state. Or using C where it's inappropriate (or not using C where it's appropriate).

Though I do agree that ridding your code of compiler warnings is a good idea in general. Because when a warning comes up afterwards, it will actually have some signalling value, instead of being ignored in a sea of similar warnings.


> I guess you also need a way to suppress spurious warnings.

    man gcc
    ...
    You can request many specific warnings with options beginning -W, for
    example -Wimplicit to request warnings on implicit declarations.  Each
    of these specific warning options also has a negative form beginning
    -Wno- to turn off warnings; for example, -Wno-implicit.  This manual
    lists only one of the two forms, whichever is not the default.  For
    further, language-specific options also refer to C++ Dialect Options
    and Objective-C and Objective-C++ Dialect Options.
> And C compilers normally don't warn you about follies, like using global mutable state.

I mean no great disrespect, but if you need a machine to remind you not to use global mutable state, get back in the oven, you're still a bit gooey on the inside.


I was just arguing against

  -Wall -Werror -Wextra -pedantic
being __all__ you need. I don't doubt that those options are certainly part of a healthy breakfast.


Thank you. I can't stand it when I build someone's C code and am greeted with page after page of compiler warnings. It gives me a sinking feeling.


Codecraft is important to me. I am obsessed with whitespace and consistent names. Imagine my delight when I found a gedit plugin called Elastic Tabstops!

http://nickgravgaard.com/elastictabstops/


Before I commit any code, I spend a surprisingly long time making sure the diff looks neat and it does things the right way.

I wouldn't revisit old code until I needed to change it for another reason, since all changes should be thought out properly.


refactoring is a natural part of coding process. in an ideal world, it only has to happen only when you need a particular chunk of code in more than two places. otherwise, time spent without adding value is just wasted.

but this is not an ideal world and from a recent thread about a similar subject, i got the impression that most of us don't like the code we wrote the second time we look at it.

i guess it's okay to spend time on code that's already perfectly working as long as you don't miss your deadlines (or arrive late to a date, or something).


Experience is nothing but trial and error. Once you've been programming for a while, you'll get much better intuition about what works and what doesn't.


If that hour a day pays you back in lower maintenance costs, then it's worth it. An ounce of prevention is worth a pound of cure.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: