闪亮的代码设计——我应该把复杂的逻辑放在哪里?
Shiny code design - where should I put the complex logic?
致所有 R Shiny 专家:您会将以下三个服务器功能中的哪一个评为第一、第二和第三?为什么?
我今天就三种解决方案中哪一种最接近 "best practice" 闪亮的应用程序设计进行了深入讨论。 (虽然它们三个的工作原理相同。)
例如,版本 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)
我绝不是 Shiny 专家,但由于 "best" 未定义,我想我会根据我创建的应用程序发表意见(没有提供支持文档)。
从最好到最差的顺序:
- 一个
- B
- C
推理:
C:虽然在多个地方使用 output$some_output
是可行的,但这样做绝不是好的做法,只会在代码中造成混乱
B:observeEvent
是重复的,因为 renderText()
旨在观察反应变量何时发生变化。我知道你有一个更复杂的应用程序,但在这个例子中存储到 reactiveValues
是过度的,没有获得任何好处。
A:非常简单的基本代码,可以无缝运行。您也可以争辩说您可以将 if statement
从 renderText()
中取出并将其包装在 reactive()
中以保持其清洁,但它们完成同样的事情。
我很好奇是否有人会做时间研究或有一些实际文档来支持 "best" 到 "worst"。
致所有 R Shiny 专家:您会将以下三个服务器功能中的哪一个评为第一、第二和第三?为什么?
我今天就三种解决方案中哪一种最接近 "best practice" 闪亮的应用程序设计进行了深入讨论。 (虽然它们三个的工作原理相同。)
例如,版本 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)
我绝不是 Shiny 专家,但由于 "best" 未定义,我想我会根据我创建的应用程序发表意见(没有提供支持文档)。
从最好到最差的顺序:
- 一个
- B
- C
推理:
C:虽然在多个地方使用 output$some_output
是可行的,但这样做绝不是好的做法,只会在代码中造成混乱
B:observeEvent
是重复的,因为 renderText()
旨在观察反应变量何时发生变化。我知道你有一个更复杂的应用程序,但在这个例子中存储到 reactiveValues
是过度的,没有获得任何好处。
A:非常简单的基本代码,可以无缝运行。您也可以争辩说您可以将 if statement
从 renderText()
中取出并将其包装在 reactive()
中以保持其清洁,但它们完成同样的事情。
我很好奇是否有人会做时间研究或有一些实际文档来支持 "best" 到 "worst"。