רובי ב-10 דקות: מדריך למתחילים

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

קרדיט תמונה: Shutterstock

קרדיט תמונה: Shutterstock

רובי היא שפת תכנות שנוצרה ע”י בחור יפני (עובדה שתתחבר לנו בהמשך) בשם יוקיהירו מאטצ’מוטו (שם חיבה: מאצ’). מאצ’ לא מצא שפת תכנות “לטעמו” – ולכן יצר אחת.

רובי דומה בהיבטים רבים לשפת Python, מכיוון שהיא:

  • שפת high level, כמעט scripting language
  • שפת general purpose
  • שפת Dynamic typing
  • התחביר שלה דומה

החוויה הראשונה בהתקלות עם רובי, שלי לפחות, היא שהיא מעט מוזרה – דומה ל Perl (“יש אצלנו יותר מדרך אחת לעשות כל דבר“). בתחביר יש הרבה קיצורים, רחוקים מהשפה האנגלית ולא כ”כ אינטואטיביים למי שלא רגיל אליהם , למשל:

%w(abc def ghi)

(ללא מרכאות) הוא קיצור מקובל ל

[“abc”, “def”, “ghi”]

דוגמה נוספת היא הבחירה במונחים:

  • string.downcase במקום string.lowercase
  • string.gsub במקום string.replace (יש מתודה בשם replace, אך היא עושה משהו אחר)
  • to_s במקום toString, כאשר יש גם מתודה בשם to_str – אבל לא נכון להשתמש בה, אם המחלקה היא לא סוג של string בפני עצמו.

דבר אחרון שעשוי להיות דיי מוזר הוא השימוש הרב בסימני פיסוק: סימני “?” או “!” משמשים כקונבנציה על שמות של מתודות/פונקציות. יש שימוש ב <=, גם ב @, או $ בשמות של משתנים, ויש גם שימוש ב :, |, &, וסימנים אחרים.

אני רואה מדריכים של רובי שמצהירים בגאווה: “הצלחנו ליצור קוד שהוא ממש כמו פסקה בשפה האנגלית!”.
בפועל, יש בדוגמאות הללו כ”כ הרבה סימני פיסוק בקוד, שזה לא נראה לי כמו קוד ספרותי – אלא הרבה יותר כמו חיבור של גיק מתבגר ולא-מתקשר.

“@הצלחנו: ליצור (!), קוד :שהוא |ממש| כמו => פסקה? בשפה! האנגלית!” – כן, בטח!

רובי, בניגוד ל Python, היא שפת OO “אמיתית” עם classes כפי שאנו מכירים אותם בג’אווה / #C. השפה הושפעה גם מ-SmallTalk, משפת LISP ומ Perl. כן,… Perl השפה שעליה נאמר שהיא שפה לכתיבה-בלבד.

לזכותה של רובי יאמר שהיא אחת השפות שצמחו במהירות הגדולות ביותר, ויש לה קהילה גדולה, איכותית, ופעילה. חוזק גדול מאוד של הקהילה הוא תשתית ה FullStack Web Development בשם Ruby on Rails (בקיצור: RoR), אבל יש לה גם כח ונוכחות מעבר לכך. ניתן לציין את RSpec, Chef, Puppet, Vagrant, Cucumber – שהשפעתם על תעשיית התוכנה היא רבה.

מתכנת ששולט ב Ruby יכול לכתוב בה בקצב מהיר מאוד, יותר מאשר ב Python – כך טוענים. המטרה של פוסט זה היא לאפשר, בזמן קצר, למתכנת של #C או ג’אווה גם להיות מסוגל לקרוא קוד זה.

התקנה

התקנת רובי פשוטה הרבה יותר על לינוקס.
משתמשי חלונות: כדאי להשתמש בלינק הזה, ולהשתמש בגרסת 32 bit, כי גרסת ה 64 היא בעייתית.
כמו כן כדאי להשתמש ברובי 2. רובי לא מזמן עשתה את המעבר מ 1.9 לגרסה 2. למרות החלפת הספרה לא היה פה שינוי דרמטי, אלא רק שינוי הדרגתי, קטן כנראה מהמעבר בין גרסה 1.8 לגרסה 1.9.

אם אתם רוצים לפתח (דאא!) אז תזדקקו דיי מהר גם ל Devkit. קובץ ההתקנה הוא בסך הכל ZIP שנפתח לאיזו תיקיה. בתיקיה זו (אני עובד בחלונות) הקלידו ב command line:

> ruby dk.rb init
> ruby dk.rb install

ה IDE החביב עלי הוא (כמובן) RubyMine.

התקנת רובי תוסיף לכם אפליקציה בשם irb (שהוא ה Interactive Ruby Shell, להפעלה מה commandline / shell) שבו תוכלו לבדוק במחזור feedback של שניות פקודות שלא ברור לכם בדיוק כיצד הן מתנהגות. אפשר להתקין את wirble שמאפשר autocomplete ו syntax highlighting ב irb.

כחלק מהתקנת רובי מגיעה גם אפליקציה בשם gem, שהוא ה Package manager של רובי (ממש כמו אלו של לינוקס, ממנה הושפעו הכלים של רובי לא-מעט). בעזרת gem מתקינים חבילות רובי. החבילה הראשונה שאני ממליץ עליה היא rspec ספריית בדיקות היחידה / BDD (שבדמותה נוצרה Jasmine של ג’אווהסקריפט – למי שמכיר). פשוט הקלידו בשורת הפקודה:

> gem install rspec

 

בואו נצא ידי חובה וניצור hello world קטן:

ברובי יש 2 מתודות להדפסה:
print שהיא המקבילה ל System.out.print בג’אווה.
ו puts (קיצור של put string. כמה טוב שלא בחרו לקרוא לה disuninject_string) שהיא המקבילה של System.out.printlnבג’אווה, ובה נשתמש בד”כ.

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

  • ברובי שימוש בסוגריים להפעלת פונקציה הוא אופציונלי, אפשר פשוט לרשום בזה אחר זה את הפרמטרים, עם רווחים.
  • ספציפית: בפקודת puts לא מקובל להשתמש בסוגריים בכלל.
  • מחרוזות ברובי יכולות להיות עם גרש אחד או גרשיים, אם כי escape chars הם ישימים רק במחרוזת עם גרשיים. כלומר ‘n\’ שקולה ל “n\\” – כי היא מקבלת \ כתו רגיל.
  • הסיבה לכך: מחרוזת עם גרש מועתקת לזיכרון כפי שהיא – ללא פענוח, ומחרוזת עם גרשיים – עוברת פענוח.
  • הדרך המקובלת ברובי היא להשתמש כמה שאפשר במחרוזות עם גרש אחד, כך שהשימוש בגרשיים ירמז שיש במחרוזת escape chars (או טריקים אחרים)

טבילת אש ראשונה

  • שמות מחלקות חייבות להתחיל באות גדולה.
  • כאשר אנו משתמשים באות גדולה בתחילת שם משתנה – הוא הופך לקבוע. אפשר לומר שגם מחלקה היא סוג של קבוע, כי הרי המחלקה (לא המופעים שלה) – לא משתנה מרגע שהוגדרה.
  • המחלקה שלנו יורשת מהמחלקה LivingCreature.
  • ה Constructor הוא מתודה (מתודות מוגרות ע”י def, קיצור של define) בשם initialize. אין צורך להגדיר טיפוסים (int, string וכו’) של משתנים ברובי – זו שפה דינמית.
  • משתני מופע (נקראים instance variables, מה שנקרא בג’אווה “members”) מוגדרים ע”י סימן @ בתחילת השם. שימו לב שאת משתני המחלקה מגדירים רק בתוך מתודות, ולא בתוך המחלקה – כפי שמקובל בג’אווה. עצם השימוש במשתנה עם שם שמתחיל ב@ – מגדיר אותו כ member של המחלקה.
  • משתני מחלקה (המקבילים ל static members בג’אווה) מוגדרים ע”י 2 סימני @.
  • שימוש במשתני מחלקה נחשב כפרקטיקה לא מומלצת ברובי, בדומה לג’אווה.
  • שמות מתודות, משתנים וקבצים ברובי נעשים ע”י שימוש ב snake_case (בהקבלה ל camelCase שבשימוש בג’אווה).
  • מקובל מאוד שמתודה או פונקציה ללא פרמטרים – לעולם לא תופיע עם סוגריים.
  • משתמשים ב PascalCase (אות גדולה ראשונה) להגדרות שמות מחלקות ומודולים.
  • עבור קבועים, מקובל מאוד להשתמש ב SCREAMING_SNAKE_CASE (בדומה לג’אווה).
  • אוקיי… הנה קוד קצת מוזר. זהו התחביר (המוזר) ברובי למשפט if מקוצר. משפטי if רגילים דורשים שימוש ב end.
  • התחביר של המשפט הוא: <עשה X> אם <תנאי>, במקרה שלנו: “עשה את הפרש הגילאים” אם “הגיל קטן מה lifespan הממוצע”.
  • אבל ביצוע חישוב וזריקה של התשובה לאוויר – היא “עשייה”?
  • כן. מכיוון שהשורה האחרונה במתודה / פונקציה ברובי – היא ערך ההחזרה (אפשר להשתמש ב return כדי להחזיר ערך מאמצע הפונקציה).
  • אין פונקציות מסוג void ברובי – תמיד פונקציה תחזיר ערך. אם לא הגדרנו אותו / אין ערך בשורה האחרונה – אזי יחזור nil.
  • נעבור להרצה:
  • אנו יוצרים מופע חדש של המחלקה: ה new נמצא בצד ההפוך לזה שאנו רגילים בגא’ווה, והוא מקבל את הארגומנטים עבור ה constructor.
  • הפעלה של מתודות – מקובל מאוד לשרשר ברובי, והרבה פונקציות בספריות הסטנדרטיות של רובי מחזירות reference לעצמן לצורך כך.
  • כפי שכבר ציינו, אין צורך בסוגריים בהפעלת time_to_live, כי היא לא מקבלת ארגומנטים.
  • הערך שנותר לבחור בן 21 לחיות (ע”פ התוכנה) – הוא שישים שנה.

כאשר שואלים את התוכנה על בחור בן 90, היא לא מבצעת כלום (כי התנאי במשפט ה if לא מתקיים) – ולכן חוזר nil.
כשנשלח nil ל puts – הוא מדפיס שורה ריקה.

שונות

רובי מספקת דרך מובנה לבצע formatting בסיסי של מחרוזות. ע”י שימוש ב {}# (בתוך מחרוזת עם גרשיים), רובי תשתול במחרוזת ערכים שזמינים ב scope. אהבתי!

שפות high level כמו רובי מעודדות את המתכנתים להשתמש בחופשיות במחרוזות בכדי לתאר “מצבים חוזרים”. בשפת C היינו משתמשים בצורך זה ב const int, בג’אווה היינו משתמשים ב enum. ל JVM יש גם מנגנון של String Pooling שמאפשר לייצר אותה מחרוזת כמה פעמים – אך לנהל רק עותק אחד בזיכרון. אני מניח שיכולת זו מבוססת על תהליך הקומפילציה של ג’אווה.

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

הערה: symbols הם לא ממש מחרוזות, ולא ניתן להפעיל עליהם מתודות של מחרוזות, אולם נשמר הקשר ש:

:hello.object_id == hello.object_id

בעוד

“hello”.object_id != “hello”.object_id

בדוגמה למעלה a ו b הן מחרוזות, בעוד c ו d הם symbols. בשורת ה puts השתמשתי בכפל עם מחרוזת, שזהו קיצור לפקודת join על מערך. כך אני גורם ל puts להדפיס שורה אחת עם פסיקים – ממש כמו שמופיע בהערה באותה השורה.

עוד דבר קטן שאנו רואים בדוגמה הוא את קונבנציית השמות למתודות של “!”: בעוד המתודה chop מחזירה עותק של המחרוזת a שהוסר ממנה הסימן האחרון (אנו לא עושים כלום עם הערך שחזר בדוגמה), המתודה !chop מסירה מהמחרוזת b את הערך האחרון ומחזירה nil.

לא ניתן להשתמש ב”!” בכל מתודה שרוצים: מי שכתב את המחלקה string יצר שתי מתודות: chop ו !chop.

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

לולאות ברובי דומות מאוד לפייטון או ג’אווהסקריפט: פורמט for … in.
בדומה לג’אווהסקריפט (שם לולאה עוברת גם על פרמטרים של אובייקט האב), יש בלולאת for רגילה – התנהגות שלרוב איננה רצויה: הערך שהוגדר (item במקרה שלנו) – ממשיך לחיות מעבר ל scope של המערך.

לפעמים זה שימושי, פעמים רבות אחרות זה מבלבל – ולכן כדאי לעבוד עם התחביר השני (שדומה מאוד ל each של jQuery). התחביר השני שקול לחלוטין, מלבד כך שהערך שהוגדר (item2 בדוגמה) חי רק ב scope של הלולאה.

השימוש של התחביר השני רחב יותר מאשר סתם לולאות והוא נקרא block, הוא בעצם סוג של inline function שמעובר למתודה (each או select).

הנה דוגמה של שימוש במתודה select של מערך (סוג של filter: ערך ההחזרה הוא רק משתנים עבורם היה ערך חיובי). התחביר ~= הוא קיצור להתאמה של מחרוזת (color) ל regular expression (שאותה כותבים בין קווים נטויים, במקרה שלנו הופעת האות e).

כפי שאתם זוכרים, השורה האחרונה בפונקציה – היא ערך ההחזרה.

עוד מבנה נתונים “טבעי” בשפת רבי הוא ה Hash (המקבילה ל Map או HashTable בג’אווה). התחביר הוא key => value. כשנתקלתי לראשונה בקטע קוד שכזה – לא שיערתי שמדובר בעצם ב Map: החץ נראה “חשוב מדי” מכדי לשמש כסימן הפרדה פשוט.

מאז גרסה 1.9 רובי הגדירה תחביר מקוצר חדש ל Hash שהמפתחות שלו הם symbols (שזה סוג של best practice). הרי הוא לפניכם. דבר קטן שמוצא-חן בעיני הוא שרובי מקבלת פסיק עודף לאחר האיבר האחרון במערך או ב Hash (דוגמה ראשונה) – מבלי להתלונן. חדל סדר תחזוקת פסיקים לאחר copy-paste. זה מאוד הגיוני עבורי: הרי הקומפיילר עובד בשבילנו, ולא להיפך.

כמה השלמות חשובות

self ברובי יכול להזכיר this בג’אווה, אבל ההתנהגות שלו שונה. אם הוגדר בתוך מתודה – הוא יצביע על המתודה, אם בתוך מחלקה ומחוץ למתודה – אזי על המחלקה, ואם מחוץ למחלקה – הוא יצביע על המרחב הגלובלי “main”.

ברובי ניתן לארגן את המחלקות / קבועים / וכו’ בתוך modules (דומה ל packages ב ++C או #C)
כדי לנווט בתוך ה module – אנו משתמשים בסימן ::

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

בלוקים הם “חתיכות של קוד” שאנו שולחים בפרמטר לפונקציה (שימושים נפוצים הם פונקציות כמו each, filter, וכו’)
הנה התחביר של הבלוק (מקור):


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

סיכום

פוסט זה ניסה להביא אתכם מ”חוסר הבנה” להבנה בסיסית של שפת רובי, והתחביר שלה – וכל זאת, בזמן קצר מאוד. שפת רובי היא מורכבת ועשירה, והיכולת “לקרוא כל קוד ברובי” – דורשת כנראה למידה ארוכה בהרבה מפוסט זה (שלא לדבר על היכולת “לכתוב כל קוד ברובי”). לרובי יש ספריות ספציפיות שיש להכיר, טכניקות של metaprogramming – שנמצאות בשימוש לא מובטל, ועוד.

מפרשן (Interpreter) ברירת המחדל של רובי נקרא MRI (קיצור של Matz’s Ruby Interpreter). הוא הסטנדרט, הוא עושה את העבודה – אבל נחשב אטי, אטי יותר מ Python – לדוגמה.

האם זה באמת נכון ומתי? קשה ממש לומר. יש הרבה מבחני ביצועים שמראים דברים שונים. לכל הפחות: זהו נושא בדיון.
עוד מגבלה של MRI היא שאין לו באמת multi-threading (אבל ח JRuby – המפרשן שרץ על ה JVM של ג’אווה יש, והוא מהיר בהרבה), ואין לו parallelism (קרי: שימוש ב GPU, SIMD, וכו’).

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

הפוסט נכתב במקור בבלוג ארכיטקטורת תוכנה

קרדיט תמונה: render of gears and the text ruby on rails / Shutterstock.com

ליאור בר-און

ליאור בר-און הוא Chief Architect בחברת סטארטאפ ישראלית גדולה.

הגב

15 תגובות על "רובי ב-10 דקות: מדריך למתחילים"

avatar
Photo and Image Files
 
 
 
Audio and Video Files
 
 
 
Other File Types
 
 
 

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

סידור לפי:   חדש | ישן | הכי מדורגים
קוקי
Guest

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

נוט מאצ'
Guest

אני לא מכיר רובי מעבר למדריך הזה, אבל אני בקלות מזהה כאן אלמנטים שלקוחים ישירות מ-SmallTalk (למשל initialize, symbols, בלוקים וכו’). אני לא אומר את זה לרעת רובי – כל השפות הנפוצות מעתיקות מאחרות – אבל אם חשבת שכל השפות בגדול אותו דבר, לא ממש טעית…

אגב, אני מניח שזה עניין של הרגל, אבל גם אותי התחביר של רובי (וגם סקלה, עוד שפה אופנתית) קצת מרתיע. ומי האידיוט שהחליט לשלב אותיות גדולות ו-snake case??

דורון מועלם
Guest

רובי זה להיפסטרים. עדיף node.js

שוקי
Guest

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

הקריאות של הקוד גרועה

היכולת להכניס מישהו לקוד קיים לצורך תיקונים או הכנסת שינויים כנראה מאוד יקרה

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

בהיבט מקצועי – נראה כמו פח אשפה שראוי להתרחק ממנו

קוקי
Guest

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

דורון מועלם
Guest

קוקי, נא להירגע.
אין ספק שלמי שמגיע משפות כמו C#, Java וכו’.. רובי היא לא רגילה במובן הזה.
ויש עוד כמה דברים לא ממש רגילים, למשל ב-Rails ה-query שלך מובנה במתודה. לדוגמה אם ארצה לחפש משתמש לפי השם שלו זה יהיה משהו כזה find_by_name וכל מיני דברים בלתי רגילים אחרים

יצחק
Guest

ב”ה

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

או אולי יש כמה כלי קסם שקיימים בשפה שלא סיפרו לנו עליהם (חוץ מהתחביר המיוחד..)

מייקי
Guest

Ruby היא שפת סקריפט דינמית. Java ו C# אינן שפות סקריפט ואינן דינמיות (טוב, #C היא סוג של…)

בכל מקרה, לשפות מסוגים שונים יש שימושים שונים. לכל שפה וסוגה יש יתרונות וחסרונות. לכן יש שפות שמתאימות יותר לפרויקט מסוים מאשר אחרות.
אז המשפט שלך “פשוט קשה לי להבין מה חסר ל C# or Java” מראה על חוסר ידע והבנה.

yit
Guest

ב”ה

עיין בזה
http://www.codeproject.com/Articles/491362/Comparing-Ruby-and-Csharp-Performance

היא עדיין הרבה מאחור..

דבר שני כוונתי היתה ב c# וג’אווה, לשפות הגיוניות מבחינת התחביר, וכל הדומים להם.

תבין את הנקודה.

אניני
Guest

כתבה יפה מאוד,
תודה.

גל
Guest
ממליץ בחום ללמוד את השפה Autoit במקרה נתקלתי בשפה הזאת לפני כ 4 שנים ומאז לא עזבתי אותה כי היא נורא עוצמתית. אני מרגיש שהיה לי מזל גדול שנתקלתי בשפה הזאת כי בזכותה יכולתי לפתח מוצר שאם הייתי מפתח אותו בשפת C# זה היה לוקח פי 5 יותר זמן והיה צורך ב 3 או 4 מתכנתים. זאת שפה עם קהילה מאוד איכותית שעוזרת מאוד. הקהילה מספקת גם המון ספריות(חבילות קוד) מאוד שימושיות. הרבה אנשים תורמים שם חבילות קוד ובגלל שיש שם חבילות קוד או דוגמאות כמעת לכל דבר, זה מקצר משמעותית תהליך פיתוח בקטע של בניית בסיסים לתוכנה… זאת שפה… Read more »
Sali
Guest

סוג חדש מאוד באתר זה הוא. לבדוק את זה
Visit W3Schools.com!

Sali
Guest

Visit W3Schools.com!good try beyotch

Sali
Guest
Visit W3Schools.com!
Guest

Hello mothafacka

wpDiscuz

תגיות לכתבה: