Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I am really curious to hear about specific examples of some of these points. Specifically:

> The abstraction leaks and when it does, it requires a good mental model of Svelte's magic.

Maybe because I have familiarized myself with how Svelte works I haven't noticed anything like that.

> Things that are easy in React at runtime turn out to be surprisingly difficult in Svelte

I suspect this is from trying to use React patterns in Svelte, which I've seen quite a lot in people asking questions on Reddit. But I'm sure there are some things like that, could you give an example?

> Two-way data binding is a constant source of bugs

Again, very curious to see an example of this.

> It's not possible to write a one-line function component or similar

What was your use case here? I haven't found myself wanting to do that anywhere.



Is it surprising that two-way data binding is a source of bugs? We learned that lesson from Angular, and it influenced React’s preference for one-way dataflow.


2-way data binding is still a useful pattern with discipline, and still also common in React (using event handlers).


Any error-prone pattern can remain useful with enough discipline, but we've learned time and time again that relying solely on discipline to cover for error-prone patterns doesn't scale.


Define "we". :) I understand this sentiment though, and I also understand designing a flexible system with zero footguns is nigh impossible. My point however was that two-way databinding is not rare in React, and there are other potential footguns to be had in idiomatic React anyway (hooks, React Context).


I realized maybe we have different definitions of 2-way data-binding also haha...

My objection is towards the Angular 1 style patterns where by passing some local component state to some children, you also implicitly allow those children to update it by binding it to some prop or by mutating it directly. This means the moment you need to share some piece of state, you can no longer reason about the state of your component in isolation nor control the ways in which it can be updated. This is at the core of what makes this approach so error prone IME.

In React, state is passed from parent to children as read-only values for which direct modification has no effect (this is the "unidirectional data flow"). The only way for a child component to update the state of a parent component is for the parent to explicitly pass down a function that exposes that functionality as part of its explicit API contract with its children.

Even in the worst case where we just naively pass down state updater functions directly (this is the case that's most similar to Angular-style 2-way-binding, which might be what you're referring to), this still results in state updates that are far easier to trace and debug as you can simply follow the function reference down to the call sites (instead of having follow all use cases of the state you passed down and trying to figure out which use cases bind or mutate). In the best case, it allows for components to offer only the minimum possible API surface to children by further restricting the set of possible state transitions (i.e. passing down openModal, closeModal functions, instead of the setIsModalOpen state updater function directly), and you can look at the parent component in isolation and confidently assert that no other possible state updates can possibly occur.

FWIW I don't have much experience with Svelte, so can't speak for which approach it's more similar to. But when I hear 2-way data binding the Angular style is the first thing that pops up in my mind from all the PTSD, so if Svelte's approach is more similar to the React style then I have nothing to object to.


It's never two-way in react. You're always in charge of updating the state in the event handler, which means you know where the update came from


Not to argue semantics, but that pattern is still called two-way databinding in my neck of the woods. In this deprecated page from the official docs, two-way databinding is defined as:

> Two-way binding — implicitly enforcing that some value in the DOM is always consistent with some React state — is concise and supports a wide variety of applications.

[1] https://reactjs.org/docs/two-way-binding-helpers.html


Well, that mixin has never been the standard way and has been deprecated for years (and for good reasons)


The mixin is irrelevant to the point I was making. :) The point is that even the official React docs defines two-way binding as I describe it.


What do you mean by two-way and one-way exactly? (Asking it because web sometimes has a different history for terms.)


Not the GP, but here's an example of abstraction leaking straight from their intro tutorial:

> A simple rule of thumb: the name of the updated variable must appear on the left hand side of the assignment. For example this...

  const foo = obj.foo;
  foo.bar = 'baz';
> ...won't trigger reactivity on obj.foo.bar, unless you follow it up with obj = obj.

This looks like a huge footgun to me, and it's not even an exotic usecase. It's in the very first page talking about reactivity in the docs.


It's not an abstraction leaking, it's an important point to understand about mutating objects.

You are allowed to use `const` to declare an object and then modify its properties, because modifying properties is not the same as reassigning.

You're absolutely right that it's something that might catch you out, but not understanding the difference between reassigning and mutating is likely to lead to other bugs and falling into other traps in future.

(by 'it's not an abstraction leaking', I mean 'the abstraction's behaviour is consistent with the behaviour of the language' - I guess it's a subjective opinion that it's not leaking)


Other reactive frameworks like MobX will react when you only mutate objects. APIs like the useState hook at least make it obvious that you need to replace the whole object. Svelte on the other hand presents this "it's cool man, just change your plain JS state like normal!" paradigm, and it would be very reasonable without being told otherwise to assume that this applies to mutating objects as well. But then it doesn't.

If re-assignment of the whole object is what I have to do anyway, I'd much rather just be given an API that's slightly clunkier but makes that fact obvious. Otherwise the behavior will be surprising and error-prone to those not closely familiar with it yet.


Another way of stating it is that Svelte doesn't attempt to plug any of the leaky abstractions that already existed in JavaScript.

JavaScript is riddled with huge footguns that aren't even exotic use cases, and if you remove or paper over them, then it's not JavaScript any more.

While React's biggest most obvious leaky abstraction is that React isn't actually reactive.

Neither is Svelte, but at least Svelte doesn't have the audacity to falsly CLAIM it's reactive in ITS OWN NAME, like React does!

I do give Svelte credit for being quite self-referentially svelte, though! And that's something great that React definitely isn't.

How React isn't reactive, and why you shouldn't care

https://dev.to/this-is-learning/how-react-isn-t-reactive-and...

>[...] Is React not reactive?

>Well, let's see about that. React components are driven off state, and setState calls are sort of like data events. And React's Hooks and JSX are basically declarative. So what's the issue here?

>Well actually very little. There is only one key difference, React decouples the data events from component updates. In the middle, it has a scheduler. You may setState a dozen times but React takes notice of which components have been scheduled to update and doesn't bother doing so until it is ready.

>But all of this is a type of buffering. Not only is the queue filled by the state update event, but the scheduling of processing that queue is as well. React isn't sitting there with some ever-present polling mechanism to poll for changes. The same events drive the whole system.

>So is React not reactive? Only if you view reactivity as a push-only mechanism. Sure React's scheduling generally doesn't play as nice with push-based reactive systems as some would want but that is hardly evidence. It seems to pass the general criteria. But it is definitely not typical reactivity. Know what else isn't? Svelte.

Using Svelte finally gets me back into the joyous productive groove that I used to enjoy so much when developing with OpenLaszlo, using prototypical "instance first" declarative constraint based programming (beyond what the kids call "reactive" these days), but with standard unbastardized JavaScript and HTML instead of Flash and XML.

There's a lot to learn from past systems that predated React and Svelte, including OpenLaszlo, Garnet and NeWS, which I've used and love to explain:

https://en.wikipedia.org/wiki/OpenLaszlo

>OpenLaszlo is a discontinued open-source platform for the development and delivery of rich web applications. It is released under the Open Source Initiative certified Common Public License (CPL).

https://news.ycombinator.com/item?id=22025026

>Oliver Steele describes "Instance First Development", which the language he designed, OpenLaszlo, supported through the "Instance Substitution Principle". I've written about it here before, and here are some links and excerpts.

https://news.ycombinator.com/item?id=14418108

>In the right context, prototypes can enable Instance-First Development, which is a very powerful technique that allows you to quickly and iteratively develop working code, while delaying and avoiding abstraction until it's actually needed, when the abstraction requirements are better understood and informed from experience with working code.

>That approach results in fewer unnecessary and more useful abstractions, because they follow the contours and requirements of the actual working code, instead of trying to predict and dictate and over-engineer it before it even works.

>Instance-First Development works well for user interface programming, because so many buttons and widgets and control panels are one-off specialized objects, each with their own small snippets of special purpose code, methods, constraints, bindings and event handlers, so it's not necessary to make separate (and myriad) trivial classes for each one.

>Oliver Steele describes Instance-First Development as supported by OpenLaszlo here:

>Instance-First Development

http://blog.osteele.com/2004/03/classes-and-prototypes/

>LZX is a prototype-based language: any attribute that can be attached to a class definition, can be attached to an instance of that class instead. This is handy in UI programming, where there are a number of objects with one-off behaviors. It’s also handy in prototyping and incremental program development, where it creates the possibility for a novel kind of refactoring.

https://news.ycombinator.com/item?id=21841054

>[...] The mantle of constraint based programming (but not Instance First Development) has been recently taken up by "Reactive Programming" craze (which is great, but would be better with a more homoiconic language that supported Instance First Development and the Instance Substitution Principle, which are different but complementary features with a lot of synergy). The term "Reactive Programming" describes a popular old idea: what spreadsheets had been doing for decades. [...]

https://news.ycombinator.com/item?id=7756215

>Oliver Steele (one of the architects of OpenLaszlo, and a great Lisp programmer) describes how OpenLaszlo supports "instance first development" and "rethinking MVC":

http://osteele.com/archives/2004/03/classes-and-prototypes

http://osteele.com/archives/2003/08/rethinking-mvc

>[...] I've used OpenLaszlo a lot, and I will testify that the "instance first" technique that Oliver describes is great fun, works very well, and it's perfect for the kind of exploratory / productizing programming I like to do. (Like tacking a sailboat against the wind, first exploring by creating instances, then refactoring into reusable building block classes, then exploring further with those...)

>OpenLaszlo's declarative syntax, prototype based object system, xml data binding and constraints support that directly and make it easy.

>OpenLaszlo's declarative syntax and compiler directly support instance first development (with a prototype based object system) and constraints (built on top of events and delegates -- the compiler parses the constraint expressions and automatically wires up dependences), in a way that is hard to express elegantly in less dynamic, reflective languages. (Of course it was straightforward for Garnet to do with Common Lisp macros!)

What is OpenLaszlo, and what's it good for?

https://web.archive.org/web/20080313080025/http://www.donhop...

>OpenLaszlo is an open source platform for developing user friendly web based applications, which work identically across all popular browsers and platforms (Windows, Mac, Linux, IE, Firefox, Safari, etc). It's ideal for presenting and editing raw XML data generated by PHP and other web services.

>OpenLaszlo supports a rich graphics model with scalable vectors, bitmaps, movies, animation, transparency, fonts, audio, streaming media, reusable components, user interface widgets, control panels, property sheets, keyboard navigation, browser "back button" navigation, as well as advanced WYSIWYG text and graphical editing tools. In other words, OpenLaszlo is the velvet glove for the iron fist of PHP. What can OpenLaszlo do?

Constraints and Prototypes in Garnet and Laszlo

https://web.archive.org/web/20080224054750/http://www.donhop...

>Garnet is an advanced user interface development environment written in Common Lisp, developed by Brad Meyers (the author of the article). I worked for Brad on the Garnet project at the CMU CS department back in 1992-3.

>One thing I like about Brad Meyers is that he's a strong programmer, as well as an excellent researcher, so he had a first-hand understanding of the real-world issues involved in programming languages and user interface architecture, unlike many academics who talk a lot of theory but never get their hands dirty. Brad Meyers understands where the rubber hits the road, and how important it is to have good tires.

>At the time I worked on it, Garnet didn't have pretty graphics like Flash, but the underlying programming system had some advanced features that are sorely lacking from most modern user interface development environments.

>Laszlo is a modern open source GUI programming system, with many of Garnet's advanced "natural programming" features like prototypes and constraints. Laszlo currently uses Flash as its virtual machine, but it's a much higher level way to program dynamic interactive web based applications, without using the proprietary Flash authoring tool.

>Garnet had a true prototype based OOP system (somewhat like Self), which is great for gui programming, because guis have so many objects that look and behave like each other except for a few little customizations (like the layout, graphical style, data source and call-back behavior).

>Garnet also had an automatic constraint system, which enabled you to simply define any attribute as a formula that depend on other attributes, without needing to worry about how and when the values were calculated. Garnet's constraint system automatically figured out the dependences of each formula, and automatically and efficiently recalculated and cached any values that needed to be updated, but only when necessary.

>With constraints, you can make a button inside a window, and define its left edge to be ((parent.width - self.width) / 2), and it will automatically remain horizontally centered in the window from then on, without you (the programmer) having to worry about what to do when the parent window's size changes.

>Without constraints, you have to manually write all the code that changes the button position whenever the window size changes, which results in code scattered all over the place in different classes and handlers and intermediate objects.

>Constraints are much easier to use and more general purpose than resize handlers, springs and struts, complex MVC updating schemes, and other Rube Goldberg devices.

>Constraints are especially useful for user interface programming, because they save you from having to write lots of annoying boiler plate and error prone code for handling updates (registering, chasing down dependencies, detecting changes, notifying updates, all happens automatically).

>Constraints make GUI programming much easier, but they're also useful anywhere in your program where one value is defined in terms of other values that might change at any time.

>Once you've tasted a programming language with constraints, you will not want to go back. Programming without constraints is like writing in machine language: error prone, low level, tedious, inefficient and mind numbing.

>Constraints are like structured programming for variables: In the same way that it's better to use loops and conditionals instead of gotos, it's also better to use declarative programming that says what you mean, instead of imperative peeks and pokes and side effects.

>Constraints let you write easy to read code, and concentrate on the interesting high level stuff that matters. You can go back later and change the layout of a complex GUI, without rewriting lots of fragile layout and event hanling code. Look at any MFC program to see how bad it can get without constraints.

>Constraints are natural and close to the way you think, because they let you declare a variable and the formula that defines its value in one place, instead of scattered all around the code. They off-load the tedious task of tracking down and maintaining all the dependencies from the programmer to the computer, which is much better at that kind of stuff.

>Garbage collection is like constraints: the computer can do a much better job than the human at performing the task perfectly, so spending some cpu time on automatic garbage collection and constraint maintenance is well worth the significant increase in programmer productivity and software reliability.

>Garnet had a prototype based object system. It was implemented in Lisp with a system called KR (Knowledge Representation, classic AI "frames" with slots and inheritance). KR was extended with an automatic constraint system that parsed the formula expressions (written in Lisp macros), figured out the dependences, wired up and maintained the dependency graph.

>An expression like "((parent.width - self.width) / 2)" would depend on self's width slot, self's parent slot, and parent's width slot. If any of them changed, then that formula would be automatically invalidated, and only recalculated on demand when it (or something that depended on it) is required.

>The cool thing was that you can make a prototype object, like a button, which has sub-structures like a label, border, drop shadow, etc. The sub-structures can be constrained to the button's dimensions, the label is centered in the border, and the drop shadow floats below and to the right, so the button's layout is automatically updated when it moves or resizes.

>The text color and border fill can depend on the button's "hilight" variable, so they automatically switch between bright and dark when you press the button (the input handler just toggles the "highlight" variable, and the graphics that depend on it are automatically updated).

>Now that you've composed and constrained a button to look and feel how you want, you can use it as a prototype to make other similar customizable buttons instances. Each instance can itself override the prototype's graphical properties, label text, action, etc.

>Instances of a prototype all magically inherit (instances of) the sub-structure of the prototype! It all just works the way you'd expect it to (with a lot of plumbing going on automatically behind the scenes). There's no need to make a separate class for each different style of button or action - prototypes let you customize any instance itself!

>Like Garnet, Laszlo is an advanced open source user interface development environment that supports prototype based OOP with constraints.

>Unlike Garnet, Laszlo deeply integrates recent trendy technologies like XML, JavaScript, Flash, data binding, networking, XML/RPC, SOAP, ReST, Java and Tomcat.

>Laszlo has a class/prototype based object system, and it (currently) uses the JavaScript runtime in Flash as its virtual machine. But it's more than just another way to program Flash.

>Unlike raw Flash, The Laszlo language is easy to learn and Laszlo programs are easy to read and write thanks to prototypes, constraints, declarative programming, and instance-first development.

AJAX is old NeWS, Laszlo is non-toxic AJAX

https://web.archive.org/web/20080227082801/http://www.donhop...

>AJAX is a new buzzword for old (but not bad) ideas.

>Don't take this as anti-AJAX. That kind of architecture is great, but it's the notion that the new AJAX buzzword describes new ideas that annoys me.

>Of course Microsoft has been supporting it since the 90's, but it goes back a lot further than that.

>For a long time, I've been evangelizing and more importantly implementing interactive applications that run efficiently over thin wire (dial-up modems, ISDN, early internet before it was fast, etc), which are locally interactive and efficient because there's a programming language on each side of the connection that implements custom application specific protocols and provides immediate feedback without requiring network round trips.

>Before he made Java, James Gosling wrote the NeWS Window System. [...]

https://en.wikipedia.org/wiki/NeWS

>NeWS (Network extensible Window System) is a discontinued windowing system developed by Sun Microsystems in the mid-1980s. Originally known as "SunDew", its primary authors were James Gosling and David S. H. Rosenthal. The NeWS interpreter was based on PostScript (as was the later Display PostScript, although the two projects were otherwise unrelated) extending it to allow interaction and multiple "contexts" to support windows. Like PostScript, NeWS could be used as a complete programming language, but unlike PostScript, NeWS could be used to make complete interactive programs with mouse support and a GUI.

HN discussion of "Sun's NeWS was a mistake, as are all toolkit-in-server windowing systems (2013) (utoronto.ca)":

https://news.ycombinator.com/item?id=22455722

>agumonkey>I've always been curious about NeWS but the web is quite short of demos about it (not helped by newspapers called Sun either). Do you know sites with videos about it ?

>Thanks for asking! ;) I've put up some old demos on youtube, and made illustrated transcriptions of some, and written some papers and articles. Sorry the compression is so terrible on some of the videos. Here are some links:

https://news.ycombinator.com/item?id=22456831




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: