Good people doing the right things
4 points by gfodor 2 hours ago | link
All of these types of arguments are at the wrong level of abstraction.
I've found that what makes the best programmer is not if they are a "duct tape" programmer or a "architecture astronaut" or whatever, but self awareness. They can call a hack a hack, and understand it's impact. They know when and how architecture can be improved, and when it should be improved. They can take criticism of their work because odds are, the criticism is something they already had an understanding of and can justify, or if not, they are willing to see where there was a gap in their thinking. They have a plan, and can forge a system ahead in a general direction of progress without getting bogged down in the details or taking one step forward and two steps back. You get the idea.
Nobody is talking about this, arguments generally deteriorate where someone sets up a false dichotomy and then the internet collectively rips them apart. But they get ripped apart because of the falseness of the dichotomy, not because of the fact that they are looking at the wrong things altogether.
-------------- 1 point by j_baker 6 hours ago | link
Unit tests are indeed productivity tools. You'd be surprised at how many stupid little errors you can catch by running tests. In fact, I would argue that unit tests improve code quality more because they give you more time to focus on the big picture without having to worry about stupid things breaking all the time.
7 points by evgen 6 hours ago | link
Alternative, you could just practice not breaking shit.
Two erroneous assumptions in your thesis are that 1) unit tests catch all stupid little errors so you can stop worrying about them, and 2) the time spent chasing down stupid little errors that would have been caught by your tests is made up for by the cost of creating those tests in the first place.
Unit tests are not magic fairy dust. Having them does not make your code bug-free and even if something is covered by a test it is still possible that both the test and the code are wrong in the same way. Putting too much belief in correctness due to tests passing can be just as bad as not having any tests at all. Unit tests are great at api boundaries and points of interface between data-munging code, but every function or process does not need its own unit test.
Unit tests also have a high up-front cost that is frequently not justified by the return on this investment. There is a subtle art to selecting the granularity of testing that takes a while to learn, and spending too much time around TDD zealots will often lead coders who have not learned this skill to waste time writing tests instead of getting things done.
Like IDEs that flag type errors, compiler warnings, and debugger breakpoints, a test is just a tool. If you can't write working, maintainable code without any of these tools then perhaps you should spend more time honing your craft instead of collecting another crutch.
Gabe da Silveira about 2 hours later:
I like Tim’s comment.
Automated testing is wonderful. I really like unit testing as a design and documentation tool. I really like acceptance tests as a regression and business communication tool. I’m really thankful that there are those individuals who are more passionate than me about testing pushing the tools forward (Selenium, Cucumber, TestSwarm, etc). Joel was really really wrong to dismiss “unit tests”.
That said, testing is far from a silver bullet. The problem is that tests are overhead, the marginal cost is low, but not free. You have to pick what to test, and some things are very hard to test (people are steadily chipping away at that, but let’s be honest, some things will always be hard to test). No test offers as complete coverage as an actual human performing an acceptance test. Common programming techniques lead to an explosive number of edge cases that are all but impossible to enumerate and therefore test.
That brings me to my agreement with Tim Bray. Functional programming is the most powerful tool for ensuring program correctness that we have in our bag. It’s really about leveraging thousands of years of mathematical practice in proving symbolic statements and applying that to software. If we can remove side effects from our code, our ability to reason about code is increased by several orders of magnitude. It certainly is inconvenient at times, but forced purity can give you guarantees that no amount of tests can ever provide. Of course it doesn’t preclude the need for tests to ensure algorithmic correctness, but just imagine the power of a unit test if the function is guaranteed pure.