Несколько лет назад я прочитал книгу «Путь «Тойоты», руководствуясь интересом к истокам разработки программного обеспечения Agile. Однако еще больше меня заинтриговали производственные процессы «Тойоты» и принципы повышения их эффективности. В книге содержалось множество ценных идей и практик, которые можно было взять на вооружение. Меня, как разработчика, особенно привлекли 5 S-принципов. Я понял, что мы часто применяем большинство из этих принципов в работе, хотя и не систематически.
5 S-принципов, заимствованных из сферы бережливого производства, — это японская методология, направленная на повышение эффективности и производительности за счет систематической организации. Вот эти принципы — Sort («Сортировка»), Set in Order («Приведение в порядок»), Shine («Очистка»), Standardize («Стандартизация») и Sustain («Поддержание»).
В этой статье мы рассмотрим, как каждый из пяти S-принципов можно применить к практике написания кода на примере JavaScript. Мы обсудим практическую реализацию, инструменты, которые помогут в этом процессе, и то, как интегрировать указанные принципы в рабочий процесс разработки. К концу статьи вы получите полное представление о том, каким образом 5 S-принципов способны усовершенствовать практику программирования и как они помогут создавать более чистый, эффективный и удобный в обслуживании код.
Важно отметить, что разработка ПО в корне отличается от производства. Мы не занимаемся массовым производством идентичных продуктов, а скорее участвуем в творческом, логическом и итеративном процессе проектирования. Поэтому сосредоточимся на адаптации этих принципов к уникальным потребностям разработки программного обеспечения, а не на их прямом применении.
Помните, что приведенные ниже примеры и практики не являются исчерпывающими или универсально применимыми ко всем производственным средам. Они лишь служат отправной точкой.
1. Sort («Сортировка»). Удаляйте ненужные элементы из рабочего пространства
В контексте программирования это означает выявление и устранение неиспользуемого кода, зависимостей и прочего мусора, который может затруднить управление и понимание кодовой базы. Ниже — пример того, как можно применить принцип Sort, а также инструменты, которые помогают в этом.
Выявление неиспользуемого кода
Начните с определения неиспользуемого кода, такого как функции, переменные, комментарии и импорт, которые больше не нужны. ESLint — популярный инструмент линтинга JavaScript, используемый для выявления и устранения подобных проблем в коде JavaScript. Он анализирует код на предмет потенциальных ошибок и обеспечивает последовательный стиль программирования, что помогает поддерживать качество кода и сокращать количество ошибок.
До:
// Неиспользуемая функция
function unusedFunction() {
console.log('This is never used');
}
// const request = new Request("https://example.org/post", {
// метод: "POST",
// тело: JSON.stringify({ username: "example" }),
// });
// Основная функция
function mainFunction() {
console.log('This function is used');
}
mainFunction();
import React from 'react';
import { useState } from 'react';
import { unusedFunction } from './utils';
const MyComponent = () => {
const [state, setState] = useState(0);
return <div>{state}</div>;
};
export default MyComponent;
После:
// Основная функция
function mainFunction() {
console.log('This function is used');
}
mainFunction();
import React from 'react';
import { useState } from 'react';
const MyComponent = () => {
const [state, setState] = useState(0);
return <div>{state}</div>;
};
export default MyComponent;
Выявление и удаление неиспользуемых зависимостей
Инструменты типа depcheck
помогут найти неиспользуемые пакеты npm в проекте.
npx depcheck
Unused dependencies
* lodash
npm uninstall lodash
2. Set in Order («Приведение в порядок»). Организуйте элементы для обеспечения эффективности рабочего потока
В контексте программирования это означает структурирование кодовой базы проекта логичным и последовательным образом, а также расположение файлов и каталогов для оптимального понимания, повторного использования и удобства сопровождения разработчиками.
Организуйте структуру проекта
Атомарный дизайн — это методология создания систем проектирования путем разбиения компонентов пользовательского интерфейса на более мелкие, многократно используемые части. Такой подход улучшает организацию и возможность повторного использования в проекте.
project/
├── src/
│ ├── components/
│ │ ├── atoms/
│ │ │ └── Button.tsx
│ │ ├── molecules/
│ │ │ └── Form.tsx
│ │ ├── organisms/
│ │ │ └── Header.tsx
│ │ ├── templates/
│ │ │ └── PageTemplate.tsx
│ │ └── pages/
│ │ └── HomePage.tsx
│ ├── assets/
│ │ ├── images/
│ │ └── styles/
│ ├── utils/
│ │ └── helpers.ts
│ └── App.ts
├── public/
│ └── index.html
├── package.json
└── README.md
Структурирование по функциям. Организация по функциям обеспечивает группировку всех файлов, относящихся к определенной функции, что облегчает управление и масштабирование больших приложений.
src/
│
├── features/
│ ├── UserManagement/
│ │ ├── components/
│ │ │ ├── UserProfile.tsx
│ │ │ ├── UserList.tsx
│ │ │ └── UserForm.tsx
│ │ ├── hooks/
│ │ │ ├── useUserData.ts
│ │ │ └── useUserList.ts
│ │ ├── api/
│ │ │ └── userApi.ts
│ │ ├── utils/
│ │ │ └── userFormatters.ts
│ │ └── index.ts
│ │
│ ├── Authentication/
│ │ ├── components/
│ │ │ ├── LoginForm.tsx
│ │ │ └── RegistrationForm.tsx
│ │ ├── hooks/
│ │ │ └── useAuth.ts
│ │ ├── api/
│ │ │ └── authApi.ts
│ │ ├── utils/
│ │ │ └── authValidators.ts
│ │ └── index.ts
│ │
│ └── Dashboard/
│ ├── components/
│ │ ├── DashboardLayout.tsx
│ │ ├── AnalyticsWidget.tsx
│ │ └── ActivityFeed.tsx
│ ├── hooks/
│ │ └── useDashboardData.ts
│ ├── api/
│ │ └── dashboardApi.ts
│ ├── utils/
│ │ └── dashboardHelpers.ts
│ └── index.ts
│
├── shared/
│ ├── components/
│ │ ├── Button.tsx
│ │ ├── Input.tsx
│ │ └── Modal.tsx
│ ├── hooks/
│ │ └── useForm.ts
│ └── utils/
│ ├── formatters.ts
│ └── validators.ts
│
├── App.ts
└── index.ts
Плоская структура:
src/
├── components/
│ ├── Header.ts
│ ├── Footer.ts
│ └── Navigation.ts
├── pages/
│ ├── Home.ts
│ ├── About.ts
│ └── Contact.ts
├── utils/
│ └── helpers.ts
└── App.ts
Указанные выше примеры приведены только в демонстрационных целях
Помните: выбор оптимальной структуры зависит от конкретного проекта и команды. Одни предпочитают плоские структуры, в то время как другие считают полезными вложенные конструкции. Главное — обсудить и согласовать подход, который способен повысить производительность команды.
- Рассмотрите компромиссные решения между глубоко вложенными структурами и плоскими конструкциями.
- Используйте понятные, описательные имена для файлов и каталогов.
- Убедитесь в том, что файлы и каталоги расположены логично для удобства доступа и сопровождения.
- Размещайте служебные функции в каталоге
utils
. - Группируйте связанные компоненты в каталоге
components
, следуя принципу атомарного проектирования или другим шаблонам, которые подходят для ваших нужд.
- Храните статические активы, такие как изображения и стили, в каталоге
assets
.
3. Shine («Очистка»). Очищайте рабочее пространство, чтобы соответствовать стандартам и выявлять проблемы
В контексте программирования это означает, что код должен быть чистым, читабельным и соответствующим стандартам. Хотя очистка обычно включает уборку и упорядочивание элементов, она также охватывает рассмотрение и решение проблем. Регулярно пересматривая и улучшая кодовую базу, вы поддерживаете ее эффективность и удобство для работы. Интегрировав указанные практики и инструменты в процесс разработки, вы сможете повысить читабельность кода, удобство сопровождения и общее качество проекта.
Форматирование и стилизация кода
Такие инструменты, как Prettier и ESLint, помогают обеспечить последовательное форматирование и качество кода.
// До форматирования
function fetchData(){
return fetch('https://api.example.com/data').then(response => response.json()).then(data => {console.log(data);});
}
// После форматирования с помощью Prettier
function fetchData() {
return fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => {
console.log(data);
});
}
Оптимизация производительности
Повышайте производительность кода, оптимизируя алгоритмы, снижая сложность и используя эффективные структуры данных. В этом помощь окажут инструменты типа SonarQube.
// Перед улучшением (нужна оптимизация)
function findMax(arr) {
let max = arr[0];
for (let i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
// После оптимизации
Math.max(...arr);
Регулярный рефакторинг
Очищайте и улучшайте код без изменения его функциональности, повышая его читабельность и удобство сопровождения. Важно регулярно выявлять области, требующие оптимизации, и вносить в них исправления. Если вы унаследовали кодовую базу от другой команды, рефакторинг для повышения эффективности будет иметь решающее значение.
// Перед упрощением (нужен рефакторинг)
function calculateTotalPrice(products) {
let totalPrice = 0;
for (let i = 0; i < products.length; i++) {
totalPrice += products[i].price;
}
return totalPrice;
}
// После рефакторинга
function calculateTotalPrice(products) {
return products.reduce((total, product) => total + product.price, 0);
}
Регулярный пересмотр и совершенствование практик обеспечивает долгосрочный успех проекта и повышает производительность разработчиков.
4. Standardize («Стандартизация»). Устанавливайте стандарты и процедуры для поддержания организованности и эффективности
Стандартизация в программировании подразумевает создание и соблюдение последовательных практик, соглашений и рекомендаций в рамках проекта или организации. Этот принцип помогает улучшить качество кода, его читаемость и сопровождаемость, а также сократить количество ошибок и улучшить взаимодействие между членами команды.
Соглашения об именовании
Используйте последовательные и описательные соглашения об именовании переменных, функций, классов и файлов. Эта практика делает код более читабельным и удобным для сопровождения. Несколько примеров:
// Переменные и функции используют camelCase
const userName = 'JohnDoe';
let userAge = 30;
function fetchUserData() {
// Получение данных пользователя
}
const calculateRadius = () => { /* ... */ }
// Классы используют PascalCase
class UserProfile {
constructor(name, age) {
this.name = name;
this.age = age;
}
}
// Константы используют UPPER_SNAKE_CASE
const MAX_RETRY_ATTEMPTS = 3;
Создание и использование руководств по стилю
Руководства по стилю определяют соглашения по написанию кода и лучшие практики для обеспечения согласованности в кодовой базе. Вы можете создать такой гайд, который будет соответствовать вашим требованиям, или выбрать один из уже существующих.
Руководство по стилю Airbnb JavaScript: популярный гайд по стилю, который охватывает различные аспекты написания кода на JavaScript.
Руководство по стилю Google Typescript: руководство по стилю от Google, содержащее всеобъемлющие стандарты и практики написания кода для Typescript.
// До стандартизации
function fetchData(){
return fetch('https://api.example.com/data').then(response => response.json()).then(data => {console.log(data);});
}
// После стандартизации
function fetchData() {
return fetch('https://api.example.com/data')
.then((response) => response.json())
.then((data) => {
console.log(data);
});
}
Последовательная обработка ошибок
Установите стандартизированный подход к обработке ошибок и ведению логов, чтобы обеспечить согласованность и облегчить отладку.
// До стандартизации
function fetchData() {
return fetch('https://api.example.com/data')
.then((response) => response.json())
.catch((error) => {
console.error(error);
});
}
// После стандартизации
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
return data;
} catch (error) {
console.error('Error fetching data:', error);
throw error;
}
}
Стандарты тестирования
Определите стандарты написания и организации тестов, включая соглашения об именовании и требования к охвату.
Создавайте файлы тестов, используя согласованное именование, например filename.test.js
:
// fetchData.test.js
const fetchData = require('./fetchData');
test('fetches data from API', async () => {
const data = await fetchData();
expect(data).toBeDefined();
});
Определение и установка порога покрытия кода
Обеспечьте создание отчетов о покрытии, установите минимальный порог покрытия и укажите, какие файлы включать или исключать из анализа покрытия.
module.exports = {
collectCoverage: true,
coverageDirectory: 'coverage',
coverageProvider: 'v8',
coverageReporters: ['text', 'lcov', 'clover'],
coverageThreshold: {
global: {
branches: 80,
functions: 80,
lines: 80,
statements: 80,
},
},
collectCoverageFrom: [
'src/**/*.{js,jsx,ts,tsx}',
'!src/**/*.d.ts',
'!src/index.tsx',
'!src/serviceWorker.ts',
],
};
Контроль версий с помощью Git
Используйте системы контроля версий, такие как Git, чтобы поддерживать стандартизированный подход к управлению кодом, обеспечивая согласованность и гладкое сотрудничество, и используйте стандартные соглашения об именовании ветвей:
- Ветви функций:
feature/short-description
. - Ветви исправлений:
bugfix/short-description
. - Ветви релизов:
release/x.y.z
.
main
feature/user-authentication
feature/dashboard-improvements
bugfix/login-error
release/1.0.0
5. Sustain («Поддержание»). Регулярно поддерживайте и пересматривайте стандарты, чтобы обеспечить их долгосрочное соблюдение
Пятый и последний S-принцип направлен на поддержание и постоянное совершенствование стандартов. Этот принцип гарантирует, что практики, установленные предыдущими четырьмя принципами, будут соблюдаться и станут частью регулярного рабочего процесса. В контексте разработки программного обеспечения это подразумевает непрерывную интеграцию, регулярные обзоры кода, автоматизированное тестирование, а также постоянное обучение и адаптацию к новым технологиям и практикам.
Git-хуки
Использование Git-хуков с помощью Husky позволяет автоматизировать проверки и задачи на разных этапах рабочего процесса Git. Это поможет поддерживать качество кода, обеспечивать прохождение тестов перед коммитами, а также внедрить соглашения о сообщениях коммитов в рамках команды.
// package.json
{
"scripts": {
"prepare": "husky install"
},
"husky": {
"hooks": {
"pre-commit": "npm run lint && npm test",
"pre-push": "npm run build",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
}
}
Непрерывная интеграция и непрерывное развертывание (CI/CD)
Реализуйте конвейеры CI/CD для обеспечения автоматического тестирования, интеграции и развертывания изменений кода. Ниже приведен пример для инструмента GitHub Actions.
Каждый запрос push или pull в ветку main
должен запускать конвейер CI, обеспечивая автоматический запуск тестов и линтинга.
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '14'
- name: Install dependencies
run: npm install
- name: Run tests
run: npm test
- name: Lint code
run: npm run lint
Документация по коду
Ведите документацию по коду, чтобы улучшить его читаемость и сопровождение. Используйте такие инструменты, как JSDoc, для создания документации.
/**
* Вычисляет площадь прямоугольника.
*
* @param {number} length - Длина прямоугольника.
* @param {number} width - Ширина прямоугольника.
* @returns {number} Площадь прямоугольника.
* @throws {Error} Если длина или ширина отрицательны.
*
* @example
* // возвращает 50
* calculateRectangleArea(10, 5);
*
* @since 1.0.0
* @author Jane Doe <jane@example.com>
*/
function calculateRectangleArea(length, width) {
if (length < 0 || width < 0) {
throw new Error('Length and width must be non-negative');
}
return length * width;
}
Регулярные проверки кода
Проводите регулярные проверки кода, чтобы обеспечить соблюдение стандартов и лучших практик программирования.
Контрольный список для проверки кода:
- Код соответствует руководству по стилю (например, Airbnb, Google).
- Функциональность корректна и соответствует требованиям.
- Код чистый, читаемый и поддерживаемый.
- Есть всеобъемлющие тесты.
- Учтены соображения производительности.
Постоянное обучение и адаптация
В индустрии программного обеспечения очень важно шагать в ногу со временем, поскольку она быстро развивается. Постоянное повышение квалификации помогает разработчикам быть в курсе новых технологий, применять их для решения проблем и открывать новые карьерные возможности.
Следите за последними тенденциями, технологиями и передовым опытом разработки на JavaScript, используя онлайн-курсы, книги, видео и т. д. Участвуйте в сообществах JavaScript (например, Stack Overflow, GitHub). Посещайте конференции и встречи (JSConf, местные встречи JavaScript-разработчиков).
Поначалу внедрение этих принципов может показаться сложной задачей, особенно в рамках крупных, устоявшихся проектов или команд. Однако долгосрочные преимущества значительно превосходят первоначальные затраты времени и сил. Более чистый и упорядоченный код приводит к уменьшению количества ошибок, облегчает вхождение в команду новых членов и повышает эффективность циклов разработки.
Помните, что цель 5 S-принципов в программировании — не достижение совершенства, а постоянное улучшение. Начните с малого — возможно, с внедрения линтера в проект или создания процесса проверки кода. Когда команда привыкнет к этим изменениям, постепенно внедряйте другие практики S-принципов.
Читайте также:
- Руководство по Git для новичков
- Хотите стать счастливым и продуктивным программистом? Используйте эти 5 методов из Психологии!
- Искусство упрощения для программистов
Читайте нас в Telegram, VK и Дзен
Перевод статьи Santhosh Sundar: Using the 5S principle in coding