Programming Things I Wish I Knew Earlier
theodp writes "Raw intellect ain't always all it's cracked up to be, advises Ted Dziuba in his introduction to Programming Things I Wish I Knew Earlier, so don't be too stubborn to learn the things that can save you from the headaches of over-engineering. Here's some sample how-to-avoid-over-complicating-things advice: 'If Linux can do it, you shouldn't. Don't use Hadoop MapReduce until you have a solid reason why xargs won't solve your problem. Don't implement your own lockservice when Linux's advisory file locking works just fine. Don't do image processing work with PIL unless you have proven that command-line ImageMagick won't do the job. Modern Linux distributions are capable of a lot, and most hard problems are already solved for you. You just need to know where to look.' Any cautionary tips you'd like to share from your own experience?"
Put enough comments in your code so that five years from now you (and others) can remember what you indented the code to do. Remember that comments are not for describing what the code technically does (that is what the code is for), comments are for what the code is intended to do. Try and comment the decisions you made when developing the code, specifically why you took the approach you did and why you didn't use other options.
Don't ask for advice about programming on slashdot unless you have a pile of salt grains ready.
Am I part of the core demographic for Swedish Fish?
Sometimes it's easier and faster to code from scratch than it is to use off-the shelf software - especially in the age of "frameworks".
In that train of thought, its often better to toss and rewrite (or write new programs) than it is to extend existing programs.
It's easier to implement a whole new framework than it is to convince your boss that writing anew is actually faster.
A database is not a bitbucket. Re-building basic database functionality in an external app is not a good idea. Applications, frameworks, languages come and go; data remains forever [1]. Business logic is part of the database. If you find yourself adding more and more "application servers" to get performance than you have a fundamental problem with your architecture (and probably a fundamental misunderstanding of how databases work). While it is not impossible to learn and implement good data management/database development practices using Microsoft tools, such a result is seldom seen in the wild.
sPh
[1] Per Tom Kyte of Oracle, whose first database job at the Department of Agriculture involved working with datasets stretching back to 1790.
Eh, isn't that the basic difference between a programmer and an engineer? When I took my programming courses, there was a distinct focus on writing code with the smallest amount of new code possible, using preexisting libraries whenever possible and if there was any suspicion that the code might be useful later to split it off into a subroutine or method of some sort as done in the particular language. Sure it's a good idea to be able to write your own libraries and solutions, but it's a waste of time once you get to the point where you know how to do it. And generally using a library that's shared by other projects is much less likely that you're going to stumble on an undiscovered bugs with your program.
If you are writing a program that touches more than two persistent data stores, it is too complicated.
I disagree. Is a program too complicated if it has 1. input, 2. output, and 3. logging? Is a program to prepare images for an online store too complicated if it reads 1. raw source images and 2. an overlay image and writes 3. finished images?
If Linux can do it, you shouldn't.
That'd be fine if we all ran Linux. But in an organization that already has to run Microsoft Access for other reasons, we have to take Windows into consideration. And I don't think Ted Dziuba was talking about just using Windows as a shell to run Linux in VirtualBox OSE either.
Don't do image processing work with PIL unless you have proven that command-line ImageMagick won't do the job.
Our programmer is far more experienced in Python than in bash, and if I felt like it, I could benchmark PIL against subprocess.Popen(['convert', ...]).
if the physical machine is not the bottleneck, do not split the work to multiple physical machines.
Yet PC game developers split a 4-player game across four PCs when one could do, and increasingly, PS3 and Xbox 360 game developers are following the same path.
It is far more efficient to buy your way out of a performance problem than it is to rewrite software. When running your app on commodity hardware, don't expect anything better than commodity performance.
If you are writing software to be used internally, sometimes springing for better hardware is worth it. But if you are writing software to distribute to the public, you can generally assume your customer has commodity hardware unless your software costs at least 1000 USD a seat.
Do not make things super-modular and generic unless they 100% have to be. In 99.9% of the projects no one, including yourself, will use your stupid dependency injection, and logging / access control can be done just fine without AOP. Don't layer patterns where there's no need. Aim for the simplest possible design that will work. Don't overemphasize extensibility and flexibility, unless you KNOW you will need it, follow the YAGNI principle (you ain't gonna need it).
"Modern Linux distributions are capable of a lot, and most hard problems are already solved for you. You just need to know where to look."
First off, I must say this piece says a lot about the Linux ecosystem. Specifically that this system's documentation is anemic at best. Why won't we have something like:
"What do you want to do?...with an associated answer...this kind of arrangement surely cannot hurt the Linux ecosystem.
You know, I find that as I get older, I am able to avoid overengineering things a lot better than when I was twenty something. There's nasty effect, though. I'm learning a lot less in depth about systems than I normally would.
Overengineering is terrible for a project, but it often is highly educational.
No. Sorry, I strongly disagree.
C is like a swiss army knife that can be used to assemble a chainsaw, a sword a lightsaber, etc. You'll have to carve out all the pieces, file them down and put them together yourself, but the swiss army knife will help you a long the way.
But don't forget the bandaids.
Look, the PHB usually wants the code to run on HIS server for HIS use only. That's what he pays you for. Not to code it in the most cross-platform friendly language-du-jour and take 2 years to iron out all the bugs.
He doesn't give a shit if it'll run on the Xbox 360 or a Linux-ready Dead Badger.
And neither should you, unless you are some kind of anal retentive who spends all day arguing the merits of absolute versus relative positioning, fixed vs percentage tables, and worrying whether your code will run on every machine conceived in the next 50 years.
I have news for you, it won't.
Hell, I got an N900 6 months ago, and it's already EOL'd as far as updates to the OS are concerned.
I suppose I could wait till there's a port of Android or something, because the three coders on the project are doing a fine job, in less than a year I'll have the same functionality as a 3210.
I'm in a different boat from most commenters here, I think, because I am a scientist writing simulations; some simluations run a long time and create a lot of data which would be costly to reproduce, and what I wish someone had told me early on was that I should comment my *data files*, not just my code. Each file should include the exact parameters used to create it, an explanation of what each column represents, and preferably there should be a way of knowing what version of your simulation code was used to create it. A couple of times in grad school I had toss out months of data after I discovered a bug in my code, and didn't know when the bug showed up and which data was affected by it.
(I'd welcome other advice from simulationists too; I've never had an advisor who was particularly programming-savvy, even though programming was always a large part of my research, and so I always had to make it up as I went along.)
That's essentially what the K&R C book steps you through, and I'd say it's the best programming book ever written (or at least the best I've read). I don't get to do much in C these days, but the stuff I learned 10-15 years ago in C has made me a much better programmer. It's sad how programmers these days give you a blank stare when you ask if you passed something by value or reference.
Put everything in version control. Everything. EVERYTHING!
Well. You could skip /home, but I know a roll back of /etc has saved me a couple of times on config upgrades.
Remember that once code is deleted, you can't get it back. However, version control changes that. Version control is one of the most vital tools for anyone developing/working with a computer.
Oh and git rocks and stuff :)
Penguins can be fascists too
A few rules of thumb for a startup environment:
1. Don't overengineer! Overengineering wastes time on things that may never be used. Features should be customer driven.
2. Functions and methods should be as small as possible. You should make it an obsession to split methods and functions into the smallest possible components. Only then can you have good code reuse. Don't start thinking I will split it when I need it, you never will!
3. Never ever reinvent the wheel. Reinventing things that exist is overengineering.
4. Don't optimize ahead of time. When I say that I don't mean don't use a hash table instead of an array where it makes sense. I mean don't try to avoid exception handling or function calls or other minor optimizations. If it has an impact on readability don't do it. Optimization always comes last. Often you'll find there are only 1 or 2 "hotspots" in your code. If you spend time optimizing these "hotspots" after your application is built thats when you'll get the best return on your investment. Another gotcha with optimization is using technologies that can't deliver the level of performance you expect. You should test to make sure the underlying components you plan to use will perform as expected before you start coding.
5. Don't cram as much code in a single statement as possible. Every compiler I know about today will produce identical code whether it's one statement or 5 statements. It makes it hard to read so don't do it!
6. Allocate time for testing. No one writes perfect code.You want to give a good impression to your customer so don't skip this step.
7. Make unit testing an obsession. Always add unit tests for new code, it reveals errors in your code. When you find a bug in your code add a unit test to test for it. If in the future someone decides to rewrite some function or method you wrote because it's not elegant enough they will not reintroduce old bugs.
8. Don't rewrite code if possible. Refectoring is almost always easier and less error prone.
I think there are several factors that contribute to this:
1. Programming is a very popular and easy to enter field.
2. It's actually pretty easy to get by as a programmer without really understanding what you are doing.
3. Regardless of how much you hear about it, modularity, reusability, and highly structured programming do not have good penetration in Software Engineering.
4. Because of #3, it is all to easy for otherwise competent programmers to paint themselves into a corner and generate software with really messy architecture and/or implementation.
5. Programmers OFTEN have to clean up after other programmers.
So, due to #1 and #2, there actually are quite a number of really bad programmers running around.
Due to #3 and #4, there are quite a number of otherwise decent programmers who produce working but unmaintainable code.
Due to #5, most programmers have ample opportunity to experience a great deal of pain from other programmer's incompetence.
Due to human nature, programmers tend to assume that all that bad code comes from #1 and #2 rather than #3 and #4.
And more speculatively and unrelated to the above:
6. Lots of programmers tend to hang out on Usenet, internet fora, mailing lists, and IRC, where harsh criticism is de rigeur, and internalize the habit of harsh criticism in their professional lives.