I am a terrible programmer
danshipper.com
danshipper.com
A smart accountant once told me that the answer to "How much money did you make?" is always, "Who wants to know?" If it's an investor, the answer is "A lot." If it's a customer, the answer is "A little." If it's the IRS, the answer is "None."
Same thing here. The answer to "Who is a good programmer?" is always, "Who wants to know?"
To a project manager, the programmer who hits every deadline (regardless of quality) is a good programmer.
To a customer, the programmer who solves their problem quickest is a good programmer.
To a business owner, the programmer who makes them the most money is a good programmer.
To a PHB, the programmer who makes them look the best is a good programmer.
To a journalist, the programmer who tells the best stories is a good programmer.
To a junior programmer, the best mentor is the good programmer.
To another programmer, the programmer they are most likely to want to go into battle with is a good programmer.
To a blogger, the programmer who best fits the profile of the point he is trying to make is a good programmer.
Make your code readable.
My theory was that because these guys were so smart, in many cases they overestimated the ability of others to comprehend what was clear to them, and as a result simply made their code too clever and omitted comments that might help clarify it.
It was a definitely a valuable experience, though; besides the natural pleasure of working with very smart people, it really drove home the importance of actively pursuing clear and well-commented code! :]
I'm not in favour of littering the code with a pile of comments which will most likely become obsolete in three months, but it's very important to do whenever you are: - implementing a non-trivial algorithm - doing something surprising (maybe to fix something on a specific architecture or whatever) - implementing a complex business rule
However, they should be encapsulated in an easy to understand API.
That way, you (the usual programmers) can call the code, and they (the very smart programmers) can write smart and efficient code. You are not supposed to tweak that smart code, just call it.
The solution is not to dumb down everything. That way leads to madness. Or Java.
None of the original developers are still at the company and one of your customers has discovered a bug in their implementation because of some obscure edge case and now you get to spend the next month understanding the complex code and writing a patch.
Writing maintainable code is not the same as dumbing everything down.
It is hard to understand. It is efficient. It probably requires computer science knowledge to solve the issue. And yet it is as maintainable and well documented as they possibly can make it.
Not everything can be 'business logic' in the sense of 'something a manager can understand but not code'.
Some algorithms are just hard. And they are worth it.
What would be Google without PageRank? What would be Skype without their LAN piercing modules? What would be iD without their game engines? What would be CryTek without their game engines?
Worthless, that's the answer.
What is absolute competence in writing novels? Writing magazine articles. Publishers want good writers that sell lots of books, young writers want good writers that critique their books.
There is a base level of competence, but even that is often local culture
You write code that will almost for sure, live on for 10+ years and will be changed by a lot of people.
Good code will be maintainable and easy to extend/change. Bad code is just... every programmer's nightmare.
Bad code will still be bad even if it made the product go live, and good code will still be good even if it took a few more days/weeks to produce it. The balance between quality and speed is completely product dependent. But sooner or later bad/fast code will claim it's price.
And to go further, where the OP argued that product quality and development time are mutually exclusive; I submit that they are not.
In the right hands, good code can be written quickly and efficiently, just as good novels can be written as quickly as bad ones are, or good music can be written as quickly as bad music is.
The parent was making the point that, like writing, good and bad coding style is entirely subjective - necessarily so because many parts of it are simply conventional.
There are some specific constructions in programming that can be shown to be better than others through complexity theory, but even the guidelines we have for these aren't global optimums.
You can't measure it with a ruler or some lines of code formulae, but good programmers are easily recognizable by other good/experienced programmers.
If I need someone to crank out a report by afternoon which will never be used again and he was able to do it, he's very competent. If I need someone to crank out a car control system and he took one year to do it but has very low defects afterward, he's very competent.
Replace the word 'programmer' with 'coder' and you might have a point. Whenever I hear the word 'coder', all I can think of is shelf-stacker. A coder writes lines of code, a programmer builds products or 'things'. All the rules and standards regarding code belong to coders - they have nothing to do with finished, shipped, or successful products.
But what do I know? I've only been building products for 13 years. And I'm drunk.
What are the ways to objectively measure the competence of a programmer?
If that was the case, then it would be much, much easier to hire and fairly compensate programmers than it is in reality.
A very rough measurement of programmer competence:
The programmer is given a product specification. He creates the program in T time using S size of code.
1/(T * S * S)
is a very good approximation of how good the developer is. (small size is more important than the taken time, that's why I've taken S square. We can tweak the formula of course. Maybe 1/(T * S * S * S) is even better in some cases.)
TL;DR: the most common thing amongst good programmers in my opinion is that they are masters of the DRY principle, but they do not overabstract; in essence they write smaller code to problems (usually even faster) than not so good programmers. The bigger the system is, the more and more architectural/design skill is needed to keep the code base small.
If a piece of software is needed by the date of a major launch, and a programmer doesn't ship, all because he wants to reduce the amount of code involved, then he's an awful programmer as far as the business is concerned.
Running over time can cost millions of $ of investment in other areas of the business:
- Press organised
- Advertising purchased
- 1000s of hours of staff training underway
- Suppliers informed of increased demand / new supplies purchased
- Customers told to expect delivery by date
Any one of these areas can cost 10x or more of the cost of developing the code.
If you're not writing code which would be affected by that kind of criteria then cool, go for whatever metric you want to define.
Time taken is almost always the number one criteria of any business requirement, or to put it another way, small size of code means almost nothing to anyone except the original developers.
>small size of code means almost nothing to anyone except the original developers.
No. Small size reflects the quality of the code: It reduces the time of future developments (non DRY code keeps growing agreessively and becomes even more non DRY and very time consuming to develop new features into). It is an investment in the future. Now you are right: sometimes it is not worth it to invest into the future, because maybe the code will be thrown away because it will turn out that the startup/product is not viable. Somtimes you know that product has a stable growing market and you will have to develop tons of features into it in the future. Then investing in the future is very important.
Not always. Case in point: a week or two ago, I refactored some C# code. It was an installer generator, which was coded entirely in the controller. Yeh who want to add unit tests, abandon all hopes.
So the code is now split into different pieces, according to responsibilities, with dependency injection, and I/O in its own layer. The result, in terms of lines of code, is a net increase. But according to your metric, I have decreased the quality of the code.
I agree that generally speaking, less code is better than more code, but more code can mean reusable, more readable code.
The bigger the system is, the more probable it is that you can make it better while decreasing the code size. Above 10.000 lines a bad code usually is not DRY enough so much, that it is very easy to decrease its size while increasing its modularity.
Yes, code size is not a perfect indicator of quality. But reducing code size is a very central part of my design philosophy. When you very conciously refactor to smaller code size (using good design patterns) the code and the abstractions in your head can become incredibily clear.
For example I write a software which deals a lot with rectangles. In the beginning my rectangles had four properties: left, right, top, bottom. After a while I've found out that my code gets more and more redundant; I have to find an abstraction which relies on the symmetries in the problems. So now my rectangle has this interface to get and set the 4 sides:
void setSide(bool vert, bool isEnd, int value)
int getSide(bool vert, bool isEnd)
Not only my code size reduced dramatically, but because of this new abstraction I've understood the problem much better!
Here's to the technical interviewers out there who know all too well that there is no correlation between number of years of employment as a "software engineer" and the quality of the engineer.
> To a customer, the programmer who solves their problem quickest is a good programmer.
Up until the codebase is such unbelievably appalling shit that you can no longer add new features, solve problems or reliably hit deadlines. I have worked on too many of these projects to be able to easily count them.
Typically, I'll be the one fixing up something after the previous developer has run away or has been sacked. There's often a culture shock when the manager/customer/project manager who is used to calling the shots suddenly finds that their latest idea needs to take a back seat while deeper (often 'invisible') problems get fixed.
Perhaps another take is that a "good programmer" is one who is still around and still adding features after a couple of years.
In the programming world, one man's treasure is inevitably another man's unreadable spaghetti dependency-ridden junk.
Obviously not true, unless your project manager is a complete idiot.
If the estimated time aligns with what they want, then you're fine. But that's rarely the case and when things slip the code cleanup is pushed to the back burner.
And a programmer is not always in charge of his estimates. He may have to arrive at it together with his team lead who is under pressure from 2-3 project managers, thus only the minimal reasonable time will be allocated, without concern for architecture changes or refactoring.
I write very nice, commented JavaScript that employs consistent whitespace and indentation and validates in JSLint all day long. That's just how I do it and I'm way faster than the coworkers of mine who code things quick and dirty.
You reach a certain level of expertise and your code will just naturally have these qualities. It will be both beautiful and will be developed quickly. Senior talent gets this. Junior talent doesn't.
This was a thought provoking article though. The main takeaway is that "getting things done" is the most important skill a programmer can have which I completely agree with. For the sake of other developer's sanity, clean code is so important too. Ugly, sloppy code takes longer to read, more effort to maintain and is frankly demoralizing and tiresome to work with. Clean code for me is probably right underneath getting things done on a skills ranking. Ideally, good developers would have both...and my experience shows that good developers do.
Sorry, bud, I worked with a couple of guys like you before - very bright, smart, self-confident, young, yet started coding before they started drinking, but with not a lot of mileage in the industry - and the problem was that this style of work is not compatible with other people. It's great for prototyping. It's great when you work alone, but it's a nightmare in a true team environment and the resulting code is nothing but a headache in a long term.
I'm sure you can ship, but that's hardly an achievement. Everyone one can, but shipped out shit in a working condition is akin to all that Made in China crap from Walmart. Nothing to be proud of to put it mildly.
> So next time you’re working on a project, give some thought to what’s most important: speed or elegance.
It's "Fast, cheap, good - pick two" and "You get what you paid for".
>Sorry, bud, I worked with a couple of guys like you before - very bright, smart, self-confident, young, yet started coding before they started drinking, but with not a lot of mileage in the industry - and the problem was that this style of work is not compatible with other people.
Me too. And it's not just the code they write that's a headache - they're usually a pain in the ass to work with because they always know way more than everyone about everything. They know more about algorithms, they know more about software engineering, they know more about software design, they know more about human nature and the industry. They even know more about things they know nothing about. Meh.
In a fast business with a very small team and a very short runway you often have to sacrifice quality in exchange for putting something out there. If something doesn't come out of the oven, there's no "long term". At that point, the choice makes itself. That's probably why a lot of people will, likely rightfully, claim that startups don't need to be highly technical unless it's where their competitive advantage will come from (and in the words of Mark Suster, 90% of startups do NOT fail because their tech wasn't good enough).
On the other hand, in long-term projects that have enough budget to survive for a while, you can shift priorities and focus on quality as appropriate.
The release process is also really important here. In web/saas you can fix things very fast behind the scenes without the customer being aware of it (Etsy claim to make what.. somewher around 100 checkins into production a day?). In mobile / boxed you have to be a lot more careful. Nobody wants to wait 2 weeks for Apple to approve your patch when a major scenario is broken in your app.
Of course, if you can have both wonderfully clean and extensible code and get that done exactly as fast as poorly written code, that's the preference.
You can ship all the code you want, but even if it's lots of mediocre code, it's still mediocre.
Quality is independent of quantity or productivity. You may choose to lower your quality in favor of a higher rate of productivity, but you've still lowered your quality.
So you may be a productive programmer. But that doesn't necessarily make you a good one.
There's also the matter of the quality of code that your'e capable of, versus the quality you actually produce. So you may be a very good programmer forced into producing shitty code (time constraints often do this).
But let me say this: a good programmer who consistently ships great, high quality code regardless of the situation is still a better programmer.
So, the perfect programmer is a better programmer? That goes without saying. I think his post is more an issue of people who build things vs. people who can code algorithms. Personally, I'm the former and as such naturally think it's superior. Let's face it, we can't all be perfect programmers.
There's the developer who can register a domain, set up a LAMP server, get a web application up, create a good database schema and make it look nice and do it all in a weekend. Then there's the programmer who will come in and look at one portion of a less-used paged and call you a shitty programmer because you did it in O(n^2) when using THIS clever algorithm you could do it in O(n).
It depends on what your focus is I suppose. The question is whether or not I (or the author of the article) would be able to optimize that chunk of code if the user experienced slowness.
Nope, they'll call you a shitty programmer because every function in your codebase depends on the interface of every other function. Then they'll charge you a fortune to fix it.
You have to have an objective notion of quality before you go trying to apply it to reality. And if you do, you might have a chance at improving it.
Ah, but I just noticed a small syntax difference in your argument. You're arguing about better CODE not better CODERS. Still arguable, but more objective. You can easily gather a lot of metrics about code. Still, if I'm programming something for my graphic designer sister to work on later, I'm going to program differently than if I was writing a compact and efficient internal piece of code.
*Using two of the only athletes I really know.
But I'm saying, when you're measuring quality objectively, it just doesn't matter. What matters is the thing itself. The created object. The outcome.
I'm not simply incorrect—I'm simply correct. My argument has the constraint of simplicity. It is defining the basic existence of a thing which we know exists, namely Quality. When you add complexity, yes, the definition is no longer sufficient to describe the entire process; but I'm not claiming that perfect code and perfect coders are possible in reality. I'm saying: start with simple and true definitions so you understand what quality is by itself, so that once you add situations and reality to it you can still try to achieve something close to "good." It is a matter of scope.
This isn't an argument. Quality exists. Defining it is hard, yes, but it's not impossible to understand that one thing can be better than another by many measures, and we say that thing has higher Quality.
Read "Zen and the art of Motorcycle Maintenance," it'll twist your brain up some more.
What you're going to say next is of course that you're right and that devolving into silly philosophical arguments doesn't mean anything to real-world work, so yes, I guess I'll agree with that.
I'm not clear who you're complaining about here. It's possible you're complaining about yourself.
I was trying to say that it if the parent writes clean, clear, and efficient code, it might qualify as the sort of beautiful code that people are striving for.
The code might be mediocre, but that doesn't mean that the product is mediocre. Pristine, beautiful code, that forms part of a bad product, is like a soprano singing the most god-awful piece of bilge anyone has ever heard. Doesn't matter how good her voice is if the song is rubbish and makes everyone cringe.
I think you just shifted the problem of defining a "good" programmer to defining "high quality" code. Some people might argue that the code that gets the job done most efficiently has the highest "quality".
The Ruby community has a great emphasis on beautiful, elegant code, but how many first commit trees on github are actually after hundreds of hours were spent, a good percentage of which involved beautifying and organizing.
I definitely prefer to read clean, well organized code, but I'd also like to read the first attempts and the discarded approaches used by the hackers I admire.
I guess where I'm going with this is that for those who are beginning or come from a non-CS background, seeing all this polished code, even in initial commits, being posted to sites like HN or reddit is very intimidating and could be a drawback from people sharing their code.
I'm no one special, and I seriously doubt anyone looks at my code, but, if someone ever did, they'd see work in progress.
Just like the code base at work. Nothing's brilliant the first time out.
If you're good enough at what you do that you have time to blog your inner debates about how good you are, you're good enough to need more important things to do.
If you're commentative enough at what you comment that you have time to comment on your inner comments about how good you comment, you're commentative enough to need more commenty comments to comment.
Surely that's what YouTube is for, people with no talent to post some random rubbish about something that nobody actually cares about?
We can't all be brilliant programmers. Heck I'm not, but I've been in the industry a long time, and know the difference between when to write good code at the expense of time and when something is unlikely to see the light of day/prototype/one-off.
They always come across as nothing but self-promotion thinly veiled under buzzwords related to software development, rarely with any real substance.
From what I can tell, he hasn't really done anything notable. He's a college student who has apparently been involved with some relatively unknown startups, and otherwise does some pretty typical and unremarkable software development.
It just seems like he's usually trying to make a big deal out of stuff that's pretty inconsequential, while continually dropping his name or that of some startup he's involved with.
1) Dan is beyond his years in terms of articulating his thoughts on startups and software development, and reminds some people of a young Jason Fried (co-founder of 37Signals, author of "Rework", etc.)
2) Dan is (much like Jason Fried) a bit of a contrarian. He has shipped almost two dozen apps/sites in the past couple years and is working night and day on growing his current startup, but he isn't dropping out of university. He also isn't out raising venture capital and trying to scale scale scale -- instead focusing on building a business that makes revenue and is profitable from (almost) day one. And lastly, because he is not chasing the "sexy", popular consumer app space -- instead focusing his efforts on the 'less glamorous' SaaS and B2B space.
*
The combination of these factors make a lot of us in HN interested in where Dan's career is headed, and thus interested in reading his posts and watching him progress as a founder while still in school.
That's why so many Dan Shipper articles get submitted here, and why they always end up near the top. He is the real deal.
I am surprised that no one has talked about technical debt yet. This is a classic case of taking technical debt for productivity. Like all forms of debt, some of it is good, it's leverage on your time (ie. you spend less time making it perfect, and more go to market faster), but you need to pay it back at some point in the future.
The key difference between what the author espouses and a good programmer, is that the good programmer makes the conscious choice to accrue the debt in favor of speed and creates an action plan to pay off the debt at a later time.
I do not believe that you can become an a good programmer until you can understand the distinction, make the proper trade-offs necessary to hit project objectives and create an action plan along the way to pay off the debt in the future.
For startup/rev1 web products, no doubt Dan's abilities are paramount. Would I want that same "ship it now" hacker ethic at work on a flight system? Or a heart monitor? Hell no.
Context matters.
It sounds like the author of the article has never had to deal with any of these issues. That doesn't make him a bad person, but it does mean that his advice shouldn't carry a lot of weight.
I doubt Torvalds produces (or produced) quick dirty code to "make stuff happen", and I also bet he's a hell of a programmer.
As stated by someone before, shipping stuff fast makes you a good "product builder", not a good programmer.
If someone needs to maintain it, and that someone isn't you, it's very likely they're going to understand your shite stream-of-consciousness code much more easily than your beautiful, elegant code that has had all of the thought process refactored out of it (but refactoring is a very important tool).
We too often forget our code sits atop a stack of compounding encapsulations we'd all find horrifically disgusting whose only true merit is that it actually functions.
Your goals when refactoring is removing useless bit of code, make the code understandable without comment and remove duplication.
That is the last step that generally requires introducing additional abstractions layers and where stuff go wrong. Too often refactoring books or articles give examples of how to use refactoring technique, but for the sake of being readable, the examples rarely really require such refactoring in the first place.
But yeah, at the end of the day I also prefer a hackish piece of code that solves the problem than the same "refactored" into conceptual art.
Takes a lot of wisdom, discipline, and not a little luck to know where to invest deeply in building robust software and where to get something done quickly so you can start testing it in the marketplace.
Also, depending on the business, the MVP may end up being a large and complex code base that can't just be hacked together haphazardly. Not all startups build iPhone apps; some build on-line retail businesses or investment banks.
Larry and Sergey's first hires were for people to replace the crumbling hacks they wrote to launch Google.
Mark Tarver compares "street programmers" (people like the OP before he started to take some CS courses) and people who focus in Computer Science without practical (industrial) coding.
I would like someone like you, with a quick turnaround on features for early products and prototypes but such personæ wouldn't be my first pick for a stable or mature product where quality is paramount to speed.
Its all relative.
FWIW, I believe you are too quick to dismiss sound theoretical background, and I say that as a college drop out who had to fire PhD students from his team in the past. Theory is important and, given the right context, I'll go with the academic type, with slower turnaround that will take months to deliver a single feature.
> The answer is: a good coder knows when something should be quick and dirty, and when > something should be thorough and clean.
From my experience, people tend to be better at one than the other, its not a simple switch in your brain that you turn on and say "ok, now this part is important so I'm going to be much more careful here". From what I've seen, a prototyper is, at the same level of competence, worse at being thorough with documentation/well thought-out data models/corner case handling/etc.
But the code in those games was crap. Looking back on the early stuff, I am amazed it even compiled. It wasn't until I had to work on a +500k LOC codebase with 30 other programmers for a year and a half that I learned the importance of writing code that can be easily read, understood, and modified by other programmers (or even myself) six months after it was written.
Writing maintainable code is a skill that comes naturally to every good developer after they have to work on the same code base for an extended period of time. Dan hasn't had time to do that because he's shipped 20 different apps in the last 2 years, but now that he's working on his own startup (and will be for the foreseeable future) it sounds like he's learning the value of elegant code.
Sometimes we have to treat programming like a black box. All we care about is getting the desired output. There will always be time to make the code efficient later.
The end user and manager only care about the output.
In regards to getting features out quickly: that's a great programmer. Though inevitably there comes a time when the code needs to be maintained - and if it is unmaintainable then I'd put you in the bad programmer category.
Now-a-days: I prefer clean code to a specific coding standard over the quick, dirty features being implemented. But, only because it usually causes more pain in the long run. I understand the "getting a feature out quickly to test it even works" mentality, and to some degree I agree with it. However, if it DOES work then a clean code base is always better. Inevitably it will need to be maintained...
After writing this (sorry: could rewrite my comment but decided not to) I've now realized that I'm now AGAINST the feature push mentality. I'd much prefer well written code and eat up the cost then rather than later on. Worst case scenario, it can then be reused...
-Sometimes this means a programmer can drop into the style already in use on a project, even if it's not the 'best' approach. That way his changes are low-impact and can be easily understood by the people who have worked in the system for years.
-Sometimes this means the programmer needs to architect a complex solution to a hard problem. (Though I think this is an assumption we make far too frequently.)
-Sometimes this means the programmer should spend some time understanding the constraints on the project, and express them in code. If a constraint is acceptable at least until the next major version of a piece of software, then why not focus on making it simple to alter the assumption, rather than adding complexity to avoid the assumption completely?
-And sometimes, this really does just mean "Ship that mess by next Friday", regardless of the cost. Sometimes it's just more important to get a poorly architected version in the hands of users that just does what it says on the tin, especially if their input could drastically change your requirements.
[1] http://www.folklore.org/StoryView.py?story=Real_Artists_Ship...
Which meaning of speed? You can write fast programs, and you can write programs fast, but you can't write fast programs fast.
Great people need to find a balance, and I don't think leaning towards one side or another shows whether someone would be a great employee and/or founder. This "ship early/ship often" and "move fast and break stuff" attitude is ok for immature products, but there's still a minimum level of quality you need to reach, and as your userbase grows and your product matures, it's almost certainly going to be important to raise the bar on quality.
Shipping prototypes is fine, but you have to keep in mind that if it catches on, your plan to rebuild a non-crap version (invariably you had this plan) will fall through because something else came up.
My rule of thumb for prototypes is to get the data models close to right, and untangle the rest later. Pulling apart spaghetti code isn't too bad as long as there's reasonably sane intent behind it. I can fix systems where people are updating state from the views and writing to the db in all sorts of unimaginable, horrible ways; however, if you're not storing the right info, you're pretty screwed and have a hell of a migration process in your future.
Edit: the link I included is more to do with algorithms and the like, mea culpa, but there are also studies cited in books like Code Complete that cover what you mention. How recent, or how good the research is, is another matter...
A huge part of being a good programmer is knowing when to just solve a problem quick and dirty, and when to really plan it out and implement a beautiful design.
Either way, if the programmer is making the right decision most of the time they should feel good about the work they are doing.
At the end of the day we provide value. Provide value to the right people at the right time and you will have a good career.
The subtitle for this should be:
"An ode to everyone that has gotten flamed on Stack Overflow or IRC for 'bad code'".
That is what sets good and bad programmers apart. Bad programmer have no clue that they are writing terrible code.