הבלוג של ינון פרק

טיפים קצרים וחדשות למתכנתים

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

18/10/2024

העליתי אתמול גירסה חדשה של מסך הכניסה לאתר עם אפשרות לכניסה דרך גיטהאב או לינקדאין. מוזמנים לנסות את זה כאן (לא כזה מלהיב, אבל עובד): https://www.tocode.co.il/login

אני משתף כמה הערות טכניות לגבי המימוש:

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

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

def self.create_from_provider_data(auth)
  authorization = Authorization.find_by(provider: auth.provider, uid: auth.uid)
  return authorization.user if authorization

  user = User.find_or_create_by(email: auth.info.email) do |user|
    user.name = auth.info.name || auth.info.full_name
    user.password = Devise.friendly_token[0, 20]
  end

  user.authorizations.create(provider: auth.provider, uid: auth.uid)

  return user
end

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

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

  2. החיבור עצמו בריילס ללוגינים חברתיים כמעט לא דורש קוד ומבוצע דרך ג'ם שנקרא omniauth.

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

  4. ובאמת מילה על אתרי הלוגין החברתי - הסיפור זהה בכולם כי כולם משתמשים באותו פרוטוקול: פותחים אפליקציה, מקבלים client_id ו client_secret ומכניסים אותם ליישום שלנו. כן חשוב להגדיר מה כתובת האתר שלנו ביצירת האפליקציה כי הם מוכנים לשים מסך לוגין חברתי רק לאנשים שהגיעו מהאתר שמתאים לאפליקציה שפתחתם. בכל אתר דף ההגדרות בו יוצרים אפליקציה מתחבא במקום אחר, בגיטהאב זה היה ב Developer Settings ובלינקדאין יש פורטל של מפתחים ובו יוצרים אפליקציה. מה שעוד היה מבלבל באתר של לינקדאין זה שצריך לבחור בטאב Products את המוצר Sign In with LinkedIn using OpenID Connect בשביל שהלוגין יעבוד.

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

השתמשו באיזה ספריות שתרצו

17/10/2024

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

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

שתי אפשרויות יותר טובות לדעתי למשימות בית:

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

  2. השתמשו רק בספריות X, Y ו Z - פה יש סוג של ייתרון לאנשים שכבר מכירים מראש את הספריות שבחרנו למשימה, אבל רוב הזמן בפרונט אנד קל לאנשים להשתמש בספריות רלוונטיות גם אם לא עבדו איתן בעבר. כלומר מי שעבד עם react-query יצליח להסתדר מהר עם swr. מי שעבד עם emotion יצליח להסתדר עם styled components וכו. ברור אל תבחרו פה רידאקס או ספריות שקשה ללמוד, אלא אם כן אתם ספציפית מחפשים לגייס אנשים שמכירים ספריות אלה.

יותר מדי גמישות יכולה לעבוד לרעתכם, גם במשימות בית.

היום למדתי: מערכת הקבצים הסודית של הדפדפנים

16/10/2024

נמאס לכם מהמגבלה של 5 מגה של local storage? רוצים לכתוב ולקרוא מהר לקבצים שיישמרו אבל אתם תקועים בתוך דפדפן? מסתבר שיש פיתרון יחסית חדש ולא מסובך שנקרא Origin private file system או בקיצור OPFS. מנגנון זה מספק לנו משהו שעובד בדיוק כמו מערכת קבצים אבל סגור בתוך הדפדפן. כרום אצלי על המחשב נתן לי Quota של 500 ג'יגה אפילו בלי לבקש רשות.

המשך קריאה

ה vimrc שלי לפיתוח ריילס

15/10/2024

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

call plug#begin()

" List your plugins here
Plug 'tpope/vim-sensible'
Plug 'tpope/vim-rails'
Plug 'ctrlpvim/ctrlp.vim'
Plug 'preservim/nerdtree'
Plug 'nanotech/jellybeans.vim'

call plug#end()

let mapleader = ","

syntax on
filetype on
set number

colo jellybeans

set hidden
set shiftwidth=2
set expandtab
set tabstop=2
set wildmenu

set incsearch
set hlsearch
set ruler
set smartindent

nnoremap <silent> <C-l> :noh<cr>

let g:ctrlp_custom_ignore = '\v[\/]\.(git|hg|svn)$|node_modules\/'

nnoremap <Leader>n :NERDTreeToggle<cr>

הסבר בקצרה:

  1. הפלאגין vim-rails הוא קסום ונותן המון קיצורי מקלדת לעבודה עם ריילס. לקח לי שנים להכיר אותו ואני לא מוותר עליו.

  2. פלאגין ctrl-p מחפש בקבצים מהר, ו nerdtree פותח עץ תיקיות. כן יש יותר חדשים מהם אבל שניהם עובדים לי טוב. שימו לב שלקראת סוף הקובץ אני אומר ל ctrl-p ממה להתעלם וממפה את ההפעלה המהירה של Nerdtree.

  3. ג'ליבינס זו ערכת צבעים מוצלחת.

  4. כפתור הלידר הוא פסיק, כי אני רגיל.

  5. חיפוש אינקרמנטלי עם צבעים מגיע מ incsearch ו hlsearch והמיפוי של Ctrl L עוזר לנקות את ההדגשה של החיפוש.

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

https://github.com/junegunn/vim-plug

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

ואם מחשבון היה טועה?

14/10/2024

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

  1. הי AI אני צריך קוד שעושה X

  2. תודה! אבל הקוד שהדפסת לא נראה יעיל במיוחד. יכול להציע 5 רעיונות אחרים?

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

  4. שמע זה כמעט עבד אבל הראה תוצאה לא נכונה. הנה ה Data עליו הרצתי. רואה את הבעיה?

  5. תודה! זה עובד מעולה.

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

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

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

חדש באתר קורס מבוא ל Git

13/10/2024

את קורס Git Hero שבאתר הקלטתי אחרי הרבה הדרכות גיט אצל לקוחות. בכל ההדרכות והייעוצים מצאתי אנשים שהתחילו לעבוד עם גיט בלי ללמוד אותו בצורה מסודרת. הם הצליחו להסתדר רוב הזמן אבל כשדברים הסתבכו הם עשו טעויות, בגלל שלא הבינו איך גיט באמת עובד ומה ה Best Practices שכדאי לאמץ. באותו קורס אני מראה לפרטי פרטים איך גיט עובד, כולל איך נשמר המידע בתיקייה .git שלו - מה שנותן לתלמידים הבנה מעמיקה וביטחון בעבודה עם גיט על פרויקטים גדולים.

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

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

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

https://www.tocode.co.il/bundles/pregit

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

משחקים קצרים וארוכים

12/10/2024

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

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

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

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

ניסוי ריילס: משחק איקס עיגול

10/10/2024

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

עקב אילוצי זמנים אני מחלק את הניסוי ל-2. בפוסט היום אני אראה קוד למשחק איקס עיגול בריילס שעובד בצורה אינטרקטיבית ובלי כתיבת JavaScript כלל. המשחק עובד כשמשחקים בו מאותו דפדפן ממש בסדר. בחלק השני של הניסוי אוסיף לזה גם Web sockets בשביל לבנות משחק איקס עיגול שאפשר לשחק מכמה מחשבים במקביל.

המשך קריאה

פייתון בלי GIL

09/10/2024

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

בשביל להתקין את גירסת הפייתון נטולת ה GIL עם pyenv הפעלתי:

CONFIGURE_OPTS=--disable-gil PYENV_VERSION_SUFFIX='-free-threaded' pyenv install -f -v 3.13.0rc3t

וידאתי שאני מריץ את הגירסה הנכונה עם:

$ python --version
Python 3.13.0rc3

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

import sys
import math
import multiprocessing.dummy as mp

def is_prime(n):
    for i in range(2, int(math.sqrt(n) + 1)):
        if n % i == 0:
            return False
    return True

if __name__ == "__main__":
    print(f"GIL enabled = {sys._is_gil_enabled()}")
    with mp.Pool(4) as p:
        print(sum(p.map(is_prime, range(1_000_000))))

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

ynonp@Ynons-MacBook-Air ~/tmp $ time PYTHON_GIL=0 python gil.py
GIL enabled = False
78500
PYTHON_GIL=0 python gil.py  2.83s user 0.04s system 306% cpu 0.938 total
ynonp@Ynons-MacBook-Air ~/tmp $ time PYTHON_GIL=0 python gil.py
GIL enabled = False
78500
PYTHON_GIL=0 python gil.py  2.85s user 0.04s system 305% cpu 0.944 total
ynonp@Ynons-MacBook-Air ~/tmp $ time PYTHON_GIL=0 python gil.py
GIL enabled = False
78500
PYTHON_GIL=0 python gil.py  2.88s user 0.04s system 317% cpu 0.919 total
ynonp@Ynons-MacBook-Air ~/tmp $ time PYTHON_GIL=1 python gil.py
GIL enabled = True
78500
PYTHON_GIL=1 python gil.py  2.61s user 0.05s system 96% cpu 2.753 total
ynonp@Ynons-MacBook-Air ~/tmp $ time PYTHON_GIL=1 python gil.py
GIL enabled = True
78500
PYTHON_GIL=1 python gil.py  2.62s user 0.05s system 97% cpu 2.741 total
ynonp@Ynons-MacBook-Air ~/tmp $ time PYTHON_GIL=1 python gil.py
GIL enabled = True
78500
PYTHON_GIL=1 python gil.py  2.64s user 0.05s system 93% cpu 2.865 total

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