Найкраща модель дизайну OOP для послідовності операцій


11

Я працюю над додатком, модуль якого здійснює наступні фінансові операції послідовно:

Коли користувач вимагає перерахувати певну суму на її банківський рахунок:

  1. перевірити, чи може відбутися будь-яка транзакція зараз? (транзакція може бути здійснена лише протягом певного періоду часу)
  2. перевірити, чи користувач просив зняти мінімальну суму
  3. перевірити, чи є у користувача обліковий запис за замовчуванням

Результат усіх вищезазначених дій повинен бути зафіксований.

Якщо всі вищевказані умови задовольняються, транзакція проводиться. Надалі можуть бути додаткові перевірки.

Яка об'єктно-орієнтована модель дизайну повинна найкраще підходити для вищезазначеного випадку?


3
Ніколи не шукайте схему дизайну, щоб вирішити проблему. Використовуйте шаблони дизайну, щоб повідомити правильне рішення. programmers.stackexchange.com/questions/70877/… Дотримуйтесь принципів SOLID, і ви не підете далеко не так.
пдр

2
Я не погоджуюсь. Шаблони мають назви, які полегшують спілкування, і їх також слід використовувати для спілкування рішень. Але я не згоден з "Ніколи не шукайте схему дизайну, щоб вирішити проблему". Вони не тільки вирішують конкретні проблеми, але і мають справу з різними силами та обмеженнями. Погляньте на "Проксі" та "Декоратор". Вони схожі, але вирішують різні проблеми. Тому, на мою думку, перед тим, як вирішити проблему самостійно, вам слід хоча б ознайомитися з відомими моделями дизайну, щоб отримати вигоду від обох, стандартний підхід до вирішення проблеми та простий спосіб її повідомлення.
Джоні Ді

10
Ось гарна характеристика того, що таке закономірність: "Вони [структури] забезпечують робочі, конкретні та адаптовані рішення проблем, які неодноразово виникають у певних ситуаціях під час розробки програмного забезпечення, від організаційного до програмного контексту". [POSA5, с. 30] Отже, з цієї точки зору, цілком зрозуміло, що пошук моделі як адаптивного рішення - це лігітимний підхід.
Джоні Ді

3
Ви просите об'єктно-орієнтовану конструкцію, щоб описати звичайне старе процедурне програмування?
mouviciel

4
Дотримуйтесь принципу KISS. Поки ваша проблема може бути вирішена за допомогою 3 "if" операторів в одному методі. Не намагайтеся використовувати шаблон дизайну лише заради того, щоб бути крутим. Кожен раз, коли ви пишете додатковий клас, завжди думайте: чи мені це справді потрібно?
Ейвер

Відповіді:


13

Це звучить як те, що ви шукаєте - це ланцюжок відповідальності . У цьому випадку у вас можуть бути такі класи:

  • TransactionValidatorBase абстрактний базовий клас
  • TransactionTimeValidator
  • TransactionAmountValidator
  • TransactionAccountValidator

Вони зв'язані між собою, щоб застосовувати всі необхідні правила.

Далі читання


11
Я розумію, що Ланцюг відповідальності - це більше фільтр - тобто ми йдемо по ланцюгу, поки не знайдемо когось, готового впоратись із відповідальністю, тоді це "посилання" впорається з відповідальністю та вийде. Одним недоліком COR в практичному плані є те, що важко змусити його повернути значення, яке, здається, вам може знадобитися для цього.
Емі Бланкенсіп

Я думаю, що ти можеш мати однорівневу ланцюжок R. Я не думаю, що мені важко повернути значення з Ланцюга з невеликим відхиленням. Кожному рівню потрібно буде повідомляти, що дотримується певного примітивного інтерфейсу, і буде потрібно приймати вхід знизу, якщо такий вхід відповідає примітивному інтерфейсу. Коли потрібне насичення інтерфейсу між двома рівнями ланцюга, які є більш тісно пов'язаними, відведення може бути поліморфовано для його підтримки.
Andyz Smith

3

Якщо ваша послідовність кроків виконує в основному обов'язки перевірки (як виглядає, що ви є), не мутуючи вкладені дані, я б подумав справді про "ланцюжок відповідальності", як пояснив у своїй відповіді @pswg

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

Ось дві статті про це:
Колекція трубопроводів Мартіна Фаулера
Більш теоретична дискусія про закономірність


2

Правильна закономірність тут насправді залежить від контексту. Перш ніж вибрати якийсь конкретний зразок, якого слід дотримуватися, я спробую знайти відповіді на ці запитання:

  • Чи потрібно створювати різні комбінації (1,2,3) перевірок під час виконання?
  • Чи потрібні їм однакові змінні для виконання своїх дій чи вони сильно відрізняються?
  • Наскільки точними повинні бути повідомлення про помилки?
  • У разі відмови чи завжди користувач повторюється з (1) кроку?
  • Як обробляється паралельність?
  • Чи додає кожен метод щось до запиту чи просто підтверджує? .

Виходячи з відчуття кишки, я би кодував їх як прості методи з агрегуючим параметром для кодів помилок.

public void DoTransaction(IErrorAgregator error, TransactionRequest request)
{
    if(!IsTransactionInCertainTimePeriod(request, error)) return;
    if(!IsTransactionAmountInUserBounds(request, error)) return;
    if(!UserHaveDefaultAccount(request, error)) return;
    bankingTransactor.PerformTransaction(request);
}

Можливо, було б доречно поставити DoTransaction в інтерфейс "ITransactionValidationStragegy" та створити шар супер-типу, який буде містити код кодової таблиці перевірки.

Однак у цій конструкції я припускаю, що логіка перевірки визначається під час компіляції.


0

Хоча тут вже згадуються зразки, я б запропонував вам подумати про те, як би ви хотіли використовувати те саме у вашій програмі, виходячи з використовуваних фреймів.

Наприклад, перевірка, яку ви хотіли б зробити, швидше за все, буде змінюватися як і коли просувається час (можливо, ви хочете додати нову перевірку в майбутньому, яка обмежує трансакції до 10 на день). Крім того, ви, можливо, не захочете проводити перевірку, перш ніж розпочнеться фактична бізнес-послуга або код інтеграції. Було б добре, якщо ви можете додавати перевірки як налаштовані.

Якщо ви використовуєте Struts, використання перехоплювачів може бути хорошою ідеєю. У разі весни, введення бобів як залежність дає вам більшу гнучкість. Моя пропозиція - не тільки подивитися на зразки / ідіоми, але і подивитися на рамки, які ви використовуєте для створення програми та побачити, як найкраще ви можете вписатись у ваші вимоги з футуристичної точки зору.


-2

Наскільки я розумію, все, що потрібно, може бути вписане в шаблон команди, як показано нижче. Дизайн класу можна зробити, як зазначено нижче.

interface Transaction{
void performAction();
}

class Banking{

void moneyValidation(){
//Validate Here
}

void timeValidation(){
//validate Here
}
}

class TimeValidation implements Transaction{

public Banking bank;

public TimeValidation (Banking bnk){
bank=bnk;
}

void performAction(){
bnk.timeValidation();
}


class MoneyValidation Implements Transaction{

public Banking bank;

public MoneyValidation(Banking bnk;){
bank=bnk;
}

void performAction(){
bnk.moneyValidation();
}
}


class Control{

private List val_list=new ArrayList();

void storeValidation(Transaction trans){
val_list.add(trans);
trans.performAction(val_list.getFirstAndRemove());
}
}

//Same for other validation classes

Ваш клас клієнта буде містити такий фрагмент коду:

Banking bnk = new Banking();
MoneyValidation m_val = new MoneyValidation (bnk);
TimeValidation t_val = new TimeValidation (bnk);
Control ctrl = new Control();
ctrl.storeValidation(m_val);
ctrl.storeValidation(t_val);

Це, як я розумію, зі сценарієм, який був наведений вище.


Це погано, тому що, коли перевірка грошей не вдається, перевірка часу марна, але це все одно буде зроблено
Ewoks
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.