В настоящее время я оборачиваю блестящие модули в классы R6 и хотел бы услышать некоторые мнения об этом дизайне.
По сути, я заинтересован в чистом подходе (читабельный код) и хочу, чтобы классы разрешали вложение (см. раздел "Вложенные модули" здесь). Текущий код отвечает обоим критериям, но у меня есть несколько вопросов относительно деталей реализации (см. "Вопросы" ниже).
Контекст
Я пишу полиморфные модули и считаю, что R6 - это хороший способ наследовать определенные поведения между модулями. Созданные объекты совместно используют данные между сеансами (не включены в приведенный ниже пример), поэтому я создал их в global.R
.
Код класса
MyModule <- R6Class(
public = list(
initialize = function(id = shiny:::createUniqueId()){
private$id <- id
},
bind = function(){
callModule(private$module_server, private$id)
},
ui = function(ns = NS(NULL)){
ns <- NS(ns(private$id))
fluidPage(
textInput(ns("text_in"), "text", "enter some text"),
textOutput(ns("text_out"))
)
}
),
private = list(
id = NULL,
module_server = function(input, output, session){
ns <- session$ns
output$text_out <- renderText({
input$text_in
})
}
)
)
Простое использование
myObj <- MyModule$new()
shinyApp(
myObj$ui(),
function(input, output, session){ myObj$bind() }
)
Верстка
some_other_module <- function(input, output, session, obj){
obj$bind()
ns <- session$ns
output$obj_ui <- renderUI({
obj$ui(ns)
})
}
some_other_moduleUI <- function(id){
ns <- NS(id)
uiOutput(ns("obj_ui"))
}
shinyApp(
some_other_moduleUI("some_id"),
function(input, output, session){
callModule(some_other_module, "some_id", myObj)
}
)
Вопросы
- Кто-нибудь делал что-то подобное раньше? Если да, то в чем главные отличия моего подхода?
- Безопасно ли использовать
shiny:::createUniqueId()
? Если нет, есть ли подобная функция в пакетеbase
? Я действительно хочу ограничить зависимости для разрабатываемого пакета. - Меня предупредили об использовании оберток вокруг
callModule
из-за вложенности. Может кто-нибудь показать использование/случай, когда этот подход не удается? - Было бы лучше использовать статическую функцию (а не функцию-член) для создания кода пользовательского интерфейса?
Заранее спасибо за любые вклады по этой теме!