es
Feedback
ToCode

ToCode

Ir al canal en Telegram

טיפים קצרים למתכנתים מאת ינון פרק

Mostrar más
1 419
Suscriptores
-124 horas
Sin datos7 días
-430 días
Archivo de publicaciones
ToCode
1 419
פרויקט AI חדש בקוד פתוח לתרגול שפות מוזיקה היא דרך מצוינת ללמוד מילים חדשות בשפה זרה ולתרגל את המילים כי כשיש שיר טוב אנחנו שומעים אותו שוב ושוב. לנגלטס הוא הניסיון שלי לעשות סדר בתהליך הזה ולבנות מערכת לימוד שפה מסודרת משירים ביוטיוב. מה שהפרויקט יודע לעשות כבר היום: 1. מדביקים קישור לשיר ביוטיוב. 2. המערכת מפעילה AI כדי להוציא את המילים של השיר, לתרגם את המילים והביטויים וליצור תרגילי אוצר מילים מהתוכן. 3. דרך הממשק אפשר להקשיב לשיר בחלקים וכל פעם לתרגל חלק אחר. אפשר לראות כאן דוגמה לשיר בערבית עם תרגום לאנגלית https://langlets.app/courses/BsvhDWS5voU ואחד בספרדית עם תרגום לאנגלית https://langlets.app/courses/5R0TtX-gVHA אם תרשמו לאתר תוכלו גם להדביק קישורים שלכם ולפעמים זה עובד. מה הלאה הפרויקט ממש בתחילת הדרך ויש עדיין המון דברים חסרים, אלה הדברים המרכזיים שאני רוצה להוסיף: 1. מסך "סטטוס יצירה" שמראה בצורה יפה את שיעור השפה שנוצר אחרי שמדביקים לינק (כרגע זה אסינכרוני ופשוט שולחים מייל כשהשיעור מוכן). 2. אפשרות לעריכה של התכנים שה AI יצר כדי לתקן או לשפר. 3. תרגולי שפה טובים ויצירתיים יותר (זה החלק הכי קשה לדעתי כי צריך להבין איך יהיה הכי כיף ללמוד ולתרגל שירים בשפה זרה). 4. דרך קלה לשתף שיעורים שיצרתי עם חברים. 5. אפליקציה לאייפון ואנדרואיד. הפרויקט כולל המון עבודה עם AI וכבר לימד אותי הרבה על כתיבת פרומפטים, עבודה עם מודלים, מה AI יכול ולא יכול לעשות. כמו שכתבתי בפתיחה אם אתם יודעים לכתוב קוד, חושבים שהרעיון מדליק ורוצים לעזור לקדם אותו כתבו לי הודעה ואשמח להכניס אתכם לעניינים. את קוד הפרויקט המלא תוכלו למצוא בגיטהאב שלו בקישור הזה: https://github.com/ynonp/langlets-rails

ToCode
1 419
אלמנט Activity ב React אז React 19.2 הוסיפו אלמנט חדש שהרבה אנשים אוהבים בשם Activity. האם באמת צריך אותו? בואו נראה מה הוא עושה ואתן לכם להחליט עד סוף הפוסט. אלמנט Activity עושה שני דברים, הראשון הוא הגדרת כלל העיצוב display: none לכל הילדים שלו כדי שהם עדיין יישארו בחיים אבל לא יופיעו על המסך. בממשקי טאבים מנגנון כזה יכול לעבוד טוב יותר ממחיקה מוחלטת של האלמנט כי כשרק משנים את ה display האלמנט עדיין שומר על ה state שלו וכל המידע ב DOM נשמר, אז אם יש לנו טופס באחד הטאבים ועוברים לטאב אחר וחוזרים הטופס עדיין ישמור על הערכים שנכתבו בו. נשים לב שגם לפני ריאקט 19.2 בנינו מנגנונים כאלה ופשוט הגדרנו לבד את כלל העיצוב display: none כשמשתמשים ניווטו בין טאבים. הכח השני של Activity, והוא הדבר החדש שבגללו נכנסה קומפוננטה חדשה לריאקט הוא מחיקה של האפקטים והרצת פונקציות הניקוי של כל האפקטים וה Cleanup Refs. מצד אחד מנגנון זה עוזר אם יש לנו בתוך עץ הקומפוננטות של אחד הטאבים אפקטים שאין בהם צורך ביציאה מהטאב - לדוגמה אולי יש אלמנט שמשתמש במצלמה אז הגיוני לסגור את המצלמה כשעוברים טאב. בדוגמאות בתיעוד הם מדברים על נגן וידאו שכדאי לעצור לפני שיוצאים מהטאב. מצד שני אם האפקט שלכם מקשיב לאירועים מ Web Socket ומעדכן את ה UI אז כיבוי האפקט מפסיק את ההאזנה לאירועים וכך כשנחזור לטאב נצטרך לבצע עדכון יזום. הנה דוגמה קטנה ל Activity בפעולה עם כמה הודעות debug כדי להבין איך זה עובד. אפשר להדביק אותה בכל יישום next 16:
'use client';

import { useState, useRef, useEffect, Activity } from "react";

function refChanged(el: any) {
  console.log(\set ref\);
  return () => {
    console.log(\unset ref\)
  }
}

function ActivityDemo() {
  useEffect(() => {
    console.log(\start effect\)
    return () => {
      console.log(\stop effect\)
    }
  }, [])

  return (
    <p ref={refChanged}>hello world</p>
  )
}

export default function Home() {
  const [visible, setVisible] = useState(true);

  return (
    <div>
      <input type="checkbox" checked={visible} onChange={() => setVisible(v => !v)} />
      <Activity mode={visible ? "visible" : "hidden"}>
        <ActivityDemo />
      </Activity>
    </div>
  );
}
הקומפוננטה ActivityDemo מציגה הודעה אחת כשנוצר האפקט והודעה נוספת כשה ref מתעדכן. כשמכבים את תיבת הבחירה הקומפוננטה הופכת בלתי נראית ואנחנו מקבלים את ההודעות unset ref ו stop effect כתוצאה מכיבוי האפקט וה Ref Cleanup Callback. אז מה דעתכם? זו הקומפוננטה שהיתה חסרה לריאקט? אני חושב שלא. הסתרה של טאבים עשינו גם קודם עם הגדרת display: none ב CSS. מי שרצה לכבות אפקטים ספציפיים ביציאה מהטאב הגדיר את ה"נראות" בתור prop והשתמש בה במערך התלויות של האפקט. כיבוי כל האפקטים כברירת מחדל כנראה רק תבלבל. למידע נוסף ועוד המון דוגמאות עם הקומפוננטה החדשה שווה להעיף מבט בדף התיעוד שלהם: https://react.dev/reference/react/Activity

ToCode
1 419
קומיט בלי פוש (או - מתי ליצור את הענף) הרבה מקומות עובדים עם גיט בשיטת עבודה דומה. בשביל להתחיל לעבוד על פיצ'ר יוצרים ענף, עושים קומיטים לאותו ענף, כשהפיצ'ר מוכן שולחים PR ובסוף אחרי המיזוג מוחקים את הענף. אני מבין למה זו גישה פופולרית: 1. שקיפות - כולם רואים את הענפים והעבודה של כולם. 2. גיבוי - אפשר לעשות push אחרי כל קומיט וכך הנתונים מגובים לשרת. 3. שיתוף פעולה - אני יכול במהלך העבודה לבקש עזרה מחבר או חברה, הם ימשכו את הענף שלי ישימו תיקון וידחפו. יצירת ענף בתחילת העבודה על פיצ'ר עוזרת לשמור על סדר עבודה ומועילה במיוחד כשאנחנו רק מתחילים לעבוד עם גיט. אבל זו רק דרך אחת לעבוד. בחיים מותר לגוון, במיוחד אם אתם קצת יותר מיומנים עם גיט. לדוגמה אם אני לא צריך לשתף את העבודה ורק חוקר רעיון, אני יכול לחכות עם יצירת הענף ועם ה push. אני מקודד על המכונה שלי, עדיין עושה קומיטים רגיל בכל צעד ואחרי שהפיצ'ר עובד אני מפעיל rebase כדי למחוק חלק מהקומיטים ולשנות הודעות של אחרים ורק אז יוצר את הענף ודוחף. בצורה כזאת כל האחרים בצוות רואים היסטוריה יותר ברורה של קומיטים. כל עוד לא דחפתי הרבה יותר קל לשנות או לזרוק קומיטים בלי לדאוג שאולי מישהו כבר משך את הקומיטים האלה. דרך אפילו יותר טובה היא ליצור את הענף אבל לחכות עם הדחיפה שלו ושל הקומיטים. כשדוחפים ענף פעם ראשונה גיט מתלונן ודורש שניצור את הענף בצורה מפורשת בשרת:
fatal: The current branch test has no upstream branch.
To push the current branch and set the remote as upstream, use

    git push --set-upstream origin test

To have this happen automatically for branches without a tracking
upstream, see 'push.autoSetupRemote' in 'git help config'.
אפשר להמשיך לעבוד על ענף מקומי בלי להגדיר את ה upstream ובלי לעשות push ולהיעזר בהודעה הזאת כדי לא לעשות push בטעות. מתי כן לדחוף? אחרי ה rebase כשכל הקומיטים עודכנו עם ההודעות הנכונות.

ToCode
1 419
איך לזוז יותר לאט שלוש רמות של לימוד מחומר כתוב או AI: 1. השלמה אוטומטית - זה כשאני מבקש מה AI לכתוב את הקוד בשבילי ישר בתוך ה IDE ולהסביר מה הוא כתב, או כשאני מתחיל לכתוב ומשתמש בטאב כדי להשלים את המימושים. 2. העתקה - זה כשאני מבקש מה AI לכתוב את הקוד בתוך מסך הצ'ט או כשאני קורא מדריך כתוב בחלון אחד וכותב את אותו הקוד לבד מאפס בחלון ה IDE שלי (לא העתק-הדבק, ממש מקליד). פה כבר לקחתי צעד משמעותי קדימה מבחינת רמת הלימוד. אני לא בטוח למה אבל ההקלדה עצמה דורשת רמת הבנה יותר מעמיקה מ Copy/Paste. 3. שינויים קטנים - מדרגה שלישית זה כשאני משנה דברים קטנים בקוד או בהנחות היסוד שלו. לדוגמה אני מבקש מ AI לכתוב דוגמה לקומפוננטה בריאקט ואז הולך ל IDE ובונה את הקומפוננטה ב next.js או מחליף שפת תכנות וכותב את הקומפוננטה לבד ב Reagent שזה הריאקט ל ClojureScript. או אם אני לומד Machine Learning אני יכול לקרוא מדריך ב pytorch ולכתוב את דוגמת הקוד בעצמי ב C++ ב libtorch או ב torch-rb ברובי. כתיבת הקוד מחדש בסביבה קצת שונה דורשת רמה יותר גבוהה של הבנה ומכריחה אותנו לחזור ל AI ולשאול שאלות הבהרה על חלקים בטקסט, מה שעוד ממשיך ומחזק את ההבנה. כשהמטרה היא ללמוד לעומק איך דברים עובדים יותר לאט זה יתרון.

ToCode
1 419
"version": "d114e02a9a610c261738bf4254648a71b3fce993",
  "encryptHistory": true,
  "clearHistory": false
}
וכן אנחנו כבר מבינים מהדוגמה כאן שבברירת מחדל אינרציה לא מפצל את קבצי ה JavaScript שלנו לפי דפים. הם כן תומכים במנגנון של פיצול קוד אם ממש נרצה אבל פשוט לא מפעילים אותו לכל פרויקט חדש. מה הלאה אינרציה כוללת עוד המון יכולות שלא הספקתי לסקור כאן כמו טיפול בהגשת טפסים, העלאת קבצים, ריענון אוטומטי של מידע (polling), ניהול מיקום הגלילה ועוד. אפשר למצוא המון דוגמאות בתיעוד שלהם כאן: https://inertia-rails.dev/ אבל האמת שמעבר למעטפת של ניתוב והצגת דפים מדובר בסך הכל באפליקציית Client Side React כך שאפשר להשתמש בכל הספריות והיכולות שאנחנו מכירים מעבודה עם ריאקט ו vite. בצד השרת ריילס יתפקד כמו שרת API שבאופן אוטומטי יודע להחזיר קומפוננטה או JSON לפי דרישה. בהשוואה ל React On Rails אינרציה נראה הרבה יותר פשוט ומינימליסטי. הוא לא מתאים לאפליקציות גדולות שצריכות Server Side Rendering או אופטימיזציות לבניה אבל באפליקציות צד לקוח הוא ייתן תוצאה מהירה וטובה.

ToCode
1 419
וזה מסיים את הקומפוננטה הראשונה שלנו. בשביל לראות את העמוד נלך לפי הכללים של ריילס. בקובץ config/routes.rb אני מוצא את השורה:
get 'inertia-example', to: 'inertia_example#index'
ובקונטרולר app/controllers/inertia_example_controller.rb אני מוצא את ההגדרה:
class InertiaExampleController < ApplicationController
  def index
    render inertia: 'InertiaExample', props: {
      name: params.fetch(:name, 'World'),
    }
  end
end
וזו גם התשובה לשאלה שהתחלנו איתה את הקריאה - מאיפה מגיע הפרמטר name. באינרציה, הפרמטרים לקומפוננטת העמוד מגיעים מהקונטרולר שמפעיל render, וכך גם שם העמוד להצגה. הוספת קומפוננטה בואו נעדכן את העמוד נוציא את מונה הלחיצות לקומפוננטה שלו ונשים אותו כמה פעמים על הדף. בעבודה עם קומפוננטות אינרציה עובד בדיוק כמו ריאקט. אני יוצר תיקייה חדשה בשם app/javascript/components בתוכה שם את הקובץ Counter.tsx ובו התוכן:
import { useState } from 'react'

export default function Counter() {
  const [count, setCount] = useState(0)
  return (
   <div className="flex flex-col items-center justify-center h-screen bg-gray-100">
      <h1 className="text-3xl font-bold mb-4">Counter: {count}</h1>
      <div className="space-x-4">
        <button
          onClick={() => setCount(count - 1)}
          className="px-4 py-2 bg-red-500 text-white rounded hover:bg-red-600 transition"
        >
          -
        </button>
        <button
          onClick={() => setCount(count + 1)}
          className="px-4 py-2 bg-green-500 text-white rounded hover:bg-green-600 transition"
        >
          +
        </button>
        <button
          onClick={() => setCount(0)}
          className="px-4 py-2 bg-gray-500 text-white rounded hover:bg-gray-600 transition"
        >
          Reset
        </button>
      </div>
    </div>
  )
}
ואז בקומפוננטה InertiaExample אני מוסיף פקודת import:
import Counter from '@/components/Counter';
ושימוש בקומפוננטה:
<Counter />
<Counter />
<Counter />
דף אינרציה שני וניווט ביניהם לאינרציה יש עוד כח על ובנוסף להיותה ספריית תבניות היא מחליפה גם את React Router ומאפשרת ניווט צד לקוח בין דפים. בואו נראה איך זה עובד. אני מעדכן את config/routes.rb כדי שיכיל את שני הנתיבים:
get 'inertia-example', to: 'inertia_example#index', as: :home
get 'inertia-about', to: 'inertia_example#about', as: :about
לאחר מכן אני מעדכן את inertia_example_controller.rb לתוכן הבא:
* frozen_string_literal: true *

class InertiaExampleController < ApplicationController
  def index
    render inertia: 'InertiaExample', props: {
      name: params.fetch(:name, 'World'),
      about_path:,
    }
  end

  def about
    render inertia: 'About', props: {
      home_path:,
    }
  end
end
אני יוצר עמוד חדש בקובץ app/javascript/pages/About.tsx עם התוכן הבא:
import { Link } from '@inertiajs/react'

export default function About({
  home_path 
}: {
  home_path: string,
}) {
  return (
    <div>
      <Link href={home_path}>Back home</Link>
    </div>
  )
}
ומעדכן את דף הבית בקובץ InertiaExample.tsx ומוסיף גם לו את הלינק:
export default function InertiaExample({ name, about_path }:
                                       { name: string,
                                         about_path: staring }) {

  return (
    <>
      <Head title="Inertia + Vite Ruby + React Example" />

      <div className={cs.root}>
        <Link href={about_path}>About Us</Link>
עכשיו נראה מה קרה פה: 1. הקונטרולר מעביר את הנתיבים לקומפוננטות. הנתיבים מוגדרים בתור פונקציות (בסגנון ריילס) כך שאם השמות עצמם יוחלפו בעתיד לא נצטרך לעדכן מחרוזות באפליקציה. 2. קומפוננטת Link מייצרת ניווט צד לקוח. כשלוחצים על הלינק מדף הבית למעבר לדף אודות הדפדפן מבצע בקשת JSON ומקבל את התוכן הבא בלבד:
{
  "component": "About",
  "props": {
    "errors": {},
    "home_path": "/inertia-example"
  },
  "url": "/inertia-about",

ToCode
1 419
חיבור ריאקט וריילס עם Inertia יש מפתחי ריילס שממש לא אוהבים FrontEnd ויעשו הכל כדי לוותר על כתיבת JavaScript, ויש אחרים שהסיבה שלהם לקום בבוקר היא הפרונט אנד ו Rails אצלם נבחר פשוט כי הוא נותן פיתרון נוח לצד השרת. אם אתם שייכים למחנה השני סיכוי טוב שמאוד תאהבו את ספריית inertia. זו ספריה שמחברת בצורה טובה את קוד הפרונט אנד לאפליקציית Rails. אינרציה היא מתחרה של React On Rails ומתמקדת בניווט בתוך היישום ובהעברת מידע מצד השרת לצד הלקוח. בפוסט זה נראה את עקרונות העבודה המרכזיים של אינרציה. יצירת הפרויקט בשביל ליצור פרויקט Rails עם Inertia אני משתמש בפקודות הבאות:
$ rails new inertia-demo
$ bundle add inertia_rails
$ bin/rails generate inertia:install
הפקודה האחרונה מריצה wizard בו אני צריך לבחור את הפריימוורק בו אני רוצה לעבוד. אני בוחר ריאקט לדוגמה זו אבל המנגנון תומך גם ב vue ו svelte. לאחר סיום ה wizard יש לי בתיקיית app/javascript מספר תיקיות חדשות: assets, entrypoints ו pages. אפשר להוסיף עוד תיקיות ככל שתרצו. נקודת הכניסה לאפליקציה היא הקובץ entrypoints/application.js. דף אינרציה ראשון שלי הדף הראשון באינרציה למעשה נוצר כבר מתוך ה wizard. הוא נקרא InertiaExample ואנחנו מוצאים את הקוד שלו בקובץ app/javascript/pages/InertiaExample.tsx. בואו נקרא אותו יחד:
import { Head } from '@inertiajs/react'
import { useState } from 'react'

import inertiaSvg from '/assets/inertia.svg'
import reactSvg from '/assets/react.svg'
import viteRubySvg from '/assets/vite_ruby.svg'

import cs from './InertiaExample.module.css'

export default function InertiaExample({ name }: { name: string }) {
  const [count, setCount] = useState(0)

  return (
    <>
      <Head title="Inertia + Vite Ruby + React Example" />

      <div className={cs.root}>
        <h1 className={cs.h1}>Hello {name}!</h1>

        <div>
          <a href="https://inertia-rails.dev" target="_blank">
            <img className={cs.logo} src={inertiaSvg} alt="Inertia logo" />
          </a>
          <a href="https://vite-ruby.netlify.app" target="_blank">
            <img
              className={\${cs.logo} ${cs.vite}\}
              src={viteRubySvg}
              alt="Vite Ruby logo"
            />
          </a>
          <a href="https://react.dev" target="_blank">
            <img
              className={\${cs.logo} ${cs.react}\}
              src={reactSvg}
              alt="React logo"
            />
          </a>
        </div>

        <h2 className={cs.h2}>Inertia + Vite Ruby + React</h2>

        <div className="card">
          <button
            className={cs.button}
            onClick={() => setCount((count) => count + 1)}
          >
            count is {count}
          </button>
          <p>
            Edit <code>app/frontend/pages/InertiaExample.jsx</code> and save to
            test HMR
          </p>
        </div>
        <p className={cs.readTheDocs}>
          Click on the Inertia, Vite Ruby, and React logos to learn more
        </p>
      </div>
    </>
  )
}
דבר ראשון שקופץ לעין הוא יצירת הקומפוננטה:
export default function InertiaExample({ name }: { name: string }) {
בשביל ליצור את העמוד יש להעביר משתנה name. תזכרו את זה כי תכף נחזור אליו כדי להבין מאיפה הוא מגיע. השימוש ב useState רגיל לגמרי לריאקט ומלמד אותנו שקומפוננטות ריאקט הן קומפוננטות צד לקוח - אינרציה תומך ב Server Side Rendering אבל לא ב React Server Components. גם לא ראיתי התיחסות בתיעוד לנושא ה Caching אחרי SSR כך שנראה שה Use Case היותר פופולרי הוא אפליקציות צד-לקוח. הקומפוננטה המיוחדת Head מאפשרת למלא תוכן באלמנטים בראש העמוד ולכן השורה:
<Head title="Inertia + Vite Ruby + React Example" />
קובעת את ה title. בשביל שזה יעבוד הם הכניסו לקובץ app/views/layouts/application.html.erb את השורה:
<title inertia><%= content_for(:title) || "Inertia Demo" %></title>
אינרציה תומך ב CSS Modules ולכן מבנה הקלאסים:
import cs from './InertiaExample.module.css'

...
<div className={cs.root}>

ToCode
1 419
כמה דברים שמפחידים אותי ב AI בואו נוריד מהשולחן כמה דברים שעולים שאותי לא מפחידים בכלל - ה AI לא יהפוך את המתכנתים למיותרים, אם כבר להיפך. ככל שיותר קוד נכתב כך יצטרכו יותר מתכנתים לתחזק אותו. ככל שמערכות הופכות יותר מורכבות כך יצטרכו יותר אנשים שיתכננו אותן וימצאו את השגיאות בהן. כבר היום אנחנו יכולים לבנות מוצרים דומים לאלה שבנינו לפני עשר שנים עם הרבה פחות אנשים, והנה לא בחרנו להמשיך לעבוד עם אקספלורר 6 ו Windows 95 וליצור אבטלה המונית. הכל טוב, כשאנחנו כותבים מערכות מתוחכמות יותר ומהר יותר עולם התוכנה משתפר. סיפור נוסף שלא מפחיד אותי בכלל הוא בעיות אבטחה, באגים ומערכות שאנשים כותבים בלי להבין. אנשים תמיד כתבו מערכות בלי להבין, אני גדלתי בעולם שבו יכולת להיכנס לבסיס הנתונים של כל אתר אינטרנט כי כולם היו פתוחים ל SQL Injection. עם הזמן אנחנו בונים תשתיות שמשפרות את המצב וגם אם בתקופה הקרובה יהיו שוב הרבה מערכות לא מאובטחות גם המטוטלת הזאת תשנה כיוון. ממה כן כדאי לחשוש? זאת הרשימה שלי: 1. פייק ניוז ופישינג - היכולת של AI ליצור קמפיינים אמינים של פישינג תלווה אותנו תקופה ארוכה מאוד. רק לא מזמן עלה לכותרות חוקר אבטחה שהצליח לבצע התחזות קולית כדי לעקוף מערכת זיהוי קולי של אחד הבנקים פה. יהיה קשה מאוד לסמוך על וידאו, קול וכמובן חתימה. הכל יהיה ניתן לזיוף. 2. התחזות הולכת להיות בעיה כשאנחנו מראיינים מועמדים לעבודה. זה כבר קורה עם כלים לרמאות בראיונות עבודה והולך להיות קשה להבין את הרמה המקצועית האמיתית של מועמד. 3. מוטיבציה הולכת להיות אתגר עצום. כש AI יכול לפתור בשבילך את שיעורי הבית אתה מפתח הרגלי עבודה גרועים וזה משהו שקשה להתגבר עליו. 4. חלומות יהיו קטנים יותר. כשלכל שאלה יש תשובה אין פליאה, אין תהייה ואין זמן לחלום על אפשרויות חדשות. זה מתחבר לקושי למצוא מוטיבציה שאנחנו כבר רואים בעבודה עם AI. מה מפחיד אתכם בעידן ה AI? ואיך אתם חושבים נצליח להתמודד עם האתגרים? אשמח לשמוע בתגובות פה או בטלגרם.

ToCode
1 419
חלק חשוב מהחיבור בין מערכות מחשב, כלומר מה API, הוא ההזדהות. כשמערכת מחשב מקבלת הודעה היא צריכה לדעת מי שלח לה את ההודעה הזאת - מערכת אחרת? תוקף זדוני? מנהל הספריה שמחובר דרך הדפדפן במחשב שלו? גולש שמחפש ספר? לכל אחד יש הרשאות שונות, יכולות שונות ולכן גם כל אחד עשוי לקבל תשובה שונה. הודעת HTTP כוללת בסך הכל 3 חלקים בהם אפשר לכתוב מידע: שורת המזהה שכוללת את הפועל והנתיב עליהם אנחנו מדברים, בלוק הכותרות ובלוק תוכן ההודעה. נתוני הזדהות נשלחים בבלוק הכותרות. יש שני סוגים של נתוני הזדהות שאנחנו יכולים למצוא בכותרות של בקשות HTTP. סוג אחד נקרא Cookie וזו כותרת שנראית כך:
GET /docs/introduction HTTP/1.1
Host: ai-sdk.dev
accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
accept-language: en-US,en;q=0.9
cache-control: no-cache
cookie: ko_id=7827ad98-2a94-440f-be5b-6dd5cfd84161; _hp2_id.3132448398=%7B%22
user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36
הבקשה בדוגמה מנסה למשוך משאב עם המזהה /docs/introduction ומעבירה לשרת מספר כותרות HTTP. אחת הכותרת נקראת cookie והיא מכילה ערך שקצת קשה לקרוא. זה בסדר אנחנו לא צריכים לקרוא אותו מי שצריך לקרוא אותו זה שרת ה Web. השרת קורא את הערך ומבין ממנו מי הבן אדם שמולו. איך ערך ה cookie מתורגם לזהות הגולש אתם שואלים? פה נכנס לתמונה תהליך ההזדהות. משתמש ממלא טופס עם שם משתמש וסיסמה, השרת בודק שהסיסמה נכונה ורושם בבסיס הנתונים ליד שם המשתמש ערך אקראי שנקרא מזהה Session, את הערך האקראי הזה הוא מחזיר באותה תשובת HTTP שנשלחת אחרי מילוי הטופס. מכאן והלאה הדפדפן יצרף את אותו ערך אקראי לכל בקשה בתור כותרת ה HTTP שנקראת cookie. השרת יקבל את הערך האקראי הזה, יסתכל בבסיס הנתונים עבור איזה משתמש הוא נוצר וכך ידע מי שלח את הבקשה. מערכות רבות לא מציגות טפסים ב HTML ובכלל לא עוברות דרך דפדפן. עבורן נוצר מנגנון נוסף שהוא כותרת בשם Authorization. במערכת כזו נבצע איזשהו תהליך הזדהות באמצעות קריאת HTTP POST עם מזהה מסוים (ממש דומה להגשת טופס), גם כאן השרת יאמת את המשתמש, יגריל ערך אקראי וישמור אותו בבסיס הנתונים וישלח חזרה את אותו ערך למערכת שפנתה אליו. בבקשות הבאות אותה מערכת תצרף כותרת HTTP בשם Authorization ותשים בה את המזהה שהיא קיבלה. בקשה כזו תיראה כך:
POST /book/1234567890/ HTTP/1.1
Host: api.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.dGVzdF91c2VyX2RhdGE.abc123dummySignature
Content-Type: application/json
Content-Length: 109

{
  "name": "The Art of Fiction",
  "author": "Jane Doe",
  "price": 19.99,
  "rating": 4.5,
  "instock": true
}
כשאנחנו ניגשים ל API תמיד נרצה לברר איך אותו API מזהה את המשתמשים - מה הנתיב (או המשאב) בו אפשר לבצע הזדהות ולקבל אסימון גישה ובאיזה כותרת HTTP ובאיזה פורמט עליי להעביר את אסימון הגישה בבקשות הבאות. סיכום מערכות רבות באינטרנט שמחות לדבר עם מערכות אחרות בצורה אוטומטית דרך API. בתור משתמשים של אותן מערכות שווה לנו ללמוד גם את ה APIs, גם כדי להבין איך המערכות בנויות וגם כדי להשתמש בהן בצורה יצירתית. קיימים כלים רבים לתקשורת עם מערכות דרך REST API - אני משתמש הרבה בפקודה בשם curl, יש כלי גרפי בשם postman שהרבה אנשים אוהבים ויש כלים רבים נוספים. לא משנה איזה כלי תבחרו היכרות עם מבנה של בקשות ותשובות HTTP והבנה של הנתיבים ב API יעזרו לכם להבין טוב יותר את המערכות ולהשתמש נכון באותם כלים.

ToCode
1 419
ג'ייסון, שזה קיצור ל JavaScript Object Notation, הוא שפה שהומצאה על ידי דאגלס קרוקפורד בשנת 2,000. בניגוד ל HTML שמתארת מסמכים, ג'ייסון היא שפה לתיאור אוביקטים כלומר מידע מובנה, אבל הייתרון הגדול שלה הוא שקל מאוד למחשבים לקרוא אוביקטי JSON - הרבה יותר קל מאשר לקרוא קבצי HTML. הנה דוגמה לקובץ JSON שמתאים לקובץ ה HTML שהראיתי קודם:
{
    header: "hello world",
    text: "HTML was also invented by Tim Berners Lee along with HTTP and the first web browser"
}
ברור שכל דבר שאפשר לתאר ב HTML אפשר לתאר גם ב JSON, אבל ה JSON הוא יותר תמציתי, מובנה והכי חשוב קל יותר לפיענוח עבור תוכנות מחשב. כל תוכנת מחשב שמקבלת JSON צריכה גם לכלול קוד שיציג את ה JSON, וכל תוכנה תוכל להציג את ה JSON בצורה שונה - דפדפן האינטרנט יהפוך את ה JSON ל HTML ויציג את זה; אפליקציית אייפון תשתמש במידע שב JSON כדי למלא שדות ספציפיים על המסך באפליקציה ואפליקציית אנדרואיד תשתמש בקוד משלה כדי להבין מה JSON מה צריך להופיע על המסך ולהציג אותו. הבנה זאת הביאה לשידרוג במערכות ווב רבות - במקום להחזיר HTML האתרים התחילו להחזיר JSON. מערכות שונות לקחו את ה JSON הזה והציגו אותו כל אחת בצורה אחרת. חיבור אוטומטי בין שתי מערכות נקרא API או בעברית ממשק תכנותי. כשדפדפן אינטרנט פונה לשרת, מקבל אוביקט JSON, הופך אותו ל HTML ומציג על המסך אנחנו אומרים שדף האינטרנט נטען דרך API. כשאפליקציה פונה לשרת, מושכת אוביקט JSON, מפענחת אותו ומשתמשת במידע כדי להציג פרטים על המסך אנחנו אומרים שהאפליקציה מתקשרת עם השרת דרך API. אוסף הבקשות ששרת יודע לטפל בהן ואוסף התשובות שהוא מחזיר הוא הגדרת ה API - הגדרת השפה בה אפשר לדבר עם מערכת זו. מה אפשר לעשות עם REST API רגע, אז מאיפה הגיעה לפה המילה REST? אם API הוא קיצור של ממשק תכנותי ומייצג חיבור בין שתי מערכות המילה REST היא גם ראשי תיבות הפעם של Representational State Transfer. את השם הזה המציא רוי פילדינג בשנת 2000 כדי לייצג שיטת עבודה מסוימת של ממשקים בין מערכות. בחיבור מסוג REST API הנתיב, שזה שם הקובץ בבקשת ה HTTP, מייצג משאב. תשובת השרת מייצגת את התוכן או ה State של אותו משאב. אני חושב שדוגמה קטנה תעזור להבהיר כאן את המושגים - נניח שאנחנו בונים מערכת לניהול ספרים בספריה והמערכת מאפשרת להציג פרטים על ספרים לפי מזהי הספר. ספרים מזוהים על ידי מזהה שנקרא ISBN ולכן ניתן להשתמש ב ISBN כדי לייצג "ספר". נתיב לדוגמה במערכת הספרים שלנו יכול להיות:
/book/0764363778
בקשת רשת בשפת HTTP למשאב זה יכולה להיות:
GET /book/0764363778
והתשובה שהשרת יחזיר עשויה להיות:
{
  "name": "JavaScript: The Good Parts",
  "author": "Douglas Crockford",
  "rating": 4.4,
  "price": "16$"
  "instock": 10
}
מערכת מחשב שתרצה להשתמש ב API כדי לקבל מידע על הספר תשלח הודעת HTTP מסוג GET עם מזהה הספר, תקבל את הפרטים של הספר ותציג את הפרטים בצורה שמתאימה לה. ומה קורה אם במערכת יש טופס שמאפשר הוספת ספרים למערכת? גם את זה אפשר לפתור עם בקשת HTTP, הפעם בקשת PUT. המערכת תנהל את הטופס בצורה שמתאימה לה וכשהמשתמש יאשר להוסיף ספר תישלח בקשת PUT שנראית כך:
PUT /book/1234567890

{
  "name": "The Art of Fiction",
  "author": "Jane Doe",
  "price": 19.99,
  "rating": 4.5,
  "instock": true
}
בממשק מסוג REST בדרך כלל כל משאב יתחיל בשם המשאב (בדוגמה שראינו זה היה book) ולפעמים אחריו יופיע מזהה ספציפי של אותו משאב. הפועל יקבע מה יש לעשות עם אותו משאב בדרך כלל לפי התבנית הבאה: 1. פעולת GET על המשאב, בלי לציין מזהה משאב, למשל GET /books מחזיר אינדקס של הפריטים כלומר את כל הספרים. 2. פעולת GET על המשאב עם ציון מזהה פריט יחזיר מידע על אותו פריט, למשל GET /books/123 יחזיר פרטים על ספר שהמזהה שלו הוא 123. 3. פעולת POST על המשאב, בלי לציין מזהה, תיצור פריט חדש מאותו משאב. למשל POST /books תיצור ספר חדש. 4. פעולת PUT על המשאב עם ציון מזהה תעדכן את הפרטים של אותו משאב לדוגמה פעולת PUT /books/123 תעדכן את הפרטים של ספר 123. 5. פעולת DELETE על המשאב עם ציון מזהה מוחקת את הפריט, לדוגמה DELETE /books/123 תמחק את ספר מספר 123. עוגיות והזדהות

ToCode
1 419
מדריך: מה זה בעצם API הפעם אנחנו עם מדריך בסיסי שאני מקווה שיעזור לאנשי בדיקות ומנהלי מוצר כמו גם למפתחים להבין את ההגיון והמטרה של אחד המושגים החשובים בפיתוח מערכות ווב היום. איך עובדים דפי אינטרנט איפה מתחילים לדבר על APIs? האמת שלסיפור הזה יש הרבה התחלות אפשריות אבל בואו נבחר להתחיל עם דפי אינטרנט. נכון ממשקי פיתוח בין מערכות היו קיימים לפני האינטרנט אבל האופן בו דברים עובדים היום מאוד מושפע מטכנולוגיית האינטרנט. את האינטרנט, או לפחות את הטכנולוגיות שמפעילות אותו, המציא טים ברנרס לי בשנת 1991 והטכנולוגיה הראשונה שהוא המציא נקראת HTTP (ראשי תיבות של Hyptertext Transfer Protocol). זהו פרוטוקול, כלומר שפה, שנועדה להגדיר איך מחשבים מעבירים ביניהם דפים ברשת האינטרנט. הפרוטוקול מגדיר בגדול שכל מחשב יכול להחזיק "דפים" ולכל דף יש מזהה. המזהה נראה כמו שם קובץ על מערכת יוניקס לדוגמה /wiki/HTTP, /en/api/client-sdks או /arunsupe/semantic-grep. פרוטוקול HTTP מגדיר שאם מישהו רוצה לבקש דף ממחשב מרוחק הוא שולח הודעה שמורכבת מהמילה GET ואחריה שם הדף למשל:
GET /en/api/client-sdks/
טים ברנרס לי גם המציא דפדפן אינטרנט שאפשר לו לקרוא את הדפים האלה (שהיו כתובים בפורמט HTML) וקצת אחריו אנשים אחרים המציאו דפדפני אינטרנט נוספים והרחיבו את הפורמט של הדפים. ב 1996 ככל שיותר אנשים כתבו דפי אינטרנט עלה הצורך בביצוע פעולות דרך דפי האינטרנט והומצא אלמנט הטופס. בשביל להגיש טפסים טים ברנרס לי עדכן את פרוטוקול HTTP והוסיף פקודה בשם POST. בשביל להגיש טופס עדיין היה צריך לציין את הנתיב להגשה ובדרך כלל צורף לבקשה מידע מהטופס. כך נראתה בקשת POST שנוצרה מטופס:
POST /cgi-bin/subscribe.cgi HTTP/1.0
Host: www.example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 27

name=Alice+Smith&email=alice%40example.com
אנחנו שמים לב שמתחת לפקודת POST מופיע עוד בלוק של מפתחות וערכים, בלוק זה נקרא הכותרות של הבקשה ואפשר להעביר אותן גם בבקשות GET. אחרי סיום הכותרות יש שורה ריקה ואחריה שורת הערכים של הטופס וטקסט זה נקרא "גוף הבקשה". לאורך השנים נוספו לפרוטוקול HTTP פעלים נוספים והיום הפרוטוקול מונה את הפעלים GET, HEAD, OPTIONS, TRACE, POST, PUT, PATCH, DELETE. קוד בצד השרת, כלומר במחשב שמקבל את הבקשה, אחראי על טיפול בבקשה. הקוד מקבל את הפועל, את הנתיב, את הכותרות ואת גוף הבקשה וצריך לבצע פעולה ולהחזיר תשובה לדפדפן. לפעמים התשובה תהיה דף אינטרנט, לפעמים היא תהיה תמונה ולפעמים הפניה לעמוד אחר. נסו את זה - בפעם הבאה שאתם גולשים ברשת פתחו בדפדפן את חלון כלי הפיתוח ועברו לטאב Network. שם תוכלו לראות את כל בקשות ה HTTP שהדפדפן שלכם שולח לשרת ואת תשובות השרת לכל בקשה. עכשיו בואו נוסיף אפליקציה דפי אינטרנט כתובים בשפה שנקראת HTML, וכן גם אותה המציא טים ברנרס לי. השפה מורכבת מתגיות ותוכן כאשר התגיות מתארות את התפקיד של כל בלוק או שורה בתוכן. לדוגמה הבלוק:
<h1>hello world</h1>
מתאר שורת כותרת עם הטקסט hello world. הבלוק:
<h1>hello world</h1>
<p>HTML was also invented by Tim Berners Lee along with HTTP and the first web browser</p>
מגדיר שורת כותרת ואחריה פיסקת טקסט רגילה. התגית h1 היא קיצור של המילה header כדי לתאר שורת כותרת והתגית p היא קיצור של המילה paragraph ולכן מתארת פיסקה. עם המצאת שפת HTML טים ברנרס לי המציא גם כלי שנקרא דפדפן אינטרנט שיודע לקרוא מסמכים בשפת HTML ולהציג אותם בצורה גרפית, למשל את הכותרות הוא הציג בגופן גדול יותר. נקפוץ 15 שנה קדימה ונגיד שאנחנו רוצים לכתוב אפליקציה לטלפון. האפליקציה שלנו צריכה להציג חוקים של משחקי לוח פופולריים וכבר כתבנו את כל החוקים בצורה יפה בשפת HTML עבור דף האינטרנט שלנו. הבעיה היא שאת האפליקציה אנשים מתקינים על הטלפון ולא פותחים בתוך דפדפן - לא כל המידע שמופיע בדף האינטרנט רלוונטי גם לאפליקציה, וייתכן ובאפליקציה המפתחים ירצו להטמיע עיצוב או מבנה שונה מזה שמופיע ברשת. הפיתרון - JSON הפיתרון שנבחר ברוב המערכות היה להישאר עם HTTP אבל להיפרד מ HTML. במקום שהשרת יחזיר דף HTML עם כל התוכן והתפקיד הסמנטי של כל חלק בתוכן, השרת עדיין יקבל פניה בשפת HTTP מהלקוחות ויחזיר "משהו אחר", משהו שגם אפליקציה וגם דפדפן אינטרנט יכולים לקרוא. ברוב האינטרנט המשהו הזה נקרא JSON.