Простые приёмы, которые сделают ваш код нагляднее
Предисловие
Доброго времени суток, коллеги! В этой статье я делюсь своим подходом к оформлению кода, и приёмами, которые позволят в первую очередь лично вам лучше воспринимать собственный код, и ориентироваться в нём, а также и другим людям, которые будут работать с этим кодом.
Я Андрей Рик, fullstack разработчик с 10+ лет опыта коммерческой разработки, множество стартапов разработал в различных командах, и несколько стартапов разработал в одиночку, в т.ч. своих собственных. Примеры кода я буду демонстрировать на React/Next, в то же время данный подход может быть применён к любому из языков программирования, и базирующихся на них фреймворках.
В процессе внедрения предложенных мной концепций, вы с высокой вероятностью можете столкнуться с тем, что код будет выглядеть непривычно для вас, и внутренняя консервативность будет подталкивать к тому, чтобы писать код «по старому».
Однако, можете мне поверить, если вы сможете позволить себе пройти через адаптацию, код не соответствующий данным концепциям оформления будет вызывать у вас отвращение, т.к. будет напоминать слипшуюся кашу трудную для восприятия. К тому же в статье я не просто описываю приёмы, но и рассказываю, для чего это нужно.
Оформляем код: как, и для чего?
Упорядоченный, опрятный, хорошо написанный для восприятия код помогает быстрее выявлять случайные ошибки, и позволяет глазам быстрее »парсить» код, что в целом ускоряет время выполнения задач. Кроме этого есть и ещё одно неочевидное, но существенное преимущество:
Когда вы пишите код сразу опрятно, вы проявляете через себя определённое отношение — к своей рабочей деятельности, к процессу, к самому (самой) себе. Порядок в коде = порядок в душé (это же касается и рабочего места). Этот подход начинает транслироваться и на все остальные сферы вашей жизни, помогая вам практически во всём (это действительно так).
Это формирует определённый склад мышления, который можно развить в себе, даже если его изначально нет. Из состояния порядка (в голове, в делах, в конце концов в собственном коде) работа идёт проще и быстрее, чаще приходят светлые идеи, и общее состояние и восприятие мира существенно превосходит работу из состояния хаоса.
Это работает только в том случае, если вы осознанно самостоятельно пишете код опрятно, а не полагаетесь на prettier, который должен «сделать это за вас», но в ряде случаев скорее мешает, чем помогает.
Не бойтесь потратить лишние силы на порядок и опрятность в своём коде. Когда вы уже научились писать опрятный код, вам не требуется прилагать для этого никаких дополнительных усилий — это происходит само собой, по другому вы уже не умеете. И вас ничто уже не заставит писать код так, как раньше.
Вложенности в коде:
Все уровни вложенности в коде отделяем табуляцией (tab) и пустыми строками.
Что такое вложенности и уровни вложенностей?
Вложенности:
Когда у нас есть открывающаяся скобка и закрывающаяся, всё что между ними считается вложенным в них. Когда у нас есть открывающийся и закрывающийся тег — всё что внутри является вложенностью этого тега. Когда мы пишем атрибуты тега внутри скобок самого тега — атрибуты тоже являются вложенностью в рамках скобок тега
Уровни вложенностей:
Как скобки, так и теги могут сами находиться внутри скобок или тегов, и в этот момент они по прежнему открывают новый уровень вложенности. Количество уровней вложенности не ограничено.
![f0bf29722fc7960b0343dc4a8d2be13e.png](https://habrastorage.org/r/w1560/getpro/habr/upload_files/f0b/f29/722/f0bf29722fc7960b0343dc4a8d2be13e.png)
Это касается и вёрстки, и функций, и стилей, и JSON-объектов, в общем всего кода.
Пример отделения вложенностей табуляциями и пустыми строками
Внутри кода одного и того же уровня вложенности пустая строка нам необходима только в двух ситуациях:
Когда следующая строка с кодом открывает новый уровень вложенности, или предыдущая строка с кодом закрывает новый уровень вложенности:
Пример, когда нужна пустая строка внутри одного и того же уровня вложенности
Пример, когда нужна пустая строка внутри одного и того же уровня вложенности
Вторая ситуация, когда мы можем добавить пустую строку — чтобы отделить логические группы кода внутри одного и того же уровня вложенности:
Пример отделения логических групп кода пустой строкой внутри одного и того же уровня вложенности
На этом ситуации, когда требуется отделять пустыми строками внутри одного и того же уровня вложенности, заканчиваются.
То есть концепция не в том, чтобы после каждой «не пустой» строки была пустая строка. Вот так, как на скрине ниже, делать НЕ надо:
Так делать НЕ надо! Концепция не в том, чтобы после каждой «не пустой» строки была пустая строка. Если на этом этапе концепция не понятна, перечитайте ещё раз содержимое статьи.
Теперь разберём, когда нам следует создавать визуальные вложенности, а когда можно разместить вложенность в одной строке.
В одну строку мы можем записать вложенность, если её содержимое занимает мало места, и содержит не более 2х образно говоря пунктов:
для подобного случая нет необходимости переносить эту вложенность на новую строку, и разделять пустыми строками
Здесь тоже нет необходимости переносить эти вложенности на новые строки, и разделять пустыми строками — т.к. содержимое вложенностей не занимает много места, и содержит не более 2х пунктов
Однако когда у нас во вложенности много элементов, гораздо нагляднее будет, если разместить каждый элемент на новой строчке.
В каких ситуациях это может быть актуально:
Когда компоненту передаётся много (более 1–2) props-ов (или HTML/JSX тегу — атрибутов), для наглядности не стоит писать их в одну строку!
Когда у нас слишком длинный className, его не следует писать в одну строку, более того, можно разбить на логические группы/условия, каждые с новой строки. Смотрите сами, насколько код ниже нагляднее чем код выше (код выше так и вообще не умещается в поле видимости полностью)
Когда мы деструктурируем много свойств из объекта
Основную суть оформления вложенностей я передал, ниже приведу несколько примеров, как с моей точки зрения оптимальнее оформлять код часто встречающихся приёмов:
Вариации классических If else
![Оптимальный вариант занимающий минимум места, в то же время обеспечивая наглядность вложенностей](https://habrastorage.org/r/w1560/getpro/habr/upload_files/36a/289/8f0/36a2898f0aa559d599917d3d3c8577d5.png)
Оптимальный вариант занимающий минимум места, в то же время обеспечивая наглядность вложенностей
Если по условиям выполняется что-то одно, и оно не занимает много места, можно записать таким образом:
![410b1b56226c3e70a1927141c5e8bc10.png](https://habrastorage.org/r/w1560/getpro/habr/upload_files/410/b1b/562/410b1b56226c3e70a1927141c5e8bc10.png)
Если вам необходимо например прервать выполнение функции, если не выполнено какое либо условие, а основная логика должна выполняться, если условие выполнено, вместо создания лишних вложенностей конструкцией if else, можно обработать невыполнение каждого условия одним лишь if, и на этом же уровне вложенности продолжить писать основную логику. Проще понять на примере — просто сравните два этих подхода:
![Код справа выглядит слишком объёмным и сложным, это отвлекает от сути, и такой код дольше воспринимается. Код слева реализует в точности то же самое, но выглядит лаконично и понятно.](https://habrastorage.org/r/w1560/getpro/habr/upload_files/e78/2fc/89a/e782fc89a52765a65e9829d14a48acd4.png)
Код справа выглядит слишком объёмным и сложным, это отвлекает от сути, и такой код дольше воспринимается. Код слева реализует в точности то же самое, но выглядит лаконично и понятно.
Если в if проверяется большое количество условий, имеет смысл визуально разделить их например вот так:
![Наглядная сложная логика](https://habrastorage.org/r/w1560/getpro/habr/upload_files/5e7/e9a/1a9/5e7e9a1a948ef366437e1df4df15245a.png)
Наглядная сложная логика
Тенарные условия «если && то» и «если ? то : иначе то» при выводе JSX
![Подобное написание вывода компонента по условию даёт и чёткое понимание вложенности, и занимает минимум места](https://habrastorage.org/r/w1560/getpro/habr/upload_files/752/564/97a/75256497a90365317e34fb7e7dcd8ebd.png)
Подобное написание вывода компонента по условию даёт и чёткое понимание вложенности, и занимает минимум места
![Подобный формат написания даёт чёткое понимание где начинается и заканчивается каждое условие, где начинается и заканчивается тот или иной результат условия](https://habrastorage.org/r/w1560/getpro/habr/upload_files/1fe/549/3af/1fe5493afe4331dcb5c73cd0e66cb44a.png)
Подобный формат написания даёт чёткое понимание где начинается и заканчивается каждое условие, где начинается и заканчивается тот или иной результат условия
Имеет смысл написать часть условия в одну строку, когда либо всё выражение короткое, либо мы имеем дело с большой основной частью, которая выводится по условию, а если условие (верно/неверно) должна выводиться какая-либо малая, незначительная часть, и при этом малую часть мы пишем сверху выражения:
![99f7d25c7914183c44057102d954a10e.png](https://habrastorage.org/r/w1560/getpro/habr/upload_files/99f/7d2/5c7/99f7d25c7914183c44057102d954a10e.png)
Пример вывода JSX через map, и примеры useEffect
![Вывод JSX через map](https://habrastorage.org/r/w1560/getpro/habr/upload_files/a21/480/463/a21480463aef6a929d8935a04fbb9560.png)
Вывод JSX через map
![Пример useEffect с объёмной вложенностью](https://habrastorage.org/r/w1560/getpro/habr/upload_files/261/528/c23/261528c2353d062dad19fe0da8299df3.png)
Пример useEffect с объёмной вложенностью
![Пример useEffect с короткой вложенностью](https://habrastorage.org/r/w1560/getpro/habr/upload_files/2b3/a97/de9/2b3a97de97e63527f3f6485b79231dfe.png)
Пример useEffect с короткой вложенностью
Разделяйте функции, компоненты, стили по разным файлам
Не пишите стили в том же файле, в котором располагается код компонента (актуально для styled-components). Благодаря этому, когда вы исследуя код будете проваливаться в функции/компоненты (по клику на их название с зажатым ctrl или ⌘), вы не потеряете фокус с текущего компонента, скакнув на другую часть файла, а вместо этого откроется другой файл, который можно перетащить в отдельную секцию редактора кода, и работать одновременно с обоими файлами. Не пишите несколько компонентов в одном файле по этой же причине.
Тем более не создавайте компоненты внутри кода других компонентов — это мало того, что увеличивает объём кода (и сложность его восприятия) внутри одного файла, так ещё и с точки зрения оптимизации «не ок».
Если у вас страница состоит из нескольких частей, которые можно выделить в самостоятельные компоненты — сделайте это, не пишите всю «вёрстку» в одном файле. После чего вызывайте эти компоненты — и вы увидите, как код стал в разы проще для понимания. Просто сравните:
Здесь мы просто напихали всю вёрстку в один файл. Ну, а что? И так работает же! (не делайте так)
А тут мы разделили части страницы на компоненты, и взглянув на этот код сразу понимаем, что где находится. Нам легко удастся найти и изменить нужную секцию при необходимости.
Старайтесь создавать компоненты и функции универсальными и переиспользуемыми. Подумайте, как меньшим количеством кода охватить и реализовать бОльшую часть функционала проекта, и когда.
Ни в коем случае не дублируйте код — создавайте более простые функции/компоненты, и расширяйте их за счёт функций/компонентов, которые базируются на функционале более простых (т.е. в них используются импортированные более простые функции/компоненты, и над ними строится логика, и эта совокупность в свою очередь является отдельной функцией/компонентом). Это тоже тема достаточно широкая, и в определённой мере является искусством. Если интересно и актуально для вас, можете написать об этом в комментариях, может как нибудь выкачу на эту тему отдельную статью.
Каждый файл с компонентом определённого типа, функцией, чем либо ещё, должен находиться в своей папке. Т.е. вы должны (для себя самого/самой) создать такую файловую структуру, чтобы чётко представлять, что если вам нужен какой то компонент, где его искать. Это очень широкая тема для отдельной статьи, по этой причине здесь я специально не раскрываю её, просто примите это как идею.
А вот для React/Next я уже написал статью об этом, так что кто разрабатывает на этом стеке, может на практических примерах посмотреть, что именно я имею в виду, и как лично я подхожу к организации понятной файловой структуры в проектах над которыми работаю.
Чистите код от «мусора»
Удаляйте неиспользуемые импорты, переменные, функции, лишние пустые строки (когда две и больше пустые строки, вместо одной), пустые строки внизу файла, комментарии, которые уже не приносят вам пользу, и закомментированные бэкапы кода, которые вам никогда не пригодятся (речь именно о случаях в которых этот код действительно не пригодится).
Не используйте «магические числа»
Лучше создать «лишнюю» переменную, и назвать её по смыслу содержимого в ней значения. Просто сравните:
Что там слева за единица? А вот справа сразу всё понятно, даже впервые взглянув на код!
Сверху — «магические числа», которые ни о чём не говорят. Снизу — сразу всё ясно, к тому же провалившись в константу MATERIAL_TYPES можно будет увидеть, какие вообще есть значения, и к чему они относятся.
Желаю удачи в разработке проектов!
Пусть ваш код будет наглядным и понятным для вас и ваших коллег, и пусть порядок будет у вас везде — начиная с вашего кода, структуры проекта, рабочего места, и заканчивая вашей головой, и всеми вашими делами!
Даже если сейчас это не так, или не везде так. Сделайте шаг навстречу позитивным изменениям. Начните с кода.
Всё вышеописанное является моим личным субъективным мнением и видением ситуации. Оно не обязательно должно совпадать с вашим мнением и видением.
Я описал пожалуй самые важные, с моей точки зрения, аспекты оформления кода, и обеспечению его наглядности. Использование данного подхода заметно влияет на моё восприятие кода, скорость работы, ощущение гармонии и удовольствия от процесса разработки. Если статья окажется полезной для вас — я очень рад.
Я буду дополнять статью, если вспомню ещё какие-либо примеры. Вообще есть ещё чем поделиться как по этой теме, так и вообще как в принципе. До встречи в следующих статьях!