Štiri pravila preprostejšega oblikovanja programske opreme iOS

V poznih devetdesetih letih prejšnjega stoletja je znani razvijalec programske opreme Kent Beck pripravil seznam pravil za preprosto oblikovanje programske opreme.

Po besedah ​​Kent Beck, dobra programska oprema:

  • Izvede vse teste
  • Ne vsebuje podvajanja
  • Izraža namero programerja
  • Minimizira število razredov in metod

V tem članku bomo razpravljali, kako lahko ta pravila uporabimo v svetu razvoja iOS, tako da bomo dali praktične primere za iOS in razpravljali o tem, kako lahko od njih imamo koristi.

Izvede vse teste

Načrtovanje programske opreme nam pomaga ustvariti sistem, ki deluje po načrtih. Toda kako lahko preverimo, ali bo sistem deloval, kot je sprva načrtovala njegova zasnova? Odgovor je z ustvarjanjem testov, ki ga potrdijo.

Na žalost se v vesolju iOS razvojnih testov večinokrat izognemo ... Toda, da bi ustvarili dobro zasnovano programsko opremo, bi morali vedno pisati kodo Swift s preverljivostjo.

Pogovorimo se o dveh načelih, ki lahko poenostavita pisno preizkušanje in oblikovanje sistema. In to so načelo enotne odgovornosti in vbrizgavanje odvisnosti.

Načelo enotne odgovornosti (SRP)

SRP navaja, da bi moral imeti razred eno in le en razlog za spremembo. SRP je eno najpreprostejših načel in eno najtežjih, ki bi lahko prišlo prav. Mešanje odgovornosti je nekaj, kar počnemo naravno.

Navedimo primer neke kode, ki jo je res težko preizkusiti, nato pa jo uporabite s pomočjo SRP-ja. Nato razpravite o tem, kako je koda naredila preizkus.

Recimo, da moramo trenutno predstaviti PaymentViewController s svojega trenutnega nadzornika pogledov, bi PaymentViewController konfiguriral svoj pogled glede na ceno našega plačilnega izdelka. V našem primeru je cena spremenljiva glede na nekatere zunanje uporabniške dogodke.

Koda za to izvedbo je trenutno videti naslednja:

Kako lahko preizkusimo to kodo? Kaj naj najprej preizkusimo? Ali je popust na ceno pravilno izračunan? Kako se lahko posmehujemo plačilnim dogodkom, da preizkusimo popust?

Pisanje testov za ta razred bi bilo zapleteno, morali bi najti boljši način za njegovo pisanje. No, najprej se lotimo velike težave. Odpraviti moramo svoje odvisnosti.

Vidimo, da imamo logiko za nalaganje našega izdelka. Imamo plačilne dogodke, ki uporabniku omogočajo popust. Imamo popuste, izračun popusta in seznam se nadaljuje.

Poskusimo jih preprosto prevesti v kodo Swift.

Ustvarili smo upravitelj plačil, ki upravlja z našo logiko v zvezi s plačili, in ločen PriceCalculator, ki ga je enostavno preizkusiti. Prav tako je nalagalec podatkov, ki je odgovoren za interakcijo omrežja ali baze podatkov za nalaganje naših izdelkov.

Omenili smo tudi, da potrebujemo razred, ki je odgovoren za upravljanje popustov. Recimo mu CouponManager in pustimo, da dobro upravlja s kuponi za popust uporabnikov.

Naš krmilnik pogleda za plačilo potem lahko izgleda tako:

Zdaj lahko pišemo teste, kot so

  • testPračunavanjeFinalPriceWithoutCoupon
  • testPračunavanjeFinalPriceWithCoupon
  • testCouponExists

in še mnogo drugih! Z ustvarjanjem ločenih predmetov se izognemo nepotrebnemu podvajanju in tudi ustvarimo kodo, za katero je enostavno pisati preizkuse.

Vbrizgavanje odvisnosti

Drugo načelo je vbrizgavanje odvisnosti. In iz zgornjih primerov smo videli, da smo že uporabili injekcijo odvisnosti od naših objektnih inicializatorjev.

Obstajata dve glavni prednosti vbrizgavanja naših odvisnosti kot zgoraj. Jasno je jasno, na katere odvisnosti se zanašajo naše vrste, in nam omogoča, da vstavimo posmehljive predmete, ko želimo preizkusiti namesto pravih.

Dobra tehnika je ustvariti protokole za naše predmete in zagotoviti konkretno izvedbo z resničnim in predrugačenim objektom, kot so naslednji:

Zdaj se lahko enostavno odločimo, kateri razred želimo vnesti kot odvisnost.

Tesno spenjanje otežuje pisanje testov. Torej, podobno več ko napišemo preizkuse, bolj bomo uporabljali načela, kot je DIP, in orodja, kot so vbrizgavanje odvisnosti, vmesniki in abstrakcija, da čim manj povežemo.

Izboljšava preizkusa kode ne odpravlja le strahu pred njeno kršitvijo (saj bomo napisali test, ki nas bo podkrepil), ampak tudi prispeva k pisanju čistejše kode.

Ta del članka se je bolj ukvarjal s tem, kako napisati kodo, ki jo bo mogoče preizkusiti kot pisanje dejanskega preizkusa. Če želite izvedeti več o pisanju enotnega testa, si lahko ogledate ta članek, kjer ustvarjam igro življenja s pomočjo testno vodenega razvoja.

Ne vsebuje podvajanja

Podvajanje je glavni sovražnik dobro zasnovanega sistema. Predstavlja dodatno delo, dodatno tveganje, doda nepotrebno zapletenost.

V tem razdelku bomo razpravljali o tem, kako lahko uporabimo vzorec oblikovanja predloge za odstranjevanje običajnih podvajanj v iOS-u. Da bi olajšali razumevanje, bomo preoblikovali izvedbo klepeta v resničnem življenju.

Recimo, da imamo trenutno v svoji aplikaciji standardni razdelek za klepete. Pojavi se nova zahteva in zdaj želimo uvesti novo vrsto klepeta - klepet v živo. Klepet, ki naj vsebuje sporočila z največ 20 znaki, in ta klepet izgine, ko zavržemo pogled klepeta.

Ta klepet bo imel enake poglede kot naš trenutni klepet, vendar bo imel nekaj različnih pravil:

  1. Omrežna zahteva za pošiljanje sporočil bo drugačna.

2. Sporočila v klepetu morajo biti kratka, največ 20 znakov za sporočilo.

3. Sporočila klepeta ne smejo obstajati v naši lokalni bazi podatkov.

Recimo, da uporabljamo arhitekturo MVP in trenutno obravnavamo logiko pošiljanja sporočil v klepetu v našem predstavitelju. Poskusimo dodati nova pravila za našo novo vrsto klepeta z imenom live-chat.

Naivna izvedba bi bila naslednja:

Toda kaj se zgodi, če bomo v prihodnosti veliko več klepetali?
Če bomo še naprej dodajali, če v vsaki funkciji preverjamo stanje našega klepeta, bo koda postala težko branje in vzdrževanje. Prav tako je težko preizkusiti, preverjanje stanja pa bi bilo podvojeno po celotnem obsegu predstavitelja.

Tu je v uporabi vzorec predloge. Vzorec predloge se uporablja, kadar potrebujemo več izvedb algoritma. Predloga je določena in nato nadgrajena z nadaljnjimi različicami. Uporabite to metodo, kadar mora večina podrazredov izvajati isto vedenje.

Lahko ustvarimo protokol za Chat Presenter in ločimo metode, ki jih bodo konkretni predmeti v fazah klepeta za predstavitev različno izvajali.

Zdaj lahko naš predstavitelj postane skladen z IChatPresenter

Naš predstavitelj zdaj obravnava pošiljanje sporočil tako, da pokliče skupne funkcije v sebi in prenese funkcije, ki jih je mogoče izvajati drugače.

Zdaj lahko zagotovimo Ustvari predmete, ki ustrezajo fazam predstavitelja, in te funkcije konfiguriramo glede na njihove potrebe.

Če v nadzornem pogledu uporabimo injekcijo odvisnosti, lahko zdaj isti krmilnik pogleda ponovno uporabimo v dveh različnih primerih.

Z uporabo oblikovalskih vzorcev lahko resnično poenostavimo svojo iOS kodo. Če želite o tem vedeti več, v naslednjem članku najdete nadaljnjo razlago.

Izraziti

Večina stroškov programskega projekta je v dolgoročnem vzdrževanju. Pisanje enostavnih za branje in vzdrževanje kode je nujno za razvijalce programske opreme.

Bolj ekspresivno kodo lahko ponudimo z dobrim testom poimenovanja, SRP in pisanja.

Poimenovanje

Številka ena stvar, zaradi katere je koda bolj izrazita - in to je poimenovanje. Pomembno je, da napišete imena, ki:

  • Razkrijte namero
  • Izogibajte se dezinformacij
  • Lahko jih je mogoče iskati

Pri poimenovanju razredov in funkcij je dober trik uporaba samostalnika ali samostalniške fraze za razrede in uporabniške glagole ali imena glagolskih fraz za metode.

Tudi pri uporabi različnih oblikovalskih vzorcev je včasih dobro, da v ime razreda dodate imena vzorcev, na primer ukaz ali obiskovalec. Bralec bi takoj vedel, kateri vzorec je tam uporabljen, ne da bi mu bilo treba prebrati vso kodo, da bi se tega naučil.

Uporaba SRP

Druga stvar, zaradi katere je koda izrazna, je uporaba načela enotne odgovornosti, ki je bilo omenjeno zgoraj. Lahko se izrazite tako, da ohranjate svoje funkcije in razrede majhne in za en sam namen. Majhne razrede in funkcije je običajno enostavno poimenovati, jih je enostavno napisati in jih je enostavno razumeti. Funkcija naj služi samo enemu namenu.

Pisni test

Pisanje testov prinaša tudi veliko jasnosti, zlasti pri delu s starejšimi kodami. Tudi dobro napisani enotni testi so izraziti. Primarni cilj testov je delovati kot dokumentacija na primeru. Nekdo, ki bere naše teste, bi moral biti sposoben, da bi hitro dojel, za kaj gre pri pouku.

Zmanjšajte število razredov in metod

Funkcije razreda morajo ostati kratke, funkcija mora vedno opravljati samo eno stvar. Če ima funkcija preveč vrstic, bi bilo to mogoče, če izvaja dejanja, ki jih je mogoče ločiti na dve ali več ločenih funkcij.

Dober pristop je šteti fizične črte in poskušati ciljati na največ štiri do šest vrstic funkcij, v večini primerov vse, kar presega to število vrstic, postane težko brati in vzdrževati.

Dobra ideja v iOS-u je sekanje konfiguracijskih klicev, ki jih običajno izvajamo pri funkcijah viewDidLoad ali viewDidAppear.

Na ta način bi bila vsaka od funkcij majhna in vzdržna, namesto ene funkcije zmešanega pogledaDidLoad. Enako bi moralo veljati tudi za pooblaščenca za aplikacije. Izogibajmo se metanju vsake konfiguracijske metode ondidFinishLaunchingWithOptions in ločenih konfiguracijskih funkcij ali še boljših konfiguracijskih razredov.

S funkcijami je malo lažje izmeriti, ali se držimo dolge ali kratke, večinoma se lahko samo zanesemo na štetje fizičnih črt. Pri pouku uporabljamo drugačno mero. Štejemo odgovornosti. Če ima razred le pet metod, to ne pomeni, da je razred majhen, lahko ima preveč odgovornosti le s temi metodami.

Znana težava v iOS-u je velika velikost UIViewControllers. Res je, da je z zasnovo krmilnika jabolčnega pogleda težko, da ti predmeti služijo enemu namenu, vendar se moramo potruditi.

Obstaja veliko načinov, kako narediti UIViewControllers majhno mojo prednost, je uporaba arhitekture, ki ima boljše ločevanje pomislekov, kot sta VIPER ali MVP, vendar to ne pomeni, da tudi pri jabolčnem MVC-ju ne moremo biti boljši.

S poskusom ločitve čim več pomislekov lahko dosežemo precej spodobno kodo s katero koli arhitekturo. Ideja je ustvariti enonamenske razrede, ki lahko služijo kot pomoč nadzornikom pregledov in kodo narediti bolj berljivo in preizkusljivo.

Nekaj ​​stvari, ki se jim preprosto izognemo brez opravičila pri pregledovanju regulatorjev, so:

  • Namesto da bi omrežno kodo napisali neposredno, bi moral biti NetworkManager razred, ki je odgovoren za omrežne klice
  • Namesto da manipuliramo s podatki v regulatorjih pogleda, lahko preprosto ustvarimo DataManager razred, ki je odgovoren za to.
  • Namesto da se igramo z nizi UserDefaults v UIViewController, lahko nad tem ustvarimo fasado.

V zaključku

Verjamem, da bi morali sestaviti programsko opremo iz komponent, ki so natančno imenovane, preproste, majhne, ​​odgovorne za eno stvar in večkratno uporabne.

V tem članku smo razpravljali o štirih pravilih za preprosto oblikovanje Kent Beck in podali praktične primere, kako jih lahko izvajamo v razvojnem okolju iOS.

Če ste uživali v tem članku, ne pozabite ploskati in pokazati svojo podporo. Sledite mi in si oglejte še veliko člankov, ki bodo vaše znanje iOS Developer dvignili na novo raven.

Če imate kakršna koli vprašanja ali komentarje, lahko tukaj zapišete sporočilo ali mi pišete na e-naslov arlindaliu.dev@gmail.com.