4 ms·
Don't agree at all. There is a huge difference between calling a function "foo()" that makes an RPC call and the relatively equivalent REST call "http.GET('/foo
by speedplane 9y ago
Don't agree at all. There is a huge difference between calling a function "foo()" that makes an RPC call and the relatively equivalent REST call "http.GET('/foo')". The former feels like a function call, and callers will assume it operates like one. However, in reality the former is not a function, it's making a network call, and it's incredibly unreliable.
In theory, the latter does the same thing, but it's far more explicit, the developer knows it relies on the network and accordingly that it may fail. Developers will be more inclined to plan for errors when the possibility of such errors are more obvious.
- pixie_ 9y agoWhat's funny is that most consumers of REST APIs do it through a wrapper that turns it back into a statically typed RPC. REST truly is a useless middleman that no one realizes they just don't need.
- dec0dedab0de 9y agoI doubt that most consumers of REST APIs are doing anything statically typed. I would guess that the vast majority of REST consumers are written in browser javascript. Server side, I bet at least half are written in a dynamic language.
- satyanash 9y agoI don't think the parent here is talking about whether the language is static/dynamic. The point is that most REST calls are wrapped in a statically 'dispatched' function call. So in most cases you'd do something like: let foo = () => http.GET('/foo'); . . . foo() //foo is statically dispatched in the source code here
- DougBTX 9y agoIt seems like "RPC" is being used pretty loosely in this thread. Whether foo in your example is RPC or not depends on its signature, if it attempts to synchronously return the response from the server, then it is RPC, if it just returns a Promise then it isn't.
- magic_quotes 9y ago> There is a huge difference between calling a function "foo()" that makes an RPC call and the relatively equivalent REST call "http.GET('/foo')". Is it really a useful distinction? Let's rename our 'foo()' to 'dangerously_unreliable_with_unpredictable_latency_foo()'. Is there still a huge difference? > accordingly that it may fail. Developers will be more inclined to plan for errors when the possibility of such errors are more obvious. That part of your comment looks suspiciously similar to the usual argument against exception handling to me.
- speedplane 9y agoDangerous and unreliable don't really capture it... how about potentialy_async_call_relying_on_network_that_raises_lots_of_exceptions_foo(), then I'd agree they are pretty similar. However http.get("foo") often says the same thing more succinctly. And to your second point... yes, all developers should check possible exceptions, just like all children should brush their teeth. However, if you have bad habits and you aren't good all the time, then at lease brush your teeth after eating sweets, and likewise, developers should please check for exceptions around network calls.
- lfischer 9y agoSome time ago, another HN user commented a lack of good async support in languages and libraries caused some of the issues with early RPC. With more languages introducing futures and promises as return values or asyncronous functions, don’t you think we might finally have the tools to express that unreliability in a simple function call?
- raquo 9y agoSounds trivially avoidable. Access the RPC call as httpSerbice.getFoo() and make it return a Future/Promise, or even a special subtype of those. 100% obvious what it does. You're going to be calling REST methods the same exact way anyway - you have to pass around the result of that restful http.get call somehow.
- badsectoracula 9y agoHow is that different than any function call that start something in the background? I have used and even written myself simple job code (with threading) that has functions like (simplified): int start(void (*job)(void*), void (*done)(void*), void* tag); `job` is called on a separate thread at some point (goes through a job scheduler) and once it is done, `done` is called at the "main" thread (at some synchronization point, usually during the event loop), `tag` is just passed around for context. `start` returns zero on failure. I don't see RPCs as anything different conceptually (after all the job might also fail). The only issue someone might have is when expecting a synchronous API, but even in non-networked code there are tons of asynchronous APIs.
- speedplane 9y agoThe main difference is that networks are inherently unreliable. Threaded or multi-processed applications can also be unreliable but for different reasons. The goal should be to inform the caller of the types of errors that may pop up. Obviously, with network or RPC calls, the caller should handle the case where the network is down. With threaded apps, the potential errors are more subtle, but the caller should definitely be aware that it's not a synchronous call. The function header you proposed is a bit clumsy due to the c semantics, but gets the general point across well enough.