Surfing the JavaScript Wave:Embracing incremental change in Real World Software Projects

JS-økosystemet bevæger sig fremad i et halsbrækkende tempo. Nye paradigmer, rammer og værktøjer frigives tilsyneladende hver dag. React Hooks er et nyligt eksempel på dette, hvor mange softwarehuse dropper værktøjer i et kapløb om at omskrive deres kodebase for at bruge de nye teknikker. Men hvad gør du, hvis du er i et lille team, der administrerer en kodebase i ikke-triviel størrelse, med begrænset tid til at investere i at forblive på den blødende kant?

At beslutte sig for at tage nye teknologier i brug er ikke en ligetil proces. Det er en konstant kamp om at afveje fordele og ulemper ved nye værktøjer og teknologier; i betragtning af både akkumulering af teknisk gæld, de potentielle risici ved tidlig adoption versus potentialet for enorme produktivitets- eller produktværdigevinster.

I scenarier i den virkelige verden er det ofte ikke hensigtsmæssigt at droppe værktøjer og omskrive al din eksisterende kode for at bruge noget nyt. Der skal findes en balance mellem at holde dine knive skarpe og stadig levere et konstant flow af forretningsværdi. Hvordan kan vi balancere disse to tilsyneladende inkompatible arbejdsgange?

Grib dit surfbræt og rid på bølgen...

En proces til inkrementel ændring

I Mobile &Practice-truppen på DataCamp har vi taget en metode til trinvis forandring til sig. Ved at bruge en kombination af enkle værktøjer og teknikker mener vi, at vi har en fleksibel tilgang til at holde kniven skarp, mens vi stadig leverer forretningsværdi til tiden:vi fokuserer på at frigøre potentiale gradvist.

Selvom vi ikke har en formel procedure, er der opstået et mønster over tid omkring disse trin.

  1. Lær og forstå
  2. Beslut og kommuniker
  3. Omfavn trinvist

Lad os se nærmere på, hvad det betyder.

Lær og forstå

Vi starter med en diskussion, fokuseret omkring målet om at nå frem til en beslutning om, hvordan vi kommer videre med et nyt teknisk tiltag. For eksempel, da React Hooks faldt, var vi begejstrede for mulighederne, men vi modstod fristelsen til at drikke Kool-Aid og stoppe produktudviklingen for at omskrive vores kodebase uden først at foretage et virkeligt kig på de faktiske fordele (Render Props - kan du huske dem?).

Vi starter med en udforskende fase med at lære om ny teknologi. Dette er ofte i form af par/mob-programmeringssessioner. Vi starter med et tomt lærred og sigter efter at få noget grundlæggende til at fungere ende-til-ende. Dette vil så udvikle sig til en yderligere session, hvor vi tager en eksisterende del af vores produktionskodebase og evaluerer, hvad der sker, hvis vi tilpasser den til at bruge den nye teknologi.

Vi stiller os selv vigtige spørgsmål:

  • Hvad er fordelene ved at gøre det på denne måde?
  • Er der nogen (skjulte) omkostninger?
  • Er dette en "viral" ændring - spreder den sig implicit til andre komponenter

Bare for at give dig en idé om, hvilken slags ting der er i omfang for disse sessioner, her er nogle nylige sessioner, vi har parret eller mobbet på:

  • React Hooks (og derfor funktionelle komponenter)
  • Ende-til-ende-test med Detox
  • Reduktion af "stilgæld" ved at bruge skrifttypeprimitiver
  • Strømlining af vores arbejdsgang med Docker Compose

Med vores nye erkendelser frisk i vores sind, kan vi træffe en beslutning om hvis og hvordan for at fortsætte.

Beslut og kommuniker

Når vi er tilfredse med fordelene/omkostningerne ved at indføre ny teknologi i vores kodebase, kan vi afstemme, hvordan vi vil omfavne den gradvist.

Vi formaliserede for nylig vores vedtagelse af Architectural Decision Records (ADR'er) som et værktøj til at tilpasse os og kommunikere vores beslutning om at indføre visse teknologier. Vi har endda en ADR for vores brug af ADR'er!

ADR er en simpel markdown-fil og introduceres i første omgang til kodebasen som et forslag i form af en PR. Ved at bruge en PR kan vi diskutere forslaget og videreudvikle vores fælles forståelse/viden omkring teknologien.

ADR vil gøre det klart, hvordan vi vil adoptere teknologien fremadrettet, og i mellemtiden dokumenterer værdien og omkostningerne, vi lærte om i "Lær &Forstå"-fasen. På denne måde kan fremtidige bidragydere (ofte vores fremtidige jeg) henvise til ADR'erne for at forstå konteksten bag en bestemt beslutning.

Omfavn trinvist

Her er den sjove del! Nu skal vi bruge teknologien i kodebasen. Så nu vil vi droppe alt og omskrive alt fra bunden? Forkert!

Ved at bruge nogle simple hyldeværktøjer og strategier kan vi sikre, at vi omfavner forandringen trinvist og bæredygtigt.

Brugerdefinerede fnugregler

Forudsat at omkostningerne er lave nok, er vi store fans af at introducere nye eslint-regler, som vi kan konfigurere som advarsler. Dette giver os mulighed for at vurdere vores fremskridt hen imod vores mål om fuldt ud at omfavne en ny tilgang over tid. Hvis en fnugregel ikke er tilgængelig for den særlige use-case, vi har, vil vi også overveje at skrive en selv.

For eksempel, hvis vi forlader en gammel måde at gøre ting på, kan vi bruge noget som react/forbid-elements regel for at markere gammeldags komponenter som forældede med en advarsel.

En anden god bivirkning ved at bruge lint-reglen-tilgangen er, at den egner sig til at rydde op, mens du går:Spejderreglen.

Spejderregel

Et af mine yndlingsprincipper i softwareudvikling er spejderreglen, der ofte citeres af onkel Bob (Robert C. Martin). Begrebet er meget simpelt:

Når det anvendes på vores metode til at omfavne inkrementelle forandringer, kan dette omskrives som noget som dette:

Når du trykker på ældre kode, der er relateret til den kode, du i øjeblikket arbejder på, skal du rydde op i den og opdatere den for at bruge dine moderne tekniske bedste praksisser.

Dette er vores vigtigste måde at omfavne ændringer gradvist:at sikre, at ny kode er skrevet til vores nye standard, mens vi refaktoriserer og opdaterer gammel kode, når og når vi rører ved den.

Et eksempel fra den virkelige verden:Funktionelle komponenter

Et eksempel fra den virkelige verden i DataCamp-mobilappen er vores anvendelse af funktionelle komponenter som en foretrukken tilgang til implementering af komponenter (selvfølgelig med nogle undtagelser).

Efter en grundig analyse og opnået en fælles forståelse af omkostningerne og fordelene ved at introducere Functional Components - og efterfølgende React Hooks - i vores kodebase, gik vi i gang med at introducere ændringer trinvist. Vi startede med at tilpasse os en ADR, der beskrev vores bedste praksis for udvikling af React-komponenter:med fokus på, hvorfor vi foretrækker funktionelle komponenter, fordelene (og ulemperne) ved at bruge dem frem for klassekomponenter, og hvornår der kan gøres undtagelser. Vi skitserede også vores tilgang til at adoptere dem i vores kodebase.

Der var mange tilfælde af, at klassekomponenterne allerede blev brugt, og vi kunne ikke retfærdiggøre at droppe værktøjer til at rette dem alle. I stedet fokuserede vi på at skrive nye komponenter udelukkende ved hjælp af den nye tilgang og vedtog en strategi for gradvist at reducere gælden over tid ved hjælp af en eslint-regel:

En advarsel vises, når en udvikler arver fra React.Component og der vil også blive produceret advarsler for alle eksisterende overtrædelser af denne nye regel. Dette giver os mulighed for at forhindre, at problemet bliver værre, samtidig med at det giver os mulighed for at overvåge reduktionen af ​​problemet over tid:

Bemærk, at vi også henviser til den tilsvarende ADR i selve advarslen:dette hjælper med at tydeliggøre ræsonnementet bag reglen for udviklere, der måske ikke er stødt på dette før, og også vores fremtidige jeg.

Ved at bruge en kombination af linting og spejderreglen som ovenfor er vi i stand til at sikre, at nye komponenter er skrevet til den nyeste standard, samtidig med at vi reducerer gælden/omfavner ændringen på tværs af resten af ​​kodebasen. Til sidst, når antallet af fnug-advarsler relateret til denne regel er lille nok, kan vi potentielt blot kort fokusere vores indsats på at reducere antallet til nul og gøre advarslen til en fejl for at forhindre tilbagegang på gælden.

Selvom dette eksempel er ret simpelt, håber jeg, at det hjælper med at demonstrere, hvordan processen kan bruges til at introducere trinvise ændringer på tværs af dine projekter med en klar overtagelsesstrategi, samtidig med at det fremmer klarhed for begrundelsen bag ændringerne. Ved at indføre ændringer gradvist er vi i stand til at følge med i den seneste udvikling af JS-økosystemet, samtidig med at vi undgår duds og stadig leverer forretningsværdi.

Konklusioner

I denne artikel har vi set på en simpel proces, som du kan anvende for at omfavne trinvise ændringer i din kodebase. Det er ikke tænkt som et ensartet mantra eller et dogmatisk mantra, men snarere som en løs ramme, som vi bruger til at omfavne trinvise ændringer i vores kodebase:

  1. Lær og forstå
  2. Beslut og kommuniker
  3. Omfavn trinvist

Det er ikke let at holde sig på forkant med den seneste udvikling fra JS-økosystemet. Fra et kommercielt softwareperspektiv er det en konstant afvejning mellem at holde din kniv skarp og stadig levere forretningsværdi. Men med den rigtige proces og et surfbræt kan du holde dig oven vande!

Er det en bølge, du også har surfet på? Fortæl os, hvilke teknikker og tilgange du har fundet på for at løse dette problem i kommentarerne...