Arsitektur bersih dalam konteks pengembangan lintas platform

Halo semuanya. Baru-baru ini, beberapa artikel telah ditulis dengan topik arsitektur bersih. Artinya, arsitektur bersih yang memungkinkan Anda untuk menulis aplikasi yang nyaman untuk dirawat dan diuji. Anda dapat membaca tentang arsitektur murni itu sendiri dalam artikel indah seperti: Kesalahpahaman Arsitektur Bersih atau Arsitektur Bersih , jadi saya tidak melihat alasan untuk mengulang apa yang telah ditulis.

Untuk memulai, izinkan saya memperkenalkan diri, nama saya Kakushev Rasul. Kebetulan saya secara bersamaan terlibat dalam pengembangan asli pada ios dan android, serta pengembangan kode backend untuk aplikasi mobile di Navibit. Ini masih merupakan perusahaan yang sedikit dikenal, yang hanya bersiap memasuki pasar untuk penjualan bahan bangunan. Kami memiliki tim yang sangat kecil, dan karena itu pengembangan aplikasi seluler sepenuhnya berada di pundak saya (belum terlalu profesional).

Dalam pekerjaan saya, saya sering harus membuat satu aplikasi di iOS dan Android, dan seperti yang Anda mengerti, karena perbedaan platform, saya sering harus menulis fungsi yang sama beberapa kali. Ini membutuhkan banyak waktu, dan beberapa waktu yang lalu, ketika saya bertemu arsitektur bersih, saya datang dengan pemikiran berikut: kotlin dan bahasa cepat sangat mirip, namun platform berbeda, tetapi dalam arsitektur bersih ada lapisan domain yang tidak terikat ke platform , tetapi mengandung logika bisnis murni. Apa yang akan terjadi jika Anda hanya mengambil seluruh lapisan domain dari android dan mentransfernya ke ios, dengan perubahan minimal?

Nah, dikandung - dilakukan. Saya memulai transfer. Dan memang idenya ternyata sebagian besar benar. Nilailah sendiri. Sebagai contoh, berikut ini adalah satu interaktor di kotlin dan swift:

Kotlin (Android)

class AuthInteractor @Inject internal constructor(private val authRepository: AuthRepository, private val profileRepository: ProfileRepository) { fun auth(login: String, password: String, cityId: Int): Single<Auth> = authRepository.auth(login.trim { it <= ' ' }, password.trim { it <= ' ' }, cityId, cloudToken) fun restore(login: String, password: String, cityId: Int, confirmHash: String): Single<AuthInfo> = authRepository.restore(login.trim { it <= ' ' }, password.trim { it <= ' ' }, cityId, confirmHash) fun restore(password: String, confirmHash: String): Single<AuthInfo> = authRepository.restore(password.trim { it <= ' ' }, confirmHash) fun getToken(): String = authRepository.checkIsAuth() fun register(login: String, family: String, name: String, password: String, cityId: Int, confirmHash: String): Single<AuthInfo> = authRepository.register(login.trim { it <= ' ' }, family.trim { it <= ' ' }, name.trim { it <= ' ' }, password.trim { it <= ' ' }, cityId, confirmHash) fun checkLoginAvailable(login: String): Single<LoginAvailable> = authRepository.checkLoginAvailable(login) fun saveTempCityInfo(authCityInfo: AuthCityInfo?) = authRepository.saveTempCityInfo(authCityInfo) fun checkPassword(password: String): Single<AuthInfo> = authRepository.checkPassword(password) fun auth(auth: Auth) { authRepository.saveToken(auth.token!!) profileRepository.saveProfile(auth.name!!, auth.phone!!, auth.location!!) } companion object { const val AUTH_ERROR = "HTTP 401 Unauthorized" } } 

Swift (iOS):

 class AuthInteractor { public static let AUTH_ERROR = "HTTP 401 Unauthorized" private let authRepository: AuthRepository private let profileRepository: ProfileRepository private let cloudMessagingRepository: CloudMessagingRepository init(authRepository: AuthRepository, profileRepository: ProfileRepository, cloudMessagingRepository: CloudMessagingRepository) { self.authRepository = authRepository self.profileRepository = profileRepository self.cloudMessagingRepository = cloudMessagingRepository } func auth(login: String, password: String, cityId: Int) -> Observable<Auth> { return authRepository.auth(login: login.trim(), password: password.trim(), cityId: cityId, cloudMessagingToken: cloudMessagingRepository.getCloudToken()) } func restore(login: String, password: String, cityId: Int, confirmHash: String) -> Observable<AuthInfo> { return authRepository.restore(login: login.trim(), password: password.trim(), cityId: cityId, confirmHash: confirmHash) } func restore(password: String, confirmHash: String) -> Observable<AuthInfo> { return authRepository.restore(password: password.trim(), confirmHash: confirmHash) } func getToken() -> String { return authRepository.checkIsAuth() } func register(login: String, family: String, name: String, password: String, cityId: Int, confirmHash: String) -> Observable<AuthInfo> { return authRepository.register(login: login.trim(), family: family.trim(), name: name.trim(), password: password.trim(), cityId: cityId, confirmHash: confirmHash) } func checkLoginAvailable(login: String) -> Observable<LoginAvailable> { return authRepository.checkLoginAvailable(login: login) } func saveTempCityInfo(authCityInfo: AuthCityInfo?) { authRepository.saveTempCityInfo(authCityInfo: authCityInfo) } func checkPassword(password: String) -> Observable<AuthInfo> { return authRepository.checkPassword(password: password) } func auth(auth: Auth) { authRepository.saveToken(token: auth.token) profileRepository.saveProfile(name: auth.name, phone: auth.phone, location: auth.location) } } 

Atau inilah contoh tampilan antarmuka repositori pada platform berbeda:

Kotlin (Android)

 interface AuthRepository { fun auth(login: String, password: String, cityId: Int, cloudMessagingToken: String): Single<Auth> fun register(login: String, family: String, name: String, password: String, cityId: Int, confirmHash: String): Single<AuthInfo> fun restore(login: String, password: String, cityId: Int, confirmHash: String): Single<AuthInfo> fun restore(password: String, confirmHash: String): Single<AuthInfo> fun checkLoginAvailable(login: String): Single<LoginAvailable> fun sendCode(login: String): Single<CodeCheck> fun checkCode(hash: String, code: String): Single<CodeConfirm> fun checkIsAuth(): String fun saveToken(token: String) fun removeToken() fun notifyConfirmHashListener(confirmHash: String) fun getResendTimer(time: Long): Observable<Long> fun checkPassword(password: String): Single<AuthInfo> fun saveTempCityInfo(authCityInfo: AuthCityInfo?) fun saveTempConfirmInfo(codeConfirmInfo: CodeConfirmInfo) fun getTempCityInfo(): AuthCityInfo? fun getConfirmHashListener(): Observable<String> fun getTempConfirmInfo(): CodeConfirmInfo? } 

Swift (iOS):

 protocol AuthRepository { func auth(login: String, password: String, cityId: Int, cloudMessagingToken: String) -> Observable<Auth> func register(login: String, family: String, name: String, password: String, cityId: Int, confirmHash: String) -> Observable<AuthInfo> func restore(login: String, password: String, cityId: Int, confirmHash: String) -> Observable<AuthInfo> func restore(password: String, confirmHash: String) -> Observable<AuthInfo> func checkLoginAvailable(login: String) -> Observable<LoginAvailable> func sendCode(login: String) -> Observable<CodeCheck> func checkCode(hash: String, code: String) -> Observable<CodeConfirm> func checkIsAuth() ->String func saveToken(token: String) func removeToken() func notifyConfirmHashListener(confirmHash: String) func getResendTimer(time: Int) -> Observable<Int> func checkPassword(password: String) -> Observable<AuthInfo> func saveTempCityInfo(authCityInfo: AuthCityInfo?) func saveTempConfirmInfo(codeConfirmInfo: CodeConfirmInfo) func getTempCityInfo() -> AuthCityInfo? func getConfirmHashListener() -> Observable<String> func getTempConfirmInfo() -> CodeConfirmInfo? } 

Situasinya mirip dengan lapisan presentasi, karena penyaji dan antarmuka tampilan pada kedua platform adalah sama. Oleh karena itu, berkat transfer semacam itu, kecepatan pengembangan saya hampir dua kali lipat, karena karena domain dan lapisan presentasi sudah sepenuhnya terbentuk pada kedua platform, tetap merupakan tugas kecil untuk menghubungkan perpustakaan tertentu dan memodifikasi lapisan ui dan data.

Terima kasih sudah membaca sampai akhir. Saya harap artikel ini akan bermanfaat bagi pengembang seluler yang terlibat dalam pengembangan asli. Semua yang terbaik

Source: https://habr.com/ru/post/id419173/


All Articles