Когда разработчик проводит code review, ему редко хватает времени вникнуть в каждую строку: приходится быстро продумывать различные ситуации, в которых этот код может не работать. При анализе существует несколько моментов, на которые стоит обращать внимание, чтобы быстро понять, как именно код работает. Подсмотрели у Nirmalya Ghosh несколько приемов, как сделать javascript-код изящнее при создании компонентов с помощью библиотеки React. Хотя у нас есть свои особенности разработки в ЕФС, о которых вы можете прочитать в этой статье, некоторые из описанных под катом приемов мы находим интересными. Читаем и обсуждаем в комментариях!
Prop-types — модуль для проверки типов React-свойств и аналогичных объектов в режиме runtime. Prop-types проверяет переданное в компонент свойство на соответствие нужному типу.
Если тип переданного в компонент свойства не соответствует описанию, в консоли браузера появится предупреждение. В приведенном выше примере консоль выдаст следующее предупреждение:
Из этого сообщения следует, что в компонент Hello передается свойство message типа string, хотя предполагается array.
Строка displayName используется в отладочных сообщениях. Если вы еще не использовали displayName в своих компонентах, обязательно попробуйте!
Как правило, при отладке кода с помощью расширения React developer tools вы видите в нем компоненты, чьи имена берутся из названия функции или класса, описывающего компонент. Однако, если у вас два компонента с одинаковым именем (button, dropdown и т.п.), то вам, скорее всего, придется переименовать один из них. В противном случае, вы не сможете их различить.
displayName решает эту проблему — компонент можно переименовать, задав ему это свойство. В приведенном примере несмотря на то, что класс называется Component, в расширении React developer tool вы увидите имя Hello, потому что Hello — это его displayName.
Этот прием очень полезен для отладки, но его часто недооценивают.
Если вы заботитесь о чистоте кода, вам следует использовать linter для его проверки. Подобные инструменты помогают унифицировать стиль кода в вашей команде: если строго следовать заданным правилам, кодовая база всегда будет единообразной.
Например, можно взять за правило использовать точку с запятой в конце строки. Если разработчики не будут следовать этому правилу, linter выдаст сообщение об ошибке или предупреждение в зависимости от ваших настроек.
Наиболее известный linter — ESLint, но вы можете использовать любой другой инструмент, подходящий для вас.
Многим из вас это известно — первая итерация не всегда самая лучшая. Следует внимательно проверить свой первоначальный код и подумать о том, что вы могли упустить. Одним из способов проверки является использование отличной, но редко применяемой техники Test Driven Development (TDD). При использовании этого подхода первая итерация может стать лучшей. Подумайте о том, что вы собираетесь сделать до того, как напишете первую строку кода, а когда внедрите новый функционал или исправите ошибку — посмотрите на внесенные изменения и подумайте, как их улучшить.
Разбиение больших функций на более мелкие позволяет многократно использовать эти функции. Кроме того, небольшие функции проще тестировать. Чтобы избавиться от дублирования кода, повторяющиеся куски кода можно поместить в специальные служебные файлы.
После создания нескольких файлов с кодом, просмотрите, в них наверняка есть строки, которые дублируют друг друга. Их можно поместить в служебный файл, а затем использовать в других файлах.
Помимо этого, важно разделять один файл на множество маленьких. Анализировать один большой файл всегда сложнее, чем несколько более мелких. Если разбить код на несколько мелких файлов, каждый из которых содержит свою логику, просматривать эти файлы станет легче.
Еще один момент, который стоит запомнить: если вы будете называть свои файлы в соответствии с функционалом, который они содержат, это поможет вам и другим разработчикам лучше понимать, что на самом деле происходит в этом файле.
Например, dropdown.js — хорошее имя, но оно слишком общее, поэтому его использование для нескольких файлов в одной директории, например, topDropdown.js, bottomDropdown.js, — плохая практика.
В качестве префикса в названии файла лучше использовать задачу, которую должен выполнить код в файле. Например, userDropdown.js, fileDropdown.js и т.п.
Важность данного совета переоценить невозможно. После разработки нового функционала, вы надеетесь, что код работает — он на самом деле может работать. Но скорее всего, возникнут краевые условия, при которых он будет работать неправильно. Тесты помогут выявить подобные случаи.
Очевидно, что написание тестов увеличит время разработки, но при этом поможет устранить возможные ошибки и сэкономить время в будущем на их поиск и исправление.
Если вы заботитесь о качестве приложения, выделите время для написания тестов.
В React 16 появился эффективный способ обработки ошибок — Error Boundaries.
По сути дела, Error Boundaries — это React-компоненты, которые ловят ошибки в своих дочерних компонентах и выводят заменяющий код (fallback UI) вместо компонента, который сломался.
Если fallback-код присутствует в вашем компоненте ErrorBoundary, внутри него можно инкапсулировать свой компонент YourComponent:
Это отличный способ вывода резервного кода для ваших компонентов в случае ошибок. Однако, необязательно помещать все ваши компоненты внутрь ErrorBoundary. Вы можете разместить компонент ErrorBoundary лишь в нескольких особо важных местах кода.
Разрабатываете ли вы новый функционал или исправляете ошибки, высока вероятность спешки при отправке изменений и создании pull request.
Зачастую, разработчик не просматривает внесенные изменения, а значит не видит возможностей для улучшений, когда большие функции разумно разбить на более мелкие, а код разделить на модули. Привычка анализировать собственный код помогает улучшить его качество.
Мы специально вынесли этот совет в заключение, поскольку это одна из самых частых ошибок, которая затягивает ревью кода. Разработчик, открывший pull request, сам впервые видит общую картину всех изменений, после чего добавляет новые коммиты в ветку вместо того, чтобы сразу проверить свой код перед открытием pull request’а.
Надеемся, что описанные советы помогут сделать ваш код лучше! Приглашаем к обсуждению в комментариях.
Всегда используйте Prop-types для описания свойств ваших компонентов
Prop-types — модуль для проверки типов React-свойств и аналогичных объектов в режиме runtime. Prop-types проверяет переданное в компонент свойство на соответствие нужному типу.
Если тип переданного в компонент свойства не соответствует описанию, в консоли браузера появится предупреждение. В приведенном выше примере консоль выдаст следующее предупреждение:
"Warning: Failed prop type: Invalid prop `message` of type `string` supplied to `Hello`, expected `array` in Hello"
Из этого сообщения следует, что в компонент Hello передается свойство message типа string, хотя предполагается array.
Хотя если вам не нравится писать propTypes для каждого компонента, возможно использовать TypeScript, который позволит проверять совместимость компонентов не во время отладки, а прямо при компиляции проекта. В разработке Единой фронтальной системы мы используем TypeScript, так как скорость обратной связи существенно снижает стоимость разработки крупных проектов.
Используйте displayName для определения имени компонента
Строка displayName используется в отладочных сообщениях. Если вы еще не использовали displayName в своих компонентах, обязательно попробуйте!
Как правило, при отладке кода с помощью расширения React developer tools вы видите в нем компоненты, чьи имена берутся из названия функции или класса, описывающего компонент. Однако, если у вас два компонента с одинаковым именем (button, dropdown и т.п.), то вам, скорее всего, придется переименовать один из них. В противном случае, вы не сможете их различить.
displayName решает эту проблему — компонент можно переименовать, задав ему это свойство. В приведенном примере несмотря на то, что класс называется Component, в расширении React developer tool вы увидите имя Hello, потому что Hello — это его displayName.
Этот прием очень полезен для отладки, но его часто недооценивают.
Также в production-сборках вы можете не увидеть название компонентов в React DevTools, поскольку все названия компонентов обфусцируются. displayName позволяет отобразить название компонента и вам будет проще найти ошибку даже на боевой конфигурации.
Используйте linter для облегчения проверки вашего кода
Если вы заботитесь о чистоте кода, вам следует использовать linter для его проверки. Подобные инструменты помогают унифицировать стиль кода в вашей команде: если строго следовать заданным правилам, кодовая база всегда будет единообразной.
Например, можно взять за правило использовать точку с запятой в конце строки. Если разработчики не будут следовать этому правилу, linter выдаст сообщение об ошибке или предупреждение в зависимости от ваших настроек.
Наиболее известный linter — ESLint, но вы можете использовать любой другой инструмент, подходящий для вас.
Поскольку проекты на платформе ЕФС разрабатываются на TypeScript, в своей работе мы используем TSLint, проверки которого запускаютс при каждом Pull Request’е, что не позволяет влить в основную ветку код, не соответствующий принятому в команде code style’e.
Первая итерация не всегда самая лучшая
Многим из вас это известно — первая итерация не всегда самая лучшая. Следует внимательно проверить свой первоначальный код и подумать о том, что вы могли упустить. Одним из способов проверки является использование отличной, но редко применяемой техники Test Driven Development (TDD). При использовании этого подхода первая итерация может стать лучшей. Подумайте о том, что вы собираетесь сделать до того, как напишете первую строку кода, а когда внедрите новый функционал или исправите ошибку — посмотрите на внесенные изменения и подумайте, как их улучшить.
В Программе «Единая фронтальная система» существует несколько видов тестирования: помимо unit-тестов, построенных на стеке karma+jasmine, мы используем регрессионное тестирование со сравнением скриншотов, построенных на технологии gemini. Поскольку мы разрабатываем большие приложения, много внимания уделяем интеграционному тестированию. Не будем раскрывать в деталях, у кого есть релевантные кейсы или примеры давайте обсуждать в комментариях.
Структура проекта должна быть понятной
Разбиение больших функций на более мелкие позволяет многократно использовать эти функции. Кроме того, небольшие функции проще тестировать. Чтобы избавиться от дублирования кода, повторяющиеся куски кода можно поместить в специальные служебные файлы.
После создания нескольких файлов с кодом, просмотрите, в них наверняка есть строки, которые дублируют друг друга. Их можно поместить в служебный файл, а затем использовать в других файлах.
Помимо этого, важно разделять один файл на множество маленьких. Анализировать один большой файл всегда сложнее, чем несколько более мелких. Если разбить код на несколько мелких файлов, каждый из которых содержит свою логику, просматривать эти файлы станет легче.
Будьте очень внимательны, когда называете файлы
Еще один момент, который стоит запомнить: если вы будете называть свои файлы в соответствии с функционалом, который они содержат, это поможет вам и другим разработчикам лучше понимать, что на самом деле происходит в этом файле.
Например, dropdown.js — хорошее имя, но оно слишком общее, поэтому его использование для нескольких файлов в одной директории, например, topDropdown.js, bottomDropdown.js, — плохая практика.
В качестве префикса в названии файла лучше использовать задачу, которую должен выполнить код в файле. Например, userDropdown.js, fileDropdown.js и т.п.
Всегда пишите тесты для своего кода
Важность данного совета переоценить невозможно. После разработки нового функционала, вы надеетесь, что код работает — он на самом деле может работать. Но скорее всего, возникнут краевые условия, при которых он будет работать неправильно. Тесты помогут выявить подобные случаи.
Очевидно, что написание тестов увеличит время разработки, но при этом поможет устранить возможные ошибки и сэкономить время в будущем на их поиск и исправление.
Если вы заботитесь о качестве приложения, выделите время для написания тестов.
Не злоупотребляйте приемом для обработки ошибок
В React 16 появился эффективный способ обработки ошибок — Error Boundaries.
По сути дела, Error Boundaries — это React-компоненты, которые ловят ошибки в своих дочерних компонентах и выводят заменяющий код (fallback UI) вместо компонента, который сломался.
Если fallback-код присутствует в вашем компоненте ErrorBoundary, внутри него можно инкапсулировать свой компонент YourComponent:
<ErrorBoundary>
<YourComponent/>
</ErrorBoundary>
Это отличный способ вывода резервного кода для ваших компонентов в случае ошибок. Однако, необязательно помещать все ваши компоненты внутрь ErrorBoundary. Вы можете разместить компонент ErrorBoundary лишь в нескольких особо важных местах кода.
В разработке платфомы ЕФС мы используем Error Boundaries для централизованной обработки ошибок. Каждая из ошибок попадает на специальный REST-сервис, позволяющий в последующим проводить анализ ошибок, допущенных при разработке приложений.
Проверяйте ваш код до отправки pull request
Разрабатываете ли вы новый функционал или исправляете ошибки, высока вероятность спешки при отправке изменений и создании pull request.
Зачастую, разработчик не просматривает внесенные изменения, а значит не видит возможностей для улучшений, когда большие функции разумно разбить на более мелкие, а код разделить на модули. Привычка анализировать собственный код помогает улучшить его качество.
Мы специально вынесли этот совет в заключение, поскольку это одна из самых частых ошибок, которая затягивает ревью кода. Разработчик, открывший pull request, сам впервые видит общую картину всех изменений, после чего добавляет новые коммиты в ветку вместо того, чтобы сразу проверить свой код перед открытием pull request’а.
Надеемся, что описанные советы помогут сделать ваш код лучше! Приглашаем к обсуждению в комментариях.