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

תחומים - פורום חרדי מקצועי

💡 רוצה לזכור קריאת שמע בזמן? לחץ כאן!
  1. דף הבית
  2. תכנות
  3. שאלות לגבי כתיבת אפליקציית שרת יציבה (בנוד)

שאלות לגבי כתיבת אפליקציית שרת יציבה (בנוד)

מתוזמן נעוץ נעול הועבר תכנות
13 פוסטים 5 כותבים 307 צפיות
  • מהישן לחדש
  • מהחדש לישן
  • הכי הרבה הצבעות
התחברו כדי לפרסם תגובה
נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
  • yossizY מנותק
    yossizY מנותק
    yossiz
    כתב ב נערך לאחרונה על ידי yossiz
    #1

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

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

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

    מבנה האפליקציה

    אני משתמש ב-Sequelize כ-ORM. (אגב, אני משתגע ממנו... לפעמים אני מרגיש שאני לוחם נגדו ולא נעזר בו, אולי אפתח עוד נושא על זה)

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

    לכל מודל יש קובץ מקביל בשם XxxxController (כאשר xxx כמובן מציין את שם המודל) שיש בתוכו כמה פונקציות CRUD-יות, פונקציות אלו בד"כ מקבלות כמה ארגומנטים רגילים כמו objectId לעשות עליו את הפעולה וכו' וכארגומנט אחרון אובייקט של user עבור בדיקת הרשאות.

    שאלה א.
    לאחרונה אני מרגיש שזה לא מספיק להעביר את ה-user לכל פונקציה, א) לפעמים אין user, לדוגמה קריאה שנגרמת מ-webhook. ב) לפעמים אני צריך יותר הקשר מאשר רק ה-user. דוגמה, אני רוצה לעשות את הפעולה בתוך transaction, ואז צריך להוסיף עוד ארגומנט עבור זה. ועוד ועוד.
    לכאורה יותר נכון לבנות איזה אובייקט של context ולהכניס לתוכו כל דבר שהוא חלק מההקשר של הפעולה, כמו ה-req והיוזר, וטרנזקציות וכו', ואת זה להעביר לכל הפונקציות.

    שאלה ב
    האם יש צורך להפריד את זה לעוד שכבות? ואם כן איך?
    כי ברעיון הייתי מעדיף לא לגשת אף פעם למודל ישירות, רק דרך ה-controller כי יש דברים שצריך תמיד לעשות כמו בדיקות הרשאה ויותר טוב שזה יהיה במקום אחד, אממה, יש הרבה פעמים צרכים מאוד ספציפיים לחלק אחד מהאפליקציה וחבל לכתוב עוד פונקציה או להוסיף עוד ארגומנטים רק עבור צורך זה, אלא יותר קל לגשת ישר דרך המודל. דוגמה, יש בקונטרולר פונקציה שנקרא findById שמביא שורה מה-DB לפי ה-ID.
    אבל יש פעמים שאני רוצה לעשות JOIN ולהביא עוד אובייקטים קשורים ביחד איתו, האם להוסיף את כל המקרים האלו לפונצקיה כארגומנטים, או לכתוב פונקציה נוספת, או להשתמש במודל ישירות?

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

    📧 יוסי@מייל.קום | 🌎 בלוג | ☕ קפה

    chagoldC dovidD 2 תגובות תגובה אחרונה
    4
    • chagoldC מנותק
      chagoldC מנותק
      chagold
      השיב לyossiz ב נערך לאחרונה על ידי
      #2

      @yossiz אמר בשאלות לגבי כתיבת אפליקציית שרת יציבה (בנוד):

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

      הגיונית אם הוא מתיימר להיות גשר לDB אז הוא צריך לתת אפשרות לכל השאילתות. (בדומה למבנה היישויות XENFORO שנותנים תמיכה לזה).

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

      תגובה 1 תגובה אחרונה
      1
      • dovidD מחובר
        dovidD מחובר
        dovid ניהול
        השיב לyossiz ב נערך לאחרונה על ידי
        #3

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

        מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

        בכל נושא אפשר ליצור קשר dovid@tchumim.com

        מנצפךמ yossizY 2 תגובות תגובה אחרונה
        1
        • מנצפךמ מנותק
          מנצפךמ מנותק
          מנצפך
          השיב לdovid ב נערך לאחרונה על ידי
          #4

          בדיקת הרשאות (authentication ו- authotization) אמורה להיעשות בשלב מוקדם יותר, של ה middleware.
          כלומר ב route אתה מגדיר לו איזה middleware הוא יעבור.

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

          אני אישית מעביר את כל ה req. ואתה יכול לבנות middleware שיסדר לך אובייקט user בתוך ה req כרצונך.

          לגבי הטרנזקציות, לא הבנתי את המקרה.

          לגבי שאלה ב:
          אני לא מבין איך אתה ניגש למודל לא דרך ה controller. כלומר מה בדיוק מבנה השרת אצלך.
          אבל כמובן שהכל צריך להיות דרך ה controller.
          ואגב, לדעתי את רוב הלוגיקה של משיכה מה DB צריך לכתוב במודל עצמו.
          נניח findBookByAuthorName, או createNewBook.

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

          אך זו רק דעתי.

          נ.ב. אני מחכה לפוסט שלך על ה-Sequelize.

          yossizY תגובה 1 תגובה אחרונה
          2
          • yossizY מנותק
            yossizY מנותק
            yossiz
            השיב לdovid ב נערך לאחרונה על ידי yossiz
            #5

            @dovid אמר בשאלות לגבי כתיבת אפליקציית שרת יציבה (בנוד):

            מה ממפה את הבקשות לפונקציות שבקונטרולר עם הפרמטרים שאמרת, שכבה שאתה עשית?

            כן, לא סיימתי לתאר את הכל כי כבר היו לי שאלות ולא רציתי לכתוב מגילה ארוכה מדי...

            בשכבה החיצונה יש את ה-routes ששם באמת יש בדיקת הרשאות כמו ש-@מנצפך כתב, וכל בקשה ממופה לפעולה באחת מהקונטרולרים

            📧 יוסי@מייל.קום | 🌎 בלוג | ☕ קפה

            תגובה 1 תגובה אחרונה
            1
            • yossizY מנותק
              yossizY מנותק
              yossiz
              השיב למנצפך ב נערך לאחרונה על ידי
              #6

              @מנצפך אמר בשאלות לגבי כתיבת אפליקציית שרת יציבה (בנוד):

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

              על דברים כאלו בדיוק התכוונתי. ב-middleware אפשר רק לחסום route שלם.

              ואתה יכול לבנות middleware שיסדר לך אובייקט user בתוך ה req כרצונך

              יש כבר, passport.

              אני לא מבין איך אתה ניגש למודל לא דרך ה controller. כלומר מה בדיוק מבנה השרת אצלך.

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

              📧 יוסי@מייל.קום | 🌎 בלוג | ☕ קפה

              dovidD תגובה 1 תגובה אחרונה
              1
              • dovidD מחובר
                dovidD מחובר
                dovid ניהול
                השיב לyossiz ב נערך לאחרונה על ידי
                #7

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

                מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                בכל נושא אפשר ליצור קשר dovid@tchumim.com

                yossizY תגובה 1 תגובה אחרונה
                1
                • yossizY מנותק
                  yossizY מנותק
                  yossiz
                  השיב לdovid ב נערך לאחרונה על ידי yossiz
                  #8

                  @dovid אמר בשאלות לגבי כתיבת אפליקציית שרת יציבה (בנוד):

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

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

                  מי כתב את הפונקציות הללו כמו findById

                  אני כתבתי.

                  ואיך זה עובד יפה וגמרי לכל הקונטרולרים?

                  לא הבנתי

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

                  📧 יוסי@מייל.קום | 🌎 בלוג | ☕ קפה

                  dovidD תגובה 1 תגובה אחרונה
                  2
                  • dovidD מחובר
                    dovidD מחובר
                    dovid ניהול
                    השיב לyossiz ב נערך לאחרונה על ידי
                    #9

                    ואיך זה עובד יפה וגמרי לכל הקונטרולרים?

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

                    מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                    בכל נושא אפשר ליצור קשר dovid@tchumim.com

                    clickoneC yossizY 2 תגובות תגובה אחרונה
                    1
                    • clickoneC מנותק
                      clickoneC מנותק
                      clickone
                      השיב לdovid ב נערך לאחרונה על ידי clickone
                      #10

                      @dovid אם זה ORM נורמלי (וככה זה נראה) אז הוא אמור לדעת מה הPK ולפי זה לתשאל לבד בצורה גנרית.
                      ככה זה לפחות בEF

                      עריכה: כעת אני רואה שמדובר על הקונטרולר ולא על המודל. - אז אני מחזיר את המילים שלי.
                      אולי הוא גם יורש מהמודל?

                      אין טסט כמו פרודקשן.

                      המייל שלי urivpn@gmail.com

                      תגובה 1 תגובה אחרונה
                      1
                      • yossizY מנותק
                        yossizY מנותק
                        yossiz
                        השיב לdovid ב נערך לאחרונה על ידי yossiz
                        #11

                        @dovid
                        המודלים הם אובייקטים שיורשים מ-Sequelize.Model. הם ה-object שב-O של ORM...
                        האובייקט הזה מגיע עם כל מיני פונקציות שימושיות.
                        למשל אני מגדיר מודל בשם User ככה:

                        const User = sequelize.define('user', {
                          id: {
                            type: Sequelize.UUID,
                            defaultValue: Sequelize.UUIDV1,
                            primaryKey: true
                          },
                          number: {
                            type: Sequelize.INTEGER,
                            autoIncrement: true
                          },
                        // וכן הלאה כל העמודות ב-DB‏‏
                        

                        הפונקציה define מחזירה לי אובייקט User עם המון פונקציות שימושיות:

                        User.findAll({ where: { ...whereConditions }, include: [ ...tablesToJoin ] });
                        User.findByPK(pk, include: { tablesToJoin });
                        User.Update({ ...updates }, { where: { ... } })
                        // או אפשר לקרוא על מופע של יוזר
                        user.update(...);
                        user.getXXX // כאשר XXX הוא שם של טבלה משוייכת
                        

                        אני לא יודע מה המקביל של זה ב-EF, (אולי entity?)

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

                        על גבי זה אני מוסיף שכבת לוגיקה שכולל בין השאר בדיקת הרשאות, "ניהול חשבונות" כמו הרצת כל מיני פעולות וטריגרים שצריכים לקרות בעת יצירת/עדכון אובייקט ב-DB וכו' וכו' בקיצור כל ה-business logic של האפליקציה.

                        בשכבה הזאת אני מוסיף לכל אובייקט פונקצית findById ועוד ממשפחת ה-CRUD שכוללים בתוכם את כל ה-business logic של האפליקציה כמו הרצת בדיקות/פעולות/טריגרים, פונקציות אלו כמובן מסתיימות בקריאה לשכבה שלמטה ממנו.

                        השכבה הזאת הוא בקבצי הקונטרולרים.

                        האם זה המכוון בקונטרולר? אני לא יודע... אף פעם לא היה נהיר לי מה אמור ליכנס בקונטרולר.

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

                        האם עכשיו השאלה יותר מובנת?

                        📧 יוסי@מייל.קום | 🌎 בלוג | ☕ קפה

                        dovidD תגובה 1 תגובה אחרונה
                        2
                        • dovidD מחובר
                          dovidD מחובר
                          dovid ניהול
                          השיב לyossiz ב נערך לאחרונה על ידי
                          #12

                          @yossiz כעת הבנתי.
                          לדעתי חייבים לשלב, כלומר לתת גישה ישירה לDB בקונטרולר בשביל 10 אחוז מהמקרים,
                          ולהשתדל שב90 אחוז הקלאסיים יהיה פתרון גנרי.
                          אני אוחז שאסור להימנע מדרכים פשוטות באופן קיצוני, בגלל כללי תכנות ארוכי טווח. כי דרכים לא פשוטות זה אומר פי עשר כח אדם במקרה הטוב, ובמקרה הגרוע אלף עבירות תכנות אחרות.

                          לגבי קונטרולר, ההגדרה ה"טהורה" שלו זה שצריך להיות שמה כמה שפחות דברים... כלומר זה אכן לא מוגדר, אבל תפקידו צריך להיות סוג של איש קשר בין יחידות שונות (קלט/לוגיקה/פלט).
                          (כעת חיפשתי שוב, ומצאתי את ההתפתלויות האלו... https://stackoverflow.com/a/1015853/1271037).

                          מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                          בכל נושא אפשר ליצור קשר dovid@tchumim.com

                          dovidD תגובה 1 תגובה אחרונה
                          4
                          • dovidD מחובר
                            dovidD מחובר
                            dovid ניהול
                            השיב לdovid ב נערך לאחרונה על ידי dovid
                            #13

                            כעת ראיתי שיש שפע חומר בחיפוש גוגל
                            "fat models and skinny controllers"
                            זה אגב ההגדרה שלמדתי בספר כלשהוא על MVC.

                            מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                            בכל נושא אפשר ליצור קשר dovid@tchumim.com

                            תגובה 1 תגובה אחרונה
                            6

                            בא תתחבר לדף היומי!
                            • התחברות

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

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