Skip to content(if available)orjump to list(if available)

The key to getting MVC correct is understanding what models are

whstl

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).

chrchr

The reason to use a factory instead of 'new' is that a factory can vary the return type, unlike a plain constructor. You need a factory when, based on the constructor parameters or the system configuration, different classes of object may be instantiated. I really have to disagree with your characterization of the GoF book. The premise is that it's a set of designs that can be applied when specific situations are encountered, though, granted, if you're reading the book before you've actually seen the situation where a particular pattern can be applied, it seems abstract. Certainly, popular conceptions of patterns taken out of context make that problem worse.

ozim

From my experience patterns suffer from new devs thinking that patterns are guidelines for writing their code and that they should create code that is generic and implements patterns. (Yes if their job is implementing framework, not when their job is to use framework to build business app)

Like everyone totally forgot patterns are mainly for understanding existing systems like you use a framework - hey this looks like a factory let’s use one from the framework we built stuff with instead of implementing our own.

Besides of course every developer wanting to build framework so others adhere to what he built not the other way around ;)

ahartmetz

I think of design patterns as possible solutions to certain problems. They should be used when the corresponding problem arises and their mental overhead is less than whatever the alternatives may be. I use them quite sparingly.

I don't find them very useful (today) to understand existing systems that don't intentionally use the patterns. They don't occur very often in well-designed systems in the first place, even less so unintentionally.

ozim

First of all design patterns were not some god given solutions. Those are solutions gathered from existing implementations and authors just gave names to those solutions.

So they will be present in well designed systems just that they are not called by their „book name”.

Then I clearly see it in all new frameworks just that each framework has their own name for implementation of the pattern.

Patterns were mostly named so people can discuss easier about solutions that are there.

I will quote first sentence of foreword from my copy of the book „All well-structured object oriented architectures are full of patterns.”

whstl

The original book completely failed to communicate that, though. This is common knowledge today, but wasn’t for a long time.

RossBencina

> Design patterns suffer because in most explanations the context is completely missing.

"most explanations"? Most crappy explanations on the web and in introductory courses perhaps.

The original GoF Design Patterns book and all of the Pattern Languages of Program Design books that followed it define and adhere to a pattern (form, template) for how to document design patterns. The main elements of this form are (GoF, p.3):

1. The *pattern name* ...

2. The *problem* describes when to apply the pattern. It explains the problem and its context [emphasis mine]. ...

3. The *solution* ...

4. The *consequences* are the results and trade-offs of applying the pattern. ...

I am guessing this form comes from Christopher Alexander, but I don't have a copy of A Timeless Way of Building at hand.

galaxyLogic

Don't overlook the "Forces". While "Problem" explains WHY you might need the specific pattern in question, the "forces" explain why some trivial solutions are not very good solutions, because you have to take into account the constraints, the assumptions about the context, why the problem is actually a problem.

MVC is a great, even proverbial pattern, but I don't recall having seen it presentewd in the "Patterns Format" anywhere. Such a presentation would make it easier to understand no doubt.

Kerrick

It is presented in the patterns format in at least these places:

- Pages 125–143 of Pattern-Oriented Software Architecture (1996) by Buschmann et al. ISBN 978-0471958697.

- Pages 330–332 of Patterns of Enterprise Application Architecture (2003) by Martin Fowler. ISBN 978-0321127426.

asalahli

> 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.

This is what happened with REST too, and it frustrates me more than it probably should.

The original pattern is such a good idea and not even remotely abstract. It's a well defined architectural pattern for a well defined problem yet people still managed to bastardize it to the point that the term REST barely means anything today

whstl

This is another good example. I remember people getting very angry here 10-15 years ago over HATEOAS.

In most discussions REST has come to mean “cute URLs” thanks to Rails.

mcny

I don't know who is to blame for this -- I think it should be the entire team, not just the developer for every time I click a link from a message somewhere on my phone and a website opens which opens an app and it says "congratulations, you have performed this operation (that isn't idempotent)". Like ok, but why are you doing stuff with a get action... Shouldn't you prompt people to ask in the app hey I am about to do something, do you want me to?

Pamar

What about "microservice", then?

rendall

Unfortunately, Fielding's dissertation itself alone gives inadequate guidance to construct or even fully identify a REST API, and so a over the subsequent years a mishmash of sometimes contradictory blog posts, discussion forums, militancy, angry flame wars, and books fleshed out the REST.

The 2007 book RESTful Web Services was wildly influential in popularizing the standard by clarifying and presenting a set of further guidelines or constraints that it called Resource-Oriented Architecture.

LegionMammal978

As far as I can tell, he's not even describing an "API" as we'd normally use the term today. For all practical purposes, it's pretty much just "using an HTTP server and hyperlinks to let (human) users discover and interact with resources". (Or replace "HTTP" with another protocol like it in all but name.) If it has any structure past that, then it's not REST in his sense.

Personally, I think "API" is an unclear term for that kind of structure. The only actual interfacing is the HTTP protocol between the server and web browser. But the browser traditionally only acts as a proxy for the user, who is the one being served access to the resources.

bobajeff

>since Alan Kay invented the term, Smalltalk is weaponised against C++/Java-style OOP.

Often I see actual common practices of "OOP" being used as arguments against it. Which are then dismissed as 'not true OOP' by it's proponents.

Only recently did I see someone give a presentation talking about not just the historical meaning of the term and it's origins but also the common practices that are associated with it and detailed some issues with it. (I'm guessing because he was tired of hearing the same defenses over and over again.)

kriops

Monads are well-defined, though. Monoids in the category of endofunctors, anyone?

The problem is when implementations aren’t actually monads at all. The same goes for other functional concepts. I wrote a blog about Java’s Optional::map here: https://kristofferopsahl.com/javas-optional-has-a-problem/

It’s the same kind of problem, where naming signals something the implementation is not.

(Am I allowed to link my own blog btw?)

lock1

Unrelated with GP post: What's wrong with Java's Optional?

IIRC it doesn't fulfill monad axiom, but I don't think there's a huge problem with it. By the time you're using Option<>-like, I don't think you should use bare `null` at all in your project. Mixing Option<>-like and bare `null` sounds like playing with fire.

Also, if you're using Java 17+ (`record` in your example), you're probably better off writing your own Option<T> to support sum-type matching & product-type destructuring.

kriops

Optional::map returns an empty optional if the passed function returns null. This is incorrect and can be especially hurtful in intermediate operations. Allowing Optional::map to return an Optional<void> would have been correct.

Alternatively, just don't call it 'map'.

I agree implementing your Option<T> type is better. The problem is that people will use whatever is available in the standard library—I am not working in isolation.

ekidd

Yes, monads are abstract, but the definition is also very precise. Specifically (using C++/Rust notation for parameterized types), if we have a type "M<T>", we also need:

    fn unit<T>(value: T) -> M<T>

    fn map<T1, T2, F>(input: M<T1>, f: F) -> M<T2>
    where F: Fn(T1) -> T2
...and finally the magic bit:

    fn flatten<T>(input: M<M<T>>) -> M<T>
This, in turn, allows defining what you really want:

    fn flatMap<T1, T2, F>(input: M<T1>, f: F) -> M<T2>
    where F: Fn(T1) -> M<T2>
...where the mapping creates an "extra" layer of M<...>, and then we flatten it away immediately.

(There are other rules than ones I listed above, but they tend to be easy to meet.)

Once you have flatMap, you can share one syntax for promises/futures, Rust-style Return and "?", the equivalent for "Option", and a few dozen other patterns.

Unfortunately, to really make this sing, you need to be able to write a type definition which includes all possible "M" types. Which Rust can't do. And it also really helps to be able to pick which version of a function to call based on the expected return type. Which Rust actually can do, but a lot of other low- and mid-level languages can't.

So monads have a very precise definition, and they appear in incomplete forms all over the place in modern languages (especially async/await). But it's hard to write the general version outside of languages like Haskell.

The main reason to know about monads in other languages is that if your design is about 90% of the way to being a monad, you should probably consider including the last 10% as well. JavaScript promises are almost monads, but they have a lot of weird edge cases that would go away if they included the last 10%. Of course, that might not always be possible (like in many Rust examples). But if you fall just barely short of real monads, you should at least know why you do.

(For example, Rust: "We can't have real monads because our trait system can't quite express higher-order types, and because ownership semantics mean our function types are frankly a mess.")

skydhash

> *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.

procaryote

This is why reading a book on design patterns is more than most junior devs can handle without then spending years trying to shove extra complexity into everything to make it use said patterns

Every `new` can be a factory or builder, but usually `new` is the right thing

jimmaswell

I'd wager reading that book and spending years trying to shove the patterns into things is a net benefit iff you learn from it where and why the patterns were appropriate or not. I've never read one of these books, but a good one should give examples of when a pattern is counterproductive.

In a greater sense, in our profession we tend to learn about new hammers by forcing them into the next (work or personal) project that vaguely resembles a nail, and I think that's largely OK if the alternative is stagnating.

heisenbit

Point in case: A singleton holding a factory to create a single instance of a fairly simple class.

null

[deleted]

kybernetikos

I've become convinced that the real problem is probably impossible to get away from.

Ultimately we want a nice set of reusable UI components that can be used in many different situations. We also want a nice set of business logic components that don't have any kind of coupling with the way they get represented.

In order to make this work, we're going to need some code to connect the two, whether it's a 'controller' or a 'view model' or some other piece of code or architecture.

However we choose to achieve this task, it's going to feel ugly. It's necessarily the interface between two entirely different worlds, and it's going to have to delve into the specifics of the different sides. It's not going to be the nice clean reusable code that developers like to write. It's going to be ugly plumbing, coupled code that we are trying to sweep into one part of the codebase so that we can keep the rest of it beautiful.

vbezhenar

Sounds like very simple task to solve.

You have Table component.

You have TableData interface. Table component asks TableData interface for data to show.

You have TableCallback interface. When user interacts with Table, like click or whatever actions are implemented, TableCallback methods are called.

When you want to use Table with your data, you implement TableData and TableCallback for your data. That's about it.

I've seen this approach implemented in most UI frameworks. You might rename TableData to TableModel or whatever, but essentially that's it.

kybernetikos

I'm not saying it's not simple to write, I'm saying it's ugly and contingent and you can't really avoid that. It's exactly this reason that has led to a proliferation of MV* patterns, including the one you describe.

But to try to explain myself more clearly - in the architecture you describe, who is that it is implementing TableData and TableCallback? Is it your beautiful clean business logic classes that have no coupling to their representation - in which case that is weirdly coupled in an ugly way, or is it some other class that acts as the bridge between the two worlds, in which case, that's where your ugly code is living.

jmkni

Yeah exactly, you can come up with all sorts of abstraction layers but your ugly code has to go somewhere eventually

travisgriggs

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.

mpweiher

Yeah, in my experience, just MV is largely just fine.

I like the term "GluePuppy". It absolutely is a crucial part, or parts.

Basically, it defines the architecture of the system, pulls all the objects together and connects them to create a useful system.

It doesn't help that we don't have linguistic support for "glueing things together", we only have procedure calls. So that's one of the issues I am addressing with Objective-S, actual linguistic support for "glue". And yeah, please don't put the rules/distinctions over designing a clean system.

That was a thing I discovered only recently when working with two teams, one Android and one iOS: developers in general, and particularly good architects, want to build these uniformly recursively decomposed modules.

You can't do that with a good OO architecture, because you absolutely need the GluePuppy to tie things together. That one is different from the other modules. If you don't allow for a GluePuppy, but instead insist on uniform modules, you inescapably get procedural decomposition instead of OO decomposition. If you are in an OO language, that means singletons everywhere, because every module needs to know about its dependencies. And that gets you into a world of hurt when you want to do what OO is supposed to be good for, handle variation.

Embrace the GluePuppy! It loves you and wants to make your life simpler.

The "lets-use-the-call-tree-to-mirror-the-view-tree" fashion also has to do with this, IMHO, because our languages only have support for writing down procedures. So if you can get your view-tree expressed by the call-tree, you get to write it down directly in the code, rather than constructing it indirectly, with the view-tree being a hidden side effect.

That is a clear benefit, but the costs are pretty horrendous.

How about we extend our languages so that we can also write down those view hierarchies directly in the code, and at the same time using a format that can also be read/written as data (down LISPers, down)?

neilv

Controller seemed fairly straightforward to me initially, when I was first learning Smalltalk (ParcPlace), and I took my simple understanding on faith.

My programs were simple, so M was data, V was presentations of the data, C was interaction on the M and maybe V.

It only got confusing when I got more experience.

mpweiher

> so M was data,

M is the Model. That means the data and all the things you might ever want to do with the data. So any interaction you might want to do from the view is (ideally) a single message-send to the model.

> V was presentations of the data

And editing the data.

> C was interaction on the M and maybe V.

> It only got confusing when I got more experience.

:-)

travisgriggs

Where “interaction” meant user interaction.

jerf

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.

catlifeonmars

> 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

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.

RossBencina

> 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.

Could you give an example? I've never understood how one could possibly reuse a Controller independently of a View. At a minimum any kind of mouse-based direct manipulation requires the Controller having access to the displayed geometry in order to implement hit testing. E.g. how is a Controller supposed to update the selection range in a text editor without screen-coordinate character extent information from the view, or a drawing editor Controller accessing scene graph geometry for object selection, control handle manipulation, etc.

mpweiher

> I've never understood how one could possibly reuse a Controller independently of a View.

And you're absolutely right!

The problem you're seeing is one of the misunderstandings/misinterpretations of MVC, that the controller is for all interactions/editing. It's not. It's perfectly fine for the View to handle this.

skydhash

> 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)

hurril

I think that a big problem here is the fact that in OOP, everything is an object, i.e.: a class. And if all you have is a hammer, then .... But it is much better to picture the model, controller and the view as emergent. But implementing this in OOP is too challenging because some things in either of those three domains are going to be a process, or a piece of state or a role, etc.

And in implementing some process, what is it? As in: what is its encoding in $language and where does it go?

So you end up with the local stamp collectors in the office and get into an argument of: it is part of the model, so should be in the Model class. "Process, nah, that is totally a controller aspect. It does something." etc.

mmahemoff

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

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

> If your conception of a "model" is perversely a user-facing widget

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

RossBencina

I don't think people called it a "model" but back in Windows VisualBasic/Delphi/C++Builder days the path of least resistance was to set up your GUI in a visual editor by laying out all your widgets in the window. Classically Qt can also be used this way. So you have this UI, you can launch the application and the UI displays and basically works, but none of the buttons do anything. But all the widgets have a great API that you can use to set permissible value ranges, set and query state, etc. And the widgets would fire events when things changed. In other words, the widget contains a model, and implements the Observer design pattern.

If you wanted to implement MVC with a separate application data model you had to do work to set up a separate model, and keep it in sync with the UI. None of this class of old tools provided any built-in assistance for defining models separate from Widgets, except for some support for binding UI to database queries/results. Of course this was separate from the Smalltalk world, where there were frameworks for building up models out of pre-defined model "atoms" such as an observable number model that you could bind to various views.

izackp

Hi, I've been making iOS apps for over 10 years now. I've experimented with many different styles, and even started doing android and web development. One thing I learned is that every abstraction or indirection makes things slightly harder to read and debug. Observers seem to have been a solution to 'callback hell' before async was a thing. However, it's rife with pitfalls.

With Observers:

We have hidden control-flow and lost intent. They subvert the readability of the developer's intention, in some cases they make you lose the callstack, and it has you searching the project on what code modifies a variable which is a lot harder than searching for a function call. Don't get me started on dealing with handling errors and out of order events. And oh man, is it easy to just avoid using encapsulation and creating a good interface/api for your piece of code.

Most of your code isn't re-usuable as you think:

A lot of things are naturally and forever tied together. Your UI is a reflection of _some_ model, The actions it can perform is based on it's current context, and if your UI changes then your business logic and model probably changes as well. This die hard need of separation and modularity only increases the complexity of the code with the majority of times the code not even being reused.

The only case that I've found somewhat reasonable to use observers is the database. What caused the database to change and effect it has is already pretty far removed from each other when a piece of UI needs to reflect the database.

Granted, It's possible to work around some of these issues, but please please I'm tired of debugging why a menu only opens 50% of the time because there is a piece of code several classes away from the context that doesn't fire correctly and looks like if (child.preferred.child.model.somethingElse.isFinished) { child.menu.child.openMenu = true }

lukasb

Any implementation of MVC I've seen the V and the C are so tightly coupled the separation seemed artificial. Skill issue?

andrewflnr

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

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.

mpweiher

> Controller is where your logic is.

That's actually precisely the anti-pattern. Massive View Controller is an example of this.

The Model is where your logic is. Everything that is in any way semantically relevant.

Views handled display and editing (yes, also editing!). Controllers ... well ... I guess you might have a need for them.

dsego

In the server-side web world the controller should ideally only receive http actions and call services or fat models. It should have no business logic, only validation and parsing. In the frontend UI world the controller is bound to UI events and communicates those from the view to the model objects. (1).

(1) https://github.com/madhadron/mvc_for_the_web

js8

I always thought that business logic, expressed in the language of your domain, should be part of the model. The controller is just a translator from the language of keystrokes and mouseclicks into the domain language, and the view is just a translator from the domain language into pieces of text and widgets to display to the user.

to11mtm

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.

mjevans

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?

bitwize

Early Microsoft frameworks (the old Windows 3.x and 9x era MFC) suggested using a "document-view" model wherein the model was a "document" class serviced by a "view" class which handled presentation and UI, serving as both view and controller. There were wizards that would spit out skeletons for these classes and everything.

adityaathalye

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

pixelworm

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.

ednite

I’m still an MVC fan, thanks in no small part to Scott Allen’s teaching (RIP). I agree that if controllers stay tiny and boring, your model stays rich and your app stays portable, testable, and easier to evolve.

If you’re learning MVC, Scott’s OdeToCode/Pluralsight material still nails the fundamentals and the why behind them.

gundmc

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

frollogaston

Last time I cared about MVC was AP Computer Science. Model is fine, but there's no reason for view vs controller. The UIView vs UIViewController thing in ObjC/Swift was one example of the silliness, something for devs to waste time arguing over. React (Native) refreshingly had no such thing. Angular was all about MVC, but they recently slimmed it down.

Also, a while back it was way less common for UIs to have backend services. Nowadays those have taken away most of the "model" side in a lot of apps.