The key to getting MVC correct is understanding what models are

55 csb6 33 9/7/2025, 1:26:44 AM stlab.cc ↗

Comments (33)

whstl · 2h ago
This problem that MVC has is similar to the problem with OOP itself, with monads, or with some design patterns: the original/popular definitions were so incredibly abstract and disconnected from real life usage that they ended up being whatever the person implementing it wanted it to be.

And then, 10, 20 years after the fact, people will start attacking popular implementations that differ from the original using some "new canonic interpretation" that is either extremely recent, or an interpretation that is old but was lost in time.

This is especially common around Smalltalk and OOP for some reason. Smalltalk's OOP is nothing like what existed either before or after, but since Alan Kay invented the term, Smalltalk is weaponised against C++/Java-style OOP. Not that C++/Java OOP is the bees knees, but at least their definition is teachable and copyable.

Design patterns suffer because in most explanations the context is completely missing. Patterns are totally useless outside very specific contexts. "Why the hell do I need a factory when I can use new"? Well, the whole point is that in some frameworks you don't want to use new Whatever, you dummy. If only this was more than a two-sentence blurb in the DDD book (and the original patterns book totally glosses over this, for almost all patterns).

And monads became the comical case, because they are totally okay in Haskell, but once it gets "explained" and migrated to other languages they become this convoluted mostly useless abstraction at best, footgun at worst (thinking of the Ruby one here).

skydhash · 38m ago
> *Design patterns suffer because in most explanations the context is completely missing. Patterns are totally useless outside very specific contexts.

It's hard to define how a pattern can be useful, because they're patterns, not recipes or snippets. They're supposed to fit in the reader's solution, not the author's examples. You're supposed to have the problem before reaching out for a solution and patterns are not solutions, they're models of solution, each with their own tradeoffs, costs and advantages.

adityaathalye · 39m ago
MVC (and other OOP patterns) work around the fact that the language does not solve the Expression Problem.

You could say, the key to getting MVC correct is understanding the Expression Problem, and designing its solution into your programming language in the first place, so you don't need MVC, but if you want to do it, it becomes actually neat and clean and modular.

frumplestlatz · 1h ago
> with monads

There are a set of three short laws that define what a monad is. I’m not sure that really fits in with MVC, OOP, or design patterns.

https://wiki.haskell.org/index.php?title=Monad_laws

antonvs · 38m ago
It’s weird that your comment seems to be downvoted. Monads have a precise mathematical definition. Comparing them to those other broad, handwavy things is delusional ignorance.
aryehof · 1h ago
> Smalltalk's OOP is nothing like what existed either before or after, but since Alan Kay invented the term.

Rubbish. In terms of OO language constructs, Smalltalk is almost entirely derived from Simula. Let’s not revise history.

whstl · 1h ago
This is an oversimplification, and part of the problem I mention.

The "big leap" in Smalltalk was the idea that everything is an object and computation is message-passing, not just classes and instances. That’s not from Simula. Simula was more like an extension of Algol with OO bolted on. Smalltalk was a whole new conceptual model, which is not as simple to explain as Simula/C++/Java-style OOP.

mpweiher · 19m ago
Hmm...have you looked at Smalltalk-72?

Now Alan makes it clear that the inspiration for OO came from Similar (and a bit from the Burroughs 220 and 5000, from Sketchpad etc.), but to say that Smalltalk is just that is a stretch at best.

The more direct line goes from Simula (Algol with classes) to C++ (C with classes).

to11mtm · 1h ago
IDK I think it's still worth considering where certain languages 'got the right things right together' to be constructive...

That said as someone fairly unfamiliar with Smalltalk I'd like an example of what other parts of Smalltalk play well with it's OOP Sauce...

jerf · 1h ago
One of the other markers of "true MVC" I look for is that you ought to have pervasive mixing and matching of the pieces. It is common for models to see some reuse in multiple "views" and "controllers", but if all or almost all of your controllers match up to precisely one view, then you're burning design budget on a distinction that is buying you nothing. If you've got strictly one-to-one-to-one matches for each model, view, and controller, then you're just setting your design budget on fire.

Another major aspect of the original "true" MVC is multiple simultaneous views on to the same model, e.g., a CAD program with two completely live views on the same object, instantly reflecting changes made in one view in the other. In this case MVC is less "good idea" than "table stakes".

I agree that MVC has fuzzed out into a useless term, but if the original is to be recovered and turned into something useful, the key is not to focus on the solution so much as the problem. Are you writing something like a CAD program with rich simultaneous editing? Then you probably have MVC whether you like it or realize it or not. The farther you get from that, the less you probably have it... and most supposed uses of it I see are pretty far from that.

skydhash · 28m ago
> If you've got strictly one-to-one-to-one matches for each model, view, and controller, then you're just setting your design budget on fire.

That's sensible. But it's generally useful to split your core state from your presentation, and then you'll find strands of logic that belongs to neither, generally glue code, but some can be useful enough to warrant a module of their own. Also your core state can be alien from the view itself (think a game data (invisible walls, sound objects) and the actual rendering).

Maybe this architecture is not MVC, but MVC can be a first stab for a quick and dirty separation. Then once a cleaner separation can be done by isolating specific modules (in layers, graph, whatever)

catlifeonmars · 1h ago
> if all or almost all of your controllers match up to precisely one view, then you're burning design budget on a distinction that is buying you nothing.

This is a really insightful way to frame it.

kqr · 43m ago
Oooh. Now I get it. I've been dismissive of MVC for nearly as long as I've known it but I realise I've only seen the bad versions. What you describe as correct sounds much more sensible.
travisgriggs · 1h ago
As a former and long smalltalker who learned MVC from the ParcPlace crowd…

I used to say things like this. M and V were always pretty unambiguous, but “controller” was kind of like “Christianity”, everyone talks like it’s a unifying thing, but then ends up having their very own thoughts about what exactly it is, and they’re wildly divergent.

One of the early ParcPlace engineers lamented that while MVC was cool, you always needed this thing at the top, where it all “came together” and the rules/distinctions got squishy. He called it the GluePuppy object. Every Ux kit I’ve played with over the years regardless of the currently in vogue lets-use-the-call-tree-to-mirror-the-view-tree, yesteryears MVVM, MVC, MVP, etc, always ends up with GluePuppy entities in them.

While on the subject, it would be remiss to not hat tip James Depseys MVC song at WWDC

https://youtu.be/kYJmTUPrVuI?feature=shared

“Mad props to the Smalltalk Crew” at 4:18, even though he’d just sung about a controller layer in cocoa that was what the dependency/events layers did in various smalltalks.

adityaathalye · 22m ago
I used to be very confused about MVC and MVCC and what have you---I can't keep design patterns straight in my head (personal limitation)---I finally went down a rabbit hole of trying to figure it out from scratch.

Like, why do we even need any of that stuff? I blogged about it [1] and spoke about it [2] and the post even got some HN love [3].

The opening parable concludes with this...

   Multitudes of sworn "Rails developer"s, "Laravel developer"s, "Django 
   developer"s, "Next.js developer"s and suchlike throng the universe… 

   Why?

   ...

   ...

   Once upon a time, there was one.
   WebObjects.
   Now they are numberless.
The occasional email and DM gives me succour that I am not alone in my confusion. Even people who've "grown up" using traditional MVC frameworks took a minute to self-check and felt "huh, looks like I can look harder at this thing that I do".

Clojuring the web application stack: Meditation One

[1] blogged: https://www.evalapply.org/posts/clojure-web-app-from-scratch...

[2] talked: https://www.youtube.com/watch?v=YEHVEId-utY&list=PLG4-zNACPC...

deck: https://www.evalapply.org/posts/clojure-web-app-from-scratch...

source: https://github.com/adityaathalye/clojure-multiproject-exampl...

[3] discussed: https://news.ycombinator.com/item?id=44041255

165 points by adityaathalye 3 months ago | 39 comments

zkmon · 21m ago
It was basically the 3-tier architecture hijacked by some authors with hyper sales-pitch who messed it up beyond recognition. The 3-tier model has 3 simple layers - Data, Business, Front-end. The MVC inventors called data as "Model" - I could not get my head around this weird naming. What does "Model" mean in plain English? And why do you need those dotted lines between Front-end and Data layers bypassing the Business layer? MVC is a fake that lasted for decades.
mmahemoff · 2h ago
A major advantage of pure models is testability. If your conception of a "model" is perversely a user-facing widget, congratulations, you'll need to write UI tests that simulate button presses and other such user actions, and maybe even inspecting pixels to check resulting state. Tests like that are a pain to compose and are fragile since the UI tends to evolve quickly and may also be vulnerable to A-B experiments. Juice ain't worth the squeeze in most cases.

In contrast, pure model components tend to evolve slowly, which justifies the investment of a comprehensive test suite which verifies things like data constraints, business logic, persistence. If automated testing were seen as a priority, this would be a no-brainer for any serious app. However, testing tends to be underappreciated in app development. This goes some way to explaining why frameworks carelessly fold in M, V, C to the same component.

mikepurvis · 2h ago
Yes to all of this with the provisos that a) there’s enough meat in terms of business logic and validation to justify the indirection of a separate object and b) you’re under a language or CI regime that can validate the boundary between the two classes for basic flubs like function misnames or bad arguments.
andrewflnr · 1h ago
> If your conception of a "model" is perversely a user-facing widget

Do people really do this? That's mind-numbing.

lukasb · 2h ago
Any implementation of MVC I've seen the V and the C are so tightly coupled the separation seemed artificial. Skill issue?
andrewflnr · 1h ago
Yeah, it's really hard to tease them apart in a GUI sort of environment, since the input is so tightly tied to the graphical view. Model and View have always seemed pretty obvious to me but I've never gotten a compelling answer as to what a controller is.

My best guess from this article, given then "associated by observer" link from View to Controller, is that the View is supposed to pass events to the Controller, which will interpret them into changes to the Model. But what's the format of these events that's both meaningfully separate from the View, e.g. could be emitted from different views to maybe different controllers, but doesn't just force the View to do most of the work we want the Controller to do?

skydhash · 52m ago
Controller is where your logic is. Your model is your state, and the view is presentation. Both are static. The controller is the dynamic aspect that update the view to match the state and update the state according to interaction or some other system events.

Splitting the logic from the state and presentation make the code very testable. You can either have the state as input and you test your presentation, or have the presentation as input (interaction and lifecycle events) and test your state (or its reflection in the presentation).

Also this decoupling makes everything more flexible. You can switch your presentation layer or alter the mechanism for state storage and retrieval (cache, sync) without touching your logic.

mjevans · 47m ago
Agreed, but maybe my mental model is splitting the 'Controller' aspect into the client / server model. Everything must get validated server side, there's no other rational choice. Otherwise you cannot enforce any consistency or business logic.

That just leaves formatting the requested changes into a language the server model accepts.

Maybe model is more 'database', controller is API interface (server side + client request requirements), and view is end user render?

to11mtm · 53m ago
At least in my head, the 'controller' is what can either take 0 or more parameters or input models as 'input' and the controller can either provide direction to the browser as to what to do next.

e.x. in a 'proper' ASP.NET MVC 4 project I 'inherited', the View took input data in and with a tiny bit of JS magic/razor fuckery around the query page etc, but overall the controllers would return the right hints for the Razor/JS 'view' to move the application flow along or otherwise do a proper reload.

samtheprogram · 40m ago
> For example, in ObjC an int is an object, but it is not observable. However, an ObjC object with an int property is observable using Key-Value Observing

I haven't written Objective-C in a decade or so, but isn't this a pretty big mischaracterization of the language? NSInteger is a typedef to a C type IIRC, while there's NSNumber for the cases you want an object and/or are deserializing -- and which has observable propeties?

b_e_n_t_o_n · 1h ago
I feel like MVC is trying to get at a core concept of having your application state in one place, your view objects/state in another place, and then having a third piece that updates the application state.

So like in React, you'd have your Redux store as the Model, React components (with useState etc) as the View, and then your Controller is the reducer which is called from UI code and updates the Model.

Maybe that's incorrect definitionally, but it makes sense to me.

pixelworm · 2h ago
I think nearly every definition of MVC I've read has been different. At this point it just means you split something into three classes as far as I can tell.
cypherpunk666 · 2h ago
jpalomaki · 45m ago
It would be interesting to read a case study of how the MVC was applied in some larger SmallTalk app.
gundmc · 2h ago
Getting totally lost in several different enterprise software implementations of MVC was a major contributor to my impostor syndrome early in my career. Glad to have some sort of vindication that I wasn't alone
aryehof · 1h ago
This perpetuates the myth that a model is an object. One object. This has lead to todays common misconception that a model is one anaemic data-bucket representing typically a database table.

Instead a model is one or more collaborating objects.

hansvm · 1h ago
And what do you call the Model object holding those collaborating objects? Is that not still one object? The article explicitly supports your position that models can be complicated (see the paragraph starting with "to support more complex views").
mkoubaa · 2h ago
The reason MVC got so abused was because of RAD frameworks: rapid application development. Most of this started with visual basic.

Basically, the thinking was to let the programmer design the view and then implement the code-behind. I'll spare you from my rants about this, but it was popular.

Nowadays, with vibe coding, there is no need to use obtuse design patterns for the sake of RAD. Sensible architectures can easily by used by LLMs without sacrificing engineer or designer agility.