Mengapa menggunakan ketat dan peringatan?


104

Menurut saya, banyak pertanyaan di tag Perl dapat diselesaikan jika orang akan menggunakan:

use strict;
use warnings;

Saya pikir beberapa orang menganggap ini mirip dengan roda pelatihan, atau komplikasi yang tidak perlu, yang jelas tidak benar, karena bahkan pemrogram Perl yang sangat terampil menggunakannya.

Tampaknya sebagian besar orang yang mahir dalam Perl selalu menggunakan kedua pragma ini, sedangkan mereka yang paling diuntungkan dengan menggunakannya jarang melakukannya. Jadi, saya pikir akan menjadi ide yang bagus untuk memiliki pertanyaan untuk ditautkan saat mendorong orang untuk use strictdan warnings.

Jadi, mengapa harus menjadi pengembang Perl use strictdan warnings?


14
Saya selalu bertanya-tanya untuk hal-hal seperti ini mengapa mereka tidak hanya menjadikannya default dan meminta pengembang benar-benar harus secara aktif melonggarkan hal-hal, di manause loose;
Paul Tyng

12
Seperti banyak hal keren dan berguna Perl dimulai sebagai hack, sebagai alat untuk orang yang menciptakannya. Belakangan ini menjadi lebih populer dan semakin banyak orang yang tidak terampil mulai menggunakannya. Ini adalah saat Anda mulai berpikir bahwa sesuatu seperti use strictitu ide yang bagus tetapi kompatibilitas mundur telah menjadi masalah nyata bagi Anda :-(
Daniel Böhmer

14
@JB Nizet, @Paul T., Sebenarnya, use strict;aktif secara default saat Anda meminta bahasa Perl 5.12 (atau lebih tinggi). Coba perl -e"use v5.012; $x=123;". no strict;sebenarnya mematikannya.
ikegami

1
Meskipun pada akhirnya maksud Anda benar, semakin sering kita mengatakannya, mungkin semakin banyak orang yang akan mendengar. Akhir-akhir ini telah ada beberapa kegaduhan saat mencoba membuat lebih banyak / lebih baik / tutorial Perl modern tersedia dan tentu saja ketat / peringatan akan berada di atas masing-masing ini. Untuk milik saya, saya berencana untuk memiliki s / w di bagian atas setiap cuplikan, agar semua pemula melihatnya setiap saat
Joel Berger

5
@JoelBerger Tidak, sebenarnya tidak seperti itu. Seperti yang saya katakan, hanya ada kata-kata yang mirip di judulnya. Ini untuk kompatibilitas mundur. adalah kalimat pertama dalam jawaban yang diterima, bagaimana menurut Anda yang berlaku untuk pertanyaan saya?
TLP

Jawaban:


83

Sebagai permulaan, use strict;(dan pada tingkat yang lebih rendah, use warnings;) membantu menemukan kesalahan ketik dalam nama variabel. Bahkan programmer berpengalaman membuat kesalahan seperti itu. Kasus yang umum terjadi adalah lupa mengganti nama instance variabel saat membersihkan atau memfaktorkan ulang kode.

Menggunakan use strict; use warnings;menangkap banyak kesalahan lebih cepat daripada tertangkap sebaliknya, yang membuatnya lebih mudah untuk menemukan akar penyebab kesalahan. Akar penyebabnya mungkin kebutuhan akan kesalahan atau pemeriksaan validasi, dan itu bisa terjadi terlepas dari keahlian programmer.

Apa yang baik tentang peringatan Perl adalah bahwa mereka jarang palsu, jadi tidak ada biaya untuk menggunakannya.


Bacaan terkait: Mengapa digunakan my?


2
@TLP, saya tidak akan membuat studi untuk mengukur seberapa besar manfaatnya. Sudah cukup untuk mengatakan bahwa mereka membantu tanpa syarat.
ikegami

1
Kenapa dijadikan opsional kalau punya banyak manfaat? Mengapa tidak mengaktifkannya secara default (seperti komentar seseorang di atas)? Apakah karena alasan kompatibilitas?
Jean

4
@ Jean, kompatibilitas mundur. Perhatikan bahwa use strict;diaktifkan secara default jika Anda menggunakan versi 5.12 atau yang lebih baru dari bahasa ( use 5.012;).
ikegami

@Jean jika Anda menulis skrip sederhana, Anda benar-benar tidak ingin diperingatkan oleh peringatan tentang nama penangan file atau karena tidak mendeklarasikan variabel sebelum menggunakannya :-)
user2676847

28

Rupanya use strictharus (harus) digunakan ketika Anda ingin memaksa perl ke kode dengan benar yang dapat memaksa deklarasi, menjadi eksplisit pada string dan sub yaitu bareword atau menggunakan ref dengan hati-hati. Catatan: jika ada kesalahan penggunaan ketat akan membatalkan eksekusi jika digunakan.

Sementara use warnings;akan membantu Anda menemukan kesalahan pengetikan dalam program seperti Anda melewatkan titik koma, Anda menggunakan 'elseif' dan bukan 'elsif', Anda menggunakan sintaks atau fungsi yang tidak digunakan lagi, apapun seperti itu. Catatan: gunakan peringatan hanya akan memberikan peringatan dan melanjutkan eksekusi yaitu tidak akan membatalkan eksekusi ..

Bagaimanapun, akan lebih baik jika kita membahas detailnya, yang saya sebutkan di bawah ini

Dari perl.com (favorit saya):

gunakan 'vars' yang ketat;

yang berarti Anda harus selalu mendeklarasikan variabel sebelum Anda menggunakannya.

Jika Anda tidak mendeklarasikan, Anda mungkin akan mendapatkan pesan kesalahan untuk variabel yang tidak dideklarasikan

Simbol global "$ variablename" membutuhkan nama paket eksplisit di scriptname.pl baris 3

Peringatan ini berarti Perl tidak terlalu jelas tentang apa ruang lingkup variabel itu. Jadi, Anda perlu eksplisit tentang variabel Anda, yang berarti mendeklarasikannya dengan mysehingga dibatasi ke blok saat ini, atau merujuknya dengan nama yang sepenuhnya memenuhi syarat (misalnya: $ MAIN :: variablename).

Jadi, kesalahan waktu kompilasi dipicu jika Anda mencoba mengakses variabel yang belum memenuhi setidaknya satu dari kriteria berikut:

  • Ditentukan sebelumnya oleh Perl itu sendiri, seperti @ARGV,% ENV, dan semua variabel tanda baca global seperti $. atau $ _.

  • Dinyatakan dengan kami (untuk global) atau saya (untuk leksikal).

  • Diimpor dari paket lain. (Penggunaan vars pragma memalsukan impor, tetapi gunakan sebagai gantinya.)

  • Sepenuhnya terkualifikasi menggunakan nama paket dan pemisah paket titik dua ganda.

gunakan 'subs' yang ketat;

Pertimbangkan dua program

# prog 1
   $a = test_value;
   print "First program: ", $a, "\n";
   sub test_value { return "test passed"; }
 Output: First program's result: test_value

# prog 2
   sub test_value { return "test passed"; }
   $a = test_value;
   print "Second program: ", $a, "\n";
 Output: Second program's result: test passed

Dalam kedua kasus kami memiliki sub test_value () dan kami ingin memasukkan hasilnya ke $ a. Namun, saat kami menjalankan kedua program tersebut, kami mendapatkan dua hasil yang berbeda:

Pada program pertama, pada titik kita sampai $a = test_value;, Perl tidak mengetahui sub test_value (), dan test_value diinterpretasikan sebagai string 'test_value'. Di program kedua, definisi test_value () muncul sebelum $a = test_value;baris. Perl menganggap test_value sebagai sub panggilan.

Istilah teknis untuk kata-kata yang terisolasi seperti test_value yang mungkin berupa subs dan mungkin string bergantung pada konteks, adalah bareword . Penanganan bareword oleh Perl dapat membingungkan, dan dapat menyebabkan bug dalam program.

Bug adalah apa yang kita temui di program pertama kita, Ingat bahwa Perl tidak akan berharap untuk menemukannya test_value(), jadi karena ia belum melihat test_value (), ia mengasumsikan bahwa Anda menginginkan sebuah string. Jadi jika Anda use strict subs;, itu akan menyebabkan program ini mati dengan kesalahan:

Bareword "test_value" tidak diizinkan sementara "strict subs" digunakan di ./a6-strictubs.pl baris 3.

Solusi untuk kesalahan ini adalah
1. Gunakan tanda kurung untuk menjelaskan bahwa Anda memanggil sub. Jika Perl melihat $ a = test_value () ;,
2. Deklarasikan sub Anda sebelum Anda menggunakannya untuk pertama kali

use strict;
sub test_value;  # Declares that there's a test_value() coming later ...
my $a = test_value;  # ...so Perl will know this line is okay.
.......
sub test_value { return "test_passed"; }

3. Dan Jika Anda bermaksud menggunakannya sebagai string, kutiplah.

Jadi, penyempitan ini membuat Perl memperlakukan semua bareword sebagai kesalahan sintaks. * Bareword adalah nama kosong atau pengenal yang tidak memiliki interpretasi lain yang dipaksakan oleh konteks. (Konteks sering kali dipaksa oleh kata kunci atau token terdekat, atau dengan pernyataan awal dari kata yang dimaksud.) * Jadi Jika Anda bermaksud menggunakannya sebagai string, kutip dan Jika Anda bermaksud menggunakannya sebagai pemanggilan fungsi, deklarasikan sebelumnya atau gunakan tanda kurung.

Bareword berbahaya karena perilaku yang tidak terduga ini. use strict; (or use strict 'subs';)membuatnya dapat diprediksi, karena bareword yang mungkin menyebabkan perilaku aneh di masa mendatang akan membuat program Anda mati sebelum dapat menimbulkan malapetaka

Ada satu tempat di mana tidak masalah untuk menggunakan bareword bahkan ketika Anda telah mengaktifkan subscriber ketat: saat Anda menetapkan kunci hash.

$hash{sample} = 6;   # Same as $hash{'sample'} = 6
%other_hash = ( pie => 'apple' );

Bareword dalam kunci hash selalu diartikan sebagai string, jadi tidak ada ambiguitas.

gunakan 'ref' yang ketat;

Ini menghasilkan kesalahan waktu proses jika Anda menggunakan referensi simbolik, dengan sengaja atau tidak. Nilai yang bukan merupakan acuan keras kemudian diperlakukan sebagai acuan simbolis . Artinya, referensi diartikan sebagai string yang mewakili nama variabel global.

use strict 'refs';

$ref = \$foo;       # Store "real" (hard) reference.
print $$ref;        # Dereferencing is ok.

$ref = "foo";       # Store name of global (package) variable.
print $$ref;        # WRONG, run-time error under strict refs.

gunakan peringatan;

Pragma yang tercakup secara leksikal ini memungkinkan kontrol yang fleksibel atas peringatan bawaan Perl, baik yang dipancarkan oleh kompilator maupun yang dari sistem run-time.

Dari perldiag:

Jadi mayoritas pesan peringatan dari klasifikasi di bawah yaitu W, D & S dapat dikontrol menggunakan warningspragma.

(W) Peringatan (opsional)
(D) Penghentian (diaktifkan secara default)
(S) Peringatan parah (diaktifkan secara default)

Saya telah membuat daftar beberapa pesan peringatan yang sering muncul di bawah menurut klasifikasi. Untuk info rinci tentang mereka dan pesan lainnya merujuk perldiag

(W) Peringatan (opsional):

Argumen hilang di% s
Argumen yang hilang ke -% c
(Apakah maksud Anda &% s sebagai gantinya?)
(Apakah yang Anda maksud adalah "lokal" alih-alih "kami"?)
(Apakah maksud Anda $ atau @ alih-alih%?)
'% S 'bukan
panjang referensi kode () yang digunakan pada% s
Salah taruh _ dalam bilangan

(D) Penghentian (diaktifkan secara default):

didefinisikan (@array) tidak digunakan lagi
didefinisikan (% hash) tidak
digunakan lagi Penggunaan my () dalam kondisi palsu
$ # tidak lagi didukung

(S) Peringatan parah (diaktifkan secara default)

elseif harus elsif
% s ditemukan di tempat yang diharapkan operator
(Operator hilang sebelum% s?)
(Titik koma hilang pada baris sebelumnya?)
% s tidak pernah diperkenalkan
Operator atau titik koma hilang sebelum% s
Masalah yang diutamakan: terbuka% s harus dibuka (% s)
Prototipe tidak cocok:% s vs% s
Peringatan: Penggunaan "% s" tanpa tanda kurung tidak jelas
Tidak dapat membuka% s:% s


10

Kedua pragma ini dapat secara otomatis mengidentifikasi bug dalam kode Anda.

Saya selalu menggunakan ini dalam kode saya:

use strict;
use warnings FATAL => 'all';

FATALmembuat kode mati pada peringatan, seperti stricthalnya.

Untuk informasi tambahan, lihat: Lebih ketat dengan peringatan penggunaan FATAL => 'all';

Juga ... Penyempitan, menurut Seuss


Sebenarnya, Anda harus menunda FATAL => "all"till runtime, dengan menetapkan ke $SIG{__WARN__} = sub { croak "fatalized warning @_" };atau Anda mengacaukan compiler mencoba memberi tahu Anda apa yang diperlukan.
tchrist

6
@ tchrist: Ini selalu bekerja untuk saya apa adanya dan seperti yang didokumentasikan. Jika Anda menemukan kasus yang tidak berfungsi seperti yang didokumentasikan, tambal dokumentasi menggunakan perlbug.
Perkakas

9

Ada utas bagus tentang perlmonks tentang pertanyaan ini.

Alasan dasarnya jelas adalah bahwa ketat dan peringatan secara besar-besaran membantu Anda menemukan kesalahan dan membantu proses debug.


3

Sumber :: Blog yang berbeda

Gunakan akan mengekspor fungsi dan nama variabel ke namespace utama dengan memanggil fungsi modul import ().

Pragma adalah modul yang mempengaruhi beberapa aspek dari waktu kompilasi atau perilaku waktu berjalan perl. Pragma memberikan petunjuk kepada kompilator.

Gunakan peringatan - perl keluhan tentang variabel yang digunakan hanya sekali, konversi string yang tidak tepat menjadi angka,. Mencoba menulis ke file yang tidak dibuka. Itu terjadi pada waktu kompilasi. Ini digunakan untuk mengontrol peringatan.

Gunakan ketat - deklarasikan cakupan variabel. Ini digunakan untuk mengatur semacam disiplin dalam skrip. Jika bareword digunakan dalam kode, mereka akan diinterpretasikan. Semua variabel harus diberi ruang lingkup, seperti my, our atau local.


1

Direktif "use strict" memberitahu Perl untuk melakukan pemeriksaan ekstra selama kompilasi kode Anda. Menggunakan direktif ini akan menghemat waktu Anda untuk men-debug kode Perl karena menemukan bug pengkodean umum yang mungkin Anda abaikan sebaliknya.


0

Ketat dan peringatan memastikan variabel Anda tidak global.

Jauh lebih rapi untuk dapat memiliki variabel yang unik untuk masing-masing metode daripada harus melacak setiap nama variabel.

$ _, atau tanpa variabel untuk fungsi tertentu, juga dapat berguna untuk menulis kode yang lebih ringkas dengan lebih cepat.

Namun, jika Anda tidak menggunakan strict and warnings, $ _ menjadi global!


0
use strict;
use warnings;

Ketat dan peringatan adalah mode untuk program perl. Hal ini memungkinkan pengguna untuk memasukkan kode dengan lebih bebas dan lebih dari itu, kode perl akan terlihat formal dan standar pengkodeannya akan efektif.

peringatan berarti sama seperti -wpada baris perl shebang, jadi ini akan memberi Anda peringatan yang dihasilkan oleh program perl, itu akan ditampilkan di terminal

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.