57

Possible Duplicates:
Frankly, do you prefer Cowboy coding?
Prototyping vs. Clean Code at the early stages
Good design: How much hackyness is acceptable?
Does craftsmanship pay off?

Which is better:

  1. Coding fast, not caring about possible errors and limits, maybe forgetting to check the input, NULL returns etc, just to complete the task or to get to the milestone, and then correct all possible errors.
  2. Coding slow, checking every line you write many times, writing tests, and checking every possible input to make a code as bug free as you can but taking weeks to write a working program.

Actually I'm using the 2nd way but it's frustrating to work, work, work and see only small improvements every day...

1

12 Answers 12

66

This depends ENTIRELY on the type of work that you're doing. For a lot of situations Test-Driven-Development, like you're currently doing, is definitely the way to go. Overall you'll spend less time on the project since you're not having to constantly go back and fix bugs and edge cases that you didn't account for the first time around. With the first option, yes, you'll finish in record time but then you'll spend a good chunk of time going back and fixing all the mistakes.

That being said, if you're in a situation where you need to get a product out the door as fast as possible (maybe you're trying to beat the competition for "first to market" advantage), toss TDD out the window and get something working and out there. A lot of great products have happened this way. Your product won't get you anywhere if you're endlessly polishing and fixing bugs if a competitor with a "good enough" product is eating your lunch.

Consider Facebook. Mark Zuckerberg created Facebook in his dorm room with PHP and MySQL, at a time when probably twenty other people or organizations were planning or already releasing social networking sites. Part of the reason for Facebook's success was that he got out the door in a hurry and beat a good part of the competition solely because he was first to the college market.

If you have time: unit test.

If you are in a race: code, and get it working - worry about the mistakes later.

EDIT: Obviously, you can't release a product that is so buggy its unusable. When using the "out the door" method, you need to realize when hunting and fixing additional bugs will only add marginal value to your product when compared with releasing now.

4
  • 22
    A good point but you have to be careful - being the first to market but with a buggy and unstable product could completely kill your venture if it's bad enough that people decide to hold out for something better. "Good enough" is a fine line to tread... Aug 10, 2011 at 15:07
  • 6
    Absolutely. Its a delicate balance, to be sure, no matter what the situation. Aug 10, 2011 at 15:19
  • 2
    It does not sound like he is doing TDD As he is writing the tests after the code. TDD allows for fast coding, it just puts some of the work of the debug process up front. Aug 10, 2011 at 18:04
  • This reminds me of number 5 of The Joel Test. (Though, I realize it's not entirely applicable here, it still reminded me of it.)
    – Reid
    Aug 10, 2011 at 21:30
34

The second way is better, in my opinion. It feels slower but the amount of re-work and fixing and retesting will be a lot less and will ultimately lead to a better product. You say it takes "weeks" to write a program - but you already know that if you go with the first method, you can write the program in "days" and then spend "weeks" in the "correct all possible errors" stage.

The only time when I'd advocate method #1 is when it's throw-away proof-of-concept code that is used to demonstrate a single window or a function that will operate in very narrow paramters.

2
  • 3
    +1 for highlight the only (IMO) valid usage for #1. Aug 10, 2011 at 14:59
  • 10
    When working with someone who does it the first way, you'll often have to go back and redo their code the second way in my experience.
    – Doug T.
    Aug 10, 2011 at 15:36
25

The only way to go fast is to go well.

I saw "Uncle" Bob Martin speak on this at a conference once. Luckily, a quote of it is on line.

There's no such thing as quick and dirty in software. Dirty means slow. Dirty means death.

Bad code slows everyone down. You've felt it. I've felt it. We've all been slowed down by bad code. We've all been slowed down by the bad code we wrote a month ago, two weeks ago, even yesterday. There is one sure thing in software. If you write bad code, you are going to go slow. If the code is bad enough, you may just grind to a halt.

The only way to go fast is to go well.

1
  • This is known as code debt. You can take a loan if you want to race to completion, but you're going to pay it with interest (unless you abandon the project).
    – RaidenF
    Apr 12, 2016 at 8:51
12

I do test driven development, where I define all my cases before hand. This allows me to code fast and loose, and then see what I missed. I then go back and re-factor what I messed up. My opinion has always been, figure out what it is supposed to do, "sketch" it down on paper, and figure out where my assumptions are wrong. There have been too many times I have tried to make something perfect the first time through, only to realize that I have to go back and redo it because of a incorrect assumption on my part.

9

I think your question creates something of a false dichotomy. In reality, the decision is not binary ("do I code slowly and carefully, or quickly and recklessly?"), but is rather on a spectrum. The two options you presented are at either extreme.

Exactly where on the spectrum you want to be depends a lot on the particular product you're working on and what your customers expect from you. You need to examine the constraints you're working with and then make an intelligent decision about what kind of process you want to use.

For instance, if you're in a position where it's very expensive to correct mistakes, or where failures are potentially catastrophic, you want to be closer to option #2. Embedded software, missile guidance code and medical tools are good examples. When fixing a bug would mean recalling millions of dollars worth of hardware, or when your mistake might result in people dying, you need to make sure that you get it right the first time.

The other end of the spectrum is when the business environment demands rapid code changes, but it's easy to fix mistakes and the penalties for failure are low. Web applications often fit this description. Your users are clamoring for new features and business logic changes, and they want them implemented yesterday. If a small mistake in the code is made, it takes fifteen minutes to edit the offending script, get the change code reviewed, and hotfix it. In this case, as long as you manage user expectations properly, they'll learn to ignore the occasional bug as long as you're responsive to their needs and maintain a quick turnaround time. Of course, even when taking this approach, you should still have safeguards in place to prevent against catastrophic failures: keep backups, do code reviews, and make sure you've got a good hotfix/revert process.

I think the reality of software development is that most projects lie somewhere between these two extremes. You usually want to be diligent about preventing bugs, but you may not want a year-long release cycle due to a burdensome QA process.

Aside from the environmental factors I mentioned earlier, I think the best way to figure out exactly where you should be is to evaluate feedback from users. If they're frustrated by long wait times for new features, you may want to trim the QA process a bit in order to be more responsive. Just make sure that you're extra quick about fixing any bugs you may introduce. On the other hand, if they're demanding absolute reliability, then make sure you've got enough safeguards in place to meet that demand as best you can.

5

Go for 2.

Think -> think further -> do a peer discussion, for complex devs -> code -> test -> eventual fix.

Far better than

Code -> code more -> realize it won't work -> fix -> discover a new bug the first code raised -> go back to scratch

2
  • 1
    That is why people create throw-away prototypes - to quickly test an important idea. So, I disagree with your answer May 23, 2014 at 7:38
  • 1
    @BЈовић, I think the problem comes when you're going fast and not doing it with an exploratory/prototyping mindset (prototyping is of course important). Rather just trying to get something production ready as fast as possible, without much thought.
    – ideasman42
    Sep 19, 2015 at 12:06
5

Are you following a Test Driven Development (TDD) approach? You'll find after 1-2 months of developing with this approach that you're just as fast as if you were following 1. and that you maintain the higher quality bar of 2. You'll also be able to make changes (re-factor) without fear, think of it as saving yourself time in the future!

I'll also add that you can go for option 1. if you are in a real rush to get sometrhing to market, or if you are prototyping. Just remember that the final deliverable of that piece of work should be ideally rm -rf *

1
  • 1
    +1: It's better than "just as fast": it's faster, and velocity increases over time due to improved quality from continuous refactoring. Aug 10, 2011 at 16:34
4

Depends. On a lot of things, but one thing that others have missed is that it depends on the size of the project. For large complex projects, debugging can be monstrous and have deep ramifications. Proper planning and structure can save a significant amount of time. Small simple projects, on the other hand, are easier to debug. There's only so many moving parts.

The bigger the project, the more careful you have to be not to set yourself up for a major headache.

3

Personally, I do #2. I don't say something is done unless I know it will pass testing. Yes, the causes me to take longer and I often go over on my allotted times on tickets.

When I close a ticket, it is very rare for QA to send it back to me. So it doesn't only save my time, but it saves the QA teams time as they don't have to retest if there are bugs.

My manager has accepted that for every hour I go over now, that is 2 or more hours we don't waste in testing.

Is it slow? Ya, sometimes. But, I find that it's faster in the long run. Putting in the extra effort now might save me from working a weekend or two before the end of the project fixing all the defects. That to me is worth it. :)

3

If I have to choose between only those 2 then definitely number 1. But I don't choose between the 2. From your description, it sounds like most of the work you do is conceptual, thinking about the code and how it should work. For me, an important part of the development process is seeing what the code actually does when compiled. Of course, I can work it out in my head, but that doesn't always mean that the compiler will do it the way I think it will. What I do is, basically, a code, compile, and test loop in which I catch errors early without having to spend an hour looking at one line of code. This way you can produce results much faster and still maintain high quality. I am not in a TDD environment right now, but I am working on implementing one.

0
3

Jarrod answered this along the dimension of the business situation.

Although that's valid, I also think the answer varies based on the type of program -- or even for different parts or "levels" of the same large program.

Deep in an "engine" used broadly by the program, it will pay off to go slow, steady, careful. Make use of tests. Do yourself a favor and define the interfaces narrowly enough that you don't need a bazillion tests to cover an excess of permutations.

But closer to the "edges" of the program, such as the UI or interfaces to evolving, external APIs, it is probably wiser to go faster. After all, the requirements are more likely to change. Plus you are more likely to find problems via direct observation by you and beta testers, than you are by wanking off writing elaborate test suites that have less hope of getting you full coverage.

Basically this is common sense, keyed off of your assessment of how stable or well-defined a given part of the program is likely to be.

2

Do it quick and dirty first to prove your concept. Make sure you've actually proven the concept you are trying to prove, then throw it away (I mean it, delete it).

Now do it again, but this time following the correct process and defensive programming. It will take a lot less long than you think, because you already know what you are doing, and your code will be a lot better than anything you could have come up with doing only quick-and-dirty.

Not the answer you're looking for? Browse other questions tagged or ask your own question.