Инстанцирование объектов с различными атрибутами


У меня есть класс с большим количеством атрибутов, большинство из которых известны, когда я создаю экземпляр объекта. Так я прохожу все значения в конструкторе:

$op = new OpenIdProvider($imgPath . $name . $ext, 'openid_highlight', 
                         0, 0, 108, 68, 6, $info[0], $info[1], $name);

Я нахожу, что наличие такого большого числа параметров делает его вводит в заблуждение как при написании и чтении кода, как это нелегко определить, какой атрибут каждому значению соответствует. Кроме того, это имеет немного запаха к нему код - кажется, что там должен быть лучший способ. Какие-либо предложения?



1813
44
задан 22 января 2011 в 02:01 Источник Поделиться
Комментарии
4 ответа

Мартин Фаулер Библии Книга рефакторинг идентифицирует запах, называемый "длинный список параметров" (p78) и предлагает следующие доработки:

Из этих я думаю, что "ввести объект параметр" лучше всего подойдут:

Вы бы обернуть атрибуты в собственный объект и передать его в конструктор. Вы можете столкнуться с той же проблемой с новым объектом, если вы решите собрать все значения сразу в конструкторе его, Хотя вы могли бы использовать сеттеры вместо параметров этого объекта.

Для иллюстрации (к сожалению, мой PHP-фу слаб):

$params = new OpenIDParams();
$params->setSomething( $imgPath . $name . $ext );
$params->setSomethingElse( 'openid_highlight' );

$params->setName( $name );

$op = new OpenIdProvider( $params );

Это немного более многословен, но он касается вашего беспокойства о том, что не понятно о назначении атрибутов / значений. Также это будет немного менее болезненным, чтобы добавить дополнительные атрибуты в уравнении позже.

51
ответ дан 22 января 2011 в 04:01 Источник Поделиться

В дополнение к ответу ЖРД я хотел бы предложить вам рассмотреть идею о том, что ваш класс должен, что многие аргументы конструктора, потому что он пытается сделать слишком много вещей.

20
ответ дан 22 января 2011 в 10:01 Источник Поделиться

Как @ЖРД ответ (+1) упомянул его в PHP-фу слаб и с его точки являются правильными и действительными я просто хочу предоставить некоторые PHP-код, чтобы проиллюстрировать :

class OpenIdProviderOptions {

private $path;
private $name = "default_name";
private $param1;
private $optionalParam2 = "foo";

public function __construct($path, $param1) {
/* you might take a $options array there for bc */
/* Also if you have 2-3 REQUIRED parameters and the rest is optional
i like putting all the required stuff in the constructor so you don't
have to do any "is that value set" checking here.

If you have 20 REQUIRED values you might split those into some objects
or something ;)
*/
}

public function getPath() {
return $this->path;
}

/* etc */

}

class OpenIdProvider {

private $settings;

public function __construct(OpenIdProviderOptions $options) {
$this->settings = $options;
}

public function foo {
$path = $this->settings->getPath();
}
}

$settings = new OpenIdProviderOptions("myopenid.example.com", "i need this");
$settings->setFoo("bar");
$settings->setBar("fubar");

$myProvider = new OpenIdProvider($settings);

8
ответ дан 22 января 2011 в 03:01 Источник Поделиться

Я думаю, что было бы лучше поставить все параметры в один массив. Затем вы создаете массив в одну команду, когда вы хотите вызвать конструктор.

Этот подход также имеет преимущество, что можно добавить дополнительные параметры для класса, см. код ниже для примера:



class OpenIdProvider
{
public $_width = 0;
public $_highliting = '';
public $_Xposition = 0;
public $_Yposition = 0;
...
...

/**
* Main constractor to set array of parameters.
* param array $parameters
* description _Xposition , _width , _Yposition ...
*/
function __constrauct($parameters)
{
if(is_array($parameters))
foreach($parameters as $needle=>$parameter)
$this->{'_'.$needle} = $parameter;
}
}
$options = array('path'=>$imgPath . $name . $ext,
'highliting'=> 'openid_highlight',
'width'=>108,
'height'=>68,
'...'=>6,
'...'=>$info[0],
'...'=>$info[1],
'...'=>$name);
$openIdObj = new OpenIdProvider($options);

7
ответ дан 24 января 2011 в 09:01 Источник Поделиться