2015-05-06 5 views
11

में पुन: उपयोग अमूर्त सिद्धांत हमारे सी # एमवीसी अनुप्रयोग में हमारे पास बहुत से इंटरफेस हैं जो उन्हें लागू करने वाली वस्तुओं के साथ 1 से 1 मानचित्र करते हैं। यानी: मूल रूप से, प्रत्येक ऑब्जेक्ट के लिए बनाया गया, एक "निकालें इंटरफ़ेस" ऑपरेशन किया गया है।सी #

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

हमारे सिस्टम में कोई ठोस वस्तुएं कई इंटरफेस लागू नहीं करती हैं।

क्या कोई मुझे बता सकता है कि क्या यह सड़क के नीचे समस्याएं पैदा कर रहा है? और यदि हां, तो वे क्या होंगे?

मैं सोच रहा था, हमारे ऐप को फिर से दोहराव है, उदाहरण के लिए इन 2 इंटरफेस (संपादित करें: हमारी सर्विसेज परत में) केवल एक चीज जो अलग है वह विधि का नाम और पैरामीटर का प्रकार है, लेकिन शब्दार्थ वे खजाने वे को संदेश भेजने के साथ ही बात करते हैं:

interface ICustomer 
{ 
    void AddCustomer(Customer toAdd); 
    void UpdateCustomer(Customer toUpdate); 
    Customer GetById(int customerId); 
} 

interface IEmployee 
{ 
    void AddEmployee(Employee toBeAdded); 
    void UpdateEmployee(Employee toUpdate); 
    Employee GetById(int employeeId);  
} 

और कहा कि मैं कहाँ लगता है पुन: उपयोग किया अमूर्त सिद्धांत रूप में यानी आएगा, जैसे कुछ करने के लिए कोड को बदलने के लिए है:

public interface IEmployee: IAdd<Employee>, IUpdate<Employee>, IFinder<Employee> 

यह भंडार पेट के बारे में नहीं है टर्न - यह किसी भी परत में इंटरफेस के बारे में है जो दिखता है कि वे अर्थात् समान व्यवहार साझा करते हैं। क्या इन परिचालनों के लिए आम इंटरफेस प्राप्त करने और "उप-इंटरफेस" को उनके द्वारा प्राप्त करने के लायक है?

कम से कम यह विधियों के अनुक्रमों को लगातार बनाए रखेगा। लेकिन यह मुझे अन्य लाभ क्या देगा? (लिस्कोव प्रतिस्थापन सिद्धांत एक तरफ)

अभी, विधियों के नाम और वापसी प्रकार सभी जगह पर हैं।

मैंने मार्क सेमैन के ब्लॉग को पुन: उपयोग किए गए सार तत्व सिद्धांत के बारे में पढ़ा लेकिन मुझे समझ में नहीं आया, यह स्पष्ट नहीं था। शायद मैं सिर्फ बेवकूफ हूँ :) मैंने हेडर इंटरफेस की फाउलर की परिभाषा भी पढ़ी।

+0

लग रहा है। –

+0

मुझे खुद को पुन: उपयोग किए गए abstractions को देखना होगा, लेकिन आपका सुझाव इंटरफ़ेस पृथक्करण सिद्धांत की तरह दिखता है, जो SOLID कोड का हिस्सा है। यह एक बुरी चीज नहीं हो सकती है :) – jrahhali

+0

मैंने जिन तरीकों का उल्लेख किया है वे वास्तव में सेवा (व्यापार) परत का हिस्सा हैं। हम डीडीडी का उपयोग नहीं कर रहे हैं। हमारे कार्यान्वयन में, एमवीसी नियंत्रक "सेवाओं" (कर्मचारी सेवा, ग्राहक सेवा के आधार पर नामित वस्तुओं) का उपयोग करते हैं, जो ऊपर दिए गए इंटरफेस को लागू करते हैं। वे एंटीटी फ्रेमवर्क में लागू एक और परत में रिपोजिटरी का "उपयोग" करते हैं, जिनमें बहुत समान इंटरफेस होते हैं। – Scott

उत्तर

10

कि सब के सब Repository pattern ...

public interface IRepository<TEntity> where TEntity : IEntity 
{ 
    T FindById(string Id); 
    T Create(T t); 
    bool Update(T t); 
    bool Delete(T t); 
} 

public interface IEntity 
{ 
    string Id { get; set; } 
} 

संपादित

का उपयोग कर हमारी प्रणाली में कोई ठोस वस्तुओं कई इंटरफेस को लागू एकजुट किया जा सकता है।

क्या कोई मुझे बता सकता है कि क्या यह सड़क के नीचे समस्याएं पैदा कर रहा है? और यदि हां, तो वे क्या होंगे?

हां, इससे समस्याएं पैदा हो जाएंगी यदि यह पहले से ही शुरू नहीं हुई है।

आप इंटरफेस का एक गुच्छा समाप्त कर देंगे जो आपके समाधान में कुछ भी नहीं जोड़ता है, बनाए रखने और उन्हें बनाए रखने में आपके समय का एक बड़ा हिस्सा निकाल देता है। चूंकि आपका कोड बेस आकार में बढ़ता है, आप पाएंगे कि सब कुछ एक जैसा नहीं है जैसा कि आपने एक बार सोचा था कि

याद रखें कि इंटरफेस केवल एक उपकरण है, जो एक अमूर्तता के स्तर को लागू करने के लिए एक उपकरण है। जबकि अमूर्त एक अवधारणा है, एक पैटर्न, एक प्रोटोटाइप है कि कई अलग-अलग इकाइयां साझा करती हैं।

आप इस अभिव्यक्त किया गया है,

यह भंडार पैटर्न के बारे में नहीं है - यह किसी भी परत में इंटरफेस है कि देखने के लिए वे शब्दार्थतः पहचान व्यवहार का हिस्सा की तरह के बारे में है। क्या इन परिचालनों के लिए आम इंटरफेस प्राप्त करने और "उप-इंटरफेस" को उनके द्वारा प्राप्त करने के लायक है?

इस बारे में interfaces नहीं, तो इस बारे में abstractions है, Repository pattern दर्शाता है कि कैसे आप सार दूर व्यवहार है कि है एक विशेष वस्तु के अनुरूप कर सकते हैं।

मैंने जो उदाहरण दिया है, उसके पास AddEmployee या UpdateEmployee नामक कोई भी विधि नहीं है ... ऐसी विधियां केवल उथले इंटरफेस हैं, अबास्ट्रक्शन नहीं।

Repository pattern की अवधारणा स्पष्ट है कि यह व्यवहार के एक सेट को परिभाषित करता है जो कई अलग-अलग वर्गों द्वारा लागू किया जाता है, प्रत्येक एक विशेष इकाई के लिए बनाया गया है।

यह मानते हुए कि प्रत्येक इकाई (उपयोगकर्ता रिपोजिटरी, ब्लॉग रिपोजिटरी इत्यादि) के लिए एक रिपोजिटरी लागू की गई है और यह मानते हुए कि प्रत्येक रिपोजिटरी को कार्यक्षमता के कोर सेट (मूल सीआरयूडी ऑपरेशंस) का समर्थन करना चाहिए, हम कार्यक्षमता के उस कोर सेट को ले सकते हैं और इसे परिभाषित कर सकते हैं एक इंटरफेस में, और फिर प्रत्येक रिपोजिटरी में उस इंटरफ़ेस को लागू करें।

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

public interface IVehicleOperator<TVehicle> where TVehicle : IVehicle 
{ 
    void Accelerate(); 
    void Brake(); 
} 

ऐसा करने में हमारे पास 1: 1 मैपिंग नहीं है, बल्कि इसके बजाय एक वास्तविक अमूर्तता है।

जबकि हम इस विषय पर हैं, तो decorator pattern की समीक्षा करने के लायक भी हो सकता है।

+0

@Scott मुझे बताएं कि क्या यह आपके प्रश्न का उत्तर देता है –

+0

उत्कृष्ट उत्तर, लेकिन मैं नहीं देख सकता कि दूसरा उदाहरण एक भंडार पैटर्न क्यों है। यह जेनेरिक का उपयोग कर एक अच्छा इंटरफेस की तरह दिखता है। –

+0

आप सही नहीं हैं, मैं जो प्रदर्शित करना चाहता था वह था कि हम मौजूदा डिजाइन पैटर्न से विचार और अवधारणाएं ले सकते हैं और उन्हें कहीं और भी उपयोग कर सकते हैं, कि जब आप 'IVehicleOperator को देखते हैं तो उन्हें विशिष्ट मामलों तक ही सीमित नहीं होना चाहिए 'और' आईरिपोजिटरी ', जो वास्तव में अलग है, वह नाम है, शेष कोड अबास्ट्रक्शन है ... –

9

को देखते हुए यह:

interface ICustomer{ 
    void AddCustomer(Customer toAdd); 
    void UpdateCustomer(Customer toUpdate); 
    Customer GetById(int customerId); 
} 

interface IEmployee 
{ 
    void AddEmployee(Employee toBeAdded); 
    void UpdateEmployee(Employee toUpdate); 
    Employee GetById(int employeeId);  
} 

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

interface IRepository<T> 
{ 
    void Add(T toAdd); 
    void Update(T toUpdate); 
    T GetById(int id); 
} 

बहरहाल, यह अभी भी बहुत अच्छी तरह से Interface Segregation Principle का उल्लंघन हो सकता है, कि उल्लेख करने के लिए नहीं है, क्योंकि यह Command-Query Responsibility Segregationपैटर्न (आर्किटेक्चर नहीं) का भी उल्लंघन करता है, इसे न तो सह-न ही contravariant बनाया जा सकता है।आप देख सकते हैं कि IAdder<T> और IUpdater<T> संरचनात्मक रूप से समान हैं

interface IAdder<T> 
{ 
    void Add(T toAdd); 
} 

interface IUpdater<T> 
{ 
    void Update(T toAdd); 
} 

interface IReader<T> 
{ 
    T GetById(int id); 
} 

इसके अलावा, (वे केवल शब्दार्थ अलग हैं), तो उन्हें बनाने क्यों नहीं:

इस प्रकार, मेरी अगला कदम इन Role Interfaces में विभाजित करने के लिए हो सकता है एक:

interface ICommand<T> 
{ 
    void Execute(T item); 
} 

संगत के लिए, आप IReader<T> रूप में अच्छी तरह नाम बदलने सकता है:

interface IQuery<T> 
{ 
    T GetById(int id); 
} 

अनिवार्य रूप से, आप इन दो इंटरफेस में सब कुछ को कम कर सकते हैं, लेकिन कुछ लोगों के लिए यह बहुत सार हो सकता है, और बहुत कम अर्थपूर्ण जानकारी ले सकता है।

हालांकि, मुझे नहीं लगता कि बेहतर जवाब प्रदान करना संभव है, क्योंकि आधार त्रुटिपूर्ण है। प्रारंभिक सवाल यह है कि इंटरफ़ेस को कैसे डिज़ाइन किया जाना चाहिए, लेकिन क्लाइंट में कहीं भी नहीं है। APPP च। 11 हमें सिखाता है, "क्लाइंट [...] अमूर्त इंटरफेस का मालिक है" - दूसरे शब्दों में, क्लाइंट इंटरफ़ेस को परिभाषित करता है, इसकी आवश्यकता के आधार पर। कंक्रीट कक्षाओं से इंटरफेस निकाले नहीं जाना चाहिए।

इस विषय पर आगे अध्ययन सामग्री: जैसे आप एक सामान्य भंडार की जरूरत

+0

हाय मार्क, मान लीजिए या नहीं मैंने आपके प्लुरसाइट कोर्स को देखा है! यही कारण है कि मैंने आरएपी को पहली जगह में देखा, हमारे इंटरफेस "गंध"। मैंने आपके ब्लॉग को देखा लेकिन समझ में नहीं आया कि अतिरिक्त प्रयास क्यों आवश्यक था। मुझे टीम को फिर से काम करने की जरुरत है। – Scott

+3

आरएपी ज्यादातर कोड आधार की वांछनीय गुणवत्ता का विवरण है। पुन: उपयोग किए गए abstractions की कमी अक्सर एक * लक्षण * है कि एक कोड बेस [एलएसपी] (http://en.wikipedia.org/wiki/Liskov_substitution_principle) का उल्लंघन करता है। यह * जरूरी * बुरा नहीं है। कोड (रखरखाव, ज्यादातर) के साथ कुछ समस्याओं को हल करने के लिए ठोस सिद्धांत मौजूद हैं। यदि आपके पास उन समस्याएं नहीं हैं, तो 'समाधान' लागू करने का प्रयास करने का कोई कारण नहीं है। –