Preflight: תפיסת באגים לפני זמן ריצה#
פרק זה מכסה את הפרגמות, בדיקות זמן־ההידור והגדרות היגיינה של זמן הריצה המונעות מרוב הבאגים להגיע למנפה השגיאות מלכתחילה. preflight נקי הוא המסלול הקצר ביותר לסשן ניפוי שגיאות קצר.
קוראים המשתמשים כבר ב־use v5.36 או מאוחר יותר רצים תחת strict ו־warnings כברירת מחדל ויכולים לדלג ישירות לחלקי האבחון וה־autoflush. שאר הפרק מניח שאתם עשויים לתחזק קוד ישן יותר שבו אף אחד מהם אינו מובלע.
Strict ו־warnings#
החל מ־Perl 5.36, use v5.36; (וכל הצהרה על גרסה גבוהה יותר) מפעילה במובלע את use strict; ואת use warnings;. סקריפטים מודרניים אינם כותבים שורות אלה - הצהרת הגרסה מכסה את שתיהן:
use v5.40;
use strict דוחה שלוש מחלקות של קוד רשלני בזמן הידור: משתנים לא־מוצהרים (strict vars), הפניות סימבוליות (strict refs), ו־barewords המשמשים כמחרוזות (strict subs). use warnings מפעיל אבחונים בזמן ריצה עבור קריאות לא־מאותחלות, המרות מספריות מאבדות מידע, מטפלי קובץ המשמשים לאחר סגירה, ועשרות פינות חדות נוספות.
קוד ישן שאינו משתמש באף אחד מהם עדיין נהנה משניהם: הוסיפו אותם, תקנו את הסמלים שעליהם הם מתלוננים, וקַבעו commit.
ביטולים ממוקדים נשארים שימושיים:
no strict 'refs'; # genuine symbolic deref
no warnings 'uninitialized'; # known-safe defaulting
no warnings 'experimental::try'; # on 5.36, 5.38 - see below
לעולם אל תבטלו בסיטונאות: no warnings; ללא רשימת קטגוריות שגוי כמעט תמיד.
לקדם אזהרות למצב fatal עבור אזור מוגדר:
local $SIG{__WARN__} = sub { die $_[0] };
שימושי בראש התוכנית בזמן פיתוח; האזהרה הראשונה הופכת לקריסה המפיקה stack-trace.
use diagnostics#
מרחיב כל אזהרה או הודעת fatal לפסקה המלאה מתוך perldiag:
use diagnostics;
הפלט מילולי - מילולי מדי לסביבת ייצור - אך בזמן ניפוי שגיאות הוא מסביר מה הודעה תמציתית כמו ”Odd number of elements in hash assignment“ באמת אומרת וכיצד לתקן אותה.
גרסה post-hoc: ניתן לצנרת את stderr של תוכנית דרך הפקודה splain כדי להוסיף הערות לאזהרות בדיעבד.
בדיקות זמן־הידור#
perl -c script.pl מנתח את הסקריפט ומריץ כל BEGIN / use, ואז עוצר לפני הוראת זמן הריצה הראשונה. -c נקי משמעו שהקובץ ותלויותיו מתהדרים בהצלחה; אין זה אומר שהתוכנית פועלת כראוי.
perl -c script.pl
script.pl syntax OK
שלבו עם -w כדי להפעיל אזהרות באופן גלובלי עבור שלב ההידור וכל קוד של זמן־הידור:
perl -cw script.pl
perl -MO=Deparse script.pl מדפיס את מה ש־perl באמת ניתח - ניתוחי קדימות שגויים, ענפים מקופלים־קבועים, for שנכתב מחדש כ־while. השתמשו בו כדי לאמת ש־perl ראה את מה שהתכוונתם:
perl -MO=Deparse script.pl
perl -MO=Deparse,-p מאלץ סוגריים מלאים והופך את הקדימות למפורשת.
perl -MO=Concise script.pl מדפיס dump קומפקטי של op-tree; בעיקר לקוראים העוסקים בעבודת אופטימיזציה מעמיקה.
autodie: לגרום לכישלון לזרוק#
פונקציות מובנות המסמנות כישלון באמצעות ערכי החזרה שקריים (open, close, chdir, unlink) קל לשכוח לבדוק אותן. autodie מחליפה אותן בגרסאות שזורקות חריגה:
use autodie qw(open close chdir);
open my $fh, '<', $path; # now dies on failure; no `or die` needed
autodie היא לקסיקלית: רק קריאות בתחומה מושפעות. צמצמו את הביטול לאתר קריאה ספציפי:
{
no autodie 'open';
open my $fh, '<', $path or warn "cannot read $path: $!";
}
העדיפו את autodie על־פני המודול הפרוש Fatal, שלא כיסה פונקציות המחזירות ספירות.
פלט ללא buffering#
כאשר פלט אבחוני נעלם לפני קריסה, או מגיע משולב באופן מוזר עם הודעות warn, הסיבה היא כמעט תמיד stdout המאוגר בבלוקים. הגדירו את $| בראש הסקריפט:
$| = 1;
כל print משוטף עכשיו מיידית. העלות היא פגיעה קטנה בתפוקת I/O; הרווח הוא שמה שאתם רואים בטרמינל תואם לסדר הפעולות שהתוכנית באמת ביצעה.
עבור מטפל קובץ ספציפי מבלי לשנות את הנבחר:
use IO::Handle;
$log_fh->autoflush(1);
אבחונים מוקדמים נפוצים ומשמעותם#
אבחון | משמעות |
|---|---|
| strict מופעל ו־ |
| רשימה שהושמה ל־hash בעלת ספירה אי־זוגית; |
|
|
| משתנה חבילה נצרך בדיוק פעם אחת. כמעט תמיד טעות הקלדה או |
|
|
|
|
למידע נוסף#
print-and-die - כאשר preflight אינו מספיק וזקוקים לאבחוני זמן־ריצה מובנים.
exceptions - הפיכת מסלולי כישלון לחריגות מטופסות שהקורא יכול לבצע עליהן התאמה.