How to manage state?

Dear pro scripters,

So can someone explain to me the whole state thing. Wikipedia

The way I understand it right now, state is just value(s) that change. Many times I want different modules to access “shared state” I simply make a module with a return table with the state, then anyone can freely read it and change it.

What’s my question?

My question originates from the fact that I keep wanting to have some functionality when a state changes. For example my problem right now is I have a module on the client called “Settings” and any module on the client can access a “setting” by doing Settings.get(). What’s a setting anyway? Settings are anything on the client that is client-only and is only sent to the server to store in datastore. Examples are UI preferences, other preferences, UI layout. I want to be able to change a “setting” table and the changes automatically get sent to the server to be saved. I can’t just do settings.key = value because that will not run any code to update the server. Now maybe there’s a much better way of doing this (please let me kow)

There’s 2 ways I know of to run a function when a key in a table changes.

  1. Make an object with a “Data” field and a “SetValue” method, and read values by doing Data.NestedTable.Key and write values by doing Object:SetValue("NestedTable.Key"), then you have to remember to not directly set the table and always go through the set method and it’s also annoying to pass the entire path into set method. This is what ReplicaService uses.

  2. Use proxy tables. You can use “proxy tables” using newproxy() or just having a blank table. Then you can use the __index and __newindex metamethod to track when a key changes. If you set a proxy[key] = {} you will then have to make another proxy table for the nested table and so on. This has some complications like you can’t use the table library or loop through the proxy table normally, and they are much much slower to create, read, and write to then normal tables.

Both of these methods feel hacky, so I want to know what to the pro scripters do?

I think I might be looking at the whole thing the wrong way and “good code” would not run into this problem anyway (if so then what’s the proper way?)

Okay thanks for reading and maybe answering :slight_smile:

1 Like

Verbose Setters and Getters are probably your safest option and is more or less how OOP languages handle things. It keeps code clean and encapsulated, and it can be achieved with relatively simple usage of metatables. While assigning __index and __newindex functions to metatables can get you the results you’re looking for, it will generally come at the cost of code maintainability.

One thing to remember about Lua is that the language intentionally has few rules. More rigid languages can utilize their rules to do things for you (like allowing you to directly set a value for a property and having the underlying engine call the Set function implicitly), but Lua’s fluidity generally means you need to be judicious in your implementation and write things out.

2 Likes

For you, I think having a set and get function is probably the best simple solution for you.

However, if you want an alternative state management method I really suggest Rodux (roblox redux).
Instead of any script editing your state which might get messy, you have actions that you can dispatch to your rodux store and that is how you edit state.
Here’s a link to rodux repo if you wanna learn more.

1 Like

Okay, so I’m not oversighting something really simple?, and people just follow set and get method rules.

@UnknownParabellum Thanks for your answer too, I’ve heard of Rodux but never knew what it did, I’ll look into it!

1 Like