4 ms·
> functional programming is superior for representing state in user interfaces It's always going to be slower than using something imperative. Trying to proces
by rudedogg 2mo ago
> functional programming is superior for representing state in user interfaces
It's always going to be slower than using something imperative. Trying to process the entire world's state for the sake of purity can feel elegant but it isn't free. And the complexity that gets added to make things performant is worse than just accepting that UIs are going to require you to jump around the tree and modify state.
Every time I go through the trouble of understanding the latest web technique (React, Elm, Signals (the newest solution), etc.) to deal with state management and the DOM, I end up walking away disappointed. There's nothing new in them that you can use to improve what we've been doing for ages in native GUI toolkits.
And to jump back to the original topic, yes, Cocoa was pretty decent, and SwiftUI while nice in many ways tries to Reactify native macOS development and made it worse. And it made Swift incredibly more complex and worse in hindsight.
- kodebach 2mo agoThe goal of the reactive/declarative approach was never to be more performant than imperative code. The goal is to more easily build UI that is performant enough and functions correctly. With imperative UI code it is incredibly easy to forget an edge case in your update logic.
- mpweiher 2mo agoNot if you actually do MVC, so solved around 50 years ago. 1. The UI tells the model to change. 2. The model does the change and possible related changes. 3. The model notifies the UI that something has changed. 4. The UI updates itself from the model. Alas almost nobody does MVC, despite calling what they do MVC.
- LoganDark 2mo agoAre you saying the UI always updates its entire self whenever anything changes in the model?
- mpweiher 2mo agoYes and no. Conceptually, the UI re-renders itself completely in order to always be an accurate reflection of the model. That is the #1 job of the view: be an accurate reflection of the model. And re-rendering itself completely is a safe way to implement that requirement. However, the UI can also look at the model in more detail and figure out what parts need to change, as long as the effect is the same as re-rendering everything. And the model can tell the view that specific subparts of the model have changed to make that job easier for the view. But if it can't figure out the details, the fallback is to re-render the entire view from the model. But not to recreate the view. The view sticks around. One way of doing this optimization is "damage rects" like Cocoa does. Another are the polymorphic identifiers used in the update queue of Blackbird.
- jay_kyburz 2mo agoImmediate mode UI ftw.
- asa400 2mo agoFunny, this almost reads like a description of how Elm works.
- mpweiher 2mo agoYep, to anybody who actually knows MVC, the whole Elm/React/SwiftUI stuff is funny. "We solved the problems of MVC by properly applying MVC". https://blog.metaobject.com/2017/03/concept-shadowing-and-capture-in-mvc.html https://blog.metaobject.com/2017/03/concept-shadowing-and-ca...
- wk_end 2mo agoI see an M and a V in this description, but no C. Is the UI updating itself automatic or manual? Because if it’s manual, that’s precisely the error-prone part that you’re saying this approach somehow solves - you’ve done the “How to Draw an Owl” meme. If it’s automatic, that doesn’t seem especially different from the React/Redux/Elm/SwiftUI approach (as a sibling points out).
- mpweiher 2mo agoYeah, M-V-C are all roles, not concrete objects. The C mediates between the input devices and the model, but in practice views can and often do fulfill that role as well. Cocoa views, for example, also fulfill the C role. Different formulations of M-V-C have the C deal with more complex interactions, with sequences of interactive prompts like wizards. The update is essentially automatic, and yes: MVC already solved the "problem with MVC" React/Redux/Elm/SwiftUI claim to solve. In 1979.
- jay_kyburz 2mo agoI like my Controller to be responsible for all the "business logic" so that its all in one place. It's the important part. The View layer is always fairly verbose and full of fluff. Especially if you have a lot of animation and formatting type code.
- mpweiher 2mo ago> I like my Controller to be responsible for all the "business logic" so that its all in one place. Business logic is supposed to go in the model. All of it. Because it's the important part. Controller these days can be largely empty. "MODELS Models represent knowledge. A model could be a single object (rather uninteresting), or it could be some structure of objects. There should be a one-to-one correspondence between the model and its parts on the one hand, and the represented world as perceived by the owner of the model on the other hand. The nodes of a model should therefore represent an identifiable part of the problem. The nodes of a model should all be on the same problem level, it is confusing and considered bad form to mix problem-oriented nodes (e.g. calendar appointments) with implementation details (e.g. paragraphs)." https://web.archive.org/web/20090424042645/http://heim.ifi.uio.no/~trygver/1979/mvc-2/1979-12-MVC.pdf https://web.archive.org/web/20090424042645/http://heim.ifi.u...
- kikimora 2mo agoMVC is not bad, but it is not a silver bullet. Calling MVC an ultimate solution to UI is oversimplification. Just looking at the steps you listed I can ask: How do you collect all notifications on step 2 to fire them on step 3 such that UI does not re-render itself too much? E.g. updating a title of each item in a list of 100 items should not trigger 100 renders. Or 100 layout calculations (which I think is harder to avoid). How do you deal with situations where on step 4 UI triggers an event that your model happens to listen and the cycle repeats while killing performance? Because you rely on events how do you avoid “event hell”? That is, a situation when an event handler triggers a change that triggers another event handler that triggers a change and so on. Sometimes it is scrolling or typing, sometimes it is parts of the model subscribed to each other bubbling events to UI.
- mpweiher 2mo agoI never claimed MVC is a silver bullet. Just that it solves "... incredibly easy to forget an edge case in your update logic." > UI does not re-render itself too much? Glad you asked! In my Blackbird reference architecture (which is an instance of MVC), I use a coalescing queue to capture the updates. The coalescing is two-level: first, simple duplicates are weeded out. Second, if the update queue gets very full, it becomes coarser-grained, and weeds out duplicates based on that coarser grain. This has multiple steps of grain up to "just re-render the whole UI". Worked like magic in Wunderlist. Except it wasn't magic at all and very simple, inspectable and tractable. > step 4 UI triggers an event that your model happens to listen That's not allowed in MVC. > Because you rely on events how do you avoid “event hell”? I don't "rely" on events and there is no "event hell". Events are only used in the M→V communication part and there are no subsequent triggers, because the only event is "the model has changed", with an optional payload specifying which part of the model. Important: it must not contain the data that changed, this the view has to fetch from the model once it processes the update event. Since the only event used is "the model changed", the view cannot ever be a source of those events, so no "event hell".
- kikimora 2mo ago>The coalescing is two-level: first, simple duplicates are weeded out. Second, if the update queue gets very full, it becomes coarser-grained, and weeds out duplicates based on that coarser grain This is not about duplicates. For example, sync updates 100 items in a list changing their titles. Items are bound to a list in the UI. Thus, 100 unique title update events triggered. >Events are only used in the M→V communication I don’t understand. Button clicked -> model change -> view update -> new event triggered -> model or view updated again … This is not something one would code on purpose, but often an attempt to create relationships between view. Like a custom layout code. Might not include model at all, just views being updated in an event handler trigger more events and more updates to views.
- ardit33 2mo agoDude, you didn't describe MVC at all, but MMVC. MVC, the controller is the intermediary between the services/data models, and the views. That still one of the best / simplest way to build large apps. MMVC is just a variation of it, with the models being able to communicate state to views and bypass controller if needed. MVC, is still one of those 'fundemental as simple as it gets, and it gets the job done' patterns.
- mpweiher 2mo agoDude, what I describe is exactly MVC. Your interpretation is a common misconception, for example promulgated by Apple. It is not MVC. https://blog.metaobject.com/2015/04/model-widget-controller-mwc-aka-apple.html https://blog.metaobject.com/2015/04/model-widget-controller-... https://blog.metaobject.com/2017/03/concept-shadowing-and-capture-in-mvc.html https://blog.metaobject.com/2017/03/concept-shadowing-and-ca... "A view is attached to its model (or model part) and gets the data necessary for the presentation from the model by asking questions. " https://web.archive.org/web/20090424042645/http://heim.ifi.uio.no/~trygver/1979/mvc-2/1979-12-MVC.pdf https://web.archive.org/web/20090424042645/http://heim.ifi.u...