Agreed. I just wouldn't call it to_server but "state". Easier to bikeshed on code, so a PR is welcome. :)
On Mon, Apr 10, 2023 at 4:14 PM Bruce Tate <br...@grox.io> wrote: > I would like to propose that we change the base example for GenServer. For > those not familiar with it, here it is: > > defmodule Stack do > > use GenServer > > > > # Callbacks > > > > @impl true > > def init(stack) do > > {:ok, stack} > > end > > > > @impl true > > def handle_call(:pop, _from, [head | tail]) do > > {:reply, head, tail} > > end > > > > def handle_cast({:push, element}, state) do > > {:noreply, [element | state]} > > end > > end > > These are the problems as I teach new Elixir developers OTP. > > First, the purpose of init is not clear. It simply returns a stack, and > does not indicate that this is an opportunity to transform the input in > some way: > > def init(stack) do > > {:ok, stack} > > end > > As a result, it's not clear what to use init for. > > Second, we don't label the state of the GenServer appropriately, and > worse, we do work in the function head, making it harder for users to grasp > the central ideas that GenServers carry state and offer the opportunity to > transform it: > > def handle_call(:pop, _from, [head | tail]) do > > {:reply, head, tail} > > end > > As a result, it's too hard for users to understand what this does without > already knowing. > > Third, the return tuples are not explicitly labeled, forcing the reader to > work harder to understand what the tuples actually do. > > Summarizing the problems: > > - The example doesn't use init to transform the initial value to the > genserver state. > - The example doesn't consistently label the last argument of the two > handlers. > - The example does work in the "pop" function head, limiting our > opportunity to label concepts. > - The example doesn't explicitly label the elements of the reply and > noreply tuples. > > I would like to propose these changes: > > defmodule Stack do > > use GenServer > > > > # Callbacks > > > > @impl true > > def init(string) do > > {:ok, String,split(string, ",", trim: true)} > > end > > > > @impl true > > def handle_call(:pop, _from, state) do > > [to_client | to_server] = state > > {:reply, head, tail} > > end > > > > def handle_cast({:push, element}, state) do > > to_server = [element | state] > > {:noreply, to_server} > > end > > end > > I don't really care whether we label the state with state or stack. I > have a slight preference for state because we're labeling the genserver > concept, not the domain concept. > > Likewise, I don't care whether we use to_server or new_genserver_state on > the server side, or the to_client or to_caller to discuss the results of > the reply and noreply tuples. > > I should also point out that we don't handle the error state and it's easy > to do so. > > I mainly care that this example communicates with more clarity. > > Feedback is welcome. > > -bt > > > Regards, > Bruce Tate > CEO > > Groxio, LLC. > 512.799.9366 > br...@grox.io > grox.io > > > -- > You received this message because you are subscribed to the Google Groups > "elixir-lang-core" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to elixir-lang-core+unsubscr...@googlegroups.com. > To view this discussion on the web visit > https://groups.google.com/d/msgid/elixir-lang-core/CAFXvW-5%2B3ECDYi76eENLEEfHDCyRfkNjX-A%3DHCKtxqFy%2BCATSQ%40mail.gmail.com > <https://groups.google.com/d/msgid/elixir-lang-core/CAFXvW-5%2B3ECDYi76eENLEEfHDCyRfkNjX-A%3DHCKtxqFy%2BCATSQ%40mail.gmail.com?utm_medium=email&utm_source=footer> > . > -- You received this message because you are subscribed to the Google Groups "elixir-lang-core" group. To unsubscribe from this group and stop receiving emails from it, send an email to elixir-lang-core+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/elixir-lang-core/CAGnRm4J2BkxWzwAOq6F1LtgpvcS-y-cGbKUn8DynuYmx6SH0jg%40mail.gmail.com.