Четыре совета по написанию «чистого кода»

Четыре совета по написанию «чистого кода»

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

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

Мы прочитали « Чистый код » Роберта Мартина и сделали все возможное, чтобы выполнить его рекомендации. Внедрение практики « чистого кода » в долгосрочной перспективе удвоит производительность(с минимальными затратами).

Из всех идей, взятых из « Чистого кода », которые мы реализовали, пять основных дали 80% прироста производительности команды.

1. « Если код не протестирован, то он нерабочий ».

Проводите много тестов, особенно модульных.

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

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

3. Классы и возможности должны быть небольшими и соответствовать принципу единичной ответственности(SRP).

Возможности должны состоять не более чем из четырех строк, а классы не более чем из 100 строк. Они также должны делать одну и только одну вещь.

4. Возможности не должны иметь побочных действий.

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

Рассмотрим каждый из данных пунктов.

1. «Если программный код не протестирован, то он нерабочий».

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

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

В «Компьютерной науке» есть две серьезные проблемы: невалидный кэш и именование.

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

Нельзя называть переменную data, foobar или myNumber, а класс — SomethingManager. Убедитесь, что используемые имена являются коротки и точны. Оптимизируйте разработку и упростите поиск файлов при помощи ярлыков IDE «Найти по имени». Уделяйте именованию первоочередное внимание.

3. Классы и возможности должны быть небольшими и соответствовать принципу единичной ответственности(SRP).

Что означает «малый размер» для возможностей? Не более четырех строк кода. Это кажется слишком малым объемом. Но следование данному принципу заставит разработчиков использовать в возможностях короткие имена, которые сделают код понятным для остальных. Вы откажетесь от вложенных конструкций IF, которые запутывают код.

Рассмотрим пример. В Node есть модуль npm под названием «build-url», который делает то, что предполагает его имя: он создает URL-адреса. Исходник файла, который мы рассмотрим, находится здесь. Ниже приведен соответствующий программный код.

function buildUrl(url, options) {var queryString = [];var key;var builtUrl;if(url === null) {builtUrl = '';} else if(typeof(url) === 'object') {builtUrl = '';options = url;} else {builtUrl = url;}if(options) {if(options.path) {builtUrl += '/' + options.path;}if(options.queryParams) {for(key in options.queryParams) {if(options.queryParams.hasOwnProperty(key)) {queryString.push(key + '=' + options.queryParams[key]);}}builtUrl += '?' + queryString.join('&');}if(options.hash) {builtUrl += '#' + options.hash;}}return builtUrl;};

Обратите внимание, что функцию имеет в себя длину 35 строк. Ее несложно понять, но было бы проще, если бы мы применили принцип «маленького кода», чтобы разделить ее на вспомогательные возможности. Вот обновленная и улучшенная версия.

function buildUrl(url, options) { const baseUrl = _getBaseUrl(url); const opts = _getOptions(url, options); if(!opts) { return baseUrl; } urlWithPath = _appendPath(baseUrl, opts.path); urlWithPathAndQueryParams = _appendQueryParams(urlWithPath, opts.queryParams) urlWithPathQueryParamsAndHash = _appendHash(urlWithPathAndQueryParams, opts.hash); return urlWithPathQueryParamsAndHash;};function _getBaseUrl(url) { if(url === null || typeof(url) === 'object') { return ''; } return url;}function _getOptions(url, options) { if(typeof(url) === 'object') { return url; } return options;}function _appendPath(baseUrl, path) { if(!path) {    return baseUrl;  }  return baseUrl += '/' + path;}function _appendQueryParams(urlWithPath, queryParams) {  if(!queryParams) {    return urlWithPath  }  const keyValueStrings = Object.keys(queryParams).map(key => {    return `${key}=${queryParams[key]}`;  });  const joinedKeyValueStrings = keyValueStrings.join('&');  return `${urlWithPath}?${joinedKeyValueStrings}`;}function _appendHash(urlWithPathAndQueryParams, hash) {  if(!hash) {    return urlWithPathAndQueryParams;  }  return `${urlWithPathAndQueryParams}#${hash}`;}

Мы не придерживались правила четырех строк, но создали пару возможностей, которые являются относительно «маленькими». Каждая из них выполняет одну задачу, которую без труда понять по имени. В результате мы получили больше кода, 55 строк вместо 35. Но его гораздо удобнее и легче читать.

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

a) Инициализировать базовый URL-адрес и настройки.

b) Добавить путь(если он есть).

c) Добавьте настройки запроса(если он есть).

d) Добавьте хэш(если он есть).

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

Перейдем к другой связанной концепции — принципу единичной ответственности. Что это значит? Цитата из Википедии:

Принцип единичной ответственности(SRP) — это принцип ООП, согласно которому каждый модуль или класс должен отвечать за одну часть функционала, предоставляемого программой. Реализация должна быть инкапсулирована в одном классе.

Роберт Мартин в « Чистом коде » дает иное определение:

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

Предположим, что мы создаем систему, которая должна включать в себя определенный тип отчета и выводить его. Неоптимальный подход к решению данной задачи может заключаться в создании единого модуля / класса, в котором хранятся данные отчета. Но это нарушает принцип SRP, так как есть две причины для изменения класса. Во-первых, если поля ввода отчета меняются, их необходимо будет обновить. Во-вторых, если изменятся требования, предъявляемые к визуализации отчета, необходимо будет обновить класс. Так что для хранения данных и логики нам необходимо использовать два различных класса, например ReportData и ReportDataRenderer.

4. Возможности не должны иметь побочного действия

Посмотрите пример, приведенный ниже. Вы заметили побочное действие?

function getUserByEmailAndPassword(email, password) {let user = UserService.getByEmailAndPassword(email, password);if(user) {LoginService.loginUser(user); // Log user in, add cookie(Side effect!!!!)}return user;}

Функцию, как следует из ее имени, предназначена для поиска посетителя по email и паролю. Но она имеет в себя скрытое побочное действие: регистрирует посетителя, который создает токен входа. Функцию добавляет его в базу данных и отправляет cookie обратно посетителю со значением logged in.

Это неправильно по ряду причин. Интерфейс возможности трудно понять без прочтения кода реализации. Даже если побочное действие входа задокументировано. Разработчики из-за простого имени возможности не подумают, что им необходимо прочитать документацию. Они будут использовать эту возможность исключительно для извлечения объекта user. При этом не понимая, что они добавляют cookie к запросу, что может привести к ошибкам.

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

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

Запомните и применяйте данные четыре принципа «чистого кода», чтобы повысить производительность вашей команды разработчиков.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *