mercredi 19 décembre 2018

Design Pattern to wrap a series of step

I'm having a financial related service that enable our users to topup their balance in our system, and then disburse the money. They'll be charged for each disbursement. The problem is, I'm having a need to do a series of step that need to be done in several places.

Related component:

  • Transaction : record of the transaction info (amount, beneficiary account, etc)
  • Payment : record of the payment info (amount, payment status)
  • Journal Entries : record the flow of money for every transaction and payment (for every movement of money in our system, we track which account act as the debit account and which as the credit account, like in accounting)

Flow of the business process:

  • Suppose there's a transaction and payment already created, next step is to confirm the transaction
  • Change transaction status to confirmed
  • Change payment status to confirmed
  • Insert new record to journal entries, with debit and credit account specified specifically for this process
  • Increment or decrement the balance of the credit and debit account

Those series of step might be done in several places, so I try to find a way to prevent other programmer that try to implement this flow forgetting a step or doing it wrong.

What I do now:

  • Create a journal entry helper. Consist of a lot of static function for each of possible business process that involve moving money between accounts. For example in this question, when confirming a payment, it moved money from user_deposit to unearned_revenue account, so user_deposit will be the debit account, and unearned_revenue will be the credit account in the newly inserted journal entry. Each of this static function only differ in telling which account will be the credit account and which will be the debit account. Beside that, this helper will also decrement or increment the balance of the credit and debit account. So in this example, it will decrement user_deposit balance and increment unearned_revenue balance. Example function name related to this example: withdrawPayment and withdrawTransaction
  • Create a payment helper. Different payment type, in different state, will need different journal entry helper. So there are a lot of static function in this helper that change the payment status, and then call the related journal entry helper. Example function name related to this example: confirmAndWithdrawCashPayment
  • Create an instance method on the transaction named like confirmAndwithdraw, which will call confirmAndWithdrawCashPayment on payment helper and withdrawTransaction on journal entry helper, which will call withdrawPayment on journal entry helper.
  • Whenever a programmer need to do this step, they just call the confirmAndwithdraw function from the transaction object

This'll work of course, but I also know that this is a very bad design. Any suggestion of a design pattern or any solution suitable for this case?

Mainly, I'm looking for a way to wrap a series of steps so that I can remove those helper class while also providing a convenient way for other programmers to implement this business process.

Sorry for the long question. If the question is not clear, please do tell me so I can provide more information.

Aucun commentaire:

Enregistrer un commentaire