I have two degrees (Bachelor’s and Master’s) in computer science, so it’s probably no surprise that I place a fairly high degree of value on the background that all of this course work provided. That being said, my experience was that you learn some pretty unfortunate ‘lessons’ in CS degree programs. To name some that I learned (and later had to unlearn):
- Writing readable code is for weaklings. Writing your entire loop logic inside the loop guard condition FTW!
- You get partial credit for non-running (or even non-compiling) code if you add a lot of vacuous comments.
- All programming projects can be wrapped up in a month or, in extreme cases, a semester.
- Source control is an important thing, theoretically, but it doesn’t solve any actual problem you have.
- There are no consequences to making an enormous mess of your code in the hour before your deadline as long as it hits the predefined benchmarks because you’ll never look at it again in your life.
- Performance and accuracy of results are all that matter.
- Staying up for 36 hours straight to wheeze across the finish line is how heroes get it done.
- All you need to deliver is a bunch of source code files that compile.
First of all, I’d like to point out that these aren’t things that a professor sat me down and said at any point and, in fact, if shown this list, they’d probably say, “those things aren’t good lessons.” But these were the lessons I learned by virtue of the incentives to which I was exposed and how I was rewarded or penalized for my actions. There’s a lot of room for improvement, but I’ll come back to that later.
The common theme that drives this list of less-than-awesome lessons learned is that the academic environment and the theory that it tends to teach lend themselves to non-representative situations, contrived for the purpose of teaching a specific lesson, such as how to implement Alpha-Beta pruning or how state machines work. The best ways to drive these points of instruction home don’t correspond with workaday dev concerns like “write me a web service that triggers a database update and keep it relevant when I change my mind every month or so.”
But one lesson that I did take away that has served me very well is, “do what’s necessary to get a D instead of an F, save that off for reference, and once that’s secured, go for the C, save, etc.” In a lot of classes, we’d submit coding assignments that would run against some kind of benchmark, and it was something like, “if you satisfy 60 of the 100 conditions you get a D, 70 of 100 and you get a C, etc.” And I learned that you mitigated a lot of risk by making it your top priority not to fail or get a 0, and then improving from there. This way, if the time ran out, you’d be less like an action hero trying to defuse a bomb before the timer goes off and more like a fussy dog show entrant trying to put a few last minute touches on your dog that would improve its chances of being judged better than the other dogs, whatever that entails.
This early lesson to which I was first exposed as an undergrad, around the time the Agile Manifesto was being written, was really the precursor to concepts like iterative development and thin-sliced, end-to-end goals for software. It taught me, through real, meaningful incentives, to make sure that I secured at least some value before chasing unicorns like an A+ off into the sunset. If there were 2 minutes left to submit the assignment, I wanted the backup plan to be an A- rather than a zero.
So what does any of this matter to you grizzled software veterans a decade or however long into your careers? Well, bear in mind that there’s always an A- (or B or C or whatever) out there when a bunch of work gets thrown your way. That web service you’re tasked with writing isn’t all or nothing. Not even a phone app that shows you the time is all or nothing (if push comes to shove, and app that tells you whether it’s AM or PM is better than nothing). Things can always be pared down and scope can always be adjusted, assuming you design towards modularity.
The overriding message of this post is that you should always, always, always look at the beginning for ways that you can secure yourself intermediate grades between 0 and A+ on the way to calling your software done; it’s the only reasonable way that you can manage expectations and adjust on the fly with a software project, apart from getting your customer to agree to indefinite delays. But, for a bit of fun, I’ll leave you with a series of ideas for how college CS curricula might better prepare students for actual development gigs. These might make you laugh to think about, but they’re actually things that could add some value:
- One assignment in every programming class starts you off not from scratch or from professor-written template code, but from whatever pile of mess some students turned in last semester (teaches you what an unkindness it is to make a mess in code)
- Every assignment requires students to update a single, shared text file whenever they’re testing against the benchmark and they get dinged if it gets out of sync (teaching about file contention and merge conflicts)
- There are one or more assignments during the course of the curriculum that simply cannot be totally completed (teaches students to prioritize while working against unrealistic parameters)
- There is some code that you carry over semester to semester and thus have to live with for years and/or there is a class where each assignment builds on the code of the last one but requires refactoring (teaches writing code with the idea of maintaining it)
- Lock kids out of the computer lab between 1 and 6 AM. (Teaches you that you’re going to work at places where juvenile heroics simply aren’t feasible for reasons ranging from the fact that this is a bad idea to the fact that the facility may be locked down at night)
- All homework/project submissions are real-world deliverables along the lines of an actual phone app, web app or MSI installer (teaches that there’s more to delivering software than writing code)