Saya telah melihat pertanyaan ini tetapi memiliki beberapa pertanyaan lagi tentang penggunaan assert
kata kunci. Saya berdebat dengan beberapa coders lain tentang penggunaan assert
. Untuk kasus penggunaan ini, ada metode yang dapat mengembalikan nol jika prasyarat tertentu dipenuhi. Kode yang saya tulis memanggil metode, lalu menyatakan itu tidak mengembalikan nol, dan terus menggunakan objek yang dikembalikan.
Contoh:
class CustomObject {
private Object object;
@Nullable
public Object getObject() {
return (object == null) ? generateObject() : object;
}
}
Sekarang bayangkan saya menggunakannya seperti ini:
public void useObject(CustomObject customObject) {
object = customObject.getObject();
assert object != null;
// Do stuff using object, which would throw a NPE if object is null.
}
Saya diberitahu bahwa saya harus menghapus assert
, bahwa mereka tidak boleh digunakan dalam kode produksi, hanya digunakan dalam pengujian. Benarkah?
-ea
atau setara.Objects.requireNonNull
di Jawa 8).Jawaban:
Gunakan
Objects.requireNonNull(Object)
untuk itu.Dalam kasus Anda ini akan menjadi:
Fungsi ini dibuat untuk tujuan yang Anda sebutkan, yaitu secara eksplisit menandai apa yang tidak boleh nol; juga dalam produksi. Manfaat besar adalah Anda memastikan Anda menemukan nilai nol tepat di tempat mereka seharusnya tidak terjadi di tempat pertama. Anda akan memiliki lebih sedikit masalah debugging yang disebabkan oleh nilai-nilai nol yang dilewatkan di suatu tempat di mana mereka seharusnya tidak.
Manfaat lain adalah fleksibilitas tambahan mengenai cek kosong berbeda dengan
assert
. Sementaraassert
kata kunci untuk memeriksa nilai boolean,Objects.requireNonNull(Object)
adalah fungsi dan dengan demikian dapat tertanam dalam kode yang jauh lebih fleksibel dan mudah dibaca. Misalnya:Perlu diingat bahwa
Objects.requireNonNull(Object)
ini hanya untuk memeriksa nol di manaassert
digeneralisasi.assert
memiliki tujuan yang sedikit berbeda dalam hal itu, yaitu pengujian terutama. Itu harus diaktifkan, sehingga Anda dapat mengaktifkannya untuk menguji dan menonaktifkannya untuk produksi. Bagaimanapun, jangan menggunakannya untuk kode produksi. Itu bisa memperlambat aplikasi dengan validasi yang tidak perlu dan rumit yang dimaksudkan untuk pengujian. Gunakan itu untuk memisahkan cek hanya pengujian dari cek yang juga dimaksudkan untuk produksi.Lihat dokumentasi resmi untuk perincian tentang
assert
.sumber
Yang paling penting untuk diingat tentang pernyataan adalah bahwa mereka dapat dinonaktifkan, jadi jangan pernah berasumsi mereka akan dieksekusi.
Untuk kompatibilitas mundur, JVM menonaktifkan validasi pernyataan secara default. Mereka harus diaktifkan secara eksplisit menggunakan argumen baris perintah -enableassertions, atau steno -ea:
Jadi, bukan praktik yang baik untuk mengandalkan mereka.
Karena pernyataan tidak diaktifkan secara default, Anda tidak pernah dapat menganggapnya akan dieksekusi ketika digunakan dalam kode. Jadi, Anda harus selalu memeriksa nilai nol dan mengosongkan Opsional, hindari menggunakan pernyataan untuk memeriksa input ke metode publik dan alih-alih gunakan pengecualian yang tidak dicentang ... Secara umum lakukan semua pemeriksaan seolah-olah pernyataan itu tidak ada di sana.
sumber
Tentunya apa yang dikatakan kepada Anda adalah kebohongan yang terang-terangan. Inilah sebabnya.
Pernyataan dinonaktifkan secara default jika Anda hanya menjalankan jvm mandiri. Ketika mereka dinonaktifkan, mereka tidak memiliki jejak, maka mereka tidak akan mempengaruhi aplikasi produksi Anda. Namun, mereka mungkin adalah teman terbaik Anda ketika mengembangkan dan menguji kode Anda, dan sebagian besar pelari kerangka pengujian mengaktifkan pernyataan (JUnit melakukannya), jadi kode pernyataan Anda dijalankan ketika Anda menjalankan tes unit Anda, membantu Anda mendeteksi potensi bug sebelumnya (misalnya Anda dapat menambahkan pernyataan untuk beberapa pemeriksaan batas logika bisnis, dan itu akan membantu mendeteksi beberapa kode yang menggunakan nilai yang tidak pantas).
Yang mengatakan, seperti jawaban lain menyarankan, untuk alasan yang tepat (mereka tidak selalu diaktifkan) Anda tidak dapat mengandalkan pernyataan untuk melakukan beberapa pemeriksaan penting, atau (terutama!) Mempertahankan keadaan apa pun.
Untuk contoh yang menarik tentang bagaimana Anda dapat menggunakan menegaskan, lihat di sini - di akhir file ada metode
singleThreadedAccess()
yang dipanggil dari pernyataan tegas pada baris 201 dan ada di sana untuk menangkap potensi akses multithreaded dalam tes.sumber
Jawaban lain sudah mencakup ini dengan cukup baik, tetapi ada opsi lain.
Misalnya, Spring memiliki metode statis:
org.springframework.util.Assert.notNull(obj)
Ada perpustakaan lain dengan
Assert.something()
metode mereka sendiri juga. Cukup sederhana juga untuk menulis sendiri.Namun, ingatlah pengecualian apa yang Anda berikan jika ini adalah layanan web. Metode sebelumnya yang disebutkan, misalnya, melempar
IllegalArgumentException
yang secara default di Spring mengembalikan 500.Dalam hal layanan web, ini seringkali bukan kesalahan server internal, dan seharusnya bukan 500, melainkan 400, yang merupakan permintaan yang buruk.
sumber
assert
adalah, untuk mendapatkan crash langsung dengan file inti yang dihasilkan sehingga Anda dapat melakukan post-mortem dengan debugger favorit Anda tepat di tempat di mana kondisi itu dilanggar.assert
untuk melempar. Menarik. Versi C / C ++ tidak melakukan hal seperti itu. Segera menimbulkan sinyal bahwa a) membunuh proses, dan b) menciptakan dump inti. Ini karena suatu alasan: Sangat sederhana untuk men-debug kegagalan pernyataan seperti itu karena Anda masih memiliki seluruh informasi tentang tumpukan panggilan yang tersedia. Menentukanassert
untuk melempar pengecualian sebagai gantinya, yang kemudian dapat ditangkap (tidak) dengan sengaja secara terprogram, mengalahkan tujuannya, imho.Throwable
. Mereka selalu bisa ditangkap. Apakah itu hal yang baik atau tidak, saya tidak tahu. Saya kira itu tergantung. Banyak program Java adalah layanan web, dan itu tidak diinginkan untuk crash karena hampir semua alasan, jadi semuanya tertangkap dan dicatat. Salah satu hal yang hebat adalah jejak tumpukan, dan itu biasanya cukup untuk mendiagnosis alasan pengecualian atau kesalahan dengan sendirinya.Gunakan menegaskan secara bebas setiap kali melakukannya membantu menangkap kesalahan pemrograman yaitu bug.
Jangan gunakan pernyataan untuk menangkap sesuatu yang mungkin terjadi secara logis, yaitu input yang diformat dengan buruk. Gunakan hanya menegaskan ketika kesalahan tidak dapat dipulihkan.
Jangan letakkan logika produksi apa pun dalam kode yang berjalan saat pernyataan diperiksa. Jika perangkat lunak Anda ditulis dengan baik, ini sepele, tetapi jika tidak maka Anda mungkin memiliki efek samping yang halus dan perilaku keseluruhan yang berbeda dengan pernyataan yang diaktifkan dan dinonaktifkan.
Jika perusahaan Anda memiliki "kode pengujian" dan "kode produksi" melakukan hal yang sama tetapi sebagai basis kode yang berbeda (atau tahapan penyuntingan yang berbeda), keluarlah dari sana dan jangan pernah kembali. Mencoba memperbaiki tingkat ketidakmampuan itu mungkin hanya buang-buang waktu saja. Jika perusahaan Anda tidak menempatkan pernyataan tegas di luar kode tes, mohon beri tahu mereka bahwa pernyataan dinonaktifkan di build produksi dan bahwa jika tidak, memperbaiki kesalahan itu sekarang menjadi prioritas pertama Anda.
Nilai penegasan tepat untuk digunakan di dalam logika bisnis dan bukan hanya rangkaian uji. Ini membuatnya mudah untuk menghasilkan banyak tes tingkat tinggi yang tidak harus secara eksplisit menguji banyak hal untuk melewati potongan besar kode Anda dan memicu semua pernyataan ini. Dalam beberapa proyek saya, tes-tes tipikal bahkan tidak benar-benar menegaskan apa-apa, mereka hanya memerintahkan perhitungan terjadi berdasarkan input spesifik dan ini menyebabkan ratusan pernyataan diperiksa dan masalah ditemukan bahkan dalam potongan-potongan logika kecil di lubuk hati.
sumber
Anda dapat menggunakan menegaskan kapan saja. Debat yang datang adalah kapan harus digunakan. Misalnya dalam panduan :
sumber