Функция оплаты с слишком много параметров


У меня есть способ слишком много параметров.

Как бы вы переделать его?

Вещи, которые я рассмотрел до сих пор:

  • передать массив в объект и проверка необходимых ключей (никакого намека кода phpdoc, программист не знает, что требуется)
  • передать объект (глупо способ с getters и SETTERS, программист еще не знает, что требуется)

Вот способ:

public function doDirectPayment(
    $amount,
    $credit_card_type,
    $credit_card_number,
    $expiration_month,
    $expiration_year,
    $cvv2,
    $first_name,
    $last_name,
    $address1,
    $address2,
    $city,
    $state,
    $zip,
    $country,
    $currency_code,
    $ip_address,
    $payment_action = 'Sale'
)
{
    $client = $this->getClient();

    $client->setParameterGet('METHOD', 'DoDirectPayment');

    $month = str_pad(ltrim((string)$expiration_month, 0), 2, '0', STR_PAD_LEFT);
    $expiration_date = $month . $expiration_year;

    $client->setParameterGet('PAYMENTACTION', urlencode($payment_action)); 
    $client->setParameterGet('AMT', urlencode($amount));
    $client->setParameterGet('CREDITCARDTYPE', urlencode($credit_card_type));
    $client->setParameterGet('ACCT', urlencode($credit_card_number));
    $client->setParameterGet('EXPDATE', urlencode($expiration_date));
    $client->setParameterGet('CVV2', urlencode($cvv2));
    $client->setParameterGet('FIRSTNAME', urlencode($first_name));
    $client->setParameterGet('LASTNAME', urlencode($last_name));
    $client->setParameterGet('STREET', urlencode($address1));

    if (!empty($address2)) {
        $client->setParameterGet('STREET2', urlencode($address2));
    }

    $client->setParameterGet('CITY', urlencode($city));
    $client->setParameterGet('STATE', urlencode($state));
    $client->setParameterGet('ZIP', urlencode($zip));
    $client->setParameterGet('COUNTRYCODE', urlencode($country));
    $client->setParameterGet('CURRENCYCODE', urlencode($currency_code));
    $client->setParameterGet('IPADDRESS', urlencode($ip_address));

    $response = $client->request(Zend_Http_Client::GET);

    return $response;
}


1041
7
php
задан 29 июля 2011 в 08:07 Источник Поделиться
Комментарии
3 ответа

Я группа параметров:

doDirectPayment(CreditCard $card, User $user, array $options = array())

Но это не решает всех проблем.

Чтобы отметить что-то требуется вы используете интерфейс, но интерфейс может только в силу существования методов, а не свойств.

Поэтому лучшим вариантом представляется заставляя параметры конструктора:

class CreditCard {
public function __construct($required1, $required2 /*, etc*/);
}

Но таким образом вы не можете инстанцировать объект без предоставления вариантов (без интерфейса).

Вы можете отметить параметры необязательны и обеспечить некоторый способ проверки. Проблема в том, как автоматически вызвать этот метод. Может быть, какой-то интерфейс SPL может помочь здесь.


Из рефакторинг Фаулера:


Длинные Списки Параметров

Слишком много параметров. Функциональность является неправильным или недостаточно использование
поля

Мешает: понимание, применение, добавление параметров

Основной рефакторинг: замену параметра метода, сохранение всего объекта, ввести объект parameter


Похоже, большинство из этих параметров выйдет из заполненных пользователем форм, так что вы могли бы просто сделать:

doDirectPayment(PaymentForm $form, array $otherOptions = array()) {
// ...
foreach ($form->getValues() as $name => $value) {
$client->setParameterGet(strtoupper($name), urlencode($value));
}
// ...
}

7
ответ дан 29 июля 2011 в 09:07 Источник Поделиться

Передача объекта (имя класса "платеж" возможно?) разве это не глупо на самом деле. Вы можете добавить публичный метод validate()для того, что можно назвать из doDirectPayment() для того, чтобы проверить, если все обязательные поля были заполнены.

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

5
ответ дан 29 июля 2011 в 08:07 Источник Поделиться

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

Вы можете иметь каждый застройщик возвращает следующий элемент по мере необходимости.

т. е.:

CreditCardInfo.Build(credit_card_type, _number, month, year) // Returns NameInfo Builder class
.Build(first_name, last_name) //Returns AddressInfo Builder class
.Build(address1, address2, city, state, zip, country) //Returns TransactionInfo Builder class
.Build(ip_address) //Returns Payment class
.DoDirectPayment();

Каждый из Строителя классы { CreditCardInfo, NameInfo, AddressInfo, TransactionInfo } есть создать метод, который возвращает следующий конструктор класса в порядке. Финал один вернулся, оплаты, будет содержать DoDirectDeposit действий.

Это помогает показать намерение каждого из параметров, и дает четкое API-интерфейс, как каждый параметр группирования способствует требованиям вызове функции.

0
ответ дан 1 августа 2011 в 04:08 Источник Поделиться