我有一个方法可以在Movie
DTO的Builder模式中设置数据。问题是这个方法有点复杂,IntelliJ显示警告。
private static Movie.Builder initMovieDto(final MovieEntity movieEntity) {
final Movie.Builder builder = (Movie.Builder) new Movie.Builder(
movieEntity.getTitle(),
movieEntity.getType()
)
.withId(movieEntity.getId().toString());
movieEntity.getRating().ifPresent(builder::withRating);
movieEntity.getRating().ifPresent(ratings -> builder.withNumberOfRating(movieEntity.getRatings().size()));
final Optional<String> locatedTitle = movieEntity.getOtherTitles().stream()
.filter(ot -> ot.getStatus() == DataStatus.ACCEPTED)
.map(ServiceUtils::toOtherTitleDto)
.filter(ot -> ot.getCountry() != null
&& ot.getCountry().getCode().equals(Locale.getDefault().getCountry()))
.map(OtherTitle::getTitle)
.findFirst();
locatedTitle.ifPresent(builder::withTitleLocated);
final Supplier<Stream<ReleaseDate>> releaseDateStream = () -> movieEntity.getReleaseDates().stream()
.filter(ot -> ot.getStatus() == DataStatus.ACCEPTED)
.map(ServiceUtils::toReleaseDateDto);
Optional<ReleaseDate> releaseDate = releaseDateStream.get()
.filter(rd -> rd.getCountry().getCode().equals(Locale.getDefault().getCountry()))
.findFirst();
if(releaseDate.isPresent()) {
builder.withReleaseDate(releaseDate.get());
} else {
releaseDate = releaseDateStream.get()
.filter(rd -> movieEntity.getCountries().stream()
.filter(c -> c.getStatus() == DataStatus.ACCEPTED)
.map(ServiceUtils::toCountryDto)
.collect(Collectors.toList()).stream()
.map(Country::getCountry)
.collect(Collectors.toList())
.contains(rd.getCountry()))
.findFirst();
if(releaseDate.isPresent()) {
builder.withReleaseDate(releaseDate.get());
} else {
releaseDate = releaseDateStream.get().findFirst();
builder.withReleaseDate(releaseDate.orElse(null));
}
}
builder.withCountries(movieEntity.getCountries().stream().filter(c -> c.getStatus() == DataStatus.ACCEPTED).map(MovieCountryEntity::getCountry).collect(Collectors.toList()));
builder.withLanguages(movieEntity.getLanguages().stream().filter(l -> l.getStatus() == DataStatus.ACCEPTED).map(MovieLanguageEntity::getLanguage).collect(Collectors.toList()));
builder.withGenres(movieEntity.getGenres().stream().filter(g -> g.getStatus() == DataStatus.ACCEPTED).map(MovieGenreEntity::getGenre).collect(Collectors.toList()));
builder.withBoxofficeCumulative(movieEntity.getBoxOffices().stream().filter(bo -> bo.getStatus() == DataStatus.ACCEPTED).map(MovieBoxOfficeEntity::getBoxOffice).reduce(BigDecimal::add).orElse(null));
builder.withOutline(movieEntity.getOutlines().stream().filter(o -> o.getStatus() == DataStatus.ACCEPTED).map(MovieOutlineEntity::getOutline).findFirst().orElse(null));
builder.withSummary(movieEntity.getSummaries().stream().filter(s -> s.getStatus() == DataStatus.ACCEPTED).map(MovieSummaryEntity::getSummary).findFirst().orElse(null));
return builder;
}
Intellij向我显示警告
Method 'initMovieDto' is too complex to analyze by data flow algorithm less... (Ctrl+F1)
This inspection analyzes method control and data flow to report possible conditions that are always true or false, expressions whose value is statically proven to be constant, and situations that can lead to nullability contract violations.
您是否知道如何优化此方法?在这种方法中,我必须在DTO Movie
对象中设置如此多的数据。
答案 0 :(得分:1)
只需将计算不同值的块转换为单独的方法即可
例如。将locatedTitle
的计算包装到方法中:
private Optional<String> locatedTitle(MovieEntity movieEntity) {
return movieEntity.getOtherTitles().stream()
.filter(ot -> ot.getStatus() == DataStatus.ACCEPTED)
.map(ServiceUtils::toOtherTitleDto)
.filter(ot -> ot.getCountry() != null
&& ot.getCountry().getCode().equals(Locale.getDefault().getCountry()))
.map(OtherTitle::getTitle)
.findFirst();
}
然后在你的main方法中,而不是整个块,只需一个简单的调用:
Optional<String> locatedTitle = locatedTitle(movieEntity);
然后对计算releaseDate
的块进行同样的操作(如果它不是最初存在的话)
冲洗并重复,直到主要方法很小且易于阅读。
这是一个很好的原则:只有较小的方法只做一件事。他们将更容易编写,测试和重构。