When to use modules

I've been reading recently about Shiny modules and thinking about when to use them (I found the how nicely explained in the modules article and in the Shiny Developer Conference talk from @garrett).

At the moment my basic understanding is that a module is a good choice when you have a collection of linked UI and server logic that you want to use either multiple times in the same app or across several apps.

Going beyond that though, I like the idea of wrapping parts of an app into modules so they can be broken down and documented more easily. E.g. my current app is a shinydashboard so I can break it into sections quite easily based on the components in the dashboard. The modules for a particular app could then be put in a package (which also contained the app) for easy documentation. Does that sound sensible? I'm slightly concerned that for this purpose modules are the wrong choice as each module would not necessarily be usable in other apps (without more work to make them very general). Maybe that doesn't matter?

I'd love to hear your thoughts, and about how you're using Shiny modules, too.

2 Likes

@jim89 Your approach makes sense to me---especially if it leads to better documentation! You could also tinker on or debug the modules one at a time without worrying about the rest of the app. I see modules as a tool to make it easier to write and understand Shiny apps; reusability is just a beneficial side effect (although a huge one).

I think this is analogous to writing a long function in R. In that case, you would likely encapsulate parts of the code as separate functions, even if you do not plan to use those functions elsewhere.

I'd be very interested to hear what others think though, because I haven't had a chance to work with Shiny apps in quite a few months.

1 Like

Does that sound sensible? I’m slightly concerned that for this purpose modules are the wrong choice as each module would not necessarily be usable in other apps (without more work to make them very general). Maybe that doesn’t matter?

I think it does not matter and it's absolutely sensible. Even if you can't reuse the modules, you're still making your code a lot more readable and explicit. Both @jcheng and myself have used this strategy in the past. I think it's a pretty good practice, not the least because it forces you to be very explicit about your dependencies and about your global state. Here's my app: GitHub - bborgesr/employee-dir. It's a multi-page app in which each page/tab is a different module. It also demoes advanced use of HTML templates, but I think the secret sauce is really the modularization :slight_smile:

5 Likes

Nice. I'll be using that repo a fair bit in the next few days I should imagine... :slight_smile:

That's an awesome app, I love the simplicity and how clean it is!

I'm probably preaching to the choir here, but using modules has enabled me to develop very large-scale shiny apps in a logical way and still maintain some level of organization :+1:

One of the concepts that I highly recommend to dive in to is passing inputs/outputs from one module to another. It took a bit of practice for me to get the hang of it, and at the last rstudio::conf I showed @jcheng my adaptation of passing a large reactiveValues() object back and forth (heavily inspired by Vincent Nijs' radiant app). While it is doing what it is technically supposed to do, it certainly is more difficult to debug and I have the risk of not knowing which modules are manipulating which slots of those values. So I'd recommend you be very explicit about which objects you pass back and forth, and try to avoid just passing one huge object every time. In my next versions of these apps I'm going to do a much better job of documentation throughout the apps.

2 Likes