फ़ंक्शन कॉल में एकाधिक तर्क एकल सरणी बनाम


24

मेरे पास एक फ़ंक्शन है जो मापदंडों के एक सेट में लेता है, फिर उन पर SQL क्वेरी की शर्तों के रूप में लागू होता है। हालाँकि, जब मैंने स्वयं के शर्तों वाले एकल तर्क सरणी का पक्ष लिया:

function searchQuery($params = array()) {
    foreach($params as $param => $value) {
        switch ($param) {
            case 'name':
                $query->where('name', $value);
                break;
            case 'phone':
                $query->join('phone');
                $query->where('phone', $value);
                break;
        }
    }
}

मेरे सहयोगी ने इसके बजाय सभी तर्कों को स्पष्ट रूप से सूचीबद्ध करना पसंद किया:

function searchQuery($name = '', $phone = '') {
    if ($name) {
        $query->where('name', $value);
    }

    if ($phone) {
        $query->join('phone');
        $query->where('phone', $value);
    }
}

उनका तर्क यह था कि तर्कों को स्पष्ट रूप से सूचीबद्ध करने से, फ़ंक्शन का व्यवहार अधिक स्पष्ट हो जाता है - जैसा कि रहस्यमय तर्क क्या था यह पता लगाने के लिए कोड में तल्लीन करने के लिए $param

मेरी समस्या यह थी कि 10+ जैसे बहुत सारे तर्कों के साथ काम करते समय यह बहुत अधिक हो जाता है। क्या कोई पसंदीदा अभ्यास है? मेरी सबसे खराब स्थिति कुछ इस तरह दिखाई देगी:

searchQuery('', '', '', '', '', '', '', '', '', '', '', '', 'search_query')


1
यदि फ़ंक्शन विशिष्ट कुंजियों को पैरामीटर के रूप में अपेक्षा करता है, तो कम से कम उन कुंजियों को एक डॉकलॉक में दर्ज़ किया जाना चाहिए - जिस तरह से आईडीई कोड में तल्लीन किए बिना संबंधित जानकारी दिखा सकता है। en.wikipedia.org/wiki/PHPDoc
इलारी काजस्ट

2
प्रदर्शन टिप: foreachइस उदाहरण में अनावश्यक है, आप if(!empty($params['name']))इसके बजाय foreachऔर का उपयोग कर सकते हैं switch
चिबॉर्ग

1
अब आपके पास एक विधि है जिसका आप उपयोग करते हैं। मैं यहाँ एक नज़र रखने का सुझाव दूंगा : book.cakephp.org/2.0/en/models/… अधिक विधियाँ बनाने के लिए। वे मानक खोज के लिए जादुई रूप से उत्पन्न हो सकते हैं और विशिष्ट खोजों के लिए कस्टम में विकसित किए जा सकते हैं। सामान्य तौर पर जो मॉडल के उपयोगकर्ताओं के लिए एक स्पष्ट एपीआई बनाता है।
ल्यूक फ्रेंकिन


2
ऊपर 'प्रदर्शन टिप' पर एक नोट: !empty($params['name'])मापदंडों के लिए परीक्षण करने के लिए नेत्रहीन उपयोग न करें - उदाहरण के लिए, स्ट्रिंग "0" खाली होगा। array_key_existsकुंजी की जांच के लिए उपयोग करना बेहतर है , या issetयदि आप परवाह नहीं करते हैं null
AmadeusDrZaius

जवाबों:


27

उपरोक्त उदाहरण के लिए आपका सहयोगी IMHO सही है। हो सकता है कि आपकी प्राथमिकता चर्चित हो, लेकिन यह भी कम पठनीय है और इसलिए कम बनाए रखने योग्य है। सवाल पूछें कि फ़ंक्शन को पहले लिखने में क्यों परेशान करें, आपका फ़ंक्शन 'तालिका में क्या लाता है- मुझे यह समझना होगा कि यह क्या करता है और यह कैसे करता है, महान विवरण में, बस इसका उपयोग करने के लिए। उनके उदाहरण के साथ, भले ही मैं एक PHP प्रोग्रामर नहीं हूं, मैं फ़ंक्शन घोषणा में पर्याप्त विवरण देख सकता हूं कि मुझे इसके कार्यान्वयन के साथ खुद को परेशान करने की आवश्यकता नहीं है।

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


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

2
@xiankai उस उदाहरण में, मैं शायद whereतर्क के लिए एक सरणी परम , विशेषकों के लिए एक joinआदि बनाऊं। उन्हें उचित रूप से नामित करके जो अभी भी स्व-दस्तावेजीकरण होगा।
जनवरी डॉगजेन

यदि मैं बदले में सेटर / गेट्टर का उपयोग करता हूं और मैं तर्क को पारित नहीं करता हूं तो क्या होगा? क्या यह एक बुरा अभ्यास है? क्या यह सेटर / गेट्टर का उपयोग करने का उद्देश्य नहीं है?
lyhong

मैं चुनौती दूंगा कि ओपी की प्राथमिकता "कम पठनीय" (कैसे?) और कम रख-रखाव है। SearchQuery ('', '', '', '', 'फू', '', '', '', '' '' '' '' '' '' '' ('' q '=>' फू '') की तुलना में कहीं कम पठनीय या प्राप्य है। 'x' => 'बार']) बड़ी संख्या में तर्क गैर-जरूरी है, कोड-गंध भी है; एक क्वेरी (), उदाहरण के लिए। और यहां तक ​​कि तर्कों की एक छोटी संख्या के लिए, तर्क क्रम में निरंतरता की कमी जो तब होती है जब तर्क सीधे पारित होते हैं, यह दर्शाता है कि हार्डकोड मापदंडों के लिए एक बुरा विचार क्या है। बस विसंगति के लिए PHP में स्ट्रिंग और सरणी कार्यों को देखें।
२०:१० पर माइकस्किंकेल

4

मेरा जवाब कमोबेश भाषा अज्ञेय है।

यदि एक जटिल डेटा संरचना (तालिका, रिकॉर्ड, शब्दकोश, वस्तु ...) में तर्कों को समूहीकृत करने का एकमात्र उद्देश्य उन्हें एक पूरे के रूप में पारित करना है, तो बेहतर है कि इससे बचें। यह जटिलता की एक बेकार परत जोड़ता है और आपके इरादे को अस्पष्ट बनाता है।

यदि समूहीकृत तर्कों का अपने आप से एक अर्थ है, तो जटिलता की वह परत पूरे डिजाइन को समझने में मदद करती है: इसके बजाय इसे अमूर्त की परत का नाम दें।

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


1

आपके मामले में, मैं आपके सहयोगी की विधि को प्राथमिकता दूंगा। यदि आप मॉडल लिख रहे थे और मैं उन पर विकसित करने के लिए आपके मॉडल का उपयोग कर रहा था। मुझे आपके सहकर्मी की विधि के हस्ताक्षर दिखाई देते हैं और इसे तुरंत उपयोग कर सकते हैं।

हालांकि, मुझे आपके searchQueryफ़ंक्शन के कार्यान्वयन के माध्यम से जाना होगा कि आपके फ़ंक्शन द्वारा क्या पैरामीटर अपेक्षित हैं।

मैं केवल उस मामले में आपके दृष्टिकोण को पसंद करूंगा जब वह searchQueryकेवल एक तालिका के भीतर खोज तक सीमित हो, इसलिए इसमें कोई जोड़ नहीं होगा। उस स्थिति में मेरा कार्य इस तरह दिखेगा:

function searchQuery($params = array()) {
    foreach($params as $param => $value) {
        $query->where($param, $value);
    }
} 

तो, मुझे तुरंत पता है कि सरणी के तत्व वास्तव में एक विशेष तालिका के स्तंभ नाम हैं जो इस पद्धति वाले वर्ग को आपके कोड में दर्शाते हैं।


1

दोनों करो, की तरह। array_mergeफ़ंक्शन के शीर्ष पर एक स्पष्ट सूची के लिए अनुमति देता है, जैसा कि आपके सहकर्मी पसंद करते हैं, जबकि आप चाहते हैं कि मापदंडों को अनैच्छिक होने से रखते हैं।

मैं प्रश्न टिप्पणियों से @ चिबॉर्ग के सुझाव का उपयोग करने का दृढ़ता से सुझाव देता हूं - यह बहुत स्पष्ट है कि आप क्या इरादा रखते हैं।

function searchQuery($params = array()) {
    $defaults = array(
        'name' => '',
        'phone' => '',
        ....
    );
    $params = array_merge($defaults, $params);

    if(!empty($params['name'])) {
        $query->where('name', $params['name']);
    }
    if (!empty($params['phone'])) {
        $query->join('phone');
        $query->where('phone', $params['phone']);
    }
    ....
}

0

इसके अलावा, आप एक क्वेरी स्ट्रिंग जैसा दिखने वाला एक स्ट्रिंग पास कर सकते हैं, और उपयोग कर सकते हैं parse_str(क्योंकि ऐसा लगता है कि आप PHP का उपयोग कर रहे हैं, लेकिन अन्य समाधान संभवतः अन्य भाषाओं में उपलब्ध हैं) इसे विधि के अंदर एक सरणी में संसाधित करने के लिए:

/**
 * Executes a search in the DB with the constraints specified in the $queryString
 * @var $queryString string The search parameters in a query string format (ie
 *      "foo=abc&bar=hello"
 * @return ResultSet the result set of performing the query
 */
function searchQuery($queryString) {
  $params = parse_str($queryString);
  if (isset($params['name'])) {
    $query->where('name', $params['name']);
  }
  if (isset($params['phone'])) {
    $query->join('phone');
    $query->where('phone', $params['phone']);
  }
  ...

  return ...;
}

और इसे कॉल करें

$result = searchQuery('name=foo&phone=555-123-456');

आप http_build_queryएक साहचर्य सरणी से स्ट्रिंग में परिवर्तित करने के लिए उपयोग कर सकते हैं (रिवर्स जो parse_strकरता है)।

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