Представьте комнату, где повсюду разбросана одежда, книги и другие вещи. Найти что-то в такой комнате было бы сложно, не так ли?
Теперь представьте, что вы пишете беспорядочный код – это не менее запутанно, если не хуже!
С другой стороны, чистый код похож на аккуратную комнату: вы легко находите то, что нужно, понимаете, что происходит, и быстрее выполняете задачи.
Давайте взглянем на этот график. Он показывает два разных подхода к написанию кода и их влияние на время, необходимое для добавления новых строк:
⚠️ «Быстрый и грязный» код (красная линия): Это когда вы пишете код быстро, без тщательного планирования и структурирования. Сначала может показаться, что это экономит время, но по мере увеличения количества строк код становится все сложнее понимать и исправлять. Со временем на добавление каждой новой строки уходит всё больше времени.
⚡Обдуманный и чистый код (синяя линия): Это когда вы пишете код внимательно, делая его понятным и простым для изменений. В начале это может занять чуть больше времени, но со временем код остается удобным в работе. Добавление новых строк не становится сложнее.
Проще говоря, написание чистого кода может казаться более медленным процессом в начале, но в долгосрочной перспективе это экономит много времени и упрощает работу. Кроме того, это способствует созданию более надежного программного обеспечения и качественных продуктов.
Написание чистого кода – это привычка, которую профессиональные разработчики культивируют, демонстрируя приверженность качеству и высокую трудовую этику. В этой статье я расскажу вам о лучших практиках, которые помогут вам поддерживать ваш код чистым.
Что мы рассмотрим:
Используйте осмысленные имена
Следуйте принципу единственной ответственности (SRP)
Избегайте излишних комментариев
Делайте код читаемым
Пишите юнит-тесты
Будьте аккуратны с зависимостями
Организуйте структуру своего проекта
Используйте единый стиль форматирования
Избегайте хардкода значений
Ограничивайте длину функций
Заключение
10 основных советов для написания чистого кода
Чтобы помочь вам начать путь к чистому коду, вот 10 практических советов, которые сделают ваш код читаемым, организованным и эффективным.
1. Используйте осмысленные имена
При выборе имен для переменных, функций и классов старайтесь использовать названия, которые ясно описывают их назначение.
Вместо того чтобы назвать переменную b
, используйте, например, numberOfUsers
. Так любой, кто читает ваш код, сможет легко понять его назначение без дополнительных комментариев. Осмысленное имя исключает догадки и предотвращает путаницу.
Пример:
// Хорошо
let numberOfUsers = 5; // Легко для понимания
// Плохо
let b = 5; // Неясно
? Советы по выбору имен
Переменные: Используйте существительные, описывающие данные, например,
userAge
илиtotalAmount
.Функции: Используйте глаголы, например,
calculateTotal()
илиfetchUserData()
.Классы: Используйте существительные в единственном числе, например,
User
илиOrder
, чтобы показать, что они представляют.
// Переменная: описывает данные, которые хранит
let userAge = 25;
// Функция: Использует слово-действие для описания того, что она делает
function calculateTotal(price, quantity) {
return price * quantity;
}
// Класс: Существительное в единственном числе, обозначающее тип объекта
class User {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
2. Следуйте принципу единственной ответственности (SRP)
Принцип единственной ответственности (single responsibility principle) подразумевает, что каждая функция или метод должны выполнять только одну конкретную задачу.
Это позволяет держать функции короткими и сфокусированными, что делает их легче для чтения, тестирования и сопровождения.
Представьте себе ящик с инструментами, где каждый инструмент имеет свое уникальное назначение — функции в чистом коде должны работать точно так же.
Например, если у вас есть функция calculateTotal
, она должна заниматься только вычислением итоговой суммы. Добавление дополнительных задач приведет к созданию запутанного и трудного для сопровождения кода.
Пример, показывающий важность четкой фокусировки функций:
Предположим, вам нужно вычислить итоговую сумму и вернуть объект с дополнительной информацией, например, кто её вычислил и когда. Вместо того чтобы добавлять эти задачи в calculateTotal
, можно создать вторую функцию.
1. Хороший пример (разделение задач):
// Эта функция вычисляет только общую сумму
function calculateTotal(a, b) {
return a + b;
}
// Эта функция создает объект с дополнительными деталями
function createCalculationRecord(a, b, user) {
let sum = calculateTotal(a, b); // Вызов функции вычисления
return {
user: user,
total: sum,
timestamp: new Date()
};
}
let record = createCalculationRecord(5, 10, "Shahan");
console.log(record);
? Почему это хорошо: Каждая функция выполняет четко определенную задачу. calculateTotal
занимается только математикой, а createCalculationRecord
добавляет дополнительные данные. Если нужно изменить способ вычисления итоговой суммы, вы редактируете только calculateTotal
. Если нужно изменить формат записи, вы редактируете только createCalculationRecord
.
2. Плохой пример (смешивание задач в одной функции):
// Эта функция вычисляет общую сумму и создает объект за один шаг
function calculateTotalAndReturnRecord(a, b, user) {
let sum = a + b;
return {
user: user,
total: sum,
timestamp: new Date()
};
}
let record = calculateTotalAndReturnRecord(5, 10, "Shahan");
console.log(record);
? Почему это плохо: Название функции calculateTotalAndReturnRecord
указывает, что она пытается выполнять сразу несколько задач. Если вам нужен только расчет суммы, вы не сможете использовать эту функцию без части с записью данных. Обновление или тестирование каждой задачи по отдельности становится сложнее.
3. Избегайте излишних комментариев
Хороший код должен быть понятным сам по себе, без необходимости в избыточных комментариях. Сосредоточьтесь на написании кода, который будет четким и понятным без дополнительного объяснения.
Комментарии полезны при объяснении сложной логики или уникального подхода, но слишком большое количество комментариев может загромоздить код и сделать его трудночитаемым.
? Комментарии полезны, когда необходимо:
Объяснить, почему что-то делается определенным образом.
При работе со сложными алгоритмами или вычислениями.
Добавить заметки о возможных ограничениях.
Пример:
// Ясное название, комментарий не нужен
let userAge = 25;
// Неясное название, необходим комментарий
let a; // возраст пользователя
4. Делайте код читаемым
Читаемый код использует отступы, разрывы строк и пробелы, чтобы держать все в порядке и структуре.
Это как написание рассказа: абзацы упрощают чтение, разбивая текст на удобные части. В коде разрывы строк выполняют ту же функцию.
Пример:
// Хороший код
if (isLoggedIn) {
console.log("Welcome!");
} else {
console.log("Please log in.");
}
// Плохой код
if(isLoggedIn){console.log("Welcome!");}else{console.log("Please log in.");}
В VS Code есть Prettier и Black — популярные форматеры, которые автоматически применяют чистую стилизацию кода для нескольких языков.
PyCharm и IntelliJ имеют мощные встроенные форматеры с настраиваемыми правилами, поддерживающие PEP 8 для Python и другие стандартные руководства. Эти инструменты обеспечивают согласованность и читаемость кода в разных проектах, минимизируя ручную работу.
5. Пишите юнит-тесты
Юнит-тесты помогают убедиться, что каждая часть вашего кода работает так, как задумано.
Тестируя небольшие, отдельные части (например, функции), вы можете обнаруживать ошибки на ранних стадиях и предотвращать их распространение на другие части кода.
По сути, юнит-тесты — это мини-проверки качества для каждой части вашего кода, чтобы убедиться, что они работают корректно.
? Пример из реальной жизни:
Рассмотрим тестирование сложного объекта на JavaScript с несколькими методами, используя класс Calculator
в качестве примера.
Это поможет вам понять, почему важно держать каждый метод сосредоточенным на одной задаче и как юнит-тесты обеспечивают корректную работу каждого из них.
Класс Calculator
включает методы для выполнения основных арифметических операций: сложение, вычитание, умножение и деление.
class Calculator {
constructor() {
this.result = 0;
}
add(a, b) {
return a + b;
}
subtract(a, b) {
return a - b;
}
multiply(a, b) {
return a * b;
}
divide(a, b) {
if (b === 0) throw new Error("Cannot divide by zero");
return a / b;
}
}
Каждый метод выполняет одну конкретную операцию. Метод divide
имеет дополнительную логику для обработки деления на ноль, которое могло бы вызвать ошибку.
Теперь напишем юнит-тесты, чтобы убедиться, что каждый метод работает так, как ожидается. ?
? Пишем юнит-тесты для каждого метода:
Для тестирования класса Calculator
мы можем написать тесты, которые охватывают как нормальные, так и крайние случаи:
// Инициализация экземпляра Calculator
const calculator = new Calculator();
// Тестирование метода add
console.assert(calculator.add(2, 3) === 5, 'Test failed: 2 + 3 should be 5');
console.assert(calculator.add(-1, 1) === 0, 'Test failed: -1 + 1 should be 0');
// Тестирование метода subtract
console.assert(calculator.subtract(5, 3) === 2, 'Test failed: 5 - 3 should be 2');
console.assert(calculator.subtract(0, 0) === 0, 'Test failed: 0 - 0 should be 0');
// Тестирование метода multiply
console.assert(calculator.multiply(2, 3) === 6, 'Test failed: 2 * 3 should be 6');
console.assert(calculator.multiply(-1, 2) === -2, 'Test failed: -1 * 2 should be -2');
// Тестирование метода divide
console.assert(calculator.divide(6, 3) === 2, 'Test failed: 6 / 3 should be 2');
try {
calculator.divide(1, 0);
console.assert(false, 'Test failed: Division by zero should throw an error');
} catch (e) {
console.assert(e.message === "Cannot divide by zero", 'Test failed: Incorrect error message for division by zero');
}
? Объяснение тестов:
Сложение (метод
add
): Проверяем, чтоadd(2, 3)
возвращает5
, аadd(–1, 1)
возвращает0
. Если эти тесты проходят, логика сложения работает корректно.Вычитание (метод
subtract
): Проверяем, чтоsubtract(5, 3)
возвращает2
, аsubtract(0, 0)
возвращает0
, подтверждая корректность вычитания.Умножение (метод
multiply
): Проверяем работу с положительными и отрицательными значениями:multiply(2, 3)
возвращает6
, аmultiply(–1, 2)
– –2.Деление (метод
divide
): Проверяем, что деление6
на3
дает2
. Также тестируем деление на ноль с использованиемtry...catch
, чтобы убедиться, что выбрасывается правильное сообщение об ошибке.
Вы видите, что если какой-либо метод не сработает, тест выдаст четкое сообщение об ошибке, что позволит нам быстро определить и устранить проблему. Тестирование методов по отдельности делает код более надежным и упрощает сопровождение проекта по мере его роста.
6. Будьте осторожны с зависимостями
Зависимости – это сторонние библиотеки или модули, от которых зависит ваш код. ?
Представьте, что вы создаете веб-приложение для отправки писем. Вместо написания кода для отправки писем вручную вы используете внешнюю библиотеку, например, Nodemailer. В данном случае Nodemailer – это зависимость, от которой зависит ваше приложение для выполнения этой функции.
Пример:
const nodemailer = require('nodemailer');
function sendEmail(to, subject, message) {
const transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'your-email@gmail.com',
pass: 'your-email-password'
}
});
const mailOptions = {
from: 'your-email@gmail.com',
to: to,
subject: subject,
text: message
};
return transporter.sendMail(mailOptions);
}
В этом коде nodemailer
импортируется и используется для создания транспортера для отправки электронной почты. Без него вам пришлось бы создавать всю функциональность электронной почты с нуля, что было бы сложно и долго. Используя Nodemailer в качестве зависимости, ваше приложение сможет легко отправлять электронные письма.
Несмотря на полезность зависимостей, вы должны стараться избегать чрезмерной зависимости от внешнего программного обеспечения или библиотек. Используйте зависимости только тогда, когда они упрощают вашу работу или добавляют важную функциональность.
Как эффективно управлять зависимостями:
Ограничивайте количество зависимостей: Подключайте только те библиотеки или модули, которые действительно необходимы для проекта.
Обновляйте версии: Используйте актуальные версии библиотек, чтобы избежать уязвимостей в безопасности.
Разделяйте логику: Создавайте основные функции самостоятельно, где это возможно. Это позволит вам удалить зависимость, если потребуется, не ломая остальной код.
Позвольте мне привести пример с нашим предыдущим кодом Nodemailer, чтобы реализовать концепцию разделения логики в вашем коде.
Вы можете создать обертку для функции отправки писем, чтобы скрыть детали использования Nodemailer. Таким образом, вы можете изменить базовый почтовый сервис или удалить зависимость от Nodemailer, не затрагивая остальной части вашего кода.
Вот как вы можете структурировать свой код для достижения этой цели:
const nodemailer = require('nodemailer');
// Основная функция для отправки email
function sendEmail(to, subject, message) {
const transporter = createTransporter();
const mailOptions = createMailOptions(to, subject, message);
return transporter.sendMail(mailOptions);
}
// Функция для создания транспортера
function createTransporter() {
return nodemailer.createTransport({
service: 'gmail',
auth: {
user: 'your-email@gmail.com',
pass: 'your-email-password'
}
});
}
// Функция создания почтовых опций
function createMailOptions(to, subject, message) {
return {
from: 'your-email@gmail.com',
to: to,
subject: subject,
text: message
};
}
// Пример использования
sendEmail('recipient@example.com', 'Test Subject', 'Hello, this is a test email.')
.then(() => {
console.log('Email sent successfully!');
})
.catch((error) => {
console.error('Error sending email:', error);
});
?️ Основные моменты:
Основные функции: Функции
sendEmail
,createTransporter
иcreateMailOptions
разделены, что позволяет изменять одну без влияния на другие.Легкость изменений: Если вы захотите перейти на другую службу для отправки писем, нужно будет изменить только функцию
createTransporter
.Удобство сопровождения: Такая структура делает код более понятным и легким для поддержки.
7. Организуйте структуру своего проекта
Хорошо организованная структура проекта так же важна, как и сам код.
Это похоже на организацию рабочего пространства — вам нужны определенные места для каждой вещи, чтобы их можно было легко найти. В программных проектах это означает создание папок для различных частей, таких как компоненты
, утилиты
и сервисы
.
? Как организовать свой проект
Для создания чистой и организованной структуры проекта распределите различные части кода по соответствующим папкам. Вот простой пример того, как может выглядеть хорошо организованная структура проекта:
myProject
├── src
│ ├── components
│ ├── services
│ ├── utils
└── tests
Разбор структуры проекта:
1. myProject: Это корневая папка вашего проекта, которая содержит всё, что связано с приложением.
2. src (Source): Папка, где находится весь исходный код вашего проекта. Именно здесь вы будете писать большую часть кода.
3. components: Подпапка, которая содержит повторно используемые элементы интерфейса (UI-компоненты). Например, если вы создаете веб-приложение, в этой папке могут быть отдельные файлы для кнопок, заголовков или форм. Каждый компонент должен находиться в отдельном файле, чтобы структура оставалась модульной.
Пример структуры внутри components:
components
├── Button.js
├── Header.js
└── Form.js
4. services: Папка, в которой находятся функции, выполняющие конкретные задачи или обрабатывающие бизнес-логику. Например, если вы отправляете письма, здесь может быть файл с функциями, связанными с отправкой писем.
Пример структуры внутри services:
services
├── emailService.js
├── userService.js
└── productService.js
5. utils (Utilities): Здесь размещаются вспомогательные функции, которые можно использовать в разных частях проекта. Это могут быть функции для форматирования дат, проверки ввода или любых других задач, которые не относятся конкретно к компонентам или сервисам.
Пример структуры внутри utils:
utils
├── formatDate.js
├── validateEmail.js
└── generateId.js
6. tests: Папка, предназначенная для тестов. Организация тестов помогает гарантировать, что с добавлением новых функций вы сможете легко их протестировать, не теряя время на поиск нужных файлов в кодовой базе.
Пример структуры внутри tests:
tests
├── emailService.test.js
├── userService.test.js
└── component.test.js
? Пример из реальной жизни: работа с Nodemailer
Предположим, вы создаете приложение, которое отправляет письма пользователям. Вы можете организовать проект следующим образом:
myEmailApp
├── src
│ ├── components
│ │ ├── EmailForm.js
│ │ └── SuccessMessage.js
│ ├── services
│ │ └── emailService.js
│ ├── utils
│ │ └── validateEmail.js
└── tests
├── emailService.test.js
└── EmailForm.test.js
EmailForm.js: Этот компонент отвечает за пользовательский интерфейс для отправки писем, включая поля для ввода получателя, темы и сообщения.
SuccessMessage.js: Этот компонент отображает сообщение об успешной отправке письма.
emailService.js: Этот сервис содержит логику отправки писем с использованием Nodemailer, сохраняя код модульным и чистым.
validateEmail.js: Утилита, которая проверяет правильность формата адреса электронной почты.
tests: Здесь пишутся тесты, чтобы убедиться, что сервисы отправки писем и компоненты работают так, как ожидается.
? Преимущества хорошо организованного проекта
Удобство навигации: Каждый, кто смотрит на ваш проект, сможет быстро понять, где находятся определенные части кода.
Удобное сотрудничество: Если вы работаете в команде, четкая структура помогает каждому знать, куда вносить свой вклад, не мешая работе других.
Масштабируемость: По мере роста проекта поддержание четкой структуры помогает управлять сложностью и сохранять чистоту кодовой базы.
Улучшенное сопровождение: Когда нужно обновить или исправить что-либо, вы сможете быстро найти соответствующие файлы, что экономит время и снижает вероятность ошибок.
8. Используйте единый стиль форматирования
Последовательное форматирование улучшает читаемость кода.
Определите правила для написания кода, например, использование двух пробелов для отступов или добавление разрыва строки перед комментариями.
Соблюдение единого стиля форматирования делает код чистым и хорошо организованным.
?️ Инструменты для форматирования
Prettier: Автоматически форматирует код на основе набора правил. Руководство по настройке и использованию Prettier в VSCode.
ESLint: Помогает соблюдать стандарты кодирования, выделяя проблемы. Руководство по настройке ESLint для ваших проектов.
9. Избегайте хардкода значений
Hardcoding — это прямое встраивание значений в код, например, установка ID пользователя как 123
вместо использования переменной.
Избегание жестко заданных значений позволяет переиспользовать код без постоянных изменений. Вместо этого храните значения в переменных, константах или файлах конфигурации.
Пример с жестко заданным значением:
// Плохо: Хардкод лимита пользователей
function createUser(name) {
let numberOfUsers = 100; // Захардкоженое значение
if (numberOfUsers >= 100) {
return 'User limit reached.';
}
// Код для создания пользователя
return 'User created.';
}
В этом примере значение numberOfUsers
жестко задано 100
. Если нужно изменить лимит пользователей, вам придется искать и модифицировать это значение в коде. Если оно встречается в нескольких местах, задача становится трудоемкой и подверженной ошибкам.
?️ Улучшенный пример с использованием констант:
// Хорошо: Использование константы
const MAX_USERS = 100; // Хранит лимит в константе
function createUser(name) {
let numberOfUsers = getCurrentUserCount(); // Получает текущее количество из функции или БД
if (numberOfUsers >= MAX_USERS) {
return 'User limit reached.';
}
// Код для создания пользователя
return 'User created.';
}
// Пример функции для получения текушего количества пользователей
function getCurrentUserCount() {
// Иммитация получения текущего количества, например, из базы данных
return 90; // Пример количества
}
? Разбор улучшенного примера:
Использование констант: Константа
MAX_USERS
определена в начале. Это позволяет менять значение в одном месте, чтобы оно автоматически применилось во всем коде.Динамические значения: Функция
getCurrentUserCount()
динамически получает текущее количество пользователей из базы данных или другого источника. Такой подход предотвращает хардкод подсчета и позволяет легко вносить изменения.Поддерживаемость: Хранение значений в константах упрощает поддержку. Если бизнес-логика меняется, и лимит пользователей увеличивается до
150
, достаточно обновитьMAX_USERS
с100
до150
, и изменения применятся во всем приложении.Ясность: Использование описательных имен для констант (например,
MAX_USERS
) улучшает читаемость кода. Любой, кто посмотрит на код, легко поймет, что это значение обозначает.
? Когда использовать файлы конфигурации
В больших приложениях стоит рассмотреть возможность использования файлов конфигурации (JSON, YAML или переменные окружения) для хранения значений, которые могут изменяться в зависимости от среды (разработка, тестирование, продакшн).
Например, в файле config.json вы можете захардкодить maxUsers
следующим образом (имейте в виду, что в config.json рекомендуется использовать camelCase, так как он обеспечивает последовательное форматирование):
{
"maxUsers": 100,
"emailService": {
"service": "gmail",
"user": "your-email@gmail.com",
"pass": "your-email-password"
}
}
? Использование конфигурации в коде:
const config = require('./config.json');
function createUser(name) {
let numberOfUsers = getCurrentUserCount();
if (numberOfUsers >= config.maxUsers) {
return 'User limit reached.';
}
// Code to create the user
return 'User created.';
}
10. Ограничивайте длину функций
Длинные функции сложнее понять и сопровождать.
Хотя строгих правил нет, рекомендуется, чтобы функции не превышали 20–30 строк. Если функция выполняет множество задач или содержит много шагов, это явный сигнал о необходимости разделения на более мелкие вспомогательные функции. Разбив эти функции на более мелкие «помощники», вы сможете сделать их более управляемыми и понятными.
Как может выглядеть длинная и сложная функция:
function updateCart(cart, item, discountCode) {
// Добавить товар в корзину
cart.items.push(item);
// Рассчитайте новую стоимость
let total = 0;
cart.items.forEach(cartItem => {
total += cartItem.price * cartItem.quantity;
});
// Применить скидку, если возможно
if (discountCode) {
total = applyDiscount(total, discountCode);
}
// Логирование транзакции
console.log(`Item added: ${item.name}, New total: $${total}`);
return total;
}
⚠️ Эта функция выполняет сразу несколько задач:
Добавляет элемент в корзину.
Рассчитывает общую стоимость.
Применяет скидку, если указан код.
Логирует транзакцию.
На первый взгляд эта функция может показаться приемлемой, но если добавятся новые задачи, она станет громоздкой, сложной для отладки и сопровождения.
Разделим эту длинную функцию на более мелкие с единственной целью:
function updateCart(cart, item, discountCode) {
addItemToCart(cart, item);
let total = calculateTotal(cart);
if (discountCode) {
total = applyDiscount(total, discountCode);
}
logTransaction(item, total);
return total;
}
function addItemToCart(cart, item) {
cart.items.push(item);
}
function calculateTotal(cart) {
return cart.items.reduce((total, cartItem) => total + cartItem.price * cartItem.quantity, 0);
}
function logTransaction(item, total) {
console.log(`Item added: ${item.name}, New total: $${total}`);
}
?Объяснение правильного подхода:
addItemToCart
: Эта функция отвечает только за добавление товара в корзину. Она проста и имеет четкую цель.calculateTotal
: Рассчитывает общую стоимость всех элементов в корзине. Если потребуется изменить способ расчета, нужно будет редактировать только эту функцию.logTransaction
: Обрабатывает логирование деталей транзакции. Если потребуется добавить, например, временную метку, это можно сделать только в этой функции, не затрагивая остальной код.updateCart
: Основная функция теперь выглядит как последовательность действий: добавление элемента, расчет общей стоимости, применение скидки и логирование результата. Такой подход делает код легче для понимания.
? Подведем итоги ограничений длины функций:
? Сосредоточьтесь на одной задаче: Каждая функция должна выполнять только одну задачу. Если функция делает слишком много, её стоит разбить на несколько.
? Используйте вспомогательные функции: Вспомогательные функции — это небольшие, целенаправленные функции, которые помогают основной. Например,
addItemToCart
,calculateTotal
и logTransaction
.? Используйте описательные имена: Названия функций должны отражать их задачи. Это делает код понятным.
Лучшие практики для написания чистого кода
Теперь, когда мы рассмотрели ключевые советы, давайте взглянем на общие принципы, лежащие в основе философии чистого кода:
? Простота: Стремитесь сделать ваш код как можно более простым.
? Последовательность: Соблюдайте единый стиль и структуру кода.
?Ясность: Код должен четко объяснять, что он делает.
⛽Эффективность: Пишите код, оптимизированный для производительности, но не в ущерб читаемости.
Эти принципы превращают программирование из простого написания кода в процесс проектирования решений. Написание чистого кода — это навык, который развивается с практикой, поэтому продолжайте учиться и совершенствоваться с течением времени.
? Замечание о зависимостях
Вместо хардкода зависимостей в коде используйте менеджеры пакетов, такие как npm (для JavaScript) или pip (для Python). Это позволяет легко обновлять или удалять зависимости по мере необходимости.
Заключение ?
Написание чистого кода похоже на создание прочного фундамента для дома. Оно поддерживает порядок и облегчает добавление новых функций или исправление ошибок по мере роста вашего проекта.
С этими советами вы сможете развить привычки, которые сделают ваш код более читаемым, поддерживаемым и приятным для работы.
Комментарии (24)
smart_alex
08.12.2024 05:14И ни слова про табличную запись кода...
StepanovAlex
08.12.2024 05:14А что это такое?
smart_alex
08.12.2024 05:14Это когда однотипные участки кода и данных форматируются в соответствии со своей структурой, превращаясь как бы в "таблицу".
Позволяет кардинально сокращать размер листингов, одним взглядом оценивать сложную структуру кода и легко выявлять трудноуловимые ошибки.
Просто супер-метод #1 для программинга и оптимизации кода.
ConstantineOupirum
08.12.2024 05:14Если я вас правильно понял, то вы имеете в виду частный случай data-driven programming?
"Табличная запись кода" даже не гуглится
smart_alex
08.12.2024 05:14Ну, я описал своими словами то, что использую в каждом своём проекте на многих языках программирования - если Гугл этого не знает, то это проблема Гугла :)
Эта методология должна как-то называться, я же не один такой умный.
qeeveex
08.12.2024 05:14Напишите статью. Почитаем.
smart_alex
08.12.2024 05:14Уже написал. В этом руководстве по стилю есть раздел с примером табличного форматирования.
https://hi-lab.ru/arduino-mega-server/manuals/programming/62-ams-code-style
qeeveex
08.12.2024 05:14Так это про оформление кода, а не архитектуру.
smart_alex
08.12.2024 05:14Насколько я понял, речь идёт об описании принципа табличного форматирования - в этой статье есть соответствующий раздел и пример.
qeeveex
08.12.2024 05:14У вас даже в названии фигурирует слово "форматирование".
Возможно это применимо к написанию кода для микроконтроллеров, там да, каждый бит имеет ценность, поэтому архитектуру закладывают на уровне форматирования, так как весь код пишется в одном файле.
Грубо говоря то что у нас лежит в отдельном модуле, там будет в отдельном блоке.
Но это мои предположения.
smart_alex
08.12.2024 05:14Это универсальный метод и он применим (почти) для любого языка программирования.
qeeveex
08.12.2024 05:14Тогда это фигня и очередное чье-то мнение на форматирование кода, коих 100500 уже разведено.
Из-за чего в golang тупо ввели это на уровне языка, чтоб разработчики не тратили время на споры.
К чистому коду это не имеет ни какого отношения. Чистый код про другое. RTFM.
smart_alex
08.12.2024 05:14Я говорю это по опыту написания многих сотен тысяч строк кода во многих проектах - а использовать это и как к этому относиться - это личное дело каждого.
Deosis
08.12.2024 05:14Скорее всего это метод форматирования, связанный с выравниванием пробелами, чтобы знаки пунктуации находились в одном столбце.
Основной минус: при добавлении переменной или функции с более длинным названием выравниваются все остальные строки.
qeeveex
08.12.2024 05:14Давно уже изобрели tools для автоформатирования.
В golang вообще на уровне языка это встроено и ни кто не тратит время на споры.
smart_alex
08.12.2024 05:14Да, при изменении названий блок придётся переформатировать.
Но со временем начинаешь писать однотипный код с однотипнными названиями, что почти исключает переформатирование.
akamap
08.12.2024 05:14Принцип единственной ответственности (single responsibility principle) подразумевает, что каждая функция или метод должны выполнять только одну конкретную задачу.
Сам Р.Мартин говорит, что такое описание не соответствует Принципу единственной ответственности...
justadi
08.12.2024 05:14Приводите пример хороших имен используя calculateTotal. Вот calculateTotal что? Это как раз пример не очень хорошего нейминга.
Mausglov
08.12.2024 05:14Соглашусь. Стоило бы назвать calculateTotalCost , потому что даже в этом контексте может быть ещё calculateTotalQuantity ( суммарное количество товаров в корзине) , calculateTotalDiscount ( общая скидка). Может, ещё что-то.
proneta
08.12.2024 05:14Весь этот JS выполняет calculate... , я считаю, что наоборот — все глаголы лишние. Редкие исключения конкретных действий , типа open close. Но calculate ни в какие ворота не подходит.
И в описательной части интерфейса: приходят писатели в душе — "для применения этой настройки необходим restart". Видели столбы, начинающиеся одинаково "Show ...." , по 10 штук рядом с простыми галками. Кроме психологической атаки на мою самооценку (реально представляешь себя в палате для ограниченных), так еще и место съедает.
У америкосов это заметно, особенности языка с детства, растягивать смысл. Я вижу это же заболевание и у автора. И понимаю предков программирования с их сестрой Краткостью.
qeeveex
08.12.2024 05:14Принцип единственной ответственности (single responsibility principle) подразумевает, что каждая функция или метод должны выполнять только одну конкретную задачу.
Самый холиварный принцип. Для того чтоб понять, нужно прочесть не один десяток мнений, статей, видосов и самого дядю Боба.
Суть его в том что причиной изменения функции должен быть один актор. Например: бухгалтерия и менеджеры. Можно написать один класс который будет обслуживать их обеих. В итоге у функции будет две причины для изменения, что не соответствует принципу.
Вместо бухгалтерии может быть что угодно, в том числе системные вещи.
gun_dose
08.12.2024 05:14Проще говоря, написание чистого кода может казаться более медленным процессом в начале, но в долгосрочной перспективе это экономит много времени и упрощает работу.
На самом деле чистый код и в краткосрочной перспективе пишется быстрее, чем грязный. Вопрос только в том, что писать код быстро и чисто сразу не получится - нужно учиться этому. Чем меньше разработчик понимает то, что он делает, тем грязнее его код. А если понимаешь плохо, то и писать быстро не получится.
saipr
Чётко и ясно. Самое главное - полезно.