Hacker News new | ask | show | jobs
by delegate 1727 days ago
This is not reinvention of PHP as some are commenting. In fact I think this is extremely cool.

If I understand it correctly, it allows you to achieve reactive data flow in a single page app without any boilerplate.

Meaning - you update the database on the server and all the relevant UI(s) will automatically receive the updated data and re-render only the parts of the UI that display that data.

This would require a ton of PHP and Javascript dealing with networking, websockets, routing, serializing data and so on.

Haven't tried it yet, but very curious to see if it works.

7 comments

The problem with this type of system in my experience is that it’s great until you hit a bug, and then you realize you have no idea what’s going on under all the automagical stuff and you go crazy
How is this different from any other framework? Try fixing a React or Rails bug.

At least their system is only 2k LOC, which will presumably be well documented.

At first glance, this appears to be much more complex. React is a relatively simple DOM diffing library. Rails is a closer comparison, especially with whatever their live-view implementation is. This appears to be doing a lot more than React, at least, including network communication, and database change event propagation. The odds seem much higher that stuff will go wrong, especially under load, and be pretty difficult to reason about.
> At first glance, this appears to be much more complex. React is a relatively simple DOM diffing library.

Their implementation is 2k lines of code. The React repo has 350k lines of code. The Rails repo has 336k lines of code (both of those according to tokei). Of course this includes tests, lots of other stuff, etc. But still, that's two orders of magnitude.

Note that react has a monorepo with a lot of tangentially related packages, such as devtools and alternative renders.
That's true, it's hard to make a fair comparaison between the two.
preact is much simpler than react (~3KB), and whats weird, it's also faster

BTW: code is very easy to read/follow https://github.com/preactjs/preact/

LoC != Complexity. React has one job, and it does it really well, part of that 350k lines of code is a LOT of tests. Just because it has those tests doesn’t mean it’s “much more complex”.

My two cents :)

After a naive removal of the tests (every folder and files that contains tests was deleted), React still has 190k lines of code.

> React has one job, and it does it really well

I'm not sure I agree. It's hard to compare without a minimal copy of React to see how small it can get, but I'm guessing it could be an order of magnitude smaller. For example, React supports different ways of doing things (class components, function compenents, hooks). Backwards compatibility is a great thing, but it's not the same as "having one job and doing it well", it's a different tradeoff. The React team has lots of people that depends on their code, and thus choose stability over being small and nimble. I think that's a responsible choice. But this leads to complexity, and losing the "having one job and doing it well".

As a more general remark, there's a cycle in software. React starts small and nimble, especially compared to the "jQuery behemots of the past". It gets really popular. So people start depending on it. So it grows, and grows, and grows. And then someone else comes out, maybe Photon, maybe Svelte, maybe something else. Compared to React, it's small and nimble. Maybe in 10 years, Photon will be really popular, will be 200k lines of code, and someone will build an alternative because it's too big and complex.

Edit: as a more meta-remark: My message is way longer than yours because I was trying to steelman my argument, and you didn't do the same with yours. Considering you made a small message "defending" React and I did a long one "defending" Photon, I think we already agree about the tradeoffs involved here.

Good point I checked and it's nowhere near 350k LOC. React is a monorepo here are some numbers for the main packages, excluding tests:

react = 3k

react-dom = 15k

It absolutely has a strong correlation with complexity.
Clojure tends to be a bit more terse than other languages. 2K of Clojure is a lot of code. Especially if macros get involved. As for the comparisons to React elsewhere; I wonder how much of that is the result of React being battle tested for a long time and expanded, would this still be so short if Facebook was written in it?

I also wouldn’t presume good documentation as a general rule. That’s something that must be proven, not presumed.

I‘d still rather read 2k loc in _any_ language, and undocumented, than 350k loc, perfectly documented.
Sure. But I’d question two things:

1) How often do you actually need to read your framework. I used rails for years and read probably less than 2KLOC out of it, ditto with Java and Spring. Good documentation beats out small code bases.

2) How much of the size difference between these two is down to age and uses? Is React so big because it’s unfocused or poorly written, or is that a consequence of it being used by so many people and projects? If it’s the latter, shouldn’t we expect that this project will end up growing if it got popular, eroding the benefit of its small size.?

> How often do you actually need to read your framework.

This brings us full circle to the question that started this conversation branch:

> it’s great until you hit a bug, and then you realize you have no idea what’s going on under all the automagical stuff

With React and Rails, "hitting a bug" is apparently rare. Maybe we should wait before assuming it will be any different with this Reactive Clojure framework.

True With any system
That's true with any system you haven't sufficiently studied.
So yes in a way, but here we're talking about something that synchronises state between a client and DB over http. The possibilities of weird edge cases seem endless :)
So more like Liveview for Phoenix / Elixir is what this kind of sounds like to me, and less so back-end mainly language like PHP.
> Meaning - you update the database on the server and all the relevant UI(s) will automatically receive the updated data and re-render only the parts of the UI that display that data.

> This would require a ton of PHP and Javascript dealing with networking, websockets, routing, serializing data and so on.

I don’t know how it was implemented, but Quora had this back in its early days (~2012). There was some mechanism that "remembered" which table lines were used to generate which UI component, and when that data changed you had a live-reload in your browser. That was really cool to see at the time; I’d love to have more background on its implementation.

> you update the database on the server and all the relevant UI(s) will automatically receive the updated data and re-render only the parts of the UI that display that data.

I really don't like that idea. It seems to me inefficient and error prone.

Let's say you're updating a database. You add some records to one table, and you update some records to some other tables.

If the program automagically updates the UI, then on the first change it will attempt to update the UI (causing lots of processing) , then on the 2nd change to the database it'll update the UI again, and on and on for each change.

Wouldn't it be better to make all your changes to the database then only after that run an updatePage() funiction that updates the web page?

From submission:

"Sounds really slow and chatty right? Actually, NO!

This is not RPC or ORM. The key is to make the language, compiler and runtime in charge of the network, like the JVM owns the heap. Idealized client/server network IO (better than could ever be coded by hand) is an explicit design goal.

How does it work? Functional programming:

- `photon/defn` is a macro that compiles Clojure syntax (s-expressions) to a dataflow signal graph (DAG). - The DAG is lifted and compiled into Missionary reactive signals. Missionary manages reactive execution (incremental maintenance such that a small adjustment to inputs results in a small adjustment to outputs)."

nothing forbids the system to give mechanisms defining rapid sequences of changes, kinda like debounce in js
I think the main risk for this kind of framework is that you spend as much time ironing out these kinds of "edge cases" (debounce, transition states, error states, transactions, authorization, url bar state, scroll bar position, paging, efficient re-renders, etc. etc.), which in practice are crucial to most non-trivial software, as you would have just writing the usual boilerplate and retaining fine-grained control.

It's great that people are innovating and creating new abstractions, and I'm sure there are apps where the tradeoff is worth it (internal CRUD-focused enterprise stuff comes to mind), but my knee-jerk reaction for a large app is that it will make easy things easier and hard things much harder.

I appreciate and have created software that needed to be complex with the associated complex underpinning.

I also have long been looking for a framework that makes easy things easier.

Yes i agree
This is where I'm at with it. "Develop apps like you do now, with a centralized app db, but now the app db (in the browser, most likely a giant Map) is an actual database with a sophisticated query language, an upgrade!"
In this sense it's same as what microsoft is trying to do with Blazor - except they are skipping whole javascript crap and compile to wasm.
Which sounds great until you experience the loading times. Last time I tried it out, the loading times for all the DLLs that a typical application requires was pretty bad. But once it loaded, things were snappy.
I just tried this Blazor demo and its really slow on mobile, even after the noticeable load screen https://www.blazorfluentui.net/calendarPage

Clicking on multiple dates takes time to transition between the two.

> Imagine a programming language runtime whose runtime state (i.e. lexical scope) is partially broadcast over network as it happens, kind of like a remote debugger.

This sounds absolutely terrifying from a security perspective...

What's to stop a malicious client from broadcasting code that deletes my entire database?

> runtime state

> code

Some overlap, but these are essentially two different things.

> What's to stop a malicious client from broadcasting code that deletes my entire database?

Your backend.

Deleting a database is probably a bad example, but my point still stands: even if you are not trasferring code back and forth, runtime state is enough to be a problem.

What if your runtime state includes an `is_authorized` flag or similar? How do you guarantee that this state remains server-side when the entire language conflates server/client side code?

For this to work, there needs to be language-level support for distinguishing untrusted inputs from trusted ones, or else it's a recipe for disaster.

If the compiler is separating server-side code from client-side code, then it's also separating out symbol bindings as well. So it knows where symbols are bound, and where they are referenced, and it can use this to limit information flow.

For example:

    (client
      (let [token (get-client-token)]
        (server
          (let [username (get-username db token)]
            (client
              (dom/p "Hello " username))))))
The compiler can infer that token is defined on the client, then sent to the server, which in turn defines username and sends that back to the client.

It's the same system you'd use in normal server/client architecture, just inlined.

Compile-time macros do indeed seem to be what provides the necessary client/server separation for sensitive data.

That does mean you are trusting the library to implement these macros correctly. In that sense, data security for these symbol bindings is a responsibility of the library, and therefore a risk, as is called out lower on the page.

Once the library is complete however, and a larger part of the community has been able to inspect it, this type of bug should not be an issue. It's one of the most fundamental concerns of the library.

any sort of networking sounds terrifying from a security perspective...

Unfortunately (or fortunately) it's also a corner-stone of computing in general