Пишем чистый интерфейсный код
2 апреля 2023 г.«Чистый код читается как хорошо написанная проза». – Грэди Буч, Clean Code**
Что такое чистый код?
Книга «Чистый код» (Robert C Martin) вышла в 2008 году и с тех пор стала классикой разработки программного обеспечения, одной из первых книг, рекомендованных работодателями и наставниками. В нем Мартин утверждает, что коду недостаточно просто работать — чтобы кодовая база была удобной в сопровождении и отказоустойчивой, код должен быть доступным и читаемым для будущих разработчиков (или нынешних разработчиков, которые могут так долго не прикасаться к коду). они забывают, о чем думали, когда это писали!). Нечистый код может стоить организации часов времени разработчиков, пытающихся расшифровать загадочный код, расширяя адаптацию для новых разработчиков, у которых есть проблемы с пониманием кодовой базы, или выискивая ошибки, возникающие в результате несоответствий или непонимания в кодовой базе.
По своей сути написание чистого кода — это написание интуитивно понятного кода, а самый интуитивно понятный код — это код, максимально приближенный к письменной английской прозе. Каждый момент вашему мозгу приходится останавливаться и что-то соображать — будь то то, что означает аббревиатура, что делает функция или что именно происходит в этой тройке — это увеличение когнитивной нагрузки, которого можно избежать. А более высокие когнитивные нагрузки приводят к тому, что у разработчиков остается меньше энергии, чтобы сосредоточиться на решении проблем, а также увеличивается вероятность совершения ошибок и появления ошибок.
Книга «Чистый код» посвящена бэкенд-разработке; однако эти принципы могут быть применены и к внешнему кодированию. Вот (количество) способов применить эти принципы к интерфейсной разработке и начать писать более чистый интерфейсный код уже сегодня.
Как написать чистый интерфейсный код
-
Используйте описательные имена. Решая, как называть переменные и функции, используйте более длинные и описательные имена — мы хотим, чтобы наш код был максимально похож на письменную прозу. Избегайте сокращений. Особенно избегайте аббревиатур, если интуитивное произношение аббревиатуры отличается от ее сокращения. Например, я вижу «char» как часто используемое имя переменной. Наш мозг произносит это «char», тогда как первый слог слова «character» произносится как «care», поэтому каждый раз, когда разработчик читает это, ему приходится останавливаться и думать, что это значит. Кроме того, более длинные имена обычно легче найти (и легче запомнить), если вам нужно искать в репозитории.
n Некоторые примеры приведены ниже. Обратите внимание, как в крайнем правом столбце, даже не видя кода, мы имеем гораздо более четкое представление о том, что делает функция. Если мы работаем с новым файлом кода, нам не нужно помнить, что делает handleClick() в этом файле (часто, если он используется один раз в репо, то же имя функции используется и в других компонентах). .
| let char = ‘a’
| let character = ‘a
’ | let selectedCharacter = ‘a’
|
|----|----|----|
| handleClick(){}
| н | onLogoutClick(){}
|
| при отправке(данные)
| н | onNewCustomerSubmit(customer_data)
|
- Используйте короткие именованные функции. Ищите возможности разбить код на более мелкие функции. Таким образом, вы уменьшите количество длинных и сложных функций и вместо этого получите родительские функции, которые очень легко читать, потому что они имеют описательно названные функции, а сложность разбивается на более мелкие функции, что значительно облегчает понимание того, что происходит.
| function createCustomer(data) {
n data.creationDate = getFormattedCurrentDate()
n data.membershipCost = calculateProRatedMembershipCost()
n n let validatedData = validateFormData(data)
n submitForm(validatedData)}
n n function calculateProRatedMembershipCost() {...}
n function getFormattedCurrentDate() {... }
n function validateFormData(data) {...}
n function submitForm(data) {...}
|
|----|
- Сведите параметры к минимуму и пишите самодокументирующиеся имена функций. Если у вас более двух или трех параметров, вместо этого передайте объект с параметрами. Вы также можете использовать деструктурирование для принудительного применения правильно названных параметров в этом объекте. Если у вас есть параметры, включите их в имя функции (по порядку), чтобы пользователям не приходилось проверять исходный код или рисковать случайно указать параметры в неправильном порядке.
| getInstructions(user_id, group_id)
| getInstructionsByUserIdAndGroupId(user_id, group_id)
|
|----|----|
| getInstructions(user_id, group_id, date, user_role)
| getInstructions({user_id: user_id, group_id: group_id, date: date, user_role: user_role})
|
| getInstructions({ user_id, group_id })
| const active_user = { user_id: ‘john123,’ group_id: ‘234’, first_name: ‘John’, age: 23
n getInstructions(active_user)
|
- **Напишите условные операторы, похожие на прозу.**Разбивая условные операторы на отдельные функции, условные операторы становятся более интуитивно понятными. Многие разработчики предпочитают тернарные выражения операторам if/else; однако тернарии менее интуитивны (особенно для молодых разработчиков) и более склонны к неправильному толкованию.
- n Вложенные тройные числа очень трудно расшифровать, и их всегда следует избегать. Я знаю нескольких старших разработчиков интерфейсов, которые сказали, что могут легко читать вложенные тернарии, но это результат многолетней практики. Написание удобочитаемого кода означает, что вы пишете для будущих читателей, а не для себя, поэтому, если есть шанс, что младшие разработчики в конечном итоге будут читать код, придерживайтесь кода, который не требует многолетнего опыта для легкого усвоения.
| if (user !== null && user_role === ‘admin’ && user.active === true) {....}
| if (isUserValidated) {...}
n n function isUserValidated(user) {
n user !== null && user_role === 'admin' && user.active === true
n }
|
|----|----|
| {selectedObject === this.id ? «выбрано» : «скрыто»
| {выбрано? «выбрано» : «скрыто»
|
| {this.props.attendees.length ? this.renderTable() : this.renderNoAttendeesMessage() }
| if (areThereAttendees) {
n this.renderAttendeesTable } else {this.renderNoAttendeesMessage}
|
| const className = (isSelected && isAvailable) ? «выделено»: (доступно)? «по умолчанию»: «скрытый»;
n | let className = 'hidden';
n if (isSelected && isAvailable) {
n className= 'highlighted'
n } else if (isAvailable) {
n className='default' }
|
- Используйте комментарии с умом. Теоретически описательный код должен быть достаточно четким, чтобы не нуждаться в комментариях. Чувство, что вам нужно написать комментарий, может быть признаком того, что стоит еще раз взглянуть и попытаться написать код более понятным образом. Тем не менее, есть некоторые случаи использования, когда комментарии необходимы и не могут быть описаны в коде: если вы объясняете намерение, стоящее за кодом (возможно, вы выбрали между двумя стратегиями, и будущим разработчикам было бы полезно знать, почему одна из них была выбран), предупреждение о конкретных последствиях (иногда мы программируем, чтобы избежать последствий, которые слишком специфичны, чтобы включать их в имена функций), разъяснение запутанного кода, который вы не можете контролировать (например, функции RegEx всегда выглядят ошеломляющими, но мы, пользователи RegEx может это изменить).
- Эффективно используйте пустое пространство. Это отличный совет как для написания кода, так и для написания текстов в целом. Добавление пустых строк между абзацами прозы, а также между функциями помогает сделать текст менее утомительным для чтения. Кроме того, использование отступов легко и интуитивно сообщает читателям взаимосвязь между функциями. п
- Имейте определенные и легко находимые соглашения о кодировании. Многие крупные организации опубликовали свои руководства по стилю в Интернете, и это отличное место для начала. Определите формат имен (все ли переменные в верблюжьем регистре? Все ли файлы с символами подчеркивания (file_upload_component.js) и т. д.), а также любые другие соглашения о стилях. Рассмотрите возможность использования линтера, такого как ESlint или prettier, для обеспечения соблюдения этих стандартов, чтобы разработчики и рецензенты кода, которые сосредоточены на других частях кода, не пропустили эти небольшие ошибки. п
- Используйте расширитель CSS, например Less или Sass, чтобы писать более чистый CSS. Одним из основных аспектов сложности программного обеспечения является усиление: когда внесение изменений в код требует изменений в нескольких местах (увеличивается вероятность того, что вы пропустите какое-то место и возникнет ошибка). Переменные CSS позволяют вам, например, установить цвета бренда в переменные, поэтому, если ваша палитра бренда изменится, вам нужно будет изменить шестнадцатеричный код только в одном месте, а не просматривать несколько файлов CSS и изменять код во многих местах. Эти библиотеки включают в себя другие функции, такие как вложение и примеси, которые помогают очищать и организовывать CSS. п
- Стремитесь к СУХОМУ коду. Принцип DRY в программировании: каждая часть знания должна иметь единственное, недвусмысленное, авторитетное представление в системе. Менее подробный вариант: «Не повторяйся» (СУХОЙ). Не задавайте цвета вашего бренда в нескольких местах CSS; используйте переменную, чтобы установить ее один раз. Не используйте одну и ту же служебную функцию в нескольких файлах; создайте центральную функцию и используйте ее. Не выполняйте одни и те же вычисления с данными вашего активного пользователя в нескольких компонентах; выполнять необходимые вычисления в одной переменной, которая находится в магазине приложений и доступна для всех компонентов. Уровень сложности кодовой базы (и задачи) возрастает по мере того, как в большее количество мест нужно вносить изменения, а также повышает вероятность возникновения ошибок. Если вы пропустите одно из мест, где был старый цвет, некоторые области вашего сайта останутся в старом цвете. Если вы пропустите обновление одного из методов компонента для расчета данных, у вашего пользователя будут неправильные данные на одной странице. Сокращение количества повторяющихся кодов делает кодовую базу проще, устойчивее и легче в обслуживании. п
- Организуйте файлы проекта интуитивно понятным и простым способом. Знакомство с новой файловой структурой может оказаться непростой задачей, если вы новичок в репозитории, особенно если он большой и содержит много файлов. . Один проект, над которым я работал, начинался с использования структуры атомарных компонентов (атомы, молекулы и организмы для простых, средних и сложных компонентов), но через 6 месяцев проект стал настолько большим, что в каждой папке было более 20 компонентов. Многие из этих компонентов были похожи друг на друга, поэтому при взгляде на страницу не было бы очевидно, какой компонент в файле «молекул» был тем, на который они смотрели. В конечном счете, мы реорганизовали приложение, чтобы иметь общую папку компонентов для простых общих компонентов, а затем компоненты были организованы в зависимости от того, к какой странице они принадлежали (это был SPA только с примерно 5 страницами/просмотрами). Было намного проще понять, какой компонент вам нужен из 6 связанных компонентов, чем папка из 20, охватывающих широкий диапазон. Конечно, количество репозиториев со временем может увеличиваться несколько непредсказуемо, поэтому приверженность организованной, интуитивно понятной файловой структуре означает готовность к повторному просмотру и, возможно, рефакторингу приложения с течением времени.
Написание чистого кода не требует дополнительной работы; это просто требует смены парадигмы: пишите код для ваших будущих читателей, которые могут знать не так много, как вы, и сделайте его как можно более описательным и близким к письменной прозе. Репозиторий, написанный с чистым кодом, более устойчив и удобен в сопровождении с течением времени. Он сводит к минимуму потенциальные ошибки в будущем, упрощает их исправление, помогает начинающим и новым разработчикам, снижая когнитивную нагрузку, и в целом делает процесс разработки более плавным.
Дополнительные ресурсы:
Clean Code Роберта Мартина
n Фото Жантин Дорнбос на Unsplash
Оригинал