Everyone who has done MVC long enough would also know that the controller is the very thin layer where services are injected and models are passes to.
The controller should have and only have logic which absolutely cannot be moved to a service layer.
Too many developers use controllers as part of their logic layer, instead of simply using it as a router for where models should be directed on a service level.
"Everyone who has done MVC long enough... The controller should have and only have logic which absolutely cannot be moved to a service layer."
Sorry, which letter in MVC is the "service layer"?
One of the reasons I don't buy into MVC is that MVC doesn't mean anything any more, and hasn't ever since the web people got their hands on it. If you ask ten developers what MVC is and get 13 different answers (see half the sibling replies to this comment), well, that's not itself a problem, but it does mean that running around telling people that they should or should not do "MVC" has been pointless for a long time.
I still like MVC for its original purpose: Multiple views in a CAD/CAM program. Makes perfect sense there. I don't think I've yet seen a place where it belongs other than that, though.
> MVC does not comprise all layers of an application.
But the topic is MVC not some particular application. I think jerf's point is that it's weird to say that a service layer is an important part of working with MVC when it's not even part of the same idea. Your statement here confirms that.
One can be talking about an expansion of the idea of MVC as if it were MVC itself, but that just proves jerf's point, too, about MVC being meaningless.
Seems to me that what people usually think of as the "Model" layer actually has "Operations", but we usually call them "methods."
And "Events" is essentially Controller code.
(There might be an argument that this describes a "fat" model vs some devs/frameworks choosing "thin" models that are just state rather than state + logic. )
It's reifying Events that attracts me to this model. This would encourage a message-passing style, which has always been a big win for me when I adopt it.
Operations is pretty much a rebranded Controller, here. But it's a good rebranding! I've seen Controllers turn into a "God class" too many times, where you end up with big lumps that do more-or-less everything.
Or, what's closer to the original paradigm, you have one Controller per Model, but that's the thing: a given action will routinely involve two or more models. Do you put a bit of persistence logic in the User Controller or the Session Controller?
Thinking in terms of Operations should encourage small classes that each do one thing, and follow their own logic, not View logic or Model logic.
And having everything communicate through well-defined Events is great, this would make it much easier to add additional sources and sinks by reusing an already-established Event with a new Operation.
It doesn't really matter what MVC "is", but it's very important where MVC goes—MVC, in the https://en.wikipedia.org/wiki/Hexagonal_architecture_(softwa... sense, belongs to one particular "adapter." MVC is not the framework of your application; it's the framework of your application's $foo adapter, where $foo can be "web" or "native UI toolkit" or "GRPC API."
Sometimes a whole application looks to be done in an MVC style; in those cases, the "application"—i.e. all the business-logic mechanism, though not necessarily all the policy controlling it—is probably some upstream thing written by a third party (e.g. someone else's API; someone else's DBMS; someone else's game engine), and the repo consists entirely of your adapter for that application.
CRUD apps, of course, really are just a reshaping of an RDBMS's DML (INSERT, UPDATE, DELETE) API, so MVC (on top of an RDBMS) really is a 100% solution to CRUD problems.
Assuming you are implicitly claiming it only makes sense to use MVC, it couldn't be MVC, because as I said in my other reply, network communication is too big a concern to just slip in to the design. It's a fundamental change. MVC doesn't have any provisions for network in it.
One of my major objections to the concept is the way people think good design == MVC and MVC == good design. I could describe to you my architecture, but then someone stuck in the MVC mindset would see my discussion of how the UI controls will drive the map object, and say "AH HA! Aren't you saying that the map is a View and the UI controls are the Controller?" To which my reply is, if MVC describes everything, and you can squeeze anything into it if you squint hard enough, it describes nothing, because that makes everything "MVC" and therefore you can't distinguish the quality of a design by whether it is or is not MVC if everything is MVC.
On the other hand, if MVC isn't everything, but is in fact a very precisely specified combination of OO patterns, then no, my Google maps design would not be MVC, because I would not use the MVC patterns as my guideline in the slightest and the odds the resulting design would happen to conform to the strict definition by the end of the project approach 0, even if you could pick out bits and pieces that sort of seem to resemble it sometimes kinda sorta. I don't "avoid" models, views, or controllers, but I never chase them.
CQRS comes to mind. spam events from user interaction, respond to them with any number of disjoint event handlers, with a tiny core runtime that ultimately acts on a specific subset of those events destined to modify the DOM in some way or another
> Sorry, which letter in MVC is the "service layer"?
Your question, sarcasm and all, makes no sense and either reflects bad faith or ignorance. The model in MVC is the model, even if it depends on the service layer or not. Design patterns describe components with respect to their roles, and the fact that the concept of service is not necessary to explain the design pattern that does not mean it should be in the acronym. In fact, models are quite obviously wrappers around repositories/gateways/services/etc etc etc. The reason behind this, obviously, is that if your goal is to simply provide a UI then it makes absolutely no sense to drag or leak the application or service layer into the interface. You just add an adapter to the repositories/gateways/services and then use that adapter to input and output the data you need to be in the UI.
> One of the reasons I don't buy into MVC is that MVC doesn't mean anything any more,
That cop-out doesn't cut it. MVC is well documented, and objectively defined. Just because some people either ignore its meaning or get a bit "creative" with their personal definition (I'm looking at you, Qt) it doesn't mean there is no concrete definition, or that you have any excuse to criticise something you don't know.
"MVC is well documented, and objectively defined."
In that case, almost nothing called MVC is MVC. For one thing, MVC has no network component to it, so anything involving client/server is automatically not using MVC, which immediately whacks what appears to be 90% of the claimed uses to me. A network layer is too important to the design of a program to just slip it in between one of the M-V or V-C or M-C layers as if it's no big deal.
I also personally consider it a critical component of MVC that it is the normal case that there are many-to-many relationships between all of the components, because otherwise, the pattern is pointlessly complicated for no gain. But it's very normal to have MVC where almost all, if not simply, all of the VC relationships are 1-to-1. You don't really have "MVC" if you have multiply-used models, but the VC element is degenerate in every use. It isn't particularly uncommon to have 1-to-1 relationships between the models either, although it is certainly the case that the models are most often reused. But then you just have data objects, not "MVC".
MVC works in CAD/CAM and similar situations, and is somewhere between "uselessly complicated" to "nonfunctional" in almost every other use case it has been ported to. (Jamming it in where it isn't necessary may "work", but is hardly a win for the pattern. Having "M" is not enough to have MVC.) Or, the term has stretched to the point where it's just useless.
The pattern is known for having been made popular by Smalltalk. In the 1980s. It makes no sense to assume that a design pattern that has been widely used for, say, 40 years is somehow not described.
The problem is just that other later GUI frameworks didn't follow that design. Smalltalk had a controller for each view to handle user input, but Windows doesn't and neither does GTK, Qt or Swing.
As Martin Fowler says[1] in his a GUI architecture overview:
"As Smalltalk developed in the 80's and 90's this led to some significant variations on the classic MVC model. Indeed one could almost say that MVC disappeared, if you consider the view/controller separation to be an essential part of MVC - which the name does imply."
I still haven't found anything that makes a clear distinction between "controller" and "model". The best explanation I've ever heard is that a controller's job is to map UI activity to the proper model and view. That's a start, but there is a lot of grey area there also as determining such can sometimes be complex in itself, which leaves the door open to "fat" controllers.
I think the biggest distinction to me is that the controller is the entry-point into an action/routine. It takes external inputs and returns an output to be sent back downstream.
In many frameworks the controller isn't even the entrypoint anymore though. Laravel for example has a separate router layer, which is the entrypoint that then passes things into a controller.
One of the biggest problems with iOS development is that most of the official coding samples include quite a lot of logic inside the controllers (called a View Controller in Apple lingo) which in turn causes novice developers to assume this is the correct way of doing it. It's such a common thing to find in codebases that the iOS community calls this the Massive View Controller pattern.
After people realise that the controller is actually the plumbing that just connects stuff, you can easily use MVC with services as described on the Eric Evans book for example and your codebase gets neatly organised, modular and testable.
it's not just code samples. i remember wwdc conferences at the time of ios3 where apple people used to officially say "we know it gets you worried, but having massive vc is actually just fine"
iOS architecture takes a bit of a while to feel out and see what works for you and your team. It's extremely overwhelming the last few years with how many alternative patterns are being pushed around and touted as the one true way.
Every Rails app I've seen has been MV, not MVC. The app/views directory contains the template part of the view code and the app/controllers directory contains the meat of the view code.
You can tell that this is happening because there is a 1:1 mapping between foos_controller and views/foo.
There's nothing wrong with MV code and it's a great paradigm for a simple app. But lots of rails apps are no longer simple...
Yeah, Rails confused an entire generation of developers by combining views and controllers into one messy, bloated, unencapsulated object, calling that a controller, and calling templates views. Rails models are also full of both view and controller logic, via validations, and full of higher-level business logic, and hacks to deal with the lack of a multi-model, transactional persistence layer.
It's possible to implement a proper separation of concerns and clean architecture using Active* modules, but Rails actively encourages bad design. I still like Ruby, and there's a lot of good software within the Rails ecosystem, but Rails itself is poorly-architected and encourages bad design.
I don't know, I err towards validation in or close to the model. You shouldn't be able to construct an invalid model and that usually involve the model validating the data you're passing to it. Rails certainly doesn't go about it in a great way though and tends to leak view based concerns into the model.
How you achieve this depends upon the language. One thing I like to do in statically typed object oriented languages is to use classes for basic data rather than spread primitives everywhere. This makes it obvious where to put validation - e.g. the PhoneNumber class in the model will necessarily ensure the data its passed isn't bad. Repeating that logic in a controller or view tends to be a poor decision.
In a Rails context, there are a dozen pattern-esque buckets that folks advocate putting non-template, non-persistence, non-validation logic into. Yet as often as seeing benefits from "service objects" or similar generic, I have also seen benefit from adding an actual View layer.
Rails has done so much to move application development forward, but if I had two nits to pick, they are the same today as they were in 2007:
1. Assuming/requiring a folder structure named after the pattern an object fits, rather than conceptual domains of an application.
2. Naming its templates "views", and not hinting to people that presentational logic should belongs in a full instance of a class, rather than in-line in template code. Partials help but insufficiently, and helpers have too many gotchas.
The sprawl of gems that attempt to address #2 this is evidence of its impact. While I appreciate the "omakase" argument, it still leads a lot of smaller or less-experienced teams to make a big mess before realizing they have better options.
Anyway, as often as I see "service objects" solutions helping a team tame their Model-View-Mess, just as often I see the solution lying in adding an actual View layer (or adding Presenters if that fits better).
I like ActiveRecord, ActiveRecord::Relation, ActiveSupport, and all the other things people tend to gripe about in Rails-land, but the specific folder structure has always been a stick in my craw.
I find the rest of Trailblazer a bit over-engineered and prescriptive, but I really like cells (http://trailblazer.to/gems/cells/). IMO these are good for encapsulating view state. It more replaces the "helper" layer than controller layer, but it also helps you write controllers that just focus on HTTP stuff and nothing else (together with service objects, of course).
Aren't services just the DRYing up of controller code into functions? Like moving ad-hoc 3rd-party API code into a 3rdPartyApi.fetchItems() namespace? Or your inline database calls into a db namespace?
Seems kind of a stretch to come up with a distinct name for such an elementary software design concept. Just like I think it would be silly to call the helper functions I write for my view layer "ViewServices", and then act like its some novel thing that the newbies aren't doing enough of.
No, not just DRYing (at least, not in my opinion).
There should be a real separation of concerns/division of responsibility.
So the direct controller "only" coordinates the model, view, and services. I put it in quotes because there's still a lot in there (which should be organized as well): changes coming from the model, UI events from the views, and events from each of the services involved.
Well, I guess you can call all of that DRYing, but it is definitely a deeper activity than just factoring out repeated code. There's real design to be done, to determine what the key concerns are exactly and how they compose to form your app.
(Put another way: you can superficially factor out repeated code and still end up with a soup of interconnected services, controllers, models and views with a variety of communication mechanisms between them.)
Controllers abstract transport-layer functionality away from application logic. It's not really about "DRY" as it is about "Why should my services have to care about HTTP status codes?"
Where I've seen this done well, All of the data for rendering a view was pulled at the beginning of the action. The database transactions are over and done with, the cost of each request is very clear, and frequently caching is un-needed because you know that 3 different parts need the same data so you just give it to them instead of waiting for somebody to ask.
There are a few frameworks that work this way, but many don't and developers have to constantly add caching layers to get anything done (and then spend tons more effort fixing cache invalidation well enough that nobody notices it's still broken)
That and the notion that global variables or state are not a thing in modern software explains most failed UI projects built by juniors initializing things as global variables from controllers that also contain logic, layout, and other stuff that does not belong there (aka. an untestable & disgraceful mess).
The same pattern applies to MOVE. Events are data and operations should do nothing else than hand off to a service layer; if it's more than 1 or 2 lines of code, it probably is mixing concerns and should therefore be refactored. Otherwise you just moved the problem (bad pun, sorry) and made it even harder to test because now your business logic is a side effect of an event that is processed asynchronously.
Service layers are easy to test because it's just easily mockable constructor/initializer injected dependencies + a bunch of stateless functions that take input and produce output (and side effects). Classic mistakes here are to make the dependencies global variables and/or making the service layer initialization actually initialize dependencies.
Yeah, the Rails community noticed this a while ago. Put the business logic doing transformations on models and interacting with external dependencies in service classes, which accomplishes three things:
1) Avoids bloating model objects.
2) Avoids creating complicated controllers.
3) Makes it much easier to move to a microservices architecture when the time comes, because business logic has already been grouped into isolated components.
Yup, This is a pattern I've come to call MVCS. I want to see I saw that in a bit of documentation somewhere but I haven't been able to find it again. The C layer should be as thin as possible and have logic in it that pertains to routing and whatever kinds of transforms your "wire"/"transport" layer needs while the Services do all the heavy lifting and contain most of the business logic.
>The C layer should be as thin as possible and have logic in it that pertains to routing and whatever kinds of transforms your "wire"/"transport" layer needs while the Services do all the heavy lifting and contain most of the business logic.
I believe Trygve Reenskaug (the inventor of MVC) would agree with this point. After MVC he went on to invent "Data, Context, Interaction" (DCI) [0], which aligns with what you're describing.
Where a service could be something external or just a library, module, class or function. I always think service is a bit of vague term describing a bunch of related functionality packaged in some reusable abstraction so you don’t need to reimplement this logic every time high up in your app.
But yes your comment makes sense. It also applies to the react world, where I have seen many apps with a ton of logic inside the lifecycle methods of react components. Lifecycle methods are the new controllers.
This simple concept pretty much bridges all design philosophies in practice. You have MVC and OOP, you have functional services, and you are free to create the appropriate amount of layers you need.
To address another comment, MVC does not mean only MVC, it's just a framework that allows you to add layers where appropriate.
I always say the Controller knows "what" not "how". But after a few years in iOS I kind of settled for a very fine-grained MVC pattern with Repositories, Reactive ViewModels and a separate Layout class per ViewController. Navigation is abstracted away but it's just a protocol implemented by a UINavigationController, nothing special. The ViewController doesn't do anything anymore except holding and wiring up the labels buttons etcetera and respond to events like viewDidLoad.
Just chopping up every single part (even table view cells) into view controllers made everything so simple that not only Controllers are super thin and dumb but also ViewModels remain really thin, but not to the point where they start feeling like a unnecessary abstraction.
Making a split between "more like a View" ViewControllers and UI code free ViewModels really helps, but I guess it's also the dirtiness of UIKit MVC that kind of forces you to abandon the ViewController.
That is right. And having service layer which dictates model changes, db ops and with its result a view change is pretty close here. This move pattern also reflects a bit the reflux idea of events and actions on models (with my limited redux knowledge).
I've rarely seen people fail to realize that having at on of code in a really fat layer is a problem.
I've seen lots of people fail to separate that code in a clean and extensible manner. The result is a still-fat layer that's split across a bunch of different files and methods. But every piece is still concerned with almost every piece of context that was originally passed into the controller.
Composability and separation of concerns are the answer, but it's much more of an art than something I've ever seen a simple tutorial for. It's gonna look different for different business cases.
Re: It's gonna look different for different business cases.
Conway's Law rules. We need constructs that easily help us fit the stack to our teams and shop conventions. MVC allowed a shop to throw masses of people and code at a problem instead of removing the need for masses of people and code.
The web made a mess out of CRUD app programming and MVC was a first step in taming the mess, but it requires fat staffing and lots of specialists to manage the screwy parts.
MVC is fine. After years experience in mobile development, my main takeaway is that application architecture acronyms in general are over-rated.
The most important thing is to separate concerns, and to agree on some sensible structure for managing views and state, and communicating between them. Usually the details of that should arise from the needs of the application, not come top-down from some idea about "the perfect application architecture". Aside from that, everything should just be kept as simple as possible.
IMO it actually adds a lot of unnecessary pain and complication to a project when a team is too rigid about which letter of an acronym each piece of code must fit into. VIPER would be an extreme example of this. It should not take five+ separate code files to execute an HTTP request and display the results in a list view.
To be honest, the real pattern is MVW (Model View Whatever).
The third thing can be a controller (true MVC), a presenter, a view-model, or, in the case of the article, operations and events.
The big deal with all this is that we have a view, usually provided by a UI framework, a model, usually provided by the app developer, and some kind of loose coupling. That's it, the good old idea of separating data from its representation.
What you stick between the model and the view is just an implementation detail of your particular framework, optimized for your particular use case.
> The third thing can be a controller (true MVC), a presenter, a view-model, or, in the case of the article, operations and events.
Well the article introduces weird new lingo which I don't think is all that great, but whatever.
"operations+events" can be equaled to "business logic". Let's keep that separated from the controllers. I want to create a new user via an http request, but I also want to do the same via a console command and since I want to do both things with the same code but one of these shouldn't be returning http status codes, it makes sense this should live in a different layer.
The whole events & operations separation in the article don't make sense to me. A "login attempt" as described in the article with a "login attempt" event being triggered by the view and that being picked by a decoupled "operation"? I don't see the value. If the operation needs to check privileges does it trigger an "check privileges" event, wait for another operation to complete? does that operation trigger another event to report the result? Wait a second... this sounds a lot like a convoluted Redux clone. Then you realize the only reason we are not doing Redux in the backend is because we are used to mutable state databases.
> To be honest, the real pattern is MVW (Model View Whatever).
It's not a pattern if it's not clearly identifiable as a pattern, MVC (original) applied to GUI interfaces. ASP.net tried to apply MVC to the web and it resulted in Webforms, which is true MVC, ASP.net MVC ironically isn't true MVC.
Like everything in IT MVC eventually became a buzzword thus lost all significance, that's why it doesn't really mean anything anymore since it doesn't describe anything specifically to most people who use the expression.
MVC is understood to be the primary partition of an application's architecture. It does not obviate the need for further code organization, which is done in all parts, Model, View and Controller. When the author says "controllers are nice self-contained bit of...[what I don't know?]", and they use that as the justification to throw away the paradigm in favor of another with Model-View-Operations+Events they show they don't understand this. Worse the proposed paradigm does not then collect all the controller code in one place, so the overall lifecycle of the application would be harder to piece together from Operations+Events modules without an overarching Controller to govern the two of them.
In my opinion, the mistake the OP makes is in not realizing that the dogmatic application of a design pattern is the fundamental issue to begin with.
So then the solution offered is another design pattern that can be dogmatically followed.
If we know that you need a UI (view), and we know that you need to represent your data in an expressive manner (model), and you need something to pull those things together for a user, a router and controller does not automatically come to mean “put all your logic here!” Instead, it means something more like “here’s where you can tie things together in whatever way makes the most sense for your application”, which lets you e.g., use AOP to handle auth (like Django decorators or middleware), delegation to a service like a REST API (e.g., Django REST Framework), or basic one-off views for simple tasks.
If something like this MOVE was to become the next big thing, I think there’s a good chance we’ll be rewriting a lot of projects to use MVC in 10 years.
Don’t blame bad code on a proven and very flexible design pattern that solves a very real problem. Blame bad code on bad coders.
Personally I see this design pattern simply as an application of Dijkstra’s Separation Of Concerns. That MVC is the best (most orthogonal and balanced) division of concerns in a gui based app.
Yeah - build out a graphql service on top of existing models, and you'll get a pretty clear picture about what the C ought to represent. You can find plenty of situations where the implementation of any of those letters is extremely thin: lots of services where the View is almost nothing (often just a JSON serialization of some of the models), or where the models are very thin. It boils down to a weirdly common, but deeply flawed, view that all the letters in your abstraction's initialism should be of equal complexity.
With Views, it seems to be easy for devs to understand that there is significant differences in the underlying approaches: are you organizing your views into page templates, serializing for some special client to consume, building components that compose one another, etc. I don't know why we can't wrap our heads around Controllers also having different approaches.
Events are how MVC was used before the web world came around. The whole point was your controller listens to model and view events so everything is updated real time as the model changes and the user interacts with the UI. The web is a bastardized version of MVC due to the lack of interactivity and state when compared to a desktop GUI application.
That aside, lots of people in the web world have a sort of "Operation" layer in MVC but call them a "service". Deciding to use events is another architectural decision some people make even in web MVC.
But you can take or leave any piece of this stuff and I feel like you don't need a new acronym for every combination of architectural decisions.
> Events are how MVC was used before the web world came around. The whole point was your controller listens to model and view events so everything is updated real time as the model changes and the user interacts with the UI. The web is a bastardized version of MVC due to the lack of interactivity and state when compared to a desktop GUI application.
It seems you're mixing up implementation details with the actual design pattern. It makes no difference if you implement MVC with events or objects or imperative programming. The only thing that matters to a design pattern is the pattern, and the pattern is how three components interact to drive an user interface.
Then the web came, and we have the MVCS+JS+REST mess. Explanation:
Model: The Javabean
View: The HTML
Controller: Whatever Java code that calls the service layers,
Service: The services in the lower layer,
JS: Since you have js with your HTML, then the JS also acts kind of like a controller for complex parts of the UI,
REST: Well that’s a second entry point to your service layer, to which the JS transmits Events (as in MOVE) that cannot be managed by a page reload. It’s a back channel unknown to the Controller.
Turns out Conrad Irwin was right, but didn't take it far enough. Merge together "Events" and "Operations" into one thing, call "Models" just "state" and you've got Reactive Programming, which appears to have proven itself as the best known way to manage UI state complexity.
Proven in what way? After almost 4 decades in this business, nothing is ever proven. For anything one person says is beyond discussion obvious, another person does something completely different, and gets the same benefits. Every generation comes up with new ways to do things, but nothing has even been clearly better to everyone all the time in all circumstances. You constantly have to evaluate everything that comes along, and see if it's better for you, your team, project, company or industry. Silver bullets are for vampires and the Lone Ranger.
It is "proven", not in a mathematical sense, nor a scientific sense, nor an engineering sense or even a legal sense. It is proven in a javascript sense.
React is just MVC turned inside out. The core principles still apply:
1. Any operation that changes the state the program is being used to manipulate should go to a single place and be fanned out to subscribers from there.
2. You want to be able to build compound views from simpler views and still treat them as the same kind of thing.
3. You want to be able to parameterize views over the behavior from interacting with them, e.g., you want to parameterize a button over what should happen when you press it, what its label should be, and if it is enabled.
You can do strict MVC in JavaScript just fine (https://github.com/madhadron/mvc_for_the_web). React has one major win that MVC can't give you: if you have lots of teams all putting things onto the same page, React controls the refresh loop so one team's code can't keep updating and destroy the performance of the whole page.
Reactive programming looks like a very good model for UIs, but I wouldn't claim anything is proven.
I am not sure we even got any implementation that is more convenient than event based UIs from a couple of decades ago. It does certainly looks like such implementations exist, they feel just within grasp, but there is a long way into "proven".
Nearly all UI frameworks use MVC. That includes iOS, ASP.NET Core, JSP and JSF (both Java), Ruby on Rails, and Django (Python).
In fact, it is easier to list UI frameworks that are not MVC-based: WPF, which is based on MVVM and React+ReactRouter+Redux, which is based on Flux.
MVVM was invented in order to support 2-way data binding. Inspired by WPF, many early JavaScript frameworks supported 2-way data binding. These days 2-way data binding is widely acknowledged as a poor design as it makes it hard to keep track of how data is flowing through your application. For more on that see [1].
React was originally introduced as the "V in MVC" [2]. Since then it drifted away from MVC in an ad-hoc manner. In part this is because of ReactRouter, which made router a view component (!), and in part this is because of Flux/Redux. The facebook engineer who came up with Flux famously declared that MVC doesn't scale (!!). This assertion was widely challenged, and later she acknowledged that it is bidirectional data flow that doesn't scale [3]. She had assumed that MVC automatically implies 2-way data binding. Redux, an implementation of the Flux architecture then became popular, and became closely associated to React, so much so that many developers believe using React implies using Redux. This is unfortunate because Redux requires tons of boilerplate ("so much throat clearing", as one developer put it), which MVC does not require.
There's a third option, an Entity-Component System (ECS). It is common in games but scales well to UIs. Everything in your UI is stored in a flat structure. Instead of putting a button in a widget 5 layers of nesting deep, you put them all in an Button[] array, and other entities reference a Button by its index. Objects are laid out more like a normalized database table than an OOP tree. Your UI thread is an event loop that iterates over and mutates the widgets. This is extremely fast, cache friendly, easy to reason about, and can scale to the tens of gigabytes (AAA games).
It's funny how the software industry can simultaneously produce games with hundreds of textured 3D models flying around the screen at 60 fps, but if I want to load a big data table of nothing but text in a web browser, the fans start spinning and the scrollbar locks up.
The Models are all the code that define your business logic. They have no idea how they get represented in the UI, and they have no idea what calls their operations.
The Views accept data and generate a UI of some kind. They have no idea where the data comes from, or what their requests actually do.
The Controller knows about both the Model and the View. It maps request from the View to operations in the Model, and then uses data from the Model to update the View.
M <= C => V
That is the broad structure behind how all those things works. They aren't all the same, but that's not the point of a design pattern.
Not _required_. There's both "inherent" and "incidental" complexity around Redux [0]. We've created our new Redux Toolkit package [1] to specifically eliminate the "incidental" complexity and simplify common Redux usage patterns. It includes utilities to simplify several common Redux use cases, including store setup, defining reducers, immutable update logic, and even creating entire "slices" of state at once.
We also just released the official Redux template for Create-React-App [2] to help speed up the process of setting up a new app.
Speaking from experience I wish WPF was based on MVVM, MVC, or even a consistent usage. What it is really based upon is hypocrisy and piles of footguns.
I don't see anything wrong with MOVE... but why does MVC need to be dead?
It's such a perfect representation of the coder trope of loudly proclaiming that this new thing I found makes everything else obsolete. Eight years later, MVC is still miraculously not dead!
It's worse than that. MVC is not only not dead, this little essay has conveniently reinvented it! (The C became an O, and the E was always there in some form.)
"That which is not dead may never die, unless involved in a serendipitous knife fight with a one-arm incestuous twin of your current lover" starts to strain the metaphor a _tiny_ bit. I think it's probably more useful in terms of expressing the problems with NPM.
With time I’m noticing those who think anything is going to die or old/new are often relatively still new in their journey of software development.
One of the reasons I see feeding this is tossing around senior dev titles with 3 to 5y experience. Even as a higher producing developer, all it did was open my eyes to how much I really had to learn.
The reality is seeing one, let alone two 10y cycles of software changes your relationship to architecture of code so much .. that I really hope seniors with 10y exp may not be the same as seniors with 20y experiences in the sheer amount of trauma they have had to help organizations heal from using the latest and greatest that is reinvents the same libraries and frameworks, and leaves more technical debt behind than it offsets by requiring refactoring in months instead of years.
Most languages are now very reasonably capable due to quality frameworks for most. This alone will do more to improve the quality of code bases in the next 10y than a replacement for MVC..
I invented a new methodology called "scattered paperwork"...
All you have to do is type all of your project documentation in MS Excel, print it out, and then throw it all over the place... Then Developers can simply pick what's on top and meet for 23 minutes (once every 2 years) to discuss their emotions... It's been a very productive decade for us so far.
My cousin's boyfriend's sister went up to the waterfall, and when they found her body 12 months later--after delivery phase--she had been completely burned out from the inside. And there was this thing... that nobody wanted, that didn't work right, just sitting there next to her. Nobody wanted to touch it. So some guys from the federal government came and picked it up with tongs, and said they'd put it in the Source Control Repository facility out in New Mexico, so it couldn't hurt anybody else.
Where can I find a good resource to learn these patterns well for web use?
I've never gotten into any of these patterns in 20 years but can get the job done efficiently as I don't put codes all over the place but at where it's easy to find for easier debugging.
Usually average people try to put their codes into these patterns without truly understanding and their logic is also not efficient, turning codes into very unreadable state instead of just dropping the pattern and write as you please (with at least minimal separation of views and consolidate identical codes).
I've always had a very loose view of MVC. It feels like all the MVC/MVVM/MV(whatever) concepts really are about separating the model from the view, and having something to connect the parts. I've never gotten hung up on the specifics beyond that, but it seems like framework after framework is built on exactly worrying about those details.
It's been 20 years - have I been missing out on a crucial details?
Ummm maybe folks are just using MVC when they shouldn't?
I don't really think most people understand how to do MVC. A LOT of people mostly pick a framework that incidentally has it slapped on the side and that's about it...
People seem to assume "view" has to mean template, "model" has to mean "database access," and controller means "anything else." When in reality, they're far simpler and more abstract and has nothing to do with the web or services:
Model - Data
View - Output
Controller - Takes input, fetches data for input(s), gives output
Do you have a part of your application that takes input and gives output? Well then MVC is probably great for that part of your application, maybe not.
I have not ever had anyone say "the adapter pattern is dead, don't use dat shit, my dear, brometheus" because most people, quite accurately, don't think it's some sort of philosophical statement it's just way to organize some shit to make your life easier when it applies.
/shrug
Use the right tool for the job; you can waste a ton of time trying to use a screwdriver on nail, or you could just get a hammer...
I like this a lot, not as an alternative to MVC but as a kind of conceptual refactoring of the same ideas behind good MVC implementations that's very easy to explain and doesn't have as much ambiguity.
I've posted a version of this comment before, but my main problem with MVC isn't that it's a bad architecture, just that in practice there's a huge amount of disagreement about what MVC (or MV* more generally) actually _is_, which can lead to confusion or weird/bad hybrid implementations.
I tend to use the "model" and "view" concepts a lot when discussing architecture, but in my experience it's almost always a mistake to try and reference any specific MV* pattern for explanatory purposes - it does not have the effect of making the discussion clearer.
The issue is that there isn't actually a consensus about what constitutes the definitional features of these patterns, especially when it comes to how the concepts involved actually translate into code. For any sufficiently notable discussion of an MV* pattern, you're going to find an argument in the comments about whether the author actually understands the pattern or is talking about something else, and typically the commenters will be talking past one another.
Note that I'm NOT claiming that there's anything wrong with MV* as an architecture, or your favorite explanation of MV* - it may be perfectly well defined and concrete and useful once you understand it. The issue is a feature of the community: lots of other people have a different (and possibly worse) understanding of what MV* means, so when you start talking about it and your understandings don't align, confusion arises. Getting those understandings back in alignment is more trouble than the acronyms are worth.
I've seen enough conversations about concrete development issues suddenly turn into disagreements about the meaning of words to realize that nothing useful is conveyed by mentioning MV* and assuming anyone knows what you're talking about - it's better to spell out exactly what you mean in reference to the code you're actually talking about, even if you have to use more words.
I like this MOVE scheme because it seems to me to divide up the conceptual space at the joints in a way that's relatively hard to misunderstand, and it seems a little easier to see how to directly relate those division back to code.
One thing seems true about MVC or any other similar pattern/acronym: people seem hostile-certain that their interpretation/implementation is correct and everyone else is doing it wrong. Even in this thread are a bunch of comments like "everyone knows" followed by a personal opinion and then a thread of confused support/dissent. People then insist their interpretation from Wikipedia, Smalltalk, Ruby or wherever is actually the one everyone agrees on as some well-defined thing despite clearly no one in this very thread agreeing.
Every platform has it's own challenges to work around. Trying to take a pattern you used in Qt and applying it precisely the same way to a Javascript/HTML application would be unwise. Things like the DOM, CSS and even the quirks/strengths of Javascript mean you should approach the problem differently. This can mean you are forced to structure your code differently. The same is true if you are dealing with iOS and Swift.
IMO, MVC should mean something different in a way that supports the context it is being applied within.
The only implementation that I can outright say is "wrong" is the Apple's iOS ViewController, which people mistakenly call MVC...and then promptly throw the kitchen sink into that layer without a casual thought, growing that single file to thousands of lines of code, with state, business logic, display logic, and everything else all wound together...and thinking everything is well and good because they are following the MVC pattern.
The ViewController isn't bad all by itself, but calling it MVC is just not it.
Ben Jaffe of Udacity cally is MVO where O = Octopus.
Basically, as the author points out, Models and Views are relatively well defined, but the Controller can be anything. Octopus, ViewModel, or in this case Operations and Events.
I do think Operations and Events are clear, but
1. are they comprehensive and
2. do they organize the code more intuitively?
It seems like you would want to put them in the same place since Events will trigger operations that operate on the model and the view. Sort of like a controller... oh, wait.
I'm a big fan of the "fire and motion" concept of dev social paradigm.
The idea is that devs and large companies have a tendency to constantly move away from tried and tested concepts not because the juice is genuinely worth the squeeze, but because doing so forces the devs "in their dust" back into learning mode and out of productivity mode, thereby maintaining or creating leadership over them (i.e. you force them into playing catchup -- catchup to your new "hot" thing).
Case in point with this article: an attempt to declare that a tried and tested and widely used concept is now outdated, and they know the "right way" we should be doing it.
This paradigm is important from a dev management perspective, in that there must be an element of actively suppressing this in a dev organisation.
E.g. having approved tech lists so you don't have another half dozen js frameworks inserted over the next 12 months, requiring permission to stray outside standard paradigms, and compartmentalizing experimental time from production time.
Otherwise your dev output drops through the floor.
MVC is fine. Its a basic concept that aligns with the underlying hardware: model - memory, view - screen, controller - cpu. It ain't broke, don't let your devs fix it.
This is an interesting idea, particularly if you couple it with other ideas or tools. The one primary issue I have with event driven systems is that it is very difficult to look at code and intuitively know what's going on.
If you're having to search your entire code base to see what happens when a user logs in, and then what happens if that user is marked as "blocked", it can get very complicated quickly.
Even worse, trying to backtrack events can be more complicated. What caused the "add to cart" event that added this special product type that is actually a digital download, but that wasn't a UI event? It could have happened in one of 10 places, debugging is difficult because you have to start somewhere in the middle and work your way backwards.
This is the issue I've had with wordpress development, actions and filters can make intuitively understanding what's going on under the hood very very difficult. Of course they give a lot of flexibility with plugins, extension points, etc, but when multiple plugins are interacting it can get very confusing.
Compare that with a more imperative controller where you branch based on conditions and you can generally follow the logic flow. Of course, there are ways to make that complex too like Form classes, validation, ORMs, etc. But I still find the more imperative paradigm of MVC easier to follow, such as in a Django case.
Where I say this can get interesting is in a use case like React. In a way, events are propagated through a tree and can be kicked off by data changes, such as in redux. If you design it right, there might be more promise in an event-based system, but introducing both server side and client side tends to complicate things.
> MVC is a phenomenal idea. You have models, which are nice self-contained bits of state, views which are nice self-contained bits of UI, and controllers which are nice self-contained bits of … What?
The implication is that what goes into controllers is not well-defined. But if what goes into models and views is well-defined, as the author agrees, then defining what goes into controllers as everything else is actually a precise definition.
I feel like his answer to what goes in the controller is answered by his acronym MOVE. Operations and Events go in the controller. It initiates the state changes in the model and the view. As an aside it’s cool to see something like MVC staying relevant, it alludes to there being design patterns that are simple and fundamentally useful in some areas.
Operations ^H^H^H Functions
A common function for applications is logging a user in. It’s actually two sub-functions composed together: first get the email address and password from the user, second load the “user” model from the database and check whether the password matches.
Functions are the doers of the MFVE world. They are responsible for making changes to your models, for showing the right views at the right time, and for responding to events triggered by user interactions. In a well factored application, each sub-function can be run independently of its parent; which is why in the diagram events flow upwards, and changes are pushed downwards.
What’s exciting about using functions in this way is that your entire application can itself be treated as an function that starts when the program boots. It spawns as many sub-functions as it needs, where each concurrently existing sub-function is run in parallel, and exits the program when they are all complete.
"What’s exciting about using functions in this way is that your entire application can itself be treated as an function that starts when the program boots."
I still see MVC in $dayjob, but it looks like React/Redux have helped a lot. A central module manages state and takes operations on that state. The desired view hierarchy is computed as a pure function of state. A library uses diffing to apply changes to the concrete implementation of the views (say, the DOM, or a native windowing framework).
I'm not sure this pattern as described is comprehensive, but the move away from MVC to other event-based patterns like React/Redux, Elm, etc, clearly did happen. MVC of course still exists in the world.
This article is the first one I’ve read on MOVE. On the other hand I’ve seen multiple in the past few years on MVVM and VIPER, just to name two MVC replacements. My guess is MOVE isn’t used much.
> the problem with MVC as given is that you end up stuffing too much code into your controllers
> [Under MOVE, e]vents are used to join all these components together safely.
The problem with events is that you put all interactions into events, creating a labyrinth of ad-hoc protocols.
Events are messages, and messages are just methods in disguise: worse ones, that don't have a call stack you can inspect.
Under this MOVE, someone will sooner or later hit the problem of wanting the V to manipulate the M in some way that O doesn't support, and will just end up creating some hack whereby a whole chunk of the M state (perhaps all of it) is downloaded via some stream of events, edited, and sent back via another stream of events.
I spent just enough time with MVC to experience that there's so many flavours and opinions and confusion and uncertainty. All of that was a smell that:
1. this is a complicated domain.
2. the lack of a very clear coherent "right answer" tells me not to dwell too much on it. I'll see more gains by getting my UIs into production and initiating the feedback loop than trying to get the architecture right.
As for item 2, I have absolutely iterated on underlying architecture, non-stop. But I feel I've been immensely successful in never letting that get in the way of shipping early and often and learning the 90% of stuff you can't learn without shipping.
So it seems that anyone can make up their favorite "architecture" even if it's not well defined. (Is MVC actually well defined?) My favorite was MVPC (Model-View-Player-Controller) as I was mostly developing an app for blind users, where a good speech/audio interface is the top priority. The "Player" here is much like an OS scheduler where you can post various tasks (speeches/sound effects) in a queue and get a notification when it's finished. This greatly simplified the event handling part as it eliminates the needs of individual timers, counters and flags.
My biggest issue with MVC is that in my experience it always ends up having the C being glue between fat Ms and fat Vs, with multiple views ocasionally growing tendrils between one another.
As in, not the pattern, but the real-world usage of it. Development constraints always end up corrupting the pretty pattern in ways that make the current problem at hand easier to solve, and this de facto architecture IMO never ends up looking like proper MVC for me.
I want to say I like Action-Domain-Responder better, but I haven't seen any real-world implementations of a ROA with it yet.
Now what are operations then? And how are they tied to events.
Let us assume a concrete architecture where views are html documents and events are put into some distributed queue. Is an operation a process that consumes events from that queue or is it something more tangible? Are operations data? In other words, are they interpreted? By what interpreter?
I think the idea of describing your business system as some giant, distributed, parallel DSL interpreter has some merits. But has it ever been implemented as such somewhere?
Sometimes it doesn't matter what the rules are just that there are rules because the rules bring order and consistency that allow for quick comprehension of the written code.
Hilariously, this is basically the pattern everyone figured out long ago with Windows Forms apps. Model View Presenter with decoupled events that are fired off to any subscribed listeners. Multiple screens and models can be updated as needed. Very easy to do in a C# app thanks to uncluttered syntax for events.
Go check out the "Microsoft Patterns and Practices" frameworks from decades ago to see many examples of this.
> Since it was invented however, new programming techniques have become popular. Without closures (or anonymous blocks) event binding can be very tedious; and without deferrables (also known as deferreds or promises) the idea of treating individual operations as objects in their own right doesn’t make much sense.
Didn't the Smalltalk team invent MVC? Because I believe Smalltalk in the 70s supported both.
I'll never understand the obsession to have one architecture to rule them all. mVC isn't dead. I set up MVC patterns all the time for small projects where I need CRUD with a sprinkling of custom code on top. It's a great pattern.
If it's not meeting your needs that just means it's not a good abstraction of your problem. And yeah, you should probably look for something else.
It's very rare to give any credence to any breathless "X is dead". Do what makes sense for you to solve the problem in front of you. There's anti-patterns but bike shedding over architecture patterns is a waste of time for a large majority of most CRUD webapps with low traffic requirements I'd wager.
What’s the point of this? No way of architecting software is dead. Just use the model that works best for the task at hand, including the competencies and preferences of the development team. Everything has its place. Besides, software architecture is not a religion, just a technique.
I've found MVC annoying, but everyone goes "everyone else is doing it so we have to do it also". Lemming Syndrome. In team environments it's usually good to standardize "slots" for certain activities. But MVC doesn't fit our work-structure well (Conway's Law).
What's good for websites is not necessarily good for data-centric CRUD. MVC tries to cater to both, and does neither well because it has to compromise to make both camps happy.
I'd like to see, first, the file/folder location be flexible. If a team wants to store the view together with the model (or view-model) in entity folders, they can. Make the file look-up mechanism more flexible, or at least have a few templates to choose from. Our shop would prefer something like this:
Second, navigation (menus, URL's, and breadcrumbs) should probably be table-lized in the RDBMS so analysts and project managers can change paths and titles and perhaps even role assignments without re-coding. The "path math" of controllers is confusing and hard to debug. Put the damned tree(s) in tables instead so we can do nice reports and analysis of them without digging through verbose code. There was an anti-DB movement in the early 2010's that was wrong-headed in my opinion, so everything was shoved into app code instead. It's time to embrace DB's and use them again for what they are good at. We then wouldn't need controllers, at least not in everyday work.
Note: If I say something bad or wrong, please explain in a reply instead of give a hit-and-run negative score. I get better with clear feedback. Thank You.
Pyramid's resource trees solve the "path math" problem quite nicely, there are some caveats to that kind of design as well, of course (mostly related to enumerability).
What's wrong with them being in the database? Analysts and project managers can then re-arrange things with fewer coding changes, using CRUD editing screens. One may have to re-project some URL's for the end-user's sake, but that's doable. "Pretty" URL's are not that useful for CRUD anyhow, but since customers expect them (because everyone else has them), they can be managed as an aesthetic wrapper.
I should note I'm a fan of the CASE idea of the 90's. It was just that the products were proprietary and too expensive. 90% of most CRUD apps can be attribute-driven. Menus, navigation, page titles, field attributes, etc. can largely be stored as meta-data in RDBMS where they are readily change-able and query-able. Buried in code makes them harder to work with. Over-focus on OOP killed the CASE dream, but I suspect it will come back. RDBMS are good at storing and managing masses of related attributes, code just isn't. (Dynamic Relational would help with attributes that are different or custom per UI widget etc. I wish it would take off.)
Computer-Aided Software Engineering. It has different interpretations, but in my usage it means most of the application is controlled by meta-data that defines navigation, data relationships, field info, screen names, role associations, etc.
It's essentially a glorified integrated ERD + IDE. If you think about it, most of the info that goes into a typical CRUD application can come from tables. Related: "Data Dictionary". When I first saw them, I went, "Wow! This is the future!", similar to my first Macintosh visit. (One tricky part is dealing with the 15% or so that still needs custom adjustments. I have some ideas about that, but that's another long topic.)
I have to confess it's the first time I read about MOVE but MVC seemed old news for almost a decade to me. MOVE seems to englobe concepts I work with like DDD, read/write segregation, event source, etc which can all live under its umbrella
State (sometimes loaded externally through APIs/network calls) modified through events (typically user input) presented to the user (typically visually). How is MVC dead? That's the majority of coding I do when I do frontend...
I think the problem going on here is that the intent of what MVC means in theory is being conflated with its alleged implementations in practice. As you said here, this is the most pure and academic view of MVC. Few would disagree that the general flow of events and state is just as you described.
The implementations of MVC are generally terrible, because the "C" is extremely subjective and you cannot find consistent patterns to follow universally. One developer's MVC app is going to look a lot different from another's unless they work on the same team or follow the same policies.
MVC (in practice) ultimately says "ok here's 80% of the puzzle I cannot figure out, good luck dealing with it". We can mostly agree on what our various businesses need or want (models+views) as well as what the browser API standards are (mostly views). The tricky bit is synchronizing those worlds in the middle. I personally find that pulling as much of the front-end into the back-end as is feasible is the most productive path to go down. It might not be the most scalable, but there is something really magical about being able to inject a business service you wrote 5 years ago into a .NET Core 3.1 Blazor component, write a small in-line LINQ mapper, and have it directly populate a table marked-up with BS4 (which then updates in real time via basic CLR event subscription). Is that MVC? I don't know. I don't really care either. It gets the job done, is easy to maintain, and makes me look good when it "just works".
Well, MOVE, as described in the article, is exactly the same as MVC, since views are notified for state changes via events, and controllers are notified by views via events as well.
I like ECS when designing certain kinds of systems but I'm not sure how relevant it is here. I'm also not sure it would be particularly useful for your average webapp.
The controller should have and only have logic which absolutely cannot be moved to a service layer.
Too many developers use controllers as part of their logic layer, instead of simply using it as a router for where models should be directed on a service level.