Mari kita mulai dengan sebuah contoh.
Katakanlah, saya memiliki metode yang disebut export
yang sangat bergantung pada skema DB. Dan dengan "sangat bergantung" Maksudku, saya tahu bahwa menambahkan kolom baru ke tabel tertentu sering (sangat sering) mengarah ke export
perubahan metode yang sesuai (biasanya Anda harus menambahkan bidang baru ke data ekspor juga).
Pemrogram sering lupa untuk mengubah export
metode 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 export
metode 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, checker
tegaskan jika table_row
berisi 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 export
metodenya". Untuk menyembunyikan programer peringatan akan (atau tidak akan - itu masalah) memeriksa export
dan 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.
sumber
export
berdasarkan Skema?export
memiliki semua yang Anda butuhkan secara realistis?Jawaban:
Anda berada di jalur yang benar dengan ide unit test Anda, tetapi implementasi Anda salah.
Jika
export
terkait dengan skema dan skema berubah, ada dua kemungkinan kasus:Entah yang
export
masih 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
export
prosedur 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.
Ini tidak ada hubungannya dengan unit test ...
... dan, sebenarnya, itu bahkan bukan ujian.
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
export
prosedur, Anda memastikan bahwa pengembang akan memperbaikinyaexport
.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
Description
kolom keProduct
tabel dan saya tidak menggunakan ORM atau generator kode, Saya setidaknya berharap untuk membuat perubahan tunggal dalamData.Product
kelas DAL, tanpa perlu mencari melalui semua basis kode dan menemukan beberapa kemunculanProduct
kelas 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 kelasB
di 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:
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.
sumber
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.B
tidak 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.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.
sumber
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.
sumber