कैसे सही OOP आवेदन बनाने के लिए [बंद]


98

हाल ही में मैं एक कंपनी 'x' के लिए कोशिश कर रहा था। उन्होंने मुझे कुछ प्रश्नों के सेट भेजे और मुझे केवल एक हल करने के लिए कहा।

समस्या इस प्रकार है -

किताबों, भोजन और छूट वाले चिकित्सा उत्पादों को छोड़कर सभी वस्तुओं पर मूल बिक्री कर 10% की दर से लागू होता है।
आयात शुल्क 5% की दर से सभी आयातित वस्तुओं पर बिना किसी छूट के लागू होने वाला एक अतिरिक्त बिक्री कर है।

जब मैं आइटम खरीदता हूं तो मुझे एक रसीद मिलती है जो सभी वस्तुओं के नाम और उनकी कीमत (कर सहित), वस्तुओं की कुल लागत के साथ परिष्करण, और भुगतान किए गए बिक्री करों की कुल मात्रा को सूचीबद्ध करती है।
बिक्री कर के लिए गोल नियम यह है कि n% की कर दर के लिए, p की एक शेल्फ कीमत में (np / 100 निकटतम 0.05 तक) बिक्री कर की राशि है।

"उन्होंने मुझे बताया, वे आपके समाधान के डिजाइन पहलू में रुचि रखते हैं और मेरे ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग स्किल का मूल्यांकन करना चाहेंगे ।"

यह उन्होंने अपने शब्दों में बताया

  • समाधान के लिए, हम चाहते हैं कि आप जावा, रूबी या सी # का उपयोग करें।
  • हम आपके समाधान के डिजाइन पहलू में रुचि रखते हैं और अपनी वस्तु उन्मुख प्रोग्रामिंग कौशल का मूल्यांकन करना चाहते हैं ।
  • आप निर्माण या परीक्षण उद्देश्यों के लिए बाहरी पुस्तकालयों या उपकरणों का उपयोग कर सकते हैं। विशेष रूप से, आप इकाई परीक्षण पुस्तकालयों का उपयोग कर सकते हैं या अपनी चुनी हुई भाषा के लिए उपलब्ध उपकरणों का निर्माण कर सकते हैं (जैसे, JUnit, Ant, NUnit, NAnt, Test :: Unit, Rake आदि)
  • वैकल्पिक रूप से, आप अपने कोड के साथ अपने डिजाइन और मान्यताओं का एक संक्षिप्त विवरण भी शामिल कर सकते हैं।
  • कृपया ध्यान दें कि हम वेब-आधारित अनुप्रयोग या व्यापक UI की अपेक्षा नहीं कर रहे हैं। बल्कि, हम एक सरल, कंसोल आधारित एप्लिकेशन और आपके स्रोत कोड में रुचि रखने की उम्मीद कर रहे हैं।

इसलिए मैंने नीचे कोड प्रदान किया है - आप बस पेस्ट कोड कॉपी कर सकते हैं और वी.एस. में चला सकते हैं।

class Program
 {
     static void Main(string[] args)
     {
         try
         {
             double totalBill = 0, salesTax = 0;
             List<Product> productList = getProductList();
             foreach (Product prod in productList)
             {
                 double tax = prod.ComputeSalesTax();
                 salesTax += tax;
                 totalBill += tax + (prod.Quantity * prod.ProductPrice);
                 Console.WriteLine(string.Format("Item = {0} : Quantity = {1} : Price = {2} : Tax = {3}", prod.ProductName, prod.Quantity, prod.ProductPrice + tax, tax));
             }
             Console.WriteLine("Total Tax : " + salesTax);
             Console.WriteLine("Total Bill : " + totalBill);                
        }
         catch (Exception ex)
         {
             Console.WriteLine(ex.Message);
         }
         Console.ReadLine();
     }

    private static List<Product> getProductList()
     {
         List<Product> lstProducts = new List<Product>();
         //input 1
         lstProducts.Add(new Product("Book", 12.49, 1, ProductType.ExemptedProduct, false));
         lstProducts.Add(new Product("Music CD", 14.99, 1, ProductType.TaxPaidProduct, false));
         lstProducts.Add(new Product("Chocolate Bar", .85, 1, ProductType.ExemptedProduct, false));

        //input 2
         //lstProducts.Add(new Product("Imported Chocolate", 10, 1, ProductType.ExemptedProduct,true));
         //lstProducts.Add(new Product("Imported Perfume", 47.50, 1, ProductType.TaxPaidProduct,true));

        //input 3
         //lstProducts.Add(new Product("Imported Perfume", 27.99, 1, ProductType.TaxPaidProduct,true));
         //lstProducts.Add(new Product("Perfume", 18.99, 1, ProductType.TaxPaidProduct,false));
         //lstProducts.Add(new Product("Headache Pills", 9.75, 1, ProductType.ExemptedProduct,false));
         //lstProducts.Add(new Product("Imported Chocolate", 11.25, 1, ProductType.ExemptedProduct,true));
         return lstProducts;
     }
 }

public enum ProductType
 {
     ExemptedProduct=1,
     TaxPaidProduct=2,
     //ImportedProduct=3
 }

class Product
 {
     private ProductType _typeOfProduct = ProductType.TaxPaidProduct;
     private string _productName = string.Empty;
     private double _productPrice;
     private int _quantity;
     private bool _isImportedProduct = false;

    public string ProductName { get { return _productName; } }
     public double ProductPrice { get { return _productPrice; } }
     public int Quantity { get { return _quantity; } }

    public Product(string productName, double productPrice,int quantity, ProductType type, bool isImportedProduct)
     {
         _productName = productName;
         _productPrice = productPrice;
         _quantity = quantity;
         _typeOfProduct = type;
         _isImportedProduct = isImportedProduct;
     }

    public double ComputeSalesTax()
     {
         double tax = 0;
         if(_isImportedProduct) //charge 5% tax directly
             tax+=_productPrice*.05;
         switch (_typeOfProduct)
         {
             case ProductType.ExemptedProduct: break;
             case ProductType.TaxPaidProduct:
                 tax += _productPrice * .10;
                 break;
         }
         return Math.Round(tax, 2);
         //round result before returning
     }
 }

आप अलग-अलग इनपुट्स के लिए इनपुट अनओम्नेट कर सकते हैं और चला सकते हैं।

मैंने समाधान प्रदान किया लेकिन मुझे अस्वीकार कर दिया गया।

"उन्होंने कहा, वे हमारे वर्तमान खुले पदों के लिए मुझ पर विचार करने में असमर्थ हैं क्योंकि कोड समाधान संतोषजनक नहीं है।"

कृपया मार्गदर्शन करें कि यहां क्या गायब है। क्या यह समाधान एक अच्छा OOAD समाधान नहीं है।
मैं अपने OOAD कौशल को कैसे सुधार सकता हूं।
मेरे वरिष्ठ भी कहते हैं कि सही OOAD एप्लिकेशन भी व्यावहारिक रूप से काम नहीं करेगा।

धन्यवाद


2
हो सकता है कि उन्होंने आपसे उम्मीद की हो कि वे गुणनखंड के बजाय एक वंशानुगत पदानुक्रम का उपयोग करके उत्पाद प्रकारों में अंतर करें। (हालांकि मुझे लगता है कि दृष्टिकोण को दिए गए परिदृश्य के लिए दोषी माना जाएगा।)
डगलस

मेरा अनुमान है कि उन्होंने आपके समाधान को अस्वीकार कर दिया क्योंकि आपने कोई इंटरफेस परिभाषित नहीं किया था।
क्रिस गेसलर

28
अंगूठे के एक नियम के रूप में, यदि कोई आपसे OOP कौशल का प्रदर्शन करने के लिए एक साक्षात्कार की स्थिति में पूछता है, तो आपको स्विच स्टेटमेंट का उपयोग करने से बचने की कोशिश करनी चाहिए - इसके बजाय एक वंशानुक्रम पदानुक्रम का उपयोग करें।
जो

4
कोड समीक्षा में पोस्ट किया जाना चाहिए।
डेरेक

मैंने वहां भी पोस्ट किया था, लेकिन वहां अच्छा समाधान नहीं मिला। लेकिन हर कोई मेरा नया समाधान देख सकता है जिसे मैंने दूसरों के मदद के बाद बनाया है codeproject.com/Questions/332077/… यहाँ आप मेरे नए कोड को भी पा सकते हैं।
सुंदर

जवाबों:


246

पहले अच्छे आकाश डबल में वित्तीय गणना नहीं करते हैंदशमलव में वित्तीय गणना करें ; यह वही है जो इसके लिए है। भौतिक समस्याओं को सुलझाने के लिए दोहरे का उपयोग करें , न कि वित्तीय समस्याओं का।

आपके कार्यक्रम में प्रमुख डिजाइन दोष यह है कि नीति गलत जगह पर है । करों की गणना करने का प्रभारी कौन है? आपने उत्पाद को करों की गणना के आरोप में रखा है , लेकिन जब आप एक ऐप्पल या किताब या वॉशिंग मशीन खरीदते हैं , तो आप जिस चीज़ को खरीदने जा रहे हैं , वह आपको यह बताने के लिए ज़िम्मेदार नहीं है कि आप कितना कर चुकाने जा रहे हैं यह। आपको बताने के लिए सरकार की नीति जिम्मेदार है। आपका डिज़ाइन बड़े पैमाने पर मूल OO डिज़ाइन सिद्धांत का उल्लंघन करता है कि वस्तुओं को अपनी चिंताओं के लिए जिम्मेदार होना चाहिए , और किसी और को नहीं। वॉशिंग मशीन की चिंता आपके कपड़े धोना है, न कि सही आयात शुल्क वसूलना। यदि कर कानून बदलते हैं, तो आप बदलना नहीं चाहते हैंवॉशिंग मशीन ऑब्जेक्ट , आप पॉलिसी ऑब्जेक्ट को बदलना चाहते हैं ।

तो, भविष्य में इन प्रकार की समस्याओं से कैसे संपर्क करें?

मैंने समस्या वर्णन में हर महत्वपूर्ण संज्ञा पर प्रकाश डालकर शुरुआत की होगी:

किताबों , भोजन और छूट वाले चिकित्सा उत्पादों को छोड़कर सभी वस्तुओं पर मूल बिक्री कर 10% की दर से लागू होता है । आयात शुल्क 5% की दर से सभी आयातित वस्तुओं पर बिना किसी छूट के लागू होने वाला एक अतिरिक्त बिक्री कर है । जब मैं आइटम खरीदता हूं तो मुझे एक रसीद मिलती है जो सभी वस्तुओं के नाम और उनकी कीमत ( कर सहित ) को सूचीबद्ध करती है , जो कुल लागत के साथ खत्म होती हैआइटम, और बिक्री करों की कुल राशि का भुगतान किया। बिक्री कर के लिए गोल नियम यह है कि n% की कर दर के लिए, p की एक शेल्फ कीमत में (np / 100 निकटतम 0.05 तक) बिक्री कर की राशि है ।

अब, उन सभी संज्ञाओं के बीच क्या संबंध हैं?

  • बेसिक सेल्स टैक्स एक तरह का सेल्स टैक्स होता है
  • इंपोर्ट ड्यूटी एक तरह का सेल्स टैक्स है
  • एक बिक्री कर की एक दर है जो एक दशमलव है
  • पुस्तकें एक प्रकार की वस्तु हैं
  • भोजन एक प्रकार की वस्तु है
  • मेडिकल उत्पाद एक तरह का आइटम है
  • वस्तुओं का आयात किया जा सकता है
  • एक आइटम का एक नाम है जो एक स्ट्रिंग है
  • एक आइटम का एक शेल्फ मूल्य है जो एक दशमलव है। (नोट: क्या किसी वस्तु की वास्तव में कीमत होती है? दो समान वाशिंग मशीन अलग-अलग दुकानों पर अलग-अलग कीमतों पर या एक ही स्टोर पर अलग-अलग समय पर बिक्री के लिए हो सकती हैं। बेहतर डिजाइन यह कहना हो सकता है कि मूल्य निर्धारण नीति एक आइटम से संबंधित है। इसकी कीमत।)
  • विक्रय कर छूट नीति उन शर्तों का वर्णन करती है, जिसके तहत किसी वस्तु पर एक बिक्री कर अनुचित है।
  • एक रसीद में आइटम, उनके मूल्य और उनके करों की एक सूची है।
  • एक रसीद में कुल होता है
  • एक रसीद पर कुल कर होता है

... और इसी तरह। एक बार जब आपके पास सभी संज्ञाओं के बीच सभी संबंध हो जाएंगे, तो आप एक वर्ग पदानुक्रम डिजाइन करना शुरू कर सकते हैं। एक सार आधार वर्ग है। इससे पुस्तक विरासत में मिली। एक अमूर्त वर्ग सेल्सटैक्स है; BasicSalesTax इससे विरासत में मिला है। और इसी तरह।


12
आपको अभी जो प्रदान किया गया था उससे अधिक की आवश्यकता है? लगता है कि आपको यह जानने की ज़रूरत है कि विरासत कैसे लागू की जाती है, और बहुरूपता क्या है।
२५:१२

27
@ सूंदर: यह उत्तर पर्याप्त से अधिक है। अब अपने कौशल को विकसित करना आपकी जिम्मेदारी है, शायद पहले उदाहरण के रूप में इसका उपयोग कर रहे हैं। ध्यान दें कि आपका उदाहरण वास्तविक जीवन के उदाहरण की परिभाषा है। आप एक वास्तविक जीवन के साक्षात्कार में असफल हो गए क्योंकि इस वास्तविक जीवन के कोड को वास्तविक जीवन डिजाइन की आवश्यकता थी जो आपने प्रदान नहीं किया था।
ग्रेग डी

9
@ नारायण: doubleउन स्थितियों के लिए आदर्श है जहाँ 0.00000001% सही उत्तर के भीतर पर्याप्त से अधिक है। यदि आप यह पता लगाना चाहते हैं कि आधे सेकंड के बाद एक ईंट कितनी तेजी से गिर रही है, तो गणित को युगल में करें। जब आप युगल में वित्तीय अंकगणित करते हैं, तो आप जवाब के साथ समाप्त हो जाते हैं जैसे कर के बाद कीमत 43.79999999999999 डॉलर है और यह सिर्फ मूर्खतापूर्ण दिखता है भले ही यह सही उत्तर के बेहद करीब हो।
एरिक लिपर्ट

31
+1 आपने एक उल्लेखनीय अभ्यास पर प्रकाश डाला है, जो बताई गई समस्या में प्रत्येक संज्ञा की जांच करना है, और फिर एक-दूसरे के बीच अपने संबंधों को संजोना है। महान विचार।
क्रिस टोंकिंसन

3
@ जोर्डो: दशमलव में, 0.10 दस बार जोड़ने पर 1.00 मिलता है। लेकिन 1.0 / 333.0 तीन सौ और तीन तीन बार जोड़ना जरूरी नहीं है कि वह दशमलव या डबल में से किसी एक को दे। दशमलव में, भिन्न में दस की शक्ति वाले भिन्नों को बिल्कुल दर्शाया जाता है; युगल में, यह दो की शक्तियों के साथ भिन्न होता है। कुछ और लगभग प्रतिनिधित्व किया है।
एरिक लिपिपर्ट

38

यदि कंपनी NUnit, JUnit या Test :: Unit जैसे पुस्तकालयों के बारे में कुछ बताती है, तो संभावना से अधिक है कि TDD वास्तव में उनके लिए आयात है। आपके कोड नमूने में कोई परीक्षण नहीं है।

मैं इसका व्यावहारिक ज्ञान प्रदर्शित करने का प्रयास करूंगा:

  • इकाई परीक्षण (जैसे। NUnit)
  • मॉकिंग (उदा। राइनोमॉक्स)
  • दृढ़ता (जैसे। NHibernate)
  • IoC कंटेनर (उदा। एनएसप्रिंग)
  • डिजाइन पैटर्न्स
  • ठोस सिद्धांत

मैं www.dimecasts.net को मुफ्त के प्रभावशाली स्रोत के रूप में पुनःप्राप्त करना चाहूंगा , अच्छी गुणवत्ता वाले स्क्रेंकोस्ट जो उपरोक्त सभी विषयों को शामिल करते हैं।


19

यह अत्यधिक व्यक्तिपरक है लेकिन यहां कुछ बिंदु दिए गए हैं जो मैं आपके कोड के बारे में बताऊंगा:

  • मेरी राय में आप मिलाया Productऔर ShoppingCartItemProductउत्पाद का नाम, कर की स्थिति आदि होनी चाहिए, लेकिन मात्रा नहीं। मात्रा किसी उत्पाद का गुण नहीं है - यह कंपनी के प्रत्येक ग्राहक के लिए अलग होगा जो उस विशेष उत्पाद को खरीदता है।

  • ShoppingCartItemएक Productऔर मात्रा होनी चाहिए । इस तरह ग्राहक एक ही उत्पाद के कम या ज्यादा खरीद सकते हैं। आपके वर्तमान सेटअप के साथ यह संभव नहीं है।

  • अंतिम कर की गणना भी इसका हिस्सा नहीं होनी चाहिए Product- यह कुछ इस तरह का हिस्सा होना चाहिए ShoppingCartक्योंकि अंतिम कर गणना में गाड़ी के सभी उत्पादों को जानना शामिल हो सकता है।


इस जवाब के साथ मेरे पास एकमात्र समस्या यह है कि यह बताता है कि एक बेहतर उत्पाद भुगतान प्रणाली (जो कि वैध है) का निर्माण कैसे किया जाए लेकिन वास्तव में ओओपी के तरीकों पर विस्तृत नहीं है। इसे किसी भी भाषा में लागू किया जा सकता है। कुछ प्रकार के इंटरफेस, वंशानुक्रम, बहुरूपता आदि को दिखाए बिना, वह अभी भी परीक्षण में विफल रहेगा।
टाइमआउट

अंतिम बिंदु के संदर्भ में: एकल गणना सिद्धांत के कारण कर गणना के लिए IMO सबसे अच्छी जगह अलग-अलग TaxCalculator वर्ग है।
राडेक

उत्तर के लिए धन्यवाद, लेकिन यह कितना व्यावहारिक है। हर कंपनी इतने व्यापक और शुद्ध OOPS मॉडल में काम करती है।
सुंदर

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

अच्छा उत्तर लेकिन मैं यह भी मानता हूं कि कर गणना एक अलग वस्तु होनी चाहिए।

14

सबसे पहले, यह एक बहुत अच्छा साक्षात्कार प्रश्न है। यह कई कौशल का एक अच्छा गेज है ।

कई चीजें हैं जिन्हें आपको एक अच्छा उत्तर देने के लिए समझने की आवश्यकता है ( कोई सटीक उत्तर नहीं है), दोनों उच्च-स्तर और निम्न-स्तर। यहाँ एक जोड़े हैं:

  • डोमेन मॉडलिंग -> आप समाधान का एक अच्छा मॉडल कैसे बनाते हैं? आप किन वस्तुओं का निर्माण करते हैं? वे आवश्यकताओं को कैसे हल करेंगे? संज्ञाओं की तलाश एक अच्छी शुरुआत है, लेकिन आप कैसे तय करते हैं कि आपकी पसंद की संस्थाएं अच्छी हैं? आपको किन अन्य संस्थाओं की आवश्यकता है? इसे हल करने के लिए आपको किस डोमेन ज्ञान की आवश्यकता है?
  • चिंताओं का पृथक्करण, ढीली युग्मन, उच्च सामंजस्य -> आप डिजाइन के उन हिस्सों को कैसे अलग करते हैं जिनमें विभिन्न चिंताएं या परिवर्तन की दरें हैं और आप उनसे कैसे संबंधित हैं? आप अपने डिजाइन को कैसे लचीला और चालू रखते हैं?
  • यूनिट परीक्षण, रीफैक्टरिंग, टीडीडी -> एक समाधान के साथ आने के लिए आपकी प्रक्रिया क्या है ? क्या आप परीक्षण लिखते हैं, नकली वस्तुओं, रिफ्लेक्टर, पुनरावृति का उपयोग करते हैं?
  • स्वच्छ कोड, भाषा मुहावरे -> क्या आप अपनी मदद करने के लिए अपनी प्रोग्रामिंग भाषा की विशेषताओं का उपयोग करते हैं? क्या आप समझने योग्य कोड लिखते हैं? क्या अमूर्तता के आपके स्तर समझ में आते हैं? कोड कितना सुपाच्य है?
  • उपकरण : क्या आप स्रोत नियंत्रण का उपयोग करते हैं? उपकरण बनाएँ? IDEs?

वहां से, आप कई दिलचस्प चर्चा कर सकते हैं, जिसमें डिज़ाइन सिद्धांतों (जैसे SOLID सिद्धांतों), डिज़ाइन पैटर्न, विश्लेषण पैटर्न, डोमेन मॉडलिंग, प्रौद्योगिकी विकल्प, भविष्य के विकास के मार्ग (जैसे कि क्या होगा अगर मैं एक डेटाबेस, या एक समृद्ध UI परत जोड़ सकता हूं) क्या बदलने की जरूरत है?), व्यापार-नापसंद, गैर-कार्यात्मक आवश्यकताएं (प्रदर्शन, रखरखाव, सुरक्षा, ...), स्वीकृति परीक्षण, आदि ...

मैं इस बात पर टिप्पणी नहीं करूंगा कि आपको अपना समाधान कैसे बदलना चाहिए, बस आपको इन अवधारणाओं पर अधिक ध्यान केंद्रित करना चाहिए।

लेकिन, मैं आपको दिखा सकता हूं कि मैंने (आंशिक रूप से) इस समस्या को कैसे हल किया , सिर्फ एक उदाहरण के रूप में (जावा में)। इस रसीद को प्रिंट करने के लिए यह सब कैसे आता है, यह देखने के लिए Programकक्षा में देखें:

------------------ यह आपका आदेश है ------------------
(001) डोमेन संचालित डिज़ाइन ----- $ 69.99
(001) बढ़ती वस्तु उन्मुख सॉफ्टवेयर ----- $ 49.99
(001) हाउस एमडी सीजन 1 ----- $ 29.99
(001) हाउस एमडी सीजन 7 ----- $ 34.50
(IMD) ग्रोइंग ऑब्जेक्ट ओरिएंटेड सॉफ्टवेयर ----- $ 2.50
(BST) हाउस एमडी सीजन 1 ----- $ 3.00
(BST) हाउस एमडी सीजन 7 ----- $ 3.45
(IMD) हाउस एमडी सीजन 7 ----- $ 1.73
                                SUB-TOTAL ----- $ 184.47
                                टैक्स कुल ----- $ 10.68
                                    कुल ----- $ 195.15
---------------- हमें चुनने के लिए धन्यवाद ----------------

आप निश्चित रूप से उन पुस्तकों पर एक नज़र रखना चाहिए :-)

बस एक चेतावनी के रूप में: मेरा समाधान अभी भी बहुत अधूरा है, मैंने सिर्फ खुशहाल रास्ते पर ध्यान केंद्रित किया है ताकि निर्माण करने के लिए एक अच्छी नींव हो।


मैं आपके समाधान के माध्यम से चला गया और इसे बहुत दिलचस्प पाया। हालांकि मुझे लगता है कि ऑर्डर क्लास को रीकैपिट छापने के लिए जिम्मेदार नहीं होना चाहिए। इसी तरह, टैक्स की गणना के लिए टैक्समेथोड वर्ग जिम्मेदार नहीं होना चाहिए। इसके अलावा, TaxMethodP अभ्यास में TaxMethod की सूची नहीं होनी चाहिए। इसके बजाय, SalesPolicy नामक वर्ग को यह सूची होनी चाहिए। SalesEngine नामक एक वर्ग को SalesPolicy, एक आदेश और एक TaxCalculator पारित किया जाना चाहिए। SalesEngine आदेश में वस्तुओं पर SalesPolicy लागू करते हैं और TaxCalculator का उपयोग कर टैक्स की गणना करेगा
Cking

@ बीओटी: दिलचस्प अवलोकन .... अभी, Orderरसीद प्रिंट करता है, लेकिन Receiptइसके अपने स्वरूपण के बारे में जानता है। इसके अलावा, TaxMethodP प्रैक्टिस एक टैक्स पॉलिसी की तरह है, यह एक निश्चित परिदृश्य पर लागू होने वाले सभी करों को रखती है। TaxMethods हैं कर कैलकुलेटर। मुझे लगता है कि आप अपने प्रस्तावित SalesEngine की तरह केवल कुछ उच्च स्तर के बाध्यकारी वर्ग को याद कर रहे हैं । यह एक दिलचस्प विचार है।
जोर्डो

मुझे बस लगता है कि हर वर्ग के पास एक अच्छी तरह से परिभाषित जिम्मेदारी होनी चाहिए और वास्तविक दुनिया की वस्तुओं का प्रतिनिधित्व करने वाले वर्गों को एक फैशन में व्यवहार करना चाहिए जो वास्तविक दुनिया के अनुरूप हो। उस मामले के लिए एक टैक्समेथोड को दो वर्गों में विभाजित किया जा सकता है। एक TaxCriteria और एक TaxCalculator। इसी तरह एक ऑर्डर को रसीद नहीं छापनी चाहिए। रसीद तैयार करने के लिए एक रसीदधारक को एक रसीद दी जानी चाहिए।
CKing

@ बीओटी: मैं पूरी तरह से सहमत हूँ! अच्छा डिजाइन ठोस हैं ! एक TaxMethod है एक कर कैलकुलेटर, और एक TaxEligibilityCheck है एक कर मापदंड। वे अलग संस्थाएँ हैं। रसीद के लिए, हाँ, सृजन भाग को विभाजित करने से डिजाइन में सुधार होगा।
जोर्डो

1
यह विचार विनिर्देश पैटर्न से आता है , एक नज़र डालें!
जोर्डो

12

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

लेकिन मैं अभी अवसाद में नहीं बदलूंगा। यह तथ्य कि आपने उन्हें यहां प्रदर्शित नहीं किया है, इसका मतलब यह नहीं है कि आप उन्हें पहले से नहीं जानते हैं या उन्हें जानने में सक्षम नहीं हैं।

आपको बस ओओपी या साक्षात्कार के साथ थोड़ा और अनुभव की आवश्यकता है।

सौभाग्य!


वास्तव में यह मेरा पहला डिज़ाइन था, मैंने एक और बनाया लेकिन आपको नहीं दिखा सकता क्योंकि चरित्र की सीमा पार हो रही है।
14:25

क्या आप इसे किसी भी उदाहरण की मदद से प्रदर्शित कर सकते हैं।
सुंदर

@ गलत: आप अपने नए डिजाइन के साथ सवाल को अपडेट कर सकते हैं।
बज्कर फ्रायंड-हैनसेन

10

जिन लोगों ने ओओपी के साथ प्रोग्रामिंग सीखना शुरू कर दिया है, उन्हें यह समझने में बहुत परेशानी नहीं है कि इसका क्या मतलब है, क्योंकि यह वास्तविक जीवन में जैसा है । यदि आपके पास OO की तुलना में अन्य प्रोग्रामिंग फैमिलि के कौशल हैं, तो इसे समझना अधिक कठिन हो सकता है।

सबसे पहले, अपनी स्क्रीन को बंद करें, या अपनी पसंदीदा आईडीई से बाहर निकलें। एक लो कागज और एक पेंसिल और की एक सूची बनाने संस्थाओं , संबंधों , लोगों , मशीनों , प्रक्रियाओं , सामान आदि, सब कुछ है कि अपने अंतिम कार्यक्रम में सामना किया जा सकता है।

दूसरा, विभिन्न बुनियादी संस्थाओं को प्राप्त करने का प्रयास करें । आप समझेंगे कि कुछ संपत्तियों या क्षमताओं को साझा कर सकते हैं , आपको इसे अमूर्त वस्तुओं में डालना होगा । आपको अपने प्रोग्राम का एक अच्छा स्कीमा बनाना शुरू करना चाहिए।

इसके बाद आपको फॉनटाइक्विटी (विधियों, कार्यों, सबरूटीन्स को कॉल करना होगा, जैसा आप चाहते हैं): उदाहरण के लिए, एक उत्पाद वस्तु बिक्री कर की गणना करने में सक्षम नहीं होना चाहिए । एक बिक्री इंजन वस्तु चाहिए।

पहली बार में सभी बड़े शब्दों ( इंटरफेस , गुण , बहुरूपता , विरासत , आदि) और डिजाइन पैटर्न के साथ परेशानी महसूस न करें , सुंदर कोड या जो भी करने की कोशिश न करें ... बस साधारण वस्तुओं के बारे में सोचें और वास्तविक जीवन में इसके बीच के व्यवधान

बाद में, इस बारे में कुछ गंभीर संक्षिप्त साहित्य पढ़ने की कोशिश करें। मुझे लगता है कि विकिपीडिया और विकीबूक शुरू करने का एक अच्छा तरीका है और फिर सिर्फ गोफ और डिज़ाइन पैटर्न और यूएमएल के बारे में सामान पढ़ें ।


3
+1 के लिए "सबसे पहले, अपनी स्क्रीन को बंद करें"। मुझे लगता है कि कंप्यूटिंग की शक्ति के लिए अक्सर सोचने की शक्ति गलत होती है।
कांटूर

1
पेंसिल और पेपर का उपयोग करने का सबसे सरल तरीका लेने के लिए +1। कई बार आईडीई :) के सामने बैठने पर लोग भ्रमित हो जाते हैं:
नीरज गुलिया

कुछ वैज्ञानिकों ने कहा कि स्क्रीन देखते समय हमारा मस्तिष्क असावधान होता है। जब मैं सॉफ़्टवेयर आर्किटेक्चर डिज़ाइन का अध्ययन करता हूं, तो हमारा शिक्षक हमें कागज़ पर काम करने के लिए तैयार करता है। वह शक्तिशाली यूएमएल सॉफ्टवेयर्स का बुरा नहीं मानता। पहले चीजों को समझना महत्वपूर्ण है।
स्मॉन्फ़

4

सबसे पहले मिश्रित नहीं होते Productरसीद (साथ वर्ग ShoppingCart) वर्ग, quantityका हिस्सा होना चाहिए ReceipItem( ShoppingCartItem), और साथ ही Taxऔर CostTotalTaxऔर TotalCostका हिस्सा होना चाहिए ShoppingCart

मेरे Productवर्ग, है केवल Nameऔर Priceऔर कुछ केवल पढ़ने के लिए गुण की तरह IsImported:

class Product
{
    static readonly IDictionary<ProductType, string[]> productType_Identifiers = 
        new Dictionary<ProductType, string[]>
        {
            {ProductType.Food, new[]{ "chocolate", "chocolates" }},
            {ProductType.Medical, new[]{ "pills" }},
            {ProductType.Book, new[]{ "book" }}
        };

    public decimal ShelfPrice { get; set; }

    public string Name { get; set; }

    public bool IsImported { get { return Name.Contains("imported "); } }

    public bool IsOf(ProductType productType)
    {
        return productType_Identifiers.ContainsKey(productType) &&
            productType_Identifiers[productType].Any(x => Name.Contains(x));
    }
}

class ShoppringCart
{
    public IList<ShoppringCartItem> CartItems { get; set; }

    public decimal TotalTax { get { return CartItems.Sum(x => x.Tax); } }

    public decimal TotalCost { get { return CartItems.Sum(x => x.Cost); } }
}

class ShoppringCartItem
{
    public Product Product { get; set; }

    public int Quantity { get; set; }

    public decimal Tax { get; set; }

    public decimal Cost { get { return Quantity * (Tax + Product.ShelfPrice); } }
}

आपके कर गणना भाग के साथ युग्मित है Product। एक उत्पाद टैक्स की नीतियों को परिभाषित नहीं करता है जो कि कर वर्ग है। समस्या के विवरण के आधार पर, दो प्रकार के बिक्री कर हैं: Basicऔर Dutyकर। आप Template Method Design Patternइसे प्राप्त करने के लिए उपयोग कर सकते हैं :

abstract class SalesTax
{
    abstract public bool IsApplicable(Product item);
    abstract public decimal Rate { get; }

    public decimal Calculate(Product item)
    {
        if (IsApplicable(item))
        {
            //sales tax are that for a tax rate of n%, a shelf price of p contains (np/100)
            var tax = (item.ShelfPrice * Rate) / 100;

            //The rounding rules: rounded up to the nearest 0.05
            tax = Math.Ceiling(tax / 0.05m) * 0.05m;

            return tax;
        }

        return 0;
    }
}

class BasicSalesTax : SalesTax
{
    private ProductType[] _taxExcemptions = new[] 
    { 
        ProductType.Food, ProductType.Medical, ProductType.Book 
    };

    public override bool IsApplicable(Product item)
    {
        return !(_taxExcemptions.Any(x => item.IsOf(x)));
    }

    public override decimal Rate { get { return 10.00M; } }
}

class ImportedDutySalesTax : SalesTax
{
    public override bool IsApplicable(Product item)
    {
        return item.IsImported;
    }

    public override decimal Rate { get { return 5.00M; } }
}

और अंत में करों को लागू करने के लिए एक वर्ग:

class TaxCalculator
{
    private SalesTax[] _Taxes = new SalesTax[] { new BasicSalesTax(), new ImportedDutySalesTax() };

    public void Calculate(ShoppringCart shoppringCart)
    {
        foreach (var cartItem in shoppringCart.CartItems)
        {
            cartItem.Tax = _Taxes.Sum(x => x.Calculate(cartItem.Product));
        }

    }
}

आप उन्हें MyFiddle पर आज़मा सकते हैं


2

डिजाइन नियमों के बारे में एक बहुत अच्छा प्रारंभिक बिंदु SOLID सिद्धांत हैं।

उदाहरण के लिए ओपन क्लोज्ड सिद्धांत बताता है कि यदि आप नई कार्यक्षमता जोड़ना चाहते हैं तो आपको मौजूदा क्लास में कोड नहीं जोड़ना होगा, बल्कि नई क्लास जोड़ना होगा।

आपके नमूना आवेदन के लिए इसका मतलब यह होगा कि नए बिक्री कर को नए वर्ग को जोड़ना होगा। वही विभिन्न उत्पादों के लिए जाता है जो नियम के अपवाद हैं।

गोल करने का नियम स्पष्ट रूप से अलग वर्ग में जाता है - एकल जिम्मेदारी सिद्धांत बताता है कि हर वर्ग की एक ही जिम्मेदारी है।

मुझे लगता है कि कोड लिखने की कोशिश करने से खुद को एक अच्छा समाधान लिखने और इसे यहां चिपकाने की तुलना में कहीं अधिक लाभ होगा।

एक सरल एल्गोरिदम सही डिजाइन कार्यक्रम लिखने के लिए होगा:

  1. कुछ कोड लिखें जो समस्या को हल करता है
  2. जांचें कि क्या कोड SOLID सिद्धांतों का अनुपालन करता है
  3. यदि गोटो 1 की तुलना में नियम उल्लंघन हैं।

2

एक पूर्ण OOP कार्यान्वयन पूरी तरह से बहस का मुद्दा है। आपके प्रश्न में मुझे जो दिखाई देता है, उससे आप उत्पाद, कर, ProductDB और इतने पर जैसे अंतिम मूल्य की गणना करने के लिए प्रदर्शन की भूमिका के आधार पर कोड को संशोधित कर सकते थे।

  1. Productएक अमूर्त वर्ग और बुक्स की तरह व्युत्पन्न प्रकार हो सकता है, खाद्य विरासत से प्राप्त किया जा सकता है। कर प्रयोज्यता का निर्धारण व्युत्पन्न प्रकारों द्वारा किया जा सकता है। उत्पाद यह बताएगा कि क्या कर लागू है या नहीं यह व्युत्पन्न वर्ग पर आधारित है।

  2. TaxCriteria एक एनुम हो सकता है और इसे खरीद (आयातित, बिक्री कर प्रयोज्यता) के दौरान निर्दिष्ट किया जा सकता है।

  3. Taxवर्ग के आधार पर कर की गणना करेगा TaxCriteria

  4. एक होने ShoppingCartItemके रूप में द्वारा सुझाए गए XXBBCC संपुटित कर सकते हैं उत्पाद और टैक्स उदाहरणों और यह मात्रा के साथ अलग उत्पाद विवरण, कर आदि के साथ कुल कीमत के लिए एक शानदार तरीका है

सौभाग्य।


1

कड़ाई से OOA / D के परिप्रेक्ष्य में, एक प्रमुख मुद्दा जो मैं देख रहा हूं वह यह है कि आपकी अधिकांश क्लास विशेषताओं में क्लास का बेमानी नाम विशेषता है। जैसे उत्पाद की कीमत, टाइपऑफ उत्पाद । इस स्थिति में, हर जगह आप इस वर्ग का उपयोग करते हैं, आपके पास वर्बोज़ होगा और कुछ भ्रामक कोड, जैसे product.productName। अपनी विशेषताओं से अनावश्यक वर्ग नाम उपसर्ग / प्रत्यय निकालें।

इसके अलावा, मैंने किसी भी वर्ग को खरीद और संबंधित रसीद बनाने से संबंधित नहीं देखा जैसा कि प्रश्न में पूछा गया था।


1

यहाँ उत्पाद, कर, आदि के लिए एक OO पैटर्न का एक शानदार उदाहरण है ... सूचना का उपयोग करें, जो OO डिज़ाइन में आवश्यक है।

http://www.dreamincode.net/forums/topic/185426-design-patterns-strategy/


3
मैं इसे एक इंटरफ़ेस बनाने पर उत्पाद (सार) वर्ग बनाना पसंद करूँगा। मैं प्रत्येक उत्पाद को एक अलग वर्ग भी नहीं बनाऊंगा। अधिक से अधिक मैं प्रति श्रेणी एक वर्ग बनाऊंगा।
कोडइन्चोस

@CodeInChaos - अधिकांश समय आपको दोनों की आवश्यकता होती है, लेकिन यदि आप एक वास्तुकार के रूप में नौकरी करने की कोशिश कर रहे हैं, तो मैं एक सार वर्ग पर इंटरफेस को लागू करना चुनूंगा।
क्रिस गेसलर

1
इस उदाहरण में इंटरफेस का कोई मतलब नहीं है। वे केवल उन्हें लागू करने वाले प्रत्येक वर्ग में कोड दोहराव की ओर ले जाते हैं। प्रत्येक वर्ग इसे उसी तरह लागू करता है।
पायोत्र पेरक

0

विज़िटर पैटर्न का उपयोग करके कर की समस्या के साथ लागत पर हमला किया।

public class Tests
    {
        [SetUp]
        public void Setup()
        {
        }

        [Test]
        public void Input1Test()
        {
            var items = new List<IItem> {
                new Book("Book", 12.49M, 1, false),
                new Other("Music CD", 14.99M, 1, false),
                new Food("Chocolate Bar", 0.85M, 1, false)};

            var visitor = new ItemCostWithTaxVisitor();

            Assert.AreEqual(12.49, items[0].Accept(visitor));
            Assert.AreEqual(16.49, items[1].Accept(visitor));
            Assert.AreEqual(0.85, items[2].Accept(visitor));
        }

        [Test]
        public void Input2Test()
        {
            var items = new List<IItem> {
                new Food("Bottle of Chocolates", 10.00M, 1, true),
                new Other("Bottle of Perfume", 47.50M, 1, true)};

            var visitor = new ItemCostWithTaxVisitor();

            Assert.AreEqual(10.50, items[0].Accept(visitor));
            Assert.AreEqual(54.65, items[1].Accept(visitor));
        }

        [Test]
        public void Input3Test()
        {
            var items = new List<IItem> {
                new Other("Bottle of Perfume", 27.99M, 1, true),
                new Other("Bottle of Perfume", 18.99M, 1, false),
                new Medicine("Packet of headache pills", 9.75M, 1, false),
                new Food("Box of Chocolate", 11.25M, 1, true)};

            var visitor = new ItemCostWithTaxVisitor();

            Assert.AreEqual(32.19, items[0].Accept(visitor));
            Assert.AreEqual(20.89, items[1].Accept(visitor));
            Assert.AreEqual(9.75, items[2].Accept(visitor));
            Assert.AreEqual(11.80, items[3].Accept(visitor));
        }
    }

    public abstract class IItem : IItemVisitable
    { 
        public IItem(string name,
            decimal price,
            int quantity,
            bool isImported)
            {
                Name = name;
                Price = price;
                Quantity = quantity;
                IsImported = isImported;
            }

        public string Name { get; set; }
        public decimal Price { get; set; }
        public int Quantity { get; set; }
        public bool IsImported { get; set; }

        public abstract decimal Accept(IItemVisitor visitor);
    }

    public class Other : IItem, IItemVisitable
    {
        public Other(string name, decimal price, int quantity, bool isImported) : base(name, price, quantity, isImported)
        {
        }

        public override decimal Accept(IItemVisitor visitor) => Math.Round(visitor.Visit(this), 2);
    }

    public class Book : IItem, IItemVisitable
    {
        public Book(string name, decimal price, int quantity, bool isImported) : base(name, price, quantity, isImported)
        {
        }

        public override decimal Accept(IItemVisitor visitor) => Math.Round(visitor.Visit(this),2);
    }

    public class Food : IItem, IItemVisitable
    {
        public Food(string name, decimal price, int quantity, bool isImported) : base(name, price, quantity, isImported)
        {
        }

        public override decimal Accept(IItemVisitor visitor) => Math.Round(visitor.Visit(this), 2);
    }

    public class Medicine : IItem, IItemVisitable
    {
        public Medicine(string name, decimal price, int quantity, bool isImported) : base(name, price, quantity, isImported)
        {
        }

        public override decimal Accept(IItemVisitor visitor) => Math.Round(visitor.Visit(this), 2);
    }

    public interface IItemVisitable
    {
        decimal Accept(IItemVisitor visitor);
    }

    public class ItemCostWithTaxVisitor : IItemVisitor
    {
        public decimal Visit(Food item) => CalculateCostWithTax(item);

        public decimal Visit(Book item) => CalculateCostWithTax(item);

        public decimal Visit(Medicine item) => CalculateCostWithTax(item);

        public decimal CalculateCostWithTax(IItem item) => item.IsImported ?
            Math.Round(item.Price * item.Quantity * .05M * 20.0M, MidpointRounding.AwayFromZero) / 20.0M + (item.Price * item.Quantity)
            : item.Price * item.Quantity;

        public decimal Visit(Other item) => item.IsImported ?
            Math.Round(item.Price * item.Quantity * .15M * 20.0M, MidpointRounding.AwayFromZero) / 20.0M + (item.Price * item.Quantity)
            : Math.Round(item.Price * item.Quantity * .10M * 20.0M, MidpointRounding.AwayFromZero) / 20.0M + (item.Price * item.Quantity);
    }

    public interface IItemVisitor
    {
        decimal Visit(Food item);
        decimal Visit(Book item);
        decimal Visit(Medicine item);
        decimal Visit(Other item);
    }

Stackoverflow में आपका स्वागत है। कृपया सुनिश्चित करें कि आपने प्रश्न के उत्तर में अपना उत्तर स्पष्ट कर दिया है। ओपी सिर्फ एक समाधान की मांग नहीं कर रहा है लेकिन एक समाधान बेहतर / बदतर क्यों है।
शमौन.SA
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.