بررسی Bad code smell ها: دلال یا Middle Man
اندازه‌ی قلم متن
تخمین مدت زمان مطالعه‌ی مطلب: دو دقیقه

دلال یا Middle man در دسته الگوهای «کدهایی بیش از اندازه وابسته به هم» قرار می‌گیرد. زمانیکه یک کلاس، تنها کاری را که انجام می‌دهد، هدایت فراخوانی به کلاس دیگری باشد، با این الگو مواجه هستیم. تشخیص این کد بد بو معمولا بسیار آسان است.  
به طور مثال:  
 public class ProductQuery 
    { 
        public dynamic GetProductsByCustomerId(int id) 
        { 
            return new ExpandoObject(); 
        } 
    } 
    public class CustomerQuery 
    { 
        private readonly ProductQuery _productQuery; 
  
        public CustomerQuery(ProductQuery productQuery) 
        { 
            _productQuery = productQuery; 
        } 
        public dynamic GetProducts(int customerId) 
        { 
            return _productQuery.GetProductsByCustomerId(customerId); 
        } 
    } 
    public static class Programm 
    { 
        static void Main(string[] args) 
        { 
            var query = new CustomerQuery(new ProductQuery()); 
            var products = query.GetProducts(1); 
        } 
    }
در کلاس ProductQuery، متدی برای دریافت تمامی محصولات مربوط به یک مشتری وجود دارد. در کلاس CustomerQuery نیز یک متد برای دریافت تمامی محصولات مشتری وجود دارد. در این مثال متد GetProducts در کلاس CustomerQuery را می‌توان «متد حسود» نیز نامید. این نوع استفاده از متد، «الگوی دلال» نیز است. زمانیکه تمامی متدهای یک کلاس به این صورت باشند، آن کلاس به عنوان دلال شناخته می‌شود.

چرا چنین بویی به راه می‌افتد  

معمولا به چند دلیل با این کد بد بو مواجه خواهیم شد: 
  • انتقال مسئولیت‌های یک کلاس به کلاسی دیگر به مرور زمان و تبدیل متدهای آن به هدایت کنندگان فراخوانی.
  • عدم تشخیص درست مسئولیت‌های یک کلاس و اجبار به افزودن هدایت کنندگان فراخوانی در کلاس‌های دیگر. این حالت معمولا زمانی اتفاق می‌افتد که یک کلاس، مسئولیت‌های زیادی داشته باشد و کلاس‌های مختلف، صرفا نیاز به هدایت فراخوانی به این کلاس را داشته باشند. 
  • عدم استفاده مناسب از الگوهای طراحی. 


روش‌های اصلاح این کد بد بو  

روش کلی برای اصلاح چنین بوی بدی، حذف متدها و کلاسهای هدایت کننده فراخوانی و تغییر تمامی استفاده کنندگان از آن‌ها است. در مثال بالا می‌توان متد GetProducts از کلاس CustomerQuery را حذف و تمامی فراخوانی‌های آن را به متد GetProductsByCustomerId از کلاس ProductQuery انتقال داد، یا بلعکس.

چه کدهایی دلال نیستند 

زمانیکه کلاس هدایت کننده فرخوانی به صورت عمدی ساخته شده باشد، معمولا با چنین الگویی روبرو نیستیم. مانند استفاده از الگوهای طراحی زیر: 
  • Chain of responsibility 
  • Decorator 
  • Proxy 
  • Adapter 
هر کدام از الگوهای طراحی ذکر شده در بالا به دلایل خاصی ایجاد می‌شوند و علارغم شباهت زیاد آن‌ها با کد بد بوی دلال، شرایط مربوط به کد بد بود را دارا نمی‌باشند و معمولا نیازی به اعمال تغییری در آن‌ها نیست. با مطالعه و بررسی دقیق الگوهای طراحی می‌توان از تشخیص اشتباه این الگوی بد جلوگیری کرد.  
  • #
    ‫۷ سال قبل، دوشنبه ۲۰ شهریور ۱۳۹۶، ساعت ۲۳:۰۹
    در الگوی mvvm و در کلاسهای view model امکان به وجود آمدن این نوع کدهای دلال وجود داره؟! در اینصورت چه راهکاری مناسبه؟ ممنون 
    • #
      ‫۷ سال قبل، دوشنبه ۲۰ شهریور ۱۳۹۶، ساعت ۲۳:۴۳
      View Model در MVVM شبیه به کنترلرها در MVC هستند. این‌ها بالاترین لایه برنامه هستند که با تزریق امکانات دیگر سرویس‌های برنامه به آن‌ها امکان استفاده‌ی نهایی از آن‌ها فراهم می‌شود. بنابراین این‌ها بله ... دلال سرویس‌های برنامه به رابط کاربری آن هستند، اما با مفهوم فوق یکی نیستند. کار کنترلرها یا ViewModelها مدیریت و سامان دهی درخواست‌ها و هدایت آن‌ها به سرویس‌های متناظر، گاهی از اوقات ترکیب چند سرویس با هم و ارائه‌ی یک پاسخ به مصرف کننده نهایی است. بنابراین این‌ها واسط بین View برنامه و Model هستند و مدیریت کننده‌ی تعاملات با برنامه.