Here are some simple and basic rules I've found for building applications that are maintainable and perform well, both in speed and stability. These rules, at one level or another, can apply to smaller modules and libraries, scripts, as well as fully featured large scale applications (both web and otherwise). In this post I will focus more on web applications, since that's where I've spent most of my time. At a higher level, they should apply to almost all areas of software development.
Note: I've attempted to keep this as unbiased as possible. However, where I found it impossible (I'm opinionated), I've created a "Soap Box" section for my personal opinions. Feel free to consider and accept or reject them as it applies to you.
"Bits is bits" and most languages, frameworks and platforms have their place, be it Ruby, Node.js, Python, PHP, etc., Rails, Sinatra, Express, Django, Zend, etc., etc. Just about anything can be made to scale; some of the largest sites in the world are built using the technologies referred to above. Often people make their choices based on what's new and buzzing. which also has it's place. It's important to choose something that you and/or your development team feel comfortable working in. Additionally, something you and/or your ops team feel comfortable deploying and supporting.
Personally, I prefer to choose a younger technology and framework that has a strong passionate open source community. Not for the technology itself, but rather for the people who choose to work in it. They tend to be the kind of people who develop because they love it, not simply because it's a job. Personally, I avoid technologies that do not promote open source — .NET and Java to name two.
Ruby is a really pretty language, it's easy to read, write and debug. Additionally, it's very test driven and has a great community behind it.
Regardless of your technology, methodology and process. Automated testing is essential to a stable production environment. And not just unit tests; functional and integration testing are your friends.
Automate everything you can. For development, there's
rake, etc. Pre- and post-commit hooks can save lives (okay outages, but still). Deployment, obviously. It doesn't have to be fancy — Chef and Vlad and things of the sort are great, but may be overkill depending on your scale — a simple
bash script or
rake_remote-task often will suffice.
Start simple, always! Use
maketo start, if you must expand due to more complicated requirements, then expand quickly to a mature higher level language — either Ruby or Python. While I prefer Ruby, Python is available by default on almost all modern Linux and BSD distro's (including Mac OSX) and therefore may be preferable. Both have excellent interfaces to the shell, while providing strong OO capabilities for building more mature and portable utilities.
Benchmarking is an often overlooked practice, but an incredibly valuable one. There are a number of methods to do this, e.g.
Benchmark class in Ruby, or simply running your app through something like
httperf (server side) or YSlow (client side) at regular intervals. Building a baseline and setting targets can make a big difference in your final product.
Too many times I've seen people fail by trying to design the car all at once. Build the tire, roll it down the hill, does it roll? Good. Now build another and attach them with an axle, do they roll? Good. This analogy translates to development well. Get something working. Test it, benchmark it, vet it, etc. I can't tell you how many times I've worked on a project for weeks or months only to see it fail due lack of iteration. I also can't tell you how many times as I've tossed something out, and felt good about it, after the first iteration because it wasn't workable or well designed.