2010-09-29 3 views
7

Я знаю, что преимущества цепочки в PHP, но позволяет сказать, что мы имеем эту следующую ситуациюВлияние метода построения цепочки

$Mail = new MailClass("mail") 
     ->SetFrom("X") 
     ->SetTo("X") 
     ->SetSubject("X") 
     ->AddRecipient("X") 
     ->AddRecipient("X") 
     ->AddRecipient("X") 
     ->AddRecipient("X") 
     ->AddRecipient("X") 
     ->AddRecipient("X") 
     ->Send(); 

Есть ли какие-либо проблемы, связанные с возвращением и повторное использование объекта снова и снова, такие вопросы, как скорость или несоблюдение лучшие практики

Также хорошо читать на этом, если ваш новый для Fluent-интерфейса: Martin Fowler on Fluent-Interfaces

Я полностью понимаю, что это не уже быть запрограммированы таким образом, и могут быть обработаны следующим образом:

$Mail = new MailClass("mail"); 
$Mail->AddRecipien(
    array(/*.....*/) 
); 
$Mail->SetFrom("X"); 
$Mail->SetTo("X"); 
$Mail->SetSubject("X"); 
$Mail->Send(); 

но позволяет сказать, что у меня есть такой объект, как так:

$Order = new Order() 
     ->With(22,'TAL') 
     ->With(38,'HPK')->Skippable() 
     ->With(2,'LGV') 
     ->Priority(); 

Примечание ->With(38,'HPK')->Skippable(). Это прекрасный пример Pro для этого типа программирования.

+0

Классы должны, ИМО, проверять свои аргументы для экземпляров и аргументов тестирования/управления их методами. В моем классе mailer is_valid_email является частным методом внутри класса. – AutoSponge

+0

«-» С (38, «HPK») -> Skippable() «Ситуация не является проблемой, например, в этом сценарии вы/класс можете знать, что Skippable применяется к последнему с добавленным. – Hannes

+2

Да, но коэффициент удобочитаемости больше, чем обычные методы компиляции этого блока кода. Это просто про читаемость – RobertPitt

ответ

5

Если вам нужно проверить что-то, я думаю, что имеет смысл проверить его в AddRecipient Meth сам, но производительность должна быть примерно одинаковой. И я не знаю общих недостатков использования метода цепочки.

1

EDIT: Обновлен ответ на матч вопрос
вызовы функций медленнее, чем петли, то есть цепочки, например, метод addRecipient() ухудшает производительность чуть-чуть по сравнению с вызовом в addRecipients() метод, который принимает массив, который затем обрабатывается в петля.

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

... 
->With(22, 'TAL') 
->With(38, 'HPK')->Skippable() 
->With(2, 'LGV') 
... 

Это требует, чтобы вы помнили, что Skippable() должен быть применен к (38, 'HPK'), а не (22, 'TAL').

Вы вряд ли заметите потерю производительности, хотя, если ваш код не будет вызван очень часто в цикле или когда у вас так много одновременных запросов на ваш веб-сервер, что он приближается к его пределам (что имеет место для тяжелых загружать веб-сайты).

Другой аспект заключается в том, что шаблон цепочки методов обеспечивает использование исключений для ошибок сигнала (что я не говорю, это плохо, оно просто отличается от классического стиля кодирования «функция вызова и проверки»).

Обычно будут выполняться функции, которые дают другие значения, чем объект, к которому они принадлежат (например, те, которые возвращают статус объекта и аксессуаров). Важно, чтобы пользователь вашего API мог определить, какие функции связаны с цепочкой, и которые не должны ссылаться на документацию каждый раз, когда он встречает новый метод (например, руководство, в котором говорится, что все мутаторы и только мутаторы поддерживают цепочку).


Ответ на первоначальный вопрос:

[...] The issues i have with chaining is the fact that you cant really perform extra validation [...]

В качестве альтернативы, реализовать специальный метод проверки, что вы называете после установки всех свойств и иметь его вернуть вам массив ошибок валидации (которые могут быть простыми строками или объектами, например, с именем ValidationFailure).

0

Это обоюдоострый меч.

Хорошая сторона? Это чище, чем повторное обращение к классу, и хотя в основном это просто синтаксическое изменение, оно немного ускорит обработку. Было бы предпочтительнее зацикливать этот тип цепочки, чем цикл каждого вызова в longform.

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

  1. Предварительная проверка ваших данных.
  2. Предварительная авторизация пользователей.

Я не вижу проблем с цепью этих методов в петлю, по производительности.

2

Вы не можете цепи непосредственно из класса конкретизации:

$Mail = new MailClass("mail") 
      ->SetFrom("X") 
      ->SetTo("Y"); 

вы должны создать экземпляр первого, а затем цепь против реализованным объекта:

$Mail = new MailClass("mail") ; 
$Mail->SetFrom("X") 
    ->SetTo("Y"); 

Если вы активизируете в отдельных сеттеров (как вам следует), тогда вам нужно убедиться, что вы бросаете исключения, когда встречается ошибка проверки. Вы не можете просто вернуть логическое значение false при ошибке, иначе цепочка попытается вызвать следующий метод против булевого, а не экземпляра класса, и вы получите.

Fatal error: Call to a member function SetSubject() on a non-object in C:\xampp\htdocs\oChainTest.php on line 23

если бросить исключения, вы можете обернуть цепи внутри Try ... Catch

$Mail = new MailClass("mail"); 
try { 
    $Mail->SetFrom("X") 
     ->SetTo("Y") 
     ->SetSubject("Z"); 
} catch (Exception $e) { 
    echo $e->getMessage(); 
} 

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

+2

Обходным путем является использование фабричных методов для создания объектов и цепочек оттуда, например 'MailClass :: создать ('почта') -> setFrom ('X')'. Недостатком PHP-версий до 5.3 является то, что у них нет поздней статической привязки, т. Е. Статические методы будут относиться к классу, где они были определены. Кроме того, статические вызовы методов медленны. – Archimedix

+0

@Archimedix - действительная точка и поздняя статическая привязка - это находка (однажды я могу обеспечить, чтобы мои библиотеки всегда запускались с 5.3+) –

+0

Я всегда использую абстрактный реестр со статическими методами для создания объектов и хранения их в массиве, поэтому мой выход был бы «Registry :: Use (« Mail ») -> X() -> Y-> Z() ;, где инициализация выполняется внутри метода:' Registry :: Use ("Mail") ' – RobertPitt

Смежные вопросы