אימות כתובות ונרמול נתפסים כפעילות אחת ברוב הפרויקטים, והבלבול עולה לצוותים בזמן אמיתי. האחד מעצב מחדש ערך כך ששתי צורות כתיבה של אותה כתובת יתאימו זו לזו; האחר מנסה להשיב אם הכתובת קיימת ואם אפשר למסור אליה. הם משתמשים בנתונים שונים, נכשלים בדרכים שונות, ובמערך בדיקות ראויים להחלטות שונות לחלוטין.
המאמר מפריד בין השניים, מסביר מדוע אין רשות שמחזיקה רשימת כתובות גלובלית שלמה, ומתאר מה מערכת יכולה להצהיר ביושר לאחר הרצה של כל אחד מהם.
מה עושה הנרמול בפועל
נרמול הוא כתיבה מחדש. הוא לוקח את מה שהמשתמש הקליד ומפיק ממנו גרסה קנונית: רישיות עקבית, סוגי רחובות מורחבים או מקוצרים לפי מוסכמה אחת, מילות כיוון תקניות, מפריד עקבי, רווחים חתוכים, ומיקוד הכתוב בצורה מוסכמת אחת. שום דבר אינו מאומת. מחרוזת שלא התאימה מעולם לשום מקום אמיתי מתנרמלת בדיוק כמו מחרוזת נכונה.
הערך של הנרמול הוא בהשוואה. שתי רשומות שמתארות את אותו מקום אך הוקלדו אחרת הופכות זהות בתו אחר תו לאחר הנרמול, וכך מתחילים לעבוד סילוק כפילויות, התאמה וחיפוש. הוא גם מייצב את האחסון: צורה אחת במסד הנתונים פירושה שצרכנים במורד הזרם מפסיקים לממש מחדש את הכללים.
הנרמול זול, דטרמיניסטי ובטוח להרצה בכל מקום. השילוב הזה הוא הסיבה שהוא שייך לגבול המוקדם ביותר שהנתונים חוצים—מטפל הטופס, סקריפט הייבוא, נקודת הכניסה של ה-API—ורק פעם אחת. נרמול חוזר בשכבות שונות הוא הדרך שבה ערך מתנדנד בין שתי צורות כתיבה.
מה האימות באמת מנסה להוכיח?
אימות שואל אם ערך מקובל, והתשובה הכנה תלויה כולה בכמה ראיות יש. שלוש שאלות שונות מתחבאות מאחורי המילה האחת.
הראשונה מבנית: האם השדות הנדרשים קיימים, האם התווים בתוך הקבוצה המותרת, האם האורך סביר. זו אינה דורשת נתוני ייחוס כלל וניתן לבצע אותה בכל מקום.
השנייה יחסית: האם המיקוד נופל בטווח שהאזור המוצהר משתמש בו, האם קוד המדינה עקבי איתו, האם המדינה מסכימה עם קוד החלוקה שלה. זו דורשת נתוני ייחוס אבל לא מסד נתוני כתובות, והיא תופסת נתח גדול מן שגיאות ההקלדה האמיתיות.
השלישית קיומית: האם באמת יש בניין במספר הזה ברחוב הזה. זו דורשת מערך נתונים מקומי סמכותי, ורק מדינות מסוימות מפרסמות כזה ששלם מספיק כדי להשיב עליה.
רוב המערכות מצהירות על השלישית ומממשות את השנייה. זה לא בהכרח שגוי, אבל זו צריכה להיות החלטה מודעת ולא תאונה, משום שהיא קובעת מה הודעת השגיאה יכולה לומר ביושר.
| שאלה | מה היא שואלת | מה היא דורשת |
|---|---|---|
| מבנית | האם השדות הנדרשים קיימים, התווים בקבוצה המותרת והאורך סביר | שום נתוני ייחוס |
| יחסית | האם המיקוד נופל בטווח שהאזור המוצהר משתמש בו, קוד המדינה עקבי איתו והמדינה מסכימה עם קוד החלוקה | נתוני ייחוס, אבל לא מסד נתוני כתובות |
| קיומית | האם באמת יש בניין במספר הזה ברחוב הזה | מערך נתונים מקומי סמכותי, שרק מדינות מסוימות מפרסמות |
האם קיים דבר כזה מסד כתובות גלובלי?
לא כזה שהוא שלם, סמכותי ועדכני. מפעילי דואר מתחזקים נתוני מסירה משלהם לשטחים שלהם, בתנאים שלהם, ורבים מהם אינם מפרסמים רשימה ברמת כתובת כלל. היכן שקיימים מערכי נתונים לאומיים, הם מכסים את אותה מדינה, בשפה ובמבנה של אותה מדינה. אין מרשם יחיד שספק יכול להיוועץ בו כדי להחליט אם כתובת שרירותית במקום כלשהו בעולם קיימת.
מה שספקים עושים בפועל, בשילובים שונים: משתמשים בנתוני ייחוס מצטברים משלהם, מתאימים מול מיקוד וגיאוגרפיות מנהליות, מחילים כללי סבירות, ובמדינות מסוימות משתמשים במערך נתונים מקומי ברישיון. כל אחד מאלה חלקי. שירות שמדווח על כתובת כתקפה מדווח בדרך כלל שהיא נראית עקבית עם מה שהשירות יודע, ושירות שמדווח עליה כלא תקפה פשוט עשוי לחסר כיסוי.
המסקנה המעשית היא שהצהרה על כתובת מאומתת אינה הצהרה שהמערכת יכולה לתמוך בה באופן גלובלי. הצהרה על כתובת תקפה מבחינה מבנית ועקבית עם נתוני הייחוס הזמינים לנו היא הצהרה שהיא כן יכולה לתמוך בה, והיא זו שראויה להיכנס לתיעוד.
מדוע הסדר חשוב: קודם נרמול, אחר כך בדיקה
יש להריץ נרמול קודם. בדיקות ייחוס נכתבות כנגד צורה קנונית, ולכן ערך לא מנורמל ייכשל בהן מסיבות שאין להן דבר עם נכונות: מיקוד עם המפריד במקום אחר, סוג רחוב מקוצר אחרת, הבדל רישיות בשם של אזור.
הסדר ההפוך גרוע מחסר תועלת. אם בדיקת הייחוס רצה ראשונה ודוחה את הערך, אבדה ההזדמנות לתקן מחרוזת שהיתה רק לא מסודרת, והמשתמש רואה שגיאה שאינו יכול לפעול לפיה. אם היא רצה ראשונה ומקבלת, עדיין נדרש הנרמול אחריה, וכך לא נחסך דבר.
כלל סדר שני חל על טיפול בשגיאות. יש להבחין בין מחרוזת שלא ניתן לפרסר, לבין ערך שמתנגש בנתוני הייחוס, לבין ערך שאינו בכיסוי שלנו. השלושה צריכים הודעות שונות ופעולות המשך שונות, וקריסתם לכשל אחד היא מה שהופך אימות כתובות לשרירותי בעיני משתמשים.
למפתחים: כללים, עקיפות ומערכי בדיקות
אין לנסות לאמת כתובת בביטוי רגולרי אחד. השונות יושבת בחלקים שביטוי רגולרי הוא הגרוע ביותר בהם—שמות רחובות, פרטי יחידה, כתבים שאינם לטיניים—והוודאות יושבת בחלקים שאפשר לבדוק כנגד רשימה. יש לשמור את התבניות לבדיקות אורך ותווים, ולהשאיר את בדיקות הייחוס בנתונים.
יש לאפשר תמיד עקיפה ידנית. נתוני ייחוס חלקיים ולעיתים שגויים, וכתובת נכונה באמת שכלי הבדיקה אינו מזהה חייבת להישאר ניתנת לשמירה. יש לרשום את העקיפה עם הערך שנדחה, כדי שאפשר יהיה להבדיל בין כלי בדיקה שמשתפר לבין כזה שרק מרגיז אנשים.
יש להחזיק נרמול ואימות כשלבים נפרדים בקוד, עם שמות נפרדים. פונקציה שמכונה בדיקת כתובת ולפעמים כותבת מחדש את הקלט שלה ולפעמים דוחה אותו היא מן הדברים שהופכים תקלות לבלתי ניתנות לאיתור. אותה הפרדה היא גם מה שמאפשר להריץ נרמול על רשומות היסטוריות ולהשאיר את האימות כשער כניסה—הבחנה מוכרת לכל מי שבונה נתוני כתובת למערכי בדיקות.
עבור מערך בדיקות, יש לאמת את שתי ההתנהגויות בנפרד: שקלט מבולגן נתון מתנרמל למחרוזת קנונית צפויה, ושזוג שדות לא עקבי נתון נדחה. כשהרשימה של נתוני הייחוס משתנה, רק הקבוצה השנייה של הבדיקות אמורה לזוז.
צעדים הבאים
כדאי לנסח במשפט אחד איזו מן שלוש השאלות המערכת עונה עליה היום, ולבדוק אם הודעות השגיאה מצהירות על יותר מכך. אחר כך יש להוסיף מערך בדיקה לכתובת נכונה שהכלי דוחה, ולהחליט מה אמור לקרות לה. מחולל הכתובות מפיק ערכים שתקפים מבחינה מבנית מעצם בנייתם, וזה הופך אותו לבסיס חיובי נוח לצד הדוגמאות השבורות במכוון שנשמרות. תקפות מבנית זה כל מה שהם: אי אפשר למסור את הערכים האלה ליעד כלשהו, והם אינם מוכיחים דבר על מקום מגורים. למעבר מפורט על אי התאמה אחת שקל לגלות, ראו מקרי בדיקה של טופס כתובת בקופה.