۱۳۹۰/۰۸/۰۵

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



قبلا در مورد تبديل switch statement به الگوي استراتژي مطلبي را در اين سايت مطالعه كرده‌ايد (^) و بيشتر مربوط است به حالتي كه داخل هر يك از case هاي يك switch statement چندين و چند سطر كد و يا فراخواني يك تابع وجود دارد. حالت ساده‌تري هم براي refactoring يك عبارت switch وجود دارد و آن هم زماني است كه هر case، تنها از يك سطر تشكيل مي‌شود؛ مانند:

namespace Refactoring.Day12.RefactoringSwitchStatement.Before
{
    public class Translator
    {
        public string ToPersian(string englishWord)
        {
            switch (englishWord)
            {
                case "zero":
                    return "صفر";
                case "one":
                    return "يك";
                default:
                    return string.Empty;
            }
        }
    }
}

در اينجا مي‌توان از امكانات ساختار داده‌هاي توكار دات نت استفاده كرد و اين switch statement را به يك dictionary تبديل نمود:

using System.Collections.Generic;

namespace Refactoring.Day12.RefactoringSwitchStatement.After
{
    public class Translator
    {
        IDictionary<string, string> Words = new Dictionary<string, string>
        {
            { "zero", "صفر" },
            { "one", "يك" }
        };

        public string ToPersian(string englishWord)
        {
            string persianWord;
            if (Words.TryGetValue(englishWord, out persianWord))
            {
                return persianWord;
            }

            return string.Empty;
        }
    }
}

همانطور كه ملاحظه مي‌كنيد هر case به يك key و هر return به يك value در Dictionary تعريف شده، تبديل گشته‌اند. در اينجا هم بهتر است از متد TryGetValue جهت دريافت مقدار كليدها استفاده شود؛ زيرا در صورت فراخواني يك Dictionary با كليدي كه در آن موجود نباشد يك استثناء بروز خواهد كرد.
براي حذف اين متد TryGetValue، مي‌توان يك enum را بجاي كليدهاي تعريف شده، معرفي كرد. به صورت زير:

using System.Collections.Generic;

namespace Refactoring.Day12.RefactoringSwitchStatement.After
{
    public enum EnglishWord
    {
        Zero,
        One
    }

    public class Translator2
    {
        IDictionary<EnglishWord, string> Words = new Dictionary<EnglishWord, string>
        {
            { EnglishWord.Zero, "صفر" },
            { EnglishWord.One, "يك" }
        };

        public string ToPersian(EnglishWord englishWord)
        {
            return Words[englishWord];
        }
    }
}


به اين ترتيب از يك خروجي پر از if و else و switch به يك خروجي ساده و بدون وجود هيچ شرطي رسيده‌ايم.