
Sekitar setahun yang lalu, saya bergabung dengan tim CityMobil sebagai pengembang Android. Saya terbiasa dengan proyek baru untuk diri saya sendiri, pendekatan dan teknologi baru. Pada saat itu, Citimobil sudah memiliki sejarah yang agak panjang, seperti proyek yang saya adopsi, aplikasi Android untuk memesan taksi. Namun, seperti yang sering terjadi dalam kasus seperti itu, kode membawa jejak karakteristik dari solusi lama. Dan sekarang, setelah berhasil refactoring kode, saya ingin berbagi ide yang, menurut pendapat saya, dapat bermanfaat bagi mereka yang harus memperbaiki proyek yang sudah ada. Dan di atas semua itu, ini dapat berguna untuk perusahaan kecil dengan tim pengembangan kecil.
Suatu bisnis sering menguji ide-idenya, mengarahkan sumber daya yang terbatas padanya, dan mencoba untuk mendapatkan umpan balik, menguji hipotesisnya secepat mungkin. Pada saat-saat seperti itu, sebagai suatu peraturan, pemikiran berkualitas tinggi dan implementasi arsitektur proyek, dengan mempertimbangkan masa depan, mulai menghilang. Secara bertahap, proyek memperoleh fungsionalitas baru, persyaratan bisnis baru muncul, dan semua ini memengaruhi basis kode. "CityMobil" dalam hal ini tidak terkecuali. Proyek ini dikembangkan secara berurutan oleh beberapa tim di kantor lama, kemudian, selama perpindahan, didukung dan sebagian terkait dengan outsourcing. Kemudian mereka mulai membentuk tim baru, dan mereka menyerahkan saya mengerjakan proyek.
Pada waktu itu, "pengembangan" pindah ke kantor Moskow, pekerjaan berjalan lancar - tugas-tugas baru yang menarik dan ambisius muncul. Namun, warisan semakin banyak memasukkan tongkat ke roda, dan begitu kami menyadari bahwa saatnya telah tiba untuk perubahan besar. Sayangnya, tidak banyak literatur yang berguna ditemukan saat itu. Dapat dimengerti, diketahui dari pengalaman, hampir tidak mungkin untuk menemukan atau menemukan resep sempurna yang bekerja pada 100% kasus.
Hal pertama yang harus dilakukan adalah memahami jika Anda benar-benar membutuhkan refactoring? Ini harus dipertimbangkan jika:
- Kecepatan memperkenalkan fitur-fitur baru tidak masuk akal rendah, meskipun spesialis tingkat tinggi dalam tim.
- Perubahan kode di satu bagian program dapat menyebabkan perilaku yang tidak terduga di bagian lain.
- Adaptasi anggota tim baru tertunda.
- Pengujian kode terhalang oleh konektivitas yang kuat.
Setelah menyadari adanya masalah, seseorang harus menemukan jawaban untuk pertanyaan-pertanyaan berikut:
- Sebenarnya apa yang salah?
- Apa yang menyebabkan ini?
- Apa yang perlu dilakukan untuk mencegah hal ini terjadi lagi?
- Bagaimana cara memperbaiki situasi?
Hampir mustahil untuk membangun proyek lama yang bagus tanpa meletakkan arsitektur tertentu. Dalam proyek kami, kami memutuskan untuk memperkenalkan arsitektur "berlapis", yang telah terbukti dengan baik.
Awalnya, proyek ini ditulis terutama dengan bantuan alat yang disediakan oleh Android SDK itu sendiri. Pendekatan ini tidak diragukan lagi berhasil, tetapi memaksa Anda untuk menulis banyak kode boilerplate, yang sangat menghambat pengembangan. Dan mengingat bahwa saat ini banyak digunakan untuk tumpukan teknologi tertentu, adaptasi dari pengembang baru membutuhkan waktu lebih lama. Secara bertahap, kami sampai pada teknologi yang lebih nyaman yang banyak diketahui dan dihargai, dan yang telah membuktikan keandalan dan konsistensi mereka:
- MVP - Pola Desain Antarmuka Pengguna (Model-View-Presenter).
- Belati 2 adalah kerangka kerja untuk menerapkan dependensi.
- RxJava2 adalah implementasi dari ReactiveX - sebuah pustaka untuk membuat program berbasis asinkron dan event menggunakan pola Observer untuk JVM.
- Cicerone adalah perpustakaan yang memungkinkan Anda untuk menyederhanakan navigasi di aplikasi.
- Sejumlah perpustakaan khusus untuk bekerja dengan peta dan lokasi.
Sangat penting untuk mengadopsi gaya kode umum untuk tim, untuk mengembangkan serangkaian praktik terbaik. Anda juga harus menjaga infrastruktur dan prosesnya. Lebih baik menulis tes untuk kode baru segera, karena ada banyak informasi mengenai hal ini.
Di dalam tim, kami mulai melakukan peninjauan kode tanpa gagal, tidak butuh banyak waktu, tetapi kualitas kode menjadi jauh lebih tinggi. Bahkan jika Anda sendirian di tim, saya sarankan bekerja pada Git Flow, membuat permintaan penggabungan dan setidaknya memeriksanya sendiri.
Semua pekerjaan "kotor" dapat didelegasikan ke CI - dalam kasus kami, ini adalah TeamCity menggunakan fastlane. Kami mengkonfigurasinya untuk membangun cabang fitur, menjalankan tes, dan mengeluarkan tes internal. Di tempat kami, kami secara terpisah mengkonfigurasi majelis untuk lingkungan produksi / pementasan, fitur- (kami memanggil mereka dengan nomor tugas dengan templat TASK # task_number) dan melepaskan cabang. Ini membuat pengujian lebih mudah, dan jika terjadi kesalahan, kami segera tahu apa yang perlu diperbaiki dan di mana.
Setelah melakukan semua tindakan pendahuluan, kami mulai bekerja. Kami memulai kehidupan baru di proyek lama dengan membuat paket (cleanarchitecture). Penting untuk tidak melupakan
aktivitas-alias saat memindahkan titik masuk ke aplikasi (a-la ActivitySplash). Jika Anda mengabaikan ini, maka, dalam kasus terbaik, Anda akan kehilangan ikon di peluncur, dan dalam kasus terburuk, kompatibilitas dengan aplikasi lain akan dilanggar.
<activity-alias android:name=".SplashActivity" android:targetActivity=".cleanarchitecture.presentation.SplashActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity-alias>
Seperti yang ditunjukkan oleh pengalaman, lebih baik memulai refactoring dengan layar kecil kecil dan sebagian aplikasi. Dan pada saat tiba saatnya untuk memproses bagian yang paling kompleks dan produktif dari program ini, sebagian besar kode sudah akan ditulis untuk modul lain dan dapat digunakan kembali.
Selain itu, kami memiliki tugas besar untuk mendesain ulang aplikasi sepenuhnya, yang, terkadang, menghasilkan penulisan ulang layar secara lengkap. Kami mulai dengan meningkatkan layar bantu, bersiap untuk melanjutkan ke hal utama.
Setelah menulis ulang bagian selanjutnya dari aplikasi, kami mencari bagian-bagian kode di bagian lama aplikasi dan ditandai dengan penjelasan dan analog @Deprecated dari ini:
https://github.com/VitalyNikonorov/UsefulAnnotation . Di dalamnya kami menunjukkan apa yang harus dilakukan ketika menulis ulang bagian dari program ini, fungsionalitas apa dan di mana ia diterapkan.
@Deprecated public class ResourceHelper {...}
Setelah semuanya siap untuk bekerja di layar utama, mereka memutuskan untuk tidak merilis fitur baru selama 6-8 minggu. Kami melakukan penulisan ulang global di cabang kami sendiri, yang kemudian kami tambahkan permintaan penggabungan. Pada akhir refactoring, mereka menerima permintaan tarik yang didambakan dan aplikasi yang hampir sepenuhnya diperbarui.

Setelah refactoring, perubahan fungsi aplikasi menjadi lebih mudah. Jadi, baru-baru ini kami kembali terlibat dalam pemrosesan layar otorisasi.
Awalnya, mereka terlihat sebagai berikut:

Setelah pemrosesan dan refactoring pertama, mereka mulai terlihat seperti ini:

Sekarang mereka terlihat seperti ini:

Akibatnya, iterasi pertama memakan waktu dua kali lebih banyak daripada yang kedua. Karena selain memproses UI, saya juga harus memahami kode logika bisnis yang terletak di tempat yang sama, meskipun ini tidak perlu, tetapi cacatnya dihilangkan, yang mengurangi waktu yang dihabiskan untuk tugas dalam iterasi kedua.
Apa yang kita miliki saat ini?
Untuk membuat kode ini nyaman untuk digunakan dan dikembangkan di masa mendatang, kami mematuhi prinsip "arsitektur bersih". Saya tidak akan mengatakan bahwa kami memiliki Clean kanonik, tetapi kami mengadopsi banyak pendekatan. Lapisan presentasi ditulis menggunakan pola MVP (Model-View-Presenter).
- Sebelumnya, kami harus mendiskusikan setiap langkah tanpa henti satu sama lain, untuk mengklarifikasi apakah perubahan dalam satu modul mempengaruhi fungsi yang lain. Dan sekarang overhead melalui korespondensi telah turun secara signifikan.
- Karena penyatuan komponen dan fragmen individual, volume basis kode telah sangat menurun.
- Sebagai hasil dari penyatuan dan pemrosesan arsitektur yang sama, ada lebih banyak kelas, tetapi sekarang ada pembagian tanggung jawab yang jelas di dalamnya, yang menyederhanakan pemahaman proyek.
- Basis kode dibagi menjadi beberapa lapisan, untuk pemisahan dan interaksinya, digunakan kerangka kerja injeksi ketergantungan Belati 2. Hal ini mengurangi koherensi kode dan meningkatkan kecepatan pengujian.
Ada banyak lagi poin menarik terkait dengan refactoring kode lama. Jika pembaca akan tertarik, saya akan menulis lebih banyak tentang mereka nanti. Saya juga akan senang jika Anda juga membagikan pengalaman Anda.