Lingkungan Android

Kata Pengantar


Dari jauh 2012, di ruang terbuka Habr, saya ingat komentar:


... jika tidak ada kasing dari awal, maka perangkat akan tetap
yang belum selesai, akan jatuh debu di rak ...

Topiknya jauh dari komponen perangkat keras. Menganalisis masalah saya, saya menjadi yakin akan kebenaran penilaian ini dan mencoba menertibkan hal-hal di rak berdebu saya.


Baru-baru ini saya didekati oleh seorang pelanggan yang meminta saya untuk menambahkan dukungan untuk beberapa layanan pada proyeknya. Tugasnya adalah saya perlu menghubungkan layanan "A" dan, sebelum memasukkan aplikasi ke dalam produksi, jalankan layanan ini di lingkungan pengujian. Saya memutuskan untuk menganalisis keputusan saya sebelumnya dan ... ngeri.


Untuk berbagai jenis rakitan, saya menggunakan berbagai file konfigurasi dengan deskripsi variabel lingkungan. Tetapi masalahnya adalah hanya untuk meneruskan nilai ke kode nyata, perlu untuk menulis kode yang sama untuk setiap jenis.


Masalahnya


Google memberi kami kemampuan untuk meneruskan nilai khusus untuk masing-masing
perakitan .


android { //... buildTypes { release { buildConfigField("String", "HOST_URL", "\"prod.com\"") } debug { buildConfigField("String", "HOST_URL", "\"debug.com\"") } } } 

Setelah menganalisis skrip build.gradle , perangkat android akan mengambil semua nilai buildConfigFileds dari buildTypes dan productFlavours dan menghasilkan file BuildConfig untuk setiap jenis perakitan:


 public final class BuildConfig { //... // Fields from build type: release public static final String HOST_URL = "prod.com"; } 

Tidak ada masalah pada pandangan pertama. Terutama ketika tidak ada banyak rasa dan nilai khusus dalam aplikasi Anda. Dalam proyek saya ada> 20 dan 3 lingkungan (internal / alpha / produksi). Jelas, hanya ada satu masalah bagi saya - untuk menyingkirkan pelat ketel.


Masalah yang sama pentingnya adalah bahwa nilai-nilai variabel lingkungan tidak boleh tercermin dalam proyek Anda. Bahkan dalam file konfigurasi. Anda harus memeriksa konfigurasi build.gradle Anda melalui VCS. Tetapi Anda tidak boleh mendaftarkan kunci Anda secara langsung, untuk ini, Anda memerlukan mekanisme pihak ketiga (misalnya, file, layanan CI Anda). Dalam praktik saya, ada beberapa proyek di mana untuk rilis produksi perakitan saya tidak memiliki akses ke nilai-nilai beberapa perpustakaan. Ini sudah merupakan masalah bisnis dan untuk kepentingannya tidak membuat biaya yang tidak perlu. Anda tidak boleh menggunakan kunci yang dimaksudkan untuk produksi selama debugging atau pengujian internal.


Cara mengatasi masalah


Di salah satu proyek lama, untuk menyimpan nilai variabel lingkungan, kami menggunakan file .properties sederhana yang menyediakan akses ke bidang melalui kunci klasik: value map. Pendekatan ini tidak menyelesaikan masalah yang mengikat. Tetapi itu memecahkan masalah pengiriman data, yang harus diterapkan. Selain itu, kita dapat mengambil file .properties sebagai dasar untuk jenis kontrak penyediaan data tertentu.


Jika kita kembali sedikit, kita memiliki langkah perantara: dari buildConfigField ke bidang kelas BuildConfig . Tetapi siapa yang melakukan ini? Semuanya cukup klise, plugin gradle yang Anda hubungkan benar-benar di semua proyek Android bertanggung jawab untuk ini.


 apply plugin: "com.android.application" 

Dialah yang bertanggung jawab atas fakta bahwa setelah menganalisis file build.gradle Anda, kelas BuildConfig akan dihasilkan untuk setiap rasa dengan set bidangnya sendiri. Dengan begitu, saya bisa menulis obat sendiri yang akan memperluas kemampuan com.android.aplikasi dan menghemat
saya dari sakit kepala ini.


Solusi untuk masalah ini adalah sebagai berikut: memberikan kontrak,
yang akan menjelaskan semua kunci dan nilai untuk semua majelis.
Perluas file konfigurasi menjadi subtipe. Berikan segalanya untuk plugin.


menggambar

Solusi


Di atas kami menemukan struktur solusinya, satu-satunya yang tersisa untuk dilakukan adalah membawa semuanya menjadi hidup. Tampaknya solusi sepele dan masalah dapat diselesaikan dengan ekstensi file build sederhana. Awalnya, saya melakukannya.


Mengungkapkan solusi
 ```groovy class Constants { // Environments properties path pattern, store your config files in each folders of pattern static final CONFIG_PROPERTY_PATTERN = "config/%s/config.properties" } android.buildTypes.all { buildType -> buildConfigFields(buildType, buildType.name) } android.applicationVariants.all { appVariant -> buildConfigFields(appVariant, appVariant.flavorName) } private def buildConfigFields(Object variant, String variantName) { def properties = getProperties(variantName) properties.each { key, value -> variant.buildConfigField( parseValueType(value), toConfigKey(key), value ) } } // Convert config property key to java constant style private def toConfigKey(String key) { return key.replaceAll("(\\.)|(-)", "_") .toUpperCase() } // Parse configuration value type private def parseValueType(String value) { if (value == null) { throw new NullPointerException("Missing configuration value") } if (value =~ "[0-9]*L" ) { return "Long" } if (value.isInteger()) { return "Integer" } if (value.isFloat()) { return "Float" } if ("true" == value.toLowerCase() || "false" == value.toLowerCase()) { return "Boolean" } return "String" } private def getProperties(String variantName) { def propertiesPath = String.format( Constants.CONFIG_PROPERTY_PATTERN, variantName ) def propertiesFile = rootProject.file(propertiesPath) def properties = new Properties() // Do nothing, when configuration file doesn't exists if (propertiesFile.exists()) { properties.load(new FileInputStream(propertiesFile)) } return properties } ``` 

Dan di sini segera muncul kesulitan-kesulitan yang tidak saya pikirkan - resimen berdebu. Saya memutuskan untuk "menjual" keputusan saya kepada rekan-rekan saya. Saya menyiapkan dermaga, menendang masalah ini untuk diskusi, dan ... Saya menyadari bahwa kita semua adalah orang, dan programmer adalah orang yang malas. Tidak ada yang ingin menanamkan kode yang tidak diketahui kepadanya dalam proyek, apakah perlu dipelajari, dibaca untuk selamanya? Bagaimana jika dia tidak bekerja? Bagaimana jika dia melakukan sesuatu yang salah? Ini asyik, tapi saya tidak mengenalnya dan tidak jelas bagaimana bekerja dengannya. Dan skrip sudah pindah ke Kotlin untuk waktu yang lama, dan saya tidak bisa port dari alur, dan sebagainya.


Hal yang paling menarik adalah bahwa semua penilaian ini sudah datang dari saya, karena Saya menyadari bahwa integrasi solusi seperti itu tidak cocok untuk saya. Plus, saya perhatikan beberapa poin yang ingin saya tingkatkan. Setelah mengimplementasikan solusi di proyek A, saya ingin mendukungnya di proyek B. Hanya ada satu jalan keluar - Anda perlu menulis plug-in.


Dan masalah apa yang akan diselesaikan oleh plug-in dan remote-nya kepada pengguna?


  • masalah programmer yang malas. Kita terlalu malas untuk menyelidiki akar masalah dan kemungkinan cara untuk menyelesaikannya. Jauh lebih mudah bagi kami untuk mengambil sesuatu yang telah dilakukan sebelum Anda dan menggunakannya.
  • dukungan. Ini termasuk dukungan kode, pengembangan dan perluasan peluang. Ketika memecahkan masalah saya, saya hanya memecahkan lingkungan probrosvarivnyh hanya dalam kode, benar-benar lupa tentang kemungkinan meneruskan ke sumber daya.
  • kualitas kode. Ada pendapat bahwa beberapa pengembang bahkan tidak melihat kode sumber terbuka yang tidak tercakup oleh tes. Ini tahun 2019 dan kami dapat dengan mudah menghubungkan layanan untuk melacak kualitas kode https://sonarcloud.io atau https://codecov.io/
  • konfigurasi. Ekstensi file build memaksa saya untuk memeriksa kode ini dan membuat perubahan secara manual. Dalam kasus saya, saya tidak selalu perlu menggunakan konfigurasi untuk buildTypes atau productFlavours , saya ingin satu hal atau semuanya sekaligus.
  • membersihkan rak berdebu. Saya akhirnya membersihkan salah satu dari mereka dan dapat melanjutkan keputusan ini dari kamar kecil saya.

Saya tidak akan membahas detail dan masalah saat menulis plugin, itu menarik topik baru. Anda dapat membuat keputusan dengan integrasinya, mengusulkan ide Anda, atau membuat kontribusi Anda
disini

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


All Articles