-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
MVC Architecture #250
Comments
Under the current design, I think the View is What you want is probably access to client data: http://rstudio.github.io/shiny/tutorial/#client-data Then it is up to you to define whatever controller you want. Not sure if that answers your question. |
My view is that model, view and controller are all in server. The view is output$ and input$ Controller is reactives and observers. -Alex Brown
|
Well, I do not have a CS background, so I may well be speaking nonsense :) |
Yeah you don't support MVC then. proper separation of concern would mean your business logic would be separate from the VIEW so 'ui.r' could not hold VIEW and CONTROLLER; that doesn't make sense. |
So, this merits a much larger discussion which is how Shiny as a web app framework is situated in and fits into the rest of the web app world. @jcheng5, I feel like at some point, we should write something along these lines... I'm just going to try my not-completely-well-formed-yet two cents here. The two frameworksMVC (and the subsequent idea of Separation of Concerns, SoC) has been the most popular web app framework until fairly recently. Nowadays, I think it is very much a tie between the traditional, imperative MCV frameworks and the more declarative, functional alternatives made possible with things like ReactJS (complemented by Flux/Redux) and Shiny's reactivity. With Shiny, we've mostly decided to commit ourselves to reactivity and a declarative render style, because we feel like that is better suited for the kind of apps that our users want to create. There's some exceptions to this, like the brand new In the reactivity world, the controller becomes a blackboxIn traditional MVC, the controller is essential and explicit: you have to specify what to do when you receive user requests and what resources you are going to mobilize to carry out the necessary tasks outlined in the model. In the reactivity world, the controller becomes a blackbox: you no longer have to worry about the sequence of imperative mutations to the DOM. The framework takes care of that for you. You only need to specify how to render the view given a particular state. When that state changes, the framework will do the work of calculating the most efficient set of mutations that take you from where you are to where you want to be. So the controller is effectively hidden from the app author, who can rest assured that -- given the right "recipe" for rendering -- the frameworks knows how to process any user request. This results in code that is more predictable. You just have to know the state of your application at any given time -- you don't have to worry about a series of imperative statements and how all those DOM mutations translate into a new state. One-way data bindingShiny has one-way data biding in a similar way to the single directional data flow that Flux has. On the other hand, MVC typically uses two-way data binding (between the model and the views) which does not necessarily scale very well. You can end up with hard-to-spot cascading and nested actions, which again makes code less predictable and harder to debug. Because of this difference, the very concept of a "model" is not as relevant or important in the reactive world as it does in the imperative or MVC world. I feel like "rendering instructions" or "recipe" make a lot more sense for reactivity. But if you want to stretch this terminology, you could kind of say that the model is whatever is placed inside the For Shiny, what this means is roughly the following. In your server code, you can (and should) have: output$y <- renderXXX({
## code that uses input$z
}) But you can never have: input$z <- renderXXX({
## code that uses output$y
}) So inputs inform outputs and never the other way around. If you need dynamic inputs, you have to use either SoC revisitedSoC is a concept that makes a lot of sense in the MVC world; it is less relevant in the reactive world. For example, if you want to be strict about this, you can say that ReactJS violates SoC because the same component often both controls the state and renders it. But these two frameworks are so different that this comparison seems a little unfair. Moreover, you can actually make that argument that the reactive world does SoC better than the MVC world in the sense that the latter frames SoC around three concerns: Model, View and Controller. In the reactive world, concerns can be defined in much broader terms -- and you can create a modular component to address whatever concerns you settle on. You can still try to follow the traditional SoC in Shiny by doing all the Views strictly in the Other resourcesI recommend this video from Facebook Developers, which describes the shortcomings they found with MVC and how Flux and React were created to address these. While there are obviously differences with Shiny, it's a good overview of the two different approaches. |
Could I've an application developed with Shiny following Model View Controller pattern.
For example...
My Views -- > HTML5/ CSS/ JS.
And my Models and Controllers programed in R language using Shiny framework.
Mapping actions in some configuration file like this.
{
url: /mysite/path/action1?id=data1&n=1000
controller: ShinyController
action:Action1
}
I have file:
ShinyController.r
Action1 = function(id, n){
...
}
The text was updated successfully, but these errors were encountered: