重构方法序列

时间:2018-08-01 13:54:44

标签: java java-8 refactoring optional

我有一系列方法需要顺序运行,将每种方法的结果用作下一个参数。但是,在调用下一个方法之前,我还要检查每个方法的结果是否为“好”(如果“坏”,则我将尽早退出该方法。如果方法不成功,则返回空的Optional。 / p>

是否可以执行重构以改进代码? 责任链感到有些落伍。

private boolean isSequenceSuccessful() {
  Optional<byte[]> result1 = doSomething();

  if (!result1.isPresent()) {
    return false;
  }

  Optional<byte[]> result2 = doAnotherThing(result1.get());

  if (!result2.isPresent()) {
    return false;
  }

  Optional<byte[]> result3 = doSomethingElse(result2.get());

  if (!result3.isPresent()) {
    return false;
  }

  return doMoreStuff(result3.get());
}

我不想使用Exceptions来控制方法的流程,因为那是代码的味道(我希望有时会得到“不好的”结果)。

4 个答案:

答案 0 :(得分:3)

您可以使用Optional和映射将其写得更短:

private boolean isSequenceSuccessful() {
    return Optional.of(doSomething())
            .flatMap(result1 -> doAnotherThing(result1))
            .flatMap(result2 -> doSomethingElse(result2))
            .map(result3 -> doMoreStuff(result3))
            .orElse(false);
}

或者使用更短的方法引用:

private boolean isSequenceSuccessful2() {
    return Optional.of(doSomething())
            .flatMap(this::doAnotherThing)
            .flatMap(this::doSomethingElse)
            .map(this::doMoreStuff)
            .orElse(false);
}

这取决于您的喜好。如果要保留中间结果变量,请使用lambda版本。

由于方法doAnotherThingdoSomethingElse确实返回了Optional<byte[]>,因此需要Optional.flatMap才能继续映射。否则,您可以将这些方法的返回类型更改为仅返回byte[]。然后,您将只使用Optinal.map,它将更加一致。

仅当Optional中存在一个值时,才执行映射。如果可以应用所有映射,则返回最后一个的值作为结果。否则,处理将快速失败,并绕过所有restig映射到最后一个语句orElse并返回其值。根据您的代码,这是false

答案 1 :(得分:0)

您可以使用library(ggplot2) library(dplyr) library(reshape2) library(readr) data1 <- read_csv("Kaggle.csv") data2 <- read_csv("country_population.csv") data2 <- melt(data2, id.vars = c("Country Name", "Country Code", "Indicator Name", "Indicator Code"), variable.name = "Year", value.name = "Population") data3 <- read_csv("life_expectancy.csv") data3 <- melt(data3, id.vars = c("Country Name", "Country Code", "Indicator Name", "Indicator Code"), variable.name = "Year", value.name = "Life Expectancy") years <- unique(data3$Year) countries <- unique(data3$`Country Name`) library(shiny) ui <- fluidPage( sidebarLayout( sidebarPanel( radioButtons(inputId = "secondgraphvariable", label = "Choose a Variable for the Second Graph", choices = c("Life Expectancy", "Population"), selected = "Population" ), selectInput( inputId = "years", label = "Choose years to display", choices = years, multiple = TRUE, selected = c(2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013) ), selectInput( inputId = "country", label = "Choose a country", choices = countries, selected = c("Tanzania", "United States", "India", "China"), multiple = TRUE), selectInput( inputId = "xaxis", label = "Choose a Variable for the X-axis of the First Graph", choices = colnames(data1), selected = "Gini coefficient 2005-2013" ), selectInput( inputId = "yaxis", label = "Choose a Variable for the Y-axis of the First Graph", choices = colnames(data1), selected = "Gross domestic product GDP percapta" ) ), mainPanel( plotOutput(outputId = "scatterplot")) ) ) server <- function(input, output) { output$scatterplot <- renderPlot({ req(input$xaxis) req(input$yaxis) scatter <- ggplot(data1, aes(x = input$xaxis, y = input$yaxis))+geom_point() }) } shinyApp(ui = ui, server = server) 方法:

map

答案 2 :(得分:0)

使用Optional::flatMap

private boolean isSequenceSuccessful() {
    Optional<Boolean> result = doSomething()
        .flatMap(this::doAnotherThing)
        .flatMap(this::doSomethingElse)
        .map(this::doMoreStuff);
    return result.isPresent() ? result.get() : false;
}

答案 3 :(得分:0)

看看模板图案,我有时将其称为披萨图案,因为它类似于制作披萨。 (例如createDough(),putIngredients(),bake(),package(),deliver())。这可能适用于您的情况。这里有几个示例和实现,但是请选择最适合您的示例。在上面的示例中,我将创建一个抽象类并创建具体的类/实现。举例说明:

public abstract class SequenceChecker {

    // ...

    public boolean isSequenceSuccessful() {
        Optional<byte[]> result1 = doSomething();
        Optional<byte[]> result2 = doAnotherThing(result1);
        Optional<byte[]> result3 = doSomethingElse(result2);
        return doMoreStuff(result3);
    }

    protected abstract boolean doMoreStuff(Optional<byte[]> result);

    protected abstract Optional<byte[]> doSomethingElse(Optional<byte[]> result);

    protected abstract Optional<byte[]> doAnotherThing(Optional<byte[]> result);

    protected abstract Optional<byte[]> doSomething();

    // ...
}