Perbedaan antara "precondition" dan "assert" dengan cepat?

105

Apa perbedaan antara precondition(condition: Bool, message: String)dan assert(condition: Bool, message: String)di Swift?

Keduanya terlihat sama bagiku. Dalam konteks mana kita harus menggunakan salah satu dari yang lain?

Chao Ruan
sumber

Jawaban:

125

assertadalah untuk pemeriksaan kewarasan selama pengujian, sedangkan preconditionuntuk melindungi dari hal-hal yang, jika terjadi, berarti program Anda tidak dapat dilanjutkan secara wajar.

Jadi misalnya, Anda mungkin menggunakan assertbeberapa kalkulasi yang memiliki hasil yang masuk akal (dalam beberapa batasan, katakanlah), untuk segera menemukan jika Anda memiliki bug. Tetapi Anda tidak ingin mengirimkannya, karena hasil di luar batas mungkin valid, dan tidak kritis sehingga tidak boleh membuat aplikasi Anda mogok (misalkan Anda hanya menggunakannya untuk menampilkan kemajuan dalam bilah kemajuan).

Di sisi lain, memeriksa bahwa subskrip pada array valid saat mengambil elemen adalah a precondition. Tidak ada tindakan yang masuk akal selanjutnya untuk objek array yang akan diambil ketika diminta untuk subskrip yang tidak valid, karena harus mengembalikan nilai non-opsional.

Teks lengkap dari dokumen (coba mengklik opsi assertdan preconditiondi Xcode):

Prasyarat

Periksa kondisi yang diperlukan untuk membuat kemajuan.

Gunakan fungsi ini untuk mendeteksi kondisi yang harus mencegah program berjalan bahkan dalam kode pengiriman.

  • Di playgrounds dan build -Onone (default untuk konfigurasi Debug Xcode): jika conditionbernilai false, hentikan eksekusi program dalam status dapat di-debug setelah pencetakan message.

  • Build dalam -O (default untuk konfigurasi Rilis Xcode): jika conditionbernilai false, hentikan eksekusi program.

  • Build yang belum diperiksa, conditiontidak dievaluasi, tetapi pengoptimal mungkin berasumsi bahwa itu akan dievaluasi ke true. Kegagalan untuk memenuhi asumsi bahwa dalam build -Ounchecked adalah kesalahan pemrograman yang serius.

Menegaskan

Gaya C tradisional menegaskan dengan pesan opsional.

Gunakan fungsi ini untuk pemeriksaan kesehatan internal yang aktif selama pengujian tetapi tidak memengaruhi performa kode pengiriman. Untuk memeriksa penggunaan yang tidak valid dalam rilis build; lihat precondition.

  • Di playgrounds dan build -Onone (default untuk konfigurasi Debug Xcode): jika conditionbernilai false, hentikan eksekusi program dalam status dapat di-debug setelah pencetakan message.

  • Build dalam -O (default untuk konfigurasi Rilis Xcode), conditiontidak dievaluasi, dan tidak ada efek.

  • Build yang belum diperiksa, conditiontidak dievaluasi, tetapi pengoptimal mungkin berasumsi bahwa itu akan dievaluasi ke true. Kegagalan untuk memenuhi asumsi bahwa dalam build -Ounchecked adalah kesalahan pemrograman yang serius.

Kecepatan Kecepatan Udara
sumber
2
"Tetapi Anda tidak ingin mengirimkannya, karena hasil di luar batas mungkin valid, dan tidak kritis, jadi sebaiknya aplikasi Anda tidak mogok" yang sangat tidak jelas bagi saya. Mohon dapatkah Anda menyertakan contoh yang tepat? Mungkin beberapa kode.
Madu
2
Menanggapi pertanyaan Anda, saya pribadi menggunakan asserts untuk menangkap hal-hal yang seharusnya tidak terjadi di build saya saat saya menulis dan mengujinya. Bayangkan pernyataan penjaga membaca JSON di mana data["name"]tidak ada, tetapi seharusnya. Memiliki penegasan di dalam penjaga..else {} akan membantu saya menangkap kesalahan saya dengan menabrak dan membawa saya ke masalah tersebut. Demikian pula, jika kode ini sedang diproduksi, assert tidak akan merusak program, dan kode cadangan apa pun yang saya gunakan ( return nil) akan mengambil alih.
Alec O
1
Tidakkah sebaiknya Anda memeriksa indeks dan tidak melakukan apa pun alih-alih merusak seluruh aplikasi?
Iulian Onofrei
Ya, Anda harus memeriksa indeks, tetapi setiap orang kadang-kadang tergelincir, dan menggunakan asserts membantu Anda menyadari bahwa Anda seharusnya memeriksa indeks ketika Anda lupa.
Victor Engel
"Tetapi Anda tidak ingin mengirimkannya, karena hasil di luar batas mungkin valid, dan tidak kritis, jadi aplikasi Anda tidak boleh mogok". Anda dapat mengirimkan aplikasi Anda dengan pernyataan sebanyak yang Anda inginkan. Swift tidak akan mengevaluasi kondisi Anda di dalam blok pernyataan dalam aplikasi rilis
Akshansh Thakur
90

Saya menemukan Swift menegaskan - manual yang hilang sangat membantu

                        debug   release   release
function                -Onone  -O       -Ounchecked
assert()                YES     NO        NO
assertionFailure()      YES     NO        NO**
precondition()          YES     YES       NO
preconditionFailure()   YES     YES       YES**
fatalError()*           YES     YES       YES

Dan dari diskusi menarik tentang Evolusi Swift

- assert: memeriksa kode Anda sendiri untuk kesalahan internal

- precondition: untuk memeriksa bahwa klien Anda telah memberikan argumen yang valid.

Selain itu, Anda harus berhati-hati tentang apa yang harus digunakan, lihat assertionFailure dan Optimization Level

onmyway133
sumber
Bisakah Anda menjelaskan perbedaan kode dan klien sendiri? Adapun klien maksud Anda seperti memasukkan angka di mana String diharapkan? Bukankah itu seharusnya ditangani dengan beberapa penanganan kesalahan sederhana?
Madu
@Honey Saya pikir maksudnya tentang argumen / hasil dari panggilan API jaringan, atau plugin klien sendiri.
Chen Li Yong
Klien adalah seseorang yang menggunakan kode Anda, katakanlah Anda sedang menulis perpustakaan dan programmer melewati data yang tidak valid. Anda tidak ingin melanjutkan dengan anggun karena itu bisa dianggap sebagai kesalahan pemrograman yang serius. Anda mungkin tidak akan pernah mengalami error pada data API jaringan yang tidak valid karena itu sangat tidak membantu pengguna.
bompf
@ onmyway133: Dari Xcode QuickHelp, saya pikir precondition()dan preconditionFailure()yang memiliki perilaku yang sama . Perbedaan antara fungsi tersebut adalah: preconditionbutuh kondisi di dalam, sementara preconditionFailurehanya membuang.
nahung89
12

Ini preconditionaktif dalam mode rilis sehingga Anda saat Anda mengirimkan aplikasi dan prasyaratnya gagal, aplikasi akan dihentikan. Assertbekerja hanya dalam mode debug sebagai default.

Saya menemukan penjelasan yang bagus ini saat menggunakannya di NSHipster:

Pernyataan adalah konsep yang dipinjam dari logika klasik. Dalam logika, pernyataan adalah pernyataan tentang proposisi dalam sebuah bukti. Dalam pemrograman, pernyataan menunjukkan asumsi yang dibuat pemrogram tentang aplikasi di tempat pernyataan itu dideklarasikan.

Ketika digunakan dalam kapasitas prekondisi dan pascakondisi, yang menggambarkan ekspektasi tentang status kode pada awal dan akhir pelaksanaan metode atau fungsi, pernyataan membentuk kontrak. Pernyataan juga dapat digunakan untuk menerapkan kondisi pada waktu proses, untuk mencegah eksekusi saat prasyarat tertentu gagal.

Greg
sumber
Pernyataan dapat diaktifkan dan dinonaktifkan menggunakan tanda kompilator; mereka dapat aktif dalam kode yang dikirim.
Pétur Ingi Egilsson
6

prasyarat

func precondition(condition: @autoclosure () -> Bool, _ message: @autoclosure () -> String = default, file: StaticString = default, line: UWord = default)

Periksa kondisi yang diperlukan untuk membuat kemajuan.

  1. Gunakan fungsi ini untuk mendeteksi kondisi yang harus mencegah program berjalan bahkan dalam kode pengiriman.
  2. Di playgrounds dan -Onone builds (default untuk konfigurasi Debug Xcode): jika kondisi bernilai false, hentikan eksekusi program dalam status yang dapat di-debug setelah mencetak pesan.
  3. Build dalam -O (default untuk konfigurasi Rilis Xcode): jika kondisi bernilai false, hentikan eksekusi program.
  4. Build yang belum diperiksa, kondisi tidak dievaluasi, tetapi pengoptimal mungkin berasumsi bahwa itu akan dievaluasi menjadi true. Kegagalan untuk memenuhi asumsi bahwa dalam build -Ounchecked adalah kesalahan pemrograman yang serius.

menegaskan

func assert(condition: @autoclosure () -> Bool, _ message: @autoclosure () -> String = default, file: StaticString = default, line: UWord = default)

Gaya C tradisional menegaskan dengan pesan opsional.

  1. Gunakan fungsi ini untuk pemeriksaan kesehatan internal yang aktif selama pengujian tetapi tidak memengaruhi performa kode pengiriman. Untuk memeriksa penggunaan yang tidak valid dalam rilis build; lihat prasyarat.

  2. Di playgrounds dan -Onone builds (default untuk konfigurasi Debug Xcode): jika kondisi bernilai false, hentikan eksekusi program dalam status yang dapat di-debug setelah mencetak pesan.

  3. Dalam -O build (default untuk konfigurasi Rilis Xcode), kondisi tidak dievaluasi, dan tidak ada efek
  4. Build yang belum diperiksa, kondisi tidak dievaluasi, tetapi pengoptimal mungkin berasumsi bahwa itu akan dievaluasi menjadi true. Kegagalan memenuhi asumsi bahwa dalam build -Ounchecked adalah kesalahan pemrograman yang serius
Hantu ke-13
sumber
0

Hanya ingin menambahkan 2 sen saya. Anda dapat menambahkan pernyataan dalam kode Anda sebanyak yang Anda inginkan. Anda dapat Mengirimkan kode Anda dengan pernyataan ini. Swift TIDAK mengevaluasi blok kode ini untuk aplikasi produksi. Ini hanya dievaluasi dalam mode debug.

Menambahkan tautan dokumentasi

Juga melampirkan gambar dari swift.org

masukkan deskripsi gambar di sini

Perhatikan juga, ini tidak terjadi pada prasyarat. Kode yang dikirimkan dengan prasyarat akan mogok dan aplikasi akan dihentikan jika prasyarat tidak dievaluasi sebagai benar.

Singkatnya, pernyataan ditujukan untuk debugging, tetapi dapat dikirimkan tanpa memengaruhi produksi. Pernyataan akan dievaluasi dalam mode debug tetapi tidak dalam produksi.

Dan

PreConditions untuk memastikan hal-hal yang tidak diharapkan tidak terjadi di lingkungan produksi. Kondisi tersebut dievaluasi dan akan menghentikan aplikasi Anda jika dievaluasi sebagai salah

Akshansh Thakur
sumber