What Does Bad Coding Look Like & Why It Will ALWAYS Cost You More In The Long Run

Ritesh Shah
16 min read

What happens when the code that a developer writes gets messy and is well… just, bad code?

Ok, so let’s put this question into perspective!

Suppose yours is a start-up company that builds mobile (iOS and Android) apps. To meet the market demand, your company is launching an excellent app that many people will want to use and be willing to pay for.

The management team pitches an idea to your project manager, and they relay the message to the teams of business analysts, developers, and software testers. Everyone then knuckles down and starts working on the project.

Now, the deadline is looming, and now your company is rushing the product to the market with a substantial code-level mess. With every new release, the dev team adds more and more features, and the code continues to get more and more disjointed. As a result, the version release cycles stretch out, bugs are left unresolved, the app’s load time increases, and constant crashing of the app ends up resulting in a bunch of negative reviews from users online.

Continuing down this path will bring a time when you and your team simply can no longer effectively manage, develop and market the product anymore.

The “messy code” debacle that started off quite small has now grown into a fire breathing monster that savagely kills your dreams of changing the world!

Although purely hypothetical, the example shows how bad coding can dramatically impede a product’s success. So what’s the solution? The answer is mostly surprisingly hard to find but is actually stupidly simple: “Clean code”.

Let’s define what a clean code is and understand its standard principles.

What is Clean Code? 🤔❓

The idea of clean code gained popularity with the publication of Robert Cecil Martin’s ”Clean Code: A Handbook of Agile Software Craftsmanship” in 2008. However, the principles of clean code date back to the beginning of software development, and Martin’s book is an essential manual for people who aim for cleanly written code. It’s a programming classic, and if you’re serious about coding, you should read this book cover to cover!

So what’s clean code?

Contrary to popular belief, clean code is not a set of rules but principles that help developers write understandable and modifiable code. By “understandable,” we mean code that any developer can easily understand. It’s structured, logical, and quite obvious.

Let’s take a look at two expert definitions of clean code.

Bjarne Stroustrup, the inventor of C++, says: 

“I like my code to be elegant and efficient. The logic should be straightforward to make it hard for bugs to hide, the dependencies minimal to ease maintenance, error handling complete according to an articulated strategy, and performance close to optimal so as not to tempt people to make the code messy with unprincipled optimisations. Clean code does one thing well.”

Notice how Bjarne uses words such as “elegant” and “efficient” with equal weight. The code you write should be not only efficient but also elegant, meaning aesthetics demands equal attention. In addition, the code should be such that it doesn’t “tempt people” to make it “messy.”

Here’s another definition from Grady Booch, best known for developing the UML (Unified Modeling Language)

“Clean code is simple and direct. Clean code reads like well-written prose. Clean code never obscures the designer’s intent but rather is full of crisp abstractions and straightforward lines of control.”

Grady’s definition of clean code supports Bjarne’s assertions on readability. Reading good code is like reading “well-written prose.” Think of your favourite novel. How did you feel when reading it? Although the experience of reading codes might not match with your experience of reading a bestseller, you’re likely to get similar joys.

Why Write Clean Code? 🤷‍♂️✍️

Remember the messy code hypothesis we presented at the beginning of the article? That should’ve been self-explanatory, but let’s dig deeper!

As a developer, you often have to wade through bad coding, trying to make sense of the tangled morass of senseless lines scattered everywhere. The only way to move faster is by keeping your code clean. However, writing clean code requires good discipline and the proper use of techniques on “cleanliness.”

But, for a moment, let’s assume you stick to the lazier way of messy code, deciding that a working mess is better than nothing. What happens then?

Every change you make breaks the existing code into two or three parts. The code then gets more disjointed and confusing. Over time, the mess becomes so big that it seems like you can’t fix it at all. Apparently, there’s no way out, or is there?

As the mess builds and productivity decreases, your company hires more staff to “fix the problem.” Since the new people you hired are not well-versed in the system design and architecture, their fixes are mostly counterproductive. Without intending to do so, they make the code even messier!

Eventually, your company might decide to review the internal development teams’ structure. They may cherry-pick the best coders and create a new team, one that’s intended to work on cleaning the existing code up, and later, create an entirely new system. Then, another team is added to support the existing system. It’s a vicious cycle, you see — one that might go on for years. Until one day, everything breaks apart . . .

Although a tad bit dramatic, this very scenario has unfortunately proven true for many organisations, costing these companies both a huge chunk of money and time by the way.

That’s why it’s so vitally important to learn the art of writing clean code and then insist on its practice!

Coding that is understandable and modifiable saves everyone’s time, makes the onboarding process easier for new recruits, and is far less confusing when debugging. Overall, code created in a disciplined, structured and orderly manner is insanely more efficient to maintain.

7 “Clean Code” Principles 🕮👌

Now that you know the undeniable importance of writing clean code, you as a programmer need to develop a “code-sense.” According to Robert C. Martin, famous Uncle Bob of programming: “A programmer with “code-sense” will look at a messy module and see options and variations. The “code-sense” will help that programmer choose the best variation and guide them to plot a sequence of behaviour preserving transformations to get from here to there.”

That means you’ll have to develop “code-sense” to write elegantly coded software. So here we’ll present 10 Clean Code Principles (as promulgated by Uncle Bob) that you can adopt right away and see instant improvements in your coding practice.

#1 – Follow the KISS, DRY, and YAGNI Rules

KISS is the acronym for Keep It Simple, Stupid. Initially originating from the US Navy in the 1960s, this acronym has been widely used across various domains. In the world of programming, it simply means the systems should be kept as simple as possible. Unnecessary complexities make the code messier, and whenever you’re tackling a complex problem, the point is to ask yourself: “Can this be written more simply?”

Then comes DRY, meaning Don’t Repeat Yourself, which helps you code by following the minimalist philosophy. Every code block must have a single and unambiguous purpose within the system.

Fun fact – Did you know that the opposite of DRY is WET (We Enjoy Typing)?

Duplication is a serious problem because it puffs up the code, and if the algorithm changes, you’ll have to fix each instance of repetition separately. That’s why, over the years, software developers have been seeking ways of eliminating duplications. One sure way is by having only one entry and one exit in every functional block. That means each function should only have one return statement — and no break, continue, or goto statements.

Finally, YAGNI (You aren’t gonna need it) dictates that you as a developer should only introduce additional functionality when it’s indispensable. Following agile software development’s principle, YAGNI states that you should code in small steps, solving the underlying problems efficiently.

#2 – Naming Conventions: Use Intention-Revealing Names

It’s evident that names should reveal intention. Choosing intention-revealing names might take some time, but it saves a lot of confusion and hassle. When you select purposeful names of variables, functions, and arrays, your code will read better. It also helps future programmers to navigate through the entire code easily.

For example, int p; // payment amount in dollars solves the problem for the time being, but it’s likely to create confusion in the future. Besides, if you need a comment to explain a variable, you should take time to rename that variable instead.

Since the name ‘p’ reveals nothing, you can rather choose a self-explanatory name such as:

int paymentAmountInDollars;

int paymentAmount$;

int onlinePaymentAmount;

Do not use letters like a, b, c, x, y, z to name your variables (except when using them as loop variables). Having an obvious (pronounceable and searchable) name makes the code easier to understand and modify later.

For example, instead of writing const yyyymmdstr = moment().format(“YYYY/MM/DD”); write const currentDate = moment().format(“YYYY/MM/DD”); as currentDate is both pronounceable and easily searchable.

#3 – Functions with The Same Level of Abstraction

Closely related to the KISS, DRY, and YAGNI principles, this rule states that functions should be small, and they should do only one thing at a time.

To ensure the function is doing a single thing, you need to ensure that all the statements within that function are at the same level of abstraction: the amount of complexity by which a system is programmed. So mixing levels of abstraction within a single function makes the code confusing!

Remember that a clean code should read like a well-written, top-down narrative. As you read down the lines of codes (the list of functions), every function should be followed by those at the next level of abstraction.

Here’s an example of how you can avoid large functions and rewrite code so that a function only does one thing at a time.

// bad practice

const addSub = (a,b) => {// add         const addition = a+b// subtract     const sub = a-b    // returning as a string    return ‘${addition}${sub}’}

// good practice

const add = (a,b) => {    return a+b}
const sub = (a,b) => {    return a-b}

Here are some dos and don’ts when writing functions:

  • Try to avoid switch statements as they do several things. If there’s no way you can avoid them, make sure each switch statement is buried in a low-level class and never repeated.
  • Use descriptive names when defining functions. It’ll clearly describe what the function does to everyone who reads the code. Don’t be afraid to make the name long and self-explanatory, as that’s always better than a short and cryptic one.
  • The ideal number of arguments in a function is zero. But, unfortunately, it’s not possible to have that figure all the time, so up to two arguments (dyadic) is still considered all right.
  • Functions should a) do something or b) answer something. They shouldn’t, however, perform both operations because that inevitably leads to confusion.

#4 – Readability Over Conciseness

Until now, we’ve focused on the conciseness of the code (KISS, DRY, and YAGNI). However, if there’s one thing that’s more important than conciseness, it’s readability. Machines and people both should be able to read the code you write. This is especially true if multiple developers are working on the same project.

If other developers are left scratching their heads, there’s no point in writing concise codes. One significant difference between a rookie programmer and a professional one is that the latter understands clarity is king and chooses clarity over entertainment value when coding. Remember that cuteness in code is dangerous in the long run!

Here’s an example:

// Bad practice

const seeUser = (phone) => {
// Do something

// Good practice

const searchUserByPhoneNo = (phone) => {
// Do something

Always keep Uncle Bob’s three rules to readability in mind: clarity, simplicity, and density of expression. So instead of having HolyHandGrenade as a function, try something that’s less comical and more straightforward, such as DeleteItems.

Don’t use whack() when you mean kill() or leaveEarth() for abort(). Say what you mean and mean what you say.

#5 – Don’t Include (too many) Comments

Most of the time, comments are a necessary evil. If you write clean and readable codes, there’s no need to comment for clarification. However, if your code is messy, you might be tempted to clean it up by inserting as many comments as possible.

For instance, if you comment “// This checks if the user with the given ID exists.” before writing a block of code, you should be aware that you’re adding a useless comment. Comments should, in fact, explain “why” you did something instead of “what” is happening in the code.

Noisy comments like this do not add anything valuable to the code. Here’s a comment that restates the obvious.

// The day of the month.

private int dayOfMonth;

Comments like such are so noisy that developers tend to skip over them. As the code changes with subsequent feature upgrades, those comments remain untouched, creating more confusion for new developers or code testers. Also, a comment is not the place to vent your frustrations, so instead, work to improve the structure of your code.

In any case, no matter how clean code you try to write, it’s likely that you’re going to insert comments once in a while to tell other developers (and your future self) the logic behind your code.

#6 – Consistency Throughout the Code

To maintain consistency throughout the code, you must know your programming language’s conventions, especially how things look on the code editor.

One simple example: When naming variables, you use camelCase in Java but snake_case in Python. However, when naming classes, you use PascalCase in C# but camelCase in Java. In addition, in C#, you put open braces in a new line, but you put them in the same line in Java.

Also, all programming languages require proper code indentation, as it makes the code easier to read and understand the flow apart from preventing errors to some extent. Besides, for object-oriented programming, SOLID principles aid in clean coding by making software designs understandable and maintainable.

Since convention changes from language to language, the following style guides might help you maintain consistency in your code.

If you’re going to code a specific style, stick to it throughout the entire project. If there’s a reason you deviate from the consistent style guide, explain them in the comments because you’ll be describing “why” you’re doing so.

#7 – Don’t Obscure Logic with Error Handling

Error handling is just one of those things you have to do no matter how well you try to code. When things go wrong, you as a programmer are responsible for ensuring the code does what it’s intended to do.

However, if error handling obscures the logic, it’s wrong. Your code should instead handle errors with grace and elegance. Here are a few tips you can consider when fixing errors.

  • Don’t return or pass null, as it moves the error checking responsibility to the function’s caller, causing errors to multiply. Instead, you should code with the knowledge that a null in an argument list means a problem.
  • Don’t assign magic numbers (numbers with no clear meanings) as other developers are bound to get confused. Instead of magic numbers, switch to variables with meaningful names.
  • While you can classify exceptions differently, like source or type, the most important distinction is how errors are caught. So make sure to define exceptions and provide context.
  • Write your try-catch-finally statement first when you are writing code that could throw exceptions. Then, try to write tests that force exceptions so that you can build transaction scope in your try-catch-finally blocks.

Elegant Code or Workable Code? 🦢🛠️

So what should I choose: elegant code or workable code? The answer should be obvious by now. No matter what the sceptics say, the aesthetics of codes does matter. At times, aesthetics precedes workability!

A merely workable code is undoubtedly going to become bad coding! It will become messier and messier with subsequent code-level changes and revisions. Remember that what’s convenient isn’t always what’s best for the development process!

Your team and your company will benefit in the long run if you follow the conventions to write elegant codes. When you write code with grace and style, anyone who’s working with you will understand everything on their own. You don’t even have to give lengthy explanations in the comments section. 

That means elegant code is for both individual coders and developmental teams.

Conclusion 🏁⌛

Clean coding is not a skill you can master overnight. Instead, it’s a set of principles that you need to incorporate into your coding life — and apply them whenever you write or fix code. Programming is both a craft and a science, and you can only learn to write better code with time and perseverance.

There’s a high need to keep up with standards to maintain a readable code, so you must practice clean code. By following the tools and techniques mentioned in this article (and carefully perusing Robert C. Martin’s book on “Clean Code”), you can imbibe in yourself the thought processes of a good coder.

If you’d like to understand more about the fundamentals and importance of clean code — or how we at WEBO Digital have incorporated its principles into practice — feel free to send us a message, and we’d be more than happy to talk to you!

Published On

October 10, 2021