Галоўная / Артыкулы / Як маленькія рашыянні накапліваюцца ў кодбэсах рэакт-проектаў з давгім тымчасам існавання

Як маленькія рашыянні накапліваюцца ў кодбэсах рэакт-проектаў з давгім тымчасам існавання

Падзесяць прыкметак адтрымання дапраў на React, якія працуюць гады: чытальны код, сконцентраваныя компаненты, стан у межах дзеінстэнцыі, лёгкія залежнасці, тэсты і манітараванне.

2206 слоў

Пачатак праекту на React — гэта простая частка. Настоямыя випробаванні наступаюць чераз месцы або гады, калі у дапрыягу стае больш паўтароў, больш функцый, больш учаснікаў і больш залежнасцей, а калькі „тымчасовых“ спосабаў рашэння таямна стануць ключовымі для функцыонавання. У такі момент сам React рэдка бывае прычыной; проблема заключаецца у тым, каб код заставаўся зрозумелым, калі ўсё навакол яго постаўляецца. У гэтым кяліку прадстаўлены падсумкі панздзесяця звычак, разгрупаваных па тых месцах, дзе на самай працоўцы накапліваюцца виткі на тыпаванне, ўжо каб вы моглі адразу з’явіць рашэнні, якія прыводзяць да проблем, перш чым код стане такім, які ніхто не хоча трагчыць.

Код, напісаны для наступнага чытача

Валіце явны код прахіткавым коду

Жыццёспадныя адназначальныя выразы, глыбокія абстракцыі і функцыі-памагчыкі, створаныя для дзесяткаў гіпатэтычных сцэнарыяў, здаюцца практычнымі калі вы іх пішаце. Чырэх месцаў пазней яны стаюць загадкай, часта для самага таго, хто іх напісаў, і ён больш не памятае прычыны.

Альтэрнатыва — це намерна просты код. Разглядзіце можлівасць атрыбутавання экрану статусам «загружаецца», «праця не выйшла» або «готава». Ранніе вярнення робяць кожны статус явным, по аднай умове за раз:

if (isLoading) {
  return <LoadingState />;
}

Бранш з адной змою таксама пастроены, а шлях успеху наступае ў канцы:

if (error) {
  return <ErrorState />;
}
return <Dashboard />;

Нічога тут не ўражае, і самэ гэта і є сэнсам: кожны можа за калькі секундаз зрозумець, який компонент і калі атрыбутуецца. У большай прыемлі, што таксама важна, як і ўражэнне чыннаго разработчыка, — гэта што наступны разработчык таксама быстра зрозумее ваш код.

Назвы — это дакументацыя, якая ніколі не становіцца застарэлай

Калі вы пісваеце код, назвы здаюцца дробным деталем, але чэрез паў года, калі вы яго дыбагаваеце, яны становяцца вельмі важлівымі. Пораўняйце пошук у базе коду для гэтага:

handleData()

з пошукам для гэтага:

calculateMonthlyRevenue()

Другая назва паведамляе вам, што вычысляе функцыя, прытымкі як вы адкрываеце файл. Большыя базы коду ў значнай меры являюцца каналамі комунікаціі межа разработчыкамі; точная назва выказвае намер, а нечыясная прыводзіць ка тому, што кожны чытач становіцца дэтективам.

Будзьце ажырлівы да загальных назв, якія з’яўляюцца пад тым прытымкам, калі спынваецца час:

data
item
temp
helper
value
thing

Так, thing сапраўды з’являецца ў рэальных базах коду. Корыстная правіла: якщо назва можа падходзіць аднакова добра для будзь-каго файла проекту, яна, верагодна, не дае достатню інфармацыю пра гэты файл.

Гранікі компанентаў і стану

Занадта вялікія компаненты стаюць дорогімі

Практычна кожны проект на React, які працуе дзеўяльгодзіны, з часам стварае компанент, які складаецца з чатырох цифраў лінакоў коду. Рэдка калі ён такі з самага пачатку — спачатку ў яго 150 лінакоў, потым дадаецца модальное вікно, пасля — фільтры, далей — зачытанне дадзеных, пасля — пераказы прав, і ўжо другое модальное вікно. У канцы канцоў, калі апусціцеся да файла, знайдзеце ўжо нешта такое:

Dashboard.tsx
1,247 lines

Компаненты такога размеру важкая для розумення, тэставання, паўтарнага выкарыстання і адлучэння прычын бягаўых канфліктав, а ўсёлякія змены ў іхах є рызыковыя, таму што любая змена можа паўзіць на стане, ад якога залежаць іншыя часткі файла. Раздзеляйце файлы раней, чым гэта стане неабходна. У змену на адны файл:

Dashboard.tsx

Разбійце экран на часткі, кожная з якіх будзе выпалняць адну задачу:

DashboardHeader.tsx
DashboardStats.tsx
DashboardFilters.tsx
RecentActivity.tsx
DashboardTable.tsx

Кожны файл тепер мае адну задачу і значна меньшы радыус вплыву. Практычны крэатар для такога рашэння: якщо не можете апісаць компанент за адна рэченне без калькі „і“, значы трэба яго раздзеліць.

Ўжывайце тыя шаблоны, якія вы вядзеце, а не тыя, якія сабе выдумваеце

Компаненты, якія можна ўжываць знову, — гарная ідея, але яе легка перэўжыць. Частая прычына неудачы — калі адны кнопкі намагаюцца выплявіць ролю ўсіх кнопак у продукце:

<UniversalButton
  type="primary"
  variant="rounded"
  size="medium"
  iconPosition="left"
  loadingStyle="spinner"
/>

Кожны новы параметр здаецца безнебяжным, але разам яны ствараюць величазнае количество варіянтав, якія ніхто не тестуе цэлысцю, і такі „ўжываны“ компанент у практыцы выходзіць менш зручным у ўжыцці, чым тры маленькія, спецыфічныя кнопкі. Ўжыванне знову є ценным; прычасна гэнералізацыя — ні.

Выделяйце спакульная абстракцыю толькі тады, калі бачыце, што патэрн дзейсна павтараецца, а не таму, што будучая сторанка можа яе патрабаваць. Як толькі такая потрэба з’явіцца, вы створыце абстракцыю на базе рэальных прыкладоў, а не заўважэнняў.

Распрацавайце стан па таму, дзе ён належыць

Кераванне станам часта прагрэшае непазначальна. Маленькія дапыткі пачынаюцца з стану компанентав:

useState()

Потым додаецца спяльны стан праз контэкст:

useContext()

І ў канцы канцоў проект з’яўляецца з Redux, калькама контэкстамі, локальным станом, станам URL і станам сервера адразу, без чыяснага адказу на тое, калькі з іх кантролюе саблейку. Кожны інструмент быў разумны, калі яго дадавалі; тут не хапае правілы пра тое, што куды патрабуецца.

Просты спосаб развярнуць порядак — групаваць станы праз ўжоў іх прыроду. Локальны UI-стан абходзіць такія рэчы:

modal open
dropdown selected
input value

Ён павінен застацца ўнутры компонента, які яго выкарыстоўвае. Стан сервера — это даны, якія знаходзяцца на бэкендзе і толькі кешуюцца ў браузеры:

users
products
analytics

Для такой категоріі следует выкарыстоўваць бібліятэку, прызначаную для запрашаў, кэшавання і паўтарнага аправеркі даўноўдзеных дадзенаў, а не копіюваць адпаведзі ручна ў глобальны сховішча. Якщо ваша команда расследжвае такі перакід, аспекты, якія трэба взяць у ўвагу, практычна раскрытыя ў нашай параболе React Query і Redux для керавання станам сервера. У падсумку, справжні глобальныя станы є малаколькі:

theme
authenticated user
app-wide preferences

Зменшыце галоўную групу станоў да мінімуму: кожны компонент можа чытаць або зменяць глобальны стан, таму чым менш яго, тым меньш багоў, якія здаюцца выходзіць нізвідзе. Фільтры, вкладкі і пагінацыя часта апавяжаны з URL, дзе яны застаюцца пасля перазавантажэння і можу быць аднародныя.

Структура і залежнасці

Зробіце структуру папак прыемнаю

Уявіце, што вы прыўязваецеся да проекта і знаходзіце гэта ў корні:

src/
components/
shared/
common/
helpers/
utils/
services/
core/
misc/
new/
new2/

Дзе павінен знаходзіцца новы компонент прафіля пользователя? Ніхто не можа сказаць, таму кожны разработчы выбірае інако, і структура продовжае зміняцца. Перакрытые каталогі, такія як shared, common, helpers і utils, паказваюць, што ніхто не выявіў, што означае кожны з іх.

Макет, адаснованы на функцыйях, усуне большую частку такой неяснасці, групаваючы код па той частцы продукту, якой ён служыць:

features/
  auth/
  dashboard/
  users/
  billing/

У межах кожной функцыйі невялікі, павтараючыся набор падкаталогоў дапамагае заставаць структуру знайомай:

components/
hooks/
services/
types/

Тепер кожны, хто працуе з білінгам, ведае, дзе знаходзіцца код білінгу, і практычна перапісва функцыяй стосуецца толькі аднаго каталога, а не дзесяці. Можна таксама викорыстоўваць іншыя структуры (дывісце наша парэльніцу структураў каталогаў у React); гэта, што важна, — правіла ўсёвыразныя і зафіксаваныя.

Спрыяйце будучай падтрымке кожнай залежнасці

Для дадавання пакета достатнек адной команды:

npm install something-cool

Косці пачынаюць давацца пазней: пакеты застаюцца невыкарыстанымі, прыносяць рэзкія змены, апавярнююць проблемы з безпекай і збільшуюць размер пакета, а ваша команда вынужданая продовжваць апдэйтаваць код, які ніхто з ўсіх не чытаў.

Таму, пры інсталяванні, спытайце ся, чырэйша ўсё-такі яго трэба. Пакет, які заўсёды эканоміць час або рашае справжняя складную проблему, напрыклад, карыстацца датамі з урахоўваннем часовых поясаў, заслуговыць на свое месца. А той, які проста перакладае стрынг, — няўжо.

Сістэмы захавання, якія растуць разам з прыемнікам

Апробавайце тыя процесы, якія нанесуць наўбольш шкоды, якщо ўздромляць

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

Вам не трэба пакрываць кожную деталь рэалізацыі. Сфокусавайцеся на тых процесах для корыстувальніка, дзе аўарія мае вельмі большыя наследкі:

  • входзжанне
  • процес адправкі замовлення
  • адасыланне важлівых форм
  • пераканання ў правах
  • расчыткі, ад якіх залежыць бізнес

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

Стараўсяцеся звернуць увагу на павольнае, накупованае пад upadku якосці працы

Большыя прыкладнення на React рэдка калі становяцца повольнымі пасля адной версіі. Якосць працы падупалае пасля кожнай нерозумной рашэння: вялікага залежнасця, вельмі большога адпраўленага зображэння, неканчатых перыядражэнняў компонентав, дзесяці запыткаў на аднам экране. Адныя ў другіяя можу прычыніць, што завантажэнне панелі керування будзе трываць пяць секунд, таму стараўсяцеся постаянна стежыць за:

  • перыядражэннямі компонентав, калі нічога з таго, што яны паказваюць, не змянілася
  • зростам розмеру пакета з кожной новай версіяй
  • тым, што адны і тыя ж запыткі адправляюцца больш чым раз на аднам экране
  • атрыбутамі окремых компонентав, якія павольна перыядражаюцца
  • дзяўгімі спісамі, якія паказваюцца без віртуалізацыі
  • вельмі большымі адпраўленымі зображэннямі

Маленькі успехі збіраюцьяся разам, а выявленыя проблемы на раннім этапе коштуюць значна менш, чым тыя, якія трэба шукаць пазней.

Намеравана створэнне „несчаслівага“ шляху

Большая частка зусілляў направляецца на „счаслівы“ шлях, дзе кожны запит успехае. У рэальных умовах з’яўляюцца перерывы ў з’язку, неудачы API, змены праваў доступу, а бэкенд вяртае данні, якіх ніхто не чакаў. Карыстальнікаві трэба показваць чыткае, зрозумелае поведамленне на кшталт „Мы не моглі завантажыць вашыя данні. Прабавайце зноў“, а не первасныя прычыны баго, такія як:

TypeError: Cannot read properties of undefined

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

Расследаванне проблем у рэальных умовах як частка разработкі

Выпуск продукту — гэта не канец работы. У рэальных умовах выяўляюцца проблемы, якіх ніколі не будзе пад час локальнай разработкі, і вам трэба маты можласць бачыць:

  • Памятківыя прычыны і месцы ўпынку
  • Запросы, якія выконваюцца медленней, чым планавалося
  • Выклікі API, якія збываюцца
  • Аб’ектывае выконанне сторанцы і взаімадзеяння
  • Тое, як людзі фактычна выкарыстоўваюць продукт

Без гэтага адчытынай пра баг ёсць проста „вядома, што вчора ўсё зламалася“. Адстэйкінг прычын багоў і контекстуальныя логі ператвараюць гэта на стэк-трейс і часовую пазначку, якія можна выкарыстоўваць для дзеяння.

Звычкі, якія дапамагаюць командзе заставацца скоординаванай

Ствараюце дакументацыю для людзей, якія вже ў камандзе

Дакументацыю часта спрыяжуць з простай роботай па перадачы інформаціі, але яна дапамагае всім у камандзе, особліва ў вопысах складных прав, нестандартнай архітэктуры, інтеграцый з трэцімі сторонамі і важлівых бізнес-правілах.

Няма патрэбы ў длігім кярыянце. Короткія прыметкі пра тое, як функцыонуе аутэнтыкацыя, як пераходзяць даны, дзе знаходзяцца основныя функцыі і чаму былі прынятыя ключовыя рашэнні, заўсёды эканаюць гады часу. Запыткі да первоначальнага разрабоўця стаюць безрэзультатнымі, калі ён пакідае проект, а ў давга трываючых праектах гэта завжды так і бывае.

Рефактораванне — это рутынная адзінка, а не прызнанне невыполнення задач

Рефактораванне не ўскладніця доказ таго, што первоначальны код быў паслабы. Зменяюцца трэбованні, каманды і продукты, і код, які падходзіў месяцы назад, можа больш не паспрацаваць для рашэння свайго завдання.

Апасцярожнае ставленне да таго, што «вось ужо працуе», ёсць небяспечным. Так сама працуе стол з трыма нагамі, пакуль хтось на яго не сядзе. Маленькія, рэгулярныя рефактораванні, падтрымваныя тэстамі, дапамагаюць контролаваць тэхнічны борг.

Адноснасты важнейшая, чым лячныя прагантаванні

Адзін разрабоўцы пішае ідэнтыфікаторы так:

camelCase

іншы ж воліць так:

snake_case

А трохі зусім іншыя кожныя калькі ствараюць новыя шаблоны компанентавання. Вялікія команды не можаць эфектыва працаваць, калі кожны файл паслухаецца толькі прабачанням яго автара, таму неабходна аўтаматызацыя еднаковасці за дапамою:

  • інструмента для прабачання коду з узгаданымі правіламі
  • аўтаматычнага форматара
  • дакументаваных правілаў называння
  • спяльных, пераглянутых шаблонов для частаўых задач

База коду должна выглядаць як адны проект, а не як дзесятак разработчыкаў, якія спарачуцца ўжо па структуре файлаў.

Выберыце архітектуру, якую ваша команда можа практычна выкарыстоўваць

Дыбаты пра архітектуру — гэта любімая разважальна дзеяльнасць: мікросервісы, монорепозытарыі, чыстая архітектура, дизайн, кераваны домэном, і ўсегда ёсць хтось, у каго є гатовыя дыяграмы. Але найболей суперфіцыйны варыянт не ўсегда яшчэ і найкращы. Хорашы выбар паспелвае тры критэрыя:

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

    Чаму гэта не ёсць захоплівым, і чаму гэта работае

    Доўгастралявая падтрымка зменяе значэнне таго, што такое «хорашая разработка»: скорасць напісання коду мае меншое значэнне, чым чытаемасць, прыемнасць будучых змян, патрэбы іншых разработчыкаў і працаванне продакту. Як чэрніца для роботы:

    • Компаненты застаюцца маленькімі і виконваюць адну функцыю.
    • Глобальны стан — це короткі, рэштытаваны список.
    • Назвы описваюць мету.
    • Кожны новы пакет мае сваю прычыну.
    • Структура папак следуе аднам задокументаваным правілу.
    • Рефактораванне ведзецца практычна без перапынэння.
    • У критычных траекторіях работы корыстніка є тэсты.
    • Праблемы ў продакцыі є виднымі.
    • У разы равных варыянтаў выграе простейшы.

    Этыя правілы не ўражаюць, і, верагатна, самэй гэтаму яны і трываюць. Па кансэпту структурных практык на рэвэле архітектуры, адзінайчы дзесяць прыемаў архітектуры, якія дапамагаюць падтрымваць код-базы фронтэнду працездатнымі гадамі.

    Ключовыя выводы

    • Большыя прыкладнення на React рэдка калі страждаюць з-за самага React; яны страждаюць чераз накупленне маленькіх спрыткаў: адна вялічезная складовая, адна таёмніца-функцыя, адна непатрэбная пакета, адзін хак, які мяў быць тымчасовым.
    • Працездатнась не можна дадаць пазней. Яна ўтвараецца з сумы багато маленькіх рашэнняў, якія прыменяюцца по аднаму.
    • Самы ўжо цэнаны момент для прыменення гэтых прыемаў — гэта ўсё раней, чым з’являюцца проблемы, калі раздзелэнне складовай чы адмова ад залежнасці ўсё ўсё коштае хвілінкі, а не тыдні.
  • Калі вас спакушае хыткая рашэння, памятаце, што чалавек, які будзе адтрымваць ўсё гэта за шасць месцаў, можа, вы самі, будзе павінен разумець, чаму ёна працюе без вашага ныявеснага контэксту.
  • Спадневаная літэратура