ארכיון חודשי: יוני 2010

דלפות זיכרון בשפות דינמיות

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

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

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

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

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

גם אנדרואיד בידנו

חברה אחת שיחררה אתמול Patch שכבר נכנס לsvn אשר מאפשר לעבוד בצורה טבעית עם FPC במערכות מבוססות Android באמצעות JNI.

אותו Patch נוסה על מספר של מכשירים מבוססי Android בניהם Milestone ו Droid של מוטורולה, HTC Desire, Nexus One, Samsung Galaxy S ועוד.

ה Patch שנכתב הוא עבור Android Dalvik VM אשר מפעיל עוד כמה דגלי ARM אשר לא נתמכו עד ל Patch ב FPC.

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

כתוב פעם אחת – קמפל לכל טלפון שאתה צריך 🙂

איך לגרום לשפה להיות חלק מהקישור בRails (ולהישאר בחיים)

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

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

/he/home
/en/home

העניין הוא ש /lang/ משתנה בהתאם לשפה, אבל בפועל הלוגיקה אצלי בתוכנה לא משתנה. אז איך לגרום שהניתוב יהיה כזה ?

בקובץ routes.rb נוסיף את השורה בצורה הבאה:

map.home :home, :action => 'home', :controller => 'index', :path_prefix => '/:locale'

והנה ההסבר:

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

עכשיו ב controller הראשי (application_controller.rb) נכתוב את הקוד הבא:

before_filter :set_locale

def set_locale
  I18n.locale = (I18n.available_locales.include? params[:locale]) ? params[:locale] : I18n.default_locale
end

וזו כל הלוגיקה שיש לנו.

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

אני יצרתי גם helper נחמד שמקצר לי את האפשרות לתרגום:

def tp(text)
  I18n.t text.to_sym, :scope => [:pages, @page.to_sym] rescue text.to_s
end

ה helper כאמור נגיש ב view. וב view עצמו זה יראה ככה:

<%= link_to tp(:home), home_path(@lang) %>

וזה הכל 🙂

טעינה עצלה

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

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

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

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

table.where('a > 2');
table.like('c', '''%bla bla''');
table.join('table2', 't2', 't2.id', 'ta.id', '!=');

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

אז מתי השאילתא הזו תרוץ ? ובכן נגיד למשל כאשר אשתמש בפונקציה בשם:

table.result('a')

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

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

כללים לביצוע binding

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

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

typedef int card32

אומר שהגדרנו כרגע טיפוס בשם card32 והוא בעצם מסוג int.

אפשר לראות את זה גם בהגדרות משתנים:

int age

אומר שהגדרנו משתנה בשם age שהוא מסוג int. ההפוך הזה הוא הפוך מבחינה לוגית של חשיבה אנושית בכל שפה אנושית שאני מכיר. כי בד"כ אנחנו אומרים "גיל כמספר שלם" או "age as an integer" ואנחנו לא אומרים "מספר שלם גיל" או "integer age", כך שצריך להבין את הלוגיקה של C ועד כמה התפיסה בה שונה מבחינת תפיסת החשיבה של שפות בני אדם א איך אנחנו בכלל קוראים בכלל את הקוד. להמשיך לקרוא

אשליות …

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

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

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

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

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

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

ועל הגישה הזו נכתב פעם שיר ישראלי : "אשליות"

להיות יזם …

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

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

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

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

אח"כ אולי תצליחו להבין טוב יותר את השיר של מטאליקה: The Unforgiven

µ.dev

µ.dev היא סביבת עבודה משולבת (IDE) עבור שפת פיתון, הבנויה כרגע לעבוד רק בווינדוז אך יש עבודה גם לגרום לו לעבוד בלינוקס (כרגע דביאן עד כמה שאני מבין).

הסביבה משוחררת בקוד פתוח (GPLv3) וכוללת את הפיטצ'רים הבאים:

  • Syntax Highlight
  • דיבוג באמצעות pdb מהסביבה עצמה
  • ניהול פרוייקטים
  • שינוי theme עבודה

ועוד …

אפשר למצוא את תמונות המסך של הסביבה.

או פשוט תורידו ותפתחו 🙂

מה שאפשר לעשות עם stored procedures

MindTheBird יצרו תחרות עבור Stored Procedures מעניינים. ופרסמו את שמות הזוכים בתחרות עם ה Stored Procedure שהם יצרו.

למי שאינו יודע, stored procedure היא שפה בתוך מסד נתונים המאפשרת ליצור פונקציות בתוך מסד הנתונים אשר רצות בצורה מהירה, וחוזרות עם תשובה של שאילתות, בד"כ ללא הידור השאילתות בעת הבקשה (בניגוד לבקשת SQL "רגילה") ולכן נחשבות למהירות ויעילות יותר מאשר קוד זהה ההרץ מחוץ למסד הנתונים.

הזוכים יצרו את ה SP הבאים:

ניתן למצוא את ה SP הזוכים בפוסט הבא של חדשות firebird.

מה זו סכמה במסדי נתונים ?

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

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

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

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

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

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