Pengembangan aplikasi seluler sepertinya tugas yang cukup sederhana. Tampaknya apa yang harus dilakukan di sana? Saya melemparkan beberapa pandangan, mengurapi dengan beberapa arsitektur, dan hanya itu, proyek sudah siap, Anda dapat mengirim aplikasi ke stasiun. Dalam serangkaian artikel saya akan membagikan fitur yang kami temui ketika mengembangkan aplikasi untuk bank besar.
Pertimbangkan 5 topik penting. Tentu saja, kebanyakan dari mereka telah dibahas lebih dari satu kali di komunitas, tetapi di balik setiap topik adalah rasa sakit, air mata, waktu yang hilang dan, yang paling penting, pengalaman yang bermanfaat bagi kami, dan saya harap ini akan bermanfaat bagi Anda.

Pada awal pengembangan aplikasi seluler, pemimpin atau perancang menghadapi pertanyaan - pola arsitektur apa yang digunakan? Studio kami memiliki pola arsitektur MVP yang umum. MVP murni memang bagus dalam bentuknya yang murni (lihat gambar di bawah), tetapi kami tidak akan menjadi pengembang nyata jika kami belum menyelesaikan pola ini. Mereka tidak berhenti pada satu opsi, dan kami mendapat dua cabang dari MVP murni.

Oleh karena itu, pada tahap desain, kami dihadapkan dengan tugas memilih satu, dan atas dasar pola arsitektur yang diterima secara umum dan dapat dipahami, lanjutkan. Tapi, sudah pada tahap awal, kami berhasil membuat kesalahan, yang kemudian membawa kami banyak masalah.
Mari kita lihat dua MVP kami tentang steroid.

Gambar menunjukkan bahwa, dibandingkan dengan MVP biasa, tidak banyak yang berubah. Kami melihat beberapa masalah saat beralih antar layar di aplikasi iOS. Sejumlah besar logika untuk membuat layar baru sebelum transisi terkonsentrasi langsung di UIViewController, tampaknya bagi kami kurang tepat, jadi hal pertama yang kami lakukan adalah menyoroti entitas Router yang terpisah, yang bertanggung jawab untuk membuat transisi antar layar dalam aplikasi.
Model dalam SurfMVP adalah layanan yang diminta oleh Presenter untuk mengambil data. Seringkali, satu layanan menyelesaikan tugas untuk seluruh modul, tetapi dalam situasi sulit Anda harus berinteraksi dengan beberapa modul.
Entitas Configurator bertanggung jawab untuk membangun modul terpisah, ia menginisialisasi semua komponen yang diperlukan dan bertanggung jawab untuk membuat dependensi di antara mereka.

Fitur utama SurfMVP adalah bahwa setiap lapisan dalam MVP dipisahkan oleh protokol. Gambar menunjukkan diagram lapisan dan hubungan protokol di antara mereka. Protokol diperlukan agar setiap lapisan terpisah dari yang lain dan secara teori mudah diganti. Setiap lapisan tidak boleh mengungkapkan rincian implementasi.
Mari kita pertimbangkan secara terpisah:
ViewInput - mengimplementasikan Lihat sendiri, Presenter menyimpan tautannya. Protokol ini menjelaskan metode yang dengannya Presenter dapat mengontrol Lihat , mentransfer data, mengubah status, dan sebagainya.
ViewOutput - mengimplementasikan Presenter , View memegang tautannya. Protokol menjelaskan serangkaian tindakan yang dapat terjadi dalam metode Tampilan , dan siklus hidup, misalnya, peristiwa interaksi pengguna dengan layar.
RouterInput - mengimplementasikan Router , dan Presenter menyimpan tautan, karena itu adalah satu-satunya yang bertanggung jawab untuk memulai navigasi lebih lanjut dalam aplikasi.
ModuleTransitionable - View diimplementasikan, Router menyimpan tautan ke sana. Ini adalah satu-satunya protokol "dasar" di SurfMVP . Diperlukan untuk menyediakan kepada Router serangkaian metode untuk bekerja dengan navigasi aplikasi.
ModuleInput - Menerapkan Presenter . Protokol ini harus berisi metode dimana modul lain yang memiliki tautan ke protokol ini dapat mengubah keadaan modul saat ini.
ModuleOutput - mengimplementasikan Presenter dari modul pemanggil, tautannya menyimpan Presenter dari module yang dipanggil. Jika layar profil dapat ditampilkan dari modul berita, maka NewsPresenter harus mengimplementasikan ProfileModuleOutput , dan ProfilePresenter harus berisi tautan ke sana.
ModuleOutput diteruskan ke Configurator modul yang disebut dan diinstal di sana di Presenter . Berisi metode modul yang memengaruhi perilaku modul pemanggilan.
Masalah SurfMVP
Berdasarkan semua hal di atas, ada satu masalah utama - navigasi. Meskipun pesan untuk menyoroti entitas Router yang terpisah adalah masalah navigasi, ternyata, mereka hilang, tetapi tidak lama. SurfMVP telah berhasil digunakan pada proyek-proyek dengan navigasi datar yang sederhana, tanpa DeepLinks dan Pemberitahuan-Push yang kompleks.
Gambar di bawah ini secara skematis menunjukkan navigasi dalam aplikasi dengan SurfMVP. Setiap modul individu berkomunikasi dengan yang lain melalui Router sendiri. Dengan demikian, navigasi setiap aliran dalam aplikasi dibangun.

Jenis navigasi ini sangat cocok untuk kasus ketika pengguna melewati aliran pilihannya dalam aplikasi. Sebagai contoh, pada gambar di bawah ini: pengguna melewati layar dari titik A ke titik D, jadi dia sendiri membangun tumpukan tempat dia harus pergi dan kembali dengan cara yang sama.

Masalah mulai pada saat ketika perlu untuk mentransfer pengguna dari titik A ke titik D, dan ini harus terjadi tanpa partisipasinya. Misalnya, jika pengguna mengklik Pemberitahuan Push atau mengikuti tautan dari aplikasi pihak ketiga. Dalam hal SurfMVP, kita harus menambahkan Router global yang akan mengontrol navigasi terlepas dari di mana pengguna saat ini berada di aplikasi. Untuk mengatasi masalah ini secara global, kami memutuskan untuk menggunakan koordinator, mari beralih ke mereka.

SurfMVP terkoordinasi

SurfMVP terkoordinasi adalah pola arsitektur di mana, tidak seperti SurfMVP, kami menghapus entitas Router yang ada di dalam setiap modul individu. Paradigma membangun aplikasi telah sedikit berubah. Modul tidak lagi sepenuhnya independen. Setiap modul, kecuali yang sepenuhnya dapat digunakan kembali, terletak di UserFlow terpisah yang terpisah, yang, seperti yang direncanakan, harus melakukan beberapa tindakan umum yang mengarahkan pengguna ke hasil yang diinginkan.
Contoh aliran seperti itu dalam aplikasi kita adalah aliran pembayaran. Pembayaran adalah seperangkat layar yang memungkinkan pengguna untuk melakukan transfer atau pembayaran dengan berbagai cara.
Dalam SurfMVP Terkoordinasi, entitas Router menggantikan entitas Koordinator , yang sekarang bertanggung jawab untuk menavigasi tidak satu modul terpisah, tetapi satu set modul yang secara logis terhubung satu sama lain. Ini menyederhanakan navigasi dan bekerja dengan aplikasi. Secara skematis, aplikasi kita terlihat seperti ini:

Di bagian paling atas adalah ApplicationCoordinator, yang bertanggung jawab untuk perutean awal dalam aplikasi. Misalnya, sebuah kasus, ketika pengguna diotorisasi, maka kami akan segera mengirimnya ke bagian utama aplikasi, jika tidak, kami akan mengirimnya ke layar otorisasi.
Jika kita memiliki Deeplinks atau Push-Notifications di aplikasi kita, kita selalu dapat mengatur inisialisasi dan memulai aturan untuk koordinator sehingga mereka membangun tumpukan langsung ke titik D yang diinginkan, yang telah kita bicarakan sebelumnya.

Secara skematis, navigasi kami sekarang terlihat seperti ini. Setiap individu UserFlow merujuk pada koordinatornya sendiri, yang pada gilirannya memutuskan apa yang akan terjadi di masa depan. Tanggung jawab untuk mentransmisikan data dan memulai navigasi lebih lanjut sekarang berada di tangan koordinator, ia sudah dikaitkan dengan modul lain atau koordinator lain untuk terus membangun tumpukan navigasi.
Pro dan Kontra dari SurfMVP Terkoordinasi
Keuntungan:
- Keuntungan utama dari pendekatan koordinator adalah kemampuan untuk menggunakan kembali seluruh blok navigasi dalam aplikasi. Sekarang, dari mana saja dalam aplikasi, dimungkinkan untuk memanggil koordinator ini dan tidak memikirkan apa pun selain menyelesaikan pekerjaannya.
- Karena logika navigasi terisolasi di dalam koordinator yang terpisah, sekarang jauh lebih nyaman untuk mengikuti navigasi: cukup buka satu file dan seluruh gambar di depan mata Anda. Tidak ada lagi kebutuhan untuk menembus semua modul individu untuk memahami apa yang mereka raih, merakit aplikasi dan melihat desain.
- Lebih nyaman untuk mendesain dalam tim besar. Cukup pada tahap desain fitur baru yang terpisah untuk mengalokasikan waktu untuk membangun seluruh navigasi dan menginisialisasi semua modul, setelah itu akan mendelegasikan pengembangan ke sejumlah besar pengembang, dan akan ada jauh lebih sedikit masalah dengan integrasi layar ini antara satu sama lain.
- Integrasi Deeplinks dan Push-Notifications tidak lagi memusingkan.
Kekurangan:
Seperti halnya pendekatan arsitektur, ada kerugian untuk SurfMVP terkoordinasi.
- Koordinator besar terluka. Karena konsentrasi semua logika di satu tempat, menjadi jauh lebih sulit untuk tidak tenggelam dalam sejumlah besar baris kode. Jika Anda tidak mengikuti prinsip tanggung jawab bersama, maka tentu saja, koordinator dapat tumbuh menjadi monster besar, dan semua keuntungan dari keterbacaan kode akan mudah menguap.
- Anda harus banyak menulis untuk mencapai kode yang indah. Karena banyaknya lapisan dalam aplikasi, yang masing-masing bertanggung jawab atas tindakan terpisah, Anda harus menerobos lapisan ini untuk mencapai koordinator yang diinginkan.
- Kebocoran Memori - masalahnya bukan hal baru, tetapi Anda harus mengikuti masalah ini agar tidak masuk ke dalam lubang. Alasan utama kebocoran memori ketika bekerja dengan koordinator adalah mempertahankan siklus dalam modul panggilan balik. Jadi, Anda perlu memantau dengan seksama tautan kuat di dalam penutupan.
Kasus khasKasus khas adalah inisialisasi Koordinator baru dan implementasi penutupan akhir. Menangkap weak coordinator
adalah wajib, jika tidak, Koordinator akan merujuk pada dirinya sendiri, yang akan menyebabkan kebocoran dalam bentuk AuthCoordinator.
func runAuthFlow() { let coordinator = AuthCoordinator(router: MainRouter()) coordinator.finishFlow = { [weak self, weak coordinator] in self?.removeDependency(coordinator) } self.addDependency(coordinator) coordinator.start() }
Kesimpulan
Pada tahap desain, kami meremehkan kompleksitas proyek dan memilih pendekatan arsitektur yang salah. Tetapi kesalahan ini membantu membentuk seperangkat aturan dan lebih hati-hati mendekati pilihan arsitektur ketika memulai proyek.
Kapan menggunakan SurfMVP Terkoordinasi
Bahkan, saat Anda inginkan, maka gunakan, tetapi kami mematuhi ketentuan berikut:
- Struktur layarnya kompleks dan dapat berubah;
- Ada Deeplinks dan / atau Pemberitahuan Push dengan navigasi;
- Penting untuk bekerja dalam tim besar;
Kapan menggunakan SurfMVP
Kami tidak melupakan pola arsitektur pertama kami. Kami masih menggunakannya di studio ketika mengembangkan proyek jika memenuhi persyaratan berikut:
- Proyek ini cukup kecil dan tidak berencana untuk berkembang pesat;
- Proyek ini memiliki struktur layar yang sangat sederhana, dan tidak mengalami perubahan yang kuat.
Bahan tambahan
Pada artikel ini, saya berbagi masalah dengan arsitektur yang kami temui saat bekerja. Tentu saja, pilihan arsitektur mana yang akan digunakan tetap ada pada Anda. Pada artikel selanjutnya saya akan berbagi masalah backend dalam proyek-proyek besar dan memberi tahu bagaimana kami menyelesaikannya. Tetap disini!