Java 如何降低圈复杂度?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16418038/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-16 06:48:46  来源:igfitidea点击:

How to reduce cyclomatic complexity?

javavalidationcyclomatic-complexity

提问by Herter

I'm working on a class which sends a RequestDTO to a Web Service. I need to validate the request before it is sent.

我正在研究一个将 RequestDTO 发送到 Web 服务的类。我需要在发送之前验证请求。

The request can be sent from 3 different places and there are different validation rules for each "requesttype", e.g. request1 must have name and phonenumber, request2 must have address, etc)

请求可以从 3 个不同的地方发送,每个“请求类型”有不同的验证规则,例如 request1 必须有姓名和电话号码,request2 必须有地址等)

I have a DTO which contains a long list of fields (name, address, city, phonenumber, etc.) and it is the same DTO sent no matter which type of request it is.

我有一个 DTO,其中包含一长串字段(姓名、地址、城市、电话号码等),并且无论它是哪种类型的请求,它都发送相同的 DTO。

I have created 3 different validation methods and based on the type the appropriate method is called.

我创建了 3 种不同的验证方法,并根据类型调用适当的方法。

In each of these methods I have a long list of if-else's to check for the fields that are necessary for each request type.

在这些方法中的每一个中,我都有一长串 if-else 来检查每种请求类型所需的字段。

private void validateRequest1(Request request) {
    StringBuilder sb = new StringBuilder();
    if (null == request) {
        throw new IllegalArgumentException("Request is null");
    }
    if (isFieldEmpty(request.getName())) {  *see below
        sb.append("name,"));
    }
    if (isFieldEmpty(request.getStreet())) {
        sb.append("street,"));
    }
    ...

isFieldEmpty()checks the string for null and isEmpty()and returns a boolean

isFieldEmpty()检查字符串是否为空isEmpty()并返回一个布尔值

This gives me a cyclomatic complexity of 28 in one of those methods so my question is.. is it possible to reduce this complexity? - if so, how would I go about doing so?

在这些方法之一中,这给了我 28 的圈复杂度,所以我的问题是..是否有可能降低这种复杂度?- 如果是这样,我将如何去做?

Ultimately I need to check a lot of fields and I cannot see how this can be done without lots of checks :/

最终,我需要检查很多字段,如果没有大量检查,我无法看到如何做到这一点:/

采纳答案by EmirCalabuch

An easy way is to promote the check into a separate method:

一种简单的方法是将检查提升为单独的方法:

private String getAppendString(String value, String appendString) {
    if (value == null || value.isEmpty()) {
        return "";
    }
    return appendString;
}

And then you can use this method instead of the ifblocks:

然后你可以使用这个方法而不是if块:

sb.append(getAppendString(request.getStreet(), "street,");

This will reduce complexity from 28 down to 3. Always remember: high complexity counts are an indication that a method is trying to do too much. Complexity can be dealt with by dividing the problem into smaller pieces, like we did here.

这会将复杂度从 28 降低到 3。永远记住:高复杂度计数表明方法试图做太多事情。复杂性可以通过将问题分成更小的部分来处理,就像我们在这里所做的那样。

回答by duffymo

Another approach would be to enforce that contract in the Request object itself. If a field is required or can't be null, say so when the Request is created.

另一种方法是在请求对象本身中强制执行该契约。如果某个字段是必需的或不能为空,请在创建请求时说明。

Create the Request in such a way that it's 100% valid and ready to go when the constructor exists.

以这样一种方式创建请求,使其 100% 有效并在构造函数存在时准备就绪。

I'd also create that String version in the Request toString() method. It should know how to render itself.

我还将在 Request toString() 方法中创建该 String 版本。它应该知道如何渲染自己。