Keturios paprastesnės „iOS“ programinės įrangos projektavimo taisyklės

Dešimtojo dešimtmečio pabaigoje, kurdamas ekstremalųjį programavimą, garsus programinės įrangos kūrėjas Kentas Beckas pateikė paprastos programinės įrangos projektavimo taisyklių sąrašą.

Pasak Kento Becko, geras programinės įrangos dizainas:

  • Vykdo visus testus
  • Nėra kopijavimo
  • Išreiškia programuotojo ketinimą
  • Sumažina klasių ir metodų skaičių

Šiame straipsnyje aptarsime, kaip šias taisykles galima pritaikyti „iOS“ kūrimo pasaulyje, pateikdami praktinius „iOS“ pavyzdžius ir aptardami, kaip mes galime iš jų gauti naudos.

Vykdo visus testus

Programinės įrangos dizainas padeda mums sukurti sistemą, veikiančią kaip numatyta. Bet kaip mes galime patikrinti, ar sistema veiks taip, kaip iš pradžių numatė jos dizainas? Atsakymas yra sukuriant testus, kurie tai patvirtina.

Deja, „iOS“ kūrime visatos bandymų dažniausiai nepavyksta… Bet norėdami sukurti gerai suplanuotą programinę įrangą, visada turėtume rašyti „Swift“ kodą, turėdami omenyje patikrinamumą.

Aptarsime du principus, pagal kuriuos testų rašymas ir sistemos kūrimas gali būti paprastesni. Tai yra vienas atsakomybės principas ir priklausomybės injekcija.

Vienos atsakomybės principas (SRP)

SRP teigia, kad klasė turėtų turėti vieną ir tik vieną priežastį pasikeisti. SRP yra vienas iš paprasčiausių principų ir vienas iš sunkiausių teisingai suprasti. Sumaišome atsakomybę - tai kažkas, ką mes darome natūraliai.

Pateiksime kažkokio kodo, kurį iš tikrųjų sunku išbandyti, pavyzdį, o po to jį atnaujinkite naudodami SRP. Tada aptarkite, kaip tai padarė kodą išbandomu.

Tarkime, kad šiuo metu turime pateikti „PayViewController“ iš dabartinio rodinių valdiklio, „PaymentViewController“ turėtų konfigūruoti savo rodinį atsižvelgdama į mūsų mokėjimo produkto kainą. Mūsų atveju kaina yra kintama, atsižvelgiant į kai kuriuos išorinius vartotojo įvykius.

Šiuo metu šio diegimo kodas atrodo taip:

Kaip mes galime patikrinti šį kodą? Ką pirmiausia turėtume išbandyti? Ar teisingai apskaičiuota kainos nuolaida? Kaip galime tyčiotis iš mokėjimo įvykių, norėdami išbandyti nuolaidą?

Rašyti testus šiai klasei būtų sudėtinga, turėtume rasti geresnį būdą tai parašyti. Na, pirmiausia pažiūrėkime į didelę problemą. Turime išardyti savo priklausomybes.

Matome, kad turime logiką įkelti savo produktą. Turime mokėjimo įvykių, kurie vartotojui suteikia teisę į nuolaidą. Mes turime nuolaidų, nuolaidų skaičiavimą ir sąrašas tęsiasi.

Taigi pabandykime tai paprasčiausiai išversti į „Swift“ kodą.

Sukūrėme „PaymentManager“, kuris tvarko mūsų logiką, susijusią su mokėjimais, ir „Separate PriceCalculator“, kurią lengva patikrinti. Taip pat duomenų kroviklis, atsakingas už tinklo ar duomenų bazės sąveiką, įkeliant mūsų produktus.

Mes taip pat minėjome, kad mums reikia klasės, atsakingos už nuolaidų valdymą. Pavadinkime tai „CouponManager“ ir tegul taip pat tvarko vartotojo nuolaidų kuponus.

Mūsų mokėjimų peržiūros valdiklis gali atrodyti taip:

Dabar galime rašyti tokius testus kaip

  • „testCalculatingFinalPriceWithoutCoupon“
  • „testCalculatingFinalPriceWithCoupon“
  • „testCouponExists“

ir daugelis kitų! Dabar kurdami atskirus objektus išvengsime nereikalingo dubliavimo ir taip pat sukūrėme kodą, kuriam nesunku rašyti testus.

Priklausomybės injekcija

Antrasis principas yra priklausomybės įpurškimas. Ir iš aukščiau pateiktų pavyzdžių matėme, kad mes jau naudojome priklausomybės injekciją savo objekto iniciatoriams.

Kaip ir anksčiau, mūsų priklausomybių nustatymas yra du pagrindiniai privalumai. Tai leidžia suprasti, kokiomis priklausomybėmis remiasi mūsų tipai, ir leidžia mums įterpti netikrus objektus, kai norime išbandyti, o ne tikrus.

Tinkama technika yra sukurti mūsų objektų protokolus ir užtikrinti, kad realus ir netikras objektas juos įgyvendintų taip:

Dabar mes galime lengvai nuspręsti, kurią klasę norime suleisti kaip priklausomybę.

Dėl įtemptos jungties sunku surašyti testus. Taigi, kuo daugiau testų rašome, tuo labiau naudojame principus, tokius kaip DIP, ir tokius įrankius kaip priklausomybės įpurškimas, sąsajos ir abstrakcija, kad sumažintume sujungimą.

Tai, kad kodas tampa labiau išbandomas, ne tik pašalina mūsų baimę jį sulaužyti (nes parašysime testą, kuris mums parems), bet ir prisideda prie švaresnio kodo rašymo.

Ši straipsnio dalis buvo labiau susijusi su tuo, kaip parašyti kodą, kurį bus galima patikrinti, nei rašyti tikrąjį vieneto testą. Jei norite sužinoti daugiau apie vienetinio testo rašymą, galite pasižiūrėti šį straipsnį, kuriame kuriu gyvenimo žaidimą, naudodamas testą.

Nėra kopijavimo

Kopijavimas yra pagrindinis gerai suplanuotos sistemos priešas. Tai reiškia papildomą darbą, papildomą riziką, prideda nereikalingą sudėtingumą.

Šiame skyriuje aptarsime, kaip galime naudoti „Template“ dizaino šabloną, kad pašalintume įprastas „iOS“ kopijas. Siekdami lengviau suprasti, mes ketiname atsisakyti realaus gyvenimo pokalbių.

Tarkime, kad šiuo metu mūsų programoje yra standartinė pokalbių dalis. Atsiranda naujas reikalavimas ir dabar norime įgyvendinti naujo tipo pokalbius - tiesioginius pokalbius. Pokalbis, kuriame turėtų būti ne daugiau kaip 20 simbolių skaičius, ir šis pokalbis išnyks, kai atmesime pokalbio rodinį.

Šio pokalbio vaizdai bus tokie patys kaip mūsų dabartinio pokalbio, tačiau jame bus kelios skirtingos taisyklės:

  1. Tinklo užklausa siųsti pokalbių pranešimus bus kitokia.

2. Pokalbių žinutės turi būti trumpos, ne daugiau kaip 20 simbolių.

3. Pokalbių pranešimai neturėtų išlikti mūsų vietinėje duomenų bazėje.

Tarkime, kad mes naudojame MVP architektūrą ir šiuo metu tvarkome pokalbių pranešimų siuntimo prezentacijoje logiką. Pabandykime pridėti naujų taisyklių mūsų naujam pokalbių tipui, pavadintam tiesioginiam pokalbiui.

Naivus įgyvendinimas būtų toks:

Bet kas atsitiks, jei ateityje turėsime daug daugiau pokalbių tipų?
Jei mes ir toliau pridėsime, jei dar patikrinsite mūsų pokalbių būseną kiekvienoje funkcijoje, kodas taps nepatogus ir sunkiai skaitomas bei prižiūrimas. Be to, tai sunkiai patikrinama ir būsenos tikrinimas būtų dubliuojamas visoje pranešėjo srityje.

Čia naudojamas šablono šablonas. Šablono šablonas naudojamas, kai mums reikia kelių algoritmo įgyvendinimų. Šablonas yra apibrėžtas ir tada kuriamas su tolesniais variantais. Naudokite šį metodą, kai daugumai poklasių reikia įgyvendinti tą patį elgesį.

Galime sukurti „Chat Presenter“ protokolą ir atskirti metodus, kuriuos konkretūs objektai „Chat Presenter Phase“ įgyvendins skirtingai.

Dabar galime priversti mūsų laidos vedėją atitikti „IChatPresenter“ reikalavimus

Dabar mūsų pranešimų tvarkytojas tvarko pranešimų siuntimą, iškviesdamas bendras funkcijas ir deleguodamas funkcijas, kurias galima įgyvendinti skirtingai.

Dabar mes galime pateikti Kurti objektus, kurie atitinka pristatymo etapus, ir konfigūruoti šias funkcijas pagal jų poreikius.

Jei savo vaizduoklyje naudosime priklausomybės injekciją, dabar tą patį vaizdo valdiklį galime naudoti dviem skirtingais atvejais.

Naudodamiesi dizaino modeliais, mes tikrai galime supaprastinti „iOS“ kodą. Jei norite sužinoti daugiau apie tai, šiame straipsnyje pateikiami papildomi paaiškinimai.

Išraiškingas

Didžiąją dalį programinės įrangos projekto išlaidų sudaro ilgalaikė priežiūra. Programinės įrangos kūrėjams būtina rašyti lengvai skaitomą ir prižiūrimą kodą.

Mes galime pasiūlyti išraiškingesnį kodą naudodami gerą įvardijimą, naudodami SRP ir rašymo testą.

Pavadinimas

Numeris vienas dalykas, kuris kodą daro išraiškingesnį, ir tai yra įvardijimas. Svarbu parašyti vardus, kurie:

  • Atskleisti ketinimą
  • Venkite dezinformacijos
  • Ar lengvai ieškoma

Kalbant apie klasių ir funkcijų įvardijimą, geras triukas yra naudoti daiktavardį ar daiktavardžio frazę klasėms ir vartotojo veiksmažodžius arba veiksmažodžių frazių pavadinimus metodams.

Taip pat, kai naudojami skirtingi dizaino šablonai, kartais naudinga į klasės pavadinimą įtraukti modelių pavadinimus, tokius kaip komanda ar lankytojas. Taigi skaitytojas iškart žinotų, koks šablonas ten naudojamas, ir nereikėtų perskaityti viso kodo, kad apie tai sužinotumėte.

Naudojant SRP

Kitas dalykas, kuris kodą daro išraiškingą, yra vienos atsakomybės principo, kuris buvo minėtas iš aukščiau, naudojimas. Galite išreikšti save laikydami mažas savo funkcijas ir klases tam tikram tikslui. Mažos klasės ir funkcijos paprastai yra lengvai pavadinamos, lengvai rašomos ir lengvai suprantamos. Funkcija turėtų tarnauti tik vienam tikslui.

Rašymo testas

Testų rašymas taip pat suteikia daug aiškumo, ypač dirbant su senuoju kodu. Gerai surašyti vienetų testai taip pat yra išraiškingi. Pagrindinis testų tikslas yra būti pavyzdžių dokumentais. Kas nors, skaitantis mūsų testus, turėtų sugebėti greitai suprasti, kas yra klasė.

Sumažinkite klasių skaičių ir metodus

Klasės funkcijos turi likti trumpos, funkcija visada turėtų atlikti tik vieną dalyką. Jei funkcijoje yra per daug eilučių, gali būti, kad ji atlieka veiksmus, kuriuos galima suskaidyti į dvi ar daugiau atskirų funkcijų.

Tinkamas būdas yra suskaičiuoti fizines linijas ir pabandyti nustatyti ne daugiau kaip keturias – šešias funkcijų linijas, dažniausiai tai, kas viršija tą eilių skaičių, gali būti sunku perskaityti ir prižiūrėti.

Gera „iOS“ idėja yra susmulkinti konfigūracijos skambučius, kuriuos dažniausiai darome naudodami „viewDidLoad“ arba „viewDidAppear“ funkcijas.

Tokiu būdu kiekviena iš funkcijų būtų nedidelė ir prižiūrima vietoj vienos netvarkos „viewDidLoad“ funkcijos. Tas pats turėtų būti taikoma ir programos delegatui. Turėtume vengti mesti kiekvieną konfigūraciją ondidFinishLaunchingWithOptions metodu ir atskiromis konfigūracijos funkcijomis ar dar geresnėmis konfigūracijos klasėmis.

Naudodamiesi funkcijomis, šiek tiek lengviau įvertinti, ar laikome ilgą, ar trumpą, dažniausiai galime pasikliauti skaičiuodami fizines linijas. Su užsiėmimais mes naudojame kitokią priemonę. Mes skaičiuojame atsakomybę. Jei klasėje yra tik penki metodai, dar nereiškia, kad klasė yra maža, gali būti, kad ji turi per daug atsakomybės tik su šiais metodais.

Žinoma „iOS“ problema yra didelis „UIViewControllers“ dydis. Tiesa, pagal „Apple View“ valdiklio dizainą sunku išlaikyti šiuos objektus vienam tikslui, tačiau turėtume stengtis.

Yra daug būdų, kaip padaryti „UIViewControllers“ mažą. Manau, kad naudojuosi architektūra, kuri geriau atskiria tokius dalykus kaip „VIPER“ ar „MVP“, tačiau tai nereiškia, kad mes taip pat negalime to padaryti geriau „Apple MVC“.

Bandydami atskirti kuo daugiau rūpesčių, galime pasiekti gana padorų kodą su bet kokia architektūra. Idėja yra sukurti vienos paskirties klases, kurios padėtų vaizdo valdytojams ir padėtų kodą lengviau perskaityti ir išbandyti.

Keletas dalykų, kurių galima tiesiog išvengti be jokių pasiteisinimų vaizdo valdikliuose:

  • Užuot rašę tinklo kodą tiesiogiai, turėtų būti „NetworkManager“ klasė, atsakinga už tinklo skambučius
  • Užuot manipuliavę duomenimis vaizdo valdikliuose, mes galime tiesiog sukurti „DataManager“ klasę, kuri yra atsakinga už tai.
  • Užuot žaidę su „UserDefaults“ eilutėmis „UIViewController“, galime sukurti fasadą.

Apibendrinant

Manau, kad turėtume sudaryti programinę įrangą iš komponentų, kurie tiksliai įvardinti, paprasti, maži, atsakingi už vieną dalyką ir yra pakartotinai naudojami.

Šiame straipsnyje mes aptarėme keturias Kent Beck paprasto projektavimo taisykles ir pateikėme praktinius pavyzdžius, kaip galime jas įgyvendinti „iOS“ kūrimo aplinkoje.

Jei jums patiko šis straipsnis, įsitikinkite, kad plaksite norėdami parodyti savo palaikymą. Sekite mane, norėdami pamatyti dar daugiau straipsnių, kurie gali pakelti jūsų „iOS“ kūrėjo įgūdžius į kitą lygį.

Jei turite klausimų ar komentarų, rašykite čia arba rašykite man el. Paštu arlindaliu.dev@gmail.com.