Good Code vs Bad Code

SHARE

Any programmer can write an average piece of code, but it takes a little more effort and experience to produce good code. If we talk about a problem statement, there are various approaches you can take to solve it and not all of them are straightforward. A bad piece of code could solve the problem, but a junior coder would struggle to understand how it solved the problem. It’s hard to define good code, but learning what bad code looks like will give you a better understanding.

Read on: Technologies That Will Shape Enterprise Software Development in 2022

What is bad code?

Remember the time the deadline for a project was approaching and your project manager was constantly asking you when it’ll be done? You went on a coding spree, improvised wherever possible and somehow delivered the project on time with everything working just fine.

You knew your code was pretty bad, but it was your code and you thought you could always fix it at a later date. But you’re not the only coder. If this was a big project, you would have collaborated with several coders who wouldn’t understand that piece of code due to bad coding practice.

An example of bad code

Suppose that piece of code represents a microservice which constitutes a customer behavior module in a CRM offering. If they were to add a new feature to the module, such as a new contact field, they would have no idea how to do it as they’re unable to understand and therefore edit the code.

You can always add inline comments to add some clarity, but a good piece of code stands on its own. What would happen if you went on leave or left the company? Your code would be impossible to maintain.

What is good code?

With no clear distinction to what constitutes good code from bad, we may consider good code a combination of best practices and common philosophies. At the end of the day, you have to get these two right.

The importance of clean and manageable code

Clean and manageable code is of utmost importance in the field of programming. It goes beyond personal preference and plays a crucial role in the efficiency, maintainability, and long-term success of a software project. Here are some key reasons why clean and manageable code is essential.

Readability and understandability: Clean code is easy to read and understand. When code is clean, it follows consistent naming conventions, utilizes proper indentation and formatting, and is well-organized. This makes it easier for other developers to comprehend the code, collaborate effectively, and quickly identify and fix issues.

Maintainability: Software projects are not static; they evolve over time. Clean code significantly improves the maintainability of a project. It is easier to make changes or add new features to clean code because it is modular, well-structured, and follows best practices. Maintenance becomes less error-prone, faster, and more cost-effective, leading to improved productivity.

Debugging and troubleshooting: When bugs or issues arise in a software project, clean code simplifies the process of debugging and troubleshooting. Clear and descriptive variable and function names, along with proper commenting, help developers identify the purpose and intent of different sections of code. This leads to faster bug identification and resolution.

Collaboration and teamwork: In most software development projects, multiple developers work together. Clean code ensures seamless collaboration and teamwork. When code is clean and follows consistent standards, it becomes easier for team members to understand each other's contributions, integrate their work smoothly, and maintain a coherent and unified codebase.

Scalability and extensibility: Clean code is inherently scalable and extensible. When code follows modular principles and is properly structured, it is easier to add new features or modify existing ones without causing a cascade of unintended side effects. This allows software projects to adapt and grow over time while minimizing technical debt.

Efficiency and performance: Clean code is often more efficient and performs better. Eliminating code duplication, optimizing algorithms, and following best practices lead to improved performance. Clean code is also easier to profile, optimize, and refactor when necessary, ensuring that the software runs efficiently and meets performance requirements.

Documentation and self-explanatory nature: Clean code serves as its own documentation. When code is written in a clean and expressive manner, it becomes self-explanatory. Developers can understand the code by reading it, reducing the reliance on external documentation. This saves time and effort in maintaining separate documentation while ensuring that the code remains comprehensible to both present and future developers.

The three philosophies of good code

I came across this article that breaks down good code into a series of commandments. Commandments is a pretty strong word for an average developer to digest, which is why I’d call them philosophies that a developer must follow in order to become a good coder.

Good code stands on its own

As I said, writing good code isn’t some miraculous feat but is a result of consistent effort and practice. If you were to compare the code you’re writing today to the code you were writing a year ago, you would be able to tell you’ve come a long way as a coder. The code might be a lot more structured, readable and would allow another coder to take over. It is more likely to stand on its own. But does it? Can another coder working on the same project reuse it without giving a second thought?

Your code might contain dependencies and still be complete if those dependencies are obvious to get by. The real test comes when someone is working on your project. The philosophy is that you should treat your code as you want others to treat you with theirs.

Suppose you’re adding a feature to allow users to geo-tag users in their photos. You’re supposed to write the base code and another developer is supposed to do the API integration with Google Places. If your code doesn’t stand on its own and is incomprehensible to the API developer, you may have to explain that to them, which defeats the whole purpose of collaborative coding.

Good code is obvious

So, you came across this logical problem where you have to disallow user registration from a specific region on a client's website. It’s a simple problem statement. You have to geo-restrict a few locations, disable some form values, and display a message to inform the restricted users.

There are several ways to add geo-restrictions. You can let the users know as soon as they are on the website, select a restricted location in the registration form, or click the ‘registration’ button from a restricted location.

None of these approaches are wrong as long as they restrict the subset of users and the other developer maintaining your project can add or remove locations to the restricted list easily. Ideally, the change should be about changing a value under a ‘restrictedCountry’ array.

If the code isn’t obvious, the developer might have to dig around the code to figure out the logic and loops, conclude if they have to make any code edits to absorb the changes, make the changes accordingly, and then integrate the code.

Good code is planned

Good code is structured, follows a set of common architectural principles, and contains independent code blocks. You have to plan everything. You have to sit down with your solutions architect team, conduct R&D on the scope of the project, define the various project phases with deadlines, etc.

Code planning for a large project may take weeks or even a month. The longer you plan, the less likely you are to end up in a situation which may delay the project deadline.

Read on: 9 Productivity Tips For Visual Studio 2019

7 essential tips for mastering the art of clean and manageable coding

These seven essential tips will help developers and programmers master the art of clean and manageable coding. By implementing these tips, you can elevate your coding skills and adopt best practices that will make your codebase more robust and efficient.

1. Use consistent and descriptive naming conventions

One of the first steps towards writing clean code is using consistent and descriptive names for variables and functions. Meaningful names make your code self-documenting and easier to understand. Avoid cryptic abbreviations or acronyms and opt for descriptive names that convey the purpose or functionality of the element. Additionally, maintain consistency throughout your codebase to ensure readability and maintainability.

2. Break down complex tasks into smaller functions/methods

Modularizing your code by breaking down complex tasks into smaller functions or methods offers several benefits. It enhances code readability, promotes reusability, and simplifies debugging. By dividing your code into smaller, more manageable units, you make it easier to understand and maintain. Embrace the concept of separation of concerns and strive for functions that do one thing well.

3. Write comments for clarity

While clean code should be self-explanatory, adding comments can further enhance its readability and understanding. Comments act as a guide for other developers (including your future self) who might work with your code. Use comments sparingly, focusing on explaining the intent, reasoning, or important implementation details. Avoid redundant or overly verbose comments that add little value.

When using comments in code, it's important to follow best practices to ensure that your comments are helpful, informative, and maintainable. Here are ten best practices for using comments effectively:

  1. Be clear and concise: Write comments that are clear, concise, and to the point. Avoid unnecessary verbosity and focus on providing essential information.
  2. Use complete sentences: Write comments using complete sentences to enhance readability and understanding. Proper grammar and punctuation make the comments more professional.
  3. Explain the why, not the what: Instead of describing what the code does, focus on explaining the reasoning behind certain design decisions or complex algorithms. This provides valuable context to readers.
  4. Comment tricky or non-obvious code: Identify sections of code that may be difficult to understand or require additional clarification. Commenting on such code helps future readers comprehend the intent and purpose.
  5. Avoid obvious comments: Don't clutter your code with comments that simply restate what the code already expresses clearly. Reserve comments for areas that require further explanation or context.
  6. Update comments when code changes: Keep comments in sync with the code. Whenever you make changes to the code, ensure that any relevant comments are updated accordingly to avoid confusion.
  7. Be consistent in comment style: Adopt a consistent style for your comments throughout the codebase. Consistency improves readability and makes the codebase more cohesive.
  8. Don't overcomment: While comments are helpful, don't overdo it. Use comments sparingly and only when necessary. Too many comments can clutter the code and make it harder to read.
  9. Remove unused or outdated comments: Regularly review your codebase and remove any comments that are no longer relevant or have become outdated. Keeping the comments up to date improves the accuracy of documentation.
  10. Document assumptions and constraints: If your code relies on specific assumptions or has constraints that future developers need to be aware of, clearly document them in comments. This helps prevent misinterpretations and avoids potential issues down the line.

Remember, comments should supplement the code and provide valuable insights. They should not serve as a substitute for writing clean, self-explanatory code. Use comments judiciously, follow these best practices, and strive to create code that is clear, maintainable, and easily understandable on its own.

Read on: Code Documentation: Make Guidelines For Your Code.

4. Implement proper indentation and formatting

Consistent indentation and formatting are vital for clean and manageable code. Properly indented code enhances readability, making it easier to follow the flow and structure. Ensure that you follow a consistent indentation style throughout your codebase. Furthermore, utilize whitespace effectively to improve code organization and readability. Consider adopting a code formatter or style guide to enforce consistent formatting.

5. Eliminate code duplication

Code duplication is a common pitfall that can lead to maintenance nightmares. By adhering to the DRY (Don't Repeat Yourself) principle, you can avoid unnecessary repetition and make your codebase more maintainable. Look for opportunities to refactor duplicated code into reusable functions or modules. This not only reduces the chances of introducing bugs but also improves the overall efficiency of your code.

6. Regularly test and refactor code

Testing and refactoring are indispensable practices for maintaining clean and manageable code. Writing automated tests helps ensure the reliability and correctness of your codebase. It allows you to catch bugs early and provides a safety net when making changes. Additionally, refactoring improves code quality by restructuring and optimizing existing code without changing its external behavior. It helps eliminate technical debt and improves the maintainability and scalability of your code.

7. Embrace test-driven development (TDD) and refactoring practices

Test-driven development (TDD) is a software development approach that emphasizes writing tests before writing the actual code. By following TDD, you ensure that your code is thoroughly tested and that your development process is driven by the requirements of the tests. Here are the steps to apply test-driven development:

Step 1: Define a test case

Identify a specific functionality or requirement that you want to implement. Write a test case that describes the desired behavior or outcome. The test case should be specific, focused, and written in a way that can be automated.

Step 2: Write the test

Write the test code that checks if the desired functionality is correctly implemented. Start with a failing test to ensure that the test code is working correctly. This serves as a reference point to validate that the functionality is indeed missing or incorrect.

Step 3: Run the test

Execute the test and confirm that it fails, as expected. This confirms that the test is accurately identifying the missing or incorrect functionality.

Step 4: Write the minimum code to pass the test

Write the minimum amount of code required to make the failing test pass. Focus on making the test pass and nothing more. Keep the code simple and avoid premature optimization or adding unnecessary features.

Step 5: Run the test again

Re-run the test to verify that the minimal code change made in the previous step has successfully addressed the failing test. The test should now pass, indicating that the minimal implementation is correct.

Step 6: Refactor the code

After successfully passing the test, refactor the code to improve its structure, readability, and performance. Ensure that the code remains clean and follows best practices. Refactoring helps eliminate any technical debt and improves the maintainability of the codebase.

Step 7: Repeat the process

Repeat the process by identifying the next functionality or requirement to implement. Define a new test case, write the test, run the test (which should fail), write the minimal code to pass the test, run the test again (which should now pass), and refactor the code.

Step 8: Maintain a suite of tests

Maintain a suite of tests that cover various aspects of the codebase. This suite serves as a safety net, ensuring that future changes or additions to the codebase don't inadvertently break existing functionality.

By following these steps, you ensure that your codebase is thoroughly tested, incrementally developed, and remains reliable. TDD promotes a robust development process, encourages better design decisions, and improves code quality and maintainability.

How do I know if my code is good?

While these philosophies are good for setting up a developers’ mindset around what good code should constitute, the practices are more like instructions they can follow in their day-to-day programming assignments.

Comments should add value

Comments can only add value to good code as they provide more clarity. If your code is too reliant on comments then it’s bad code, then you must consider rewriting it before adding any more comments.

Indentation

You spent weeks making sure the code will be well structured, but is it at the end of the project? Indentation takes collaborative efforts of various stakeholders. It should be obvious for all the developers on the project to understand where a block of code starts and where it ends. Indentation is all about making the codebase well-defined and straightforward to understand.

Naming conventions

Classes should stick to the single responsibility principle (SRP). Good naming conventions, together with SRP, make a developers’ life much simpler when trying to understand a new project.

Naming conventions should differ with various scopes if a Class is executing an intensive scope of work. When and where a variable goes out of scope with a single glance at the code block is a good place to start.

Use expressive naming conventions for all but the most transient objects. An informative name says a lot about when and how to use the object.

Avoid magic numbers, constants, and hard strings

One constant in your entire codebase is bad, two are ugly, and three are a recipe for disaster. Once the code is a part of the main branch, figuring out the constant’s value would take going through the entire codebase and no developer has this amount of spare time. What if changing this magical number crashes the entire program? Hard strings are a bad code choice if you’re looking to localize your application.

Timing

I came across this image on BetterProgramming, which they believe is self-explanatory.

How do you write good code?

According to the most upvoted answer on Stack Overflow to “What does a good programmer's code look like?” good code is organized, tested, straightforward and independent.

Mastering the art of clean and manageable coding is crucial for every developer. By implementing the essential tips outlined in this article, you can significantly improve your coding skills and adopt best practices that lead to more efficient, maintainable, and easily understandable code. Whether it's using consistent and descriptive naming conventions or regularly testing your code, you'll be well on your way to becoming a proficient developer who produces clean, manageable, and high-quality code.

Additional resources for further learning

"Clean Code: A Handbook of Agile Software Craftsmanship" by Robert C. Martin

"Refactoring: Improving the Design of Existing Code" by Martin Fowler

"Test-Driven Development: By Example" by Kent Beck 

 

SHARE

Cookie Settings

×

When you visit any website, it may store or retrieve information on your browser in the form of cookies. This information may be about you, your preferences or your device. This is mostly used to make the website work as you would expect it to. The information doesn’t identify you but can be used to offer a more personalized web experience.

Because we respect your right to privacy, you can choose to not allow certain types of cookies. By clicking on the different category headings, you can find out more and change from our default settings. However, blocking certain types of cookies may negatively impact your experience on this site and the services we are able to offer.

Cookie Policy

Manage Consent Preferences

These cookies are necessary for the website to be able to function, hence cannot be switched off in our systems. They are usually only set in response to actions made by you which amount to a request for services. This includes setting your privacy preferences, logging in or filling in forms. You can set up your browser to block or alert you about these cookies, however some parts of the website won’t work as a result. These cookies don’t store any personally identifiable information.

These cookies allow us to count visits and traffic sources, so we can measure and improve the performance of our site. They help us know which pages are the most and least popular and see how visitors move around the site. All information these cookies collect is aggregated and therefore anonymous. If you do not allow these cookies, we will not know when you have visited our site.

These cookies may be set through our site by our advertising partners. They may be used by those companies to build a profile of your interests and show you relevant adverts on other sites.    They do not store directly personal information, but are based on uniquely identifying your browser and internet device. If you do not allow these cookies, you will experience less targeted advertising.