Saya seorang pengembang iOS dengan pengalaman dan pertanyaan ini sangat menarik bagi saya. Saya melihat banyak sumber dan bahan yang berbeda tentang topik ini, tetapi saya masih bingung. Apa arsitektur terbaik untuk aplikasi jaringan iOS? Maksud saya kerangka abstrak dasar, pola, yang akan cocok dengan setiap aplikasi jaringan apakah itu aplikasi kecil yang hanya memiliki beberapa permintaan server atau klien REST yang kompleks. Apple merekomendasikan untuk digunakan MVC
sebagai pendekatan arsitektur dasar untuk semua aplikasi iOS, tetapi tidak satu MVC
pun MVVM
pola yang lebih modern menjelaskan di mana harus meletakkan kode logika jaringan dan bagaimana mengaturnya secara umum.
Apakah saya perlu mengembangkan sesuatu seperti MVCS
( S
untuk Service
) dan dalam Service
lapisan ini menaruh semua API
permintaan dan logika jaringan lainnya, yang dalam perspektif mungkin sangat kompleks? Setelah melakukan penelitian, saya menemukan dua pendekatan dasar untuk ini. Di sini direkomendasikan untuk membuat kelas terpisah untuk setiap permintaan jaringan ke layanan web API
(seperti LoginRequest
kelas atau PostCommentRequest
kelas dan sebagainya) yang semuanya mewarisi dari kelas abstrak permintaan dasar AbstractBaseRequest
dan selain itu untuk membuat beberapa manajer jaringan global yang merangkum kode jaringan umum dan preferensi lain (mungkin AFNetworking
kustomisasi atauRestKit
tuning, jika kita memiliki pemetaan objek yang kompleks dan kegigihan, atau bahkan implementasi komunikasi jaringan sendiri dengan API standar). Tetapi pendekatan ini sepertinya merupakan biaya tambahan bagi saya. Pendekatan lain adalah untuk memiliki beberapa tunggal API
operator atau kelas manajer seperti dalam pendekatan pertama, tetapi tidak untuk membuat kelas untuk setiap permintaan dan bukan untuk merangkum setiap permintaan sebagai metode contoh umum dari kelas ini manager seperti: fetchContacts
, loginUser
metode, dll Jadi, apa yang apakah cara terbaik dan benar? Apakah ada pendekatan menarik lainnya yang belum saya ketahui?
Dan haruskah saya membuat lapisan lain untuk semua hal-hal jaringan seperti ini Service
, atau NetworkProvider
lapisan atau apa pun di atas MVC
arsitektur saya , atau lapisan ini harus diintegrasikan (disuntikkan) ke dalam MVC
lapisan yang ada misalnya Model
?
Saya tahu ada pendekatan yang indah, atau bagaimana monster seluler seperti klien Facebook atau klien LinkedIn menghadapi kompleksitas logika jaringan yang tumbuh secara eksponensial?
Saya tahu tidak ada jawaban pasti dan formal untuk masalah ini. Tujuan dari pertanyaan ini adalah untuk mengumpulkan pendekatan yang paling menarik dari pengembang iOS yang berpengalaman . Pendekatan yang disarankan terbaik akan ditandai sebagai diterima dan diberikan dengan hadiah reputasi, yang lain akan dibatalkan suara. Sebagian besar pertanyaan teoritis dan penelitian. Saya ingin memahami pendekatan arsitektur dasar, abstrak, dan benar untuk aplikasi jaringan di iOS. Saya berharap penjelasan rinci dari pengembang berpengalaman.
sumber
Jawaban:
I want to understand basic, abstract and correct architectural approach for networking applications in iOS
: tidak ada pendekatan "yang terbaik", atau "yang paling benar" untuk membangun arsitektur aplikasi. Ini adalah pekerjaan yang sangat kreatif. Anda harus selalu memilih arsitektur yang paling mudah dan dapat dikembangkan, yang akan jelas bagi pengembang mana pun, yang mulai mengerjakan proyek Anda atau pengembang lain di tim Anda, tetapi saya setuju, bahwa mungkin ada "baik" dan "buruk" " Arsitektur.Anda berkata:
collect the most interesting approaches from experienced iOS developers
Saya tidak berpikir bahwa pendekatan saya adalah yang paling menarik atau benar, tetapi saya telah menggunakannya dalam beberapa proyek dan puas dengan itu. Ini adalah pendekatan hybrid dari yang telah Anda sebutkan di atas, dan juga dengan peningkatan dari upaya penelitian saya sendiri. Saya menarik dalam masalah membangun pendekatan, yang menggabungkan beberapa pola dan idiom terkenal. Saya pikir banyak pola perusahaan Fowler dapat berhasil diterapkan ke aplikasi seluler. Berikut adalah daftar yang paling menarik, yang dapat kami terapkan untuk membuat arsitektur aplikasi iOS ( menurut saya ): Lapisan Layanan , Unit Kerja , Fasad Jarak Jauh , Objek Transfer Data ,Gateway , Layer Supertype , Kasus Khusus , Model Domain . Anda harus selalu merancang lapisan model dengan benar dan jangan lupa tentang kegigihan (ini dapat secara signifikan meningkatkan kinerja aplikasi Anda). Anda bisa menggunakannyaCore Data
untuk ini. Tapi Anda tidak boleh lupa, ituCore Data
bukan ORM atau database, tetapi manajer grafik objek dengan ketekunan sebagai pilihan yang baik. Jadi, sangat seringCore Data
bisa terlalu berat untuk kebutuhan Anda dan Anda dapat melihat solusi baru seperti Realm dan Couchbase Lite , atau membangun pemetaan objek / lapisan kegigihan ringan Anda sendiri, berdasarkan pada SQLite mentah atau LevelDB. Saya juga menyarankan Anda untuk membiasakan diri dengan Desain Berbasis Domain dan CQRS .Pada awalnya, saya pikir, kita harus membuat layer lain untuk jaringan, karena kita tidak ingin pengendali gemuk atau model yang berat dan kewalahan. Saya tidak percaya pada
fat model, skinny controller
hal - hal itu. Tetapi saya benar- benar percaya padaskinny everything
pendekatan, karena tidak ada kelas yang harus gemuk, tidak pernah. Semua jaringan secara umum dapat diabstraksi sebagai logika bisnis, akibatnya kita harus memiliki lapisan lain, di mana kita dapat meletakkannya. Layer Layanan adalah yang kami butuhkan:Di
MVC
ranah kamiService Layer
adalah sesuatu seperti mediator antara model domain dan pengontrol. Ada variasi yang agak mirip dari pendekatan ini yang disebut MVCS di mana aStore
sebenarnya adalahService
layer kita .Store
contoh vends model dan menangani jaringan, caching dll. Saya ingin menyebutkan bahwa Anda tidak harus menulis semua jaringan dan logika bisnis di lapisan layanan Anda. Ini juga dapat dianggap sebagai desain yang buruk. Untuk info lebih lanjut, lihat model domain Anemic and Rich . Beberapa metode layanan dan logika bisnis dapat ditangani dalam model, sehingga akan menjadi model "kaya" (dengan perilaku).Saya selalu menggunakan dua pustaka: AFNetworking 2.0 dan ReactiveCocoa . Saya pikir itu harus dimiliki untuk aplikasi modern yang berinteraksi dengan jaringan dan layanan web atau mengandung logika UI yang kompleks.
ARSITEKTUR
Pada awalnya saya membuat
APIClient
kelas umum , yang merupakan subclass dari AFHTTPSessionManager . Ini adalah pekerja keras dari semua jaringan dalam aplikasi: semua kelas layanan mendelegasikan permintaan REST yang sebenarnya. Ini berisi semua penyesuaian klien HTTP, yang saya butuhkan dalam aplikasi tertentu: SSL menyematkan, memproses kesalahan dan membuatNSError
objek langsung dengan alasan kegagalan terperinci dan deskripsi semuaAPI
dan kesalahan koneksi (dalam hal ini pengontrol akan dapat menampilkan pesan yang benar untuk pengguna), mengatur permintaan dan tanggapan serializer, header http dan hal-hal lain yang berhubungan dengan jaringan. Lalu aku logis membagi semua permintaan API ke subservices atau, lebih tepatnya, microservices :UserSerivces
,CommonServices
,SecurityServices
,FriendsServices
dan seterusnya, sesuai dengan logika bisnis yang mereka terapkan. Masing-masing layanan microser ini adalah kelas yang terpisah. Mereka, bersama-sama, membentuk aService Layer
. Kelas-kelas ini berisi metode untuk setiap permintaan API, memproses model domain dan selalu mengembalikan aRACSignal
dengan model respons yang diurai atauNSError
ke pemanggil.Saya ingin menyebutkan bahwa jika Anda memiliki logika serialisasi model yang kompleks - kemudian buat layer lain untuk itu: sesuatu seperti Data Mapper tetapi lebih umum misalnya JSON / XML -> Model mapper. Jika Anda memiliki cache: maka buatlah sebagai layer / layanan terpisah juga (Anda seharusnya tidak mencampur logika bisnis dengan caching). Mengapa? Karena lapisan caching yang benar bisa sangat kompleks dengan gotcha sendiri. Orang-orang menerapkan logika kompleks untuk mendapatkan caching yang valid dan dapat diprediksi seperti caching monoid dengan proyeksi berdasarkan para profesional. Anda dapat membaca tentang perpustakaan yang indah ini bernama Carlos untuk lebih mengerti. Dan jangan lupa bahwa Data Inti benar-benar dapat membantu Anda dengan semua masalah caching dan akan memungkinkan Anda untuk menulis lebih sedikit logika. Juga, jika Anda memiliki beberapa logika antara
NSManagedObjectContext
dan model permintaan server, Anda dapat menggunakanPola repositori , yang memisahkan logika yang mengambil data dan memetakannya ke model entitas dari logika bisnis yang bertindak pada model. Jadi, saya menyarankan untuk menggunakan pola Repositori bahkan ketika Anda memiliki arsitektur berbasis Core Data. Hal-hal abstrak Repository kaleng, sepertiNSFetchRequest
,NSEntityDescription
,NSPredicate
dan sebagainya untuk metode biasa sepertiget
atauput
.Setelah semua tindakan ini di lapisan Layanan, pemanggil (view controller) dapat melakukan beberapa hal asinkron yang kompleks dengan respons: manipulasi sinyal, rantai, pemetaan, dll. Dengan bantuan
ReactiveCocoa
primitif, atau hanya berlangganan dan menunjukkan hasilnya dalam tampilan . Saya menyuntikkan dengan Dependency Injection di semua kelas layanan ini sayaAPIClient
, yang akan menerjemahkan panggilan layanan tertentu ke yang sesuaiGET
,POST
,PUT
,DELETE
, dll permintaan ke titik akhir REST. Dalam halAPIClient
ini diteruskan secara implisit ke semua pengontrol, Anda dapat membuat ini eksplisit dengan parametris atasAPIClient
kelas layanan. Ini bisa masuk akal jika Anda ingin menggunakan berbagai penyesuaianAPIClient
untuk kelas layanan tertentu, tetapi jika Anda, untuk beberapa alasan, tidak ingin salinan tambahan atau Anda yakin bahwa Anda akan selalu menggunakan satu contoh khusus (tanpa penyesuaian) dariAPIClient
- membuat singleton, tapi JANGAN, tolong JANGAN Akan membuat kelas layanan sebagai lajang.Kemudian setiap view controller lagi dengan DI menyuntikkan kelas layanan yang dibutuhkan, memanggil metode layanan yang sesuai dan menyusun hasilnya dengan logika UI. Untuk injeksi ketergantungan saya suka menggunakan BloodMagic atau kerangka kerja Topan yang lebih kuat . Saya tidak pernah menggunakan lajang,
APIManagerWhatever
kelas dewa atau hal-hal salah lainnya. Karena jika Anda memanggil kelas AndaWhateverManager
, ini menunjukkan bahwa Anda tidak tahu tujuannya dan itu adalah pilihan desain yang buruk . Lajang juga merupakan anti-pola, dan dalam kebanyakan kasus (kecuali yang langka) adalah solusi yang salah . Singleton harus dipertimbangkan hanya jika ketiga kriteria berikut dipenuhi:Dalam kasus kami, kepemilikan satu instance tidak menjadi masalah dan kami juga tidak memerlukan akses global setelah kami membagi manajer god kami menjadi layanan, karena sekarang hanya satu atau beberapa pengontrol khusus yang memerlukan layanan tertentu (mis.
UserProfile
Kebutuhan pengontrolUserServices
dan sebagainya) .Kami harus selalu menghormati
S
prinsip dalam SOLID dan menggunakan pemisahan kekhawatiran , jadi jangan letakkan semua metode layanan dan panggilan jaringan Anda dalam satu kelas, karena ini gila, terutama jika Anda mengembangkan aplikasi perusahaan besar. Itu sebabnya kita harus mempertimbangkan injeksi ketergantungan dan pendekatan layanan. Saya menganggap pendekatan ini sebagai modern dan pasca-OO . Dalam hal ini kami membagi aplikasi kami menjadi dua bagian: kontrol logika (pengontrol dan peristiwa) dan parameter.Berikut ini adalah alur kerja umum arsitektur saya. Misalkan kita memiliki
FriendsViewController
, yang menampilkan daftar teman pengguna dan kita memiliki opsi untuk menghapus dari teman. Saya membuat metode diFriendsServices
kelas saya yang disebut:di mana
Friend
model / objek domain (atau bisa juga hanyaUser
objek jika mereka memiliki atribut yang sama). Underhood metode ini mem-parsingFriend
untukNSDictionary
parameter JSONfriend_id
,name
,surname
,friend_request_id
dan sebagainya. Saya selalu menggunakan pustaka Mantle untuk jenis boilerplate dan untuk lapisan model saya (parsing maju dan mundur, mengelola hierarki objek bersarang di JSON dan sebagainya). Setelah parsing itu panggilanAPIClient
DELETE
metode untuk membuat permintaan SISA aktual dan kembaliResponse
dalamRACSignal
ke pemanggil (FriendsViewController
dalam kasus kami) untuk menampilkan pesan yang sesuai untuk pengguna atau apa pun.Jika aplikasi kita sangat besar, kita harus memisahkan logika kita lebih jelas. Misalnya tidak selalu baik untuk mencampur
Repository
atau memodelkan logika denganService
satu. Ketika saya menjelaskan pendekatan saya, saya telah mengatakan bahwaremoveFriend
metode harus diService
lapisan, tetapi jika kita akan lebih bertele-tele kita dapat melihat bahwa itu lebih baik milikRepository
. Mari kita ingat apa itu Repositori. Eric Evans memberikan deskripsi yang tepat dalam bukunya [DDD]:Jadi, pada
Repository
dasarnya adalah fasad yang menggunakan semantik gaya Koleksi (Tambah, Perbarui, Hapus) untuk menyediakan akses ke data / objek. Itu sebabnya ketika Anda memiliki sesuatu seperti:getFriendsList
,getUserGroups
,removeFriend
Anda dapat menempatkannya diRepository
, karena koleksi-seperti semantik yang cukup jelas di sini. Dan kode seperti:jelas merupakan logika bisnis, karena itu di luar
CRUD
operasi dasar dan menghubungkan dua objek domain (Friend
danRequest
), itu sebabnya ia harus ditempatkan diService
lapisan. Saya juga ingin memperhatikan: jangan membuat abstraksi yang tidak perlu . Gunakan semua pendekatan ini dengan bijak. Karena jika Anda akan membanjiri aplikasi Anda dengan abstraksi, ini akan meningkatkan kompleksitas aksidentalnya, dan kompleksitas menyebabkan lebih banyak masalah dalam sistem perangkat lunak daripada yang lainnyaSaya menggambarkan Anda contoh Objective-C "lama" tetapi pendekatan ini bisa sangat mudah diadaptasi untuk bahasa Swift dengan lebih banyak perbaikan, karena ia memiliki fitur yang lebih berguna dan gula fungsional. Saya sangat merekomendasikan untuk menggunakan perpustakaan ini: Moya . Hal ini memungkinkan Anda untuk membuat
APIClient
layer yang lebih elegan (pekerja keras kami seperti yang Anda ingat). SekarangAPIClient
penyedia kami akan menjadi tipe nilai (enum) dengan ekstensi yang sesuai dengan protokol dan meningkatkan pencocokan pola perusakan. Pencocokan enum + pola Swift memungkinkan kita untuk membuat tipe data aljabar seperti pada pemrograman fungsional klasik. Layanan microser kami akan menggunakanAPIClient
penyedia yang ditingkatkan ini seperti pada pendekatan Objective-C yang biasa. Untuk lapisan model alih-alihMantle
Anda bisa menggunakan perpustakaan ObjectMapperatau saya suka menggunakan perpustakaan Argo yang lebih elegan dan fungsional .Jadi, saya menggambarkan pendekatan arsitektur umum saya, yang dapat disesuaikan untuk aplikasi apa pun, saya pikir. Tentu saja bisa ada banyak perbaikan. Saya menyarankan Anda untuk belajar pemrograman fungsional, karena Anda bisa mendapatkan banyak manfaat dari itu, tetapi jangan terlalu jauh dengan itu. Menghilangkan keadaan yang bisa berubah secara global, dibagikan, dapat diubah, membuat model domain yang tidak dapat diubah atau membuat fungsi murni tanpa efek samping eksternal, umumnya, merupakan praktik yang baik, dan
Swift
bahasa baru mendorong hal ini. Tetapi selalu ingat, bahwa membebani kode Anda dengan pola fungsional murni yang murni, pendekatan kategori-teoretis adalah ide yang buruk , karena pengembang lain akan membaca dan mendukung kode Anda, dan mereka dapat frustrasi atau menakutkan dariprismatic profunctors
dan hal-hal semacam itu dalam model abadi Anda. Hal yang sama denganReactiveCocoa
: janganRACify
kode Anda terlalu banyak , karena dapat menjadi sangat cepat dibaca, terutama untuk pemula. Gunakan ketika itu benar-benar dapat menyederhanakan tujuan dan logika Anda.Jadi,
read a lot, mix, experiment, and try to pick up the best from different architectural approaches
. Itu adalah saran terbaik yang bisa saya berikan kepada Anda.sumber
". I don't like singletons. I have an opinion that if you decided to use singletons in your project you should have at least three criteria why you do this (I edited my answer). So I inject them (lazy of course and not each time, but
sekali `) di setiap pengontrolMenurut tujuan dari pertanyaan ini, saya ingin menggambarkan pendekatan arsitektur kami.
Pendekatan arsitektur
Arsitektur aplikasi iOS umum kami didasarkan pada pola-pola berikut: Lapisan layanan , MVVM , Pengikatan Data UI , Injeksi Ketergantungan ; dan paradigma Pemrograman Reaktif Fungsional .
Kami dapat mengiris aplikasi khas konsumen menghadap ke lapisan logis berikut:
Lapisan perakitan adalah titik bootstrap aplikasi kita. Ini berisi wadah Injeksi Ketergantungan dan deklarasi objek aplikasi dan dependensinya. Lapisan ini juga mungkin berisi konfigurasi aplikasi (url, kunci layanan pihak ke-3 dan seterusnya). Untuk tujuan ini kami menggunakan perpustakaan Typhoon .
Lapisan model berisi kelas model domain, validasi, pemetaan. Kami menggunakan perpustakaan Mantle untuk memetakan model kami: mendukung serialisasi / deserialisasi ke dalam
JSON
format danNSManagedObject
model. Untuk validasi dan bentuk representasi dari model kami, kami menggunakan FXForms dan FXModelValidation perpustakaan.Lapisan Layanan menyatakan layanan yang kami gunakan untuk berinteraksi dengan sistem eksternal untuk mengirim atau menerima data yang direpresentasikan dalam model domain kami. Jadi biasanya kami memiliki layanan untuk komunikasi dengan API server (per entitas), layanan pengiriman pesan (seperti PubNub ), layanan penyimpanan (seperti Amazon S3), dll. Pada dasarnya layanan membungkus objek yang disediakan oleh SDK (misalnya PubNub SDK) atau mengimplementasikan komunikasi mereka sendiri logika. Untuk jaringan umum kami menggunakan perpustakaan AFNetworking .
Tujuan lapisan penyimpanan adalah untuk mengatur penyimpanan data lokal pada perangkat. Kami menggunakan Data Inti atau Realm untuk ini (keduanya memiliki pro dan kontra, keputusan apa yang akan digunakan didasarkan pada spesifikasi nyata). Untuk pengaturan Data Inti, kami menggunakan pustaka MDMCoreData dan banyak kelas - penyimpanan - (mirip dengan layanan) yang menyediakan akses ke penyimpanan lokal untuk setiap entitas. Untuk Realm kami hanya menggunakan penyimpanan serupa untuk memiliki akses ke penyimpanan lokal.
Lapisan manajer adalah tempat di mana abstraksi / pembungkus kami tinggal.
Dalam peran manajer dapat:
Jadi, peran manajer dapat berupa objek apa pun yang mengimplementasikan logika aspek atau perhatian tertentu yang diperlukan untuk aplikasi yang berfungsi.
Kami mencoba untuk menghindari lajang, tetapi lapisan ini adalah tempat di mana mereka tinggal jika mereka diperlukan.
Lapisan koordinator menyediakan objek yang bergantung pada objek dari lapisan lain (Layanan, Penyimpanan, Model) untuk menggabungkan logika mereka ke dalam satu urutan pekerjaan yang diperlukan untuk modul tertentu (fitur, layar, kisah pengguna atau pengalaman pengguna). Biasanya rantai operasi asinkron dan tahu bagaimana bereaksi pada kasus-kasus keberhasilan dan kegagalan mereka. Sebagai contoh, Anda dapat membayangkan fitur olahpesan dan
MessagingCoordinator
objek yang sesuai . Menangani operasi pengiriman pesan mungkin terlihat seperti ini:Pada masing-masing langkah di atas, sebuah kesalahan ditangani bersamaan.
Lapisan UI terdiri dari sublayer berikut:
Untuk menghindari Pengontrol Tampilan Masif kami menggunakan pola MVVM dan mengimplementasikan logika yang diperlukan untuk presentasi UI di ViewModels. ViewModel biasanya memiliki koordinator dan manajer sebagai dependensi. ViewModels digunakan oleh ViewControllers dan beberapa jenis Tampilan (misalnya sel tampilan tabel). Perekat antara ViewControllers dan ViewModels adalah Data Binding dan pola Command. Untuk memungkinkan lem itu kami gunakan pustaka ReactiveCocoa .
Kami juga menggunakan ReactiveCocoa dan
RACSignal
konsepnya sebagai antarmuka dan mengembalikan tipe nilai dari semua koordinator, layanan, metode penyimpanan. Ini memungkinkan kita untuk rantai operasi, menjalankannya paralel atau seri, dan banyak hal berguna lainnya yang disediakan oleh ReactiveCocoa.Kami mencoba menerapkan perilaku UI dengan cara deklaratif. Penjilidan Data dan Tata Letak Otomatis sangat membantu untuk mencapai tujuan ini.
Lapisan infrastruktur berisi semua pembantu, ekstensi, utilitas yang diperlukan untuk pekerjaan aplikasi.
Pendekatan ini bekerja dengan baik untuk kami dan jenis aplikasi yang biasanya kami bangun. Tetapi Anda harus mengerti, bahwa ini hanyalah pendekatan subjektif yang harus disesuaikan / diubah untuk tujuan tim konkret.
Semoga ini bisa membantu Anda!
Anda juga dapat menemukan informasi lebih lanjut tentang proses pengembangan iOS di blog ini memposting Pengembangan iOS sebagai Layanan
sumber
Karena semua aplikasi iOS berbeda, saya pikir ada beberapa pendekatan berbeda di sini untuk dipertimbangkan, tetapi saya biasanya menggunakan cara ini:
Buat kelas manajer pusat (tunggal) untuk menangani semua permintaan API (biasanya bernama APICkomunikator) dan setiap contoh metode adalah panggilan API . Dan ada satu metode pusat (non-publik):
Sebagai catatan, saya menggunakan 2 pustaka / kerangka kerja utama, ReactiveCocoa dan AFNetworking. ReactiveCocoa menangani respons jaringan async dengan sempurna, Anda dapat melakukannya (sendNext :, sendError :, dll.).
Metode ini memanggil API, mendapatkan hasilnya dan mengirimkannya melalui RAC dalam format 'mentah' (seperti NSArray pengembalian AFNetworking).
Kemudian metode seperti
getStuffList:
yang disebut metode di atas berlangganan sinyal itu, mem-parsing data mentah menjadi objek (dengan sesuatu seperti Motis) dan mengirimkan objek satu per satu ke penelepon (getStuffList:
dan metode serupa juga mengembalikan sinyal yang dapat berlangganan pengontrol untuk berlangganan ).Kontroler berlangganan menerima objek oleh
subscribeNext:
blok dan menanganinya.Saya mencoba banyak cara di aplikasi yang berbeda tetapi yang ini bekerja paling baik dari semua jadi saya telah menggunakan ini di beberapa aplikasi baru-baru ini, cocok untuk proyek-proyek kecil dan besar dan mudah untuk memperpanjang dan memelihara jika ada sesuatu yang perlu dimodifikasi.
Semoga ini bisa membantu, saya ingin mendengar pendapat orang lain tentang pendekatan saya dan mungkin bagaimana orang lain berpikir ini dapat ditingkatkan.
sumber
+ (void)getAllUsersWithSuccess:(void(^)(NSArray*))success failure:(void(^)(NSError*))failure;
dan- (void)postWithSuccess:(void(^)(instancetype))success failure:(void(^)(NSError*))failure;
yang melakukan persiapan yang diperlukan dan kemudian memanggil manajer API.Dalam situasi saya, saya biasanya menggunakan perpustakaan ResKit untuk mengatur lapisan jaringan. Ini menyediakan penguraian yang mudah digunakan. Ini mengurangi upaya saya mengatur pemetaan untuk berbagai respons dan hal lain.
Saya hanya menambahkan beberapa kode untuk mengatur pemetaan secara otomatis. Saya mendefinisikan kelas dasar untuk model saya (bukan protokol karena banyak kode untuk memeriksa apakah beberapa metode diterapkan atau tidak, dan lebih sedikit kode dalam model itu sendiri):
MappableEntry.h
MappableEntry.m
Hubungan adalah objek yang mewakili objek bersarang dalam respons:
RelationshipObject.h
RelationshipObject.m
Lalu saya mengatur pemetaan untuk RestKit seperti ini:
ObjectMappingInitializer.h
ObjectMappingInitializer.m
Beberapa contoh implementasi MappableEntry:
User.h
Pengguna.m
Sekarang tentang pembungkus Permintaan:
Saya memiliki file header dengan definisi blok, untuk mengurangi panjang baris di semua kelas APIRequest:
APICallbacks.h
Dan Contoh kelas permintaan APIR yang saya gunakan:
LoginAPI.h
LoginAPI.m
Dan semua yang perlu Anda lakukan dalam kode, cukup menginisialisasi objek API dan menyebutnya kapan pun Anda membutuhkannya:
SomeViewController.m
Kode saya tidak sempurna, tetapi mudah diatur sekali dan digunakan untuk proyek yang berbeda. Jika itu menarik bagi siapa pun, mb saya bisa menghabiskan waktu dan membuat solusi universal untuknya di suatu tempat di GitHub dan CocoaPods.
sumber
Menurut saya semua arsitektur perangkat lunak didorong oleh kebutuhan. Jika ini untuk tujuan belajar atau pribadi, maka putuskan tujuan utama dan buatlah yang mendorong arsitektur. Jika ini adalah pekerjaan untuk disewa, maka kebutuhan bisnis adalah yang terpenting. Caranya adalah dengan tidak membiarkan benda-benda mengkilap mengalihkan perhatian Anda dari kebutuhan sebenarnya. Saya menemukan ini sulit dilakukan. Selalu ada hal-hal mengkilap baru yang muncul dalam bisnis ini dan banyak dari mereka tidak berguna, tetapi Anda tidak selalu bisa mengatakannya di muka. Berfokuslah pada kebutuhan dan rela meninggalkan pilihan-pilihan buruk jika Anda bisa.
Sebagai contoh, saya baru-baru ini membuat prototipe cepat dari aplikasi berbagi foto untuk bisnis lokal. Karena kebutuhan bisnis adalah untuk melakukan sesuatu yang cepat dan kotor, arsitektur akhirnya menjadi beberapa kode iOS untuk memunculkan kamera dan beberapa kode jaringan yang melekat pada Tombol Kirim yang mengunggah gambar ke toko S3 dan menulis ke domain SimpleDB. Kode itu sepele dan biayanya minimal dan klien memiliki koleksi foto yang dapat diukur yang dapat diakses melalui web dengan panggilan REST. Murah dan bodoh, aplikasi ini memiliki banyak kekurangan dan kadang-kadang akan mengunci UI, tetapi itu akan sia-sia untuk melakukan lebih banyak untuk prototipe dan memungkinkan mereka untuk digunakan untuk staf mereka dan menghasilkan ribuan gambar uji dengan mudah tanpa kinerja atau skalabilitas keprihatinan. Arsitektur jelek, tapi itu sesuai dengan kebutuhan dan biaya sempurna.
Proyek lain yang terlibat menerapkan database aman lokal yang disinkronkan dengan sistem perusahaan di latar belakang ketika jaringan tersedia. Saya membuat sinkronisasi latar belakang yang menggunakan RestKit karena tampaknya memiliki semua yang saya butuhkan. Tetapi saya harus menulis begitu banyak kode khusus untuk RestKit untuk berurusan dengan JSON istimewa sehingga saya bisa melakukan semuanya lebih cepat dengan menulis JSON saya sendiri ke transformasi CoreData. Namun, pelanggan ingin membawa aplikasi ini ke rumah dan saya merasa bahwa RestKit akan serupa dengan kerangka kerja yang mereka gunakan pada platform lain. Saya menunggu untuk melihat apakah itu keputusan yang bagus.
Sekali lagi, masalah bagi saya adalah fokus pada kebutuhan dan biarkan yang menentukan arsitektur. Saya berusaha keras untuk menghindari menggunakan paket pihak ketiga karena mereka membawa biaya yang hanya muncul setelah aplikasi berada di lapangan untuk sementara waktu. Saya mencoba menghindari membuat hierarki kelas karena jarang menghasilkan. Jika saya dapat menulis sesuatu dalam periode waktu yang masuk akal alih-alih mengadopsi paket yang tidak cocok dengan sempurna, maka saya melakukannya. Kode saya terstruktur dengan baik untuk debugging dan berkomentar dengan tepat, tetapi paket pihak ketiga jarang. Dengan itu, saya menemukan Jaringan AF terlalu berguna untuk diabaikan dan terstruktur dengan baik, berkomentar dengan baik, dan dipelihara dan saya sering menggunakannya! RestKit mencakup banyak kasus umum, tapi saya merasa seperti saya berkelahi ketika saya menggunakannya, dan sebagian besar sumber data yang saya temui penuh dengan kebiasaan dan masalah yang paling baik ditangani dengan kode khusus. Dalam beberapa aplikasi terakhir saya, saya hanya menggunakan konverter JSON bawaan dan menulis beberapa metode utilitas.
Satu pola yang selalu saya gunakan adalah untuk mendapatkan panggilan jaringan dari utas utama. 4-5 aplikasi terakhir yang saya lakukan mengatur tugas penghitung waktu latar belakang menggunakan dispatch_source_create yang sering bangun dan melakukan tugas jaringan sesuai kebutuhan. Anda perlu melakukan beberapa pekerjaan keselamatan utas dan memastikan bahwa kode modifikasi UI dikirim ke utas utama. Ini juga membantu untuk melakukan onboarding / inisialisasi Anda sedemikian rupa sehingga pengguna tidak merasa terbebani atau tertunda. Sejauh ini ini telah bekerja dengan cukup baik. Saya sarankan melihat hal-hal ini.
Akhirnya, saya berpikir bahwa ketika kita bekerja lebih banyak dan seiring OS berkembang, kita cenderung mengembangkan solusi yang lebih baik. Butuh waktu bertahun-tahun untuk melupakan keyakinan saya bahwa saya harus mengikuti pola dan desain yang menurut orang lain wajib. Jika saya bekerja dalam konteks di mana itu adalah bagian dari agama setempat, ahem, maksud saya praktik teknik terbaik departemen, maka saya mengikuti kebiasaan surat itu, itulah yang mereka bayar untuk saya. Tetapi saya jarang menemukan bahwa mengikuti desain dan pola lama adalah solusi optimal. Saya selalu mencoba melihat solusi melalui prisma kebutuhan bisnis dan membangun arsitektur untuk mencocokkannya dan menjaga hal-hal sesederhana mungkin. Ketika saya merasa tidak ada cukup di sana, tetapi semuanya bekerja dengan benar, maka saya berada di jalur yang benar.
sumber
Saya menggunakan pendekatan yang saya dapatkan dari sini: https://github.com/Constantine-Fry/Foursquare-API-v2 . Saya telah menulis ulang perpustakaan itu di Swift dan Anda dapat melihat pendekatan arsitektur dari bagian-bagian kode ini:
Pada dasarnya, ada subkelas NSOperation yang membuat NSURLRequest, mem-parsing respons JSON dan menambahkan blok panggilan balik dengan hasilnya ke antrian. Kelas API utama membangun NSURLRequest, menginisialisasi subclass NSOperation dan menambahkannya ke antrian.
sumber
Kami menggunakan beberapa pendekatan tergantung pada situasinya. Untuk sebagian besar hal, AFNetworking adalah pendekatan paling sederhana dan paling kuat di mana Anda dapat mengatur header, mengunggah data multi-bagian, menggunakan GET, POST, PUT & DELETE dan ada banyak kategori tambahan untuk UIKit yang memungkinkan Anda untuk misalnya mengatur gambar dari sebuah url. Dalam aplikasi yang kompleks dengan banyak panggilan, kadang-kadang kita abstraksi ke metode kenyamanan kita sendiri yang akan menjadi seperti:
Ada beberapa situasi di mana AFNetworking tidak sesuai namun seperti di mana Anda membuat kerangka kerja atau komponen pustaka lainnya karena AFNetworking mungkin sudah ada di basis kode lain. Dalam situasi ini, Anda akan menggunakan NSMutableURLRequest baik inline jika Anda membuat satu panggilan atau diabstraksi menjadi kelas permintaan / respons.
sumber
Saya menghindari lajang ketika merancang aplikasi saya. Mereka adalah tipikal untuk banyak orang, tetapi saya pikir Anda dapat menemukan solusi yang lebih elegan di tempat lain. Biasanya yang saya lakukan adalah membangun entitas saya di CoreData dan kemudian meletakkan kode REST saya dalam kategori NSManagedObject. Jika misalnya saya ingin membuat dan POST Pengguna baru, saya akan melakukan ini:
Saya menggunakan RESTKit untuk pemetaan objek dan menginisialisasi saat start up. Saya menemukan routing semua panggilan Anda melalui singleton menjadi buang-buang waktu dan menambahkan banyak boilerplate yang tidak diperlukan.
Dalam NSManagedObject + Extensions.m:
Dalam NSManagedObject + Networking.m:
Mengapa menambahkan kelas pembantu tambahan ketika Anda dapat memperluas fungsionalitas kelas dasar umum melalui kategori?
Jika Anda tertarik pada informasi lebih rinci tentang solusi saya, beri tahu saya. Saya senang berbagi.
sumber
Coba https://github.com/kevin0571/STNetTaskQueue
Buat permintaan API di kelas yang terpisah.
STNetTaskQueue akan berurusan dengan threading dan delegate / callback.
Dapat diperpanjang untuk berbagai protokol.
sumber
Dari perspektif desain murni kelas, Anda biasanya akan memiliki sesuatu seperti ini:
Kelas model data - Ini benar-benar tergantung pada berapa banyak entitas nyata yang Anda hadapi, dan bagaimana mereka terkait.
Misalnya, jika Anda memiliki array item yang akan ditampilkan dalam empat representasi berbeda (daftar, bagan, grafik dll), Anda akan memiliki satu kelas model data untuk daftar item, satu lagi untuk sebuah item. The daftar kelas item akan dibagi oleh empat pengendali tampilan - semua anak dari tab bar controller atau nav kontroler.
Kelas-kelas model data akan berguna tidak hanya menampilkan data, tetapi juga membuat serial dimana mereka masing-masing dapat mengekspos format serialisasi mereka sendiri melalui metode ekspor JSON / XML / CSV (atau apa pun).
Penting untuk dipahami bahwa Anda juga memerlukan kelas pembuat permintaan API yang memetakan langsung dengan titik akhir REST API Anda. Katakanlah Anda memiliki API yang mencatat pengguna - jadi kelas pembuat API Login Anda akan membuat payload POST JSON untuk api login. Dalam contoh lain, kelas pembuat permintaan API untuk daftar item katalog, API akan membuat string kueri GET untuk api terkait dan mengaktifkan kueri REST GET.
Kelas pembuat permintaan API ini biasanya akan menerima data dari pengontrol tampilan dan juga mengembalikan data yang sama untuk melihat pengontrol untuk pembaruan UI / operasi lainnya. View controller kemudian akan memutuskan bagaimana memperbarui objek Model Data dengan data itu.
Akhirnya, inti dari klien mengambil data API - REST yang tidak menyadari segala macam permintaan API yang dibuat oleh aplikasi Anda. Kelas ini lebih cenderung menjadi singleton, tetapi seperti yang ditunjukkan orang lain, itu tidak harus singleton.
Perhatikan bahwa tautan itu hanya implementasi biasa dan tidak mempertimbangkan skenario pertimbangan seperti sesi, cookie, dll, tetapi cukup untuk membuat Anda pergi tanpa menggunakan kerangka kerja pihak ke-3.
sumber
Pertanyaan ini sudah memiliki banyak jawaban yang sangat bagus dan luas, tetapi saya merasa saya harus menyebutkannya karena tidak ada orang lain yang memilikinya.
Alamofire for Swift. https://github.com/Alamofire/Alamofire
Ini dibuat oleh orang yang sama dengan AFNetworking, tetapi lebih dirancang secara langsung dengan mempertimbangkan Swift.
sumber
Saya pikir untuk saat ini proyek sedang menggunakan arsitektur MVVM dan Proyek besar menggunakan arsitektur VIPER dan berusaha untuk mencapai
Dan pendekatan Arsitektur untuk membangun aplikasi jaringan iOS (klien REST)
Masalah pemisahan untuk kode yang bersih dan mudah dibaca menghindari duplikasi:
inversi ketergantungan
Penanggung jawab utama:
Anda akan menemukan di sini adalah arsitektur GitHub MVVM dengan Proyek API Swift lainnya
sumber
Dalam rekayasa perangkat lunak seluler, yang paling banyak digunakan adalah pola Clean Architecture + MVVM dan Redux.
Arsitektur Bersih + MVVM terdiri dari 3 lapisan: Domain, Presentasi, Lapisan data. Di mana Lapisan Presentasi dan Lapisan Gudang Data bergantung pada Lapisan Domain:
Dan Presentation Layer terdiri dari ViewModels and Views (MVVM):
Dalam artikel ini, ada deskripsi yang lebih rinci tentang Arsitektur Bersih + MVVM https://tech.olx.com/clean-architecture-and-mvvm-on-ios-c9d167d9f5b3
sumber