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

Затем я начал понимать, что хорошая система не начинается с хорошего интерфейса, отличных функций и сложных вещей. Хорошие системы начинаются с хорошего качества кода.

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

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

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

Используйте описательные имена

Мы можем начать с имен. Имена переменных и функций должны быть максимально описательными. Не используйте сокращения или имена, которые не имеют смысла. Вот пример плохих и хороших имен.

Плохие имена ❌

const fn = 'Farizal';
const ln = 'Hamami';

function full() {
    return fn + ln;
}

Хорошие имена ✅

const firstName = 'Farizal';
const lastName = 'Hamami';

function getFullName() {
    return firstName + lastName;
}

Имя переменной, функции или класса должно отвечать на все важные вопросы. Он должен рассказать вам, почему он существует, что он делает и как он используется.

Роберт С. Мартин

Старайтесь избегать использования комментариев

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

Неверный код ❌

// Check to see if the employee
// is eligible for full benefits
if ((employee.flags & HOURLY_FLAG) && (employee.age > 65))

Хороший код ✅

if (employee.isEligibleForFullBenefits())

Я часто вижу, как разработчики оставляют комментарии, которые являются избыточными и не содержат никакой новой информации, кроме самого кода.

Повторяющийся комментарий ❌

// Declare first name
const firstName = 'Farizal';

// Declare last name
const lastName = 'Hamami';

/**
  Get full name by combining
  first name and last name
*/
function getFullName() {
    return firstName + lastName;
}

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

Информативный комментарий ✅

// SimpleDateFormat is not thread-safe,
// so we need to create each instance independently.
const dateFormat = new SimpleDateFormat(
  ”EEE, dd MMM yyyy HH:mm:ss z”);
df.setTimeZone(TimeZone.getTimeZone(”GMT”));

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

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

Дайте согласованное имя функции

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

Несовместимые имена ❌

class Circle {
    public function getRadius() {...}
    public function fetch_color() {...}
    public function retrieveArea() {...}
}

Последовательные имена ✅

class Circle {
    public function getRadius() {...}
    public function getColor() {...}
    public function getArea() {...}
}

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

Уменьшить количество символов в строке

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

Слишком долго ❌

throw ValidationException::withMessages(['email' => trans('auth.failed'), 'error' => 'Your password is incorrect', 'redirect' => true]);

Сохраняйте длину короткой ✅

throw ValidationException::withMessages([
    'email' => trans('auth.failed'),
    'error' => 'Your password is incorrect',
    'redirect' => true
]);

Функции должны быть небольшими

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

Сложная функция ❌

function createAppointment(appointment) {
    const patientList = this.$api.get('patient');
    const currentPatient = patientList.find((patient) => {
        patient.id = appointment.patient_id
    });
    const selectedDoctor = doctorList.find((doctor) => {
        doctor.id = appointment.doctor_id
    });
    const selectedLocation = locationList.find((location) => {
        location.id = appointment.location_id
    });
    this.sendAppointment(selectedDoctor, selectedDoctor, currentPatient);
}

Простая функция✅

function createAppointment(appointment) {
    const currentPatient = getCurrentPatient(this.patientId);
    this.sendAppointment(
      appointment,
      currentPatient
    );
}

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

Роберт С. Мартин

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

function buildCar(float wheelDiameter, float wheelColor, float wheelMaterial, float wheelManufacturer, String engineType, String engineColor, String engineManufacturer);

Его можно улучшить, используя их объекты в качестве параметров ✅

function buildCar(Wheel wheel, Engine engine);

Рекомендации по форматированию

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

К счастью, в подходе «Чистый код» существуют соглашения по форматированию. Я думаю, в этом случае нам нужна сделка, поэтому было бы хорошо, если бы каждый разработчик следовал этому сценарию 😆.

Переменные

Переменные должны быть объявлены как можно ближе к их использованию.

function paySalary(Employee employee) {
    const bonus = calculateBonus(employee);
    const totalSalary = bonus + employee.getSalary();
    sendMoney(employee, totalSalary);
}

Переменные экземпляра должны быть объявлены в верхней части класса.

public class Employee {
    private String name;
    private String id;
    private float salary;
    
    public function getName() { ... }
}

Функции

Зависимые функции должны быть вертикально близки.

function paySalary() {
    calculateBonus(salary);
}

function calculateBonus(salary) {
    return (salary / 10);
}

Связанные функции должны быть рядом друг с другом.

class Employee {
    public function payTax() {}

    public function payOverdueTax(date) {}

    public function increaseSalary() {}

    public function decreaseSalary() {}
}

Горизонтальное выравнивание

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

public class WebService {
    private    Request         request;
    private    Response        response;
    private    FitnesseContext context;
    protected. long            requestTimeLimit;
}

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

public class WebService {
    private Request request;
    private Response response;
    private FitnesseContext context;
    protected long requestTimeLimit;
}

Отступ

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

public String functionName() {return "";}

Мы можем улучшить его, добавив отступ ✅

public String functionName() {
    return "";
}

Заключение

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

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

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