क्लास के साथ टाइप कोड बदलें (Refactoring से [Fowler])


9

इस रणनीति में इस तरह की जगह शामिल है:

public class Politician
{
    public const int Infidelity = 0;
    public const int Embezzlement = 1;
    public const int FlipFlopping = 2;
    public const int Murder = 3;
    public const int BabyKissing = 4;

    public int MostNotableGrievance { get; set; }
}

साथ में:

public class Politician
{
    public MostNotableGrievance MostNotableGrievance { get; set; }
}

public class MostNotableGrievance
{
    public static readonly MostNotableGrievance Infidelity = new MostNotableGrievance(0);
    public static readonly MostNotableGrievance Embezzlement = new MostNotableGrievance(1);
    public static readonly MostNotableGrievance FlipFlopping = new MostNotableGrievance(2);
    public static readonly MostNotableGrievance Murder = new MostNotableGrievance(3);
    public static readonly MostNotableGrievance BabyKissing = new MostNotableGrievance(4);

    public int Code { get; private set; }

    private MostNotableGrievance(int code)
    {
        Code = code;
    }
}

क्यों इस प्रकार, इस तरह की गणना करने के लिए यह बेहतर है:

public class Politician
{
    public MostNotableGrievance MostNotableGrievance { get; set; }
}

public enum MostNotableGrievance
{
    Infidelity = 0,
    Embezzlement = 1,
    FlipFlopping = 2,
    Murder = 3,
    BabyKissing = 4
}

इस प्रकार से जुड़ा कोई व्यवहार नहीं है और अगर वहाँ था तो आप किसी भी प्रकार के रिफैक्टरिंग रास्ते का उपयोग कर रहे होंगे, उदाहरण के लिए, 'प्रतिस्थापन प्रकार को उपवर्गों के साथ बदलें' + 'पॉलीमॉर्फ के साथ सशर्त बदलें'।

हालाँकि, लेखक यह समझाता है कि वह इस पद्धति पर क्यों (जावा में?):

संख्यात्मक प्रकार के कोड, या गणना, सी-आधारित भाषाओं की एक सामान्य विशेषता है। प्रतीकात्मक नामों के साथ वे काफी पठनीय हो सकते हैं। समस्या यह है कि प्रतीकात्मक नाम केवल एक उपनाम है; संकलक अभी भी अंतर्निहित संख्या देखता है। संकलक प्रकार 177 नंबर का उपयोग करके चेक करता है न कि प्रतीकात्मक नाम। कोई भी विधि जो एक तर्क के रूप में टाइप कोड लेती है, एक संख्या की उम्मीद करती है, और एक प्रतीकात्मक नाम का उपयोग करने के लिए मजबूर करने के लिए कुछ भी नहीं है। यह पठनीयता को कम कर सकता है और कीड़े का स्रोत बन सकता है।

लेकिन जब इस कथन को C # पर लागू करने की कोशिश की जा रही है, तो यह कथन सत्य प्रतीत नहीं होता है: यह एक संख्या को स्वीकार नहीं करेगा क्योंकि एक गणना को वास्तव में एक वर्ग माना जाता है। तो निम्नलिखित कोड:

public class Test
{
    public void Do()
    {
        var temp = new Politician { MostNotableGrievance = 1 };
    }
}

संकलन नहीं करेंगे। तो क्या नई # उच्च स्तरीय भाषाओं में, जैसे #, या क्या मैं किसी चीज़ पर विचार नहीं कर रहा हूं, इस रीफैक्टरिंग को आवश्यक नहीं माना जा सकता?


var temp = new Politician { MostNotableGrievance = MostNotableGrievance.Embezzlement };
रॉबर्ट हार्वे

जवाबों:


6

मुझे लगता है कि आपने अपने सवाल का लगभग जवाब दे दिया है।

कोड का दूसरा टुकड़ा पहले से अधिक पसंद किया जाता है क्योंकि यह प्रकार-सुरक्षा प्रदान करता है। पहले टुकड़े के साथ, यदि आपके पास मछली की समान गणना है तो आप ऐसा कुछ कह सकते हैं

MostNotableGrievance grievance = Fish.Haddock;

और संकलक परवाह नहीं करेगा। यदि Fish.Haddock = 2 है तो उपरोक्त बिल्कुल बराबर होगा

MostNotableGrievance grievance = MostNotableGrievance.FlipFlopping;

लेकिन स्पष्ट रूप से इस तरह के रूप में तुरंत पठनीय नहीं है।

कारण गणना अक्सर बेहतर नहीं होती है क्योंकि अंतर्निहित रूपांतरण और अंतर से आप सटीक एक ही समस्या के साथ छोड़ देते हैं।

लेकिन, C # में, ऐसा कोई अंतर्निहित रूपांतरण नहीं है, इसलिए उपयोग करने के लिए एक बेहतर संरचना है। आप शायद ही कभी इस्तेमाल किए गए पहले दो तरीकों में से किसी एक को देखेंगे।


5

यदि मूल्य से जुड़ा कोई व्यवहार नहीं है और कोई अतिरिक्त जानकारी नहीं है जिसे आपको इसके साथ संग्रहीत करने की आवश्यकता है और भाषा पूर्णांकों को अंतर्निहित रूपांतरण का समर्थन नहीं करती है, तो मैं एक एनम का उपयोग करूंगा; वे वहाँ के लिए कर रहे हैं।


1

एक और उदाहरण जो आपको प्रभावी जावा (मद 30, यदि आप इसे देखना चाहते हैं) में पाया जा सकता है। यह C # के लिए भी मान्य है।

मान लीजिए कि आप विभिन्न जानवरों को मॉडल बनाने के लिए इंट कॉन्स्टेंट का उपयोग करते हैं, सांप और कुत्ते कहते हैं।

int SNAKE_PYTHON=0;
int SNAKE_RATTLE=1;
int SNAKE_COBRA=2;

int DOG_TERRIER=0;
int DOG_PITBULL=1;

मान लें कि ये स्थिरांक हैं और शायद विभिन्न वर्गों में भी परिभाषित हैं। यह आपको ठीक लग सकता है और यह वास्तव में काम कर सकता है। लेकिन कोड की इस पंक्ति पर विचार करें:

snake.setType(DOG_TERRIER);

स्पष्ट रूप से, यह एक त्रुटि है। संकलक शिकायत नहीं करेगा और कोड निष्पादित करेगा। लेकिन आपका सांप कुत्ते में नहीं बदलेगा। ऐसा इसलिए है क्योंकि कंपाइलर केवल देखता है:

snake.setType(0);

आपका सांप वास्तव में एक अजगर है (और टेरियर नहीं है)। इस सुविधा को प्रकार सुरक्षा कहा जाता है और यह वास्तव में यही कारण है कि आप उदाहरण कोड हैं

var temp = new Politician { MostNotableGrievance = 1 };

संकलन नहीं होगा। MostNotableGrievance एक पूर्णांक नहीं एक MostNotableGrievance है। एनम के साथ आप इसे टाइप सिस्टम में व्यक्त कर सकते हैं। और यही कारण है कि मार्टिन फाउलर और मुझे लगता है कि गणनाएं महान हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.