#Refactoring advice for actor with multiple states

1 messages · Page 1 of 1 (latest)

clever kraken
#

So I made this terrible code yesterday: https://git.ahlcode.fi/nicd/aurinko/src/commit/05b7a81139f78a6c8b35ed210b9fd24cdc43c817/backend/src/aurinko/updater.gleam

The problem is that I have at least three states:

  1. when the actor is started with only the credentials (InitialState),
  2. when the initial login and module fetch is done so that we have the auth cookies (LoadedState), and
  3. when we have loaded measurement data (LoadedState with Dataset set to something).

Due to having multiple states, I need to keep checking the shape of the state at every turn, or do what I did here and unwrap the values into separate variables that I pass around. But that's very verbose, and I keep writing username, password, cookies, cookies_acquired, ... over and over again.

If you have a suggestion how this could be cleaned up, I'd love to hear it. 🙂 But it's a bunch of code to read.

#

Another issue is that both states have err for errors, but because they're not in the same place, I have to destructure the values completely on lines 105-124 to add the error.

vivid gate
#
type State {
  Pending(PendingState)
  Loading(LoadingState)
  Loaded(LoadedState)
}

type PendingState

type LoadingState

type LoadedState

type Message {
  PendingMessage(PendingMessage)
  LoadingMessage(LoadingMessage)
  LoadedMessage(LoadedMessage)
}

type PendingMessage

type LoadingMessage

type LoadedMessage

fn handle_message(message: Message, state: State) -> Next(Message, State) {
  case message, state {
    PendingMessage(message), Pending(state) -> 
      handle_pending_message(message, state)
    ...
    _, _ -> actor.continue(state)
  }
}

factor it out so you aren't handling the world in a single function

clever kraken
#

but now in handle_pending_message the state is still State, right?

vivid gate
#

no the state is now PendingState

clever kraken
#

ohhhh yeah

#

is it possible to deduplicate parts where the different states contain the same things or should I just write them out?

vivid gate
#

you can dedupe them yeah

type State {
  State(some: Common, stuff: Here, rest: Rest)
}

type Rest {
  Pending(PendingState)
  Loading(LoadingState)
  Loaded(LoadedState)
}

and then pass them in as params like

handle_pending_message(some: Common, stuff: Here, state: PendingState) -> State
clever kraken
#

thanks! 💜 I'll try this

vivid gate
#

😂

clever kraken
#

it is only the truth

clever kraken
#

thanks for the help!