صادقانه، نوشتن کلاسهای عالی که قابل پیکربندی مجدد هم باشند خیلی دشوار و سخت نیست. اما اگر در کد نویسی به روشهای خاصی عادت کردین، ممکنه که اینطور نباشه.
بهترین راه برای تبدیل یک کلاس موجود به یک کلاس قابل تنظیم، اینه که ابتدا منطق رو به کلاسهای جداگانه منتقل کنیم و سپس قسمت Hardcode شده برنامه رو به سازنده یا آرگومان های متد منتقل کنیم.
در این مقاله از GitHub Gist استفاده شده است و لود شدن قسمت مربوط به کد ها ممکن است کمی زمانبر باشد
قبل از اینکه وارد کار بشیم و یه نمونه انجام بدیم بیاید ببینیم درباره چی داریم صحبت میکنیم.
قبل از اینکه وقت خودتون رو صرف refactoring کلاس موجود به کلاس قابل پیکربندی بکنید لازمه که بدونید با این کار چه چیزی بدست میارید.
استفاده از کلاسی که قابلیت پیکربندی داشته باشه خیلی آسونه و قابل توسعه است.به شکل احمقانه ای ساده است. و بزرگترین نقطه عطف اون اینه که قابل تست هم هست.
در اینجا خلاصه ای از کلاس هایی که با آنها سرو کار داریم ، آورده شده است.
شما یک کلاس OrderProcessor با یک متد ProcessOrder دارید.
بعد، یک کلاس پایه Order و سه زیر کلاسVirtualOrder ، ServiceOrder ، ShippingOrder وجود دارد.
درک کلاس Order کاملا غیر ضروری است. با فکر کردن در مورد نحوه اجرای اون منحرف نشید. فقط همین اندازه بدونید که دو تا properties به نام های Name و Price دارد.
زمان اجرای اون یک دقیقه طول کشید. کار هم میکنه. مسلما تو خوشحالی. مدیرت هم خوشحاله. مشتری شما هم خوشحاله.چی از این بهتر!
اما این خیلی داغونه.
این به نظرم میتونه یک Switch باشه. اگر این اولین فکر شماست، شما بر جنبه های کاملاً بی ربط توسعه نرم افزار تمرکز کردید.
بهتر البته یک مفهوم ذهنی است. اگر مطمئن باشید (که نیستید) این کلاس هرگز تغییر نخواهد کرد (که تغییر خواهد کرد) ، این ممکن است یک پیاده سازی عالی باشد (که اینگونه نیست).
من و شما در حال بازسازی این آشفتگی به یک کلاس منطقی و قابل تنظیم هستیم. بدون هیچ گونه تلاش زیادی.
ما این کلاس رو با با این سه ویژگی بهترش میکنیم.
خوانایی (Readability):خوانایی متد های این کلاس به طرز وحشتناکی است.
نگهداشت پذیری (Maintainability): اگر نیاز دارید که بخش "ServiceOrder" را اصلاح کنید، این کار را در جایی انجام خواهید داد که توسط کد غیر مرتبط احاطه شدهاست. همچنین، اگر برنامه نویسان دیگر روی همان کلاس مشغول به کار باشند، احتمالا با اختلافات ادغام مواجه می شوید.
انعطاف پذیری (Flexibility): سفارش جدیدی اضافه می شود؟ اگر نیاز دارید ، باید چیز دیگری اضافه کنید. من مطمئن هستم که شما قبلاً می دانید که این کار بد و نقض آشکار Open / Closed است.
معمولا چند تکرار برای refactor یک کلاس شلوغ و نامرتب طول میکشد. اول، ما در حال بهبود خوانایی هستیم. اگر غیرقابل خواندن باشد، دستیابی به یک کلاس بسیار خوب و انعطافپذیر دشوار است.
خلاص شدن از شر if-else اولین قدم عالی است.
خواندن متد ProcessOrder بسیار ساده تر شده است و اکنون فقط یک کار واحد انجام می دهد.
ما if-else نامطبوع را گرفته و آن را با یک dictionary جایگزین کرده ایم. همچنین اگر نوع سفارش جدیدی ارائه شود ، نیازی نیست که آن را به صورت دستی در دو مکان اضافه کنیم.
ما به راحتی می توانیم در این نقطه متوقف شویم. شما قبلاً کلاس را خیلی ساده تر کرده اید. اما هنوز دقیقاً به "ساده احمقانه" نرسیده اید. این هدف نهایی ما است.
در حال حاضر، کلاس ما هنوز درباره نحوه پردازش هر نوع آگاهی دارد.
در این حالت ، دستیابی به قابلیت نگهداری عبارت است از تجزیه مجدد پیاده سازی های عملکرد خارج از کلاس پردازنده و در کلاس های خود.
این بازسازی مجدد فوق العاده ساده به ما امکان می دهد تا هر پردازش را به صورت دقیق انجام دهیم. دیگر نیازی نیست که کل OrderProcessor را "new" کنیم تا ببینیم مثلاً یک سفارش به درستی پردازش می شود.
مطمئناً ، آزمایش واحد در این مرحله آسان است. اما هنوز لازم است که سه بار متد ProcessOrder را امتحان کنید ، فقط مطمئن شوید که به درستی کار می کند.
برای هر نوع سفارش جدید، باید همان متد را با یک مورد دیگر تست کنید. این مطمئنا یک code smell است.
آخرین refactoring شما قصد دارد که این کلاس processor را به طرز شگفت آوری ساده کند. شما به سادگی این dictionary را به یک وابستگی صریح تبدیل میکنید.
خیلی سبک خیلی ساده. بسیار ساده برای تست. هنگامی که کد شما به طور ناگهانی ساده احمقانه می شود ، می دانید که به سطح انتزاع درستی رسیده اید. این یکی از آن مواقع است. تبریک می گویم
اما، باز هم برای اندازهگیری خوب، من یک آزمایش ساده انجام دادم. ۱ میلیون تکرار در کلاس non-refactored - نسبت به کلاس انعطافپذیر، فراخوانی متد سفارش فرآیند برای هر نوع سفارش.
خودت تصمیم بگیر که اون شمارهها چقدر وحشتناکه
منبع : Nicklas Millard