חזק וברור

לא משנה באיזו שפה וטכנולוגיה (מערכת) אתם משתמשים, כולנו בסופו של דבר מתעסקים בדבר אחד : עבודה עם מידע.

אחד המיתוסים הענקיים בעולם התכנות הדינמי (כדוגמת פיתון, רובי, פרל ו PHP) הוא שלא משנה לנו מה הטיפוס של המידע, היות ואותו container של המידע (כלומר משתנה) יכול פעם אחת להכיל מערך, פעם שנייה מחרוזת, פעם שלישית מספר, פעם רביעית מצביע/קישור למשהו ופעם חמישית משהו אחר (יש בכלל משהו אחר ?).

למה זה משנה אתם בטח שואלים. ובכן מה קורה אם יש לכם את המצב הבא:

"100" += 55 * 24

מה הכוונה של המשפט ? האם הכוונה היא שאנחנו רוצים לקבל את הערך של 55*24 בתור מחרוזת והלוסיף את הערך של הפעולה לסוף המחרוזת ? או אולי להפוך את 100 למספר עם הערך של התוצאה ?

אז נכון שזו דוגמא מאוד מופשטת וכל שפה תתנהג שונה, וצריך לדעת, אבל העניין הוא שחייבים להבין מה המידע שיש לנו, איך אנחנו ניגשים אליו ומה התוצר שאנחנו צריכים לקבל.

למשל נגיד ויש לנו מערכת פרללית שמקבלת ביטים, עכשיו הcontainer שמקבל את הביטים שולח חזרה לפי איטרטורים את הביטים. מה קורה כאשר נקבל 4 ביט במקום 24 ביט שאמורים להגיע אלינו, כי הcontainer פירק את זה למנות של 4 ביט כל פעם ? איך אפשר לדעת מתי נקבל את כמות הביטים הנכונים כל פעם ? בשביל זה צריך להבין איך הcontainer עובד ואיך אם בכלל להשיג את המידע כמו שצריך, או אם הוא מתאים למה שמחפשים, או אולי צריך סוג אחר לגמרי של container.

עוד דוגמא לצורך להבין את הcontainer והמידע בו תתרחש בדוגמא הבאה הכתובה בפרל:

my $s = "some string";
my $container = \$s;
print $container;

התוצר של מה שכתבתי אומנם מאוד כפוי, אבל אנחנו נקבל את הכתובת שהמידע של s$ נמצא בו (כלומר התייחסות למידע) ולא את המידע עצמו, ולכן אנחנו חייבים לבדוק מה סוג המידע שcontainer$ מכיל, ויותר מזה, לבדוק אם נמצא reference מה הסוג שלו, כלומר scalar, array או hash. עדיין המידע הזה מאוד חשוב, אי אפשר לברוח מזה.

הנושאים האלו משום מה נראה שלא עולים בכלל אצל רוב המפתחים שמשתמשים בשפות דינמיות, שאוהבים להשוויץ בזה שלא משנה להם סוג המידע, אבל מן הסתם זה המידע הכי חשוב, ומן הסתם התוצר של זה הוא שגם ה container של המידע הוא מאוד חשוב.

אבל הבעיה לא שייכת רק לשפות הדינמיות. ניקח את ++C בתור דוגמא לכך:

void deleteFile(const int numberOfFiles);
void deleteFile(const bool validateFile);
void deleteFile(const float precentageOfFreeSpace);

כמו שאפשר לראות, יצרתי 3 פונקציות של ++C עם override שכל אחת מהם מכילה טיפוס אחר, ועושה משהו אחר. למשל הפונקציה הראשונה תמחק רק כמות קבצים מסויימת. השניה תשאל האם למחוק (כל קובץ שמגיע אליה), והשלישית מחפשת כמה אחוזים של מקום פנוי אנחנו מנסים להשיג במחיקה.

במידה ואכתוב את הקוד הבא:

deleteFile(1);

מי לדעתכם תהיה הפונקציה שתופעל בפועל ? התשובה היא שאי אפשר לדעת ללא הרצת הקוד עם breakpoint או הדפסה למסך את הסוג פונקציה.

מה הסיבה לכך ? ובכן בעולם הC ו ++C טיפוס נתונים אינו נאכף בצורה חזקה, ולכן כמעט כל טיפוס הוא בעצם מספר, ולא תמיד המהדר יודע להבחין מה הכוונה של המתכנת לבין ההגדרה.

זו הסיבה שאני כל כך אוהב טיפוסי נתונים חזקים ומעדיף אותם כל פעם מחדש על פני הגמישות האין סופית הזו. הגמישות האין סופית הזו היא הסיבה שהרבה בעיות כדוגמת מה שהצגתי למעלה נמנעות בשפות עם טיפוסי נתונים חזקים (כדוגמת פסקל):

procedure DeleteFile(const NumberOfFiles : longint); overload;
procedure DeleteFile(const ValidateFile : Boolean); overload;
procedure DeleteFile(const PrecentageOfFreeSpace : single); overload;

אם אכתוב

deleteFile(1);

אז הערך הבוליאני כבר לא יתקיים, ואני יכול להגיד ב 100% שהפרוצדורה עם המספר השלם (שמבקשת את כמות הקבצים למחיקה) היא זו שתקבל בפועל את הקריאה וזה בגלל ש1 הוא מספר שלם, ואז אני צריך לאכפוף את delete עם כמות האחוזים בצורה פשוטה של כתיבת המספר בצורה הבאה:

DeleteFile(1.0);

או

DeleteFile(1 + 0.0);

במידה ורציתי להתייחס לאחוזים, ובכך פתרתי את כל הבעיות שלי. בעוד שב ++C  במידה ואכתוב את הפתרון של 1.0, המהדר ידע שהתכוונתי ל float, אבל במידה ואשתמש במספר שלם, הוא עדיין לא ידע במה מדובר, ולכן לא ברור מה יתרחש, דבר שמוביל להמון באגים שלוקח ימים, שבועות ואף חודשים למי שאינו בקיא בבעיות אלו.

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

האם עדיף לא להיכנס לכאב ראש מההתחלה לבעיות כאלו מאשר לשבור את הראש כאשר הן מתרחשות ?

20 מחשבות על “חזק וברור

  1. ארתיום

    כמה בעיות בקוד C++‎ שלך:

    1. מילה delete היא שמורה לאופרטור מחיקה
    2. אין דבר כזה "overload" אתה לא צריך לציין דבר כזה במפורש.
    3. אין דבר כזה "Bool" יש bool.

    מי לדעתכם תהיה הפונקציה שתופעל בפועל ? התשובה היא שאי אפשר לדעת ללא הרצת הקוד עם breakpoint או הדפסה למסך את הסוג פונקציה

    סליחה??? אתה ממש מדבר שטויות, כי דברים כאלה מוגדרים היטב בתקן השפה.

    Delete(1)‎ תמיד יקרא לך לפונקציה עם int ועם true ל־bool. מה שכן, ברגע שתנסה לקרוא ל־Delete(1+1.0)‎ הקומפיילר לא יתן לך בגלל שהתוצאה של 1+1.0 היא double ואז יש לו מספר אפשרויות שלא מוגדרות היטב והוא יתלונן. אם היית מגדיר פונקציה עם double ולא float אז הוא היה קורא ל־double.

    חוץ מזה… אם אתה לא יודע איך לכתוב פונקציות עם העמסה עדיף אל תכתוב. העמסות מסוג זה בעיתיות — פשוט לא עושים אותם, או אם עושים אז עושים עבור **כל** טיפוס פרימיטיבי או יותר פשוט כותבים template ועושים לו secialization לטיפוסים אחרים שצריך להגדיר עבורם פעולות מיוחדות.

    בקיצור… אם אתה **לא** יודע שפה מסוימת… אל תכתוב בה.

  2. ik_5 מאת

    ארתיום, נחמד שיש תקן, אבל בפועל עם התקן של ++C, עדיין יש את הבעיה של העמסת אופרטורים והטיפוס שלהם. אתה לא מאמין לי ? תתחיל לחפש על זה בגוגל, יש הרבה מאוד מידע בנושא שתומך את מה שאני אומר.
    http://www.daniweb.com/forums/thread38244.html
    קח דוגמא קטנה. חש הרבה מאוד בעיות עם זה.

    ארתיום, ולמה לסבך כל דבר ולעבוד עם template ?! בנתיים אני מראה בהרבה דוגמאות כמה גישה שונה משיגה מצב שבמקום שאתה משתמש ב template לי אין צורך בו.

  3. ארתיום

    תקשיב… מה שאתה מדבר עליו זה א.ב. תקרא כל ספר/מדריך של C++‎ ותסתכל שם על פרקים על העמסה… אלה הדוגמאות הראשונות שיהיו לך שם שתצטרך להיזהר מהם.

    העמסה זה טוב כל עוד:

    1. או שהיא מכסה כל מקרה אפשרי לגמרי
    2. או שהיא תמיד מוגדרת היטב כמו למשל int ומחלקה אחרת לגמרי.

    שוב, תבין זה הבסיס של העמסה… אם אתה לא יודע בסיס… אל תתקרב לשם.

    חבל עידו, אתה זורק דברים על השפה שאתה לא יודע אותה… אני לא יודע הרבה על פסקל אבל אני גם לא מדבר עליה מעבר לתחום שאני מכיר היטב.

    שוב עידו, תעשה בבקשה שיעורי בית… זה לא נראה מקצועי במיוחד קטע הקוד שהבאת

  4. עידו

    ומהכיוון השני, הדוגמא שלך על שפות דינאמיות לא רלוונטית.

    ההתנהגות של 24 * 55 =+ '100' מוגדרת בשפה (כמו שאמרת) ובפרפרזה על מה שארתיום אמר, אם אתה לא מכיר את השפה, אל תתפלא אם יהיו לך באגים.

    ואתה צודק שה container חשוב, אבל כשאתה כותב קוד, אתה יודע מה ה input שאתה צריך לקבל ומה ה output שאתה צריך לתת. כל unittest שנכתב בצורה סבירה, יעלה לך על בעיות מהסוג שתיארת.
    וזה לא שאתה יכול להפטר מה unittest כשיש לך type safety…

    באגים בסגנון של לצפות למחרוזת אבל לקבל מספר קורים לעיתים נדירות.

    Jay Fields מציג ניסוי כזה:
    נניח שיש לך לך פונקציה שמחזירה את התוצאה של 1 + 1, בשפה עם type safety, אתה יודע שערך ההחזרה של הפונקציה הוא מספר, אבל אתה עדיין לא יודע עם הפונקיה שלך עובדת כמו שצריך, יתכן שהיא מחזירה את הערך 6.
    אז אתה צריך להוסיף unittest שבודק האם ערך ההחזרה הוא 2, אבל 2 הוא מספר לכן אתה לא באמת צריך גם לבדוק שערך ההחזרה הוא מספר ולכן type safety הופך להיות מיותר.

    בסופו של דבר, באגים שנובעים מה container הם מעטים מאוד ובדרך כלל ניתנים לתיקון בצורה פשוטה.

  5. ik_5 מאת

    ארתיום, דבר ראשון מעולם לא התיימרתי לדעת ++C להפך, אני לא בדקתי את התחביר של ++C כי אני מתנזר מהשפה הזו, היא כאב ראש גדול מידי, מול התועלת (כאשר אני משווה לתכנולוגיות מתחרות). תראה כמה כלים יש לך אבל בשביל להשיג משהו רציני אתה או צריך להתעלם מהם, או להתמחות בכולם (דבר שלוקח הרבה מאוד שנים) או להשתמש בספריה כלשהי שמנסה לספק לך את הפונקציונליות שאתה מחפש רק בצורה פשוטה. עדיין עצם זה שכתבתי מה שכתבתי, לא הופך ללא נכון אז זה לא בדיוק החוסר ידע שלי, אלא הבעיה של השפה.

    עידו, כאשר אני מקבל מידע מהשתמש או כל מידע שאין לי שליטה בו, אני צריך להיות זהיר כי אני לא יודע מה יהיה התוכן. אם אני לא יודע מה אני אקבל, אני סביר להניח שאקבל את המידע בתור מחרוזת, ואנסה להמיר אותה למספר, ואז כבר לא חשוב לי אם התוכן שאני מספק הוא מספר כי כבר המרתי. אם ההמרה לא הצליחה, אז יש שגיאה שהוזן תוכן לא נכון. אם האורך של המחרוזת גדול מידי לאורך המספר או שתהיה גלישה אני יכול לדעת את זה הרבה לפני ההמרה וגם אז לדווח על שגיאה.

    כך שבעיות של containers הן לא כאלו נדירות. אם תראה את כל ה sql injection שהתרחשו רק עכשיו בחודש האחרון, זה בדיוק הבעיות האלו. ציפו לתוכן, אבל לא בדקו אותו, כי זה לא היה משנה.

    ברגע שאני מבין שאין לי שליטה בכל מה שאני לא עושה בקוד שלי, אז פתאום הדברים הרבה יותר חשובים. למשל מאיר אמר לי שמה שהצגתי הוא מקרה קצה, אבל הוא ממש לא. אם ניקח את פיתון, במידה ואני רוצה לעבוד עם מחרוזת לדומא, אז פרט ל format string, כל דבר אחר אני חייב לדאוג שהוא יבין מתי אני מתכוון ל iterator ומתי אני מתכוון לכל התוכן של המחרוזת, ככה שכל מי שמתכנת בפיתון צריך לטפל בזה כל הזמן.

  6. עידו

    עידו, אני לא מסכים איתך, זה פשוט לא ככה במבחן המציאות.
    בפייתון מחרוזות עובדות כמו שמצפים מהן לעבוד, אתה לא צריך לטפל בזה כל הזמן.

    זה לא שלא קרה לי שציפיתי לקבל list בפייתון וקיבלתי מחרוזת במקום – והמערכת עבדה בגלל זה בצורה שגוייה – אבל באגים מהסוג הזה לא מטרידים אותי, ולא צריכים להטריד אף אחד. unittest פשוט מגלה את השגיאה והתיקון לוקח חצי דקה. יודע מה, גם בלי unittest, רק צריך להפעיל את האפליקציה ולגלות את הבעיה.

    אני אשמח אם תוכל להציג דוגמא קונקרטית לבעיה כזאת בפייתון שלא נפתרת ב unittest בסיסי.

    הפעם היחידה ש type safety הטריד אותי בפייתון היה כשבניתי web framework והקלט הגיע בתור מחרוזת json. במקרה הזה הייתי צריך לבדוק שה json שהגיע תואם את מה שאני מצפה ממנו – כלומר שאני מקבל מספר כשאני מצפה למספר ותאריך כשאני מצפה לתאריך. אבל זה כמובן לא נגמר רק ב type safety, הייתי צריך גם לבדוק שהמחרוזת שקיבלתי היא באורך המתאים וכשאני מקבל email אז הוא באמת מייצג אימייל וכו'. type safety היה רק חלק קטן וממש לא משמעותי במנגנון בדיקת הקלט.

    אני מציע לקרוא את המאמר הבא: http://tartley.com/?p=456 שמדבר על שפות דינאמיות ב NET.

    אגב, בגירסא הבאה של c sharp, הם מוסיפים טיפוס נתונים dynamic שאומר לקומפיילר לא לבדוק type safety על אותו משתנה אלא רק לבדוק duck typing בזמן ריצה.

  7. Shai

    עידו, אני רוצה להצטרף להמלצתו של ארתיום שתימנע מלכתוב שטויות. חוץ מקוד הלא-ממש-++C שכתבת, עשית סלט בין שתי אבחנות לגבי שפות: static/dynamic זה לא אותו דבר כמו strong typed/weak typed. פייתון היא דינמית וגם strong typed — לכל ערך יש סוג שמגדיר את הפעולות שאפשריות עליו, ועל 100+"1" תקבל כאפה. כפי שציינת, C הסטאטית היא לא-ממש-strong-typed, ואילו SQL היא סטאטית ו-weak-typed ממש.

    בגלל שאתה לא מבדיל בין שתי האבחנות, אתה גם לא טורח להבדיל בין weak-type (מה שקורה ב-SQL ו-JavaScript) לבין duck-typing (פייתון ואחרות; לא יודע פרל ו-PHP). בראשון, השפה עושה כמיטב יכולתה "להסתדר", לא חשוב מה נחת עליה, והתוצאות הרבה פעמים בעייתיות. בשני, הגישה היא של דרישת-ממשק ע"י שימוש בו — כלומר, אני מתעד שפרמטר הוא "עצם דמוי-קובץ", ומשתמש בפונקציות ש"קוראות" ממנו; אם יש לו פונקציות כאלה, אז הצלחתי, ואם לא, תעוף שגיאה. גם אם אתה לא עושה unittest אינטנסיבי, יש כאן הרבה פחות פתח לבעיות.

    בגלל חוסר ההבדלה הנ"ל, הטענה שהבאת בשם המתכנתים הדינמיים היא קריקטורה של הטענות האמיתיות. אני אדבר בשם ה-duck-typing — שם הטענה היא לא "לא אכפת לי מה סוג המידע", אלא "לא אכפת לי כל עוד הממשקים הרלוונטיים מסופקים". אנשי ה-weak-typing, ירחם עליהם האל, יצטרכו להגן על עצמם.

  8. ik_5 מאת

    ארתיום, עידו, שי, אתם מפספסים לגמרי את הנקודה שלי.

    זה לא משנה לאף אחד אם מה שכתבתי חוקי כרגע בחוקי התחביר, אלא אם יש בעיה בשפה מסויימת או לא, וגם זה לא הנקודה כאן בפוסט.

    מה שאני מעלה כאן בפוסט זה משהו שונה לגמרי מכל הטענות שלכם.
    כן, duck type אומר שלא משנה איך אני מקבל את המידע העיקר שהוא שמור לי ואכישהו הוא מכיל טיפוס כלשהו. לא ממש מעניינת הנקודה הזו.
    weak type אומרת שערך תמיד יכול להיות יותר מטיפוס אחד, לא מעניין.

    הנקודה שלי כאן, שאם אתם לא יודעים איך המידע יתנהג בתוך מה ששומר אותו, אז יהיו לכם בעיות. כלומר הטיפוס הלא ידוע בשפה דינמית שמתקבל ומתנהג בצורה מסויימת, אז אוקי אתם לא יודעים מה הוא, אבל חשוב לכם איך הוא מתנהג ! כי אם הוא לא יעביר לכם את המידע כמו שאתם מצפים, אז אתם בבעיה, וזו הנקודה שלי בכל הפוסט הזה. אתם נתפסים לכל השוליים ולא למה שאני מנסה להגיד כאן.

    מה אתם לא מסכימים שאם אתם מקבלים מידע (לא משנה הטיפוס) ואתם לא מתנהגים איתו כמו שצריך אז משהו לא תקין והוא גורר הרבה בעיות ?

    בגלל זה אני אומר ש strong type עדיף, כי אז יש לי יכולות להתמודד עם המידע ברמות שונות בהתאם לצורך שלי. מצד אחד אני לא צריך מליון בדיקות תנאי בשביל לדעת איך להתנהג עם המידע, ומצד שני בשביל להמיר אותו לצורה ידידותית עבור התוכן הרבה יותר קל לי, כי אני יכול להתאים את עצמי יותר טוב.

    עידו, קיבלת תוכן json, ובאמצע שלו יש script injection האם אתה יכול לדעת בוודאות שזה מתרחש ? זה תלוי מאוד בצורה שאתה ממיר את JSON ויש לך בפיתון הרבה מאוד צורות להמיר את המידע להרבה מאוד סוגים, מספיק שאחד מהם עושה eval על הקוד, שהוא יריץ לך קוד.

    אם היה לך יכולת לדעת שיש במבנה משהו לא תקין לפני ההמרה, או לדעת איך להתנהג עם המרה גם כאשר יש לך פעולה כזו, היא מאוד חשובה. וזו הנקודה שלי, ולכן אין כאן סלט, אלא יש כאן חוסר הבנה של הנקודה שלי, אתם כל אחד ממתבצרים בשפה הספציפית שלו במקום לראות את התמונה שציירתי כאן.

  9. שי

    עידו,

    א. (למרות שהשאלה הופנתה לארתיום) לפונקציה עם ה-int. בשביל לחשוף את הבעיות עם העמסה אתה צריך לבנות דוגמה קצת מורכבת יותר, עם ירושה או templates.

    ב. אתה מחמיץ לגמרי את הפואנטה של עידו: בעיות type הן לא כל, ואפילו לא רב הבעיות שאתה יכול להיתקל בהן, ומה שאתה צריך לעשות ממילא כדי לפתור את הבעיות האחרות יטפל גם בבעיות type.

    ג. אתה מחמיץ למדי נקודה שלי, וממשיך להשתמש בביטוי strong type כשאתה מתכוון ל-static type.

    ד. בסופו של דבר, אנחנו לא מסכימים על "הוא גורר הרבה בעיות". מה שאנחנו רואים בפועל זה "הוא גורר קצת בעיות והן נפתרות בקלות".

    ה. איזה מערכת סוגים — סטאטית, דינמית, חזקה, חלשה, עם קוצים — פותרת בעיות של script injection, ואיך? למה זה קשור?

  10. שי

    … סליחה, אבל בעצם התגובה שלך הבהירה לי שהתגובה הקודמת שלי לא ברורה מספיק. אז אני אגיד את זה בצורה בוטה יותר:

    כתבת בפוסט: "אחד המיתוסים הענקיים בעולם התכנות הדינמי (כדוגמת פיתון, רובי, פרל ו PHP) הוא שלא משנה לנו מה הטיפוס של המידע, היות ואותו container של המידע (כלומר משתנה) יכול פעם אחת להכיל מערך, פעם שנייה מחרוזת, פעם שלישית מספר, פעם רביעית מצביע/קישור למשהו ופעם חמישית משהו אחר"

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

    כלומר, זה לא באיזו נקודת תחביר של ++C: בנקודה המרכזית של הפוסט שלך אתה מקשקש על דברים שאתה לא מבין.

  11. ארתיום

    deleteFile(deleteFile(1);
    למה הוא יכנס ?1);‎
    למה הוא יכנס ?

    בפירוש הפונקציה עם int כי 1 הוא int. ואין לו פירוש אחר. למעשה לכל קבוע ולכל ביטוי יש טיפוס. לפעמים יש casting אוטומטי בין טיפוסים כמו שאפשר לכתוב bool t=1;‎ או int t=true;‎ כשאתה משתמש ב־overloading ויש מספר דרכים לבצע casting או במילים אחרות casting לא חד משמעי, הקומפיילר לא יקמפל את הקוד שלך.

  12. ik_5 מאת

    שי, אתה עדיין מפספס את הנקודה שלי.
    יש לך תוכן, אתה צריך לקבל אותו בצורה כלשהי ?
    אוקי קיבלת עם JSON פעם אחת את הדבר הבא:

    {
    device : 'motherboard'
    }

    פעם שנייה
    {
    device: {'motherboard', 'cpu', 'fan'}
    }

    אתה צריך קוד שיתייחס לשני המצבים האלו ? כן. זו הנקודה שלי. שעם כל הכבוד לכל מה שאתם אומרים, עדיין אין קשר למה שאני אומר כאן.
    אתה צריך קוד שיטפל בשני המקרים, ככה שלהגיד שה container לא משנה הוא לא נכון בסופו של דבר גם אם הוא מיוצג באותה צורה בשפה אתה משתמש, אתה חייב לדעת איך התוכן שהתקבל שמור בשביל להשתמש בו.

    לא יעזור כל דבר אחר שתגידו, זו הנקודה של הפוסט כאן. אתם סיבכתם את הנושא והעלתם הרבה נתונים, אבל עדיין לא התייחסתם למה שכתבתי, שזה שהתוכן הוא מאוד חשוב. כן יש עוד מליון דברים אחרים שצריך לטפל בהם ואופלי הם חשובים אפילו יותר, אבל בסופו של דבר בלי שליטה בתוכן שקיבלת כל דבר אחר חשוב.

  13. שי

    לא, עידו, זה אתה שמפספס את הנקודה, שחוץ ממך (כשאתה מדבר בשם משתמשי שפות דינמיות) אף אחד לא טוען אחרת.

    חוץ מזה, מה שצפריר אמר.

  14. ik_5 מאת

    צפריר, זה בדיוק מה שאני אומר (שאתם מדברים על משהו שונה לגמרי).
    ניקח דוגמא פשוטה יותר.
    אני מצפה לקבל מהשתמש ערך מספרי בין 0 ל10.
    המשתמש מזין לי ערך למשל של "10L" (בלי גרשיים).
    לפי מה שאתם אומרים, זה לא משנה בשפה דינמית שקיבלתי את הערך הזה כי ה container מסוגל להכיל את המידע.
    אני אומר, שזה לא משנה שהcontainer מסוגל להכיל את המידע, בשביל להשתמש במידע הזה, אני עדיין צריך לבדוק אותו, כלומר אם אני אנסה בפיתון לעשות את הפעולה הבאה:

    a = "10L"
    int(a)

    אני אקבל חריגה, למרות שה container מכיל את הערך. כלומר אני עדיין צריך לבדוק את התוכן בשביל לדעת איך לפעול, ובדיוק על זה אני מדבר בפוסט שלי. שעם כל העבוד לסוגי המידע וליכולות המופלאות לשמור כל סוג מידע בעולם, עדיין בשביל להשתמש בו כמו שצריך, צריך לבדוק את התוכן שלו.

    ולכן אין בזה שום יתרון על פני strong type (או strict type אם אתם ממש רוצים).

    אני מקווה שעכשיו אתם מבינים על מה אני מדבר ועד כמה מה שאתם אורמים לא קשור לזה.

  15. שי

    צפריר טען שאתה — בתגובה הלפני-אחרונה שלך, ובפוסט — מדבר על שני דברים שונים לגמרי. אני חושב שהוא צודק. ובאמת, כל מי שענה לך (לעניין!) לפוסט, קיבל תגובה שזה נושא אחר — כי אתה החלטת משום מה להחליף נושא בין הפוסט והתגובות.

    ולעניין הטענה שאתה מביע בתגובה האחרונה: אף אחד, בשום מקום ראוי להתייחסות, לא טען שהשימוש בשפות דינאמיות פוטר אותך מבדיקת קלט. אתה (אני נאלץ לחזור כתקליט, בתקווה שסוף סוף זה יחדור) מתקיף דחליל.

  16. ik_5 מאת

    איך בדיוק אני מדבר על משהו שונה ?!

    נתתי דוגמא של תחביר JSON שפעם אחת מכיל מידע עם ערך אחד ופעם שניה מכיל מידע עם כמה ערכים, כל אחד מהם דורש ממך התייחסות שונה לאותו מקרה.

    שי, קרא שוב את הפוסט שלי, תראה שאני כל הזמן מדבר על הגישה למידע החל מהפסקה הראשונה ועד לפסקה האחרונה שאני משווה את הערכים שאני שולח לפונקציות.

    אני אומר שאין שום יתרון לשפה דינמית מול שפה מהודרת כשזה נוגע להתעסקות במידע, כי מידע בראש ובראשונה אתה צריך לבדוק ערכים ואז לדעת איך להתמודד איתם.
    אז נכון שיש לך container עם קסם שיודע לשמור כל ערך, אבל אם לא נבחר container נכון למה שאתה צריך או שהוא לא מסוגל לנפות לך את השגיאות של המשתמש הוא לא עוזר לך ולוקח ממך עבודה רבה. ובגלל זה ה strong type (כן אני עדיין קורא לזה ככה) נותן לך כאן יתרון, כי אתה יודע בוודאות מה הסוג שתקבל, ותדע להתמודד איתו טוב יותר.

    האם הסיכום הזה מצליח להסביר לך על מה אני מדבר ?

  17. Shai

    א. שני דברים, שונים למדי זה מזה, שאתה מדבר עליהם, הם משתנים בתוכנית וקלט חיצוני. קלט חיצוני כולם חייבים לבדוק. לגבי משתנים — אפילו פרמטרים לפונקציה — הנושא הרבה יותר פתוח. כאמור, מה שאתה יכול לבדוק סטאטית, כמעט לגמרי נבדק בשפות דינאמיות ע"י הפעלת מתודות. ה-trade-off שלוקחת הגישה הדינאמית הוא לטובת נוחות, גמישות, והסרת ביורוקרטיה (כגון הגדרת מחלקה יורשת למחלקה קיימת רק בשביל להצהיר שהקיימת אכן מממשת ממשק).

    ב. שני סוגי טיעון שאתה מערבב ביחד הם "לשפה סטאטית יש יתרון" ו"לשפה דינאמית אין יתרון". לא הבהרת מה היתרון של שפות סטאטיות, וצללת להדגמת חוסר-היתרון של שפות דינאמיות בבדיקת קלט, כאילו הוא מוכיח איזשהו יתרון של שפות סטאטיות.

    ג. נו באמת. תלך ללמוד: http://en.wikipedia.org/wiki/Strong_typing במקום להמשיך להתווכח באויר. פייתון היא strongly typed.

    ד. ההבדל האמיתי בהקשר של שגיאות הוא גילוי שגיאות בקומפילציה לעומת זמן ריצה. יש לזה ערך. אבל, כמו שציין עידו, הרבה פחות ממה שאתה נותן לזה.

כתיבת תגובה

הזינו את פרטיכם בטופס, או לחצו על אחד מהאייקונים כדי להשתמש בחשבון קיים:

הלוגו של WordPress.com

אתה מגיב באמצעות חשבון WordPress.com שלך. לצאת מהמערכת / לשנות )

תמונת Twitter

אתה מגיב באמצעות חשבון Twitter שלך. לצאת מהמערכת / לשנות )

תמונת Facebook

אתה מגיב באמצעות חשבון Facebook שלך. לצאת מהמערכת / לשנות )

תמונת גוגל פלוס

אתה מגיב באמצעות חשבון Google+ שלך. לצאת מהמערכת / לשנות )

מתחבר ל-%s