Writing clear and concise code is a fundamental skill that we developers should strive to master. Clean code is not only easier to read and understand but also promotes maintainability, collaboration, and efficient debugging.
I could list all of the qualities that I notice in clean code, but there is one overarching quality that leads to all of them. Clean code always looks like it was written by someone who cares. There is nothing obvious that you can do to make it better. All of those things were thought about by the code’s author, and if you try to imagine improvements, you’re led back to where you are, sitting in appreciation of the code someone left for you — code left by someone who cares deeply about the craft. Michael Feathers, author of Working Effectively with Legacy Code
Let’s look at some examples:
Overcomplicating Code
Bad way
public string GetFormattedName(string firstName, string middleName)
{
string formattedName = string.Empty;
if (!string.IsNullOrEmpty(firstName))
{
formattedName += firstName.Trim();
}
if (!string.IsNullOrEmpty(middleName))
{
if (!string.IsNullOrEmpty(formattedName))
{
formattedName += " ";
}
formattedName += middleName.Trim();
}
return formattedName;
}
Good way
public string GetFormattedName(string firstName, string middleName)
=> string.Join(" ", firstName?.Trim(), middleName?.Trim()).Trim();
In the simplified code, the string.Join method is used to concatenate the names with spaces, and the ?. null-conditional operator is used to handle potential null values. The code is more concise, easier to read, and achieves the same functionality without unnecessary complexity.
Overcomplicating code can lead to increased cognitive load, reduced maintainability, and higher chances of introducing bugs. It’s important to strive for simplicity and readability in code whenever possible. Let's take a look at another example.
Bad way
bool isEven = (number % 2 == 0) ? true : false;
Good way
bool isEven = number % 2 == 0;
Loops Instead of LINQ
90% of cases loops can be substituted with a LINQ query. It might be my personal viewpoint, but I believe LINQ query is much more comprehensible than a significantly larger for-loop.
Bad way
public List<int> GetEvenNumbers(List<int> numbers)
{
List<int> evenNumbers = new List<int>();
foreach (int number in numbers)
{
if (number % 2 == 0)
{
evenNumbers.Add(number);
}
}
return evenNumbers;
}
Good way
public List<int> GetEvenNumbers(List<int> numbers)
=> numbers.Where(number => number % 2 == 0).ToList();
Complex IF Condition
A complex if condition refers to a conditional statement that involves multiple logical operations, conditions, or an expression that might be difficult to read and maintain.
Bad way
if (number % 2 == 0)
{
// Do something
}
Better way
private bool IsEven(int number) => number % 2 == 0;
if (IsEven(number))
{
// Do something
}
}
This practice helps in reducing code duplication, improving code organization, and enhancing code maintainability.
Deep Nesting
In the example below, the code is 3-level nested and this can make the code harder to understand and maintain. Deep nesting can also increase the risk of introducing logical errors and make code modifications more challenging.
Bad way
if (condition1)
{
if (condition2)
{
if (condition3)
{
// Do something
}
}
}
Good way
if (condition1 && condition2 && condition3)
{
// Do something
}
Just ensure that the conditions are logically correct and properly grouped. Also, it might be a perfect time to refactor and extract them into methods as we did in the previous example IsEven.
String Concatenation
The GenerateGreeting method concatenates multiple strings using the + operator. While this code may work correctly, it can become problematic when dealing with more complex scenarios or a large number of concatenated strings
Bad way
public string GenerateGreeting(string name)
{
return "Hello, " + name + "! " + "How are you today?";
}
Good way
public string GenerateGreeting(string name)
{
return $"Hello, {name}! How are you today?";
}
Magic Numbers
Avoid using magic numbers. Assign meaningful constants or enumerations to such values to improve code clarity and maintainability.
Bad way
if (status == 2)
{
// Do something
}
Good way
const int InProgressStatus = 2;
if (status == InProgressStatus)
{
// Do something
}
Long Methods
Break down long methods into smaller, focused methods. This improves code readability, reusability, and maintainability.
Bad way
public void ProcessData()
{
// Several hundred lines of code
}
Good way
public void ProcessData()
{
ValidateInput();
CalculateValues();
SaveData();
}
Poor Naming Conventions
Using meaningful and descriptive names for variables, methods, and classes improves code readability and helps others understand our code.
Bad way
var dt = DateTime.Now.ToString("YYYY/MM/DD");
Good way
var currentDate = DateTime.Now.ToString("YYYY/MM/DD");
Inconsistent Formatting
Consistent and properly indented code enhances readability and reduces confusion.
Bad way
public void PrintNumbers()
{
for (int i = 0;i < 10; i++)
{
Console.WriteLine(i);
}
}
Good way
public void PrintNumbers()
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine(i);
}
}
Excessive Comments
Avoid commenting on obvious code. Comments should be used to explain complex logic or clarify code that may be unclear.
Bad way
// Increment counter by 1
counter++;
Good way
counter++;
File-Scoped Nested Namespaces
File-scoped namespaces were introduced in C# 10.0 and allow us to define namespaces directly at the file level without enclosing them in a traditional namespace block
Ok
// File-scoped nested namespace declaration
namespace MyApplication.Utilities
{
public static class Helper
{
}
}
Better way
namespace MyApplication.Utilities;
public static class Helper
{
}
Final Thoughts
By avoiding these bad practices and adopting good coding practices, we can significantly improve the readability, maintainability, and overall quality of our C# code.
Thanks for reading!
Through my articles, I share Tips & Experiences on web development, career, and the latest tech trends. Join me as we explore these exciting topics together. Let’s learn, grow, and create together!
➕More article about Programming, Careers, and Tech Trends.
Top comments (4)
Thank you very much :-)
You're welcome @artydev :)
Great guidelines!
You can leave out the junior part in the title, this applies to all levels.
Hi Boudewijn, thanks for your comment and suggestion. I wasnt sure when I was creating the title rsrs. I'll remove it right now