Java多步骤验证方法-重构

Java多步骤验证方法-重构,java,Java,我有一个方法,可以执行多个验证,这些验证依赖于前面的验证。这是一项纯粹的休息服务,没有表单/前端。e、 g public Json processPayment(User user, Amount amount, CardData cardData) { Json result = new Json(); Json userResult = validateUser(user); if (userResult.isNotValid()) result.p

我有一个方法,可以执行多个验证,这些验证依赖于前面的验证。这是一项纯粹的休息服务,没有表单/前端。e、 g

public Json processPayment(User user, Amount amount, CardData cardData) {
    Json result = new Json();

    Json userResult = validateUser(user);
    if (userResult.isNotValid())
        result.put("errorCode", userResult.get("errorCode");
        result.put("message", userResult.get("message");
        return result;
    }

    Merchant merchant = getMerchant(user);
    Json merchantResult = validateMerchant(user);
    if (merchantResult.isNotValid())
        result.put("errorCode", merchantResult.get("errorCode");
        result.put("message", merchantResult.get("message");
        return result;
    }

    Json limitsResult = validateLimits(user, merchant, amount);
    if (limitsResult.isNotValid())
        result.put("errorCode", limitsResult.get("errorCode");
        result.put("message", limitsResult.get("message");
        return result;
    }

    // Like above there are few more steps.
    .
    .
    .

    // All validations are fine process transaction.
    Json transactionResult = processTransaction(user, merchant, amount, cardData);
    if (transactionResult.isNotValid())
        result.put("errorCode", transactionResult.get("errorCode");
        result.put("message", transactionResult.get("message");
    } else {
        result.put("message", "Transaction Successful");
        result.put("referenceNumber, transactionResult.get("rrn");
    }

    return result;
}
在每个步骤中,如果结果无效,则应立即返回错误消息,否则继续下一步

由于有多个步骤,这种方法变得太大,几乎不可能进行单元测试

我想把这个方法分解成更小的方法。我已经将每个步骤的所有业务逻辑转移到单独的方法中,但流程仍然保留在这个大方法中

Sonarint CC为47,这是一个大问题

请建议处理此问题的正确方法


谢谢。

您可以编写
doValidation()
函数,如下所示

private doValidation(Json validationResult, Json result) {
    if (validationResult.isNotValid())
        result.put("errorCode", validationResult.get("errorCode");
        result.put("message", validationResult.get("message");
        return false;//validation failed
    }
    return true;//validation passed
}
并从
processPayment()
方法调用此方法

public Json processPayment(User user, Amount amount, CardData cardData) {
    Json result = new Json();

    if( !doAllValidations(user,amount,cardData, result) )
       return result;

    // All validations are fine process transaction.
    Json transactionResult = processTransaction(user, merchant, amount, cardData);
    if (transactionResult.isNotValid())
        result.put("errorCode", transactionResult.get("errorCode");
        result.put("message", transactionResult.get("message");
    } else {
        result.put("message", "Transaction Successful");
        result.put("referenceNumber, transactionResult.get("rrn");
    }

    return result;
}
最后,如果需要,可以将所有验证移到其他方法

public bool doAllValidations(User user, Amount amount, CardData cardData, result) {
        Json userResult = validateUser(user);
        if (!doValidation(userResult, result))
          return result;


        Merchant merchant = getMerchant(user);
        Json merchantResult = validateMerchant(user);
        if (!doValidation(merchantResult, result))
          return result;

        Json limitsResult = validateLimits(user, merchant, amount);
        if (!doValidation(limitsResult, result))
          return result; 
        ....
}

这里有一个小例子,可以为您提供解决方案

主要思想是每个验证步骤共享一个公共上下文。此上下文保存验证过程的所有信息

接下来是一个验证程序队列。每个代表一个验证步骤。验证器更改上下文(如添加商家对象),调用您的验证方法,并在必要时更改上下文的结果

验证过程本身只是在队列上迭代,寻找失败的验证程序

只要运行这个代码。也许这有助于:

import java.util.*;
接口支付验证接口{
公共布尔验证(PaymentValidationContext);
}
类PaymentValidationContext{
字符串结果=”;
字符串用户;
int cardData;
弦乐商人;
public PaymentValidationContext(字符串用户,int cardData){
this.user=用户;
this.cardData=cardData;
}
}
类支付验证器{
公共静态布尔validateUser(PaymentValidationContext上下文){
if(context.user==null){
context.result+=“用户错误\n”;
返回false;
}
返回true;
}
公共静态布尔validateMerchant(PaymentValidationContext上下文){
context.merchant=context.user+“#”+context.cardData;
if(context.merchant.length()!validator.validate(context));
返回context.result;
}
//用于测试-------
公共静态void main(字符串[]args){
处理器p=新处理器();
System.out.print(p.processPayment(“Foobar”,1337));//确定
System.out.print(p.processPayment(null,1337));//失败
System.out.print(p.processPayment(“,1));//失败
}
}

是您要找的。这是我已经在做的。所有业务逻辑都在此方法之外。这个方法中只有流程,但所有单独的方法都会返回结果,我必须检查结果是否有效,并在此基础上继续下一步。将4行验证结果移动到其他方法。让我把processPayment方法也放进去。在这种情况下,
doAllValidations
方法变得更大,而不是
processPayment
。这听起来是完美的解决方案。我将尝试基于此重构代码,并在此处更新。谢谢@obenland你是指
javax.naming.Context
还是我应该添加我自己的简单实现?哦。我没能把这个拿走。我认为拥有一个公共上下文类是很好的,但是对于这个示例,您不需要一个。我确定了我的答案
import java.util.*;

interface PaymentValidatorInterface {
    public boolean validate(PaymentValidationContext context);
}

class PaymentValidationContext {
    String result = "";
    String user;
    int cardData;
    String merchant;

    public PaymentValidationContext(String user, int cardData) {
        this.user = user;
        this.cardData = cardData;
    }
}

class PaymentValidator {
    public static boolean validateUser(PaymentValidationContext context) {
        if (context.user == null) {
            context.result += "User is wrong\n";
            return false;
        }
        return true;
    }

    public static boolean validateMerchant(PaymentValidationContext context) {
        context.merchant = context.user + "#" + context.cardData;
        if (context.merchant.length() <= 3) {
            context.result += "Marchant is wrong\n";
            return false;
        }
        return true;
    }

    public static boolean finishValidation(PaymentValidationContext context) {
        context.result += "Everything is fine.\n";
        return true;
    }
}

public class Processor {
    private final static Queue<PaymentValidatorInterface> validators = new LinkedList<>();
    static {
        validators.add(PaymentValidator::validateUser);
        validators.add(PaymentValidator::validateMerchant);
        validators.add(PaymentValidator::finishValidation);
    }

    public String processPayment(String user, int cardData) {
        PaymentValidationContext context = new PaymentValidationContext(user, cardData);
        validators.stream().anyMatch(validator -> !validator.validate(context));
        return context.result;
    }

    // For testing -------
    public static void main(String[] args) {
        Processor p = new Processor();
        System.out.print(p.processPayment("Foobar", 1337));    // ok
        System.out.print(p.processPayment(null, 1337));        // fails
        System.out.print(p.processPayment("", 1));             // fails
    }
}