From Podcast 38

Here’s a brief conversation between Jeff and I which I transcribed from Stack Overflow podcast #38, starting at [42:28].

Joel: There’s a debate over Test Driven Development… should you have unit tests for everything, that kind of stuff… a lot of people write to me, after reading The Joel Test, to say, “You should have a 13th thing on here: Unit Testing, 100% unit tests of all your code.”

And that strikes me as being just a little bit too doctrinaire about something that you may not need. Like, the whole idea of agile programming is not to do things before you need them, but to page-fault them in as needed. I feel like automated testing of everything, a lot of times, is just not going to help you. In other words, you’re going to write an awful lot of unit tests to insure that code that, really, is going to work, and you’re definitely going to find out if it doesn’t work [if you don’t write the tests] does, actually still work, … I don’t know, I’m going to get such flame mail for this because I’m not expressing it that well. But, I feel like if a team really did have 100% code coverage of their unit tests, there’d be a couple of problems. One, they would have spent an awful lot of time writing unit tests, and they wouldn’t necessarily be able to pay for that time in improved quality. I mean, they’d have some improved quality, and they’d have the ability to change things in their code with the confidence that they don’t break anything, but that’s it.

But the real problem with unit tests as I’ve discovered is that the type of changes that you tend to make as code evolves tend to break a constant percentage of your unit tests. Sometimes you will make a change to your code that, somehow, breaks 10% of your unit tests. Intentionally. Because you’ve changed the design of something… you’ve moved a menu, and now everything that relied on that menu being there… the menu is now elsewhere. And so all those tests now break. And you have to be able to go in and recreate those tests to reflect the new reality of the code.

So the end result is that, as your project gets bigger and bigger, if you really have a lot of unit tests, the amount of investment you’ll have to make in maintaining those unit tests, keeping them up-to-date and keeping them passing, starts to become disproportional to the amount of benefit that you get out of them.

Jeff: I think that’s a great point. Although, I do think if you’re working on older code bases that don’t have a lot of churn, …

Joel: Yeah.

Jeff: To me it’s about churn. If you’re working on an old code base that isn’t going to have that much churn, and you want to change it where you can’t break anything, where if you break anything it’s really really bad, then it’s probably worth your time to go in and develop a bunch of unit tests. You’re building scaffolding around this grand old building, this classic old building that’s not going to change for another 200 years, so sure, build a bunch of scaffolding around the building.

Joel: Yeah. They work really for things like a compiler, where the design is not going to change because the language is fixed.

Jeff:That’s right.

Joel:I might do more black-box tests, sort of like unit tests but more from the perspective of “does this compile all code correctly,” with enormous numbers of tests, than just the internal, “does this particular function work in this particular way at all times.”

Last week I was listening to a podcast on Hanselminutes, with Robert Martin talking about the SOLID principles. (That’s a real easy-to-Google term!) It’s object-oriented design, and they’re calling it agile design, which it really, really isn’t. It’s principles for how to design your classes, and how they should work. And, when I was listening to them, they all sounded to me like extremely bureaucratic programming that came from the mind of somebody that has not written a lot of code, frankly.

And here I am ranting against somebody that doesn’t have a chance to respond. But just to give you one example, a part of the SOLID principles was that if you write a class, that class has contracts with all the other classes that it interacts with, and those contracts should be expressed in interfaces [PDF]. So you shouldn’t just interact with the class, because that class may change. If you have a particular class that you need to use, you should make a custom interface just for what you’re going to use in that class. That interface, then, never has to change. And the interface is the only thing that you have to #include.

Does that make sense? So, you’ve got some class, with 40 different little methods on it, and I’m only going to use six of them, so I should make an interface with those six things that I can use, and the class will implement that interface, and that’s my contract with the class, that those are the only six things I’m going to use.

People that say things like this have just never written a heck of a lot of code. Because what they’re doing is spending an enormous amount of time writing a lot of extra code, a lot of verbiage, a lot of files, and a million little classes that don’t do anything and thousands of little interface classes and a lot of robustness to make each of these classes individually armed to go out into the world alone and do things, and you’re not going to need it. You’re spending a lot of time in advance writing code that is just not going to be relevant, it’s not going to be important. It could, theoretically, protect you against things, but, how about waiting until those things happen before you protect yourself against them?

This seems to be where a lot of the Object Oriented Design community went, and if anybody has any strong feelings about this, call in and tell me what you think–tell me if I’m totally off track here–but it seems to me like a lot of the Object Oriented Design principles you’re hearing lately from people like Robert Martin and Kent Beck and so forth have gone off the deep end into architecture for architecture’s sake. It doesn’t seem like you could actually get any code written if you’re spending all your time writing 8,000,000 unit tests, and every single dinky little class that you need to split a URL into four parts becomes an engineering project worthy of making a bridge, where you spend six months defining 1000 little interfaces. They’ve just gone off the deep end, and I don’t think these people write very much code if they’re coming up with these principles, to be honest, it doesn’t even make sense.

Jeff: Well, there are places where that level of testing makes sense. If you’re working at Microsoft and you’re working on the .NET Framework…

Joel: Yeah.

Jeff: … you have a totally different set of obligations to your public …

Joel: Correct.

Jeff:… Your code’s going to be used millions and millions of times.

Joel: Yeah. In fact, if you’re making any kind of API, a plug in API, it is very important to separate things into interfaces and be very very contractual, and tightly engineered. Just like you want to put a lot of effort into your user interface, you also want to put a lot of effort into your API that people are calling… it’s just an interface, and you want it to be good and solid and robust. And that’s fine.

But this idea that every single class in your code, all these classes interacting with each other, should be so tightly defined

Listening to this interview on Hanselminutes, there seemed to be an intense obsession with creating lots and lots of little classes that all did one particular thing…

One of the SOLID principles, and I’m totally butchering this, but, one of the principles was that you shouldn’t have two things in the same class that would be changed for a different reason [PDF]. Like, you don’t want to have an Employee class, because it’s got his name which might get changed if he gets married, and it has his salary, which might get changed if he gets a raise. Those have to be two separate classes, because they get changed under different circumstances. And you wind up with millions of tiny little classes, like the EmployeeSalary class, and it’s just… (laughs) idiotic! You can’t build software that way! The way real software works is that you create these very imperfect things, and they work great. They really do. And then you have a little problem, and you go and you fix the little problem, because it’s code, and you have an editor, and you edit it. These classes are not going to go wander off flying in the universe all by themselves and need to work perfectly and unchanged until the end of time.

Jeff: Right. The longer I think about this, the less I care about code hygiene issues (laughs). Because the unit of measure that really matters to me is, how quickly you can respond to real business needs with your code. And by that I mean, how well are you serving the people that are using your code. To me that’s what it’s all about. Anything that gets in the way of you fixing your code or improving your code in a way that your customers can appreciate, is a negative. If that means using Ruby, or having lots of unit tests: whatever’s working for you: do that. But if it’s getting in the way, if it becomes friction, like, “I’d love to have this great new feature but I’d have to have 1000 unit tests,” that’s a negative.

Joel: Yeah. And the worst thing that happens is that you get people that just stop thinking about what they’re doing. “This is the principle, to always write unit tests, so I’m always going to write unit tests,” and then they’re just not thinking about how they’re spending their time, and they wind up wasting a lot of it.

Jeff: Yeah, it’s a balancing act. And I don’t want to come out and say I’m against [unit] testing, because I’m really not. Anything that improves quality is good. But there’s multiple axes you’re working on here; quality is just one axis. And I find, sadly, to be completely honest with everybody listening, quality really doesn’t matter that much, in the big scheme of things… There was this quote from Frank Zappa: “Nobody gives a crap if we’re great musicians.” And it really is true. The people that appreciate Frank Zappa’s music aren’t going, “that guitar was really off.” They’re hearing the whole song; they’re hearing the music, they’re not really worried whether your code has the correct object interfaces, or if it’s developed in a pure way, or written in Ruby or PHP… they don’t really care about that stuff. We do internally, but it’s important to balance that, I think, and I think that gets missed a lot, which is, maybe, the point you’re getting at.

Joel: Yeah.

Jeff: I think over time, more and more, I’ve become really lax on my thinking about this, because what matters is what you deliver to the customer, and how happy the customer is with what you’ve delivered. There’s many, many ways to get there.

I am not having any problems with Google

A very irresponsible journalist, Paul Boutin, wrote a whole story in the Industry Standard which appears to me made up from whole cloth.

He is attributing, to me, a comment posted by an anonymous poster.

I am not using Google Apps, I did not write the comment in question, basically none of the things that Boutin said I did are true.

A part of the problem is the design of my discussion groups, which look too much like the main Joel on Software site. A part of the problem is unregistered, anonymous posters… that will be turned off immediately. Another part of the problem is The New Tech Journalism, which will have to remain a rant for another day.

Purchase orders and custom licenses

Over on the Business of Software group, we’re discussing those big bureaucratic companies who want a custom legal agreement to buy $79 worth of software. “Lawyer-infested companies that are obsessive-compulsive about contracts do not pirate software and they CERTAINLY don’t try to trick you into signing a contract ‘allowing’ them to pirate your software. This theory is laughable.”

“By installing Java, you will be able to experience the power of Java”

Just because there’s room on the dialog box, doesn’t mean you have to put something there. The Java installer starts off with a dialog box that manages to repeat the word Java six times without really telling you what it is, just that it’s “everywhere.”

People don’t like to read. If you can’t think of anything to say, maybe you should just shut up. This whole damn dialog could read

Java Loves You—Please Wait

without any loss in functionality.

Goals

Seth Godin reminded me about having goals. “Having goals is a pain in the neck,” he says, but “the people who get things done, who lead, who grow and who make an impact… those people have goals.”

OK, good point. Here are Fog Creek Software’s goals for 2009, in no particular order:

  • Ship FogBugz 7.0 for all platforms
  • Ship Copilot Desktop for all platforms
  • Release the next documentary about software development
  • Build a kick-ass new product from the ground up with the summer interns, and get the first dollar of customer revenue before they go back to school
  • Put on a fantastic Business of Software conference
  • Relive the glory days with another FogBugz World Tour

I like what Seth said about how “if you don’t have a goal, you never have to worry about missing it.”

Copilot OneClick for Macintosh

Fog Creek Copilot is an inexpensive, and very easy to use, remote tech support system that allows you to remote-control someone else’s computer over the Internet without installing anything special. It’s perfect for ad-hoc tech support, and used extensively by helpdesks, software companies providing telephone support, and people helping their friends and families with computer problems. At Fog Creek, we even use it to conduct coding interviews for programmers.

The new Copilot OneClick feature lets you preinstall the software on all the computers you connect to frequently, so every time your dad calls up needing help with the accounting software running his Ponzi scheme, you just click one link and you’re logged onto his computer.

As usual, it works through all kinds of firewalls, proxies, and NATs without any configuration, it’s protected by 128-bit SSL, and there’s never anything to configure.

Today, the Copilot team released the Macintosh version of the OneClick feature, so all the Copilot goodness is available on Windows or Mac, or both (you can control Windows computers from Macs and vice versa). And it’s cheap, by which I mean, inexpensive—I don’t mean that you can just buy it two drinks and take it back to your apartment and expect to be taking a bubble bath with it—most people get the $19.95 unlimited plan; it’s even free on weekends when we have lots of unused bandwidth.

Read about the team’s experience developing a Mac-based installer, then try the free trial! Bubble bath not included!

Another resume tip

Are you a software developer applying to a small company?

Here’s a tip from someone who has read thousands of resumes. When you’re applying to a startup, or a software company with less than, say, 100 employees, you may want to highlight the Banging Out Code parts of your experience, while deemphasizing the Middle Management parts of your experience.

When a startup CTO sees a resume that says things like:

  • Responsible for $30m line of business
  • Architected new ERP platform
  • Managed team of 25 developers
  • Optimized business processes

they think, “Spare me, that’s all we need, somebody running around trying to manage and optimize and architect when we just need someone who isn’t afraid to write code.” Here’s the stuff CTOs at startups want to see on a resume:

  • Single-handedly developed robust 100,000 LOC threadsafe C++ service
  • Contributes to OpenBSD file system in spare time
  • Wrote almost 75% of the Python code running IsIt2009Yet.Com

If you’ve been in a large company for too long, you may feel that you put in your time, with all those years working your way up the hierarchy from the $50,000 coder jobs to the $250,000 Senior Vice President in Charge of Long Meetings With Other Senior Vice Presidents, and you’re kind of enjoying the nice parking space and the personal assistant and stuff, and coding? not so much, so now you’ve found a cool startup or small company, and you’re thinking, maybe now’s the time to jump ship? So you send your resume with your ERP stuff and SAP stuff and Vice President stuff to the startup, and it gets tossed.

Those VP jobs just don’t exist at startups, and the few VPs they have are the founders and a key early hire or two. Not you. And startups certainly don’t need extra middle managers. To a startup founder, middle managers just seem like added expense without more code getting written, and the only thing we REALLY need is

  • code to be written, and
  • customers to be called on the telephone.

Now, there’s a lot of resumes I see where, actually, I suspect that the candidate may have been (ahem) slightly overemphasizing the management/leadership/“architect” parts of the job, and slightly underemphasizing the banging out of code. And that’s fine if you’re looking to jump to a management position at a big company that, inexplicably, doesn’t have anyone to promote from within.

But for startups, everything about your resume has to scream getting your own hands dirty. Otherwise your resume makes you look like you’re looking for the kind of job where you can call meetings that take people away from coding all day long, which, to a startup, is about as useful as a one-legged man in a butt-kicking contest.

(More resume tips, and, if you’re really looking for a job, don’t forget the job board).