Ang pattern ng Disenyo ng Repository sa Swift

Isang malinis na paraan upang mag-query sa iyong mga modelo

Anong problema ang nalutas nito?

Kung kailangan mong tanungin ang iyong mga bagay sa modelo mula sa iba't ibang mga lokasyon sa iyong code nang paulit-ulit, ang isang imbakan ay maaaring maging tunay na kapaki-pakinabang upang magbigay ng isang solong-entry point upang gumana sa iyong mga modelo at alisin ang dobleng query code. Maaari mo itong gawin nang higit pa at gamitin ito ng mga protocol, sa ganitong paraan madali mong mai-out ang mga pagpapatupad (halimbawa para sa mga pagsusuri sa yunit) o ​​maaari mo itong magamit sa mga generik upang makagawa ng isang mas * drum roll * generic abstraction. Sa artikulong ito tatalakayin ko ang lahat ng mga kasong ito.

Sketching ang eksena.

Sabihin nating mayroon kang ilang mga code na kumukuha ng data mula sa isang API at mapa ito upang mai-modelo ang mga bagay. Sa halimbawang ito kukuha ako ng isang listahan ng mga artikulo mula sa isang server.

Ito ay maaaring magmukhang medyo masaya, ngunit ito ay RxSwift lamang, gamit ang Moya bilang ang layer ng abstraction layer, ngunit hindi talaga ito maintindihan kung ano ang nangyayari. Ang paraan kung paano mo makuha ang iyong data ay ganap sa iyo.

Ang piraso ng code na ito ay

  1. Isang kahilingan ng GET sa server
  2. Ang mga mapa ng nagbalik na JSON sa isang hanay ng mga bagay na Artikulo
  3. Ang pagsasara ay tatawag kapag ang lahat ng gawain ay tapos na.

Bakit kailangan natin ng isang imbakan?

Sa ngayon hindi tayo. Kung tawagan mo lamang ang API isang beses sa iyong buong code ng code, ang pagdaragdag ng isang imbakan ay maaaring masobrahan (o tulad ng maaaring sabihin ng over-engineering).

Ok ... ngunit kailan ang isang bagay na repositoryo na maginhawa upang magamit?
Sabihin natin na ang iyong codebase ay nagsisimula na lumago, at kailangan mong isulat ang code upang ulitin nang paulit-ulit ang mga artikulo. Maaari mong sabihin "kopyahin ang code at i-paste ito kahit saan kailangan mong makuha ang lahat ng mga artikulo."

Walang pinsala na nagawa, walang namatay. Tama ba?

Sa sandaling iyon isang malaking pulang alarma ang dapat magsimulang kumikislap sa iyong utak.

Kamusta repositoryo.

Ang isang imbakan ay isang bagay lamang na sumasama sa lahat ng code upang mag-query sa iyong mga modelo sa isang lugar, kaya mayroon kang isang solong punto ng pagpasok kung nais mo ang e.g. makuha ang lahat ng mga artikulo.

Gumawa tayo ng isang bagay na repositoryo na nagbibigay ng isang pampublikong API upang makuha ang mga artikulo.

Maaari naming tawagan ang pamamaraang ito at hindi namin kailangang mag-alala tungkol sa kung ano ang nangyayari sa likod ng mga eksena upang makuha ang aktwal na mga artikulo.
Tawagan lamang ang pamamaraan, at makuha mo ang mga artikulo. Nice, di ba?
Ngunit maghintay, mayroong higit pa!

Pangasiwaan ang lahat ng mga pakikipag-ugnayan sa artikulo

Maaari naming gamitin ang imbakan upang magdagdag ng maraming mga pamamaraan upang makipag-ugnay sa aming modelo ng bagay. Karamihan sa mga oras na nais mong gawin ang CRUD (lumikha, basahin, i-update, tanggalin) ang mga operasyon sa iyong modelo. Kaya lang, idagdag lamang ang lohika para sa mga operasyon na ito sa imbakan.

Gumawa ito ng isang magandang API na gagamitin sa buong iyong code, nang hindi na ulitin nang paulit-ulit ang parehong code.

Sa pagsasagawa, magiging ganito ang paggamit ng isang imbakan.

Medyo maganda at mababasa, di ba? Ngunit, maghintay na makakakuha ng mas mahusay.

Power-up: mga protocol

Sa nakaraang code, palaging ginagamit ko ang halimbawa ng 'pagkuha ng data mula sa isang API'. Ngunit paano kung kailangan mong magdagdag ng suporta upang mai-load ang data mula sa isang lokal na file ng JSON sa halip na isang online na mapagkukunan.

Mahusay kung lumikha ka ng isang protocol na naglilista ng mga pangalan ng pamamaraan, maaari kang lumikha ng isang pagpapatupad para sa online na API at isa upang makuha ang data sa offline.

Ito ay maaaring ganito.

Sinasabi lang ng isang protocol na 'kung sumasang-ayon ka sa akin, kailangan mong lagda ang mga pamamaraan na ito, ngunit wala akong pakialam sa aktwal na pagpapatupad!'

Sa gayon mahusay, maaari kang lumikha ng isang WebArticleRepository at isang LocalArticleRepository. Pareho silang lahat ng mga pamamaraan na nakalista sa protocol, ngunit maaari mong isulat ang 2 ganap na magkakaibang pagpapatupad.

Power-up: Pagsubok sa Yunit

Ang paggamit ng mga protocol ay talagang maginhawa kung nais mong subukang subukan ang iyong code, dahil maaari ka lamang lumikha ng isa pang bagay na nagpapatupad ng protocol protocol, ngunit sa halip ay ibabalik ang data ng tanga.

Kung gagamitin mo ito kasama ang dependency injection, ginagawang madali itong subukan ang isang tukoy na bagay.

Isang halimbawa

Sabihin nating mayroon kang isang modelo ng view, at ang modelo ng view ay makakakuha ng data sa pamamagitan ng isang repositoryo.

Kung nais mong subukan ang modelo ng view, natigil ka sa mga artikulo na kukuha mula sa web.
Ito ay hindi talaga ang gusto natin. Nais naming maging deterministik ang aming pagsubok hangga't maaari. Sa kasong ito, ang mga artikulo na nakuha mula sa web ay maaaring magbago sa paglipas ng panahon, maaaring walang koneksyon sa internet sa oras na tumatakbo ang mga pagsubok, maaaring bumaba ang server, ... ito ang lahat ng posibleng mga sitwasyon kung saan mabibigo ang aming mga pagsubok, sapagkat sila ay sa labas ng aming kontrol. At kapag sumubok tayo, nais / kailangan nating kontrolin.

Sa kabutihang palad ito ay talagang simple upang malutas ito.

Kumusta, dependency injection.

Kailangan mo lamang itakda ang articleRepo na pag-aari sa pamamagitan ng initializer. Ang default na kaso, ay ang gusto mo para sa iyong code ng produksyon at kapag sumulat ka ng isang unit test, maaari mong palitan ang repository sa iyong bersyon ng pangungutya.

Ngunit marahil ay iniisip mo, mabuti kung ano ang tungkol sa mga uri? Ang isang WebArticleRepository ay hindi isang MockArticleRepository, kaya hindi ba magreklamo ang tagatala? Well, hindi kung gagamitin mo ang protocol bilang isang uri. Sa ganitong paraan ipinagbigay-alam namin ang tagatala, payagan ang lahat hangga't sumasaayon ito sa ArticleRepository protocol (na parehong ginagawa ng Web at MockArticleRepositoryo).

Ang panghuling code ay magiging ganito.

At sa iyong pagsubok sa yunit maaari mong palitan ito ng ganito.

Ngayon ay mayroon kang ganap na kontrol sa kung ano ang data na ibabalik ang iyong imbakan.

Super power-up: generics

Maaari mong gawin ito nang higit pa, sa pamamagitan ng paggamit ng mga generics. Kung iniisip mo ang tungkol dito, ang karamihan sa mga imbakan ay palaging may parehong mga operasyon

  1. makuha ang lahat ng mga bagay
  2. kumuha ng ilan sa mga bagay
  3. ipasok ang ilang mga bagay
  4. tanggalin ang bagay
  5. i-update ang isang bagay

Well ang tanging bagay na naiiba ay ang salitang 'bagay', kaya maaaring ito ay isang mahusay na kandidato na gumamit ng isang protocol na may mga generics. Maaaring kumplikado ito, ngunit talagang simpleng gawin ito.

Una naming pinangalanan ang protocol sa Repository, upang gawin itong higit pa ... generic .
At pagkatapos ay aalisin namin ang lahat ng mga uri ng Artikulo, at palitan ang mga ito ng magic T. Ngunit ang titik T ay isang kapalit lamang ng ... anumang nais namin. Kailangan lang nating markahan ang T bilang nauugnay na uri ng protocol.

Kaya ngayon maaari naming gamitin ang protocol na ito para sa anumang modelo ng bagay na mayroon kami.

1. Repositoryo ng artikulo

Ilalagay ng tagabili ang uri ng T sa Artikulo, dahil sa pamamagitan ng pagpapatupad ng mga pamamaraan, tinukoy namin kung ano ang T. Sa kasong ito isang bagay na Artikulo.

2. Pag-iimbak ng Gumagamit

Ayan yun.

Inaasahan kong nasiyahan ka sa artikulo at kung mayroon kang anumang mga katanungan o mga puna, tanungin lamang sila sa ibaba o maabot ang akin sa Twitter at hayaan ang isang chat.