Seorang rekan kerja telah menambahkan perintah assert beberapa kali dalam perpustakaan kami di tempat di mana saya akan menggunakan pernyataan if dan memberikan pengecualian. (Saya belum pernah mendengar tentang assert sebelumnya.) Berikut adalah contoh bagaimana dia menggunakannya:
assert('isset($this->records); /* Records must be set before this is called. */');
Saya akan melakukan:
if (!isset($this->records)) {
throw new Exception('Records must be set before this is called');
}
Dari membaca dokumen PHP tentang assert , sepertinya Anda disarankan untuk memastikan assert aktif dan menambahkan penangan sebelum menggunakan assert. Saya tidak dapat menemukan tempat di mana dia melakukan ini.
Jadi, pertanyaan saya adalah, apakah menggunakan assert adalah ide bagus yang diberikan di atas dan haruskah saya menggunakannya lebih sering daripada jika dan pengecualian?
Catatan lain, kami berencana untuk menggunakan pustaka ini pada berbagai proyek dan server, termasuk proyek yang bahkan mungkin bukan bagian kami (pustaka bersifat open source). Apakah ada perbedaan dalam menggunakan assert?
'isset
(baris kode denganassert
)? Bukan hanyaisset
(tanpa kutipan tunggal,'
)?Jawaban:
Aturan praktis yang dapat diterapkan di sebagian besar bahasa (semua yang samar-samar saya ketahui) adalah bahwa an
assert
digunakan untuk menyatakan bahwa suatu kondisi selalu benar sedangkan anif
sesuai jika dapat dibayangkan terkadang akan gagal.Dalam hal ini, saya akan mengatakan itu
assert
tepat (berdasarkan pemahaman saya yang lemah tentang situasi) karenarecords
harus selalu diatur sebelum metode yang diberikan dipanggil. Jadi, kegagalan untuk menetapkan rekor akan menjadi bug dalam program daripada kondisi runtime. Di sini,assert
membantu memastikan (dengan pengujian yang memadai) bahwa tidak ada kemungkinan jalur eksekusi program yang dapat menyebabkan kode yang dijaga denganassert
dipanggil tanparecords
disetel.Keuntungan menggunakan
assert
sebagai lawanif
adalah yangassert
umumnya dapat dimatikan dalam kode produksi sehingga mengurangi overhead. Jenis situasi yang paling baik ditanganiif
dapat terjadi selama runtime dalam sistem produksi sehingga tidak ada yang hilang dengan tidak dapat mematikannya.sumber
assert_options(ASSERT_BAIL)
. Ini lebih cepat daripada solusi manual if / throw.Pikirkan pernyataan sebagai "komentar kuat". Dari pada komentar seperti:
// Note to developers: the parameter "a" should always be a number!!!
menggunakan:
assert('is_numeric(a) /* The parameter "a" should always be a number. */');
Artinya persis sama dan ditujukan untuk audiens yang sama persis, tetapi komentar pertama mudah dilupakan atau diabaikan (tidak peduli berapa banyak tanda seru), sedangkan "komentar kuat" tidak hanya tersedia untuk dibaca dan dipahami manusia, itu juga terus-menerus diuji mesin selama pengembangan, dan tidak akan diabaikan jika Anda menyiapkan penanganan assert yang baik dalam kode dan kebiasaan kerja.
Dilihat dengan cara ini, pernyataan adalah konsep yang sama sekali berbeda dari if (error) ... dan pengecualian, dan keduanya dapat hidup berdampingan.
Ya, Anda harus mengomentari kode Anda, dan ya, Anda harus menggunakan "komentar kuat" (menegaskan) bila memungkinkan.
sumber
Itu sepenuhnya tergantung pada strategi pengembangan Anda. Sebagian besar pengembang tidak menyadari
assert()
dan menggunakan pengujian unit hilir. Tetapi skema pengujian proaktif dan built-in terkadang bisa menguntungkan.assert berguna, karena dapat diaktifkan dan dinonaktifkan. Itu tidak menguras kinerja jika tidak ada penangan pernyataan seperti itu yang ditentukan. Kolega Anda tidak memilikinya, dan Anda harus merancang beberapa kode yang memungkinkannya sementara dalam lingkungan pengembangan (jika E_NOTICE / E_WARNING aktif, jadi harus menjadi penangan pernyataan). Saya menggunakannya sesekali di mana kode saya tidak dapat menerima jenis variabel campuran - saya biasanya tidak terlibat dalam pengetikan ketat dalam PHP yang diketik lemah, tetapi ada kasus penggunaan acak:
function xyz($a, $b) { assert(is_string($a)); assert(is_array($b));
Yang misalnya akan mengkompensasi kurangnya penentu tipe
string $a, array $b
. PHP5.4 akan mendukung mereka, tetapi tidak dicentang.sumber
Assert bukanlah pengganti untuk kontrol aliran normal seperti
if
atau pengecualian, karena ini hanya dimaksudkan untuk digunakan untuk debugging selama pengembangan.sumber
Catatan penting tentang assert di PHP lebih awal dari 7. Tidak seperti bahasa lain dengan konstruksi assert, PHP tidak membuang pernyataan assert sepenuhnya - ia memperlakukannya sebagai fungsi (lakukan debug_backtrace () dalam fungsi yang dipanggil dengan assertion). Mematikan asserts tampaknya hanya mengubah fungsi menjadi tidak melakukan apa pun di mesin. Perhatikan bahwa PHP 7 dapat dibuat untuk meniru perilaku ini dengan menyetel zend.assertions ke 0 alih-alih nilai yang lebih normal dari 1 (aktif) atau -1 (nonaktif).
Masalah yang muncul dalam assert itu akan mengambil argumen apa pun - tetapi jika argumennya bukan string, maka assert mendapatkan hasil ekspresi apakah assert aktif atau nonaktif. Anda dapat memverifikasi ini dengan blok kode berikut.
<?php function foo($a) { echo $a . "\n"; return TRUE; } assert_options(ASSERT_ACTIVE, FALSE); assert( foo('You will see me.')); assert('foo(\'You will not see me.\')'); assert_options(ASSERT_ACTIVE, TRUE); assert( foo('Now you will see')); assert('foo(\'both of us.\')');
Mengingat maksud dari assert ini adalah bug, dan sudah lama sejak itu ada dalam bahasa sejak assert diperkenalkan kembali di PHP 4.
String yang diteruskan ke assert dievaluasi, dengan semua implikasi performa dan bahaya yang menyertainya, tetapi ini adalah satu-satunya cara untuk mendapatkan pernyataan assert agar berfungsi sebagaimana mestinya di PHP (Perilaku ini tidak digunakan lagi di PHP 7.2).
EDIT: Diubah di atas untuk mencatat perubahan di PHP 7 dan 7.2
sumber
zend.assertions
pengaturan ini untuk mematikan sepenuhnyaassert()
.Assert sebaiknya hanya digunakan dalam pengembangan karena berguna untuk debugging. Jadi jika Anda mau, Anda dapat menggunakannya untuk mengembangkan situs web Anda, tetapi Anda harus menggunakan pengecualian untuk situs web langsung.
sumber
Tidak, rekan kerja Anda tidak boleh menggunakannya sebagai penangan kesalahan tujuan umum. Menurut manual:
Jika Anda terbiasa dengan rangkaian pengujian otomatis, kata kerja "assert" biasanya digunakan untuk memverifikasi keluaran dari beberapa metode atau fungsi. Sebagai contoh:
function add($a, $b) { return $a + $b; } assert(add(2,2) == 5, 'Two and two is four, dummy!'); assert(is_numeric(add(2,2)), 'Output of this function to only return numeric values.');
Rekan kerja Anda tidak boleh menggunakannya sebagai pengendali kesalahan tujuan umum dan dalam kasus ini sebagai pemeriksaan masukan. Sepertinya bidang rekaman tidak dapat disetel oleh beberapa pengguna perpustakaan Anda.
sumber
Rekan kerja Anda benar-benar mencoba menerapkan design by contract (DbC) dari bahasa Eiffel dan berdasarkan buku: Object Oriented Software Construction, 2nd Edition.
Penegasan, seperti yang dia gunakan, akan menjadi {P}-bagian dari Hoare Logic atau Hoare Triple: {P} C {Q}, di mana {P} adalah pernyataan prasyarat (ion) s dan {Q} adalah pernyataan pasca-kondisi (ion) s.
Saya akan mengambil catatan kritis dari saran yang diberikan tentang fitur assert di PHP yang memiliki bug. Anda tidak ingin menggunakan kode buggy. Apa yang Anda inginkan adalah pembuat PHP untuk memperbaiki bug di assert. Sampai mereka melakukannya, Anda dapat menggunakan assert, tetapi gunakan dengan memperhatikan status buggy saat ini.
Selain itu, jika fitur assert buggy, saya sarankan Anda tidak menggunakannya dalam kode produksi. Namun demikian, saya menganjurkan agar Anda menggunakannya dalam pengembangan dan pengujian kode jika sesuai.
Terakhir — jika Anda melakukan studi desain demi kontrak, Anda akan menemukan bahwa ada konsekuensi penggunaan pernyataan Boolean dalam kaitannya dengan pewarisan klasik berorientasi objek — yaitu — Anda tidak boleh melemahkan prasyarat, atau melemahkan pascakondisi. Melakukannya bisa berbahaya bagi objek turunan polimorfik Anda yang berinteraksi satu sama lain. Sampai Anda memahami apa artinya — saya akan membiarkannya!
Selain itu — saya sangat menyarankan agar pembuat PHP melakukan studi komprehensif tentang desain berdasarkan kontrak dan mencoba memasukkannya ke dalam PHP ASAP! Maka kita semua bisa mendapatkan keuntungan dari memiliki kompiler / interpreter yang sadar DbC, yang akan menangani masalah yang disebutkan dalam jawaban (di atas):
CATATAN: Bahkan penggunaan
if
-statement sebagai pengganti assert (precondition) akan mengalami konsekuensi yang mengerikan jika digunakan untuk memperkuat prasyarat atau melemahkan post-condition. Untuk memahami apa artinya, Anda perlu mempelajari desain demi kontrak untuk mengetahuinya! :-)Selamat belajar dan belajar.
sumber