5 ms·
From the conclusion: > If you design a system, it is not helpful to consider options like MVC vs MVVM vs MVP. Instead, identify potential problems and if neces
by westoncb 8y ago
From the conclusion:
> If you design a system, it is not helpful to consider options like MVC vs MVVM vs MVP. Instead, identify potential problems and if necessary solve them.
I think that's a pretty good take on it. There's an annoying tendency for most conversations including the notion of MVC to devolve into nitpicking about which variant is actually being discussed and whether some architecture is 'really' MVC or something else that looks like it.
Its main value is in an abstract principle that it references: when modeling something, it's useful to separate a thing's essence from representations of that essence (the Model in MVC would be the essence and Views representations). This is an idea that shows up all over the place; it's almost certainly related to human cognitive structure in some way. (The Controller component is more arbitrary; you can see it pointed out in the article also that it was more related to implementation than the more general Model/View concepts.)
One way I've found useful for thinking about the principle is in terms of causality within a system. When you're separating out the model/essence from the view/representation portions of a system, the most important distinction is: the essence carries all the information necessary to determine (a configuration of) the representation. In this case, you can set up a mapping from the essence to the representation once; after that, you can stop thinking about the view/representation because changes to the model/essence already cover everything.
It's a very general kind of information compression that helps us manage system complexity by creating causal hierarchies.
(An example of another kind of 'causal hierarchy' I was thinking about recently: the decomposition of changes in position in Newtonian mechanics ultimately to forces (rather than working with e.g. velocity directly). If you know about the forces (and mass), they imply everything you need to know about acceleration, from which you may deduce, velocity, and then position. Once you have that mapping from force->acceleration->velocity->position your mind is freed up to only thinking about forces.)
- chiefalchemist 8y ago> "There's an annoying tendency for most conversations including the notion of MVC to devolve into nitpicking about which variant is actually being discussed and whether some architecture is 'really' MVC or something else that looks like it." Agreed. I'd like to add, for as long as I've been in any code / tech discussions (which goes back to the first commercially available home PCs), conversations nearly always default to nitpicking about something. Anecdotally, many of the tech-minded seemed to be exhibitionists. They'll go out of their way to show everyone else they're willing to masturbate over the details of some technology they hold close to their heart (?). Sorry. I had to get that off my chest.
- archagon 8y ago> When you're separating out the model/essence from the view/representation portions of a system, the most important distinction is: the essence carries all the information necessary to determine (a configuration of) the representation. In this case, you can set up a mapping from the essence to the representation once; after that, you can stop thinking about the view/representation because changes to the model/essence already cover everything. How does this work when you have to deal with animations, or state that you don't want to commit until the user completes a gesture or activity, or complex transitions between screens? It's not necessarily a good idea to shove all that stuff directly into the model. I think if you treat the Controller as a mere implementation detail, your interfaces will lack liveliness. Simulation time and running user input are just as essential to the view as any changes to the model. That's (IMO) what the Controller is there for: to encapsulate that sort of temporal complexity.
- westoncb 8y agoTL;DR: I'm experimenting with that problem now. Currently I'm trying out this idea of 'transient state' described more below. ------- I've actually been working on something that deals a lot with that problem. It's a game with all the rendering done in a single pixel shader. All the gameplay logic is in a class called GameStateTransformer. The idea was to treat the game like a dynamical system where the state evolves as a function of 1) time 2) a sequence of 'events'. The core of it is a loop that runs 60 times per second, evolving state via time-dependent logic and by grabbing/processing any events in the queue at that time. The rendering (i.e. view) is connected to the state (i.e. model) by executing a function `mapStateToUniforms()`[0] every frame. It always works the same way regardless of whether there is an animation going on or whatever; animation logic just updates parts of the state that will get mapped to GLSL uniforms (mostly it's things like `deathAnimRatio` taking on values between 0 and 1.) The situation with events taking place over time was certainly the most complex architectural aspect I had to deal with. There were two main things I used: 1) 'transient state'; I would set up a bit of temporary/transient state by making a call like `runTransientState('player.dying', {deathPosition: blah}, 1.5)` —first arg is a path into the state object, second is a 'data' object, third is the amount of time it should remain in the state. After that call my state object would contain something like `{..., player: {..., dying: {position: blah}}}` So other code could check `if (state.player.dying)` and access related sub-data (e.g. `state.player.dying.position`); and that part of the state would be deleted after 1.5 seconds. 2) Emitting events at key points during animations/transitions (generally when they finish). Also the 'transient state' system always emits an "[transientStatePath]_finished" event when a bit of transient state's time runs out (e.g. "player.dying_finished"). There was another subsystem I put in place related to this which I haven't had to use much so far though: 'contingent evolvers', which are objects that define a `condition(state)` function and an `evolve(state, deltaTime)` function, and are automatically only executed while their condition is met. Not positive how well this would scale to larger applications, but it has worked well for the game so far. Source is here if you're curious: https://github.com/westoncb/under-game https://github.com/westoncb/under-game [0] For those unfamiliar with GLSL 'uniforms' they are variables passed into your shader from the application code. Since all of my rendering is in a pixel shader, the code there is function of the current values of the uniforms + x,y coordinate of some pixel.
- itronitron 8y agoSomething not mentioned much when discussing MVC* is that each part often runs in its own process and each have distinct constraints, or performance characteristics. View is dependent on graphics rendering, Model is often dependent on IO, and Controller is typically dependent on User. In contrast to the author, I consider MVC to be a very well defined concept. However it is a concept and the implementation details are left to each specific application. In fact in any GUI there are multiple incarnations of the MVC paradigm each designed to their specific responsibility and happily ignorant of the others.