Предисловие

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

Я Андрей Рик, fullstack разработчик с 10+ лет опыта коммерческой разработки, множество стартапов разработал в различных командах, и несколько стартапов разработал в одиночку, в т.ч. своих собственных. Примеры кода я буду демонстрировать на React/Next, в то же время данный подход может быть применён к любому из языков программирования, и базирующихся на них фреймворках.

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

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

Оформляем код: как, и для чего?

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

Когда вы пишите код сразу опрятно, вы проявляете через себя определённое отношение - к своей рабочей деятельности, к процессу, к самому (самой) себе. Порядок в коде = порядок в душé (это же касается и рабочего места). Этот подход начинает транслироваться и на все остальные сферы вашей жизни, помогая вам практически во всём (это действительно так).

Это формирует определённый склад мышления, который можно развить в себе, даже если его изначально нет. Из состояния порядка (в голове, в делах, в конце концов в собственном коде) работа идёт проще и быстрее, чаще приходят светлые идеи, и общее состояние и восприятие мира существенно превосходит работу из состояния хаоса.

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

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

Вложенности в коде:

Все уровни вложенности в коде отделяем табуляцией (tab) и пустыми строками.

Что такое вложенности и уровни вложенностей?

Вложенности:

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

Уровни вложенностей:

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

Это касается и вёрстки, и функций, и стилей, и JSON-объектов, в общем всего кода.

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

Как настроить ширину TAB 2 пробела вместо 4х в Visual Studio Code:

Визуальное сравнение кода где TAB шириной 4 пробела и 2 пробела

Пример отделения вложенностей табуляциями и пустыми строками
Пример отделения вложенностей табуляциями и пустыми строками

Внутри кода одного и того же уровня вложенности пустая строка нам необходима только в двух ситуациях:

Когда следующая строка с кодом открывает новый уровень вложенности, или предыдущая строка с кодом закрывает новый уровень вложенности:

Пример, когда нужна пустая строка внутри одного и того же уровня вложенности
Пример, когда нужна пустая строка внутри одного и того же уровня вложенности
Пример, когда нужна пустая строка внутри одного и того же уровня вложенности
Пример, когда нужна пустая строка внутри одного и того же уровня вложенности

Вторая ситуация, когда мы можем добавить пустую строку - чтобы отделить логические группы кода внутри одного и того же уровня вложенности:

Пример отделения логических групп кода пустой строкой внутри одного и того же уровня вложенности
Пример отделения логических групп кода пустой строкой внутри одного и того же уровня вложенности

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

То есть концепция не в том, чтобы после каждой "не пустой" строки была пустая строка. Вот так, как на скрине ниже, делать НЕ надо:

Так делать НЕ надо! Концепция не в том, чтобы после каждой "не пустой" строки была пустая строка. Если на этом этапе концепция не понятна, перечитайте ещё раз содержимое статьи.
Так делать НЕ надо! Концепция не в том, чтобы после каждой "не пустой" строки была пустая строка. Если на этом этапе концепция не понятна, перечитайте ещё раз содержимое статьи.

Теперь разберём, когда нам следует создавать визуальные вложенности, а когда можно разместить вложенность в одной строке.

В одну строку мы можем записать вложенность, если её содержимое занимает мало места, и содержит не более 2х образно говоря пунктов:

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

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

В каких ситуациях это может быть актуально:

Когда компоненту передаётся много (более 1-2) props-ов (или HTML/JSX тегу - атрибутов), для наглядности не стоит писать их в одну строку!
Когда компоненту передаётся много (более 1-2) props-ов (или HTML/JSX тегу - атрибутов), для наглядности не стоит писать их в одну строку!
Когда у нас слишком длинный className, его не следует писать в одну строку, более того, можно разбить на логические группы/условия, каждые с новой строки. Смотрите сами, насколько код ниже нагляднее чем код выше (код выше так и вообще не умещается в поле видимости полностью)
Когда у нас слишком длинный className, его не следует писать в одну строку, более того, можно разбить на логические группы/условия, каждые с новой строки. Смотрите сами, насколько код ниже нагляднее чем код выше (код выше так и вообще не умещается в поле видимости полностью)
Когда мы деструктурируем много свойств из объекта
Когда мы деструктурируем много свойств из объекта

Основную суть оформления вложенностей я передал, ниже приведу несколько примеров, как с моей точки зрения оптимальнее оформлять код часто встречающихся приёмов:

Вариации классических If else
Оптимальный вариант занимающий минимум места, в то же время обеспечивая наглядность вложенностей
Оптимальный вариант занимающий минимум места, в то же время обеспечивая наглядность вложенностей

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

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

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

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

Наглядная сложная логика
Наглядная сложная логика

Тернарные условия "если && то" и "если ? то : иначе то" при выводе JSX
Подобное написание вывода компонента по условию даёт и чёткое понимание вложенности, и занимает минимум места
Подобное написание вывода компонента по условию даёт и чёткое понимание вложенности, и занимает минимум места
Подобный формат написания даёт чёткое понимание где начинается и заканчивается каждое условие, где начинается и заканчивается тот или иной результат условия
Подобный формат написания даёт чёткое понимание где начинается и заканчивается каждое условие, где начинается и заканчивается тот или иной результат условия

Имеет смысл написать часть условия в одну строку, когда либо всё выражение короткое, либо мы имеем дело с большой основной частью, которая выводится по условию, а если условие (верно/неверно) должна выводиться какая-либо малая, незначительная часть, и при этом малую часть мы пишем сверху выражения:

Пример вывода JSX через map, и примеры useEffect
Вывод JSX через map
Вывод JSX через map
Пример useEffect с объёмной вложенностью
Пример useEffect с объёмной вложенностью
Пример useEffect с короткой вложенностью
Пример useEffect с короткой вложенностью

Разделяйте функции, компоненты, стили по разным файлам

Не пишите стили в том же файле, в котором располагается код компонента (актуально для styled-components). Благодаря этому, когда вы исследуя код будете проваливаться в функции/компоненты (по клику на их название с зажатым ctrl или ⌘), вы не потеряете фокус с текущего компонента, скакнув на другую часть файла, а вместо этого откроется другой файл, который можно перетащить в отдельную секцию редактора кода, и работать одновременно с обоими файлами. Не пишите несколько компонентов в одном файле по этой же причине.

Тем более не создавайте компоненты внутри кода других компонентов - это мало того, что увеличивает объём кода (и сложность его восприятия) внутри одного файла, так ещё и с точки зрения оптимизации "не ок".

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

Здесь мы просто напихали всю вёрстку в один файл. Ну а что? И так работает же! (не делайте так)
Здесь мы просто напихали всю вёрстку в один файл. Ну а что? И так работает же! (не делайте так)
А тут мы разделили части страницы на компоненты, и взглянув на этот код сразу понимаем, что где находится. Нам легко удастся найти и изменить нужную секцию при необходимости.
А тут мы разделили части страницы на компоненты, и взглянув на этот код сразу понимаем, что где находится. Нам легко удастся найти и изменить нужную секцию при необходимости.

Не пишите "слипшийся код"

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

Старайтесь создавать компоненты и функции универсальными и пере-используемыми

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

Ни в коем случае не дублируйте код!

Создавайте более простые функции/компоненты, и расширяйте их за счёт функций/компонентов, которые базируются на функционале более простых (т.е. в них используются импортированные более простые функции/компоненты, и над ними строится логика, и эта совокупность в свою очередь является отдельной функцией/компонентом). Это тоже тема достаточно широкая, и в определённой мере является искусством. Если интересно и актуально для вас, можете написать об этом в комментариях, может как нибудь выкачу на эту тему отдельную статью.

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

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

Чистите код от "мусора"

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

Не используйте "магические числа"

Лучше создать "лишнюю" переменную, и назвать её по смыслу содержимого в ней значения. Просто сравните:

Что там слева за единица?? А вот справа сразу всё понятно, даже впервые взглянув на код!
Что там слева за единица?? А вот справа сразу всё понятно, даже впервые взглянув на код!
Сверху - "магические числа", которые ни о чём не говорят. Снизу - сразу всё ясно, к тому же провалившись в константу MATERIAL_TYPES можно будет увидеть, какие вообще есть значения, и к чему они относятся.
Сверху - "магические числа", которые ни о чём не говорят. Снизу - сразу всё ясно, к тому же провалившись в константу MATERIAL_TYPES можно будет увидеть, какие вообще есть значения, и к чему они относятся.

Желаю удачи в разработке проектов!

Пусть ваш код будет наглядным и понятным для вас и ваших коллег, и пусть порядок будет у вас везде - начиная с вашего кода, структуры проекта, рабочего места, и заканчивая вашей головой, и всеми вашими делами!

Даже если сейчас это не так, или не везде так.. Сделайте шаг навстречу позитивным изменениям. Начните с кода.

Всё вышеописанное является моим личным субъективным мнением и видением ситуации. Оно не обязательно должно совпадать с вашим мнением и видением.

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

Я буду дополнять статью, если вспомню ещё какие-либо примеры. Вообще есть ещё чем поделиться как по этой теме, так и вообще как в принципе. До встречи в следующих статьях!

Комментарии (54)


  1. aamonster
    25.07.2024 19:30
    +15

    Первый совет (про пустые строки в начале и конце каждого уровня вложенности) я бы отнёс скорее к вредным советам или по крайней мере к попытке навязать свой экзотический Code Style (приемлемо, если вся команда его использует, но если нет – я бы крайне не рекомендовал внедрять). Не надо так.