Argumen bidang vs metode [tertutup]


9

Saya baru saja mulai menulis beberapa kelas baru dan terpikir oleh saya bahwa saya menambahkan banyak argumen metode yang tidak sepenuhnya diperlukan. Ini mengikuti kebiasaan untuk menghindari keadaan dalam kelas yang khusus untuk beberapa pemanggilan metode, daripada konfigurasi umum atau dependensi kelas.

Melakukannya berarti bahwa banyak metode yang tidak memiliki argumen berakhir dengan satu, dua atau tiga.

Saya ingin mendengar pendapat Anda tentang apa yang Anda pikirkan tentang tradeoff ini, dan bagaimana Anda memutuskan pendekatan mana yang harus diambil dalam situasi apa?

Karena kode seringkali lebih mudah dipahami daripada bahasa Inggris ketika mendeskripsikan kode, saya membuat sedikit intisari yang memiliki kedua varian di dalamnya: https://gist.github.com/JeroenDeDauw/6525656


Argumen yang digunakan hanya sebagai variabel lokal (bukan global untuk seumur hidup objek) seharusnya hanya dalam ruang lingkup selama itu masuk akal ... Saya merasa sangat menjengkelkan ketika dev menyimpan toko non-instance state sebagai instance state karena itu nyaman ... Hanya pendapat saya. Membuatnya sulit untuk melihat bagaimana sebenarnya alur eksekusi.
Maks

Menggunakan parameter dan membiarkan kelas memperhatikan apakah ia harus mengubah status saat menjalankan suatu metode, dengan baik mengikat ke dalam prinsip "katakan jangan tanya" . Ingatlah bahwa Tell jangan tanya bukan berarti Anda tidak dapat menanyakan objek tentang kondisinya ( blatant plug )
Marjan Venema

Jawaban:


2

Karena satu-satunya metode yang terlihat secara eksternal dari contoh Anda adalah updateTable, saya pikir boleh saja menggunakan bidang alih-alih parameter metode.

Jika ini adalah bagian dari kelas yang lebih umum (mis. TableTools), Saya akan memindahkan metode helper yang membutuhkan negara ke kelas batin yang tersembunyi.

Contoh kode semu:

class TableTools {
    ...
    public void updateTable(currentTable, newTable) {
        TableUpdater u = new TableUpdater(schemaModifier, currentTable, newTable);
        u.removeRemovedFields();
        u.addAddedFields();
     }

     private class TableUpdater { ... }
}

Dengan begitu, Anda menghindari bidang yang hanya digunakan oleh satu metode publik. Selain itu, kode ini adalah thread-safe dalam arti bahwa setiap panggilan ke updateTable menggunakan salinan TableUpdater sendiri dan, dengan demikian, variabel instan TableUpdater.


7

Menggunakan bidang mengkooptasi kemampuan untuk memiliki multithreading tersedia untuk metode yang menggunakan bidang tersebut.

Menggunakan bidang-bidang seperti itu hanya sedikit lebih baik daripada menggunakan global dari sudut pandang reusability dan maintainability, poin utama di sini adalah bahwa pengaturan yang rumit memerlukan dokumentasi yang cermat dan terkini tentang metode mana yang menggunakan dan / atau mengungkit bidang mana; sesuatu yang tidak perlu Anda lakukan saat menggunakan argumen.


Multhithreading tidak relevan untuk use case saya, seperti di PHP. Saya setuju bahwa pendekatan ini buruk jika cara bidang yang digunakan tidak sepele. Dalam hal ini mereka hanya ditulis untuk (dan selalu ditulis untuk) dari satu-satunya metode publik. Saya tidak mengantisipasi ini menyebabkan masalah. Adapun bidang seperti ini hanya sedikit lebih baik daripada global, saya tidak yakin apa yang Anda maksud. Bisakah Anda menguraikan?
Jeroen De Dauw

7

Dalam kata-kata awam:

  • metode harus memiliki argumen sesedikit mungkin (Martin Clean Code)
  • salah satu fitur objek adalah dari yang mereka dapat (dan seharusnya) memiliki negara
  • metode non-statis yang tidak beroperasi pada keadaan objek, yaitu menerima semuanya sebagai parameter, tidak kohesif
  • metode non-kohesif mungkin juga dibuat statis dan dikelompokkan dalam kelas utilitas

Sekali lagi, menurut pendapat saya metode non-kohesif milik kelas utilitas dan bukan ke kelas dengan nama domain.


1

Jangan gunakan bidang dalam kasus saat ini! Dua "utas" yang menggunakan objek pada saat yang sama akan saling membingungkan. Mereka tidak harus menjadi nyata, utas terpisah juga (karenanya kutipan). Jika Anda mengatur objek untuk satu tabel, lalu memanggil metode yang menggunakannya untuk tabel lain, lalu mencoba menggunakan pengaturan asli, Anda memiliki masalah. Tetap dengan parameter untuk saat ini.

Apa yang ingin Anda lakukan di sini adalah membuat kelas updater baru yang hanya digunakan dalam satu kasus. Kelas asli dapat memiliki metode untuk membuat instance kapan pun diperlukan. Kelas baru akan memiliki bidang. Anda memiliki yang terbaik dari kedua dunia. Terkadang lebih mudah untuk tetap menggunakan parameter, tetapi dalam contoh Anda, Anda sudah sampai di mana kelas yang terpisah akan lebih baik.


0

Saya pikir, bahwa pemilihan harus sesuai dengan situasi nyata, seperti yang Anda lihat. Jika item milik instance, itu harus dilihat sebagai bidangnya. Jika item tersebut eksternal dari instance, item tersebut harus dilewatkan sebagai parameter metode.

Kita harus dibimbing dalam kasus ini bukan oleh keefektifan (perbedaannya tidak signifikan), atau (kemudahan Tuhan!) Kemudahan mengetik, tetapi oleh pemahaman dan kealamian kode.


0

Menurut pendapat saya, jika Anda menulis kode yang melakukan sesuatu terhadap sesuatu, maka ia harus mengambil parameter yang menentukan hal-hal apa yang harus dilakukan dan namanya harus menentukan sejauh mungkin apa yang dilakukannya terhadapnya.

Jika Anda menulis kode yang mengemas tindakan untuk dilakukan pada sesuatu maka Anda harus membungkus hal-hal yang harus dilakukan pada suatu objek dan meneruskannya ke hal Anda yang melakukan sesuatu .

Tindakan ini kemudian menjadi semacam meta-deskripsi panggilan ke metode pertama yang mungkin dapat Anda lakukan di kemudian hari dengan mengantri atau bahkan memutuskan untuk tidak melakukannya sama sekali karena alasan tertentu.

Jadi, pertanyaan Anda diterjemahkan menjadi apakah itu Aksi atau Fungsi ? Suatu Tindakan dapat ditunda atau dibatalkan dan oleh karena itu harus merangkum apa yang ditindaklanjuti. Suatu Fungsi terjadi segera sehingga tidak perlu lagi mempertahankan parameternya.

Anda dapat membatalkan dan Bertindak tetapi bukan suatu Fungsi .

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.