Developers face a dilemma every time we sit down to code: What’s the best way to build high-quality software on time and on budget?
Developers face a dilemma every time we sit down to code:
What’s the best way to build high-quality software on time and on budget?
When writing code, there's a delicate balancing act between:
Balancing each area is tricky (at best) under normal business circumstances — especially since feature requests, budgets, and deadlines are mostly outside the developer’s control.
It's a constant challenge that requires careful decision-making, but I’ve developed a framework that helps me find the right balance for each project.
Who this blog is for:
To find the right balance between speed, quality, and performance, I like to assess three things:
Here’s what that looks like in practice.
In one corner, there’s the drive to get a solution in place… fast.
It’s tempting to respond with quick, occasionally sloppy code. Sometimes, development teams skip testing in favor of meeting a deadline.
This rarely works out in the long run, though.
Cutting corners often leads to higher maintenance costs, more bugs, increased technical debt, and decreased code quality. Here’s a common scenario we can all probably relate to: Hasty code that the next developer needs to spend time untangling and deciphering before they can even start to fix a bug.
That being said, it’s good to acknowledge that there will be times when strict deadlines require trade-offs. But, instead of writing low-quality code or skipping testing, I like to do things like build repeatable frameworks, de-prioritize non-functional requirements, and reuse existing code when possible.
In practice, that can look like:
Writing code that’s clear, understandable, and self-documenting does usually take more time.
However, if code is clear enough that a junior developer can pick it up later, it’s virtually guaranteed to save both time and money in the long run.
I’m a big believer in believing in your code. Developers should pride themselves on their code.
Sometimes that pride comes at the expense of cryptic functions and class names that no one else can follow. When it comes to balancing development time with elegant code, the more clear and self-documenting you can make your code, the higher opinion others will have of it, and the quicker you’ll be able to make changes to it later.
To complicate things further, there’s the fact that modern software uses a dizzying array of languages and technologies.
Every development language has a unique flavor of syntax and its own (often forceful) opinions on style. I’ve found that it’s better to go ahead and adapt my coding style to match the language of each file, rather than carry over the style from one language to the other. There’s nothing more annoying than opening some C# file and seeing a bunch of code that looks like it was written in Javascript, or vice versa.
When it comes to production development, I like to keep in mind that somebody has to pay for every line of code. To navigate this landscape and maintain syntactic elegance, I like to:
On that last one, just be mindful of only cleaning the room you’re in, not the room next door, so to speak. In other words, only clean up obvious junk, such as commented code and dead code, method and variable names, or other small changes.
However, never make radical changes to the foundation of the code. Remember, somebody has to pay for those changes. If you go overtime chasing “code squirrels” you may be one paying for it yourself when you run out of hours you can bill the client.
It’s been said before that the fastest code is no code at all.
If you don’t need to make another call to the database, for example, don’t!
Obviously, there are times when you have no choice. Performance in software development is a notoriously tricky situation and there’s a lot to consider.
Just take the example of presenting a report. You may need to pull data from a database server in a different timezone, make various calculations on that data using the processor of the hosting server, and then send it to the device in the hand of the end-user for on-screen rendering in a human-readable format.
That whole process of getting data from server to screen can have any number of bottlenecks. To avoid them, I try to:
Let’s use the report presentation example above. Think about what you need to do and what resources you have at your disposal.
First, you need to retrieve data from the database. Servers that host databases often come with more RAM, CPU, and disk space than an entire office full of laptops. Use it! In other words, let the data server do some of the heavy lifting. For reports, that usually means making a background job that collects the data, runs some or most of the calculations, and then saves the “digested” data into a flat reporting table.
With this approach, the report simply needs to ask for a range of data without doing any further calculations on it. This works especially well for reports that are only run once or twice a day.
I’ve always been a fan of regular, even required, code review.
No one on the dev team will remember every tiny optimization, nor will they have an encyclopedic understanding of how every part of the system functions. It's amazing how often small errors and typos get overlooked, especially after spending all day working through a complex feature.
Code reviews provide a fresh perspective so you can catch those errors before they go to production. No one likes to have a spelling mistake pointed out to them by the end-user. Catch it in code review!
Now let’s look at code optimization decisions.
Optimization is critical, but changes can have far-reaching implications. Even a simple change can lead to unexpected outcomes. Without regular testing, it’s easy to introduce a new bug through seemingly innocuous changes.
Sure, a piece of code might run faster after a simple optimization, but software rarely operates in a bubble. There’s always something that connects to another step elsewhere. That’s why having automated unit tests in place is absolutely essential!
It’s always better to catch a bug at development time, instead of chasing down the symptoms reported by the end-user.
To recap, building great software takes balance.
I've found it best to prioritize only the essential features, write clear and understandable code, use the resources you have available, and incorporate code reviews and automated testing to ensure a successful outcome.
Whether you’re trying to use in-house resources to solve a business problem, or you’re a developer building your own side gig or coding business, keeping these three areas in mind will help you balance time, money, and other scarce resources.
And if you want some extra help with that website, app, or internal tool, get in touch with Codepoet. We’re a team of experienced software developers who specialize in a variety of languages and technologies. Take a look at some of our past projects to see what we do, then get in touch to discuss your next project.