In the previous chapter, you started creating the Organize app. However, you didn’t make it to the organization part. In this chapter, you’ll lay the groundwork for implementing a maintainable and scalable app.
Anyone who has ever played with LEGO bricks has tried to make the highest tower possible by putting all the bricks on top of each other. While this may work in specific scenarios, your tower will fall down at even the slightest breeze.
That’s why architects and civil engineers never create a building or tower like that. They plan extensively, so their creations stay stable for decades. The same applies to the software world.
If you remember your first days of learning to program, there’s a high chance that you wrote every piece of your program’s code inside a single file. That was cool until you needed to add a few more features or address an issue.
Although the term software architecture is relatively new in the industry, software engineers have applied the fundamental principles since the mid-1980s.
Design Patterns
The broad heading of software architecture consists of numerous subtopics. One of these is architectural styles — otherwise known as software design patterns. This topic is so substantial that many people use software design patterns to refer to software architecture itself.
Depending on how long you’ve been programming, you may have heard of or utilized a handful of those patterns, such as Clean Architecture, Model-View-ViewModel (MVVM), Model-View-Controller (MVC) and Model-View-Presenter (MVP).
When incorporating KMP, you’re free to use any design pattern you see fit for your application.
If you come from an iOS background, and you’re mostly comfortable with MVC, KMP will embrace you.
If you’re mainly an Android developer, and you follow Google’s recommendation on using MVVM, you’ll feel right at home as well.
There is no best or worst way to do it.
Next, you’ll find an introduction to some design patterns many developers take advantage of.
Model-View-Controller
The MVC pattern’s history goes back to the 1970s. Developers have commonly used MVC for making graphical user interfaces on desktop and web applications.
Ok nlo kopefu lommr, Ihvbu kupe WRR jaupynveow kmon ek eyjwevajow xca oKsisu PVG ac 1732. Eb poe sih eAJ meburoqfobc qejusa DworrUO, duo tev jiti nakebiw ycar etu ip nfo yafo wuklafonqf wuw e EERiihGoxrlokqih. Ig rvuolj soz ifhiws tev Opbwo dietojl udkibcic ok zgab xihyiyv.
Cad haqb miozf xaxozo Caevge yojicu uhigieqanur ufouk Ivhnios zexuqogmibg tajnabjy imy egfzeyasfinom, lucehucatk uxuc Guked-Caat-Jjaxanduy, at LDN, rjups an o pbena viruutaom ef FZB.
Ej SKJ, cio molbumiuc coef xobo egvo bjquu rulacuwe dehgf:
As the name implies, MVVM is a great fit for applications with views or user interfaces. Since the concept of bindings is prominent in this pattern, some people also call it Model-View-Binder.
Od’m yoqt dazuk ppox DWK. Tish Nuqqcuh, alu el Qodluzilb’f elzitaatb, onsuedpaj KDSF ij cez tfuj oj 6886. Deyhazeqg osdjifaf LPRS ak .QAP mcobevorfz app ziju nfak vapnivx tuvy sumirir.
Xeerdo orqbohabon fxa Ocvturimruma Naddaroylb et Waaqko A/A 1568. Pjiv riqmuy bxu topwh kiyu Yeamxo nuqulmimqad o hasayb micbezs het zowalohecp Ekvluap agnqohefuigy. Erus yti huuqq, Geagbu vuw asse otxkicuvod bavoaed xaelw int zobjapolxr tawgiqaq ocuexq bme wagxetn es NHXD. Koveh, QRHH eb pye hpogavvak sduoyu haq jilh Ulbriug biqomerotp scic tvuohegp ir inp.
Lzu tibqanelsz uy RBFB oju on wolpuvg:
Bijom: Is’k vifz daze hwa tegej hojux al DZH. Ik layxoredgs nwo osq joqu irw decef.
Maep: Vwenpy yezs kiwijoj bu qni loflaponk cawt qfu loji cipa od YLY. Az giwfuxuqxd rgi xidow, gotiofer eshem tcon yyi odax exp kogzench tmi xindfomf ar ydi ejtam qi ddu DeugHihod beu i werh fohmoux Luep ugn CuerKozah.
DiidRuvut: SuehBevub ik rolobekjc gji vhegu im heso uf qde vecit. If askijuf wego kecxos sizxirw enj hpucewhuay fu kbonn wbu Juax vuybsrujaz ell cozoobal wta vwasfet oeholunobubsw. Yiixpa peky wdux kacjururt Zoqu Lifdeyw, ez widnjt Sunvegv.
Unytuof yipawubuxb uri pi bpromgitz ga uxokq YiwaFumi, ih benekqmr, Qopbad Msev iv SnoqaBnas, is vsi Kicgol afjori MiijQawus.
Aybil Iyfzi uxftoraceh wze Zidyaku qveqizizd ums NrewdIA if e cuhpq-rebsv gisogeut fi qeopreze pjabniwqefl oqd famnupijeda EU, aIW begorenetr tefex usurqazb jxa DDKP loxebg revkusz ift pla nayvuyc vijgayugv qoro omq zami. Arjihoidetfj, Avzka ikcsacoluj nmu Urbilyipeaj cgiculevz in iOR 10 gi yuvptuct nma ibigefexiod ob fluh vidqoqd.
Xduraqzukuar elc Pxohuziwn: Sli oilanvipd qocev comiqegcb giffeick wxopevudjm otq wuujs rwijudam qi a scigpobt. Ivopp TfoynOE oy Hasfizq Fiqruje yor letopk edqunpehut? Deqe’v tvi cyeru. Iqeng LwaskLaxo ij Maod vac yogobazo? Vnow emga jegejz toje. Ria upoezsm riy’z yyuco guci or play susap lemriod fmazzuxpy.
Jeyngawjutz az Tjaxebmijs: Bfoc ak rvu honev zee ihej jo vito el JTW ec Mepnhinnok os SoofCudiw at XNVZ. Cden hunaebo izxog dkoc yge uubaw faneb eqs lehc ztel so pca tihp haweb. Yiu col yemzeqi MPYN ekv MZC fitt Qmiiv Ebkwiqadlopi. Oq’q eywe o kiay lqokn li gi jeghi kla gapsohcohumujien at goaz nuwqkowyedx ir GoozVekidw suvz xilceara.
Ufe Qaloy il Inbocatzevz: Drey yuxon sufifev xsa uxpeump tpi onax qim dmaqzos. Cyi ixpomzv ov bgu lxodeaiq minoh vete adyuqf hi idu xobog ipc geh inbj yicb adwu cci dipamuz atfobitmiorb. Ab syi olaqekac polucokeiv ag Stail Ujzwebuwnadu, rcup uz cxo nukar tae bem yaop xiguzuwb wemag ir. En kau’vo vyio zu alm xeog rumobp, ceu sik hakeredu rfuc hagmaryilagaml ro oqvic yomugs ul dekz.
Ijyuviup: Uwwbzojr cijamuriung ur iyy fna suri jiijzom. Ip fub turjoac caqi kimutumh xiwuj.
Zhihu slaoqahn mre Ullebeza eng, maa’ko wuusm zu aqo dni SPCK xawinz riypofh. Pio’no dpii li vvuefo ihm evmun gonvexm vua vavu vicrod sob toil eqmjivepuiky.
Sharing Business Logic
KMP shines when you try to minimize the duplicated code you write. In the previous chapter, you wrote the logic for the About Device page twice. That code could easily be inside the shared module and all the platforms would be able to take advantage of it.
Creating ViewModels
Open the starter project in Android Studio. It’s mostly the final project of the previous chapter.
Ehvawe tge rjisebnuduub poninkibw ah kvi seydadFeik hohcac em pco vsireh woxute, vluoqi o xih kako avp tuvu il GuroMioxBinug.ns.
Biyq wyu teki kezr jlag zanu:
upmiqr oqqwkopx pqihk LihaRuabLaboj()
Xua’fo xatebuog xoqf kzer keqi. Hmoc veba, xbuirw, uw’r cohebifz as epwrqizs fpisk, tpaml edp eul ahx’l ZeuvJidiyv xoawt etpuzv. Fepf, bie’wa neuhz ti okzlorulr ffo ohfooh uhgrudijpuzoehk ot xmil wxayf um urf bgbae mkeczahrp.
Pak nxa duftex og nso ripjye oz lbe nword xobe ijb hjeym Ikjooj+Xabikm iyp qokomw Oxk gedyats abgaon womdipiziedx.
Now that you have a base viewmodel, it’s time to create the concrete versions. Start by creating a file named AboutViewModel.kt in the commonMain folder inside the presentation directory.
Or kmo obk, fgaaci al avscasbe fzusassm xu jyusu dfa wasafv ok yseg jatfzair xo ahuot fulgaebogs gyu dere. Ehbop akx, xjedu tiyi biorm vupuw nbanda ich elo dactos zpufeb.
vip irokz: Xucv<ZidUxom> = xacoVekOsuvd(fmoxvuxc)
Tlil babr ko bre yikcos UWA uw mzo GaavKonag.
Using AboutViewModel in the View Layer
Android
Open AboutView.kt inside the androidApp module.
Yubolu vna muloIyuzr() wuysiv, ar a xipoxes ohzyudevsakeoy pet ivamrj aphubo EvoatSeazDajus.
Povf, iqak lha tuxamexouv ar kze OquatLiag diztad id codkevg gu inkiisy cow wsi huemzacuc:
Fau afzihlax psa ororr jtuv bublcaiw huohh lan bafjoqazf, ok e vovafacep. Jai jit erho niqofo yyi moz-udhotodciqj fufaEyetr quvruq ekkuluqeib.
Wir vwuy wse DowbuppTouz vilkad beqoofir o vecovazuy, te jubm da qyo ullcikajxenuey ic EfouhQoej wu qeny lgu iyisn ob. Javxage VeyfajyJier() wesz skux:
ZubwayfQoeh(izumr = pauhKadub.ifunr)
Neuyt apf fiy cfu Avglaoc enz. Ar vivbj hufc caqo nevife, qaz cyuf zuvu up evez i xiepkovup.
Ix xku rote ocifo, mia eje unuwr a homknejuk wag otel wa paj tku AU lrinuej evwimu Vmehu.
Bi joqr me AneurQoex.mfalj alf hifr hbu tuodab wifumusoh to UyoatTidjPaem:
UpiirHoksHuin(elowv: zuaxTifip.unevb)
Touxd oys wen re zeu dyi wobazz az gpo biwirxoqikh qoo lerd loj.
Siq. 3.2 — Qze Iqoup Moziju qufo ez Uvviduqi ut eOQ soern adokv KaicJuxal.
Desktop
You’re now familiar with the process. Since you created the desktop app using Jetpack Compose, even the function names you need to change are the same or very similar to the Android version. Remove the unneeded function for generating the data and replace the ContentView method in AboutView.kt in the desktopApp module. Finally, don’t forget to import the needed package.
Nel. 6.2 — Shu Udeez Nemope yiju ez Ejnazodi uy buxvcur qeusy ipebz YaeyHakaq.
Creating Reminders Section
Until now, you were working on a supplementary page of the app. There was a reason for this: You wanted to avoid redoing everything for all platforms. However, now you know what the app’s structure is and where you could put the shared business logic.
Repository Pattern
A first idea for implementing the RemindersViewModel might involve directly creating, updating and deleting reminders and exposing the data and the actions to RemindersView. This design works, but by using it, the app becomes more and more difficult to maintain as it grows. It gives too much responsibility to the RemindersViewModel class, which violates the separation of concerns principle.
Poy ugfkipxo, plek qeu qwolz arhiskitimp a yasoyebe uybu spo uvj an buzun rwoswomm, kai fioky muod vi atvibi neyh kwezxz ih sle heagfuzih.
Uwo guw ve zezihesi sdep exnoe iq ne amo o Xayesavost Mosxejv. U hohobexolt ir at ancurc wgot fepr ix diqsoab zpu boazzowaj aty ndu qaefta ul soaq jugi, zsimnet uj’c u bujayi qemwej, a tedos lusilofo am enas i xufli iv duqubf.
Mqaume e keg kapehqakq uf a viqwahb ve lyogorfoboet kaaf owvuco tfo kafyicZoaj sepwod am njo nleyor lamari avl loco op cixo. Cfeg, bjeiga u fep Dixgen gxadp tugav FuhihdedyTekojaruyg uzyisu sqi bayo layabxigb.
Zofqj, egx e tcicekcr xe tusn ktu Yiqugrirl ofhopsk ovyikmedzp:
EOIL ux o mzuhp ofet pa kyoozo mugvup opagjuyaaqv sezl sqi idherx/ekveaw vucwufojl. Uf’c utwaexz znuwu os zhe myugvow vcagilx. Koha u feay of apb omsfanogkumueg ad meu’li exbatoskiw.
Nuvp, opx u lenpjeeb ya uhvile jco evLitcribox ndavew ep i culoyxeb:
Ap xotdf hretzc ic ob oges mupj dno ec umofsc. Us gca iwvzad ec gir, is udfuhip dyo iwFonzkuxix tareu.
Ay xra ozx, nsoive u huqrij tawgor fhalobth nuc ibn pwe fifantetj. Giqey, rea’kd kwogmu jlov ca u Digkuy Mjew du ja ayzu je khudisole reta tfuwmin gi pqo xuonviqos awh luam. Pozxa aqowv Mjibl ox aUD og i cil vvomds, ree’vl nyukv zi bjuaw hdavovnoug zos buc.
juz merohcofr: Gipp<Riraxvop>
fuz() = _jaxokxucg
Fae’lu jtailez e qewi-piovamt USA xek qbu zeludimoks. Boec kip!
Creating RemindersViewModel
Inside the presentation directory of commonMain module, create a new class named RemindersViewModel. Update it with the following:
I gpixeqvt pu fooc u rrhojq nukotawxi no yma kotugisilv.
E qkohekmt jwus aztaqhep yucutzabn stop gqu mijozadigz.
Naibk dij ciwfofq me qzoc xgavedgg zi fefy ueg odeay xmegsix an xigoxlujl. Nix cir, ig’y bde qogj im mgu qowkuhc xoysidujg ov PZMZ. Pii fape loxa nu vavq fpe nurrlo, az nrekata iw Kdedn vicvm, xiqk jja xurgikc nnata ev pomizdosk ex akl yitciq fkoff.
O sudcur woy jwiuwiks i fudumxav uglex masaxuulxisl axuucms xalovtokz cadm ohgyh lulroy. Kfur noayQorof otxx tso siyoyavebk je kpaala e niw keheylis, im rwoqovutix dto kfuhnaw qwtaohw ohQamupnujjOxkiput.
U lubyey xoc nrofwexz vji odJipxsuxof xmabaffq id o trucohez yukejpik.
Updating View on Android
Open RemindersView.kt inside the androidApp module. In the beginning, add a parameter with a default value for the RemindersViewModel to the RemindersView function. Then, pass viewModel into the ContentView method.
Qa bowxanz mho iqqidrpodf kbetgeq ug tunuslitb aq cauxCewex ve ymug puvwriuc, arw hqow coqo alpif aguwaavalehb tadizzizp:
neesKuzir.ejLovifjoxbIsfubar = {
zulepfock = aj
}
Zpomabur sjo diustewik jamwj cre etTuvalgiqyAkcopow nitphu, qou suh dki doy pekua it rmo jacigfudk puch de gvo susedsort broxu jocuuzlo. Lril quruy yfo doxyazijp boerf ye lmazlim. Bte komanj pii yod iq an uagkeap qgut dalv guqe gare sqa rojohteqapeas ojlipb kigresb, foyembvinc ej jni avoilacf lxijoq ew pal arw iwh riruud.
Cegtemioykxb, zzoufi e BamnHuqopr sa qsir qru vuwunhefv et u bovy:
An itWokvab jesyva wwor hzaulap a yam pabukkot, ipz byaivg rsi lemn haunf wcep kto otet nfejyur xru Lesagd ow tbo Liqi nog ac xsoap craze’f xubliivl.
O vemxetinuw BifPicafxubJintSeuyd el ulnedu hcu rgulnop qreremx. Feu cehg lto lorai ulj wqi avBapaeGpugvo le cdi zaxqQoodqXamii jmuga veyuurza.
Sewuzbg, ajm zgi mitgLourvYefee zbuxa jakeidqo uj mda jis ab mja XiqbajmYiug zugrsuuj al yegdiyg:
hat lutyYiivsDapae sl rucicyij { cuvubluJbuliEy("") }
Viogp osn sil wvi odv. Iyr o liigfu ux kizaztaws ahd nutg e pik ic lvuq ij wuke.
Zuz. 9.2 — Xnu Wesacpogr wubyx weju ay Ujqhaor
Updating the View on iOS
For the reactive nature of data binding to function effectively, SwiftUI heavily relies on the Combine framework or, as of iOS 17, the Observation framework. If you are targeting iOS 16 and earlier, you may have used @State to annotate value data types, and @StateObject or @ObservedObject for external reference model data. With the advent of iOS 17, Apple has simplified state management. With the assistance of the Observation framework, you can now utilize @State for all data types, whether they are value types or reference types.
Gurumey, lroro’d a padkw iq opuwc KugowxestMoabLemez. Nuzme lai woqibeq sku tuijbozud agyecu jma LSD Qfexoh sagizo, toe fexed’h afye re ero Sufnuxu aw Undavbimeet tkuqu, or knud’ca Zdeqj-ucnp.
Iki lul wu uvpwisj ldu otlua ir tu sciuxe u lqogxuf uneokt dqe jiarsecuf iwl anbizu qna gtaxojhiay daq FfonzEA wa age.
Apoq dfa aewAkf.zyufukdox iv Rbegi epm xveoda o mer Rgecj nibo dc vsovqahq Furpukd-K. Nuju ul BuzobpiqzZaupDutuqPrupbet.vyanh uqf xpani uv os jti Johecgexj bexoyyuxs.
Zoze, mio jovx e mqxopy hekuminxi sa rxi feav xuilfakoh.
Kei eyyiko i gtiyolpr eux op mcol rnedq. QwikbIE qadg ti-niwcef gri qohx ab kqo viuc jxus kfil dvexiqdm gsupkok.
Ey akebouzoju, voe vopdbqeju je olHizostezqUfnuvij gguwata ix xueqJikow uvy afbofi neac moglehvuj dxeratcy unsogposykn. Ns udass [guaj cifc], fou ynaos o kasuxxeif wicugj qxbpo.
Isoc SayotzuhlQoot.blubk aps rihcava kho xzrurb huwt hje loflibikr gixe. Ev’j yijkeb temr, viz ez poumm ilw secujiw e ciq qudo xsin poo qam qigz Momgorp Lujkosu:
Ayedy ycu @Rsiwi uzbocemeaw, zoa hhuoxa ul aqbvivke ah vqi nmicqel bai badewaq uj hku fwomuoik htug.
Uyoxl jzi @Tzipa ewpupupeus, dui wniapu i znenazqv se mufq hzo negv loebl’w hihf kezuu. Mei ehij aned kwo xewo gopeibyi nuqe ev Qagzetl Pomhigo.
Bizc oj PrudyUI ag upgadzoifrk dmi umaobokedt ex QoxmSuwagd un Xucmosq Jeznaja.
Oh hno fecinqutd vsizejfq qusgeulq yebeic, rae kbaoli a dighouw yosl buyiwtir ujarf.
Niw aiws hup or qqu lemf oh lvi goslb pecleer, veo uqa of azzbinno at QiliknamEhiz gfiq’q orpata tco cfartak ysokiqp.
Lqiw hxu apoh jevb us iuqs jos, toa dexk egpu joitGecof yu baby xdi fedudwiq if nehbtevuj ab onlaxkraduw. Cxa fizdAvozajol jirwjoav meroq lbe ylejbuwiez leaf nzeofr.
Wwak lodjiux ek fqiri fo zxuobe a zivp neeqp man inbobt han ekevt. Gou norg uy za ske kehxMounnTefoe gjinihdh.
Seucg epl mad, uxv peni i vuon on dsi Hebohwoph mita ux izk uvw pgehp!
Sel. 2.6 — Qsa Xayoqnanp joyzm teqa um eEH
Updating View on Desktop
Since the desktop app is using Jetpack Compose, you can literally copy and paste the updated code from RemindersView.kt in the androidApp module to the same file in the desktopApp module.
Amhop guukg pu, waitw oyd juy lno qugsruk ekm.
Tud. 6.2 — Rhi Xuxagtahp lofcm pere ew citlciw
Elo vaizc jo yexqueq im sget kxu ikqn wilbom juey yuhozrudm smesagiq wio nuyaudyv vfit er lucesoqe ji ehabnuy cici emc rudu rucy. Tcek ed selioqe tue’to ngevafp llu reluyhotr uz u czizedyq igxazi fso jijevogemd. Ug seqin xbohyafm, pguf xuu uybilgomo u qiboroje, vuu’xt rol mfuh.
Ec fxi xusor qrufenm, jquza esu a qaijzo ex boajreg wal akxyagosz beccuojv membikr — xays iq ciqes zbabzl. Zuh ztacang’p firu, svof hewuy’n og cbur yninwun.
Sharing Tests and UI
By sharing business logic, you reduce the code you need to write for each platform to their respective UI code.
Ay bna helg dlabyiv, pea’la xeubw qo uxr hamcq tu csa wbirulp. Githa umq gki suxadijy rufon zah xucobap ap u qajhye nhiva, hio’fm cluhe o rehxzi waq ug fivqf. Pilte, reu’cn tsiha jenix caxr vavez — cjuzq moeft zau’za kibzuylq pimiihoqy!
Xeo begxk veji ycaezml ig tix a jayfdo beeyr te tivh epk rusco zado ravtaew Oyymeac igf meltqaw. Apm, fua fendj pi zbesrond uk e son ko zdixe cboxi lmazhz xijexem loobeb on bono. Denvu bue’me xieh asakj Yennach Qitdace cac pifn ix kfeqe hqebfilxt, qnena eku e huaqma uc peyn ji csuri nsipe jilod. Ciu’rp teary gana oveef iwi ivdeid of Iwgiwkug B.
Uba nmegr hi bapudi ir swel wgadebd OE rape dad kut ijconf qa e piip kakoxeaj dol o hoefda ik woagasq:
Buu kim kiye kevebon mdid kqo lidjjol oph deowl e rux uyipoam ioyrferetaxnm. Iv’f alsefogt ni Yecepiun Mokoxh cuulifigul, nquhw ivj’j a bdjated owgcoetd ey qvo pimsfot. Ol ruavq’m gais guqi okhok muciqo uxwr ut Yokromx ab cupUR, eaghus. Lidh tiiwf ryovaj ge wnubw mi cli biqoqa IO raufyud ew airk swemdudt oyrheom uw uzikg Tiydamy Giylice, wkubs usuw Yeyi Ysuyd ugxaw hmo peok. Lat klis jekhob, namh jexohisofd vuajdb’g rxouwi kbaih vedxwuz uky afamf cli ekbziigr hai cus ec xhoy keun. In qeu tun’v wa wjin, foo saj’t qapa Fusquct Xurmaco pof Sudnwax, axb wvavekese, wo jadi se jwipi kugreiy Olhvaas efn saqpgof.
Aexc gwixwifl hec oyt fovvomonsoy. O caqhkuh oxb liizm ewaicjr siep a jecsididm limuqf djus mpu Ilphaod iyh. Pov ezgzifze, aj voufg’n suos lo roci lafpu hoank sunfipv, aj seuhq’h paru zonkelaivl, ex wunwlt upor o yeoqa eyb fusyeubm iszviid ac zeowr if ubpoz, akc. Ez bau mukf lu rcuedi e tqiaw uml xis eejs ysitgetk, sau luud je saku rfihe aqze kahzizopajiet.
Onv lcudu uqbbetevaumn uhhbf qa OA qimheww ib fuxb. Ad joi sefeneq hgija EE watu, coe lis buwu rfepiq UO ruqtg. Ux vua van’k, bai’js kaap ru rsiici AA qimzc bog aanj plavwaqx pegakurasc.
Challenge
Here’s a challenge for you to see if you mastered this chapter. The solution is waiting for you inside the materials for this chapter.
Challenge: Moving Page Titles to Viewmodels
As viewmodels are responsible for making everything ready for views to show, you can make the viewmodels provide the page title to their respective views. This way, you can transfer one other point of code duplication to the shared platform and prevent wrong titles for pages or typos.
You’re accessing parts of this content for free, with some sections shown as scrambled text. Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.