5 Signs It's Time To Refactor Your Shiny Dashboard
<span data-preserver-spaces="true">Everybody loves a good dashboard. They are the best way to visualize data and provide insights. As the requirements get longer and time frames get shorter, dashboards can quickly become a nightmare to maintain. That's where refactoring comes into play.</span> <blockquote><span data-preserver-spaces="true">Are you developing dashboards in Python and Dash? </span><a class="editor-rtfLink" href="https://wordpress.appsilon.com/dash-vs-shiny/" target="_blank" rel="noopener noreferrer"><span data-preserver-spaces="true">Here's when and why you should switch to Shiny.</span></a></blockquote> <span data-preserver-spaces="true">Here are the top five reasons why you should refactor your Shiny dashboard:</span> <ul><li><a href="#reason-1">It takes minutes to scroll your Server/UI files</a></li><li><a href="#reason-2">Your reactivity is like spaghetti</a></li><li><a href="#reason-3">You want to introduce unit tests, but don't know where to start</a></li><li><a href="#reason-4">You copy-paste the code</a></li><li><a href="#reason-5">The app performance is making you sleepy</a></li></ul> <h2 id="reason-1"><span data-preserver-spaces="true">It Takes Minutes to Scroll Your Server/UI Files</span></h2> <span data-preserver-spaces="true">The backbone of Shiny applications are <code>server.R</code> and <code>ui.R</code> files. Usually, the app starts small within those files and then starts to grow. Finally, it reaches the state when navigation through the logic becomes next to impossible.</span> <span data-preserver-spaces="true">That is the perfect case for introducing <strong>Shiny </strong></span><strong><span data-preserver-spaces="true">modules</span></strong><span data-preserver-spaces="true">. Their main purpose is to avoid code duplications, but they are also great for organizing the app. </span> <span data-preserver-spaces="true">Each Shiny module consists of its piece of Server and UI logic, small enough to swallow and digest. Modules also separate the namespaces, so you don't have to worry about setting the same ID for different buttons.</span> <span data-preserver-spaces="true">The perfect Server and UI calls these modules and points the developer to the appropriate script for the particular functionality. </span> <h2 id="reason-2"><span data-preserver-spaces="true">Your Reactivity is Like Spaghetti</span></h2> <span data-preserver-spaces="true">Reactivity is what makes Shiny applications so great. It is easy, intuitive, and works nicely. However, for complex apps, it can quickly get out of hand and behave unexpectedly. </span> <span data-preserver-spaces="true">The Shiny developer's nightmare is when the app starts to refresh itself due to some unplanned event. Even worse is the race condition - the situation when your observers behave differently on each run depending on which was triggered first. Whenever you start adding the "priority" argument to the observers, it looks like a time to stop and rethink.</span> <span data-preserver-spaces="true">The idea to solve this problem is to </span><strong><span data-preserver-spaces="true">avoid reactivity whenever possible</span></strong><span data-preserver-spaces="true">. For example, widgets shouldn't be created with <code>renderUI</code> in the Server but directly in the UI. You should then use the "update" type of functions to control the flow better. </span> <span data-preserver-spaces="true">Some actions can only be performed in the browser via JavaScript, not even to bother reactivity.</span> <blockquote><span data-preserver-spaces="true">Want to make Shiny faster with JavaScript? </span><a class="editor-rtfLink" href="https://wordpress.appsilon.com/r-shiny-faster-updateinput-css-javascript/" target="_blank" rel="noopener noreferrer"><span data-preserver-spaces="true">Here's a guide to get you started</span></a><span data-preserver-spaces="true">.</span></blockquote> <span data-preserver-spaces="true">Another approach to simplify reactivity is to move the code logic to functions and classes that aren't using it. That way, these functions can be triggered whenever they are needed.</span> <h2 id="reason-3"><span data-preserver-spaces="true">You Want to Introduce Unit Tests, But Don't Know Where to Start</span></h2> <span data-preserver-spaces="true">Unit tests are a crucial concept in programming. For Shiny apps, it is not always easy to implement them. Implementation might also require some refactoring. </span> <span data-preserver-spaces="true">If you're about to introduce unit testing (probably with the <code>testthat</code> package), but you find it hard to find what to test, it is an indicator that too much logic is put directly into Shiny. </span> <span data-preserver-spaces="true">It is very tempting to have objects in the Shiny environment and modify them directly through the reactive/observers' logic. This approach is prone to errors and nearly impossible to unit test.</span> <span data-preserver-spaces="true">Make sure to move the logic to easily reusable and testable functions and classes. It will help if they are reactivity-free. The Shiny layer should be as thin as possible and only call the appropriate functions when needed.</span> <span data-preserver-spaces="true">Finally, if you already have a mature Shiny application but no unit tests implemented, it is time to work on that and refactor ASAP.</span> <h2 id="reason-4"><span data-preserver-spaces="true">You Copy-Paste the Code</span></h2> <span data-preserver-spaces="true">The easiest mistake to spot and solve. Whenever you copy-paste the code logic, it is time to stop and rethink what you are doing. It is rarely a good idea. </span> <span data-preserver-spaces="true">Extract the logic to the separate function or module, and you should be good to go. </span> <span data-preserver-spaces="true">Creating a package would be better and allow you to reuse the logic within the application and between the applications. And of course, don't forget to add unit tests to the newly extracted logic.</span> <h2 id="reason-5"><span data-preserver-spaces="true">The App Performance is Making You Sleepy</span></h2> <span data-preserver-spaces="true">"Hello World" Shiny application is blazing fast. However, as you add more and more things, it can quickly become slow and annoying. </span> <span data-preserver-spaces="true">It can be caused by redundant reactivity and useless going back and forth to the Server while staying inside the browser (see 2.). </span> <span data-preserver-spaces="true">The other common reason is overloading the app with the data processed in memory. Usually, there is no need to use whole big datasets in the Shiny application, but rather let the user filter it out first to some reasonable piece to analyze. </span> <span data-preserver-spaces="true">The <code>plumber</code> package allows us to create a smart API to the database and load only data that is needed - thus making the application fast and enjoyable.</span> <h2><span data-preserver-spaces="true">Conclusion</span></h2> <span data-preserver-spaces="true">And there you have it - top why reasons why you should immediately refactor your Shiny application. There are others, of course, but these five are the most common ones we encountered in years of developing Shiny apps. </span> <strong><span data-preserver-spaces="true">If you want to make a scalable enterprise Shiny dashboard, then you can always reach out to </span></strong><a class="editor-rtfLink" href="https://wordpress.appsilon.com/shiny" target="_blank" rel="noopener noreferrer"><strong><span data-preserver-spaces="true">Appsilon </span></strong></a><strong><span data-preserver-spaces="true">for help. </span></strong><span data-preserver-spaces="true">We're continually pushing the limits of what's possible with Shiny, and we'd be happy to guide you and your company.</span> Learn More <ul><li><a class="editor-rtfLink" href="https://wordpress.appsilon.com/why-you-should-use-r-shiny-for-enterprise-application-development/" target="_blank" rel="noopener noreferrer"><span data-preserver-spaces="true">Why You Should Use R Shiny for Enterprise Application Development</span></a></li><li><a href="https://appsilon.com/fast-data-loading-from-files-to-r/" target="_blank" rel="noopener noreferrer">Fast Data Loading from Files to R</a></li><li><a href="https://appsilon.com/r-shiny-faster-updateinput-css-javascript/" target="_blank" rel="noopener noreferrer">Make R Shiny Dashboards Faster with updateInput, CSS, and JavaScript</a></li></ul> <a href="https://appsilon.com/careers/" target="_blank" rel="noopener noreferrer"><img class="aligncenter size-large wp-image-5940" src="https://wordpress.appsilon.com/wp-content/uploads/2020/11/appsilon.hiring0-1024x576.jpg" alt="" width="1024" height="576" /></a> <p style="text-align: center;"><strong><span data-preserver-spaces="true">Appsilon is hiring for remote roles! See our </span></strong><a class="editor-rtfLink" href="https://wordpress.appsilon.com/careers/" target="_blank" rel="noopener noreferrer"><strong><span data-preserver-spaces="true">Careers</span></strong></a><strong><span data-preserver-spaces="true"> page for all open positions, including <a href="https://appsilon.com/careers/#r-shiny-developer" target="_blank" rel="noopener noreferrer">R Shiny Developers</a>, <a href="https://appsilon.com/careers/#fullstack-software-engineer-tech-lead" target="_blank" rel="noopener noreferrer">Fullstack Engineers</a>, <a href="https://appsilon.com/careers/#frontend-engineer" target="_blank" rel="noopener noreferrer">Frontend Engineers</a>, a <a href="https://appsilon.com/careers/#senior-infrastructure-engineer" target="_blank" rel="noopener noreferrer">Senior Infrastructure Engineer</a>, </span></strong><strong><span data-preserver-spaces="true">and a </span></strong><a class="editor-rtfLink" href="https://wordpress.appsilon.com/careers/#community-manager" target="_blank" rel="noopener noreferrer"><strong><span data-preserver-spaces="true">Community Manager</span></strong></a><strong><span data-preserver-spaces="true">. Join Appsilon and work on groundbreaking projects with the world's most influential Fortune 500 companies.</span></strong></p>