אפליקציית דמו אחד ועוד אחד פיתוח תוכנה לוגו
מצגת 02

הלוגיקה העסקית
BusinessLogicLayer

הישויות, ההגדרות והכלים המשותפים — הכול בלי לדעת שקיים דפדפן.

מה תפקיד השכבה?

  • כאן חיות הישויות (‏Car, ‏Student…) וכללי העסק שלהן.
  • יורשת מ-Record של שכבת הנתונים — ולכן כל ישות כבר יודעת להישמר ולהיטען.
  • אסור לה להכיר UI או HTTP: אין HttpContext, אין HTML, אין Session.
  • בזכות זה אותה BLL משרתת אתר, אפליקציית MAUI, ‏Job לילי ובדיקות.
Web / MAUI / Job UI (גנרי) BLL DAL + DB

ישות עסקית = מחלקה קטנה

public class Student : Record
{
    [Column(Size = 100)] public string FirstName { get; set; }
    [Column(Size = 100)] public string LastName  { get; set; }
    [Column(Size = 20)]  public string IdNumber  { get; set; }
    [Column] public DateTime BirthDate  { get; set; }
    [Column] public int    Grade        { get; set; }
    [Column] public double Average      { get; set; }
    [Column] public bool   IsActive     { get; set; }
    [Column(Size = 255)] public string Picture { get; set; }
}
  • שדות = עמודות. שום דבר מעבר.
  • לוגיקה עסקית (חישוב ממוצע, ולידציה של ת"ז) מתווספת כמתודות על אותה מחלקה.
  • קשר לישות אחרת? תכונה מטיפוס הישות — נשמרת אוטומטית כ-BIGINT של ה-ID שלה.

‏Settings — קונפיגורציה שחיה ב-DB

// קריאה (מטמון בזיכרון, נטען פעם אחת בעליית האפליקציה):
string url = Settings.Val["MeshulamUrl"];

// כתיבה:
await Settings.SetAsync("MeshulamUrl", "https://...");

// זריעת ברירות מחדל — כל פרויקט דורס את CreateAsync:
public override async Task CreateAsync()
{
    await base.CreateAsync();
    await AddAsync("MeshulamUrl", "כתובת סליקה", "https://sandbox...");
}
  • למה DB ולא appsettings.json? כי אפשר לשנות בזמן ריצה, לכל לקוח, בלי דיפלוי.
  • הזריעה אידמפוטנטית — רצה בכל עלייה, מוסיפה רק מפתחות חסרים.

‏Util — ארגז הכלים המשותף

  • תאריכים:DateString, ‏ToDate, חודשים עבריים ולועזיים, ‏Decode("תשע\"ו")=776.
  • ולידציה:IsValidTz (ספרת ביקורת), ‏IsPhone, ‏IsValidEmail.
  • טקסט:StripHTML, ‏CleanHiddenChars, ‏UrlEscape.
  • קבצים:Mime(), ולידציית סיומות, ‏Compress/Decompress (GZip).
  • אבטחה:ProtectAppState — הצפנת מצב האפליקציה שנשלח ללקוח.
  • רשת:SendHttpRequestAsync עם HttpClient משותף.

reuse-first: לפני שכותבים עזר חדש — בודקים שהוא לא כבר כאן.

ייצוא מסמכים — עברית כולל

  • מחלקת בסיס אחת: Exporter — מחזירה byte[]; הקונטרולר עוטף ב-File(...).
  • Excel ‏(NPOI) — גיליון RTL אמיתי; ‏Word ‏(OpenXML) — טבלאות BiDi.
  • PDF ‏(MigraDoc) — פונט מוטמע בקובץ ה-DLL ו-FlipHebrew שמסדר עברית ויזואלית.
Exporter exporter = new ExcelExporter("Students.xlsx", rtl: true);
exporter.AddTable(dataTable);
return File(exporter.GetBytes(), exporter.ContentType, exporter.FileName);

כללי הזהב של השכבה

  • אסינכרוני עד הסוף — מתודה שנוגעת ב-DB מחזירה Task.
  • בלי תלות ב-UI — מה שצריך נתוני-סביבה מקבל אותם כפרמטר.
  • ישויות רזות; לוגיקה משותפת עולה ל-Util או למחלקת בסיס.
  • Settings ל-DB, לא לקבצי קונפיגורציה.
  • מה שנכון לכל הפרויקטים — מתוקן קודם כאן, בתבנית.