0
\$\begingroup\$

I've been reading about pure methods and immutability in Java. I have a current application and want to convert all the methods to pure methods.

My app takes payment from users. I first create a payment in the DB:

Payment payment = new Payment(); 
payment = createPayment(orderId, status, address1, address2, country, state, price);

// createPayment() creates a row in the database table, saving orderId, status, address1, address2, country, state, price
// state is the inital state of the payment, in this cased INITIATED
createPayment() returns a Payment model


// make the payment with the payment processor
PaymentResult paymentResult = paymentService.pay(payment);

PaymentResult contains properties such as authCode, pspReference, resultCode, refusalReason.

The Payment model also contains authCode etc. properties. I now want to update my Payment model, including its status. I currently have:

paymentService.updatePaymentFromPaymentResultOnAuthorise(paymentResult, payment);

And updatePaymentFromPaymentResultOnAuthorise is:

public void updatePaymentFromPaymentResultOnAuthorise(PaymentResult paymentResult, Payment payment) throws PaymentException {

    try {

        boolean success = !isNullOrEmpty(paymentResult.getAuthCode());

        if (success) {
            payment.setLastStatus(payment.getStatus());
            payment.setStatus(PaymentStatus.PAID);
        }

        payment.setPspReference(paymentResult.getPspReference());
        payment.setAuthCode(paymentResult.getAuthCode());
        payment.setResultCode(String.valueOf(paymentResult.getResultCode()));
        payment.setRefusalReason(paymentResult.getRefusalReason());

        paymentDAO.updatePayment(payment);

    } catch (Exception e) {
        throw new PaymentException(String.format("there was an error updating the payment with paymentId %s", payment.getId()));
    }
}

As you can see, updatePaymentFromPaymentResultOnAuthorise is not a pure method as it changes the argument payment. This pattern is repeated throughout the app.

Is the only way to make this method pure to create a copy of payment within updatePaymentFromPaymentResultOnAuthorise and return this new object? This seems expensive and it will need to be done in many places throughout my app. But is that my only option?

\$\endgroup\$
4
  • 1
    \$\begingroup\$ Let's start with the reasons why you want to make a major change to the APIs in your system. What is wrong with the current implementation and what problem will you solve by changing everything to pure methods? \$\endgroup\$ Apr 5, 2019 at 11:17
  • 1
    \$\begingroup\$ @TorbenPutkonen The current implementation works fine. I want to move towards pure functions as it's cleaner, easier to test and less bug prone. \$\endgroup\$
    – Mark
    Apr 5, 2019 at 12:31
  • \$\begingroup\$ You have to consider that the pattern you have copies the pattern in the underlying persistence layer (EJB3). It's ok to change the pattern in order to hide the persistence layer but on the other hand if your developers are accustomed to EJB3 and are expecting your API to behave likewise, changing to pure methods is going to cause problems. \$\endgroup\$ Apr 5, 2019 at 12:40
  • \$\begingroup\$ It's more a case of getting into the habit of following Java good practices. My current implementation work, but changing argument properties isn't a great idea, and makes things hard to test \$\endgroup\$
    – Mark
    Apr 5, 2019 at 12:44

1 Answer 1

2
\$\begingroup\$

The biggest problem I see is that the objects you pass around in EJB3 are part of the transaction. If you try to reload the payment again from the EntityManager, you will get back the exact same instance you are trying to avoid changing. You will have to jump through hoops in order to reload the payment as a completely new object and that pretty much negates anything that makes pure methods less error prone.

Following best practises is a valid reason but in this case I get the feeling that the baby gets thrown out with the bath water. Don't feel bad, though. EJB3 transaction model is not intuitive at all, needs very good project documentation and guidelines and it still needs constant care taking anyway.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.