ಟೇಲರ್ ಸ್ವಿಫ್ಟ್ ಟ್ರಾವಿಸ್ ಕೆಲ್ಸೆ ಆಟ

ಟ್ರಾವಿಸ್ ಕೆಲ್ಸೆ

Ҳар як хатогиро чӣ гуна бояд ислоҳ кард – аз ҳад зиёд вокуниш нишон дод

Ҳар як хатогиро чӣ гуна бояд ислоҳ кард – аз ҳад зиёд вокуниш нишон дод


Ман як барномаи каме вибекод кардам ва чанд рӯз пеш ба хатогӣ дучор шудам.

Хатогӣ чунин рафт. Тасаввур кунед, ки як масир дар веб-барнома. Ин масир пайдарпайии қадамҳоро нишон медиҳад – аслан кортҳо. Ҳар як корт дорои тугмаест, ки ба корти оянда ҳаракат мекунад. Ҳама чиз хуб кор мекунад. Бо вуҷуди ин, ҳамин ки ман кӯшиш кардам инчунин аз он тугма ба сервер занг занед, ҳаракат дигар кор намекунад. Он ларза ва шикаста мешуд.

Ҳамин тавр, илова кардани занги дурдаст ба ҳар ҳол ҳаракатро вайрон кард.

Ман боварӣ надоштам, ки сабаби хатогӣ чист. Равшан аст, ки занги сервери дурдасти нав иловашуда (ки ман онро тавассути амалҳои React Router мекардам) ба ягон тариқ ба ман халал расонд. scrollIntoView занг занед. Аммо ман гуфта наметавонистам, ки чӣ тавр. Ман дар аввал фикр мекардам, ки мушкилот дар он буд, ки React Router саҳифаи маро аз нав намоиш медиҳад (амал боиси барқароркунии маълумот мегардад), аммо аслан ягон сабабе вуҷуд надорад, ки барқароркунӣ ба гардиши ҷорӣ халал мерасонад. Сервер ҳамон ашёро бармегардонд, бинобар ин он набояд чизеро тағир диҳад.

Дар React, коркарди дубора бояд ҳамеша бехатар бошад. Чизи дигар хато буд – ё дар коди ман, ё дар React Router, ё дар React, ё ҳатто дар худи браузер.

Чӣ тавр ман ин хатогиро ислоҳ мекунам?

Оё ман метавонам ба Клод муроҷиат кунам, ки онро ислоҳ кунад?


Ман ба Клод гуфтам, ки мушкилотро ҳал кунад.

Клод чанд чизро кӯшиш кард. Он шартҳоро дар он аз нав навиштааст useEffect ки дар бар мегирад scrollIntoView занг зада гуфт, ки хатогӣ ислоҳ шудааст. Аммо ин кумак накард. Он гоҳ кӯшиш кард, ки тағир диҳад smooth ҳаракат кардан ба instantва чанд чизи дигар.

Ҳар дафъа Клод бо ифтихор изҳор мекард, ки мушкилот ҳал шудааст.

Аммо ин тавр набуд!

Хатогӣ ҳанӯз дар он ҷо буд.

Чунин ба назар мерасад, ки ман аз Клод шикоят мекунам, аммо воқеан такони навиштани ин мақола дар он аст, ки ман мебинам, ки муҳандисони инсонӣ (аз ҷумла худам) ба ҳамон хатогиҳо роҳ медиҳанд. Ҳамин тавр, ман мехостам равандеро, ки одатан барои ислоҳи хатогиҳо пайравӣ мекунам, ҳуҷҷатгузорӣ кунам.

Чаро Клод борҳо хато мекард?

Клод борхо хато мекард, зеро он репро надошт.


А такрорё парвандаи такрористеҳсолкунанда, пайдарпаии дастурҳост, пас ҳангоми риоя шудан ба шумо роҳи боэътимоди муайян кардани он, ки хатогӣ ҳоло ҳам рух медиҳад ё не. Ин “озмоиш” аст. A repro мегӯяд, ки чӣ бояд кард, чӣ интизор меравад ба амал меояд, ва чй дар асл рӯй дода истодааст.

Аз нуқтаи назари ман, ман аллакай як репрои хуб доштам:

  1. Тугмаро пахш кунед.
  2. Дар интизор меравад рафтор ба поён ҳаракат мекард, аммо воқеӣ рафтори чархуште буд.

Ҳатто беҳтар, хатогӣ ҳар дафъа рӯй дод.

Агар такрори ман беэътимод мебуд (масалан, агар ин танҳо 30% кӯшишҳо рух дода бошад), ман бояд ё тадриҷан сарчашмаҳои гуногуни номуайяниро бартараф кунам (масалан, сабт кардани шабака ва масхара кардани он дар кӯшишҳои оянда) ё бо зарбаи ҳосилхезӣ зиндагӣ мекардам, ки бояд ҳар як ислоҳи эҳтимолиро борҳо санҷим. Аммо хушбахтона, репрои ман боэътимод буд.

Ва аммо, ба Клод, репрои ман аслан вуҷуд надошт.

Мушкилот дар он аст, ки “ҷабҳаҳои ҳаракаткунанда” аз репроам барои Клод ҳеҷ маъно надошт. Клод чашм ё роҳҳои дигари дарк кардани ҷиттерро надорад. Ҳамин тавр, Клод аслан амал мекард бе repro – он кӯшиш кард, ки хатогиро ислоҳ кунад, аммо барои тасдиқи он ҳеҷ чизи мушаххасе накард. Ин хеле маъмул аст, ҳатто барои беҳтарини мо.

Дар ин ҳолат, Клод натавонист repro-и маро маҳз пайравӣ карданд, зеро он ба экран “нигар” карда наметавонист (бо гирифтани чанд скриншот онро гирифта наметавонист). Пас, агар ман мехостам, ки Клод онро ислоҳ кунад, аввалин репрои ман номувофиқ буд. Ин метавонад бо Клод мушкиле ба назар расад, аммо ин дар асл ҳангоми кор бо одамони дигар ғайриоддӣ нест – баъзан хатогӣ танҳо дар як мошин ё барои корбари мушаххас ё бо танзимоти мушаххас рух медиҳад.

Хушбахтона, як ҳила ҳаст. Шумо метавонед як repro барои тиҷорат дигар то он даме, ки шумо худро бовар кунонед, ки он ба шумо барои пешрафт дар мушкилоти аслӣ кӯмак мекунад.

Ин аст, ки чӣ тавр шумо метавонед репрограммаи худро тағир диҳед ва баъзе чизҳоеро, ки бояд эҳтиёт кунед.


Тағйир додани репро, ки шумо бо он кор мекунед, ҳамеша хатар аст. Хавф дар он аст, ки репрои нав ба хатогии аслии шумо ҳеҷ иртиботе надорад ва ҳалли он беҳуда сарф кардани вақт аст.

Бо вуҷуди ин, баъзан иваз кардани репро ногузир аст (Клод наметавонад ба экрани ман нигоҳ кунад, бинобар ин ман бояд чизи дигареро пайдо кунам). Ва баъзан он барои итератсия хеле фоиданок аст (бигӯед, репро, ки даҳ сонияро мегирад, назар ба репрое, ки даҳ дақиқа мегирад, хеле арзишмандтар аст). Аз ин рӯ, омӯзиши тағир додани репрос муҳим аст.

Идеалӣ, шумо як репро ба репро оддӣтар, тангтар ва мустақимтар иваз мекунед.

Ин аст идеяе, ки ман ба Клод пешниҳод кардам:

  1. Ҷойгиркунии ҳуҷҷатро чен кунед.
  2. Тугмаро пахш кунед.
  3. Мавқеи гардиши ҳуҷҷатро бори дигар чен кунед.
  4. Дар интизор меравад рафтори он аст, ки делта вуҷуд дорад, ба воқеӣ рафтор ин аст, ки ҳеҷ чиз вуҷуд надорад.

Фикри ман ин буд, ки ин тақрибан ба мушкилоте, ки бо чашми худ дидаам, баробар аст. Гарчанде ки ин репро ҷиттерро ба даст намеорад, эҳтимолан ба поён ҳаракат накардан бо он алоқаманд аст. Ҳатто агар он на танҳо Мушкилот, онро мустақилона ҳал кардан меарзад.

Клод каме илова кард console.logс, саҳифаро тавассути Playwright MCP кушод ва дар атроф клик кард. Дар ҳақиқат, мавқеи чархзанӣ буд не сарфи назар аз пахш кардани тугма тағир меёбад.

Хуб, ҳоло Клод аст қодир аст, ки хатогиро тафтиш кунад!

Оё мо бо дарёфти репро тамом шудем?

Дар асл, мо не!

Як доми умумӣ бо танг кардани repro ин аст, ки шумо фикр кунед шумо як чизи хубе ёфтед, аммо воқеан репрои нави шумо мушкилоти ба ҳам алоқамандро, ки ба ҳамин тарз пешниҳод мекунад, сабт мекунад. Ин як хатои хеле гаронбаҳост зеро шумо метавонед соатҳои зиёдеро барои ҳалли мушкилоти дигаре, ки шумо мехоҳед ҳал кунед, сарф кунед.

Масалан, мумкин аст, ки Клод танҳо мавқеи ҳаракатро хонда бошад хеле барвактва ҳатто агар хато бошад буд ислоҳ шуда бошад, он ҳоло ҳам мавқеъро бетағйир “мебинад”. Ин хеле гумроҳкунанда хоҳад буд – ҳатто барои ислоҳи дуруст, санҷиш мегӯяд, ки он ҳанӯз хато аст ва Клод ислоҳи дурустро аз даст медиҳад! Ин бо муҳандисони инсон низ рӯй медиҳад.

Ин аст, ки чаро, вақте ки шумо як repro танг, шумо низ бояд тасдиқ, ки а мусбат натиҷа («ҳама чиз кор мекунад») ҳанӯз ҳам ҳаст имконпазир аст ки бо репро нав ба даст оваранд.

Инро бо мисол шарҳ додан осонтар аст.

Ман ба Клод гуфтам, ки занги шабакавиро шарҳ диҳад (ки дар аввал хатогиро ошкор кард). Агар репрои нав (“пайвандкуниро чен кунед, тугмаро пахш кунед, бори дигар ҳаракат кунед”) воқеан хатогиеро, ки ман ислоҳ кардан мехостам (“ҳаҷҷаҳои ҳаракат дар клик”) сабт кунад, мо бояд тағиротеро интизор шавем. аллакай тасдиқ карда шудааст барои ислоҳи ин хато (шарҳ додани занги амал) ба инчунин рафторро дар репрои нав ислоҳ кунед (мавқеъҳои ҳаракат акнун бояд гуногун бошанд).

Ва ҳамин тавр шуд! Дар ҳақиқат, муваққатан шарҳ додани занги шабакавӣ инчунин санҷиши Клод иҷро мекард – мавқеъҳои ҳаракатро муқаррар кард буданд акнун дигар.

Дар ин лаҳза, кӯшиш кардан лозим аст, ки кодро дар ҳар ду самт якчанд маротиба тағир диҳед (шарҳ диҳед, шарҳ диҳед) то боварӣ ҳосил кунед, ки ҳар як таҳрир натиҷаи такрории навро пешгӯӣ мекунад. (Инчунин бояд таҳрирҳои дигарро анҷом дод, то ҳар як таҳрири дуюм кор кунад.)

Андозаи ҳаракат ҳанӯз ҳам ба он занги шабакавӣ алоқаманд буд.

Ин ҳанӯз маънои онро надорад, ки repro нав ҳамон мушкилотро ифода мекунад. Он метавонад як чизи ба ҳам алоқаманд ё танҳо як қисми он бошад. Ин ҳамеша хатари тағир додани репро аст. Аммо, занги шабакавӣ, ки бо мавқеъи ҳаракат алоқаманд аст, ҳадди аққал аст мисли шубҳанок ҳамчун мушкилоти аслӣ (ҷиши ҳаракат) ва метавонист мустақилона ҳал карда шавад. Ин як сабаби кофӣ барои идомаи репрои нав аст.


Ман филиали нав таъсис додам ва аз Клод хоҳиш кардам, ки ҷараёни кори зеринро риоя кунад:

  1. Repro-ро иҷро кунед, то мавҷуд будани хатогиро тафтиш кунед.
  2. Аз рамзи мувофиқ чизеро хориҷ кунед (нест кардани ҷузъҳо, хориҷ кардани коркардкунандагони рӯйдодҳо, содда кардани шароит, хориҷ кардани услубҳо, хориҷ кардани воридот ва ғайра).
  3. Repro-ро дубора иҷро кунед, то боварӣ ҳосил кунед, ки оё хатогӣ ҳанӯз вуҷуд дорад.
  4. Агар хатогӣ ҳанӯз вуҷуд дошта бошад, тағиротро ворид кунед.
  5. Агар хато бошад не дар он ҷо, назарияеро дар бораи он, ки чӣ метавонист онро “ҳал кард” нависед ба иҷрои охирин баргардонед ва кӯшиш кунед, ки як пораи хурдтарро нест кунед.

Ман ба берун рафтанӣ будам, аз ин рӯ ба Клод гуфтам, ки онро нигоҳ дорад ва ором нашавад, то он даме, ки репро ба чизе, ки минбаъд кам карда намешавад – ҷузъи React бидуни китобхонаҳои иловагӣ (ҳатто React Router) ва мантиқи ҳадди ақал.

Вақте ки ман баргаштам, Клод барои ман якчанд парвандаҳои такрорӣ эҷод кард, аммо асабонӣ буд, ки ҳеҷ яке аз онҳо хатогиро нишон надоданд:

⏺ I've done extensive investigation and created three progressively more
  accurate minimal reproductions. All of them work correctly, but the real
  page fails. I've tested:
 
  - Plain React state updates
  - React Router revalidation
  - Component remounting
  - New object references
  - Synchronous loaders
  - Various dependency arrays
  - Multiple renders during scroll
 
  Everything I can think of has been tested and ruled out. The bug
  consistently reproduces in the real app but not in any repro. This
  suggests there's something very specific about the page
  environment that I haven't captured.
 
  The workaround (deferring network call with setTimeout) works reliably,
  which confirms that the issue is the timing between the
  mutation/revalidation and the scroll. But I cannot determine WHY React
  Router's revalidation breaks scrollIntoView in the real app when it
  doesn't in the repros.
 
  I've committed all the repros and investigation notes for future
  reference.

Оё ин маънои онро дорад, ки кам кардани хатогӣ на ҳама вақт кор мекунад?

Не.

Ин маънои онро дорад, ки Клод дастурҳои маро иҷро карда натавонист. Аммо ба роҳ ба онҳо пайравӣ накардан ҷолиб аст, зеро одамон (аз ҷумла ман) аксар вақт як хато мекунанд.

Ҳангоме ки Клод кодро содда мекард, он ташаккул ёфт назарияхо. Эҳтимол, ин таъсир бефосила аст. Мумкин аст, ки бо барқарорсозӣ чизе кор кунад. Шояд React як чизи аҷибе мекунад. Ва он сар шуд озмоиш ин назарияҳо, эҷоди ҳолатҳои ҷудогонаи такрористеҳсолкунӣ, ки ба онҳо тамаркуз кардаанд ва бубинанд, ки оё онҳо хатогиҳоро нишон медиҳанд.

Эҷоди назарияҳо ва озмоиши онҳо бузург аст! Мо бояд бешубҳа ин корро кунем.

Аммо боз ба дастурҳои ман нигаред:

  1. Repro-ро иҷро кунед, то мавҷуд будани хатогиро тафтиш кунед.
  2. Аз рамзи мувофиқ чизеро хориҷ кунед (нест кардани ҷузъҳо, хориҷ кардани коркардкунандагони рӯйдодҳо, содда кардани шароит, хориҷ кардани услубҳо, хориҷ кардани воридот ва ғайра).
  3. Repro-ро дубора иҷро кунед, то боварӣ ҳосил кунед, ки оё хатогӣ ҳанӯз вуҷуд дорад.
  4. Агар хатогӣ ҳанӯз вуҷуд дошта бошад, тағиротро ворид кунед.
  5. Агар хато бошад не дар он ҷо, назарияеро дар бораи он, ки чӣ метавонист онро “ҳал кард” нависед ба иҷрои охирин баргардонед ва кӯшиш кунед, ки як пораи хурдтарро нест кунед.

Як чизи мушаххасе ҳаст, ки ман кӯшиш мекардам, ки онро иҷро кунам. Он чизе ки мо кӯшиш мекунем, ки кафолат диҳем дар ҳар лаҳза, мо як гузаргоҳ дорем, ки хатогиҳо то ҳол вуҷуд доранд аст рӯй медиҳад ва бо ҳар қадам, мо майдони рӯи ин хаторо кам мекунем.

Клод аз озмоиши назарияҳои худ хеле саргарм шуд ва бо як қатор парвандаҳои санҷишӣ анҷом ёфт, ки дар асл хатогиро нишон намедиҳанд. Боз ҳам, санҷиши назарияҳои нав кори бад нест, аммо агар онҳо ноком шаванд, дуруст кор кардан ба парвандаи аслӣ баргаштан аст (ки то ҳол хатогиро нишон медиҳад!) ва бартараф кардани чизҳо то пайдо кардани сабаб.

Ин ба ман мафҳуми онро хотиррасон мекунад рекурсии асоснок. Ин кӯшиши амалӣ намудани а fib(n) функсияе, ки бояд рақамҳои Фибоначиро ҳисоб кунад:

function fib(n) {
  if (n <= 1) {
    return n;
  } else {
    return fib(n) + fib(n - 1);
  }
}

Дар асл, ин функсия хато аст – он то абад овезон мешавад. Ба хато навиштам fib(n) ба ҷои fib(n - 2)ва ҳам fib(n) занг мезанад fib(n)ки занг мезанад fib(n)ва ғайра. Он ҳеҷ гоҳ аз рекурсия берун нахоҳад шуд, зеро n харгиз «хурдтар» намешавад.

Забонҳое, ки мефаҳманд рекурсии асоснок намегузорад, ки ин хато кунам. Масалан, дар Lean, ин хатои навъи мебуд:

def fib (n : Nat) : Nat := /- error: fail to show termination for fib -/
  if n ≤ 1 then
    n
  else
    fib n + fib (n - 2)

Лин инро медонад n “хурдтар намешавад” (дақиқтар дар ин ҷо нигаред) бинобар ин медонад, ки ин рекурсия то абад овезон хоҳад шуд. Он «бо мурури замон наздик намешавад».

Ин як дастури Lean нест, аммо ман умедворам, ки шумо ин истиораи беақлро мебахшед.

Ман фикр мекунам, ки бо раванди кам кардани парвандаи repro ҳамин аст. Шумо инро донистан мехоҳед ту ҳамеша, хамеша пешравии афзоянда ва репро торафт хурдтар мешавад. Ин маънои онро дорад, ки шумо бояд боинтизом бошед ва пораҳоро оҳиста-оҳиста хориҷ кунед, танҳо то даме ки хатогӣ боқӣ мемонад. Дар баъзе лаҳзаҳо, шумо ҳатман чизеро, ки нест кардан лозим аст, тамом мекунед, ки ин ё хато дар коди шумо ё иштибоҳ дар қисмҳоеро, ки шумо минбаъд кам карда наметавонед (масалан, React) нишон медиҳад.

То он даме, ки шумо онро пайдо кунед, такрор кунед.


Клод ин масъаларо ҳал накард, аммо он маро хеле наздик кард.

Пас аз он ки ман ба он гуфтам, ки воқеан дастурҳои маро иҷро кунед ва танҳо хориҷ кунед чизҳо, он рамзи кофӣ хориҷ карда шуд, ки мушкилот дар як файл мавҷуд буд. Ман он файлро берун аз роутер кӯчондам ва ногаҳон ҳамон код кор кард. Пас аз он ман онро ба роутер баргардондам ва он боз шикаст. Баъд ман онро а сатҳи олӣ маршрут ва он кор кард.

Вақте ки он дар дохили тарҳбандии реша ҷойгир карда шуда буд, чизе мешиканад.

Тарҳбандии решаи ман чунин менамуд:

import { Outlet, ScrollRestoration } from "react-router-dom";
 
export function RootLayout() {
  return (
    <div>
      <ScrollRestoration />
      <Outlet />
    div>
  );
}

Аха. Маълум мешавад, ки қаблан як хатое вуҷуд дошт (аллакай дар моҳи июн ислоҳ карда шуда буд), ки боиси React Router шудааст ScrollRestoration на дар ҳар як тағирёбии масир, на дар ҳар як ревалидатсия фаъол созед. Азбаски занги шабакаи ман (тавассути амал) масирро дубора тасдиқ кард, он ба кор андохта шуд ScrollRestoration дар давоми scrollIntoViewбоиси ҷанҷол мегардад.

Ин ҷараёни дақиқи кор – як ба як нест кардани чизҳо ва таъмини он, ки хатогӣ ҳанӯз мавҷуд аст – хари маро борҳо наҷот дод. (Ман як маротиба дар як ҳафта барои нест кардани нисфи дарахти React-и Facebook сарф кардам, ки хатогиҳоро дунбол мекард. Нақшаи ниҳоӣ ~ 50 сатри код буд.) Ман ягон усули дигареро намедонам, ки пас аз тамом шудани назарияи шумо ин қадар самаранок бошад.

Агар ман лоиҳаро худам таъсис медодам, ман версияи охирини React Router-ро истифода мебурдам ва ба ин хатогӣ дучор намешудам. Аммо лоиҳа аз ҷониби Клод таъсис дода шуда буд, ки бо сабабҳои нофаҳмо тасмим гирифт, ки ман бояд версияи кӯҳнаи вобастагии асосиро истифода барам.

Хуб!

Шодии вибекодинг.

Leave a Reply