שאלות לגבי כתיבת אפליקציית שרת יציבה (בנוד)
-
בדיקת הרשאות (authentication ו- authotization) אמורה להיעשות בשלב מוקדם יותר, של ה middleware.
כלומר ב route אתה מגדיר לו איזה middleware הוא יעבור.אבל אתה אכן צריך לפעמים לגשת גם אח"כ ל user, כדי לדעת האם יש לו גישה לרשומה הספציפית שהוא מבקש (נניח שאתה מרשה לו לקבל רשימת ספרים, אבל רק של אגף ספציפי).ואת זה אני לא חושב שתמיד אפשר לבדוק ב middleware. כי זה מחוץ ל scope שלה הרבה פעמים.
אני אישית מעביר את כל ה req. ואתה יכול לבנות middleware שיסדר לך אובייקט user בתוך ה req כרצונך.
לגבי הטרנזקציות, לא הבנתי את המקרה.
לגבי שאלה ב:
אני לא מבין איך אתה ניגש למודל לא דרך ה controller. כלומר מה בדיוק מבנה השרת אצלך.
אבל כמובן שהכל צריך להיות דרך ה controller.
ואגב, לדעתי את רוב הלוגיקה של משיכה מה DB צריך לכתוב במודל עצמו.
נניח findBookByAuthorName, או createNewBook.ה controllre אמור להיות רק החלק האחרון שהבקשה מגיעה אליו, והוא עושה את בדיקת הנתונים וטיוב הנתונים שלא יכולנו לעשות לפני זה. כמו כן לעשות פעולות שלא קשורות למודל. כמו, לשלוח מייל. או לשלוח הודעה ב webSocket.
אך זו רק דעתי.
נ.ב. אני מחכה לפוסט שלך על ה-Sequelize.
-
@dovid אמר בשאלות לגבי כתיבת אפליקציית שרת יציבה (בנוד):
מה ממפה את הבקשות לפונקציות שבקונטרולר עם הפרמטרים שאמרת, שכבה שאתה עשית?
כן, לא סיימתי לתאר את הכל כי כבר היו לי שאלות ולא רציתי לכתוב מגילה ארוכה מדי...
בשכבה החיצונה יש את ה-routes ששם באמת יש בדיקת הרשאות כמו ש-@מנצפך כתב, וכל בקשה ממופה לפעולה באחת מהקונטרולרים
-
@מנצפך אמר בשאלות לגבי כתיבת אפליקציית שרת יציבה (בנוד):
אבל אתה אכן צריך לפעמים לגשת גם אח"כ ל user, כדי לדעת האם יש לו גישה לרשומה הספציפית שהוא מבקש (נניח שאתה מרשה לו לקבל רשימת ספרים, אבל רק של אגף ספציפי).ואת זה אני לא חושב שתמיד אפשר לבדוק ב middleware. כי זה מחוץ ל scope שלה הרבה פעמים.
על דברים כאלו בדיוק התכוונתי. ב-middleware אפשר רק לחסום route שלם.
ואתה יכול לבנות middleware שיסדר לך אובייקט user בתוך ה req כרצונך
יש כבר, passport.
אני לא מבין איך אתה ניגש למודל לא דרך ה controller. כלומר מה בדיוק מבנה השרת אצלך.
אולי לא הסברתי מספיק.
המודל הוא אובייקט של sequelize שדרכו אפשר לקבל רשומות מה-DB. ובקונטרולר בד"כ אני מוסיף עוד לגיקה, למשל בדיקת גישה של המשתמש, או אם יש צורך לעשות פעולות בכל יצירה/מחיקה/עדכון של אובייקט.
הבעיה היא שאני לא רוצה שכל צורך חד פעמי יצטרך לגשת רק דרך הקונטרולר כי אז צריך מליון פונקציות/פרמטרים בקונטרולר.
אז לפעמים אני ניגש ישירות דרך sequelize, ואז זה עוקף את הלוגיקה שאני כותב בגישה דרך הקונטרולר. -
אם ככה אני לא מבין את שאלה א', בטח שזה טוב להעביר אובייקט קונטקסט שבתוכו יש מיכל לשפע נתונים זמניים שצריכים לעבור בין שכבה לאחרת.
בקשר לשאלה ב' מה זה נקרא "לא דרך המודל" מי כתב את הפונקציות הללו כמוfindById
ואיך זה עובד יפה וגמרי לכל הקונטרולרים? -
@dovid אמר בשאלות לגבי כתיבת אפליקציית שרת יציבה (בנוד):
בטח שזה טוב להעביר אובייקט קונטקסט שבתוכו יש מיכל לשפע נתונים זמניים שצריכים לעבור בין שכבה לאחרת
מצויין, זה מה שרציתי לשמוע.
(הגעתי לבסיס קוד קיים וזה לא היה ככה.)מי כתב את הפונקציות הללו כמו findById
אני כתבתי.
ואיך זה עובד יפה וגמרי לכל הקונטרולרים?
לא הבנתי
בגדול אני רואה שהשאלות לא ברורות מספיק. יש לי עוד המון שאלות כאלו על מבנה טוב אבל קשה לפרט הכל. כנראה שצריך פשוט שימוש חכמים.
-
@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.
האם עכשיו השאלה יותר מובנת?
-
@yossiz כעת הבנתי.
לדעתי חייבים לשלב, כלומר לתת גישה ישירה לDB בקונטרולר בשביל 10 אחוז מהמקרים,
ולהשתדל שב90 אחוז הקלאסיים יהיה פתרון גנרי.
אני אוחז שאסור להימנע מדרכים פשוטות באופן קיצוני, בגלל כללי תכנות ארוכי טווח. כי דרכים לא פשוטות זה אומר פי עשר כח אדם במקרה הטוב, ובמקרה הגרוע אלף עבירות תכנות אחרות.לגבי קונטרולר, ההגדרה ה"טהורה" שלו זה שצריך להיות שמה כמה שפחות דברים... כלומר זה אכן לא מוגדר, אבל תפקידו צריך להיות סוג של איש קשר בין יחידות שונות (קלט/לוגיקה/פלט).
(כעת חיפשתי שוב, ומצאתי את ההתפתלויות האלו... https://stackoverflow.com/a/1015853/1271037).