Bagaimana cara menggambar perhatian programmer dalam kondisi tertentu?

13

Mari kita mulai dengan sebuah contoh.

Katakanlah, saya memiliki metode yang disebut exportyang sangat bergantung pada skema DB. Dan dengan "sangat bergantung" Maksudku, saya tahu bahwa menambahkan kolom baru ke tabel tertentu sering (sangat sering) mengarah ke exportperubahan metode yang sesuai (biasanya Anda harus menambahkan bidang baru ke data ekspor juga).

Pemrogram sering lupa untuk mengubah exportmetode karena tidak terlalu jelas Anda bahkan harus melihat ini. Tujuan saya adalah untuk memaksa programmer secara eksplisit membuat keputusan untuk menentukan apakah dia lupa untuk melihat exportmetode atau hanya tidak ingin menambahkan bidang ke data ekspor. Dan saya sedang mencari solusi desain untuk masalah ini.

Saya punya dua ide, tetapi keduanya memiliki kekurangan.

Pembungkus “Baca semua” yang cerdas

Saya bisa membuat pembungkus pintar yang memastikan semua data dibaca secara eksplisit.

Sesuatu seperti ini:

def export():
    checker = AllReadChecker.new(table_row)

    name    = checker.get('name')
    surname = checker.get('surname')
              checker.ignore('age') # explicitly ignore the "age" field

    result = [name, surname] # or whatever

    checker.check_now() # check all is read

    return result

Jadi, checkertegaskan jika table_rowberisi bidang lain yang tidak dibaca. Tetapi semua hal ini terlihat agak berat dan (mungkin) mempengaruhi kinerja.

“Periksa bahwa metode” unittest

Saya hanya bisa membuat unittest yang mengingat skema tabel terakhir dan gagal setiap kali tabel diubah. Dalam hal ini programmer akan melihat sesuatu seperti "jangan lupa untuk memeriksa exportmetodenya". Untuk menyembunyikan programer peringatan akan (atau tidak akan - itu masalah) memeriksa exportdan secara manual (itu masalah lain) memperbaiki tes dengan menambahkan bidang baru ke dalamnya.

Saya punya beberapa ide lain tetapi terlalu sulit untuk diimplementasikan atau terlalu sulit untuk dipahami (dan saya tidak ingin proyek menjadi teka-teki).


Masalah di atas hanyalah contoh dari kelas masalah yang lebih luas yang saya temui dari waktu ke waktu. Saya ingin mengikat beberapa potongan kode dan / atau infrastruktur sehingga mengubah salah satu dari mereka segera memberitahu programmer untuk memeriksa yang lain. Biasanya Anda memiliki beberapa alat sederhana seperti mengekstraksi logika umum atau menulis unittest yang andal, tetapi saya sedang mencari alat untuk kasus yang lebih kompleks: mungkin beberapa pola desain yang sekarang saya sadari.

Vadim Pushtaev
sumber
Bisakah Anda menghasilkan exportberdasarkan Skema?
coredump
Ini tidak dapat dibuat secara aoutmatic, itu sebabnya saya harus meminta programmer untuk melihat kode dan membuat keputusan.
Vadim Pushtaev
Apakah ini akan menjadi solusi untuk menambahkan dua daftar nama bidang (ekspor dan jangan-ekspor) ke kelas ekspor, dan memiliki uji unit yang memeriksa bahwa kedua daftar bersama-sama mencakup set lengkap bidang dari database?
Sjoerd Job Postmus
Dapatkah Anda membuat tes secara otomatis yang memeriksa apakah exportmemiliki semua yang Anda butuhkan secara realistis?
biziclop
1
komentar dalam kode sumber solusi terlalu sederhana? Biasanya ada yang terlewat karena tidak ada pengingat, komentar akan memperbaikinya.
gbjbaanb

Jawaban:

11

Anda berada di jalur yang benar dengan ide unit test Anda, tetapi implementasi Anda salah.

Jika exportterkait dengan skema dan skema berubah, ada dua kemungkinan kasus:

  • Entah yang exportmasih berfungsi dengan baik, karena tidak terpengaruh oleh sedikit perubahan dalam skema,

  • Atau rusak.

Dalam kedua kasus, itu adalah tujuan dari pembangunan untuk melacak regresi yang mungkin ini. Sekumpulan tes — apakah itu tes integrasi, atau tes sistem, atau tes fungsional atau yang lainnya — memastikan bahwa exportprosedur Anda bekerja dengan skema saat ini , terlepas dari kenyataan bahwa itu berubah atau tidak sejak komitmen sebelumnya. Jika tes itu lulus, bagus. Jika gagal, ini merupakan pertanda bagi pengembang bahwa ia mungkin telah melewatkan sesuatu, dan indikasi yang jelas ke mana harus mencari.

Mengapa implementasi Anda salah? Ya, karena beberapa alasan.

  1. Ini tidak ada hubungannya dengan unit test ...

  2. ... dan, sebenarnya, itu bahkan bukan ujian.

  3. Bagian terburuk adalah bahwa memperbaiki "tes" memerlukan, yah, sebenarnya mengubah "tes", yaitu melakukan operasi yang sama sekali tidak terkait dengan export.

Sebagai gantinya, dengan melakukan tes aktual untuk exportprosedur, Anda memastikan bahwa pengembang akan memperbaikinya export.


Secara lebih umum, ketika Anda menghadapi situasi di mana perubahan dalam satu kelas selalu atau biasanya membutuhkan perubahan di kelas yang sama sekali berbeda, ini adalah pertanda baik bahwa Anda melakukan kesalahan desain dan melanggar Prinsip Tanggung Jawab Tunggal.

Sementara saya berbicara secara khusus tentang kelas, ini berlaku lebih atau kurang untuk entitas lain juga. Misalnya, perubahan dalam skema database harus tercermin secara otomatis dalam kode Anda, misalnya melalui generator kode yang digunakan oleh banyak ORM, atau setidaknya harus mudah dilokalisasi: jika saya menambahkan Descriptionkolom ke Producttabel dan saya tidak menggunakan ORM atau generator kode, Saya setidaknya berharap untuk membuat perubahan tunggal dalam Data.Productkelas DAL, tanpa perlu mencari melalui semua basis kode dan menemukan beberapa kemunculan Productkelas di, katakanlah, lapisan presentasi.

Jika Anda tidak dapat membatasi perubahan secara wajar di satu lokasi (baik karena Anda berada dalam kasus di mana itu tidak berfungsi, atau karena itu membutuhkan sejumlah besar pengembangan), maka Anda membuat risiko kemunduran . Ketika saya mengubah kelas A, dan kelas Bdi suatu tempat di basis kode berhenti berfungsi, itu adalah regresi.

Pengujian menurunkan risiko regresi dan, yang jauh lebih penting, menunjukkan lokasi regresi. Inilah sebabnya ketika Anda tahu bahwa perubahan di satu lokasi menyebabkan masalah di bagian basis kode yang sama sekali berbeda, pastikan Anda memiliki cukup tes yang menimbulkan alarm segera setelah regresi muncul di tingkat ini.

Dalam semua kasus, hindari mengandalkan dalam kasus seperti itu hanya pada komentar. Sesuatu seperti:

// If you change the following line, make sure you also change the corresponding
// `measure` value in `Scaffolding.Builder`.

tidak pernah berhasil. Tidak hanya pengembang tidak akan membacanya dalam banyak kasus, tetapi akan sering berakhir baik dihapus atau pindah jauh dari baris yang bersangkutan, dan menjadi tidak mungkin untuk dipahami.

Arseni Mourzenko
sumber
Ya, "tes" itu memang bukan tes, ini semacam jebakan, semacam If you change the following line...itu bekerja secara otomatis dan tidak bisa diabaikan begitu saja. Saya belum pernah melihat seseorang yang benar-benar menggunakan perangkap seperti itu maka keraguannya.
Vadim Pushtaev
1
Masalahnya adalah kelas Btidak berhenti bekerja, mungkin mulai bekerja dengan tidak benar. Tapi saya tidak bisa memprediksi masa depan dan tidak bisa menulis tes yang memprediksi masa depan, jadi saya mencoba mengingatkan pengembang untuk menulis tes baru itu.
Vadim Pushtaev
@VadimPushtaev: ketika datang ke pengujian, "mungkin mulai bekerja dengan tidak tepat" dan "berhenti bekerja" adalah hal yang persis sama. Anda tidak dapat memprediksi masa depan, tetapi Anda harus dapat mengetahui dengan tepat persyaratan, dan menguji bahwa persyaratan tersebut dipenuhi oleh produk Anda yang sebenarnya.
Arseni Mourzenko
Ya, itu benar. Saya sebenarnya ingin mengingatkan pengembang untuk memikirkan persyaratan baru . Saya hanya ingin melambaikan tangan: "Halo, Anda yakin tidak lupa tentang ekspor? Tanyakan kepada manajer atau sesuatu, itu masalah umum ”.
Vadim Pushtaev
Terima kasih, jawaban Anda membantu saya mengatur pikiran saya dan saya punya rencana tertentu sekarang.
Vadim Pushtaev
3

Bagi saya sepertinya perubahan Anda tidak ditentukan. Misalnya Anda tinggal di suatu tempat yang tidak memiliki kode pos, jadi Anda tidak memiliki kolom kode pos di tabel alamat. Kemudian kode pos diperkenalkan, atau Anda mulai berurusan dengan pelanggan yang tinggal di mana ada kode pos, dan Anda harus menambahkan kolom ini ke tabel.

Jika item pekerjaan hanya mengatakan "tambahkan kolom kode pos ke tabel alamat" maka ya, ekspor akan rusak, atau setidaknya tidak akan mengekspor kode pos. Tetapi bagaimana dengan layar input yang digunakan untuk memasukkan kode pos? Laporan yang mencantumkan semua pelanggan dan alamat mereka? Ada banyak hal yang perlu diubah ketika Anda menambahkan kolom ini. Pekerjaan mengingat hal-hal itu adalah yang penting - Anda tidak boleh mengandalkan artefak kode acak untuk "menjebak" pengembang agar mengingat.

Ketika keputusan dibuat untuk menambahkan kolom yang bermakna (yaitu, bukan hanya beberapa pencarian dalam cache atau didenormalkan atau nilai lain yang tidak termasuk dalam ekspor atau laporan atau pada layar input) item pekerjaan yang dibuat harus mencakup SEMUA perubahan diperlukan - menambahkan kolom, memperbarui skrip populate, memperbarui tes, memperbarui ekspor, laporan, layar input, dan sebagainya. Ini mungkin tidak semua ditugaskan ke (atau diambil oleh) orang yang sama, tetapi mereka semua harus dilakukan.

Terkadang pengembang memilih untuk menambahkan kolom sendiri sebagai bagian dari penerapan beberapa perubahan yang lebih besar. Misalnya seseorang mungkin telah menulis item pekerjaan untuk menambahkan sesuatu ke layar input dan laporan, tanpa memikirkan bagaimana penerapannya. Jika hal ini sering terjadi, Anda harus memutuskan apakah item-item-adder Anda perlu mengetahui detail implementasi (agar dapat menambahkan semua item kerja yang tepat) atau apakah pengembang perlu menyadari bahwa item-item pekerjaan tersebut adder terkadang meninggalkan semuanya. Jika yang terakhir maka Anda memerlukan budaya "jangan hanya mengubah skema; ​​berhenti dan pikirkan apa lagi yang mempengaruhi."

Jika ada banyak pengembang dan ini terjadi lebih dari satu kali, saya akan menyiapkan tanda checkin untuk pemimpin tim atau orang senior lainnya untuk diberitahu tentang perubahan skema. Orang itu kemudian dapat mencari item pekerjaan terkait untuk menangani konsekuensi dari perubahan skema mereka, dan jika item kerja hilang, tidak hanya dapat menambahkannya tetapi mendidik siapa pun yang meninggalkan mereka dari rencana.

Kate Gregory
sumber
2

Hampir selalu, saat membuat ekspor saya juga membuat impor yang sesuai. Karena saya memiliki tes lain yang mengisi penuh struktur data yang diekspor, saya kemudian dapat membangun tes unit pulang-pergi yang membandingkan asli yang terisi penuh dengan salinan yang diekspor kemudian diimpor. Jika sama, maka ekspor / impor selesai; jika tidak sama maka pengujian unit gagal dan saya tahu bahwa mekanisme ekspor perlu diperbarui.

Pete Kirkham
sumber
ini dapat memeriksa, bahwa setiap objek disimpan dan dimuat ulang dari db. Ini tidak mencakup kasus bahwa bidang-db yang ada tidak memiliki bidang objek yang sesuai.
k3b
@ k3b benar. Setidaknya dalam sistem saya, yang umumnya terjadi jika sesuatu tidak lagi digunakan tetapi belum dihapus dari skema, yang berada di luar lingkup mekanisme ekspor - unit test untuk objek kegigihan memeriksa apakah masing-masing bidang objek adalah bertahan, tapi saya tidak menguji kolom yang tidak digunakan karena itu tidak akan memiliki efek yang dapat diamati pada fungsi sistem.
Pete Kirkham