Comment by PaulHoule

3 days ago

Fielding won the war precisely because he was intellectually incoherent and mostly wrong. It's the "worse is better" of the 21st century.

RPC systems were notoriously unergonomic and at best marginally successful. See Sun RPC, RMI, DCOM, CORBA, XML-RPC, SOAP, Protocol Buffers, etc.

People say it is not RPC but all the time we write some function in Javascript like

   const getItem = async (itemId) => { ... }

which does a

   GET /item/{item_id}

and on the backend we have a function that looks like

   Item getItem(String itemId) { ... }

with some annotation that explains how to map the URL to an item call. So it is RPC, but instead of a highly complex system that is intellectually coherent but awkward and makes developers puke, we have a system that's more manual than it could be but has a lot of slack and leaves developers feeling like they're in control. 80% of what's wrong with it is that people won't just use ISO 8601 dates.

When I realized that I was calling openapi-generator to create client side call stubs on non-small service oriented project, I started missing J2EE EJB. And it takes a lot to miss EJB.

I'd like to ask seasoned devs and engineers here. Is it the normal industry-wide blind spot where people still crave for and are happy creating 12 different description of the same things across remote, client, unit tests, e2e tests, orm, api schemas, all the while feeling much more productive than <insert monolith here> ?

  • I've seen some systems with a lot of pieces where teams have attempted to avoid repetition and arranged to use a single source of schema truth to generate various other parts automatically, and it was generally more brittle and harder to maintain due to different parts of the pipeline owned by different teams, and operated on different schedules. Furthermore it became hard to onboard to these environments and figure out how to make changes and deploy them safely. Sometimes the repetition is really the lesser evil.

    • I see, it's also reminiscent of the saying "microservices" are an organisational solution. It's just that I also see a lot of churn and friction due to incoherent versions and specs not being managed in sync now (some solutions exists are coming though)

    • > I've seen some systems with a lot of pieces where teams have attempted to avoid repetition and arranged to use a single source of schema truth to generate various other parts automatically, and it was generally more brittle and harder to maintain due to different parts of the pipeline owned by different teams, and operated on different schedules.

      I'm not sure what would lead to this setup. For years there are frameworks that support generating their own OpenAPI spec, and even API gateways that not only take that OpenAPI spec as input for their routing configuration but also support exporting it's own.

    • > it was generally more brittle and harder to maintain

      It depends on the system in question, sometimes it's really worth it. Such setups are brittle by design, otherwise you get teams that ship fast but produce bugs that surface randomly in the runtime.

      1 reply →

  • I keep pining for a stripped-down gRPC. I like the *.proto file format, and at least in principle I like the idea of using code-generation that follows a well-defined spec to build the client library. And I like making the API responsible for defining its own error codes instead of trying to reuse and overload the transport protocol's error codes and semantics. And I like eliminating the guesswork and analysis paralysis around whether parameters belong in the URL, in query parameters, or in some sort of blob payload. And I like having a well-defined spec for querying an API for its endpoints and message formats. And I like the well-defined forward and backward compatibility rules. And I like the explicit support for reusing common, standardized message formats across different specs.

    But I don't like the micromanagement of field encoding formats, and I don't like the HTTP3 streaming stuff that makes it impossible to directly consume gRPC APIs from JavaScript running in the browser, and I don't like the code generators that produce unidiomatic client libraries that follow Google's awkward and idiosyncratic coding standards. It's not that I don't see their value, per se*. It's more that these kinds of features create major barriers to entry for both users and implementers. And they are there to solve problems that, as the continuing predominance of ad-hoc JSON slinging demonstrates, the vast majority of people just don't have.

    • I can write frickin' bash scripts that handle JSON APIs with curl, jq, here quotes and all that.

      A lot of people just do whatever comes to mind first and don't think about it so they don't get stuck with analysis paralysis.

         curl -fail
      

      Handling failure might be the real hardest programming problem ahead of naming and caches and such. It boggles my mind the hate people have for Exceptions which at least make you "try" quite literally if you don't want the system to barrel past failures, some seem nostalgic for errno and others will fight mightily with Either<A,B> or Optional<X> or other monads and wind up just barreling past failures in the end anyway. A 500 is a 500.

      1 reply →

  • Brb, I'm off to invent another language independent IDL for API definitions that is only implemented by 2 of the 5 languages you need to work with.

    I'm joking, but I did actually implement essentially that internally. We start with TypeScript files as its type system is good at describing JSON. We go from there to JSON Schema for validation, and from there to the other languages we need.

  • It's not that we like it, it's just that most other solutions are so complex and difficult to maintain that repetition is really not that bad a thing.

    I was however impressed with FastAPI, a python framework which brought together API implementation, data types and generating swagger specs in a very nice package. I still had to take care of integration tests by myself, but with pytest that's easy.

    So there are some solutions that help avoid schema duplication.

    • fastapi + sqlmodel does remove many layers that is true, but you still have other services requiring lots of boilerplate

  • My experience is that all of these layers have identical data models when a project begins, and it seems like you have a lot of boilerplate to repeat every time to describe "the same thing" in each layer.

    But then, as the project evolves, you actually discover that these models have specific differences in different layers, even though they are mostly the same, and it becomes much harder to maintain them as {common model} + {differences}, than it is to just admit that they are just different related models.

    For some examples of very common differences:

    - different base types required for different languages (particularly SQL vs MDW vs JavaScript)

    - different framework or language-specific annotations needed at different layers (public/UNIQUE/needs to start with a capital letter/@Property)

    - extra attached data required at various layers (computed properties, display styles)

    - object-relational mismatches

    The reality is that your MDW data model is different from your Database schema and different from your UI data model (and there may be multiple layers as well in any of these). Any attempt to force them to conform to be kept automatically in sync will fail, unless you add to it all of the logic of those differences.

    • anybody ever worked with model-driven methodologies ? the central model is then derived to other definitions

  • Having 12 different independent copies means nobody on your 30 people multi-region team is blocked.

I remember getting my hands on a CORBA specification back as a wide-eyed teen thinking there is this magical world of programming purity somewhere: all 1200 pages of it, IIRC (not sure what version).

And then you don't really need most of it, and one thing you need is so utterly complicated, that it is stupid (no RoI) to even bother being compliant.

And truly, less is more.

I'm not super familiar with SOAP and CORBA, but how is SOAP any more coherent than a "RESTful" API? It's basically just a bag of messages. I guess it involves a schema, but that's not more coherent imo, since you just end up with specifics for every endpoint anyways.

CORBA is less "incoherent", but I'm not sure that's actually helpful, since it's still a huge mess. You can most likely become a lot more proficient with RESTful APIs and be more productive with them, much faster than you could with CORBA. Even if CORBA is extremely well specified, and "RESTful" is based more on vibes than anything specific.

Though to be clear I'm talking about the current definition of REST APIs, not the original, which I think wasn't super useful.

  • SOAP, CORBA and such have a theory for everything (say authentication) It's hard to learn that theory, you have to learn a lot of it to be able to accomplish anything at all, you have to deal with build and tooling issues, but if you look closely there will be all sorts of WTFs. Developers of standards like that are always implementing things like distributed garbage collection and distributed transactions which are invariably problematic.

    Circa 2006 I was working on a site that needed to calculate sales tax and we were looking for an API that could help with that. One vendor uses SOAP which would have worked if we were running ASP.NET but we were running PHP. In two days I figured out enough to reverse engineer the authentication system (docs weren't quite enough to make something that worked) but then I had more problems to debug. A competitive vendor used a much simpler system and we had it working in 45 min -- auth is always a chokepoint because if you can't get it working 100% you get 0% of the functionality.

    HTTP never had an official authentication story that made sense. According to the docs there are basic, digest, etc. Have you ever seen a site that uses them? The world quietly adopted cookie-based auth that was an ad-hoc version of JSON Web Tokens, once we got an intellectually coherent spec snake oil vendors could spam HN with posts about how bad JWT is because... It had a name and numerous specifics to complain about.

    Look at various modern HTTP APIs and you see auth is all across the board. There was the time I did a "shootout" of roughly 10 visual recognition APIs, I got all of them working in 20-30 mins except for Google where I had to install a lot of software on my machine, trashed my Python, and struggled mightily because... they had a complex theory of authentication which was a barrier to doing anything at all.

    Worse is better.

    • Agree with most of what you said, except about HTTP Basic auth. That is used everywhere - take a look at any random API and there is roughly 90% chance that this is the authentication mechanism used. For backends which serve a single frontend maybe not so much, but still in places.

      2 replies →

    • > Have you ever seen a site that uses them?

      I lost the thread...are we talking websites or APIs?

      Both use HTTP, but those are pretty different interfaces.

What RPC mechanisms, in your opinion, are the most ergonomic and why?

(I have been offering REST’ish and gRPC in software I write for many years now. With the REST’ish api generated from the gRPC APIs. I’m leaning towards dropping REST and only offering gRPC. Mostly because the generated clients are so ugly)

  • Just use gRPC or ConnectRPC (which is basically gRPC but over regular HTTP). It's simple and rigid.

    REST is just too "floppy", there are too many ways to do things. You can transfer data as a part of the path, as query parameters, as POST fields (in multiple encodings!), as multipart forms, as streaming data, etc.

    • Just not in C++ code. gprc has a bajillon dependencies, and upgrades are a major pain. If you have a dedicated build team and they are willing to support this - sure, go ahead and use it.

      But if you have multiple targets, or unusual compilers, or don't enjoy working with build systems, stay away from complex stuff. Sure, REST may need some manual scaffolding, but no matter what your target is, there is a very good chance it has JSON and HTTP libs.

    • > REST is just too "floppy", there are too many ways to do things.

      I think there is some degree of confusion in your reply. You're trying to compare a framework with an architecture style. It's like comparing, say, OData with rpc-over-HTTP.

      1 reply →

Amen. Particularly ISO8601.

  • Always thought that a standard like ISO8601 which always stores the date and time in UTC but appends the local time zone would beneficial.

    • Sometimes you need your timestamps to be in a named timezone. If I have a meeting at 9am local time next month, I probably want it to still be at 9am even if the government suddenly decided to cancel daylight time.

      3 replies →

    • I don't think I ever needed something like that... Since most cases don't need local time zone, why not keep two separate fields?

      1 reply →

  • ISO8601 is really broad with loads of edge cases and differing versions. RFC 3339 is closer, but still with a few quirks. Not sure why we can't have one of these that actually has just one way of representing each instant.

    Related: https://ijmacd.github.io/rfc3339-iso8601/

    • I love how that's live!

      Since ISO 8601 costs 133 CHF I suspect hardly anybody has actually read it, I think if you wanted something that supports all the weird stuff you might find somebody wrote it in 390 assembly.

> Fielding won the war

It’s a bit odd to say fielding “won the war” when for years he had a blog pointing out all the APIs doing RPC over HTTP and calling it REST.

He formalised a concept and gave it a snappy name, and then the concept got left behind and the name stolen away from the purpose he created it for.

If that’s what you call victory, I guess Marx can rest easy.

  • > He formalised a concept and gave it a snappy name, and then the concept got left behind and the name stolen away from the purpose he created it for.

    I'm not sure the "name was stolen" or the zealot concept actually never got any traction in production environments due to all the problems it creates.

    • > I'm not sure the "name was stolen" or the zealot concept actually never got any traction in production environments due to all the problems it creates.

      That is a false dichotomy. Fielding gave a name to a specific concept / architectural style, the concept got ignored (rightly or wrongly, doesn’t matter) while the name he coined got recycled for something essentially entirely unrelated.

I mean, HTTP is an RPC protocol. It has methods and arguments and return types.

What I object to about eg xml-rpc is that it layers a second RPC protocol over HTTP so now I have two of them...