Super Solutions for Shiny Apps #4 of 5: Using R6 Classes

[This article was first published on r – Appsilon Data Science | End­ to­ End Data Science Solutions, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Super Solutions for Shiny Apps #4 of 5: Using R6 Classes

TL;DR

Why use object-oriented programming in Shiny applications? It’ll help organizize organize the code in your application!  

one of these days i'm gonna get organizized

Organize Your Shiny Code with Object-Oriented Programming

Classes are used widely in all R programming — usually the S3 ones. Even if you’ve never heard of them, as an R user you’re for sure familiar with object classes like data.frame. The magic of classes makes same functions (like print or plot) operate differently for specific cases. This system also allows you to define methods and attributes dedicated for object – thus basing your code around objects, not functions. How can it be useful in Shiny app? Well, for advanced apps it helps you in organizing your code. When designing a Shiny app it is often the way it should work – usually the user is interacting with some specific data structure that requires e.g. exploration, modification, saving, exporting etc. What is more, Shiny apps contain much more additional stuff required for production-ready applications that will work great when being organizized organized in a class system.

Let us go through this functionality. 

You may wonder what objects can be stored in the app. Well, there might be ‘settings’ with private fields of configuration and public methods to get or modify them. There might be a ‘user data’ class with all of the values specific for the logged-in user and methods to read them. The data probably comes from some database, the connection to which may be another class, as well as the log builder. And some specific spatial dataset used on this new screen that required unusual functions to operate on. And so on…

The point is this: once your app grows with new functionalities you will end up with tons of functions organized between multiple ‘utils-something’ scripts and a bunch of lists with stored current values. Using object oriented programming (OOP) in the Shiny App allows developers to organize the code in the packs object-attributes-functions. It will introduce a clear system of getting the current state of the piece of functionality, the operations that can be performed with it, the auxiliary functions, the initial state of the object (which can depend on the particular user access rights, which might be very useful!).

In Appsilon we recommend using an R6 class system. What is R6? To make a long story short, it is a modern, fast and simple implementation of object-oriented programming (OOP) in R. To learn more about the system, check Hadley’s Advanced R book.

How do we recommend organizing the code with the class system introduced? Keep each class in the separated script with a name similar to the class name, and store them all together in a folder separated from other code e.g. ui definitions of modules (folders structure might be problematic when developing a Shiny app as a package – doing it has pros and cons. In Appsilon we do not package our apps as it gives us more freedom with building the apps). Once the code is imported (either in a package or separately with e.g. modules::use function) the class needs to be initialized in the global.R script with the new() method (automatically available for all classes) and attached to some object. The class, its attributes and methods can be used everywhere in the code – but you’ve gained a clear overview of the purpose of the method call and what object it modifies and where to find the details about this particular functionality.

Here’s a practice example: 

# in global.R
logger_manager = LoggerManager$new()

# in logger_manager.R
LoggerManager <- R6Class(
  "LoggerManager",
  private = list(
    ...
  ),
  public = list(
    initialize = function() {
      ...
    },
    log_input = function(
     ...
    ) {
      ...
    }
  )
)

It might not be obvious from the beginning which classes will be used in the code – Shiny apps often start as a simple prototype to finally become some advanced production solution. Just don’t be afraid and always have in mind that classes are a good solution to organize your code once your app goes big! 

Thanks for reading!  Questions? Comments? Add them below and/or find me on Twitter @dubelmarcin.  You can also check out the other posts in the “Super Solutions for Shiny Architecture Series”: #1 Using Session Data, #2 Javascript is your friend, and #3 Softcoding Constants in the App.   

And don’t forget to sign up for our newsletter!

Article Super Solutions for Shiny Apps #4 of 5: Using R6 Classes comes from Appsilon Data Science | End­ to­ End Data Science Solutions.

To leave a comment for the author, please follow the link and comment on their blog: r – Appsilon Data Science | End­ to­ End Data Science Solutions.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)