I work at a very small software company that has as clients other small businesses. We do custom software. In 2010 that means we do web development. We bid on projects, complete the projects we get, fix any bugs for free for 6 months, and charge a very competitive hourly rate for new features. We don’t have failed projects, per se. Sometimes a customer might pay us to create something that doesn’t end up helping their business, but the software we create is of reasonably high quality and does what it claims to do. It’s tough times economically, so when a customer wants us to create a new feature on their web page, we generally try to get it done in hours, not days. Some days I close several tickets. I feel like I am delivering quite a bit of value to our customers. Now we support our products with a 6 month guarantee of free bug fixes, which means if I spend 2 hours on a small feature, I need to be reasonably certain that it works correctly, because if it comes back with a major issue two weeks later, we don’t charge the customer for the time it takes to fix. The more time I spend on a feature, the less perceived value the client is getting because it is costing them more. However, if I do the feature in less time, and it turns out to have a bug, any cost savings the customer might have seen go away the moment that the feature fails in production and they suffer real business losses. There are books upon books written on this topic, but I’m just going to share a few things that I’ve learned in my short career thus far in software development.
Software development doesn’t need to be slow to be high quality. I have been a slow convert to the unit testing religion, but now I am just about there. These days when a client wants a new feature, I find the test classes that correlate to the class I’m messing with, write some tests for the new functionality which fail. I type in some code, run the tests and repeat until they are all passing. I run all the unit tests for the project (which currently runs very quickly as we haven’t been doing this for a long time) to make sure I didn’t inadvertently break anything else and ship it. It’s fast and I see very few bugs slip through this way.
Develop a small set of simple, high quality tools. Most of our work is in PHP. After you are done groaning about how awful PHP is, read on. A lot of our work consists of rescue operations. Small business owners and budding entrepreneurs, bless their little hearts, don’t usually have a lot of cash to throw around, so they take the lowest bid for their website work. The lowest bid is usually a company from India or Romania or some other exotic locale where US dollars are still worth quite a bit. These thrifty folks end up with a half-working, extremely buggy piece of software which is basically a single folder with a whole bunch of files in it ending with “.php”. The internals of these files would make any software developer worth his or her salt cringe. You and I know that the best thing to do would be to throw the whole thing out, and start from scratch, preferably with a language like Python or Ruby. Well, the client doesn’t know that, they come to us to fix the code. Well, we have a tool, it is a very lightweight PHP framework that can integrate nicely with existing code. I have used it so much that I am at a point where it feels natural to use it to solve problems. Our clients do pay us to fix their code which we do gladly, and efficiently, usually replacing the broken parts completely with clean, MVC style code.
Imperative, object-oriented code is efficient for writing web software. I’ve read a bunch about heavy OO patterns and this and that, and I think most of it is crap. Nobody needs all that. What customers need is to create related hunks of data, which I call “rows” from a database perspective, or “objects” from a programming perspective. I have created my very own simple, Active Record style ORM for PHP and MySQL. Basically, you give me an existing database table. In about 2 minutes I can slap together about 20 lines of boilerplate code (mostly informing the ORM what the name and data type is of each column) which gives me the ability to easily do CRUD operations (create, read, update, delete) on your database table. The ORM generates all the SQL in the background, so the only code I have to write is PHP. The columns of your database become public members of the class instances (objects). Now, according to the rules of OO, this is a big mistake. Well, really, it’s not. You’ve got collections of data to move around and use, why hide everything behind a bunch of pointless accessors? All that extra data-hiding cruft just slows things down. What the customer wants is a bunch of data that gets dumped into the correct parts of the HTML. The customer doesn’t care about “proper OO” and neither should you. They are not paying you hourly to implement latest design pattern you read about.
Use a dynamic, “scripting” language like PHP, Python, or Ruby (or Perl if you are a masochist). I now point Apache directly at my project folder so when I’m done typing, I hit a few keys which save my work, switch to a console to run a test or switch to a browser and reload the page. I see the results of what I typed within about one second of when I finished typing. There is no deploy step, no compile step, no waiting, no distraction, just instant feedback. It’s amazing, and it has revolutionized my workflow. Remember, our clients are paying hourly rates, which when you break it down into minutes is generally some amount of money greater than $1 per minute. A five minute compile/deploy step costs the client several dollars each time. I remember writing code in Visual Studio, I believe the F5 button was the compile/run shortcut. Hitting that on a reasonably complex piece of software was like an invitation to go get a snack, start up a conversation with a coworker or get distracted with interesting articles on the internet. The big secret is of course that every programming language gets compiled, it’s just that C++ compiles really slowly, has an extra pre-processor step and has to be linked with a bunch of other code in a time consuming way. Things like Python get compiled as they are read into the interpreter into byte code which is then executed by the interpreter immediately. That just happens to be really fast, plus the byte code is cached to disk oftentimes. In the .01% of the time when the simplest possible code in your scripting language of choice isn’t fast enough for your client’s need, first check to see if you can fix it with a better algorithm, if not, rewrite the critical, innermost loop in C.
In conclusion, I may use a lame tool (PHP) and butcher “best OO practices” and make babies cry by completely ignoring “functional” programming, but I get things done. Not only that, but I get things done well, with a low defect rate, and quickly. The code I write is easily maintainable and ships with good test coverage. The “good, fast, cheap: pick two” thing is a lie. With a familiar, well-honed collection of tools any software developer can do all three.
Comments 2
I’ll definitely be sharing this post with some friends of mine, you have some really valuable insights.
Posted 18 Feb 2010 at 12:15 pm ¶I agree that good, fast, and cheap can be achieved, but I think you then rely on motivation, which can be pretty elusive.
Posted 18 Feb 2010 at 12:35 pm ¶Post a Comment