There's nothing that impacts your bottom line as severely as poorly written code. With $3 trillion GDP loss stemming from workflow inefficiencies, and millions of dollars drained away in patching software vulnerabilities, engineering teams are only just beginning to realize the impact of low quality code.
Poorly executed code can drain the productivity of the engineering team, and even the usability of software. Moreover, low code quality also reflects ineffective team communication, poor team collaboration, and is the starting point of incurring humongous technical debt.
I am not surprised promoting code quality is the first step software engineering teams can take towards improving developer productivity, and the overall bottom line of an enterprise.
In this article, let's talk about the importance of code quality, impacts on engineering productivity, and then zero in on actionable ways to improve it.
The Anatomy of Bad Code
On the development front, code quality translates to creating a reusable, and maintainable codebase. A reusable code might be used just once, but is read a thousand times– to fix bugs, discover patterns, add next functionality, or remember how the product works.
Now think about losing all these benefits just because you underestimated code quality, or put it in the backseat of your engineering efforts. Code quality is subjective, and sometimes harder to define, but here are some common patterns across engineering teams that show how a low quality code looks like:
- Presence of code smells that usually stem from lack of readability. A readable code is performant, and saves time so no developer has to build a codebase from scratch (always).
- Long methods that make your code stretch from 200 LoCs to a mile– Hard to read, and harder to maintain.
- Non-idiomatic code written without syntax, indentation, and full of backtracking.
- Absence of meaningful, specific, and contextual variable names to make things easier for a developer reading, and reviewing your code. Using “fn” over “employeeName’’ provides no insight, or context into the purpose. Moreover, shifting between different naming conventions within the same codebase is another metric to measure your code quality. Using camelcase in your 1st line, and underscore case in the middle is a sin.
- Low quality code and high cyclomatic complexity are directly related. Cyclomatic complexity communicates higher decision points, loops, and branches, making it harder to maintain the code, or to understand, and debug it.
- Breaking existing functionality everytime a new change is added.
- Unintelligible flow, tight coupling, and low cohesion
- Overuse of design patterns makes the code look more bloated, and harder to maintain.
Decoding the Culprits: Top Causes of Low Quality Code
Dealing with low code quality repeatedly? Here are your culprits:
1. Coding Without Planning, and Standards
One of the primary culprits behind low-quality code is a rush to start coding without caring for planning and design. Skipping or giving short shrift to requirement analysis and system design can set the stage for code riddled with issues. This happens when teams either over architecture, or follow bad-design principles.
Without a clear architecture, teams resort to shortcuts, creating a tightly-coupled, tangled, and spaghetti-like code that's tough to understand and maintain. Besides, moving without planning often creates code that doesn't scale well. As the project grows, so does the complexity of maintaining and extending it.
Another issue plaguing your code is a blatant disobey of coding standards. Most devs are overworked- they keep lights on, have to manage incidents irrespective of workhours, and code under tumultuous pressure of uneven demands, and tight-packed deadlines. In such a case, ignoring coding standards to deliver on time becomes a way of life for most devs.
Ignoring coding standards is like driving in the Wild West of code. When every developer follows their own style, the codebase becomes confusing, inconsistent, causes readability issues, and maintenance nightmares.
2. Lack of Tech- Business Alignment
Nothing holds your engineering team back than lack of alignment. Competing vision, frequent scope creep, and rushed development can often put devs on the edge; even coercing them to change the way they build, and code.
As the business side revises its requirements or priorities, development teams have the pressure to continually adapt. The other times, we overstretch ourselves after looking out for future requirements even when customers are not asking for it. And when things don’t pan out, teams often end up building products that were neither needed nor desired in the first place.
All of these factors put devs on spots, and impact the code they write– often adding inconsistencies, complexity, and lack of shared ownership of the codebase.
3. Unrealistic Deadlines, and Overpressured Devs
Deadlines are not antithetic to software development; rather they are crucial to manage production costs, and help engineering teams achieve their goals. However, these deadlines start killing productivity of your team when they come with clogged calendars, back to back meetings, and less active coding time for devs– which is just 1 hour a day as of now.
Managing engineering deadlines is a make or break point for most dev teams. And 40% of devs agree with it. They ignore quality checks, resort to quick fixes and hacks to just deliver on time, and achieve their timelines. This rushed development then spirals into low quality, and poorly executed code.
4. The "Works-for-Me" Mindset
Imagine you're working on a group project, and someone casually quips, "It's working like a charm for me; the issue must be something of yours." Pretty frustrating, right? Well, this mindset is the perfect recipe for disaster for engineering teams.
Devs, under pressure of deliverables, and an overworked schedule sometimes overlook the fact that different environments exist. Their code might run seamlessly on their own setup but stumble elsewhere.
This nonchalant approach often leads to compatibility issues and persistent bugs that just won't go away, often creating a loose feedback cycle, and low quality code.
5. Accumulating Enough Technical Debt For a Lifetime
Technical debt isn’t interest free. It charges humongous interest in the form of complex code– It's not just complex; it's "how-did-this-even-work-in-the-first-place" complex.
Moreover, the “fix it later” approach often comes at the expense of documentation, frequent bugs, and even high software development costs to rise in the long run. The longer it lingers, the more resources, and code integrity it siphons away, leading to timeline nightmares, and exhausted developers, and a compromised codebase.
It also distorts the active coding time for devs. As of now, they are focusing 42% of their time in resolving technical debt– a blatant wastage of resources, and even loss of ability to code on parts of developers.
Unpacking the Price of Low Quality Code– The Toll on Engineering Teams and Bottom Line
Subpar software has cost organizations more than $2.8 trillion in the States alone. Here are a few more shocking impacts of low quality code on developer productivity, and financial health of enterprise:
1. Engineering Woes, and A Never Ending Developer Toil
It’s no rocket science to decode how a dev’s mental state can hinder their ability to code, and vice versa. Sufficient rest, no burnout, low stress levels, and happiness– all of these impact how a dev delivers code, and build software.
A poorly written code adds to the miseries of already overworked developers. The daily grind creates a vicious cycle of debugging- maintenance nightmares- technical debt for developers, even propagating the ‘always on’ culture, and longer workhours.
We know a lot of devs who code even when they are tired, long past the office hours, and then discovering later that the work was discarded, because either it was not enough, or had to be undone. The “net-negative work” actually creates, and stems from low quality code all at once– even expanding the amount of work to be done, and sometimes starting from scratch.
Demotivated developers are less likely to invest their best efforts in a project. Nothing can compensate for this developer toil– neither sabbaticals, nor a well-brewed beer, nor micro-napping.
2. Less Active Code Time
A dev's overall productivity takes a hit when they are dealing with low quality code. They now have to put deciphering code and fixing issues than on actual development work.
Didn’t we just mention how devs have only an hour a day to code, while they have to spend 42% of their time fighting bugs, and resolving technical debt. Besides, lack of validated and reviewed code creates strong regressions while devs rework the codebase. The need to address regressions consumes active coding time that could have been spent on building features.
What could have been a straightforward task becomes a marathon of tracing, testing, and fixing. Moreover, code that lacks readability and structure is a ticking time bomb. It demands frequent maintenance as requirements change or as new features are added. All of this interrupts devs flow state, where they are unable to concentrate, and deliver beautiful, and strong code.
3. Frequent Speed Bumps Derailing Engineering Velocity
For long term projects, extending beyond 2 weeks, code quality is a major deciding factor for optimal development speed.
With a badly executed code as your sidekick, it becomes hard to answer questions like– how frequently your team ships? Or, what is the failure rate?
It’s not that devs don’t work hard enough. The stigma is far from real. Rather they are too overwhelmed with bugs, to work on the roadmap.
Poorly documented or convoluted code creates knowledge silos, where only a few team members understand how it works, while most ICs settle with tribal knowledge. This reliance on a select few experts slows down engineering velocity, and blocks developers in doing their core work.
Besides, ill-designed and tightly coupled code modules are less reusable. In such cases, teams have to reinvent the wheel instead of building upon existing, reusable components, making engineering superhard to scale.
4. The Crisis of High Software Development
Let’s talk numbers here– the language every business irrevocably understands:
- High code complexity shoots software maintenance budgets by 25%, and adds a hefty 14% to the overall development budget.
- According to Stripe, the toll from 'bad code' has already reached staggering losses of up to $85 billion annually.
- Low quality code increases the overall delivery timeframe by atleast 50%.
- Vulnerabilities sneak in when code quality is compromised. Based on Contrast Security's research running checks on 8 billion lines of code, a typical modern application has 79% library code and just 21% custom code. Predictably, 76% of these applications harbor at least one vulnerability, while 34% have ‘very high’ chances of breach.
PS: Interested in knowing more about high development costs and its intricacies? Check out our latest post on Linkedin.
These numbers are independent of shipping costs of bad code, or being defeated to market by your rivals– they too are worth considering; howsoever hidden they are. No matter how competent your product vision seems, it WILL struggle when prone to bugs, and hacks.
Do we need anymore proofs into how low quality code can severely impact your bottom line, and even kill your business.
Conquering Low Quality Code: Strategies That Work in Both Letter and Spirits
Consistently delivering good code requires investment, and commitment of resources- a developer’s coding abilities, money, easing deadlines, and development time.
But, the good news is– Building a software that stands the test of time doesn’t require teams to cease their other engineering activities. Rather, the refactoring is about taking subtle, but consistent steps. Here we are discussing the strategies that are evergreen, yet underrated in building high-quality code:
- Streamline your developer’s workload using engineering analytics. Visualize your IC’s workday in terms of efforts distributed: bugs vs roadmap vs technical debt. The best way forward is to work with them in optimizing their schedule so they can have active coding time, and deliver real value.
- Generally, engineering managers can redistribute work based on the 80:20 rule– with 80% time reserved for building features, or fixing bugs, while 20% is kept for refactoring, so teams can also tackle technical debt head-on.
- The second point of action is pair programming and effective code reviews. Going solo might be a regular devs way to get work done, but studies have shown how working together on a single codebase can improve its vitality, and overall productivity of everyone involved. Code reviews are the last leg to finally ship your code to production, also it's the last opportunity to catch any quality errors that can later damage your product.
Engineering teams can find the real-value out of their tight review cycles by using Hatica’s collaboration dashboard.