闪亮的代码设计-应该将复杂的逻辑放在哪里?

时间:2019-11-12 21:11:43

标签: r session shiny listener shiny-reactivity

对所有R Shiny专家:您将对以下三个服务器功能中的哪一个进行第一,第二和第三评分,为什么?

今天,我对这三种解决方案中的哪一种最接近“最佳实践” Shiny应用程序设计进行了深入的讨论。 (尽管它们三个都一样工作。)

例如,C版本对我来说很奇怪,因为有条件地覆盖渲染函数是不必要的(因为有条件输出渲染是这些函数的作用)。

当然,原始应用程序在处理输入值时包含更多逻辑。我简化了示例以使区别显而易见。

library(shiny)

ui <- fluidPage(

  shiny::radioButtons(
    inputId = "some_input", 
    label = "Please choose:", 
    choices = c("something", "nothing")
  ),

  shiny::textOutput(
    outputId = "some_output"
  )  

)

# version A: all logic within rendering function
server <- function(input, output, session) {

   output$some_output <- shiny::renderText({

       if(input$some_input == "something"){
         # imagine some complex logic here
         "some value was chosen"
       } else {
         NULL
       }

   })

}

# version B: most logic within input observer, 
# using reactive session userData
server <- function(input, output, session) {

  session$userData$memory <- shiny::reactiveValues(
    "stored_value" = NULL
  )

  output$some_output <- shiny::renderText({
    session$userData$memory$stored_value
  })

  shiny::observeEvent({
    input$some_input
  }, {

    if(input$some_input == "something"){
      # imagine some complex logic here
      session$userData$memory$stored_value <- "some value was chosen"
    } else {
      session$userData$memory$stored_value <- NULL
    }
  })

}

# version C: all logic within observer, 
# setting the rendering function conditionally
server <- function(input, output, session) {

  shiny::observeEvent({
    input$some_input
  }, {

    if(input$some_input == "something"){
      # imagine some complex logic here
      output$some_output <- shiny::renderText({ "some value was chosen" })
    } else {
      output$some_output <- shiny::renderText({ NULL })
    }

  })

}

shinyApp(ui = ui, server = server)

1 个答案:

答案 0 :(得分:1)

我绝不是一个闪亮的专家,但是由于“最佳”的定义没有定义,我认为我会根据自己创建的应用程序发表意见(没有提供支持的文档)。

从好到坏的顺序:

  1. A
  2. B
  3. C

理由:

C:尽管在多个地方使用output$some_output可以工作,但这绝不是一个好习惯,只会在代码中造成混乱

B:observeEvent是重复的,因为renderText()旨在观察反应变量何时更改。我知道您有一个更复杂的应用程序,但是在此示例中,存储到reactiveValues的操作是最重要的,没有获得任何好处。

A:非常简单的基本代码,可以无缝运行。您也可能会争辩说可以将if statement中的renderText()取出并包裹在reactive()中以使其更干净,但是他们完成了相同的事情。

我很想知道是否有人会进行时间研究或有一些实际的文档来将“最佳”备份到“最差”。