Argomenti multipli nella chiamata di funzioni rispetto a un singolo array

23

Ho una funzione che accetta una serie di parametri, quindi li applica come condizioni a una query SQL. Tuttavia, mentre preferivo un array a argomento singolo contenente le condizioni stesse:

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;
        }
    }
}

Il mio collega preferiva elencare esplicitamente tutti gli argomenti invece:

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

    if ($phone) {
        $query->join('phone');
        $query->where('phone', $value);
    }
}
La sua argomentazione era che elencando esplicitamente gli argomenti, il comportamento della funzione diventa più evidente, invece di dover scavare nel codice per scoprire quale fosse l'argomento misterioso $param .

Il mio problema era che questo diventa molto prolisso quando si ha a che fare con molti argomenti, come 10+. C'è qualche pratica preferita? Il mio scenario peggiore vedrebbe qualcosa di simile al seguente:

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

    
posta xiankai 01.10.2013 - 08:03
fonte

5 risposte

27

IMHO il tuo collega è corretto per l'esempio sopra. La tua preferenza potrebbe essere concisa, ma è anche meno leggibile e quindi meno manutenibile. Poni la domanda perché preoccuparsi di scrivere la funzione, in primo luogo, che cosa fa la tua funzione 'portare sul tavolo' - Devo capire cosa fa e come lo fa, in grande dettaglio, solo per usarlo. Con il suo esempio, anche se non sono un programmatore PHP, posso vedere abbastanza dettagli nella dichiarazione della funzione che non devo preoccuparmi della sua implementazione.

Per quanto riguarda un numero maggiore di argomenti, questo è normalmente considerato un odore di codice. In genere la funzione sta cercando di fare troppo? Se si trova un'esigenza reale per un numero elevato di argomenti, è probabile che siano correlati in qualche modo e appartengano in una o poche strutture o classi (forse anche una serie di elementi correlati come le linee in un indirizzo). Tuttavia, il passaggio di un array non strutturato non fa nulla per risolvere gli odori del codice.

    
risposta data 01.10.2013 - 08:36
fonte
4

La mia risposta è più o meno agonostica della lingua.

Se l'unico scopo di raggruppare gli argomenti in una struttura di dati complessa (tabella, record, dizionario, oggetto ...) è passarli nel loro complesso a una funzione, meglio evitarlo. Ciò aggiunge un inutile livello di complessità e rende oscure le tue intenzioni.

Se gli argomenti raggruppati hanno un significato da soli, allora quel livello di complessità aiuta a comprendere l'intero progetto: nominalo invece un livello di astrazione.

Potresti scoprire che invece di una dozzina di singoli argomenti o un grande array, il miglior design è con due o tre argomenti, ognuno dei quali raggruppa i dati correlati.

    
risposta data 01.10.2013 - 09:23
fonte
1

Nel tuo caso, preferirei il metodo del tuo collega. Se stavi scrivendo modelli e stavo usando i tuoi modelli per svilupparli. Vedo la firma del metodo del tuo collega e posso usarlo immediatamente.

Mentre dovrei passare attraverso l'implementazione della tua funzione searchQuery per vedere quali parametri sono previsti dalla tua funzione.

Preferirei il tuo approccio solo nel caso in cui searchQuery è limitato alla ricerca solo all'interno di una singola tabella, quindi non ci saranno join. In questo caso la mia funzione sarebbe simile a questa:

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

Quindi, so immediatamente che gli elementi della matrice sono in realtà i nomi delle colonne di una particolare tabella che la classe che ha questo metodo rappresenta nel codice.

    
risposta data 01.10.2013 - 09:21
fonte
1

Fai entrambi, una specie di. array_merge consente una lista esplicita nella parte superiore della funzione, come piace al tuo collega, pur mantenendo i parametri non troppo complessi, come preferisci.

Raccomando caldamente di utilizzare il suggerimento di @ chiborg nei commenti delle domande: è molto più chiaro ciò che intendi.

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']);
    }
    ....
}
    
risposta data 01.10.2013 - 17:13
fonte
0

Potresti anche passare una stringa simile a una stringa di query e usare parse_str (perché sembra che tu stia usando PHP, ma altre soluzioni sono probabilmente disponibili in altre lingue) per elaborarle in un array all'interno del metodo:

/**
 * 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 ...;
}

e chiamalo come

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

Puoi usare http_build_query per convertire da un array associativo a una stringa (il contrario che parse_str fa ).

    
risposta data 01.10.2013 - 14:48
fonte

Leggi altre domande sui tag