Написание ясного и лаконичного кода — фундаментальный навык, которым мы, разработчики, должны стремиться овладеть. Чистый код не только легче читать и понимать, но и способствует сопровождению, совместной работе и эффективной отладке.

Я мог бы перечислить все качества, которые я замечаю в чистом коде, но есть одно всеобъемлющее качество, которое приводит ко всем из них. Чистый код всегда выглядит так, как будто его написал небезразличный человек. Нет ничего очевидного, что вы можете сделать, чтобы сделать его лучше. Все эти вещи были продуманы автором кода, и если вы попытаетесь вообразить улучшения, вы вернетесь туда, где вы находитесь, сидя в знак признательности за код, который кто-то оставил для вас — код, оставленный кем-то, кто глубоко заботится о коде. ремесло. Майкл Фезерс, автор книги «Эффективная работа с устаревшим кодом».

Давайте рассмотрим несколько примеров:

Слишком сложный код

В приведенном ниже примере метод GetFormattedName предназначен для объединения имени и отчества в отформатированную строку. Однако код излишне сложен и может быть упрощен.

Плохой способ

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;
}

Хороший способ

public string GetFormattedName(string firstName, string middleName)
 => string.Join(" ", firstName?.Trim(), middleName?.Trim()).Trim();

В упрощенном коде метод string.Join используется для объединения имен с пробелами, а оператор ?. null-conditional используется для обработки возможных нулевых значений. Код стал более лаконичным, его легче читать, и он обеспечивает ту же функциональность без излишней сложности.

Чрезмерное усложнение кода может привести к увеличению когнитивной нагрузки, снижению ремонтопригодности и повышению вероятности появления ошибок. Важно стремиться к простоте и удобочитаемости кода, когда это возможно. Давайте посмотрим на другой пример.

Плохой способ

bool isEven = (number % 2 == 0) ? true : false;

Хороший способ

bool isEven = number % 2 == 0;

Циклы вместо LINQ

90% циклов случаев можно заменить запросом LINQ. Это может быть моя личная точка зрения, но я считаю, что запрос LINQ намного понятнее, чем цикл for значительно большего размера.

Плохой способ

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;
}

Хороший способ

public List<int> GetEvenNumbers(List<int> numbers) 
 => numbers.Where(number => number % 2 == 0).ToList();

Комплексное условие ЕСЛИ

Сложное условие if относится к условному оператору, который включает в себя несколько логических операций, условий или выражений, которые могут быть трудными для чтения и обслуживания.

Плохой способ

if (number % 2 == 0)
{
   // Do something
}

Лучший способ

private bool IsEven(int number) => number % 2 == 0;
if (IsEven(number))
   {
     // Do something
   }
}

Эта практика помогает уменьшить дублирование кода, улучшить организацию кода и повысить удобство сопровождения кода.

Глубокая вложенность

В приведенном ниже примере код имеет 3 уровня вложенности, и это может затруднить его понимание и поддержку. Глубокая вложенность также может увеличить риск появления логических ошибок и усложнить модификацию кода.

Плохой способ

if (condition1)
{
    if (condition2)
    {
        if (condition3)
        {
            // Do something
        }
    }
}

Хороший способ

if (condition1 && condition2 && condition3)
{
    // Do something
}

Просто убедитесь, что условия логически правильны и правильно сгруппированы. Кроме того, это может быть идеальное время для рефакторинга и извлечения их в методы, как мы сделали в предыдущем примере IsEven .

Конкатенация строк

Метод GenerateGreeting объединяет несколько строк с помощью оператора +. Хотя этот код может работать правильно, он может стать проблематичным при работе с более сложными сценариями или большим количеством объединенных строк.

Плохой способ

public string GenerateGreeting(string name)
{ 
   return "Hello, " + name + "! " + "How are you today?";
}

Хороший способ

public string GenerateGreeting(string name)
{ 
   return $"Hello, {name}! How are you today?";
}

Магические числа

Избегайте использования магических чисел. Назначьте значимые константы или перечисления для таких значений, чтобы улучшить ясность кода и удобство сопровождения.

Плохой способ

if (status == 2)
{
    // Do something
}

Хороший способ

const int InProgressStatus = 2;

if (status == InProgressStatus)
{
    // Do something
}

Длинные методы

Разбейте длинные методы на более мелкие, целенаправленные методы. Это улучшает читаемость кода, повторное использование и ремонтопригодность.

Плохой способ

public void ProcessData()
{
    // Several hundred lines of code
}

Хороший способ

public void ProcessData()
{
    ValidateInput();
    CalculateValues();
    SaveData();
}

Плохие соглашения об именах

Использование осмысленных и описательных имен для переменных, методов и классов улучшает читабельность кода и помогает другим понять наш код.

Плохой способ

var dt = DateTime.Now.ToString("YYYY/MM/DD");

Хороший способ

var currentDate = DateTime.Now.ToString("YYYY/MM/DD");

Несовместимое форматирование

Последовательный код с правильным отступом улучшает читабельность и уменьшает путаницу.

Плохой способ

public void PrintNumbers()
{
for (int i = 0;i < 10; i++)
{
Console.WriteLine(i);
}
}

Хороший способ

public void PrintNumbers()
{
    for (int i = 0; i < 10; i++)
    {
        Console.WriteLine(i);
    }
}

Чрезмерные комментарии

Не комментируйте очевидный код. Комментарии следует использовать для объяснения сложной логики или разъяснения кода, который может быть непонятным.

Плохой способ

// Increment counter by 1
counter++;

Хороший способ

counter++;

Вложенные пространства имен с файловой областью

Пространства имен с файловой областью были введены в C# 10.0 и позволяют нам определять пространства имен непосредственно на уровне файла, не заключая их в традиционный блок пространства имен.

Ok

// File-scoped nested namespace declaration
namespace MyApplication.Utilities
{
    public static class Helper
    {
    }
}

Лучший способ

namespace MyApplication.Utilities;
    
public static class Helper
{
}

Последние мысли

Избегая этих плохих практик и применяя хорошие методы кодирования, мы можем значительно улучшить читабельность, удобство сопровождения и общее качество нашего кода C#.

Спасибо за прочтение!

В своих статьях на Medium я делюсь мыслями о веб-разработке, советами по карьере и последними тенденциями в области технологий. Присоединяйтесь ко мне, когда мы вместе исследуем эти захватывающие темы. Давайте учиться, расти и творить вместе!

👏Похлопайте, чтобы статья распространилась

Ещё статьи на тему Программирование, карьера и технические тренды.

🔔Подписывайтесь на меня в Средних | Твиттер | ЛинкедИн