यदि एल्स - बार-बार कोड लॉजिक


15

मेरे बॉस ने मुझे एक विशेष तर्क के साथ एक प्रोजेक्ट दिया। मुझे एक वेब पेज विकसित करना होगा जिसमें उत्पाद पर पहुंचने तक उसे कई मामलों में नाविक का नेतृत्व करना होगा।

यह साइट में नेविगेशन की पथ योजना है:

पथ योजना

महत्वपूर्ण!

उत्पाद पृष्ठ में नेविगेटर यह चुन सकता है कि उसे कौन सा फ़िल्टर चाहिए।

  • यदि A, वह / वह अवश्य B (और तब C) या C से गुजरता है और उत्पादों तक पहुँचता है।
  • यदि B, वह / वह अवश्य C से गुजरता है और उत्पादों तक पहुँचता है।
  • यदि C, वह सीधे उत्पादों पर पहुंचता है।

बेशक अगर मैं AI से शुरू करता हूं तो सबसे लंबे रास्ते का अनुसरण कर रहा हूं और जब मैं अपने उत्पादों तक पहुंचता हूं तो मेरे पास 3 सक्रिय फिल्टर होते हैं।

अब तक मैंने निम्नलिखित कोड विकसित किया है जो ठीक काम करता है।

if filter_A
  if filter_B
     filter_C()
     .. else ..
  else
     filter_C
    .. else ..
else
   if filter_B
      filter_C()
     .. else ..
   else
     filter_C()
     .. else ..

मैं यह पूछने के लिए यहां हूं कि इस स्थिति में एक अधिक विशेषज्ञ प्रोग्रामर ने क्या किया होगा। मैंने DRY सिद्धांत का सम्मान नहीं किया, मुझे यह पसंद नहीं है और मैं इस तरह के तर्क को विकसित करने का एक वैकल्पिक तरीका जानना चाहता हूं।

मैंने फ़ंक्शंस में कोड के हर सेक्शन को विभाजित करने के बारे में सोचा था लेकिन क्या इस मामले में यह एक अच्छा विचार है?



नियंत्रण प्रवाह आरेख सभी नियंत्रण को दर्शाता है filter_C, लेकिन सशर्त विवरण यह दर्शाता है कि नियंत्रण प्रवाह चारों ओर जा सकता है filter_C। है filter_Cवैकल्पिक?
कर्टिसहैक्स

@CurtisHx फ़िल्टर C अनिवार्य है। क्षमा करें, मेरी गलती है कि मैंने कॉपी-पेस्ट किया।
केविन सिटाडिनी

2
यह प्रश्न भाषा-अज्ञेय कैसे हो सकता है ? जावा में एक मुहावरेदार समाधान हास्केल में एक मुहावरेदार समाधान से बहुत अलग होगा। क्या आपने अपने प्रोजेक्ट के लिए किसी भाषा पर फैसला नहीं किया है?
२३

जवाबों:


20

आपने यह नहीं कहा है कि क्या फ़िल्टर किसी भी पैरामीटर को लेते हैं। उदाहरण के लिए,filter_A एक श्रेणी फ़िल्टर हो सकता है, ताकि यह केवल "क्या मुझे आवेदन करने की आवश्यकता नहीं है" का सवाल है filter_A, यह "मुझे filter_Aश्रेणी फ़ील्ड = fooCategory" के साथ सभी रिकॉर्ड लागू करने और वापस करने की आवश्यकता हो सकती है ।

आपके द्वारा बताए गए तरीके को लागू करने का सबसे सरल तरीका (लेकिन नीचे दिए गए उत्तर के उत्तरार्ध को पढ़ना सुनिश्चित करें) अन्य उत्तरों के समान है, लेकिन मेरे पास बूलियन चेक बिल्कुल नहीं होगा। मैं इंटरफेस को परिभाषित करेगा FilterA, FilterB, FilterC:। फिर आपके पास कुछ हो सकता है (मैं एक जावा प्रोग्रामर हूं, इसलिए यह जावा-एस्क सिंटैक्स होगा))

class RequestFilters {
    FilterA filterA;
    FilterB filterB;
    FilterC filterC;
}

तब आपके पास ऐसा कुछ हो सकता है ( प्रभावी जावा से एनम सिंगलटन पैटर्न का उपयोग करके ):

enum NoOpFilterA implements FilterA {
    INSTANCE;

    public List<Item> applyFilter(List<Item> input) {
       return input;
    }
}

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

List<Item> filterItems(List<Item> data, RequestFilters filters) {
    List<Item> returnedList = data;
    returnedList = filters.filterA.filter(data);
    returnedList = filters.filterB.filter(data);
    returnedList = filters.filterC.filter(data);
    return returnedList;
}

लेकिन मैं अभी शुरुआत कर रहा हूं।

मुझे संदेह है कि applyFilterकॉल वास्तव में सभी तीन प्रकार के फिल्टर के लिए समान होगा। अगर ऐसा है, तो मैं इसे ऊपर वर्णित तरीके से भी नहीं करूंगा। आप केवल एक इंटरफ़ेस के द्वारा भी क्लीनर कोड प्राप्त कर सकते हैं, फिर ऐसा कर रहे हैं:

class ChainedFilter implements Filter {
     List<Filter> filterList;

     void addFilter(Filter filter) {
          filterList.add(filter);
     }

     List<Item> applyFilter(List<Item> input) {
         List<Item> returnedList = input;
         for(Filter f : filterList) {
             returnedList = f.applyFilter(returnedList);
         }
         return returnedList;
     }
}

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

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


धन्यवाद, क्योंकि आपको कोड बदलने के साथ-साथ बिना तर्क बदलने का सबसे सरल तरीका संभव लगता है। यह आपके उत्तर को सर्वश्रेष्ठ बनाता है। मैं इस कोड डिज़ाइन ASAP
केविन Cittadini

यदि आप अपने था Filterएक के रूप में Predicateआप इसे सीधे इस्तेमाल कर सकते हैं तो Streamएपीआई। कई भाषाओं में समान कार्यात्मक निर्माण होते हैं।
बोरिस स्पाइडर

3
@BoristheSpider जावा 8 का उपयोग करने पर ही यह होता है; उन्होंने यह भी नहीं कहा कि वह किस भाषा का उपयोग कर रहे थे। अन्य भाषाओं में इस तरह का एक निर्माण होता है, लेकिन मैं यह नहीं करना चाहता कि सभी अलग-अलग स्वादों में कैसे जाना है
ड्यूर्रोन 597

3
समझ में आया - यह केवल यह ध्यान देने योग्य है कि ओपी सबसे स्वच्छ संभव कार्यान्वयन प्रदान करना चाहता है या नहीं। आपके पास निश्चित रूप से पहले से ही उत्कृष्ट उत्तर के लिए मेरा +1 है।
बोरिस स्पाइडर

3

इस मामले में, फ़िल्टरिंग के तर्क को अलग करना महत्वपूर्ण है, और फ़िल्टर कैसे चलते हैं इसका नियंत्रण प्रवाह। फ़िल्टर तर्क को अलग-अलग कार्यों में अलग किया जाना चाहिए, जो एक दूसरे से स्वतंत्र चल सकते हैं।

ApplyFilterA();
ApplyFilterB();
ApplyFilterC();

नमूना कोड पोस्ट में, वहाँ 3 बूलियन्स है filter_A, filter_B, और filter_C। हालाँकि, आरेख से,filter_C हमेशा चलता है, ताकि बिना शर्त के बदला जा सके।

ध्यान दें: मैं मान रहा हूं कि नियंत्रण प्रवाह आरेख सही है। पोस्ट किए गए नमूना कोड और नियंत्रण प्रवाह आरेख के बीच एक विसंगति है।

कोड नियंत्रण का एक अलग टुकड़ा जो फ़िल्टर चलता है

ApplyFilters(bool filter_A, bool filter_B)
{
    listOfProducts tmp;
    if (filter_A)
        ApplyFilterA();
    if (filter_B)
        ApplyFilterB();
    ApplyFilterC();
}

नियंत्रित करने के बीच एक अलग जुदाई है कि कौन से फ़िल्टर चलते हैं, और फ़िल्टर क्या करते हैं। तर्क के उन दो टुकड़ों को तोड़ दो।


+1 यह बहुत आसान लगता है और स्वीकृत उत्तर की तुलना में कम हो जाता है।
winkbrace

2

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

if filter_a
  do_filter_a()

if filter_b
  do_filter_b()

do_filter_c()

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

optional_filters_array = (a, b, c, d, e, f, g, h, etc)

for current_filter in optional_filters_array
  do_filter(current_filter)

do_required_filter()

या:

optional_filters_array = (a, b, c, d, e, f, g, h, etc)
required_filter = last_filter


for current_filter in optional_filters_array
  do_filter(current_filter)

do_filter(required_filter)

कैसे करें, आपको फ़िल्टर प्रसंस्करण सबरूटीन को परिभाषित करना होगा।


1

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

तो यह मानते हुए कि फिल्टर वास्तव में उत्पादों की सूची को कम करते हैं, यहाँ छद्म कोड है ...

class filter
    func check(item) returns boolean
endclass

func applyFilter(filter, productList) returns list
    newList is list
    foreach item in productList
        if filter.check(item) then
            add item to newList
        endif
    endfor 
    return newList
endfunc



filterA, filterB, filterC = subclasses of filter for each condition, chosen by the user
products = list of items to be filtered

if filterA then
    products = applyFilter(filterA, products)
endif

if filterB then
    products = applyFilter(filterB, products)
endif

if filterC then
    products = applyFilter(filterC, products)
endif

# use products...

आपकी आवश्यकताओं में, फ़िल्टरसी स्वचालित रूप से लागू नहीं होता है, लेकिन आरेख में, यह है। यदि आवश्यकता यह है कि कम से कम फ़िल्टरसी को लागू किया जाना चाहिए, तो कोई बात नहीं, फिर आप फ़िल्टरफ़िल्टर (फ़िल्टरसी, उत्पादों) को बिना जाँच करें कि क्या फ़िल्टरसी चुना जाता है।

filterC = instance of filter, always chosen

...

# if filterC then
products = applyFilter(filterC, products)
# endif

0

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

यदि आप ऑब्जेक्ट ग्राफ़ की तरह फिल्टर की निर्भरता को मॉडल करते हैं, तो संभव प्रवाह पथ को संभालने वाला कोड बिना किसी बालों वाले तर्क के बहुत आगे है। साथ ही, ग्राफ़ (व्यावसायिक तर्क) बदल सकता है, जबकि ग्राफ़ की व्याख्या करने वाला कोड समान रहता है।

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