Two Approaches to Decoupling
htmx.org
htmx.org
If you buy into the philosophy that the UI is a deterministic function of server state and ephemeral view state (ui = f(state, viewstate)), then the core question is medium.
With browser, embracing HTML is the only sane choice for business. As such, the function at hand needs to convert those two state objects into a blob of HTML. This is the classic HTML template problem.
However, if you treat the state(s) as streams, then you'll be where I am at in building a differential HTML engine. I'm calling this first (big) version: RxHTML ( https://book.adama-platform.com/rxhtml/ref.html ) and it uses my modified JSON delta format ( https://book.adama-platform.com/reference/deltas.html ).
The spiritual design question is what minimal things does HTML need with reactive data binding.
It's pretty awesome to be able to debug a user experience by having 4 views up at once, and then see a real-time update on all 4 views at once.
The tech at this time is beta quality, but I'm working through this as I build a real SaaS for everyday people. I'm having a bunch of fun especially as tailwind dramatically simplifies the styling.
It assumes always-online, synchronous operation.
How do you in your model implement an auto-completion list? Do you allow it to re-generate not on each keystroke?
Maybe it's just an unfortunate wording, but "gossip" has a specific meaning in P2P/distributed systems and I can't see how it fits in with what you've written so far.
But, having spent the better part of an hour trying to understand your proposal, I have to say that it isn't something that solves a proportionally sized problem.
Modified html with added tags for conditional processing has been done to death. I've done it. At least five former colleagues of mine has done it. At the end of it you'll come to the same conclusion as we, and everyone else, did and abandon it.
Secondly, this seems like a very overengineered solution, and it's not clear what the problem is. Your project will end up trying to be all things to all people because no one can tell at a glance what problem it should be used for.
If you're targeting a problem at a higher level then there's very little need to invent new low-level components; the existing ones should mostly be fine.
To be honest, if the browser allowed s-expressions and specified the evaluation of them, most current frameworks (and JSON itself) would be made redundant.
For conditional processing that you and your colleagues did, was it within the browser? I'm doing this as simple step such that I turn a giant "HTML forest" into lean javascript and DOM binding. It's working well for me, so I wonder what the gap is?
Personally, my stack is underengineering since I'm combining the roles of web server, database, messaging stack, queues, caches, load balancer, workflow into one cohesive platform. My dry run video: https://www.youtube.com/watch?v=bWYgChA_aYA&feature=youtu.be goes into more details.
Yes - it's the most common way to do it (the script language that comes with htmx runs in the browser too).
> It's working well for me, so I wonder what the gap is?
It usually turns out that it's less work simply using JS in the browser than remembering the new language. I'm not saying that your effort would have the same result, but it's the result I've seen in the past for this sort of thing.
> Personally, my stack is underengineering since I'm combining the roles of web server, database, messaging stack, queues, caches, load balancer, workflow into one cohesive platform.
That's what I meant by over-engineered - too much is included in the project, much of which won't be used by most intended users. I accept that maybe "over-engineered" is the wrong word.
Tell me, what's the problem statement you had that prompted this development effort? What problem where you trying to solve when you started this?
Using websockets made building the game easier, but now there is exceptionally complex state within the process (await/async). Generally speaking, the cloud is unforgiving place to hold state within a process.
I can speak deeply about streams at scale ( https://dl.acm.org/doi/10.1145/3477132.3483572 ).
Adama emerged as a tool to help define a "transactional document schema" which I could use to emit deltas to a logger (like Kafka), and once I added a notion of "privacy polices with code"... the potential exploded.
I believe I'm onto something with this platform, so I've decided to start hiring to build digital products that fit the thesis.
I would say I'm over-engineering in that I'm making the service available to others rather than leveraging in a portfolio of products, but I'd rather keep it open rather than have secrets.
(It's a good thing I'm retired because this is a large endeavor)
> Apparently facebook uses a whitelist to deal with the security issues introduced by GraphQL, but many developers who are using GraphQL appear to not understand the security threats involved with it.
I link to a longer essay on the inherent issues w/ increasing the client-side expressiveness of an API. It boils down to the fact that you give that power to anyone who can fire up a web console, in contrast with server-side expressiveness.
[1] - https://intercoolerjs.org/2016/02/17/api-churn-vs-security.h...
From personal experience the biggest challenge a GraphQL implementation faces is tighter/direct coupling with the backend data Schema which tends to either become friction in schema evolution or attract so much engineering effort that it is essentially also sustaining development of a hypermedia API.
What is old is new again and all that.
I am a web developer from the late 90s and I am trying to resurrect hypermedia as a viable option for rich web applications.
I read this post as education for the younger webdevs who may not know these things.
Disclaimer: I wrote the linked article for that solution.
Instead, it’s a meandering journey to their already chosen solution.
I can’t tell what their objection to graphql is and why hypermedia API’s are less of a security concern.
And their example with json API’s and close coupling doesn’t address the fact that adding a field doesn’t break backwards compatibility, and even if you do need to spin up a new api, any competent architecture will separate rendering an api from the business logic to generate its data, so standing up a new api variation won’t be a huge amount of work.
GraphQL increases client-side expressiveness of an API, but it also puts that power in the hands of potentially hostile users who, for example, could open up a console and start crafting dangerous queries (showing data that shouldn't be allowed, creating expensive queries that DoS your system, etc.)
Since with hypermedia APIs the UI is produced server side, you can, when producing the HTML, have full access to something like SQL. The server side is a trusted computing environment.
Facebook whitelists their GraphQL queries to avoid security issues, but many developers don't even realize that it is one.
> And their example with json API’s and close coupling doesn’t address the fact that adding a field doesn’t break backwards compatibility
In my example, I remove functionality.
However, the smart way to implement graphql is to map queries to a restful url (that’s a simple tool to build), so that the full graph isn’t exposed to end users.
Hypermedia URLs are typically specialized and don't expose general query functionality, whereas, as its expressiveness increases, GraphQL approaches the expressiveness of SQL. That's the whole point: you don't want to have to make back end changes to support new front end features.
The more powerful you make your GraphQL-based API, the more dangerous the security implications are. The less powerful you make it, the more it fails to address the fundamental problem of requiring back end changes to support front end needs.
It boils down to the fact that you simply can't increase the expressiveness of an untrusted computing environment like the browser without increasing security risk, whereas on the server side you can hand full SQL-style query access to your developers.
This is the crux of the problem. Also the reason XML fell out of favor and lead to a massive and still incomplete reinvention of the wheel in the form of JSON schema etc.
Imagine a client side programming language for which a valid html snippet is simply the serialization of an object. And vice versa. No parsing required.
The point is that much of the web has been shaped by the adoption of javascript as the exclusive browser side programming language.
Most of this was due to the overuse of XML, but it seems we are heading in that direction with either JSON or YAML everywhere these days.
The usual complaint is XML is bloated, but it is really how you write it,
{ "Name":"John", "age":20}
Vs
<name="John" age="20" />
and XML gives you both types and presentation with DTD and XSLT
You mention the data/presentation mix and that is not necessarily an advantage - separation of duties is usually a good idea, unless you can properly channel that "efficiency". But that too seems not insurmountable: the real, visual presentation on screen is anyway delegated to CSS. The (X)HTML structure is still in a sense supposed to capture the logical structure of the document/object that is being transmitted. What would be required is a way for the client-side language to distill the data-centric logic from the occasionally inflationary use of things like <div> elements (which seems another hack trying to fix poor design anyway).
In any case, no point crying over spilled milk. The winner-takes-all nature of the web means it is doomed to be building on the hacks adopted by the dominant entities to solve their needs. A historical accident that keeps giving.
Who knows, maybe as the browser is enabled with WASM and whatnot there will be a chance in the future to have a more rational approach to API's, REST, Hypermedia, Linked Data and that magical universe.
<item> <Name>John</Name> <Age>20</Age> </item>
or <item_John age="20"/> where john is parsed manually out of item object
or full blown up insanity <person> <item> <key>name</key> <value>John</value> </item> <item> <key>age</key> <value>20</value </item> </person>
As far as I know, that is not well-formed XML; the tag name is missing. You'd have to write it like this:
<person name="John" age="20" />
What's interesting, from the perspective of this article, is that at the application level, a hypermedia API is much more tightly bound to your particular application (you are returning specific UI to the client that would be a pain for a third party to consume) but that, despite that tighter coupling, the hypermedia API handles changes better.
The HTML response is the view. This is how the basic web works. The browser (as a client) knows how to render HTML. HTML also provides affordances (links and forms) to transition state.
Htmx has similar behavior to the basic web. Their client adds additional affordances to HTML and they allow state transition within the page.
People may disagree with this approach but to say it is not flexible seems odd when browsers are the most flexible hypermedia client in existence.
Something like RPC nudges towards the producer (or backend); graphql moves it to the consumer (or frontend).
A different way is to not look at this as a line of information flow between 2 points, by introducing a 3rd party, an impartial standards body. Maybe it's just a semantic or procedural difference, but when the locus is defined at the meta-architecture level there's no more room for discussion about exactly where you place the locus. Pay the vendor before you ship, or pay the courier when you receive? Neither: introduce an escrow.
The problem is users will interact with a majority of (get) APIs through a CDN and as developers we should reduce unnecessary data sitting in the CDN because it costs quite alot of money to serve.
For example if a CDN is returning JSON data {name: “Bart”} were only paying for 50 bytes or so of data transfer. BUT if instead we convert this to HTML and serve it, we would be 10x (or more)the data stored on the CDN to serve that data.
I don’t see a strong argument for paying 10x more to serve data as HTML.
https://htmx.org/essays/two-approaches-to-decoupling/#but-th...
> Many people would object that, sure, this hypermedia API may be flexible for our web application, but it makes for a terrible general purpose API.
> This is quite true. This hypermedia API is tuned for a specific web application. It would be cumbersome and error-prone to try to download this HTML, parse it and try to extract information from it. This hypermedia API only makes sense as part of a larger hypermedia system, being consumed by a proper hypermedia client.
We do care about commands that add and change state. Those are simple apis that have strict property requirements.
Also GraphQL is a horrible invention for quick and dirty work with no regard for long term maintenance. You’d be begging for an eventual big ball of mud.
Not to say it's wrong to do server-side rendering of the frontend, but I got the impression that the article wanted to make a distinction that I'm not seeing.
hypermedia APIs have not proven to be good data APIs, but they have proven to be excellent at surviving change within a larger hypermedia system (like the web)
in this article I'm trying to show why, despite the promise of decoupling that comes with a generic JSON Data API, it is hypermedia APIs (with tight server/front end coupling) that survive change better, due to the uniform interface of REST
I haven't a hard time understanding the utility of this, the article gives an example (removing ability of transfers), but why would a webpage need those hypermedia controls in the response if they are already encoded in the API of the business logic? for ex: The business logic tells the presentation layer, "if X field is true, disable transfers button".
This is in contrast to hypermedia where the client (a browser) simply sees the new hypermedia and renders it. In this case, the client is decoupled from the particulars of the business logic.
This is due to the uniform interface of REST. See https://htmx.org/essays/hateoas/
I particularly liked the bit about the way that the JSON approach, decoupled in theory, often ends up being tightly coupled in practice, such that you keep having to change both at once. And many places are structured such that you need two people or even two teams to make a single change. That doesn't sound decoupled at all!
I'm excited to see how it is to give on that in-practice-imaginary decoupling and try for HATOEAS at the fractions-of-a-page level that HTMX looks to enable.
https://www.oreilly.com/library/view/restful-web-clients/978...
it's not a trivial task though
> The central feature that distinguishes the REST architectural style from other network-based styles is its emphasis on a uniform interface between components.
Well, no. What distinguishes REST is that it uses HTTP verbs on resources.
And then it talks about Fielding mostly-not-implemented stuff and . . . no. Just no.
Before we've even gotten to the end of the para about coupling, it's clearly a bunch of crap.
Which is too bad, because personally I think REST is garbage, but CRUD garbage meant to replace SOAP "what is that thing?" garbage.
N.B. I am not making any claims about whether any particular HTTP API should serve JSON or HTML, I’m just saying that JSON is a strictly more flexible option.
What I'm reading [1] is that they're advocating for side-by-side decoupling.
In other words, humans and computers need different interfaces. Rather than try and build one, which is bad for both [2] build 2, one for the humans (however you prefer) and one for the computers (REST API).
Perhaps I'm reading it this way because I'm prejudiced, (I've written our systems this way) and it seems to be working well.
[1] this whole article is both well formatted, and seems to make a good post, but equally seems to feel like you're not sure what it's trying to say. Perhaps it makes more sense in context,rather than as a stand-alone article.
[2] the computer-client team has different needs to the human-client team. One wants a very stable API, the other wants regular changes. One is content driven, the other process driven. Ultimately they want different things making two interfaces makes both teams happier with less conflict between them that you have to umpire.
- a general purpose API is insufficient for any particular application, each application will require a special-purpose API alongside the general API
- assuming that you are going to have an application-specific API, it makes sense that the application-specific API should serve data specifically-tailored to that application (in this case hypermedia)
That said, it seems like the most interesting discussion would be about the tradeoffs between the two-JSON-API solution that they reference and the one-JSON-API + one-HTML-API solution that they suggest.
This makes me think about server functionality that is not exposed in the web app but it's still there, with potential security implications. An instance of the more generic case of client functionality not being in sync with server functionality of which client-only form validation is another scenario.