פרק 24: מאת לוקאש אנפורוביץ' בבלוויו, וושינגטון (אוגוסט 2021)
פרקים קודמים
האם אתם יכולים לזהות את הבאג בקוד שלמטה? האם אתם רואים את הבאג בבדיקת הקוד כשמעיינים רק באתר הקריאה?
Token CreateToken(int command_data, int buffer_id);
...
auto token = CreateToken(GetCommandBufferId(), GetCommandData());
אותו סוג עשוי לפעמים לייצג ערכים מדומיינים לא תואמים.
מצב זה מתרחש בדרך כלל בסוגי נתונים לא ספציפיים כמו מספרים שלמים או מחרוזות.
הדוגמה שלמעלה ממחישה איך הדבר יכול לגרום לבאגים.
למרבה המזל, //base
של Chromium מאפשר להציג בקלות סוגים שונים של תוכן בוטה:
#include "base/types/strong_alias.h"
// The first template argument of StrongAlias is a "tag" type.
// The "tag" type is used to distinguish between different
// StrongAlias types.
using CommandData = base::StrongAlias<class CommandDataTag, int>;
using CommandBufferId = base::StrongAlias<class CommandBufferIdTag, int>;
Token CreateToken(CommandData command_data, CommandBufferId buffer_id);
סוגים נפרדים משפרים את נוחות הקריאה.
בנוסף, StrongAlias
מזהה בלבול מסוג 'בלבול' בזמן ההידור:
test.cc:456:16: error: no matching function for call to 'CreateToken'
auto token = CreateToken(GetCommandBufferId(), GetCommandData());
^~~~~~~~~~~
test.cc:123:7: note: candidate function not viable: no known conversion from
'StrongAlias<class CommandBufferIdTag, [...]>' to
'StrongAlias<class CommandDataTag, [...]>' for 1st argument
Token CreateToken(CommandData command_data, CommandBufferId buffer_id);
^
המהדר רואה שהסוגים אינם תואמים, כי יש להם סוג 'תג' אחר.
ניתן להזין כל סוג ב-StrongAlias
בתור ה'תג'.
הדוגמה ממחישה שבסוג ה'תג' אין צורך בהגדרת סוג אפילו בשום מקום – עדיף להשתמש בהצהרה להעברה במקום של מחלקה שלא קיימת.
בעתיד, במקום סוג לא ספציפי (למשל, בוליאני, int ומחרוזת), כדאי להשתמש בחלופות הבאות:
- יש להשתמש ב-
base::IdType32<TagType>
במקום להשתמש ב-int32_t
כמזהה. - יש להשתמש ב-
base::TokenType<TagType>
במקום ב-base::UnguessableToken
לא ספציפי. - צריך להשתמש במחלקה מסוג enum במקום בבול בוליאני (לדוגמה,
kForReload
,kNotForReload
במקוםtrue
,false
). - יש להחליף סוגים אחרים שאינם ספציפיים ב-
base::StrongAlias<TagType, SomeWrappedType>
.