Sådan undgås protokollorientering besat programmering

ikon kredit til Aneeque Ahmed

For cirka et år siden fangede jeg WWDC-videoer fra 2015, da en bestemt konferencesamtale fandt min opmærksomhed. Det ser ud til at have fanget alles opmærksomhed. I betragtning af det Swift-relaterede indhold, der er skabt i det forløbne år, har scoringer af mennesker hoppet mod et radikalt nyt programmeringsparadigme.

Jeg henviser naturligvis til den forbløffende tale om protokollorienteret programmering præsenteret af David Abrahams. Hvis du ikke har set det endnu, og du skriver apps i Swift, er det absolut værd at tjekke ud! Seriøst, gør det nu.

Det følgende er ikke et forsøg på at dæmpe køligheden af ​​det, der blev præsenteret under denne tale. Protokoludvidelser, når de anvendes korrekt, er et vidunderligt værktøj med mange praktiske anvendelser, som vi vil gennemgå i slutningen af ​​denne artikel.

Problemet er noget, som vi alle er skyldige i (selv inkluderet bestemt). Når du har en skinnende ny hammer, er alt et søm.

Så i det sidste halvandet år har protokoller været hammeren, og vores projekter søm. Hvad lærte vi?

Genoprettelsen af ​​POOP

Det starter altid som et uskyldigt ønske om at lære noget nyt. Det er ikke alt for forskelligt fra at pakke ud, at Nintendo 64 til jul og opholder sig hele natten og spiller Goldeneye med dine søskende.

Ja, jeg er opmærksom på, hvor meget det daterer mig.

Uanset hvad, regner du med, at intet forhindrer dig i at refaktorere hele applikationen i disse genanvendelige protokoller, så du går til byen.

”Wow, du kan virkelig flytte alt fra en klasse til en protokol,” tænker du for dig selv. ”Har klasser endda et formål længere? Skal vi erstatte alt med strukturer? ”

Beruset med magt, dit hoved spinder ud af kontrol. Dine klasser og strukturer har ikke længere nogen synlige metoder i dem. De er kun en liste over protokollkonformationer. Du har forsikret dig selv, at det er sådan, de sjove børn gør det.

Protokolorientering Obsessed Programming er produktet af ønsket om at over-anvende protokoludvidelser, især i situationer, hvor de bare ikke er nødvendige.

POOP er en perfekt forståelig reaktion på et fantastisk nyt værktøj, men ligesom jeg har sagt før, er der altid kompromis med alt, hvad du gør i programmeringen. Det er aldrig nok blot at se på fordelene. Vi skal altid overveje omkostningerne.

Så hvad er fordelene med protokolorienteret programmering? Hvorfor ønsker vi måske at undgå impulsen til at refaktorere alt til protokoller og protokoludvidelser? Hvad gør POOP til at poope?

Det hele kommer ned på kodelæsbarhed.

Hvordan Protocol Orientation Obsessed Programming skader læsbarheden af ​​din kode.

Når du arbejder med et team af udviklere, er den største bidragyder til din succes effektiv kommunikation. Læsbar kode fører til bedre kommunikation. Ulæselig kode bremser teamet, fordi det tager mere tid for alle at finde ud af, hvad det gør.

Som udvikler i et team skal du altid stræbe efter at reducere den kognitive byrde, som din kode lægger på dine kolleger.

At have læsbar kode betyder mere end blot at vælge de rigtige klasse- og funktionsnavne. Det har meget at gøre med at præsentere den passende mængde information på et enkelt sted.

En anden udvikler burde ikke have noget problem med at finde ud af, hvad din kode gør bare ved at se på en fil.

Der er en betegnelse for dette. Vi kalder det lokal ræsonnement.

Det betyder, at folk skal kunne resonnere om din kode uden at skulle flytte fra sted til sted for meget. Det er en designfilosofi, der favoriserer eksplicit kode.

Når du skriver kode med det formål at bevare lokal ræsonnement, prøver du at undgå komplicerede klassehierarkier og design, der tvinger andre udviklere til at hoppe fra fil til fil bare for at få et mentalt billede af, hvad din kode gør.

Protokolorientering Obsessed Programmering er problematisk, fordi det gør lokal ræsonnement næsten umulig.

For bedre at forstå, hvorfor det er tilfældet, vil jeg bede dig om at behage

Den fantastiske eksploderende struktur

Lad os sige, at du har en grundlæggende Milkshake-struktur. Det har nogle variabler og funktioner, som du muligvis er bekendt med.

Nu er vi måske ikke nødvendigvis enige med de funktioner, der er tildelt vores Milkshake-struktur, men vi kan være enige om, at vi har et læseligt kodestykke her.

Det vil sige, at det hele er udtalt for os. Vi behøver ikke at se andre steder for at få en fornemmelse af, hvad denne struktur gør. Det er let at resonnere over.

Hvad ville der ske, hvis vi skulle refaktorere dele af vores Milkshake til nogle separate protokoller?

Det er ikke forfærdeligt. Teknisk fungerer det stadig ligesom vores anden strukturdefinition.

Desværre er det meget mindre læseligt.

Jeg forstår, at en erfaren programmør ikke burde have noget problem med at udlede, at min Milkshake-struktur erhverver sin evne til at transportere drenge til et gård via protokollkonformitet.

Denne konklusion er imidlertid ikke umiddelbart synlig. Den person, der læser koden, skal bruge lidt mental energi for at nå frem til den forståelse.

I en kontrolleret indstilling som dette fjollede lille eksempel er det fint. Men når du arbejder på et stort projekt med flere teammedlemmer, pålægger du omkostningerne for alle, der skal interagere med din kode. Det bremser projektet ned.

At tvinge folk til at tænke, når der ikke er nogen åbenbar fordel ved at gøre det, betyder lidt mere end at spilde alles tid. Kode som denne brænder tønder kontanter til jorden.

Det bliver meget værre, når du begynder at sende protokoller og udvidelser til separate filer. Medmindre du kommandoer klikker på hver af disse protokoller, har du ingen idé om, hvad denne struktur gør. Det dræber lokal ræsonnement.

Kom og tænk på det, udtrykket protokolorienteret tilsløring kan være mere passende i betragtning af dets tendens til at gøre kode mindre direkte.

Forskellen mellem POP og POOP.

Forhåbentlig har jeg ikke svingt din mening omvendt. Jeg har ikke til hensigt at sige, at vi skal kaste hænderne op og aldrig bruge protokoludvidelser igen. Jeg kan godt lide mit nye legetøj! Det gør fantastiske ting.

Jeg er kun ved at gøre noget ved en vis moderering. Lad os ikke være for hastige med anvendelsen af ​​protokoludvidelser. Fordi der er en kompromis med læsbarhed, bør vi være betyder når og hvor vi bruger dem.

POP bliver POOP, når vi holder op med at tænke på de underliggende årsager til, at en protokol kan hjælpe os. POOP er den blinde anvendelse af protokoller til alle situationer under den vildledte opfattelse, at protokoller altid er bedre end kedelige gamle strukturer og klasser.

Forhåbentlig har jeg overbevist dig om ellers. Lad os nu prøve at forstå nogle af fordelene ved protokoludvidelser.

Hvad får vi med protokoludvidelser?

Så hvorfor gennemførte vi al denne forretning med at gøre Swift til et protokollorienteret sprog? Hvad prøver vi i praksis at opnå ved at gøre det?

Kort sagt komposibilitet

Protokoludvidelser giver os en måde at dele funktioner og variabler mellem klasser og strukturer uden at bruge arv. Så længe to separate enheder deler de samme krævede egenskaber, får begge den nye opførsel. Det er sejt!

Inden vi havde protokoludvidelser, måtte vi oprette et separat objekt for at holde fast i den funktionalitet, vi ønskede at dele mellem dem. Vi kaldte det Objektsammensætning.

Den samme Milkshake ved hjælp af Objektsammensætning i stedet for protokoludvidelser

Masser af udviklere bruger stadig objektsammensætning i dag. Du bruger næsten helt sikkert det i dit arbejde.

Kan du huske den gang, du lavede en genanvendelig visning, som du lagde i en masse forskellige skærme på din app? Det er objektsammensætning.

Du tvang ikke dine synskontrollører til at arve fra en superklasse, der indeholder adfærden. Du komponerede din visningskontroller ud af genanvendelige dele, hvoraf den ene var din brugerdefinerede visning.

Med protokoludvidelser får vi en ekstra måde at komponere på. Nu kan nye adfærd tilføjes via protokolkonformitet i additon til objektsammensætning.

Det er et ekstra værktøj i vores bælte, og når det bruges korrekt, kan det gøre os mere produktive.

Nogle praktiske anvendelser til protokoludvidelser

I betragtning af at den primære fordel ved at bruge protokoludvidelser er komposibilitet, udgør det meste af de praktiske anvendelser at genbruge adfærd i lignende enheder. Hvis du finder ud af, at du har brug for den samme adfærd mere end et par steder, kan du overveje at bruge en protokoludvidelse for at undgå duplikering.

Årsag nr. 1. Flere enheder bruger den samme opførsel

Lad os gå tilbage til vores eksempel. Vi viste, hvordan vi kan udregne "SipBySipConsumable" -adfærden ved at flytte den til en protokoludvidelse. Selvfølgelig syntes det lidt dumt at gøre det, da der ikke er andre enheder, der bruger adfærden.

Men hvad nu hvis vi programmerede et slags spil, hvor formålet er at drikke alle slags forskellige drikkevarer? Ville det være så fjollet da?

Nix. Slet ikke.

Ved at flytte koden til en protokoludvidelse undgår vi behovet for at duplikere den samme adfærd igen og igen i alle andre drikkevarer-lignende enheder.

Husk, at vi altid skal overveje forholdet mellem omkostninger og fordel. Femten duplikationer af den samme funktion er meget sværere at vedligeholde end en enkelt implementering.

Så når mange ting har brug for den samme opførsel, kan vi acceptere den lette ding til læsbarheden.

POOP er resultatet af, at der ikke er nogen god grund til at flytte koden til en protokoludvidelse. POP er den fornuftige anvendelse af protokoludvidelser for at gøre kodebasen mere vedligeholdelig.

Årsag nr. 2. Vi har virkelig brug for enhedstest denne ting

Med protokoludvidelser får vi evnen til at udtrække adfærd fra de ting, der implementerer denne adfærd. Det betyder, at vi kan teste adfærden i et isoleret miljø, hvor ingen af ​​klassens eller strukturens afhængighed er bundet til at anvende.

Dette er en enorm velsignelse for enhedstestning. Det kan ikke overdrives.

Det betyder, at vores enhedstest suite kan bruge enklere enheder end dem, der bruges i vores produktionskode. Det gør effektivt enhedstest meget lettere. Hvis du er nysgerrig efter, hvordan det fungerer, så kig på min Easy Mocking With Swift Protocols-artikel.

På en relateret note bør protokolludvidelser ikke være en undskyldning for at TDD din codebase til absolut ruin. Enhedstest har deres egne afvejninger, hvilket er et andet emne, jeg drøfter i en separat artikel. Hvad skal vi enhedstest i vores iOS-apps?

Under alle omstændigheder, når det bliver meget tydeligt, at du skal enhedsteste noget, er protokoludvidelser et kraftfuldt værktøj til at gøre det.

Årsag nr. 3. Genbrug af den samme kode mellem iOS og MacOS

Protokoludvidelser, når de kombineres med tilknyttede typer, kan rive nogle store barrierer ned, når det kommer til deling af kode mellem forskellige operativsystemer.

Lad os sige, at du har en UIView-underklasse med en vis opførsel, som du vil overføre til MacOS-versionen af ​​din app. Desværre er Cocoa bare ikke det samme som UIKit. Det bruger NSViews, ikke UIViews. Underklassificering er ude af spørgsmålet.

Men med protokoller og tilknyttede typer kan du definere en opførsel, som både en NSView- og UIView-underklasse kan dele. Det gør kodebaser på tværs af platforme meget mere vedligeholdeligt!

Beklager, jeg har ikke skrevet en artikel om det endnu. Jeg får fat på det. Når jeg gør det, vil jeg henvise til det her.

Lad dit sind blæses, men hold dit: i takt.

Vi lever i en fantastisk tid med fantastiske nye værktøjer, der kommer ud hvert år. Vi har al grund til at være ophidset, men vi har også masser af grunde til at temperere noget af denne begejstring.

Protokolorienteret programmering og Swift baner vejen mod en ny æra med programmering. Det kan være en multiplikator på vores produktivitet, eller det kan være en lukke, som vi hænger os sammen med.

Så længe vi prioriterer kodelæsbarheden frem for alt andet, laver vi nogle apps, der POP og undgår at træde i en stor bunke POOP.

Jeg håber, at du havde det så sjovt at læse dette, som jeg havde skrevet det. Hvis du nød denne historie, skal du være enig i den, være uenig i den og ønske at stumme mig stille, indtil alle dine overbevisede handlinger kulminerer i et øjeblik med mordisk raseri, eller du synes det bare var nyttigt, kan du anbefale og følge!

Support praktisk iOS-udvikling

Kan du lide det, du ser? Sparede jeg dig tid?

Hvis det er tilfældet, skal du tage et øjeblik og støtte mig på Patreon.

Som et støttemedlem får du eksklusiv adgang til indhold, en afstemning om de dækkede emner og på de højere niveauer et "hjælp mig med at få unstuck" -pas, hvor jeg personlig vil hjælpe dig med at løse et problem med din iOS-app.