Confusion about the term "proxy" - server

I bumped into this sentence when reading about javascript-promises in https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise:
'A Promise is a proxy for a value not necessarily known when the promise is created.'
The whole term 'proxy' seems very confusing. When searching online you bump into terms like 'javascript-proxy', 'server-proxy'. Are this all the same thing? If not what are the differences?

Related

What is ZIO error channel and how to get a feeling about what to put in it?

ZIO (https://zio.dev/) is a scala framework which has at its core the ZIO[R, E, A] datastructure and its site gives the following information for the three parameters:
ZIO
The ZIO[R, E, A] data type has three type parameters:
R - Environment Type. The effect requires an environment of type R. If this type parameter is Any, it means the effect has no
requirements, because you can run the effect with any value (for
example, the unit value ()).
E - Failure Type. The effect may fail with a value of type E. Some applications will use Throwable. If this type parameter is
Nothing, it means the effect cannot fail, because there are no
values of type Nothing.
A - Success Type. The effect may succeed with a value of type A. If this type parameter is Unit, it means the effect produces no
useful information, while if it is Nothing, it means the effect runs
forever (or until failure).
It's easy to get what A is: it's the value returned by the function in the nominal case, ie why we coded the function for.
R is so kind of dependency injection - an interesting topic, but we can just ignore it to use ZIO by alway setting it to Any (and there is actually a IO[E, A] = ZIO[Any, E, A] alias in the lib).
So, it remains the E type, which is for error (the famous error channel). I roughtly get that IO[E, A] is kind of Either[E, A], but deals with effect (which is great).
My question is: why should I use an error channel EVERYWHERE in my application, and how can I decide what should go in the error channel?
1/ Why effect management with an error channel?
As a developper, one of your hardest task is to decide what is an error and what is not in your application - or more preciselly, to discover failure modes: what the nominal path (ie the goal of that code), what is an expected error that can be dealt with by the application in some way later on, and what are unexpected errors that the application can't deal with. There is no definitive answer for that question, it depends of the application and context, and so it's you, the developper, who needs to decide.
But the hardest task is to build an application that keeps its promises (your promises, since you chose what is an error and what is the nominal path) and that is not surprising so that users, administrators, and dev - including the futur you in two weeks - know what the code do in most cases without having to guess and have agency to adapt to that behavior, including to respond to errors.
This is hard, and you need a systematic process to deals with all the possible cases without going made.
The error channel in IO bi-monad (and thus ZIO) helps you for that task: the IO monad helps you keep track of effects, which are the source of most errors, and the error channel makes explicit what are the possible error cases, and so other parts of the application have agency to deal with them if they can. You will be able to manage your effects in a pure, consistant, composable way with explicit failure modes.
Moreover, in the case of ZIO, you can easely import non-pure code like legacy java extremelly easily:
val pure = ZIO.effect(someJavaCodeThrowingException)
2/ How do I choose what is an error?
So, the error channel provide a way to encode answer to what if? question to futur dev working on that code. "What if database is down?" "there's a DatabaseConnectionError".
But all what if are not alike for YOUR use case, for CURRENT application level. "What if user is not found?" - ah, it may be a totally expected answer at the low, "repository" level (like a "find" that didn't find anything), or it can be an error at an other level (like when you are in the process of authenticating an user, it should really be there). On the first case, you will likely not use the error channel: it's the nominal path, sometimes you don't find things. And in the second case, you will likelly use the error channel (UserNotFoundError).
So as we said, errors in error channel are typically for what if question that you may want to deal with in the application, just not at that function level. The first example of DatabaseConnectionError may be catch higher in the app and lead to an user message like "please try again" and a notification email to sysadmin ("quick, get a look, something if wrong here"). The UserNotFoundError will likely be managed as an error message for the user in the login form, something like "bad login or password, try again or recover credentials with that process".
So these cases (nominal and expected errors) are the easy parts. But there are some what if questions that your application, whatever the level, has no clue how to answer. "What if I get a memory exception when I try to allocate that object?" I don't have any clue, and actually, even if I had a clue, that's out of the scope of the things that I want to deal with for that application. So these errors DON'T go in the error channel. We call them failure and we crash the application when they happens, because it's likely that the application is now in an unknow, dangerous, zombie state.
Again, that choice (nominal path/error channel/failure) is your choice: two applications can make different choices. For example, a one-time-data-processing-app-then-discard-it will likelly treat all non-nominal paths as failures. There is a dev to catch the case in realtime and decide if it's important (see: Shell, Python, and any scripting where that strategy is heavely used - ok, sometimes even when there is no dev to catch errors:). On the other end of the specter, Nasa dev put EVERYTHING in the error channel(+), even memory CORRUPTION. Because it is an expected error, so the application need to know how to deal with that and continue.
(+)NOTE: AFAIK they don't use zio (for now), but the decision process about what is an error is the same, even in C.
To go further, I (#fanf42) gave a talk at Scala.io conference. The talk, "Ssytematic error management in application", is available in French here. Yes, French, I know - but slides are available in English here! And you can ping me (see contact info near the end of slide deck).

REST vs RPC - *Actual purpose* differences

I started writing web-apps and distributed apps when REST was already popular, so I actually never used RPC.
When searching for a simple explanation of the difference between them, I started to understand, but some examples got me confused.
I saw things like this:
GET /getLastUser
or this:
POST /changeUserName
If REST is meant for resources, and RPC is meant for procedures, isn't it a bad practice using RPC for something like this?
Correct me if I'm wrong, but the way I see it, RPC should be more purely functional.
Meaning that calling a procedure should always:
return the same result for the same arguments
not affect state
So, RPC calls like this:
GET /addTwo?num=5
that return something like this:
{
"result": 7
}
seem more logical to me (although that's a very simple example).
If this question gets closed for being too "opinion-based", I'll just know that I should do whatever the heck I want...
RPC is not meant to be functional. Calling a same procedure twice gives no guarantee about the result.
This question can be answered a few different ways, and pretty deep. I think this might be a fair summary.
With RPC the primitives typically are function names, arguments and results.
With REST the primitive is a 'resource representation'.
So where with RPC you might call a function, in REST you are really sending and retrieving the state of a resource, regardless of protocol.
This means you typically only ask a server 'can you give me the state of this resource', or you tell a server 'here's a new resource state, please store it at this location'. The only successful answers REST will give are "the current state" or "this operation worked", but with RPC the question (function + arguments) and answer (the result) can be anything.
So you can argue that when you describe it like this, RPC is a lot more flexible. It probably is, but because REST confines itself to just transmitting state, you gain a lot of guarantees that a simple RPC-based protocol does not give.
REST is not just about transferring state. The usage hyper-links is another important requirement for a service to be called REST, and this is also something that you don't get 'out of the box' with RPC.
Lastly, it can be argued that HTTP itself is an RPC-like protocol. I think it's possible to build a RESTful service on top of any RPC service.

Is there a term for properties that capture a true/false/null status?

I'm doing a bunch of refactoring to change properties that were previously merely boolean (true/false) to a state that can also capture the null status (true/false/null). I find myself forced to describe the new status as "true/false/null". This is both lengthy and not particularly meaningful to non-dev folks in the business that don't use the term 'boolean' or 'null'.
Is there a term that better describes the new property type that I'm introducing?
This is basically known as three-valued logic (3VL), a term which allows the value to be true, false or some indeterminate value.
Wikipedia has a page on 3VL which you may find of interest.
I've heard some people use the term tri-state logic for this as well but I suspect that will cause a lot of electronics enthusiasts to get all hot and bothered about misappropriation of the term - it means something quite different in that arena (putting a device in high impedance mode to minimise its effect on the circuit as a whole).

Are Futures in Scala really functional?

I am reading this blog post that claims Futures are not "functional" since they are just wrappers of side-effectful computations. For instance, they contain RPC calls, HTTP requests, etc. Is it correct ?
The blog post gives the following example:
def twoUsersFeed(a: UserHandle, b: UserHandle)
(implicit ec: ExecutionContext): Future[Html] =
for {
feedA <- usersFeed(a)
feedB <- usersFeed(b)
} yield feedA ++ feedB
you lose the desired property: consistent results (the referential transparency). Also you lose the property of making as few requests as possible. It is difficult to use multi-valued requests and have composable code.
I am afraid I don't get it. Could you explain how we lose the consistent result in this case ?
The blog post fails to draw a proper distinction between Future itself and the way it's commonly used, IMO. You could write pure-functional code with Future, if you only ever wrote Futures that called pure, total functions; such code would be referentially transparent and "functional" in every remotely reasonable sense of the word.
What is true is that Futures give you limited control of side effects, if you use them with methods that have side effects. If you create a Futurewrapping webClient.get, then creating that Future will send a HTTP call. But that's not a fact about Future, that's a fact about webClient.get!
There is a grain of truth in this blog post. Separating expressing your computation from executing it, completely, via e.g. the Free monad, can result in more efficient and more testable code. E.g. you can create a "query language", where you express an operation like "fetch the profile photos of all the mutual friends of A and B" without actually running it. This makes it easier to test if your logic is correct (because it's very easy to make e.g. a test implementation that can "run" the same queries - or even just inspect the "query object" directly) and, as I think the blog post is trying to suggest, means you could e.g. combine multiple requests to fetch the same profile. (This isn't even purely a functional-programming concern - some OO books have the idea of a "command pattern" - though IME functional programming tools like for/yield syntax make it much easier to work in this way). Whereas if all you have is a fetchProfile method that, when run, immediately fires off a HTTP request, then if your code logic requests the same profile twice, there's no way to avoid fetching the same profile twice.
But that isn't really about Future per se, and IMO this blog post is more confusing than helpful.

RxJS is to events as promises are to async

In Requesting a clear, picturesque explanation of Reactive Extensions (RX)? I asked about what RX is all about, and I think, thanks to the provided answers I now got the idea.
In the referenced question i quoted a sentence from http://reactive-extensions.github.com/RxJS/ which says:
RxJS is to events as promises are to async.
Although I think that I got the idea behind RX, I do not get this sentence at all. I can not even say what it is exactly that I do not understand. It's more like ... I don't see the connection between the first and the second half of the sentence.
To me, this sentence sounds important and impressive, but I can hardly tell whether it's true or not, whether it's a great insight or not, and so on ...
Can anybody explain what the sentence means in words someone (like me) can understand who is new to all this reactive stuff?
Promises are a way to define computations that may happen once an asynchronous operation completes. RxJs is a way to define computations that may happen when one or more events, in a stream, occur (onNext), complete (onCompleted), or throw an exception (onError).