דילוג לתוכן הראשי
ניסיון מקצועי

הפיכת חוזי Swagger לשירותי BFF מוכנים ל-Production

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

מקור
UMTB Bank, Senior Backend & Platform Engineer
Tech Stack
NestJS · Node.js · TypeScript · Swagger/OpenAPI
Platform Engineering, Developer Experience (DevEx), פיתוח Backend,

אמל״ק

הבעיה
כל שירות backend-for-frontend חדש בבנק היה צריך את אותו קוד תשתית סביב חוזה API קפדני, עוד לפני שורת לוגיקה עסקית אחת. זה עלה זמן והסתכן בסטייה מהחוזה.
התרומה שלי
הייתי אחראי על רוב שכבת התשתית של ה-BFF ותרמתי כ-70% מבסיס הקוד שלה, כולל הפלטפורמה שמייצרת שירותי NestJS ממפרטי Swagger ואת תהליך היצירה מחדש ששומר על קוד מותאם.
תוצאה וראיות
יצירת שירות BFF חדש התקצרה מכארבעה ימים לפחות מארבע שעות, ירידה של כ-90%. הנתון מתייחס ליצירת השירות בלבד, לא לעבודה על ה-SDKs.
להעמקה בפרטים הטכניים

הבעיה

כל שירות backend-for-frontend חדש בפלטפורמה הבנקאית של בנק מזרחי-טפחות (UMTB) היה צריך את אותו קוד תשתית סביב חוזה API בנקאי קפדני: DTOs, controllers וקוד החיבור ביניהם. מפתח בנה את כל זה לפני שכתב שורת לוגיקה עסקית אחת. העבודה החוזרת עלתה זמן בכל שירות, והשאירה מקום לסטייה של קוד התשתית מהחוזה שלו.

הקשר

הצטרפתי אחרי שהיסודות הראשוניים של תשתית ה-BFF כבר היו במקום. אחר כך לקחתי אחריות על רוב השכבה הזו ותרמתי כ-70% מבסיס הקוד שלה. הפלטפורמה שירתה תהליכים בנקאיים עם הגדרות API קפדניות, מבוססות חוזה. ההגדרות האלה השתנו עם התפתחות מפרטי Swagger/OpenAPI.

אילוצים

  • החוזים היו קפדניים. הקוד שנוצר היה צריך להתאים למפרט Swagger/OpenAPI.
  • המפרטים השתנו עם הזמן. יצירה מחדש של שירות לא יכלה להרוס את הלוגיקה העסקית של מפתח.
  • מפתחים היו צריכים דרך מפורשת, מבוססת תבניות, לסמן אילו קבצים חייבים לשרוד יצירה מחדש בלי שינוי. לוגיקה עסקית של המפתח ו-interceptors מותאמים הם דוגמאות לכך.
  • הפלטפורמה הייתה צריכה לייצר שירותי NestJS פעילים, לא רק DTOs ושלדים.

התפקיד שלי

לקחתי אחריות על רוב שכבת התשתית של ה-BFF ותרמתי כ-70% מבסיס הקוד שלה. זה כולל יצירת שירותים, קונפיגורציה ושילוב דרישות compliance.

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

ארכיטקטורה וגישה

בכל שירות שנוצר יש קו ברור בין קוד שנוצר לקוד שבבעלות המפתח.

DTOs ו-controllers נוצרים ממפרט Swagger/OpenAPI. כל שירות תואם לחוזה שלו מעצם הדרך שבה הוא נוצר.

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

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

כל מה שמחוץ לגבול הזה נוצר מחדש מהמקורות העדכניים של הפלטפורמה. זה כולל DTOs ו-controllers שנוצרו, הגדרות Swagger שנצרכות, תבניות תשתית, וקונפיגורציית תלויות כמו package.json כשהמדיניות לא מכסה אותה.

SDKs משותפים של התשתית. ה-SDKs של Node.js ל-HTTP, ל-Kafka ול-Redis הם תשתית משותפת. יצירה מחדש עלולה היתה לדרוס אותם. ניהלתי אותם דרך הפלטפורמה כך ששרדו יצירה מחדש. מפתחים קיבלו שיפורי SDK כשיצרו שירות מחדש. הם לא התקינו חבילות מחדש ולא בנו שירותים ידנית.

החלטות מרכזיות

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

שיקולים ופשרות

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

תוצאות ואימות

יצירת שירות BFF חדש התקצרה מכארבעה ימים לפחות מארבע שעות. זו ירידה של כ-90%.

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

נתון ה-90% שייך ליצירת השירות. הוא לא מתאר את העבודה על ה-SDKs. התרומה של ה-SDKs הייתה איכותית: פיתוח ומסירה מהירים יותר של שירותים בנקאיים. לא נמדד עבורה נתון.

מה למדתי

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