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
How to reduce cyclomatic 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 if
blocks:
然后你可以使用这个方法而不是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 版本。它应该知道如何渲染自己。