변수

2010-06-07 3 views
1

을 설정하는 배열을 전달 나는 종종이 관용구를 참조하십시오변수

public function __construct($config) 
{ 
    if (array_key_exists('options', $config)) { 
     ... 
    } 
    if (array_key_exists('driver_options', $config)) { 
     ... 
    } 
} 

가 여기이 매개 변수를 사용하는 방식에 관심입니다.

(defun ct (&key options driver_options) 
     (do-something-with-option-and-driver_option)) 

을하지만 PHP에서 오전 이후 오히려 매개 변수의 목록을 생성자를 가지고 있고이 필요하지 않을 경우이를 null이 될 수 있도록 다음과 같습니다 내가 혀짤배기에 있다면 내가 할 것입니다.

다른 초기화에서 매개 변수로 배열을 사용하는 것에 대해 어떻게 생각하십니까?

답을 얻으려면 함수 사용자와 API 디자이너의 관점을 고려해야합니다.

혹시 이것이 코드 냄새라고 들었습니까?

감사

편집 : 나는 또한 당신이 배열 매개 변수와 관련된 몇 가지 질문/문제를 해결하는 것입니다. 특히 당신은 @Brent Baisley보다 같은 대답을 가지고

  • @ircmaxell 경우 당신이 배열의 키를 잘못 입력하는 경우?
  • 함수/메서드에 아무런 의미가없는 키가 있으면 어떻게됩니까?
+0

PHP 스 니펫이 대답 일 것 같아서 질문에 혼란 스럽습니다. 구문은 배열에 전달되고 키는 검사되고 처리됩니다. if (array_key_exists ('options', $ config))'나는 그 자신이 isset 또는! empty를 사용할지라도 그 키가 존재 하는지를 확인하고 .. if (isset ($ config [ 'options'])) {// do something' –

+0

실제로 array_key_exists, isset에 대해 논하지 않 잖아. 당신이 당신의 메서드/함수를 실행하는 데 필요한 모든 것을 포함하고있는 배열을 원한다면 묻고있다. – mathk

답변

1

개인적으로, 나는 그 관용구를 싫어합니다. 필요한 경우 긴 매개 변수 목록을 대신 사용하는 것을 선호합니다.

문제는 함수 서명을 살펴보면 배열이 가질 수없는 요소를 알 수 없다는 것입니다. 그 위에 구현은 거의 인식되지 않는 키가 있는지 결코 확인하지 않습니다. 따라서 배열 키를 잘못 입력하면 아무 경고도 표시되지 않습니다.

더 나은 대안은 구성 개체를 전달하는 것입니다. 최소한 IDE는 사용 가능한 구성 객체에 대한 힌트를 제공 할 수 있으며, 누락 된 옵션에 대한 계산 된 기본값은 구성 객체의 getter에 표시되는 생성자에서 멀리 이동할 수 있습니다. 분명한 대안은 여러 구성 옵션에 대한 설정자를 제공하는 것입니다. 이것은 각 기본값에 필요한 필수 항목을 제공하는 데 도움이되지 않지만 제공 될 수 있습니다.

1

"옵션 배열"의 디자인 패턴과 매우 흡사합니다. PHP가 파이썬의 인수 확장을 지원한다면, 나는 긴 매개 변수 목록에 동의 할 것이다. 하지만 난 단지 foo(1, 2, 'something', true, 23, array(4), $bar); 정말 읽을 수 없게 찾을 수 있습니다. 나는 일반적으로 설정할 필요가 약 3 개 또는 4 개의 매개 변수가있을 때 배열을 사용합니다 ...

나는 "구성"을 제안하는 것이 좋습니다 구성 방법에 액세스하기위한 보호 된 방법을 생성하는 것이 좋습니다) 기본 클래스에서 : 다음

abstract class Configurable { 
    protected $options = array(); 
    protected $requiredOptions = array(); 

    public function __construct(array $options = array()) { 
     $this->options = $options; 
     foreach ($this->requiredOptions as $option) { 
      if (!isset($this->options[$option])) { 
       throw new InvalidArgumentException('Required argument [$'.$option.'] was not set'); 
      } 
     } 
    } 

    protected function _getOption($key, $default = null) { 
     return isset($this->options[$key]) ? $this->options[$key] : $default; 
    } 
} 

, 클래스, 당신은

class Foo extends Configurable { 
    protected $requiredOptions = array(
     'db', 
     'foo', 
    ); 

    public function __construct(array $options = array()) { 
     parent::__construct($options); 
     if ($this->_getOption('bar', false)) { 
      //Do Something 
     } 
    } 
} 

한 가지를 설정해야 할 일을 정의하는 requireOptions 배열을 오버로드 할 수 있습니다. 이렇게하는 경우 필요한 옵션을 문서화하십시오. 당신을 따르는 사람들의 삶을 훨씬 쉽게 해줄 것입니다.

+1

글쎄, 기본적으로 같은 문제가있다. IDE는 유효한 옵션 (또는 그 유형)에 대한 힌트를 제공 할 수 없습니다. – Artefacto

+0

필자는 개인적으로 매개 변수로 배열을 가졌을 때 긴 매개 변수 목록을 지나치는 경우를 싫어합니다. 긴 매개 변수 목록은 좋은 해결책이 아니지만 Martin Fowler는 그의 책 "Refactoring에서 기존 코드의 디자인 개선"에서이 문제에 대한 답을 얻었습니다. "긴 매개 변수 목록"이라는 냄새가 나는데 해결 방법은 "매개 변수를 메서드로 바꾸고 매개 변수 소개 개체, ... ". 배열 대신 @Artefacto가 가리키는 오브젝트를 선호합니다. – mathk

+0

@Artefacto 글쎄, IDE는 일반적으로 메서드에 대한 docblock을 제공 할 수 있습니다 (NetBeans 및 Eclipse로 테스트했습니다). 그래서 옵션을 문서화하는 한 (내가 내 대답에서 말했듯이) 문제가되어서는 안됩니다. 물론, autocomplete는 잃어 버릴 테지만,'array ('something'=> 'foo', 'else'=> 'bar')를 고려할 때 코드가 읽기 쉬울 때 더 읽기 쉽기 때문에 그럴 가치가 있다고 생각합니다. 'foo (1,3,52, true, 'something');가 정말로 전혀 설명 할 수없는 "힌트"를 필요로하는 모든 유형의 "힌트"가 필요합니다. 코드 작성에 신경 쓰지 않고 유지/디버깅을 수행합니다. 그것 ... – ircmaxell

0

많은 선택적 매개 변수가있는 경우 유용한 매개 변수로 배열을 사용합니다. 일반적으로 array_merge를 사용하여 전달 된 배열을 "defaults"배열과 병합합니다. 검사가 필요하지 않습니다. 매개 변수가 필요한 경우 array_diff_key를 사용하여 필수 매개 변수가 누락되었는지 판별 할 수 있습니다.

function params($p_array) { 
    static $default_vals = array('p1'=>1, 'p2'=>null, 'p3'=>'xyz'); 
    static $rqd_params = array('p1'=>null, 'p3'=>null); 
    // check for missing required params 
    $missing_params = array_diff_key($rqd_params, $p_array); 
    if (count($missing_params)>0) { 
     //return an error (i.e. missing fields) 
     return array_keys($missing_params); 
    } 
    // Merge passed params and override defaults 
    $p_array = array_merge($default_vals, $p_array); 
}