2011-05-11 7 views
31

मैं मुख्य रूप से जावा डेवलपर हूं। मैंने कुछ जावा देवों से मुलाकात की है जो एओपी से प्यार करते हैं। मैं हाल ही में उभरते हुए अधिक से अधिक एओपी "डिजाइन पैटर्न" देख रहा हूं जो काफी व्यापक रूप से अपनाया जाता है। फिर भी, मुझे अभी भी विश्वास नहीं है कि कुछ कारणों से ओओ कोड में एओपी सामान्य रूप से एक अच्छा विचार है।एओपी क्या कर सकता है कि ओओपी नहीं कर सकता है?

  1. यह अपारदर्शी जटिलता कि डिबग के लिए बेहद मुश्किल हो सकता है के रूप में कोड को "जादू" कहते हैं, और यह अत्यंत कठिन वस्तु उन्मुख कोड यह प्रभावित करता है डिबग करने के लिए कर सकते हैं।

  2. यह ज्यादातर अनावश्यक है, और (खराब) अक्सर इस्तेमाल किया अच्छी तरह से डिजाइन करने के लिए, या पिछले गरीब डिजाइन के लिए क्षतिपूर्ति करने के लिए होने से बचाने के होने के लिए मुझे लगता है।

यहां एक उदाहरण है कि पिछले कुछ सालों में मैं अपने प्रश्न के लिए पृष्ठभूमि के रूप में बहुत कुछ देख रहा हूं।

AOP से पहले (हाइबरनेट डॉक्स से)

public void saveMyEntityToTheDatabase(MyEntity entity) { 
    EntityTransaction tx = null; 
    try { 
     tx = entityManager.getTransaction(); 
     tx.begin(); 
     entityManager.persist(entity); 
     tx.commit(); 
    } catch (RuntimeException e) { 
     if(tx != null && tx.isActive()) { 
      tx.rollback(); 
     } 
     throw e; 
    } 
} 

AOP

@Transactional 
public void saveMyEntityToTheDatabase(MyEntity entity) { 
    entityManager.persist(entity); 
} 

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

एक OO समाधान

public void saveMyEntityToTheDatabase(MyEntity entity) { 
    database.performInTransaction(new Save(entity)); 
} 

यह समाधान मानता है कि database वस्तु व्यवहार तर्क यह है कि पहलू जिम्मेदार कि @Transactional तरीकों का प्रबंधन करता है उसी तरह का होता है। यह ऊपर की मेरी चिंताओं को संबोधित करता है और यह स्पष्ट करता है कि EntityManager के साथ बातचीत का प्रबंधन करने वाला कोई और प्रोग्रामिंग प्रतिमान नहीं पेश करता है।

तो अंततः, मेरा प्रश्न: ओओपी क्या कर सकता है कि ओओपी नहीं कर सकता? मैं ट्रेस लॉगिंग में इसकी उपयोगिता से थोड़ा आश्वस्त हूं, और शायद डिफ़ॉल्ट toString() कार्यान्वयन या कुछ समान है, लेकिन मुझे यह जानना अच्छा लगेगा कि किसी को विशेष प्रकार की समस्याओं के लिए ओओ से काफी बेहतर पाया गया है या नहीं।

+1

AOP, बाईटकोड संशोधन के साथ, उदाहरण के लिए पारदर्शी रूप से (उदाहरण के लिए) 3 पार्टी पुस्तकालयों के लिए कोड soure को संशोधित करने की आवश्यकता के बिना जोड़ सकते हैं। –

+1

@ जोहान, ... जो एओपी कंपाइलर को एक उत्कृष्ट हैकिंग टूल बनाता है। – weekens

+0

@weekens, बिल्कुल - इसे ओओपी के प्रतिस्थापन नहीं बल्कि ओओपी को लागू करने के लिए सुविधाजनक साधन है, कभी-कभी हैक्स द्वारा। –

उत्तर

10

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

निश्चित रूप से वाईएमएमवी।

+0

मुझे यह जवाब पसंद है। आप विक्रेता विकसित पहलुओं के बारे में एक अच्छा मुद्दा बनाते हैं, और मुझे लगता है कि मैं कभी भी उन चीजों के लिए एओपी का उपयोग करूंगा जो जादुई होने की आवश्यकता है। हालांकि, इस संबंध में, मैं काफी संतुष्ट हूं [मुगल] (http://en.wikipedia.org/wiki/Muggle)। – Daniel

12

एओपी ओओ है; पहलू ऑब्जेक्ट्स हैं।

मुझे समझ में नहीं आता कि क्यों या मानसिकता।

एओपी जंजीर, क्रॉस-कटिंग चिंताओं (जैसे लॉगिंग, सुरक्षा, लेनदेन, रिमोट प्रॉक्सीइंग इत्यादि) के लिए एकदम सही विकल्प है।)

अद्यतन:

मुझे लगता है कि ओपी द्वारा की पेशकश की आलोचनाओं व्यक्तिपरक और के रूप में सार्वभौमिक नहीं व्यापक रूप से कहा गया है। सबूत के बिना कहा गया दावा सबूत के बिना खारिज कर दिया जा सकता है।

मुझे जादू का उपयोग करने में विश्वास नहीं है, लेकिन अगर आप इसे समझते हैं तो एओपी जादू नहीं है। मैं यह समझता हूँ। शायद ओपी नहीं करता है। यदि ऐसा है, और ओपी ओओ समाधान के साथ अधिक आरामदायक है, तो मैं कहूंगा कि इसके लिए जाना है।

"मुझे अनावश्यक होने के लिए लगता है" केवल एक राय है, सबूत के बिना पेशकश की जाती है। "मैं असहमत हूं" को छोड़कर इसका कोई जवाब नहीं है।

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

हाथ से लिखित ओओ दृष्टिकोण के साथ प्रयास करें।

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

+0

एओपी ओओ है? ओओपी गुंजाइश से एओपी का उपयोग नहीं कर सका? उदाहरण के लिए कार्यात्मक प्रोग्रामिंग में? –

+0

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

+0

मैं वास्तव में यह AOP इस तरह से देखने के लिए बहुत उपयोगी पाते हैं नहीं है: यह मेरे लिए काफी एक अलग प्रतिमान की तरह लगता है। किसी भी कारण से आप कहेंगे कि यह "सही" विकल्प था (प्रश्न में दो आलोचनाओं के संबंध में)? – Daniel

8

मेरे लिए एओपी Interceptor Pattern का एक शॉर्टेंड है। और इंटरसेप्टर पैटर्न स्वयं Template Method, AFAICS से व्युत्पन्न (या प्रभावित या प्राप्त हुआ) है।

Interceptor का एक लोकप्रिय उदाहरण Servlet Filter है। और हम जानते हैं कि कई मामलों में वे बहुत उपयोगी हैं।

चूंकि, ये सभी पैटर्न उपयोगी हैं, इसलिए एओपी, जो इनसे व्युत्पन्न है, भी उपयोगी है। और जैसा कि आपने स्वयं अपने कुछ उपयोगों को बताया है।

+0

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

6

सामान्य रूप से, फ़ॉर्म के सभी प्रश्न "वह क्या कर सकता है?" अर्थहीन हैं सभी सामान्य प्रयोजन भाषाएं समान रूप से शक्तिशाली हैं (देखें: Church's Thesis)।

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

+0

यह मेरे लिए बहुत ही अल्पकालिक दृश्य जैसा लगता है। मेरे अनुभव में, कम टाइप किए गए वर्ण अपफ्रंट का अनुवाद नहीं करता है "कुछ व्यवहार करने के लिए आपको कितना काम करना है"। रखरखाव कोड में बिताए गए समय का एक बेहतर भविष्यवाणी है। – Daniel

+0

मैंने यह नहीं कहा कि आपको #characters गिनना चाहिए। आप जो भी समय चाहें उस पर प्रयास/लागत की जो भी परिभाषा लेते हैं उसे लें। मेरा मुद्दा यह है कि सभी भाषाओं को बराबर बनाया जाता है। –

1

मेरे लिए अब तक केवल एकमात्र उपयोग केस है, जिसके लिए एओपी निश्चित रूप से ओओपी से बेहतर है विधि कॉल ट्रेसिंग।

+0

यह मेरा अनुभव भी रहा है। मैंने एस्पेक्टजे को बस इसे लागू करने के लिए सीखा! – Daniel

1

मुझे उस एप्लिकेशन में काम करने की दुर्भाग्य है जहां सादे ओओपी का उपयोग करके सेवा कॉल की गई थी। मैं इसे नफरत है, और मैं क्यों आपको बताने के लिए जा रहा हूँ:

पहले, अपने उदाहरण कुछ हद तक साधारण है, के रूप में आम तौर पर लेन-देन की सीमा एक एकल डाटाबेस बातचीत के आसपास नहीं है, लेकिन पूरे कारोबार सेवा मंगलाचरण के आसपास। इसलिए उदाहरण के लिए के निम्नलिखित विधि पर विचार करते हैं:

@Transactional 
public Employee hire(Person p, Employee manager, BigDecimal salary) { 
    // implementation omitted 
} 

जो

Employee hired = service.hire(candidate, manager, agreedOnSalary); 

आपके मामले में का उपयोग कर उत्पन्न होता है, यह बन गयी:

class HireAction implements Callable<Employee> { 
    private final Person person; 
    private final Employee manager; 
    private final BigDecimal salary; 

    public HireAction(Person person, Employee manager, BigDecimal salary) { 
     this.person = person; 
     this.manager = manager; 
     this.salary = salary; 
    } 

    @Override 
    public Employee call() throws Exception { 
     // implementation omitted 
    } 
} 

और

द्वारा लाया
Employee hired = session.doInTransaction(new HireAction(candidate, manager, agreedOnSalary)); 

con यह सुनिश्चित करने के लिए संरक्षक आवश्यक है कि सभी पैरामीटर असाइन किए गए हैं (इसलिए संकलक शिकायत कर सकता है अगर कोई कॉलर अपडेट किए बिना विधि में पैरामीटर जोड़ा जाता है)।

दूसरा दृष्टिकोण निम्नलिखित कारणों के लिए अवर है:

  1. यह सूखी उल्लंघन करता है, के रूप में प्रत्येक पैरामीटर 3 बार उल्लेख किया गया है, और बदले में दो बार टाइप करें। विशेष रूप से, आप पैरामीटर के लिए JavaDoc कहां डालते हैं? क्या आप इसे भी कॉपी करते हैं?
  2. यह सेवा में संबंधित सेवा संचालन को समूह बनाना मुश्किल बनाता है, और उनमें से कोड साझा करता है। हां, आप सभी संबंधित परिचालनों को एक ही पैकेज में रख सकते हैं, और कोड साझा करने के लिए एक सामान्य सुपरक्लास है, लेकिन फिर यह अधिक वर्बोज़ है कि एओपी दृष्टिकोण उन्हें एक ही कक्षा में डालने का तरीका है। या आप की तरह पागल बातें कर सकता है:

    class HRService { 
        class HireAction { 
         // impl omitted 
        } 
        class FireAction { 
         // impl omitted 
        } 
    } 
    

    और

    Employee emp = session.doInTransaction(new HRService().new HireAction(candidate, manager, salary)); 
    
  3. का उपयोग कर एक आवेदन प्रोग्रामर भूल सकता है लेन-देन शुरू करने के लिए यह आह्वान:

    Employee e = new HireAction(candidate, manager, salary).call(); 
    

    या पर लेन-देन शुरू गलत सत्र/डेटाबेस। लेनदेन और व्यापार तर्क विभिन्न चिंताओं, आमतौर पर विभिन्न डेवलपर्स द्वारा हल किया जाता है, और इसलिए अलग किया जाना चाहिए।

संक्षेप में, सादा OOP दृष्टिकोण दोनों के विकास और रखरखाव के दौरान बढ़ी हुई लागत के लिए अग्रणी है, और अधिक वर्बोज़ और त्रुटि की संभावना है।

अंत में, AOP के अपने critism के बारे में:

यह अपारदर्शी जटिलता है कि अत्यंत डिबग करने के लिए कठिन हो सकता है के रूप में कोड करने के लिए "जादू" कहते हैं,

जटिलता हमेशा कठिन है उत्पत्ति के बावजूद, डीबग करने के लिए। मुझे हाइबरनेट स्रोत कोड के साथ कुछ डिबगिंग सत्र याद हैं, जिनके कमांड पैटर्न के न्यायसंगत उपयोग ने मैटर्ड किए गए कोड को ढूंढना मुश्किल नहीं बनाया है।

एओपी इंटरसेप्टर की उपस्थिति गैर-स्पष्ट हो सकती है (हालांकि यदि एक विधि @Transactional पर टिप्पणी की गई है, तो मैं इसे स्पष्ट मानता हूं), यही कारण है कि एओपी को कम से कम इस्तेमाल किया जाना चाहिए (जो कि किसी समस्या की समस्या नहीं है एक परियोजना में पार कटौती चिंताओं आमतौर पर काफी छोटा है)।

और यह प्रभावित करता है डिबग वस्तु उन्मुख कोड के लिए बेहद मुश्किल बना सकते हैं।

ऐसा कैसे? मुझे समस्या नहीं दिखाई दे रही है, लेकिन यदि आप इसका वर्णन करना चाहते थे, तो शायद मैं आपको बता सकता हूं कि मैं इसे कैसे हल/टालना चाहता हूं।

ऐसा लगता है कि मुझे अधिकतर अनावश्यक होना चाहिए, और (बदतर) अक्सर अच्छी तरह से डिजाइन करने से बचने के लिए या पिछले खराब डिजाइन की क्षतिपूर्ति करने के लिए उपयोग किया जाता है।

हर प्रौद्योगिकी खराब इस्तेमाल किया जा सकता। क्या मायने रखता है कि अच्छी तरह से उपयोग करना कितना मुश्किल है, और यदि हम करते हैं तो हम क्या कर सकते हैं।

+0

मैं सहमत हूं: उदाहरण सेवा-स्तर एपीआई के लिए विफल रहता है। मेरा इरादा सिर्फ एक सरल दृष्टिकोण का वर्णन करना था। मुझे लगता है कि आप हाइबरनेट और खराब डिजाइन के बारे में कुछ अच्छे अंक बनाते हैं। – Daniel

संबंधित मुद्दे