Memahami Kode Bersih di Android

Sebagai pengantar, saya ingin mengingat kutipan Paman Bob
Anda membaca artikel ini karena dua alasan. Yang pertama - Anda adalah seorang programmer, yang kedua - Anda ingin menjadi programmer terbaik.
Bayangkan Anda berada di perpustakaan dan mencari beberapa buku. Jika perpustakaan diurutkan, memiliki kategori buku, maka Anda akan dengan cepat menemukan yang Anda butuhkan. Selain itu, desain interior dan arsitektur yang keren akan membuat masa tinggal Anda di perpustakaan ini cukup nyaman untuk Anda.

Seperti halnya menulis buku, jika Anda ingin membuat sesuatu yang hebat, maka Anda perlu tahu cara menulis dan cara mengatur kode Anda. Jika Anda memiliki anggota tim atau orang lain yang memiliki kode Anda (usang), mereka hanya perlu melihat nama variabel atau paket atau kelas, dan mereka akan segera mengerti. Mereka tidak perlu mengatakan "E ** l" Saya kode ini dan mulai lagi dari awal.

Apa itu Kode Bersih?




Terjemahan
Programmer yang terhormat:

Ketika saya menulis kode ini, hanya Tuhan dan saya yang tahu cara kerjanya!
Sekarang hanya Tuhan yang tahu ini!

Sebelum Anda mencoba untuk mengoptimalkan rutin ini dan itu tidak akan mengarah pada kesuksesan (kemungkinan besar), silakan tambahkan penghitung waktu untuk memperingatkan pengembang berikutnya

Total jam yang dihabiskan: 567

Seperti yang Anda lihat, itu tidak cukup untuk menyelesaikan pengembangan lebih cepat. Jika di masa depan mereka tidak dapat menemukan kode ini, maka itu juga akan menjadi hutang teknis.

Kode Anda dalam keadaan "Murni" jika setiap anggota tim Anda dapat memahaminya. Kode bersih dapat dibaca dan diperbaiki oleh pengembang mana pun selain pembuat aslinya. Dengan pemahaman muncul keterbacaan, mutabilitas, ekstensibilitas, dan pemeliharaan.

Haruskah saya mengurus ini?


Alasan Anda harus peduli dengan kebersihan kode Anda adalah karena Anda menjelaskan pemikiran Anda kepada pengembang lain. Itu sebabnya Anda harus berhati-hati agar kode Anda lebih elegan, sederhana dan mudah dibaca.

Tanda Kode Bersih


  • Kode Anda harus elegan: Kode Anda harus membuat Anda tersenyum seperti kotak musik yang dibuat dengan baik atau mobil yang dirancang dengan baik
  • Kode Anda harus fokus: setiap fungsi, setiap kelas, setiap modul mengimplementasikan satu tugas, yang tetap sama sekali tidak terganggu dan tidak tercemar oleh detail di sekitarnya.
  • Kode tidak mengandung duplikat
  • Berhasil lulus semua tes
  • Meminimalkan jumlah entitas, metode, kelas, dan sebagainya

Perbedaan antara seorang programmer yang baik dan seorang profesional adalah bahwa seorang programmer profesional memahami bahwa kelengkapan kode adalah yang terpenting. Seorang profesional menggunakan kekuatan ini untuk menulis kode yang dipahami semua orang - Robert C. Martin

Tulis nama sadar


Memilih nama yang baik mungkin membutuhkan banyak waktu, tetapi nantinya akan lebih menghemat. Nama variabel, fungsi, kelas harus menjawab semua pertanyaan penting. Itu harus memberi tahu Anda mengapa itu ada, mengapa itu diperlukan dan bagaimana menggunakannya. Jika nama tersebut memerlukan komentar, nama tersebut tidak mengungkapkan tujuannya

Contoh sederhana

// Bad variables naming var a = 0 // user ages var w = 0 // user weight var h = 0 // user height // Bad functions naming fun age() fun weight() fun height() // Bad classes naming to get user data class UserInfo() // Best practices varibales naming var userAge = 0 var userWeight = 0 var userHeight = 0 // Best practices functions naming fun setUserAge() fun setUserWeight() fun setUserHeight() // Best practices classes naming to get user data class Users() 

Nama kelas


Kelas dan objek harus berupa kata benda, seperti Custom, WikiPage, Account, dan AddressParser. Hindari kata-kata seperti Manajer, Pemroses, Data, atau Info. Juga ingat bahwa nama kelas tidak boleh berupa kata kerja.

Nama Metode


Nama metode harus berupa kata kerja, misalnya postPayment, deletePage, atau save. Pengubah akses, predikat harus dinamai berdasarkan nilainya dan dengan awalan dapatkan, atur, dan sesuai dengan standar JavaBean.

Sebelum kita melanjutkan, istirahat sejenak, beli kopi dan kue.



Oke, sekarang mari kita beralih ke prinsip SOLID.

Tulis kode dengan mengikuti prinsip-prinsip SOLID


Prinsip-prinsip ini dikembangkan oleh Paman Bob, SOLID adalah singkatan yang menggambarkan seperangkat prinsip yang dirancang untuk menulis kode yang baik.

Prinsip Tanggung Jawab Tunggal


Ini berarti bahwa setiap kelas hanya memikul satu tanggung jawab. Seharusnya tidak ada lebih dari satu alasan untuk mengubah kelas. Tidak perlu menambahkan semuanya ke kelas Anda, hanya karena Anda bisa melakukannya. Hancurkan kelas besar menjadi yang lebih kecil dan hindari Kelas Dewa.

Contoh:

Kami memiliki RecyclerView.Adapter dengan logika bisnis di dalam onBindViewHolder

 class MyAdapter(val friendList: List<FriendListData.Friend>) : RecyclerView.Adapter<CountryAdapter.MyViewHolder>() { inner class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) { var name: TextView = view.findViewById(R.id.text1) var popText: TextView = view.findViewById(R.id.text2) } override fun onBindViewHolder(holder: MyViewHolder, position: Int) { val friend = friendList[position] val status = if(friend.maritalStatus == "Married") { "Sold out" } else { "Available" } holder.name.text = friend.name holder.popText.text = friend.email holder.status.text = status } override fun getItemCount(): Int { return friendList.size } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.item_friendlist, parent, false) return MyViewHolder(view) } } 

Ini membuat RecyclerView.Adapter tidak sepenuhnya bertanggung jawab karena mengandung logika bisnis di dalam onBindViewHolder. Metode ini hanya bertanggung jawab untuk memasukkan data ke dalam tampilan.

Prinsip keterbukaan / penutupan (O)


Entitas perangkat lunak harus terbuka untuk ekspansi, tetapi ditutup untuk modifikasi. Ini berarti bahwa jika Anda mengembangkan kelas A dan kolega Anda ingin mengubah fungsi di dalam kelas ini. Mereka dapat dengan mudah melakukan ini dengan memperluas kelas ini tanpa mengubah kelas itu sendiri.
Contoh sederhana adalah kelas RecyclerView.Adapter. Anda dapat dengan mudah mengembangkannya dan membuat adaptor Anda sendiri dengan perilaku non-standar tanpa memodifikasi RecyclerView.Adapter itu sendiri.

 class FriendListAdapter(val friendList: List<FriendListData.Friend>) : RecyclerView.Adapter<CountryAdapter.MyViewHolder>() { inner class MyViewHolder(view: View) : RecyclerView.ViewHolder(view) { var name: TextView = view.findViewById(R.id.text1) var popText: TextView = view.findViewById(R.id.text2) } override fun onBindViewHolder(holder: MyViewHolder, position: Int) { val friend = friendList[position] holder.name.text = friend.name holder.popText.text = friend.email } override fun getItemCount(): Int { return friendList.size } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder { val view = LayoutInflater.from(parent.context).inflate(R.layout.item_friendlist, parent, false) return MyViewHolder(view) } } 

Prinsip Substitusi Barbara Lisk (L)


Kelas anak harus melengkapi orang tua, dan tidak mengubahnya. Ini berarti bahwa subkelas harus menimpa metode induk yang tidak melanggar fungsionalitas kelas induk ini. Sebagai contoh, kami membuat antarmuka kelas yang memiliki pendengar onClick () dan kemudian Anda menerapkan pendengar di MyActivity dan memberikannya tindakan Toast ketika onClick () dipanggil.

 interface ClickListener { fun onClick() } class MyActivity: AppCompatActivity(), ClickListener { //........ override fun onClick() { // Do the magic here toast("OK button clicked") } } 

Prinsip pemisahan antarmuka


Prinsip ini menyatakan bahwa klien tidak boleh bergantung pada metode yang tidak ia gunakan.
Ini berarti bahwa jika Anda ingin menulis kelas A dan menambahkan fungsionalitas kelas B lainnya ke dalamnya, Anda tidak perlu mendefinisikan ulang semua kelas A di dalam kelas B.

Contoh: dalam aktivitas kami, kami perlu mengimplementasikan SearchView.OnQueryTextListener (), tetapi kami hanya membutuhkan metode onQuerySubmit ().

 mSearchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener{ override fun onQueryTextSubmit(query: String?): Boolean { // Only need this method return true } override fun onQueryTextChange(query: String?): Boolean { // We don't need to implement this method return false } }) 

Bagaimana kita melakukan ini? Mudah! Cukup buat panggilan balik dan kelas yang memperluas SearchView.OnQueryTextListener ()

 interface SearchViewQueryTextCallback { fun onQueryTextSubmit(query: String?) } class SearchViewQueryTextListener(val callback: SearchViewQueryTextCallback): SearchView.OnQueryTextListener { override fun onQueryTextSubmit(query: String?): Boolean { callback.onQueryTextSubmit(query) return true } override fun onQueryTextChange(query: String?): Boolean { return false } } 

Jadi kami menambahkannya ke tampilan kami

 val listener = SearchViewQueryTextListener( object : SearchViewQueryTextCallback { override fun onQueryTextSubmit(query: String?) { // Do the magic here } } ) mSearchView.setOnQueryTextListener(listener) 

Atau lebih menggunakan Fungsi Ekstensi di Kotlin

 interface SearchViewQueryTextCallback { fun onQueryTextSubmit(query: String?) } fun SearchView.setupQueryTextSubmit (callback: SearchViewQueryTextCallback) { setOnQueryTextListener(object : SearchView.OnQueryTextListener{ override fun onQueryTextSubmit(query: String?): Boolean { callback.onQueryTextSubmit(query) return true } override fun onQueryTextChange(query: String?): Boolean { return false } }) } 

 val listener = object : SearchViewQueryTextCallback { override fun onQueryTextSubmit(query: String?) { // Do the magic here } } mSearchView.setupQueryTextSubmit(listener) 

Prinsip Pembalikan Ketergantungan


Ketergantungan pada abstraksi, tanpa ketergantungan pada sesuatu yang spesifik.
Definisi inversi ketergantungan pada Paman Bob terdiri dari dua konsep.

Modul tingkat atas tidak harus bergantung pada modul tingkat bawah. Keduanya harus dikaitkan dengan abstraksi. Abstraksi tidak harus bergantung pada detail. Rinciannya harus bergantung pada abstraksi. Modul tingkat tinggi yang menerapkan logika kompleks harus mudah digunakan kembali tanpa perubahan pada modul tingkat rendah. Untuk melakukan ini, Anda harus memasukkan abstraksi yang memisahkan modul dari tingkat atas dan bawah dari satu sama lain.

Contoh sederhana dari pola MVP ini. Anda memiliki objek antarmuka yang membantu Anda berkomunikasi dengan kelas-kelas tertentu. Apa yang dimaksud - kelas UI (Aktivitas / Fragmen) tidak perlu mengetahui implementasi sebenarnya dari metode presenter. Jadi, jika Anda membuat perubahan di dalam presenter, kelas UI tidak perlu khawatir tentang perubahan ini.

Mari kita lihat sebuah contoh

 interface UserActionListener { fun getUserData() } class UserPresenter : UserActionListener() { // ..... override fun getUserData() { val userLoginData = gson.fromJson(session.getUserLogin(), DataLogin::class.java) } // ..... } 

Dan sekarang aktivitasnya

 class UserActivity : AppCompatActivity() { //..... val presenter = UserPresenter() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // Activity doesn't need to know how presenter works // for fetching data, it just know how to call the functions // So, if you add method inside presenter, it won't break the UI. // even the UI doesn't call the method. presenter.getUserData() } //.... } 

Dengan cara ini, kami membuat antarmuka yang abstrak implementasi presenter, dan kelas tampilan kami mempertahankan referensi ke PresenterInterface.

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


All Articles