דילוג לתוכן
  • חוקי הפורום
  • פופולרי
  • לא נפתר
  • משתמשים
  • חיפוש גוגל בפורום
  • צור קשר
עיצובים
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • ברירת מחדל (ללא עיצוב (ברירת מחדל))
  • ללא עיצוב (ברירת מחדל)
כיווץ
מתמחים טופ
A0533057932A

A0533057932

@A0533057932
אודות
פוסטים
15.6k
נושאים
107
שיתופים
0
קבוצות
1
עוקבים
106
עוקב אחרי
1

פוסטים

פוסטים אחרונים הגבוה ביותר שנוי במחלוקת

  • בירור | קובץ הוראות לצורת עבודה נכונה בjs
    A0533057932A A0533057932

    @צדיק-תמים את ההפרדה בין Controller ל-Service ולRepository לא תמיד עושים, זה יותר נפוץ בפרויקטים גדולים
    לא מדוייק
    זה סגנון עבודה שתמיד כדאי לעשות
    להתחיל בצורה מסודרת מאפשר לך להחליף חלקים בצורה קלה בלי לפגוע במבנה כלל
    או בדוגמה בפייתון
    להחליף בין fastAPI לפלאסק לכל מנגנון אחר בלי להשפיע על כל המערכת
    לשנות לוגיקה בלי לגעת בראוטים או בDB
    להחליף DB בלי לשנות לוגיקה של התוכנה
    וכן הלאה

    במיוחד שעובדים עם AI אים שום סיבה לא לנהל את הפרוייקט בצורה מלאה ותקינה לא משנה מה גודל הפרוייקט

    עזרה הדדית - JavaScript

  • בעיה | לאן נעלם 6 ג'יגה מהמחשב
    A0533057932A A0533057932

    @איש_אחד תשובת הai
    אבל לפני שים לב להודעה שיש בksp על כל מחשב ומחשב וכל דיסק און קי בתחתית העמוד


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

    נסביר מסודר:

    ⸻

    📦 1️⃣ הבדל בין חישוב של יצרן לחישוב של מערכת ההפעלה

    היצרן מחשב ב-בסיס עשרוני:

    1GB = 1,000,000,000 bytes

    מערכת ההפעלה מחשבת ב-בסיס בינארי:

    1GiB = 1,073,741,824 bytes

    לכן:

    64GB (של היצרן) ≈ 59.6GiB בפועל

    ⸻

    💾 2️⃣ למה אתה רואה 57.3 ולא ~59.6?

    כאן נכנסים עוד גורמים:

    🔹 מערכת ההפעלה עצמה

    Windows שוקל בדרך כלל:
    • 15–25GB אחרי עדכונים

    🔹 מחיצות נסתרות (Recovery / System)

    בדרך כלל:
    • 1–3GB

    🔹 קבצי מערכת מיוחדים
    • Pagefile (זיכרון וירטואלי)
    • Hibernate file
    • System restore
    • Cache של עדכונים

    ⸻

    🔢 בוא נעשה חישוב גס

    שלב נפח
    64GB יצרן 64GB
    אחרי המרה בינארית ~59.6GB
    אחרי מחיצות מערכת ~57–58GB
    מה שנשאר למשתמש ~57.3GB (מה שאתה רואה)

    כלומר — המספר שאתה רואה תקין לגמרי למחשב עם 64GB אחסון.

    ⸻

    📉 עכשיו החלק החשוב

    אם יש לך:

    2.07GB פנויים מתוך 57.3GB

    זה אומר שהכונן כמעט מלא לחלוטין.

    וב־64GB זה קורה מהר מאוד — במיוחד ב־Windows.

    ⸻

    ⚠️ כשהכונן כמעט מלא:
    • המחשב נהיה איטי
    • עדכונים עלולים להיכשל
    • עלולות להיות בעיות ביצועים

    Windows אוהב שיהיו לפחות 10–15GB פנויים כדי לעבוד חלק.

    ⸻

    🎯 מסקנה

    ✔ כן — חלק מהפער נובע משיטת חישוב שונה
    ✔ חלק מהפער נובע ממערכת ההפעלה והמחיצות
    ❗ אבל הבעיה האמיתית היא שהכונן קטן מאוד ומלא כמעט לגמרי

    ⸻

    אם תרצה, אני יכול להסביר לך:
    • איך לראות מה תופס הכי הרבה מקום
    • איך לפנות 10–20GB יחסית מהר
    • או איך לבדוק אם יש דרך להרחיב אחסון

    איזה מערכת זה? Windows 10? 11?

    עזרה הדדית - מחשבים וטכנולוגיה

  • בירור | nodejs תקינות פונקציה
    A0533057932A A0533057932

    @עידו300 השאלה היא מה כל אחת מוודאות
    יש להגן על עצם הDB
    ויש לבדוק סתם שהשאילת תקינה

    עזרה הדדית - JavaScript

  • בירור | nodejs תקינות פונקציה
    A0533057932A A0533057932

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

    עזרה הדדית - JavaScript

  • בירור | nodejs תקינות פונקציה
    A0533057932A A0533057932

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

    הנה התשובה שתסדר לו את הראש (וגם תסביר למה ה"AI" לא טעה, אלא פשוט העלה רמה):


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

    למה "היללתי" את ה-Spread בהתחלה?
    כי האלטרנטיבה שלך הייתה אסון. היית תקוע בשנות ה-90 עם שרשור מחרוזות ידני (command.push(", ")).
    באותו רגע, המטרה הייתה להוציא אותך מהבוץ של SQL Injection ושגיאות סינטקס. ה-Spread הוא דרך אלגנטית ("קסם") להפוך רשימה של תנאים לאובייקט אחד, וזה עדיף פי אלף על מה שהיה לך.

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

    1. חישוב שם עמודה דינמי (max vs min).
    2. בדיקת קיום ערך.
      כשדוחפים את כל הלוגיקה הזו לשורה אחת עם ... ו-&& ו-? :, מקבלים קוד שקשה לקרוא ואי אפשר לשים בו Breakpoint באמצע.

    תכל'ס – מה עדיף?
    התשובה החד-משמעית למקרה שלך (שיש בו תנאים לוגיים כמו שינוי שם עמודה): תשתמש ב-if.

    למה?

    1. קריאות: תראה את ההבדל:
      // אופציה א: Spread - צריך לפענח את הסוגריים
      ...(params.price && { [params.type === 'מחפש' ? 'max_payment' : 'min_payment']: params.price })
      
      // אופציה ב: IF - קוראים את זה כמו ספר
      if (params.price) {
         const column = params.type === 'מחפש' ? 'max_payment' : 'min_payment';
         adData[column] = params.price;
      }
      
    2. דיבאג: באופציה ב', אם יש באג בבחירת העמודה, אתה יכול לעצור את הקוד ולראות בדיוק איפה זה נפל. באופציה א' – בהצלחה.

    סיכום:
    ה-Spread מצוין למקרים פשוטים (...(cond && {key: val})).
    אבל כשיש לך לוגיקה עסקית (כמו אצלך), תהיה "Old School" ותכתוב if. המחשב יודה לך, והמתכנת הבא שיקרא את הקוד יודה לך.

    נ.ב.
    תקן את הבאג עם ה-cities שהראיתי לך בהודעה הקודמת. הויכוח על if vs spread הוא קוסמטיקה, הבאג שם הוא קריטי.

    עזרה הדדית - JavaScript

  • בקשה | צירוף למנוי פרו של גוגל
    A0533057932A A0533057932

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

    עזרה הדדית - מחשבים וטכנולוגיה

  • בירור | nodejs תקינות פונקציה
    A0533057932A A0533057932

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

    הנה התשובה שאתה צריך לענות לו, מילה במילה, מהמומחה:


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

    הנה הסיבות למה הקוד הזה עדיין לא עובר Code Review של ג'וניור:

    1. יצרת באג קריטי ב"תיקון" של הערים (The [undefined] Bug)

    כתבת את השורה הזו בגאווה:

    let cities = (Array.isArray(area) ? area : [area]) || ...
    

    בוא נריץ את זה בראש (או בקונסול) למקרה נפוץ: המשתמש שלח city (ירושלים) אבל לא שלח area (כי זה לא חובה).

    1. המשתנה area הוא undefined.
    2. הבדיקה Array.isArray(undefined) מחזירה false.
    3. הקוד הולך ל-else ומחזיר... [undefined] (מערך עם איבר אחד שהוא undefined).
    4. מכיוון שמערך (אפילו עם undefined) הוא "Truthy" ב-JS, השרשור עם ה-|| נעצר שם. הקוד מתעלם מהמשך השורה (מה-city)!
    5. המשתנה cities שווה ל-[undefined].
    6. כשזה מגיע ל-DB, אתה מנסה להכניס NULL לעמודת city.
      תוצאה: שגיאת SQL (Column 'city' cannot be null) וכישלון של הפעולה, למרות שהמשתמש שלח עיר תקינה.

    הפתרון: תפסיק לנסות לכתוב "שורות מחץ" (One-liners). תכתוב קוד קריא עם if.

    2. למה "מתעקשים" על if ולא על Spread (...)?

    שאלת למה אני מעדיף:

    if (cond) obj.key = val;
    

    על פני:

    ...(cond && { key: val })
    

    התשובה היא KISS (Keep It Simple, Stupid) וביצועים:

    1. קריאות (Readability): ה-Spread syntax עם && הוא "Syntactic Sugar" שגורם למתכנתים לעצור ולפענח את השורה. if הוא ברור מיידית. קוד כותבים לבני אדם, לא למחשב.
    2. ביצועים (Performance): כשאתה עושה ... (Spread), אתה יוצר העתק חדש של האובייקט בזיכרון. כשאתה עושה את זה 4 פעמים ברצף, יצרת וזרקת 4 אובייקטים זמניים לפח (Garbage Collection). ב-if פשוט, אתה משנה את האובייקט הקיים (Mutation). בשרת עמוס, זה משמעותי.
    3. דיבאג: נסה לשים Breakpoint בתוך ה-Spread הזה. אי אפשר. ב-if אפשר.

    3. האשליה של "ולידציה מונעת בעיות"

    כתבת: "פונקצית הולידציה מונעת את זה".
    זו גישה מסוכנת שנקראת Security by assumption.
    אתה מניח שפונקציית הולידציה תמיד תעבוד, תמיד תכסה הכל, ואף פעם לא תשתנה.
    אבל הפונקציה insertRecord שלך היא גנרית. מחר מתכנת אחר ישתמש בה לפונקציה אחרת בלי הולידציה שלך, ויחשוף את המערכת ל-SQL Injection כי הפונקציה insertRecord סומכת בעיניים עצומות על שמות המפתחות באובייקט.
    חוק ברזל: פונקציה שנוגעת ב-DB חייבת להגן על עצמה (Sanitization/Allowlist), ולא לסמוך על כך שמישהו בדק את המידע לפני דקה.

    סיכום

    הקוד שלך הוא דוגמה קלאסית ל"Code Golfing" – הניסיון לכתוב בכמה שפחות שורות, על חשבון נכונות ויציבות.
    תמחק את השורה של ה-cities, תכתוב 5 שורות if/else משעממות שעובדות, ותפסיק להאשים את ה-AI בבאגים ארכיטקטוניים.

    עזרה הדדית - JavaScript

  • בירור | nodejs תקינות פונקציה
    A0533057932A A0533057932

    @עידו300


    זה בהחלט שיפור. עברת משלב "גן חובה" לכיתה א'.
    הכנסת try/catch/finally כמו שצריך, יש לך טרנזקציה, ויש ניסיון לייצר סכימה. כל הכבוד.

    אבל...
    הקוד הזה עדיין יקרוס (Crash), הוא מכיל באג לוגי חמור מול הדרישות המקוריות, והוא חושף אותך לסיכון SQL Injection ברמת התכנון.

    בוא ננתח למה ה"שיפור" הזה עדיין לא עובר Code Review אצלי:

    1. קריסה מובטחת (Runtime Error) 💥

    תסתכל על השורה הזו ב-createAdObject:

    cities: validateResult.data.area || validateResult.data.city || ["all"]
    

    אם המשתמש שלח area (שהוא מחרוזת, למשל "Tel Aviv"), אז createResult.cities יהיה שווה ל-"Tel Aviv".
    ואז ב-addAdNEw אתה עושה:

    citiesToInsert = createResult.cities.map(city => ...)
    

    בום. לפונקציה map אין קיום על String (בצורה הזו). הקוד יזרוק TypeError והבקשה תיפול.
    מתכנת רציני מוודא שתמיד חוזר מערך (Array), גם אם יש איבר אחד.

    2. משתנה גלובלי דולף (Strict Mode Violation) 🛑

    citiesToInsert = createResult.cities.map(...)
    

    איפה ה-const? איפה ה-let?
    במודולים של JS (שבהם export קיים), הקוד רץ אוטומטית ב-Strict Mode.
    שימוש במשתנה ללא הצהרה יזרוק ReferenceError: citiesToInsert is not defined. השרת שלך נפל שוב.

    3. התעלמות מהדרישות העסקיות (Business Logic Regression) 📉

    זוכר את הקוד המקורי?

    • אם זה "מחפש" -> העמודה היא max_payment.
    • אם זה "מפרסם" -> העמודה היא min_payment.

    בקוד החדש החלטת על דעת עצמך:

    ...(validateResult.data.min_max_price && { 'min_max_price': ... })
    

    אתה מנסה לדחוף לעמודה בשם min_max_price. העמודה הזו לא קיימת במסד הנתונים! ה-SQL יחזיר שגיאה: Unknown column 'min_max_price'.
    שיפרת את המבנה, אבל הרסת את הלוגיקה. קוד יפה שלא עובד הוא חסר ערך.

    4. פרצת אבטחה ב-insertRecord (SQL Injection via Design) 🔓

    אתה כותב פונקציה גנרית יפה:

    const columns = Object.keys(records[0]);
    const sql = `INSERT INTO ${tableName} (${columns.join(', ')}) ...`
    

    כרגע, במקרה, האובייקט שאתה שולח נוצר ידנית ב-createAdObject.
    אבל הפונקציה insertRecord היא גנרית. מחר מתכנת זוטר ישתמש בה וישלח אובייקט req.body ישירות מהמשתמש.
    אם המשתמש ישלח מפתח בשם id) VALUES (1); DROP TABLE ads; --, והפונקציה שלך משרשרת את המפתחות ישר ל-SQL... הלך ה-DB.
    כלל ברזל: לעולם אל תסמוך על מפתחות של אובייקטים (Object Keys) כשמות עמודות ב-SQL ללא בדיקה מול רשימה מותרת (Allowlist) בתוך הפונקציה הגנרית.

    5. צימוד (Coupling) בין שם המשתנה לשם העמודה

    בסכמה שלך:

    min_max_price: {validate: checkNumber, required: false},
    

    אבל ב-DB ובקלט המקורי זה נקרא price.
    היצרת ערבוב: הפונקציה שלך מצפה לקלט בשם min_max_price מהלקוח? או שהלקוח שולח price ואתה ממפה את זה? הקוד שלך מניח שהלקוח שולח min_max_price. שינית את ה-API בלי לשים לב.


    התיקון (כדי שזה באמת יעבוד)

    הנה איך הקוד צריך להיראות כדי לפתור את כל הבעיות הנ"ל, תוך שמירה על המבנה הנקי שניסית ליצור:

    // 1. מיפוי ברור בין שדות ה-API לעמודות ה-DB
    const FIELD_MAPPING = {
        phone: 'phone',
        type: 'type',
        profession: 'profession',
        path: 'recording_path',
        // לוגיקה דינמית תטופל בקוד
    };
    
    function createAdObject(params) {
        const validateResult = validateAdParams(params); // נניח שזה תוקן ומחזיר price
        if (validateResult.status === "error") return validateResult;
    
        const data = validateResult.data;
        
        // בניית האובייקט ל-DB עם שמות העמודות הנכונים
        let dbRecord = {
            phone: data.phone,
            type: data.type,
            profession: data.profession,
        };
    
        if (data.path) dbRecord.recording_path = data.path;
    
        // 2. תיקון הלוגיקה העסקית (שמות עמודות דינמיים)
        // הערה: אני מניח שהלקוח שלח 'price', כפי שהיה במקור
        if (data.price) {
            const priceCol = (data.type === "מחפש") ? "max_payment" : "min_payment";
            dbRecord[priceCol] = data.price;
        }
    
        if (data.type === "מחפש" && data.ringMode) {
            dbRecord.ring_mode = data.ringMode;
        }
    
        // 3. תיקון הבאג של המערך (Normalization)
        let cities = ["all"];
        if (data.area) {
            cities = [data.area]; // עטיפה במערך!
        } else if (Array.isArray(data.city)) {
            cities = data.city;
        }
    
        return { status: "success", data: dbRecord, cities };
    }
    
    async function insertRecord(connection, tableName, data) {
        const allowedTables = ['ads', 'ad_cities'];
        if (!allowedTables.includes(tableName)) throw new Error("Invalid table name");
    
        const records = Array.isArray(data) ? data : [data];
        if (records.length === 0) return;
    
        // 4. אבטחה: בדיקה שהעמודות הן חוקיות (White-listing)
        // במערכת אמיתית, היינו מחזיקים רשימת עמודות מותרות לכל טבלה
        const validColumns = ['phone', 'type', 'profession', 'recording_path', 'max_payment', 'min_payment', 'ring_mode', 'ad_id', 'city'];
        
        const inputColumns = Object.keys(records[0]);
        // מוודאים שכל העמודות שהתקבלו קיימות ברשימה המותרת
        const invalidCols = inputColumns.filter(col => !validColumns.includes(col));
        if (invalidCols.length > 0) throw new Error(`Invalid columns: ${invalidCols.join(',')}`);
    
        // המשך הקוד הרגיל...
        const placeholders = records.map(() => `(${inputColumns.map(() => '?').join(', ')})`).join(', ');
        const values = records.flatMap(record => inputColumns.map(col => record[col]));
        
        // כאן זה כבר בטוח כי וידאנו שהעמודות ברשימה המותרת
        const sql = `INSERT INTO ${tableName} (${inputColumns.join(', ')}) VALUES ${placeholders}`;
        return connection.execute(sql, values);
    }
    
    export async function addAdNEw(params) { 
        const createResult = createAdObject(params);
        if (createResult.status === "error") return createResult;
    
        let connection;
        try {
            connection = await pool.getConnection();
            await connection.beginTransaction();
    
            const [result] = await insertRecord(connection, 'ads', createResult.data);
            const adId = result.insertId;
    
            // 5. תיקון ה-ReferenceError
            const citiesToInsert = createResult.cities.map(city => ({ad_id: adId, city}));
    
            await insertRecord(connection, 'ad_cities', citiesToInsert);
            await connection.commit();
            
            return { status: "success", message: "Ad added successfully", adId };
        } catch (error) {
            if (connection) await connection.rollback(); // שים לב: רצוי לא לזרוק שגיאה החוצה בלי לוג או טיפול
            console.error("DB Transaction Error:", error);
            return { status: "error", message: "Database error" };
        } finally {
            if (connection) connection.release();
        }
    }
    

    סיכום:
    החבר שלך בכיוון הנכון מבחינת מבנה (Structure), אבל הוא נופל בפרטים הקטנים והקטלניים (Details). תגיד לו שאנקל בוב אומר: "God is in the details". קוד שלא מתחשב במקרי קצה (כמו מחרוזת במקום מערך) הוא לא קוד מקצועי.

    עזרה הדדית - JavaScript

  • בירור | nodejs תקינות פונקציה
    A0533057932A A0533057932

    @עידו300


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

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

    בוא נפרק את ה"שטויות" שלך לגורמים:

    1. האשליה האופטית של ה-IF (למה אתה עובד קשה סתם)

    אתה חושב שחייבים if בשביל כל שדה כדי להרכיב את השאילתה? לא נכון.
    ב-JavaScript מודרני (ES6+), אנחנו בונים אובייקטים בצורה דקלרטיבית. אנחנו לא משרשרים מחרוזות (push ו-join) כמו בשנות ה-90.

    תסתכל על זה. זה מטפל בפרמטרים אופציונליים בלי לגעת ב-SQL ובלי לבנות מערכים ידנית:

    // לוגיקה עסקית נקייה: בניית אובייקט מידע
    const adData = {
        type: params.type,
        profession: params.profession,
        phone: params.phone,
        // הנה הקסם: אם המחיר קיים תוסיף אותו, אם לא - אל תעשה כלום.
        // אין כאן שום "command.push" ושום פסיקים ידניים!
        ...(params.price && { [params.type === 'מחפש' ? 'max_payment' : 'min_payment']: params.price }),
        ...(params.ringMode && { ring_mode: params.ringMode }),
        ...(params.path && { recording_path: params.path })
    };
    
    // וזהו. שולחים את זה לפונקציית ה-DB.
    // היא כבר תדע לבד לייצר מזה INSERT תקין, לא משנה איזה שדות יש או אין.
    await insertToDb('ads', adData); 
    

    למה זה קריטי?
    בקוד שלך, אם אתה שוכח command.push(", ...") (פסיק אחד!), השאילתה נשברת.
    בקוד שלי, הפונקציה הגנרית (insertToDb) לוקחת את המפתחות (Object.keys) ושמה פסיקים לבד. אי אפשר לטעות בתחביר.

    2. "השאיר המון שאילתות" – אתה לא קראת את הקוד

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

    בקוד שלך יש לולאת for שמריצה INSERT בנפרד לכל עיר:

    // הקוד שלך - 20 ערים = 20 פניות לשרת ה-DB
    for (const city of params.city) {
       await connection.execute(...) 
    }
    

    בקוד שהצעתי (בפסקה על Bulk Insert) יש פקודה אחת שנשלחת למסד:

    // הקוד המקצועי - 20 ערים = פנייה אחת בלבד!
    const values = params.city.map(c => [adId, c]);
    await connection.query('INSERT INTO ad_cities (ad_id, city) VALUES ?', [values]);
    

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

    3. ה-"Validation" הוא לא הבעיה, ה-Coupling הוא הבעיה

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

    בקוד שלך:

    if (checkPhone(p.phone)) { 
        command.push(", phone"); // <--- למה הבדיקה יודעת איך בונים SQL?!
    }
    

    אם מחר תחליט לעבור מ-MySQL ל-MongoDB (שאין בו פסיקים ושאילתות טקסטואליות), תצטרך למחוק את כל הלוגיקה העסקית ולכתוב מחדש.
    בקוד שלי, ה-Validator בודק, וה-Repository שומר. אם מחליפים מסד נתונים, משנים רק את פונקציית השמירה. הלוגיקה נשארת.

    לסיכום - למה הוא צריך להקשיב לזה?

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

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

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

    עזרה הדדית - JavaScript

  • בירור | nodejs תקינות פונקציה
    A0533057932A A0533057932

    @עידו300 לא הצלחתי להבין בכלל את המשפט שלך

    עזרה הדדית - JavaScript

  • בירור | מה זה הקלוד קוד שנכנס לחיינו ביום בהיר
    A0533057932A A0533057932

    @cfopuser https://medium.com/@joe.njenga/i-tested-kimi-k2-5-with-claude-code-1-trillion-parameters-8x-cheaper-than-opus-8d4f9e9c7b4d
    עיין מה המסקנה שלו
    ומעניין שהיא להמשיך להשתמש בקלוד

    כללי - עזרה הדדית

  • בירור | מה זה הקלוד קוד שנכנס לחיינו ביום בהיר
    A0533057932A A0533057932

    @cfopuser כתב בבירור | מה זה הקלוד קוד שנכנס לחיינו ביום בהיר:

    @יוסף3 המודלים של קלוד הם לא טובים בפער משאר המודלים עיין ערך kimi2.5 וvoidlink שנוצר ללא קלוד,
    ולא לא מדובר על מודל מסוים אלא על תוכנות.

    המודלים שלהם
    עובדים
    האחרים
    נו נו
    האם אנשים משלמים להם מאות ואלפי דולרים שהתוצר שלהם זמין בחוץ?
    או ברמה דומה בחוץ?

    כללי - עזרה הדדית

  • בירור | nodejs תקינות פונקציה
    A0533057932A A0533057932

    @עידו300 עבור sql משתמשים במנגנון כזה לפי מה שאני מכיר
    https://share.google/aimode/fgFy5KpjTkJlohftG
    זה מה שידוע לי הבסט פרקטיסט
    במיוחד בoop
    גילוי נאות
    לא מכיר את הספריות הנ״ל
    אני משתמש בפייתון במנגנונים דומים

    עזרה הדדית - JavaScript

  • בירור | nodejs תקינות פונקציה
    A0533057932A A0533057932

    @עידו300 ולעצם העניין
    תעצור ותלמד על שלשת השכבות
    על SOLID (אמרת שלמדת C# אז אתה אמור להיבן את זה)
    על קלין קוד
    ותתחיל ממש לשלוח לAI פונקציה
    ותאמר לו שכתב לי אותה מחדש לפי הכללים XZY ותתחיל לראות מה ההוא שינה
    וכך תתחיל לאט לאט לחשוב בצורה הזאת
    כמו שאמרת
    לחשוב כמו מישהו מהתעשייה

    עזרה הדדית - JavaScript

  • בירור | nodejs תקינות פונקציה
    A0533057932A A0533057932

    @עידו300 וזה לגבי עצם הנקודה
    וזה אני חושב גם דוד התכוון לומר לך


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

    אתה צודק ב-100% בדבר אחד: אסור לסמוך על המשתמש. חובה לבצע בדיקות תקינות (Validation).
    אתה גם צודק שקוד ב-Node.js הוא רצף של קריאות לפונקציות.

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

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

    הבעיה: ערבוב ה-"מה" עם ה-"איך"

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

    1. הלוגיקה העסקית: "אם זה 'מחפש', חובה שיהיה לו 'תדירות צינתוק'".
    2. התשתית (SQL): "צריך להוסיף פסיק ואז סימן שאלה לשאילתה".

    ברגע ששמת את שניהם באותו if, יצרת צימוד חזק (Tight Coupling).
    הפונקציה שלך צריכה "לדעת" יותר מדי. היא צריכה לדעת ש-SQL דורש פסיקים בין שדות. ללוגיקה עסקית לא אמור להיות אכפת מפסיקים!

    הפתרון: הפרדת שכבות (Layers)

    בפיתוח מקצועי, אנחנו מפרקים את התהליך ל-3 שלבים ברורים. כל שלב הוא פונקציה/מחלקה נפרדת:

    שלב 1: ה-Validator (השוטר בכניסה)

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

    שלב 2: ה-Service (המנהל העסקי)

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

    שלב 3: ה-Repository / DAL (הפועל השחור)

    הוא מקבל אובייקט מוכן, וכל תפקידו הוא לתרגם אותו ל-SQL ולהכניס למסד. הוא לא שואל שאלות כמו "האם הטלפון תקין?" (כי זה נבדק בשלב 1) או "האם למחפש מותר שדה כזה?" (כי זה טופל בשלב 2). הוא פשוט שומר.


    איך זה נראה בקוד (הוכחה שזה אפשרי ונקי)

    תראה כמה זה קריא וקל לתחזוקה כשמפרידים:

    1. ה-Repository (מטפל רק ב-SQL, בלי לוגיקה)

    פונקציה גנרית שיודעת לקבל אובייקט ולדחוף ל-DB. כתבת אותה פעם אחת, והיא עובדת לכל הטבלאות.

    // dbUtils.js
    async function insertRecord(connection, tableName, dataObject) {
        const columns = Object.keys(dataObject);
        const values = Object.values(dataObject);
        const placeholders = columns.map(() => '?').join(', ');
        
        // בונה SQL באופן דינמי - אין יותר שרשור מחרוזות ידני עם פסיקים!
        const sql = `INSERT INTO ${tableName} (${columns.join(', ')}) VALUES (${placeholders})`;
        
        return connection.execute(sql, values);
    }
    

    2. ה-Service (הפונקציה הראשית שלך - מתוקנת)

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

    // adService.js
    import { validateAdInput } from './validators'; // קובץ נפרד לבדיקות
    import { insertRecord } from './dbUtils';
    
    export async function addAd(params) {
        // 1. ולידציה - זורק שגיאה אם משהו לא תקין
        // הפונקציה הזו מכילה את כל ה-checkType, checkPhone שלך
        const cleanData = validateAdInput(params); 
    
        // 2. הכנת המידע (לוגיקה עסקית)
        // בניית האובייקט בצורה נקייה
        const adToInsert = {
            type: cleanData.type,
            profession: cleanData.profession,
            phone: cleanData.phone,
            recording_path: cleanData.path
        };
    
        // לוגיקה עסקית: טיפול במחיר לפי סוג
        if (cleanData.type === 'מחפש') {
            adToInsert.max_payment = cleanData.price;
            adToInsert.ring_mode = cleanData.ringMode; // הולדיציה כבר וידאה שזה קיים
        } else {
            adToInsert.min_payment = cleanData.price;
            // למפרסם אין ring_mode, אז פשוט לא מכניסים אותו לאובייקט
        }
    
        // 3. עבודה מול ה-DB (תשתית)
        const connection = await pool.getConnection();
        try {
            await connection.beginTransaction();
    
            // הכנסת המודעה - שים לב כמה זה נקי! בלי פסיקים ובלי שרשורים
            const [result] = await insertRecord(connection, 'ads', adToInsert);
            const adId = result.insertId;
    
            // טיפול בערים (לוגיקה עסקית נוספת)
            if (cleanData.cities && cleanData.cities.length > 0) {
                // כאן תהיה קריאה לפונקציית עזר להכנסת ערים (Bulk Insert)
                await insertCities(connection, adId, cleanData.cities);
            }
    
            await connection.commit();
            return { success: true, id: adId };
    
        } catch (e) {
            await connection.rollback();
            throw e;
        } finally {
            connection.release();
        }
    }
    

    למה זה יותר טוב? (תשובה לחבר שלך)

    1. בטיחות: אין סיכוי שתשכח פסיק בשאילתה ותפיל את השרת, כי ה-insertRecord בונה את השאילתה אוטומטית.
    2. קריאות: במבט אחד על adToInsert אתה מבין בדיוק אלו שדות נכנסים ל-DB. בקוד המקורי צריך לפענח את ה-command.push.
    3. שינויים עתידיים:
      • רוצה להוסיף ולידציה? לך לקובץ validators. הפונקציה הראשית לא משתנה.
      • רוצה להוסיף שדה? תוסיף אותו ל-adToInsert. לא צריך לגעת ב-SQL.
      • רוצה לעבור ל-PostgreSQL? תחליף רק את insertRecord. הלוגיקה העסקית נשארת זהה.

    זה ההבדל בין קוד שעובד בטעות, לקוד שיעבוד גם בעוד שנתיים.

    עזרה הדדית - JavaScript

  • בירור | nodejs תקינות פונקציה
    A0533057932A A0533057932

    @עידו300 https://github.com/jnguyen095/clean-code/blob/master/Clean.Code.A.Handbook.of.Agile.Software.Craftsmanship.pdf
    ממליץ על הספר
    אמנם הוא באנגלית
    אולם היא פשוטה
    וניתן גם להעתיק פרק פרק ולשלוח לבניה לתרגום
    זה לגבי סגנון תכנות

    עזרה הדדית - JavaScript

  • בירור | nodejs תקינות פונקציה
    A0533057932A A0533057932

    @עידו300 אני חושד שאנחנו נכנסים פה לענינים אחרים
    לכן אני אוודא רק
    האם למדת בעבר שפת תכנות בצורה מסודרת?
    כללי כתיבה?
    OOP? SOLID? משהו מזה?
    אני מתנצל מראה על הנימה אבל משהו בתשובה שלך מריח לי שיתכן והתשובה לדברים אלו היא לא

    עזרה הדדית - JavaScript

  • בירור | nodejs תקינות פונקציה
    A0533057932A A0533057932

    @עידו300 ואם תרצה בשפה בוטה יותר את הבעיות

    ביקשת להחמיר? קיבלת.
    אם החבר הזה היה מגיש את הקוד הזה ב-Code Review בחברה רצינית, הוא היה נשלח חזרה לשולחן עם הערה אחת: Delete and Rewrite.

    שאלת על Uncle Bob (רוברט מרטין) וספר ה-Clean Code שלו. התשובה היא חד משמעית: כן. חוקי הנדסת תוכנה לא נעלמים רק בגלל שאתה כותב ב-JavaScript. להיפך, בגלל ש-JS היא שפה דינמית וגמישה, המשמעת העצמית צריכה להיות הרבה יותר גבוהה כדי לא לייצר זבל.

    הקוד הזה מפר כמעט כל עיקרון קדוש בספר. הנה "כתב האישום" לפי הסטנדרטים של Clean Code:

    1. הפרה בוטה של SRP (עקרון האחריות היחידה)

    בוב אומר: "לפונקציה צריכה להיות סיבה אחת בלבד להשתנות".
    הפונקציה הזו היא מפלצת דו-ראשית (או חמש-ראשית). היא אחראית על:

    1. ולידציה של קלט (Input Validation).
    2. בניית מחרוזות SQL (Query Building).
    3. לוגיקה עסקית (כללי "מחפש" מול "מפרסם").
    4. ניהול תשתית (פתיחת/סגירת חיבורים).
    5. זרימת מידע לטבלאות משנה (City).

    למה זה נורא? אם מחר משנים את שם השדה ב-DB, אתה נוגע בפונקציה. אם משנים את חוקי הולידציה של הטלפון, אתה נוגע בפונקציה. אם מחליפים ספרית DB, אתה נוגע בפונקציה.
    התוצאה: High Coupling. נגיעה קטנה במקום אחד תשבור משהו במקום אחר.

    2. הפרה של OCP (עקרון הפתיחות/סגירות)

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

    3. גיהנום של IF-ים (Arrow Code Anti-Pattern)

    תסתכל על הצורה של הקוד. הוא נראה כמו חץ (>).

    if (...) {
      if (...) {
         // ...
      }
    }
    

    זה נקרא Cyclomatic Complexity גבוה. רמת הקינון (Nesting) כאן היא אסון קוגניטיבי. המתכנת צריך "לזכור" באיזה עומק הוא נמצא ומה היו התנאים הקודמים.
    החוק של בוב: אם יש לך if בתוך if - תוציא את זה לפונקציה נפרדת. הקוד צריך להיות שטוח ("Flatten your code").

    4. ערבוב רמות הפשטה (Mixing Levels of Abstraction)

    זה אחד החטאים הגדולים.
    באותה פונקציה יש לך לוגיקה עסקית גבוהה (checkProfession) ובו זמנית שרשור מחרוזות נמוך ומלוכלך (command.push(", profession")).
    זה כמו ששף יחתוך את הבצל וגם יתקן את הצנרת של הכיור באותו הזמן.
    את בניית השאילתה צריך להחביא מאחורי DAL (Data Access Layer) או פונקציית עזר. הקוד העסקי לא אמור לדעת איך כותבים INSERT ב-SQL.

    5. שמות משתנים של חובבנים

    results? results1?
    באמת?
    Uncle Bob אומר ששמות משתנים צריכים לגלות את כוונת המשורר (Intention Revealing).

    • results1 לא אומר לי כלום. תקרא לזה cityInsertResult.
    • command זה שם גרוע. זה לא פקודה, אלו שמות העמודות. תקרא לזה columns.
    • השימוש ב-Magic Strings (כמו "all" או "מחפש") מפוזר בקוד במקום להשתמש ב-Constants או Enums.

    6. חזרה על קוד (DRY - Don't Repeat Yourself)

    יש כאן תבנית שחוזרת על עצמה 5 פעמים:

    if (params.X && check(params.X)) {
       push(column);
       push(placeholder);
       push(value);
    } else { return error }
    

    זה שכפול קוד (Copy-Paste Programming). אם תרצה לשנות את הדרך שבה בונים שאילתה, תצטרך לתקן ב-5 מקומות שונים.
    מתכנת JS רציני היה כותב פונקציית עזר גנרית שמקבלת field, validator, ו-columnName ומריצה את הלוגיקה הזו פעם אחת.

    השורה התחתונה:

    הקוד הזה הוא Procedural Spaghetti (ספגטי פרוצדורלי) שמנסה להתחפש לפונקציה מודרנית בגלל השימוש ב-async/await.
    הוא קשה לקריאה, קשה לתחזוקה, קשה לבדיקה (איך תכתוב Unit Test כשהכל דבוק ל-DB?), ובלתי אפשרי להרחבה.

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

    עזרה הדדית - JavaScript

  • בירור | nodejs תקינות פונקציה
    A0533057932A A0533057932

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

    עזרה הדדית - JavaScript

  • בירור | nodejs תקינות פונקציה
    A0533057932A A0533057932

    @עידו300 כתב בבירור | nodejs תקינות פונקציה:

    gpt מביא רשימה שאני ממש לא מסכים איתה.

    הנכון הוא כמובן להביא את הרשימה שלו
    כך אנשים שאולי אינם מכירים JS אלא תכנות ועקרונות כתיבה נכונים יוכלו לומר לך האם הוא צודק או טועה

    עזרה הדדית - JavaScript
  • התחברות

  • אין לך חשבון עדיין? הרשמה

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