Introduction :
Before diving into this blog, let me mention that I’m writing it on a very special day—25th December 2024. First of all, Merry Christmas to everyone! 🎄✨ Today, we’re going to discuss one of the most important topics in the software engineering field. So, let’s get started.
There are essentially two types of code: working code and non-working code.
Non-working code: This type of code is essentially useless—it doesn’t compile successfully and fails to meet the requirements of the given functionality. Every developer tries to avoid writing non-working code as much as possible.
Working code: This is code that compiles perfectly, functions as expected, and meets the requirements of the given functionality. However, within working code, we encounter two further classifications:
Good code
Bad code
I once read a tweet that said,
"A Software Engineer should not be judged by how many lines of code they write but by the productivity of their code."
This raises an important question: How do we increase the productivity of our code?
The simple answer is by writing Good Code.
In this blog, I’ll share some ideas on how to write good code that can set you apart from other developers, drawing from my 1.6 years of experience in the tech industry and the valuable lessons I've learned along the way.
1. Make the Code Work First:
First and foremost, focus on making the code work before thinking about refactoring. Ensure that it compiles successfully and meets all the requirements. In most cases, certain conditions might fail to meet the desired requirements, so address those thoroughly. Additionally, ensure that your code does not break any existing functionality. If your organization has automated tests, run them to verify that everything is working as expected.
2. Take care of naming conventions :
After making your code functional, check the names of your variables and functions. They should be meaningful and descriptive. For example, if a function returns the maximum element of an array, name it something like getMaxElement
. Similarly, for variables, if one represents a map, name it something like countDuplicateMap_
. Using meaningful names makes it clear to reviewers what each function or variable is intended to do.
3. Use the const
Keyword Appropriately :
If you are working with simple, straightforward values like a number (100
) or a string (customerId
), avoid hardcoding them directly in your code. Instead, define them as const
variables and use those constants throughout your class. This improves readability and maintainability.
class Demo {
const MAX_ARRAY_SIZE = 500;
private myFunction(): void {
for(int i=0;i<MAX_ARRAY_SIZE; i++) {
// logic
}
}
}
4. Ensure Each Function Has a Single Responsibility
It’s crucial to write multiple helper functions to provide a clear understanding of the code flow to the reviewer. However, each helper function should perform only one specific task. A single function should contain only one logic. For instance, if you are writing a function to return the sum of an array of elements, it should focus solely on calculating and returning the sum. It should not include logic for finding the maximum element.
5. Use the static
Keyword Appropriately
If a function or helper function does not depend on the current class or its members, and its functionality is not directly related to the class, consider making it a static
function. Additionally, move such functions to a utility or public class where they can be accessed by other parts of the codebase in the future. This promotes code reusability and better organization.
6. Avoid Using switch
Statements
switch
statements are often used to replace large if-else
chains, but they can be challenging to maintain and debug. When adding more cases, you need to manually update the code with each new case and ensure the correct usage of break
statements, which can be time-consuming and error-prone.
Consider this example:
function getNumber(day) {
let dayNumber;
switch (type) {
case 'Sunday':
dayNumber = 1;
break;
case 'Monday':
dayNumber = 2;
break;
case 'Wednesday':
dayNumber = 3;
break;
case 'Thursday':
dayNumber = 4;
break;
default:
dayNumber = -1;
}
return dayNumber;
}
If you need to add more cases to a switch
statement, you might end up copy-pasting code, increasing the risk of redundancy and inconsistency.
How to Avoid switch
Statements
You can replace switch
statements with object literals, which are simpler, easier to write, read, and maintain. Here’s an example:
const days = {
Monday: 1,
Tuesday: 2,
Wednesday: 3,
Thursday: 4
};
function getNumber(type) {
return days[type] || -1;
}
console.log(getNumber('Monday')); // Result: 1
// If the type isn't found in the days object, the function will return the default value -1
console.log(getNumber('unknown')); // Result: -1
Why Use Object Literals?
Adding a new case is as simple as adding a key-value pair to the object.
Object literals inherently avoid the issues of missing
break
statements.You can include a default value using the
||
operator, making the function more robust.
In the example above, the getNumber
function will return -1
as the default value if the given day
is not found in the days
object. This approach enhances readability and simplifies maintenance.
Conclusion :
Writing clean and maintainable code is essential for long-term success in software development. By ensuring your code works first, following naming conventions, leveraging const
and static
appropriately, keeping functions focused on a single responsibility, and avoiding switch
statements with better alternatives like object literals, you can create code that is easier to understand, debug, and scale. Small, thoughtful improvements lead to significant impacts on code quality over time.
Thank you so much for reading this article. Stay tuned for more tutorials and follow me for more tech insights!