۱۳۹۰/۰۷/۱۷

آشنايي با Refactoring - قسمت 6


در ادامه بحث «حذف كدهاي تكراري»، روش Refactoring ديگري به نام "Extract Superclass" وجود دارد كه البته در بين برنامه نويس‌هاي دات نت به نام Base class بيشتر مشهور است تا Superclass. هدف آن هم انتقال كدهاي تكراري بين چند كلاس، به يك كلاس پايه و سپس ارث بري از آن مي‌باشد.

يك مثال:
در WPF و Silverlight جهت مطلع سازي رابط كاربري از تغييرات حاصل شده در مقادير داده‌ها، نياز است كلاس مورد نظر، اينترفيس INotifyPropertyChanged را پياده سازي كند:

using System.ComponentModel;

namespace Refactoring.Day6.ExtractSuperclass.Before
{
    public class User : INotifyPropertyChanged
    {
        string _name;
        public string Name
        {
            get { return _name; }
            set
            {
                if (_name == value) return;
                _name = value;
                raisePropertyChanged("Name");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        void raisePropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler == null) return;
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}


و نكته‌ي مهم اين است كه اگر 100 كلاس هم داشته باشيد، بايد اين كدهاي تكراري اجباري مرتبط با raisePropertyChanged را در آن‌ها قرار دهيد. به همين جهت مرسوم است براي كاهش حجم كدهاي تكراري، قسمت‌هاي تكراري كد فوق را در يك كلاس پايه قرار مي‌دهند:

using System.ComponentModel;

namespace Refactoring.Day6.ExtractSuperclass.After
{
    public class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected void RaisePropertyChanged(string propertyName)
        {
            var handler = PropertyChanged;
            if (handler == null) return;
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

و سپس از آن ارث بري مي‌كنند:

namespace Refactoring.Day6.ExtractSuperclass.After
{
    public class User : ViewModelBase
    {
        string _name;
        public string Name
        {
            get { return _name; }
            set
            {
                if (_name == value) return;
                _name = value;
                RaisePropertyChanged("Name");
            }
        }
    }
}


به اين ترتيب اين كلاس پايه در ده‌ها و صدها كلاس قابل استفاده خواهد بود، بدون اينكه مجبور شويم مرتبا يك سري كد تكراري «اجباري» را copy/paste كنيم.

مثالي ديگر:
اگر با ORM هاي Code first كار كنيد، نياز است تا ابتدا طراحي كار توسط كلاس‌هاي ساده دات نتي انجام شود؛ كه اصطلاحا به آن‌ها POCO يا Plain old CLR objects يا Plain old .NET Classes هم گفته مي‌شود. در بين اين كلاس‌ها، متداول است كه يك سري از خصوصيات، تكراري و مشترك باشد؛ مثلا تمام كلاس‌ها تاريخ ثبت ركورد را هم داشته باشند به همراه نام كاربر و مشخصاتي از اين دست. اينجا هم براي حذف كدهاي تكراري، يك Base class طراحي مي‌شود: (+)