Lambda和清潔程式碼的一個重構案例 - frankel

banq發表於2020-06-25

原始碼:

List<Person> persons = ...;
persons.stream().filter(p -> {
    if (p.getGender() == Gender.MALE) {
        return true;
    }
    LocalDate now = LocalDate.now();
    Duration age = Duration.between(p.getBirthDate(), now);
    Duration adult = Duration.of(18, ChronoUnit.YEARS);
    return age.compareTo(adult) > 0) {
        return true;
    }
    return false;
}).map(p -> p.getFirstName() + " " + p.getLastName())
  .collect(Collectors.toList());


它很長,甚至令人費解。
第一步是應用正確的命名,並將邏輯移到它所屬的位置。

public class Person {

    // ...

    public boolean isMale() {
        return getGender() == Gender.MALE;
    }

    public boolean isAdult(LocalDate when) {
        Duration age = Duration.between(birthDate, when);
        Duration adult = Duration.of(18, ChronoUnit.YEARS);
        return age.compareTo(adult) > 0;
    }
}


這個小的重構已經提高了lambda的可讀性:

persons.stream().filter(p -> {
    if (p.isMale()) {
        return true;
    }
    LocalDate now = LocalDate.now();
    return p.isAdult(now);
}).map(p -> p.getFirstName() + " " + p.getLastName())
        .collect(Collectors.toList());


命名lambda:

// Implementation details
Predicate<Person> isMaleOrAdult = p -> {
    if (p.isMale()) {
        return true;
    }
    LocalDate now = LocalDate.now();
    return p.isAdult(now);
};
Function<Person, String> concatenateFirstAndLastName = p -> p.getFirstName() + " " + p.getLastName();

// Core
persons.streams()
    .filter(isMaleOrAdult)
    .map(concatenateFirstAndLastName)


流(最後一行)變得更具可讀性,而不是隱藏在實現細節的後面。它不會阻止開發人員閱讀它們,只有在必要時才閱讀。

相關文章