함수 호출의 다중 인수 대 단일 배열


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
함수가 특정 키를 매개 변수로 기대하는 경우 적어도 해당 키를 DocBlock에 문서화해야합니다. 이렇게하면 IDE에서 코드를 조사하지 않고도 관련 정보를 표시 할 수 있습니다. en.wikipedia.org/wiki/PHPDoc
Ilari Kajaste

2
성능 팁 :이 foreach경우에는가 필요하지 if(!empty($params['name']))않으며 foreach및 대신 사용할 수 있습니다 switch.
chiborg

1
이제 사용하는 방법이 하나 있습니다. 더 많은 메소드를 작성 하려면 book.cakephp.org/2.0/en/models/… 를 참조 하십시오 . 표준 검색을 위해 마술처럼 생성하고 특정 검색을 위해 사용자 정의로 개발할 수도 있습니다. 일반적으로 이는 모델 사용자에게 명확한 API를 제공합니다.
Luc Franken


2
위의 '성능 팁'에 대한 참고 사항 : 맹목적으로 !empty($params['name'])매개 변수를 테스트 하는 데 사용하지 마십시오. 예를 들어 문자열 "0"은 비어 있습니다. array_key_exists키를 확인하거나 isset신경 쓰지 않는 경우 사용 하는 것이 좋습니다 null.
AmadeusDrZaius

답변:


27

IMHO 동료는 위의 예에 맞습니다. 선호도는 간결 할 수 있지만 읽기 어렵고 유지 관리하기가 쉽지 않습니다. 처음에 함수를 작성하는 것이 왜 귀찮은 지, 함수가 무엇을 '테이블에 가져다 놓는'지 질문하십시오. 어떻게 무엇을하는지, 어떻게 사용하는지 이해해야합니다. 그의 예제를 사용하면 PHP 프로그래머는 아니지만 함수 선언에서 구현에 대해 신경 쓸 필요가없는 세부 사항을 충분히 볼 수 있습니다.

더 많은 수의 인수는 일반적으로 코드 냄새로 간주됩니다. 일반적으로 함수가 너무 많은 것을 시도하고 있습니까? 많은 수의 인수가 실제로 필요한 경우 인수가 어떤 방식으로 관련되어 있고 하나 또는 몇 개의 구조 또는 클래스 (주소의 행과 같은 관련 항목의 배열 일 수도 있음)에 함께 속해있을 수 있습니다. 그러나 구조화되지 않은 배열을 전달하면 코드 냄새를 해결하는 데 아무런 도움이되지 않습니다.


많은 수의 인수가 필요한 경우, 함수는 본질적으로 0 개 이상의 인수를 취한 다음 해당 인수에 의해 설정된 결과를 제한합니다. 인수 자체는 서로 다른 SQL 절과 관련이 없으며 동일한 구조를 갖지 않을 수도 있습니다 (하나는 간단한 WHERE 일 수 있지만 다른 하나는 WHERE 외에도 여러 개의 JOIN이 필요함). 이 특정 경우에도 여전히 코드 냄새로 간주됩니까?
xiankai

2
@xiankai이 예제에서는 where인수에 대해 하나의 배열 매개 변수를 join지정하고 지정자에 대해 하나의 배열 매개 변수를 작성할 수 있습니다. 적절하게 이름을 지정하면 자체 문서화가됩니다.
Jan Doggen

대신 setter / getter를 사용하고 인수를 전혀 전달하지 않으면 어떻게됩니까? 나쁜 습관입니까? setter / getter를 사용할 목적이 아닙니까?
lyhong

OP의 선호도가 "읽기 어렵고"(어떻게?) 유지 관리가 쉽지 않다는 것에 도전합니다. searchQuery ( '', '', '', '', 'foo', '', '', '', 'bar')는 searchQuery ([ 'q'=> 'foo', 'x'=> 'bar']) 많은 수의 인수는 불필요하게 코드 냄새가 아닙니다. 예를 들어 query (). 그리고 더 적은 수의 인수라도 인수가 전달 될 때 발생하는 인수 순서의 일관성 부족은 매개 변수를 하드 코딩하는 것이 얼마나 나쁜 아이디어인지 직접 보여줍니다. 불일치에 대해서는 PHP의 문자열 및 배열 함수를 살펴보십시오.
MikeSchinkel

4

내 대답은 다소 언어에 구애받지 않습니다.

복잡한 데이터 구조 (테이블, 레코드, 사전, 객체 ...)에서 인수를 그룹화하는 유일한 목적이 함수 전체에 인수를 전달하는 것이라면 피하는 것이 좋습니다. 이것은 쓸모없는 복잡성의 계층을 추가하고 의도를 모호하게 만듭니다.

그룹화 된 인수가 그 자체로 의미가있는 경우 해당 복잡성 계층은 전체 디자인을 이해하는 데 도움이됩니다. 대신 추상화 계층이라는 이름을 지정하십시오.

수십 개의 개별 인수 또는 하나의 큰 배열 대신 최상의 설계는 각각 관련 데이터를 그룹화하는 두 세 개의 인수를 사용하는 것입니다.


1

귀하의 경우 동료의 방법을 선호합니다. 당신이 모델을 작성하고 있고 모델을 개발하기 위해 모델을 사용하고 있다면. 동료의 방법의 서명을보고 즉시 사용할 수 있습니다.

그러나 searchQuery함수에서 예상되는 매개 변수를 확인하려면 함수 구현을 거쳐야 합니다.

searchQuery단일 테이블 내에서만 검색하도록 제한된 경우 에만 조인이 없으므로 접근 방식을 선호합니다 . 이 경우 내 기능은 다음과 같습니다.

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

따라서 배열의 요소는 실제로이 메서드를 사용하는 클래스가 코드에서 나타내는 특정 테이블 의 열 이름이라는 것을 즉시 알고 있습니다.


1

둘 다하세요. array_merge동료가 좋아하는대로 함수의 맨 위에 명시 적 목록을 허용하면서 원하는대로 매개 변수가 다루기 어려워지지 않도록합니다.

또한 질문 의견에서 @chiborg의 제안을 사용하는 것이 좋습니다. 원하는 것이 훨씬 명확합니다.

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) 로 변환 하는 데 사용할 수 있습니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.