۲۹ شهریور ۱۴۰۳

Techboy

اخبار و اطلاعات روز تکنولوژی

از استفاده از enum در لایه دامنه در سی شارپ خودداری کنید

مشکلات استفاده از انواع enumeration در لایه دامنه برنامه های دات نت و مزایای استفاده از انواع رکورد به جای آن را بدانید.

مشکلات استفاده از انواع enumeration در لایه دامنه برنامه های دات نت و مزایای استفاده از انواع رکورد به جای آن را بدانید.

هنگام کار بر روی برنامه‌ها، اغلب باید گروهی از ثابت‌ها را در منطق تجاری و حتی در لایه‌های دامنه نشان دهید. با این حال، باید از استفاده از انواع enumeration یا enums در لایه دامنه خودداری کنید و به جای آن از جایگزین هایی مانند انواع رکورد استفاده کنید.

چرا؟ در این مقاله، نکات منفی استفاده از enumerations در لایه دامنه را توضیح خواهیم داد.

یک پروژه برنامه کاربردی کنسول در ویژوال استودیو ایجاد کنید

ابتدا، اجازه دهید یک پروژه برنامه کاربردی کنسول NET Core در ویژوال استودیو ایجاد کنیم. با فرض اینکه Visual Studio 2022 در سیستم شما نصب شده است، مراحل ذکر شده در زیر را برای ایجاد یک پروژه برنامه کاربردی کنسول NET Core جدید دنبال کنید.

  1. Visual Studio IDE را راه اندازی کنید.
  2. روی “ایجاد پروژه جدید” کلیک کنید.
  3. در پنجره “ایجاد پروژه جدید”، “Console App (.NET Core)” را از لیست الگوهای نمایش داده شده انتخاب کنید.
  4. بعدی را کلیک کنید.
  5. در پنجره “پیکربندی پروژه جدید خود”، نام و مکان پروژه جدید را مشخص کنید.
  6. بعدی را کلیک کنید.
  7. در پنجره «اطلاعات اضافی» که در ادامه نشان داده شده است، «.NET 8.0 (پشتیبانی طولانی مدت)» را به عنوان نسخه چارچوبی که می خواهید استفاده کنید، انتخاب کنید.
  8. روی ایجاد کلیک کنید.

ما از این پروژه برنامه کاربردی کنسول NET 8 برای کار با نمونه‌های کد نشان داده شده در بخش‌های بعدی این مقاله استفاده خواهیم کرد.

مشکل enums چیست؟

در حالی که انواع شمارش می‌توانند انعطاف‌پذیری را در حفظ مجموعه‌ای از مقادیر ثابت در برنامه شما فراهم کنند، آنها اغلب ارتباط تنگاتنگی بین مدل دامنه و کدی که از آن استفاده می‌کند ایجاد می‌کنند، بنابراین توانایی شما را برای تکامل مدل دامنه محدود می‌کند.

API یادگیری عمیق Keras 3.0 از TensorFlow، PyTorch، Jax پشتیبانی می کند

مجموعه زیر را که برای تعریف نقش‌های کاربر و سرپرست استفاده می‌شود، در نظر بگیرید.

public enum Roles
{
    User,
    Administrator,
    Reviewer,
    SuperAdmin
}

همچنین می توانید از یک enum برای تعریف گروهی از ثابت ها همانطور که در قطعه کد زیر نشان داده شده است استفاده کنید.

public enum Roles
{
    User = 1,
    Administrator = 2,
    Reviewer = 3,
    SuperAdmin = 4
}

مشکل ۱: بوی کپسولاسیون

حالا، فرض کنید باید بدانید که آیا یک نقش خاص به نقش مدیر مربوط است یا خیر. قطعه کد زیر یک روش برنامه افزودنی به نام IsAdmin را نشان می دهد که بررسی می کند آیا یک نقش خاص یک Administrator یا SuperAdmin است.

public static class RolesExtensions
{
    public static bool IsAdmin(this Roles roles)
        => roles == Roles.Administrator ||
           roles == Roles.SuperAdmin;
}

این ما را با اولین مشکل استفاده از enums در لایه دامنه مواجه می‌کند. اگرچه می‌توانید با استفاده از روش‌های افزونه روی enum کار کنید، اما کد شما اصل کپسوله‌سازی را زیر پا می‌گذارد، زیرا منطق جستجوی مدل و مدلی که ایجاد کرده‌اید جدا هستند. به عبارت دیگر منطقی که مدل را بررسی می کند در یک کلاس نیست. این یک ضد الگو است و مدلی از این نوع اغلب به عنوان مدل کم خونی شناخته می شود.

مشکل ۲: کد اسپاگتی

یک مشکل دیگر با enums: ممکن است اغلب لازم باشد از ارسال‌های واضح در کد برنامه خود برای بازیابی مقداری از یک شمارش استفاده کنید. خط کد زیر این را نشان می دهد.

int role = (int)Roles.User;

بازیگران صریح رویکرد خوبی نیستند. آنها همیشه از نظر عملکرد پرهزینه هستند و به این معنی است که شما از انواع ناسازگار در برنامه خود استفاده کرده اید یا اینکه انواع به درستی تعریف نشده اند. استفاده از enums در لایه دامنه شما می‌تواند منجر به استفاده از کست‌های صریح در سراسر برنامه شود، کد را به هم ریخته و خواندن و نگهداری آن را سخت‌تر کند.

TypeScript 5.2 مدیریت منابع صریح را به ارمغان می آورد

مساله ۳: محدودیت های نامگذاری

به یاد داشته باشید، نمی توانید کاراکترهای فاصله را در نام ثابت های شمارش در سی شارپ قرار دهید. بنابراین، کد زیر در سی شارپ معتبر نیست.

public enum Roles
{
    Admin,
    Super Admin
}

برای غلبه بر این محدودیت می توانید از ویژگی ها استفاده کنید.

using System.ComponentModel.DataAnnotations;
public enum Roles
{
    Admin,
    [Display(Name = "Super Admin")]
    SuperAdmin
}

با این حال، زمانی که برنامه شما نیاز به پشتیبانی از مناطق مختلف داشته باشد، با مشکل مواجه خواهید شد.

به جای enums از انواع رکورد استفاده کنید

یک جایگزین بهتر استفاده از انواع ضبط است. همانطور که در قطعه کد زیر نشان داده شده است، می توانید از انواع رکوردها برای ایجاد یک نوع تغییرناپذیر استفاده کنید.

public record Roles(int Id)
{
    public static Roles User { get; } = new(1);
    public static Roles Administrator { get; } = new(2);
    public static Roles Reviewer { get; } = new(3);
    public static Roles SuperAdmin { get; } = new(4);
}

یک شیء تغییرناپذیر شیئی است که پس از نمونه سازی، نمی توان آن را تغییر داد. از این رو رکوردها دارای ایمنی ذاتی نخ و مصونیت نسبت به شرایط مسابقه هستند. اشیاء تغییرناپذیر همچنین کد شما را خواناتر و نگهداری آسان‌تر می‌کنند.

توسعه وب تمام پشته با HTMX و Bun، قسمت 1: Elysia و MongoDB

یک مزیت قابل توجه استفاده از انواع رکورد، حفظ کپسولاسیون است زیرا هر روش پسوندی که بنویسید می تواند بخشی از خود مدل باشد. به یاد داشته باشید، شما نمی توانید هیچ روشی را در یک enum قرار دهید.

علاوه بر این، همانطور که کد زیر نشان می دهد، سوابق ارائه نام های معنی دار را آسان می کند.

public record Roles(int Id, string Name)
{
    public static Roles User { get; } = new(1, "User");
    public static Roles Administrator { get; } = new(2, "Administrator");
    public static Roles Reviewer { get; } = new(3, "Reviewer");
    public static Roles SuperAdmin { get; } = new(4, "Super Admin");
    public override string ToString() => Name;
}

اکنون می‌توانید به ثابت‌های رکورد Roles به همان روشی که می‌توانید به ثابت‌های شمارش دسترسی داشته باشید، دسترسی پیدا کنید.

Roles admin = Roles.Administrator;
Roles user = Roles.User;
Roles reviewer = Roles.Reviewer;
Roles superAdmin = Roles.SuperAdmin;

هنگامی که متد ToString() را فراخوانی می کنید، همانطور که در شکل ۱ نشان داده شده است، نام ثابت در پنجره کنسول نمایش داده می شود.

ثابت رکورد

شکل ۱: نمایش نام ثابت رکورد در پنجره کنسول.

به طور متناوب، می توانید به جای یک نوع رکورد از یک کلاس استفاده کنید و سپس ثابت های مورد نیاز خود را تعریف کنید. با این حال، من همیشه یک نوع رکورد را به دلایل عملکرد ترجیح می دهم. انواع رکورد انواع سبک وزن هستند که به دلیل سرعت آنها بسیار بیشتر از کلاس ها است. یک رکورد به خودی خود یک نوع مرجع است، اما از بررسی برابری داخلی خود استفاده می کند، که بر اساس مقدار و نه با مرجع بررسی می کند.