نمایش نتایج 1 تا 3 از 3

نام تاپیک: کد را در کجا تعریف کنم؟

  1. #1

    کد را در کجا تعریف کنم؟

    سلام دوستان .

    یک سئوال در این رابطه داشتم که طبق در نظر گرفتن کدنویسی بصورت ماژولاریتی و اصول solid ، دقیق متوجه نشدم که سناریویی که در زیر میگم را در چه ماژولی تعریف کنم .


    من دو موضوع و سناریو دارم .
    قبل از همه ، موضوع درباره ی لایه ی دسترسی داده و ماژول با الگوی طراحی Repository هست .
    مثلا موجودیت های زیر را (در زبان سی شارپ) داریم :



    public class UserAccountEntity
    {
    public int Id { get; set; }
    public string UserName { get; set; }
    public string Password { get; set; }
    public string FullName { get; set; }
    public virtual ICollection<TruckEntity> TruckEntities { get; set; }
    }



    public class TruckEntity
    {
    public int Id { get; set; }
    public string PlaqueNumber { get; set; }
    }






    =========================


    موضوع اول :
    در Repository هم متد جنریک Edit را برای به روزرسانی و ویرایش را نوشتم .
    اما این متد Edit ، برای یک جدول خاص طراحی نشد . بنابراین نمیتونه Navigation Property یا Navigation Collection Property هایی (مثل پروپرتی TruckEntities در کد بالا) که به جدول دیگه مربوط هستند را پیدا کنه (مثلا اگر جدول UserAccountEntity را بخواهیم ویرایش کنیم ، نمیتونه رکوردهایی که از قبل که در TruckEntity بودند و مربوط به اون رکورد از UserAccountEntity بودند را پیدا کنه) و حذف کنه .


    پس باید خودمان موقع به روزرسانی یک رکورد ، تمام رکوردهای مربوط به Navigation Property ها را پیدا و حذف کنیم و بعدش اون رکورد را به روزرسانی کنیم .


    البته راهکار دیگه و متد آماده ای هم فکر کنم ef core داشته باشه اما فعلا این طور میخوام در نظر بگیرم که برای به روزرسانی ، ابتدا باید همه ی رکوردهای مربوط به جداول Navigation Property یا Navigation Collection Property ای که در اون جدول هستند را بصورت دستی حذف کنم و سپس جدول مورد نظر را ویرایش کنم .


    حالا با در نظر گرفتن اصول solid و همچنین کدنویسی ماژولار ، این کدها را (کدهایی که قبل از فراخوانی متد Repository.Edit ، ابتدا تمام رکوردهای مربوط به Navigation Property یا Navigation Collection Property یی که مربوط به این رکورد از این جدول هستند را حذف میکنه و سپس متد Repository.Edit را فراخوانی میکنه) را کجا باید تعریف کرد؟


    اگر این کدها را در ماژول Repository تعریف کنم ، خوب ماژولاریتیِ ماژولِ Repository را پایین میاره . یعنی انتقال ماژولِ Repository را به برنامه های دیگه ، کم میکنه . چون کدش شخصی سازی میشه و فقط برای استفاده در فقط همون موجودیت میتونه استفاده بشه (و نه حتی در موجودیت های دیگه هم استفاده نمیشه ، چه برسه به برنامه های دیگه) .


    البته اگر از این روش برم (یعنی این کدها را در ماژول Repository تعریف کنم) ، ابتدا یک کلاس Repository ئه جنریک مینویسم که قابل انتقال به هر برنامه ای باشه و متدهاش را virtual میگیرم اما کلاس های فرزندش (که مثلا در اینجا میتونه TruckRepository و ... باشه) را فقط در همون برنامه استفاده میکنم که قابل انتقال نیست .
    مثلا متد Edit را در کلاس فرزندش (مثلا در کلاس TruckRepository) هم میشه override کرد که قبل از فراخوانی متد پدر ، اون کدهای حذف کردن مربوط به جداول مربوط به Navigation Property یا Navigation Collection Property را انجام بده .




    حالا اگر این کدها را در ماژول Repository ننویسم و بجایش ، درون ماژولی که از ماژول Repository داره استفاده میکنه ، تعریف کنم (یعنی درون ماژولی که از ماژول Repository و کلاس هاش شی میسازه ، تعریف کنم) ، در اون صورت خوبی اش اینه که ماژولاریتیِ ماژولِ Repository بالا میره و کل ماژول اش را میشه به هر برنامه ای منتقل کرد اما نمیدونم طبق اصل single responsibility در solid ، این کار درسته یا نه . چون کدهای حذف کردن (قبل از ویرایش) و کلا منطق دسترسی داده (Data Access Logic) ، مربوط به ماژول Repository و کلا مربوط به ماژول دسترسی داده هست که این کدهاش ، از این ماژول (ئه Repository) خارج شده .


    در مقاله ی زیر در مایکروسافت ، چند جا اشاره کرد که وظیفه ی Repository ، منطق دسترسی داده هست :

    Implementing the Repository and Unit of Work Patterns in an ASP.NET MVC Application (9 of 10) | Microsoft Learn



    "You can implement a single repository for all entity types, or one for each type. If you implement one for each type, you can use separate classes, a generic base class and derived classes, or an abstract base class and derived classes.


    You can include business logic in your repository or restrict it to data access logic."


    ======================


    موضوع دوم :
    مثلا فرض کنید که در یک موجودیت خاص ، میخواهیم طبق چند فیلد ، فیلتر کنیم .
    مثلا در موجودیت UserAccountEntity ، میخواهیم طبق چند فیلد UserName و FullName فیلتر کنیم .
    این هم معمولا بصورت خاص برای یک موجودیت خاص هست که کدش قابل انتقال به برنامه (یا موجودیت) دیگه نیست .


    کد این را هم کجا تعریف کنیم؟ (درون ماژول Repository تعریف کنیم یا درون ماژولی که از Repository داره استفاده میکنه و ازش شی میسازه ، تعریف کنیم) ؟
    کلا یک توضیحی میدین که از کجا متوجه بشم که این نوع کدها را در کجا تعریف کنیم؟


    ضمنا مایکروسافت در همون مقاله ، دو کد زیر را نوشت :



    public class StudentController : Controller
    {
    public ViewResult Index(string sortOrder, string currentFilter, string searchString, int? page)
    {
    ViewBag.CurrentSort = sortOrder;
    ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
    ViewBag.DateSortParm = sortOrder == "Date" ? "date_desc" : "Date";


    if (searchString != null)
    {
    page = 1;
    }
    else
    {
    searchString = currentFilter;
    }
    ViewBag.CurrentFilter = searchString;


    var students = from s in studentRepository.GetStudents()
    select s;
    if (!String.IsNullOrEmpty(searchString))
    {
    students = students.Where(s => s.LastName.ToUpper().Contains(searchString.ToUpper ())
    || s.FirstMidName.ToUpper().Contains(searchString.ToU pper()));
    }
    switch (sortOrder)
    {
    case "name_desc":
    students = students.OrderByDescending(s => s.LastName);
    break;
    case "Date":
    students = students.OrderBy(s => s.EnrollmentDate);
    break;
    case "date_desc":
    students = students.OrderByDescending(s => s.EnrollmentDate);
    break;
    default: // Name ascending
    students = students.OrderBy(s => s.LastName);
    break;
    }


    int pageSize = 3;
    int pageNumber = (page ?? 1);
    return View(students.ToPagedList(pageNumber, pageSize));
    }
    }






    و همچنین :





    public class GenericRepository<TEntity> where TEntity : class
    {
    public virtual IEnumerable<TEntity> Get(
    Expression<Func<TEntity, bool>> filter = null,
    Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
    string includeProperties = "")
    {
    IQueryable<TEntity> query = dbSet;


    if (filter != null)
    {
    query = query.Where(filter);
    }


    foreach (var includeProperty in includeProperties.Split
    (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
    {
    query = query.Include(includeProperty);
    }


    if (orderBy != null)
    {
    return orderBy(query).ToList();
    }
    else
    {
    return query.ToList();
    }
    }
    }




    که هر دو منطق دسترسی داده (Data Access Logic) هستند اما یکی را در ماژولی که از Repository استفاده میکرد ، تعریف کرد (در کلاس StudentController تعریف کرد) و یکی دیگه را در همون ماژول Repository تعریف کرد .
    با اونکه خودش در اون متن در اون مقاله گفته بود که منطق دسترسی داده (و حتی بخشی از منطق تجاری) میتونه در Repository تعریف بشه .



    لطفا دلیل تون را برای جواب هم بگید .


    با تشکر ازتون .

  2. #2
    کاربر دائمی آواتار ROSTAM2
    تاریخ عضویت
    اسفند 1390
    محل زندگی
    فارس
    پست
    1,646

    نقل قول: کد را در کجا تعریف کنم؟

    نقل قول نوشته شده توسط SajjadKhati مشاهده تاپیک
    سلام دوستان .

    یک سئوال در این رابطه داشتم که طبق در نظر گرفتن کدنویسی بصورت ماژولاریتی و اصول solid ، دقیق متوجه نشدم که سناریویی که در زیر میگم را در چه ماژولی تعریف کنم .


    من دو موضوع و سناریو دارم .
    قبل از همه ، موضوع درباره ی لایه ی دسترسی داده و ماژول با الگوی طراحی Repository هست .
    مثلا موجودیت های زیر را (در زبان سی شارپ) داریم :



    public class UserAccountEntity
    {
    public int Id { get; set; }
    public string UserName { get; set; }
    public string Password { get; set; }
    public string FullName { get; set; }
    public virtual ICollection<TruckEntity> TruckEntities { get; set; }
    }



    public class TruckEntity
    {
    public int Id { get; set; }
    public string PlaqueNumber { get; set; }
    }






    =========================


    موضوع اول :
    در Repository هم متد جنریک Edit را برای به روزرسانی و ویرایش را نوشتم .
    اما این متد Edit ، برای یک جدول خاص طراحی نشد . بنابراین نمیتونه Navigation Property یا Navigation Collection Property هایی (مثل پروپرتی TruckEntities در کد بالا) که به جدول دیگه مربوط هستند را پیدا کنه (مثلا اگر جدول UserAccountEntity را بخواهیم ویرایش کنیم ، نمیتونه رکوردهایی که از قبل که در TruckEntity بودند و مربوط به اون رکورد از UserAccountEntity بودند را پیدا کنه) و حذف کنه .


    پس باید خودمان موقع به روزرسانی یک رکورد ، تمام رکوردهای مربوط به Navigation Property ها را پیدا و حذف کنیم و بعدش اون رکورد را به روزرسانی کنیم .


    البته راهکار دیگه و متد آماده ای هم فکر کنم ef core داشته باشه اما فعلا این طور میخوام در نظر بگیرم که برای به روزرسانی ، ابتدا باید همه ی رکوردهای مربوط به جداول Navigation Property یا Navigation Collection Property ای که در اون جدول هستند را بصورت دستی حذف کنم و سپس جدول مورد نظر را ویرایش کنم .


    حالا با در نظر گرفتن اصول solid و همچنین کدنویسی ماژولار ، این کدها را (کدهایی که قبل از فراخوانی متد Repository.Edit ، ابتدا تمام رکوردهای مربوط به Navigation Property یا Navigation Collection Property یی که مربوط به این رکورد از این جدول هستند را حذف میکنه و سپس متد Repository.Edit را فراخوانی میکنه) را کجا باید تعریف کرد؟


    اگر این کدها را در ماژول Repository تعریف کنم ، خوب ماژولاریتیِ ماژولِ Repository را پایین میاره . یعنی انتقال ماژولِ Repository را به برنامه های دیگه ، کم میکنه . چون کدش شخصی سازی میشه و فقط برای استفاده در فقط همون موجودیت میتونه استفاده بشه (و نه حتی در موجودیت های دیگه هم استفاده نمیشه ، چه برسه به برنامه های دیگه) .


    البته اگر از این روش برم (یعنی این کدها را در ماژول Repository تعریف کنم) ، ابتدا یک کلاس Repository ئه جنریک مینویسم که قابل انتقال به هر برنامه ای باشه و متدهاش را virtual میگیرم اما کلاس های فرزندش (که مثلا در اینجا میتونه TruckRepository و ... باشه) را فقط در همون برنامه استفاده میکنم که قابل انتقال نیست .
    مثلا متد Edit را در کلاس فرزندش (مثلا در کلاس TruckRepository) هم میشه override کرد که قبل از فراخوانی متد پدر ، اون کدهای حذف کردن مربوط به جداول مربوط به Navigation Property یا Navigation Collection Property را انجام بده .




    حالا اگر این کدها را در ماژول Repository ننویسم و بجایش ، درون ماژولی که از ماژول Repository داره استفاده میکنه ، تعریف کنم (یعنی درون ماژولی که از ماژول Repository و کلاس هاش شی میسازه ، تعریف کنم) ، در اون صورت خوبی اش اینه که ماژولاریتیِ ماژولِ Repository بالا میره و کل ماژول اش را میشه به هر برنامه ای منتقل کرد اما نمیدونم طبق اصل single responsibility در solid ، این کار درسته یا نه . چون کدهای حذف کردن (قبل از ویرایش) و کلا منطق دسترسی داده (Data Access Logic) ، مربوط به ماژول Repository و کلا مربوط به ماژول دسترسی داده هست که این کدهاش ، از این ماژول (ئه Repository) خارج شده .


    در مقاله ی زیر در مایکروسافت ، چند جا اشاره کرد که وظیفه ی Repository ، منطق دسترسی داده هست :

    Implementing the Repository and Unit of Work Patterns in an ASP.NET MVC Application (9 of 10) | Microsoft Learn



    "You can implement a single repository for all entity types, or one for each type. If you implement one for each type, you can use separate classes, a generic base class and derived classes, or an abstract base class and derived classes.


    You can include business logic in your repository or restrict it to data access logic."


    ======================


    موضوع دوم :
    مثلا فرض کنید که در یک موجودیت خاص ، میخواهیم طبق چند فیلد ، فیلتر کنیم .
    مثلا در موجودیت UserAccountEntity ، میخواهیم طبق چند فیلد UserName و FullName فیلتر کنیم .
    این هم معمولا بصورت خاص برای یک موجودیت خاص هست که کدش قابل انتقال به برنامه (یا موجودیت) دیگه نیست .


    کد این را هم کجا تعریف کنیم؟ (درون ماژول Repository تعریف کنیم یا درون ماژولی که از Repository داره استفاده میکنه و ازش شی میسازه ، تعریف کنیم) ؟
    کلا یک توضیحی میدین که از کجا متوجه بشم که این نوع کدها را در کجا تعریف کنیم؟


    ضمنا مایکروسافت در همون مقاله ، دو کد زیر را نوشت :



    public class StudentController : Controller
    {
    public ViewResult Index(string sortOrder, string currentFilter, string searchString, int? page)
    {
    ViewBag.CurrentSort = sortOrder;
    ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "name_desc" : "";
    ViewBag.DateSortParm = sortOrder == "Date" ? "date_desc" : "Date";


    if (searchString != null)
    {
    page = 1;
    }
    else
    {
    searchString = currentFilter;
    }
    ViewBag.CurrentFilter = searchString;


    var students = from s in studentRepository.GetStudents()
    select s;
    if (!String.IsNullOrEmpty(searchString))
    {
    students = students.Where(s => s.LastName.ToUpper().Contains(searchString.ToUpper ())
    || s.FirstMidName.ToUpper().Contains(searchString.ToU pper()));
    }
    switch (sortOrder)
    {
    case "name_desc":
    students = students.OrderByDescending(s => s.LastName);
    break;
    case "Date":
    students = students.OrderBy(s => s.EnrollmentDate);
    break;
    case "date_desc":
    students = students.OrderByDescending(s => s.EnrollmentDate);
    break;
    default: // Name ascending
    students = students.OrderBy(s => s.LastName);
    break;
    }


    int pageSize = 3;
    int pageNumber = (page ?? 1);
    return View(students.ToPagedList(pageNumber, pageSize));
    }
    }






    و همچنین :





    public class GenericRepository<TEntity> where TEntity : class
    {
    public virtual IEnumerable<TEntity> Get(
    Expression<Func<TEntity, bool>> filter = null,
    Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
    string includeProperties = "")
    {
    IQueryable<TEntity> query = dbSet;


    if (filter != null)
    {
    query = query.Where(filter);
    }


    foreach (var includeProperty in includeProperties.Split
    (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
    {
    query = query.Include(includeProperty);
    }


    if (orderBy != null)
    {
    return orderBy(query).ToList();
    }
    else
    {
    return query.ToList();
    }
    }
    }




    که هر دو منطق دسترسی داده (Data Access Logic) هستند اما یکی را در ماژولی که از Repository استفاده میکرد ، تعریف کرد (در کلاس StudentController تعریف کرد) و یکی دیگه را در همون ماژول Repository تعریف کرد .
    با اونکه خودش در اون متن در اون مقاله گفته بود که منطق دسترسی داده (و حتی بخشی از منطق تجاری) میتونه در Repository تعریف بشه .



    لطفا دلیل تون را برای جواب هم بگید .


    با تشکر ازتون .
    سلام
    بنظر من زیادی شلوغش کردی.
    برای هر کاری می خوای Query بنویس یا از LINQ استفاده کن. حالا تعریف کلاس دیگه اختیاریه....

    ذخیره سازی فایل در دیتابیس - لیست پخش (aparat.com)

    System.Windows.Media.MediaPlayer - لیست پخش (aparat.com)
    آخرین ویرایش به وسیله ROSTAM2 : پنج شنبه 30 آذر 1402 در 05:20 صبح

  3. #3

    نقل قول: کد را در کجا تعریف کنم؟

    نقل قول نوشته شده توسط ROSTAM2 مشاهده تاپیک
    سلام
    بنظر من زیادی شلوغش کردی.
    برای هر کاری می خوای Query بنویس یا از LINQ استفاده کن. حالا تعریف کلاس دیگه اختیاریه....

    ذخیره سازی فایل در دیتابیس - لیست پخش (aparat.com)

    System.Windows.Media.MediaPlayer - لیست پخش (aparat.com)
    سلام
    خیلی ممنون .
    احتمالا منظورم را خوب متوجه نشدید .
    اونها کدهای من نیستن . کدهای مایکروسافت هستن .

    سئوال ام درباره ی solid و تعریف کد در چه مکانی بود .
    تشکر

تاپیک های مشابه

  1. تقویم شمسی با امکان تعریف کردن روز های تعطیل
    نوشته شده توسط nicolas1390 در بخش کامپوننت های سایر شرکت ها، و توسعه کامپوننت
    پاسخ: 9
    آخرین پست: چهارشنبه 14 آذر 1397, 13:25 عصر
  2. راهنمایی در مورد تعریف تعداد ستون های بیشتر در اکسس 2003
    نوشته شده توسط unforgiven در بخش مطالب مرتبط با بانکهای اطلاعاتی در VB6
    پاسخ: 4
    آخرین پست: یک شنبه 17 بهمن 1395, 18:42 عصر
  3. پاسخ: 6
    آخرین پست: دوشنبه 04 اسفند 1393, 22:14 عصر
  4. پاسخ: 5
    آخرین پست: سه شنبه 18 تیر 1392, 11:56 صبح
  5. پاسخ: 2
    آخرین پست: جمعه 17 شهریور 1391, 07:03 صبح

قوانین ایجاد تاپیک در تالار

  • شما نمی توانید تاپیک جدید ایجاد کنید
  • شما نمی توانید به تاپیک ها پاسخ دهید
  • شما نمی توانید ضمیمه ارسال کنید
  • شما نمی توانید پاسخ هایتان را ویرایش کنید
  •