2010-04-23 2 views
1

Я использую ASP.NET MVC 2.Как обрабатывать типы платежей с изменяющимися свойствами в наиболее элегантный способ

My current payment types with properties

Держа это просто, у меня есть три вида оплаты: кредитная карта, e- проверить, или «счет меня позже». Я хочу:

  1. выбрать тип один платеж
  2. дисплей несколько полей для одного типа оплаты на мой взгляд
  3. выполнения некоторых логики с помощью этих полей (специфичные для типа)
  4. дисплей вид подтверждения
  5. запускать более определенную логику, используя эти поля (специфические для типа)
  6. дисплея вида квитанции

Каждый тип платежа имеет поля, специфичные для типа ... возможно, 2 поля, может быть, больше. Пока я знаю, сколько и какие поля, но еще можно добавить. Я считаю, что лучшая вещь для моих представлений заключается в том, чтобы иметь частичный вид для каждого типа оплаты для обработки разных полей и позволить контроллеру решить, какой частичный рендер (если у вас есть лучший вариант, я открыт). Моя реальная проблема исходит из логики, которая происходит в контроллере между представлениями. Каждый тип платежа имеет переменное количество полей. Я бы хотел, чтобы все было строго типизировано, но похоже, что какой-то словарь является единственным вариантом. Добавьте к этой конкретной логике, которая выполняется в зависимости от типа платежа.

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

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

ответ

0

Это одна за вещь для, скажем, Order объекта на самом деле не заботиться о конкретном типе оплаты - только зная, что есть PledgedAmount и DepositedAmount свойства, например, достаточно для этого класса, чтобы делать свою работу (например, «не позволяйте себе идти в состояние отправления, если заказ не взимается, с помощью любого способа оплаты мне все равно, пока он заряжен как-то круто»).

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

Например, я использовал последний подход, когда добавлял поддержку международных адресов для одного из моих приложений. Я абстрагировал адреса в общий набор полей: AdministrativeArea, Municipality и т. Д., И определил класс AddressScheme, который определил AddressFieldRule s для каждого поля, указав, требуется ли это, если необходимо применить регулярное выражение, если есть определенный набор допустимых значений и т. д. Это было уместно, поскольку мы могли добавлять или удалять страны в разрешенный список в любое время без перекомпиляции и повторного развертывания приложения; пользовательский интерфейс мог бы динамически генерировать себя на основе AddressScheme, который сам был загружен из базы данных. Милая.

Но действительно ли вы будете добавлять типы платежей (a) с большой частотой или (b) без повторной компиляции своего приложения? Иногда вам действительно нужен фактический тостер вместо машины для приготовления завтрака с хлебом и другим блоком броузеров на основе дрожжей, поэтому просто добавьте переключатель или словарь, который отображает тип в правильный вид: я думаю, что это вполне приемлемо для Пользовательский интерфейс должен быть способен различать эти типы и, что более важно, для вас, чтобы настраивать и настраивать представление каждого типа, но более высокие части могут извлечь выгоду из некоторой абстракции. I talked about that in my answer to a different question related to billing.

В вашем примере вы можете обмениваться общим кодом для шагов 1, 4 и 6, но делегировать их определенным методам и представлениям для шагов 2, 3 и 5. И мир по-прежнему будет крутиться.

Мои два цента. Удачи!

+0

Вот что говорят другие ребята из моей команды. Мне нравится тостерная аналогия. –

0

Похоже, что у вас есть три разных рабочих процесса, каждый из которых относится к другому способу оплаты, выбранному пользователем. Хотя вы только явно указываете, что шаги 3 и 5 имеют проблемы, связанные с оплатой, казалось бы, все после шага 1 должно отображать конкретную информацию о платеже (если на шаге 4 пользователь не подтверждает конкретную информацию платежа, а на шаге 6 их получение не выполняется 't указать, как они заплатили).

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

Как указано, в то время как вы указали, что не используете интерфейс, причина, по которой вы дали, кажется немного тревожной. Похоже, вы использовали интерфейс, если типы платежей содержали одни и те же поля. Интерфейсы предназначены для определения контрактов поведения, поэтому вы не должны использовать их для определения общих данных.

+0

Не может ли общее поведение быть IPaymentMethod.MakePayment()? –

+0

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