AWebOfBrown
Joined 10 years ago
Joined 10 years ago
To me it is absolutely farcical that he was being being paid by a harness company (Amp) as a staff software engineer, slop-coded a solution to keeping LLMs on track (Beads), and having paid for all of this Amp and Steve...parted ways. Beads never went into Amp. Someone cottoned on to the value Steve was providing, for my money.
His point about the runtime complexity of an API being entirely distinct from how the interface to it's code is exposed (whether GraphQL or REST or otherwise) is fairly obvious, I think.
The counter-argument is that unlimited query complexity makes it far bigger problem, and the author's point is that if you're using it for private APIs with persisted queries, you shouldn't have that problem unknowingly.
Don't get me wrong - I think the takeaway is that GraphQL's niche is quite small, and he's defending exactly that niche. It's not often the case that you can develop an API in a private manner which doesn't undercut higher-order value in the future, as the rise of AWS hopefully made evident.
He wasn't wrong in his assessment of complexity, but the fact he refused to acknowledge the business priorities were the same between Google and companies he called out, absolutely baffled me. The gist from my perspective was that companies external to his own should bend over backwards for performance, while his should not, because his personal goals were tied to improving the performance of the web. Hopefully that's an over-simplification and I've missed something, but that's what I can recall.
I agree with most of what you said, but this seems a bit ironic.
Your suggestions almost exclusively involve large investments of time with little established proof that they are efficient. Do you genuinely believe reading RFC 2616 "cover to cover" is an efficient way of solving the specific problems they came across?
I would wager most developers wishing to be "really good" actually have a concrete desire like a greater paycheque or employer in mind. If that is true, I doubt reading someone's booklist necessarily is their fastest pathway, and their economic perspective is exactly what stops them doing so.
By far the greatest benefit is being able to sanely implement a type-safe API. To me, it is utter madness throwing custom extensions of the Error class arbitrarily deep in the call-stack, and then having a catch handler somewhere up the top hoping that each error case is matched and correctly translated to the intended http response (at least this seems to be a common alternative).
To me, it's a contextual term much like 'single responsibility'. In this case, the two "sides" of an integration test are present. A consumer issues a request and a provider responds accordingly. The tests would ascertain that with variations to the client request, the provider behaves in the expected manner.
At which point you might point out that this sounds like an e2e test, but actually using the client web app, for example, might involve far more than a simple http client/library - in no small part because the provider can easily run a simple consumer in memory and avoid the network entirely. E2e tests tend to be far more fragile, so from the perspective of achieving practical continuous deployment, it's a useful distinction.
integration tests in this instance: varying HTTP requests (infrastructure layer) provoke correct behaviour in application layer.
e2e: intended client issues http requests under the correct conditions, which provokes certain provider behaviour, which client then actually utilises correctly.
This, to me, is why the most important part of testing is understanding the boundaries of the tests. Not worrying about their names.
The problem I've seen is over-dependence on writing unit tests with mocks instead of biting the bullet and properly testing all the boundaries. I have seen folk end up with 1000+ tests, of which most are useless because the mocks make far too many assumptions, but are necessary because of the layer coupling.
This was mostly in Node though, where mocking the request/response gets done inconsistently, per framework. Go might have better tooling in that regard, and maybe that sways the equation a bit. IMO there's still merit to decoupling if there's any feasibility of e.g. migrating to GraphQL or another protocol without having to undergo an entire re-write.
I don't disagree that it's more practical, initially, as you've described it. However, I think it's important to point out the tradeoff rather than presenting it as purely more efficient. I've seen this approach result in poor separation of concerns and bloated use cases (`DoTheActualThing`) which become tedious to refactor, albeit in other languages.
One predictable side effect of the above, if you're working with junior engineers, is that they are likely going to write tests for the application logic with a dependency on the request / response as inputs, and asserting on status codes etc. I shudder to think how many lines of code I've read dedicated to mocking req/res that were never needed in the first place.