Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

When to use functions and when to decide that it is not worth it?

Asked by 5 years ago
Edited 5 years ago

Recently, I had a discussion in the discord about whether or not to use :UpdateAsync or :SetAsync mainly because I did not need to access the previous values when saving the player's data. I have been mostly encouraged to use :UpdateAsync because it does not return a cached value. However, I don't need to know what the returned value is. Is it worth it to use :UpdateAsync which requires the creation of a function? Another thing that came up during that discussion was that I was creating two functions and using each only once. I am wondering when I should decide not to use functions and when to use functions. You see, I was setting an index in a table to the value returned by the functions and I felt that a function was easier. Here is the script:

local function saveData(player, retryCompatible)
    local dataStoreService = game:GetService("DataStoreService")
    local mainDataStore = dataStoreService:GetDataStore("generic")
    local function createTableOfNames(objectList)
        local newTable = {}
        for i,v in pairs(objectList:GetChildren()) do
            table.insert(newTable, v.Name)
        end
        return newTable
    end
    local function findEquipedTool(starterGear)
        local starterGearList = starterGear:GetChildren()
        if #starterGearList > 1 then
            return false
        else
            for i,v in pairs(starterGear:GetChildren()) do
                return v.Name
            end
        end
    end
    local replicatedStorage = game:GetSErvice("ReplicatedStorage")
    local stats = replicatedStorage.Stats
    local playerData = stats:FindFirstChild(player.Name)
    local purchasedItems = playerData.PurchasedItems
    local spaceCoins = playerData.SpaceCoins
    local snow = playerData.Snow
    local starterStuff = player.StarterGear
    local equippedTool = findEquipedTool(starterStuff)
    local listToSave = {}
    local specialKey = "User-"..player.UserId
    listToSave["Equipped"] = equippedTool
    listToSave[purchasedItems.Name] = createTableOfNames(purchasedItems:GetChildren())
    listToSave[spaceCoins.Name] = spaceCoins.Value
    listToSave[snow.Name] = snow.Value
    local success, message = pcall(
        mainDataStore.SetAsync,
        specialKey,
        listToSave
    )
    if not success and retryCompatible then
        local maxRetryAttempts = 3
        local retryAttempts = 0
        repeat
            wait(5)
            local success, message = pcall(
                mainDataStore.SetAsync,
                mainDataStore,
                specialKey, 
                listToSave
            )
            retryAttempts = retryAttempts + 1
        until retryAttempts == maxRetryAttempts or success
    end
end
return saveData

I am wondering if I should use :UpdateAsync in the areas where :SetAsync is being used. Also, you can see the two functions I create that I only use once each. I would appreciate any insight you guys may have. Thanks!

0
This is also just a general question about the convention of using functions. User#21908 42 — 5y
0
please UpdateAsync erhggg User#19524 175 — 5y
1
Don't arbitrarily use Update it has a purpose. It is not better, it is different! gullet 471 — 5y

2 answers

Log in to vote
4
Answered by
gullet 471 Moderation Voter
5 years ago
Edited 5 years ago

They have different purposes, if you just need to set a value then use Set if you need a function to update a value then use Update. If there are several servers writing to the same key you most likely don't want values to overwrite each other, hence update. If it's updating the cash value of a player for example, it doesn't matter what was there before, then set.

Update: Lets look at two scenarios

Scenario #1 We have a player in our server that has cash and purchased something during the game, we got his cash when he joined, no other server is editing his cash value and the current server knows exactly what it should be, when he leaves it doesn't matter what the old value in the datastore is, because we got it before and nothing else would affect it. When they leave we use Set.

Scenario #2 I have a list of unique names that records in what order the first time a player joined our game is. At the moment it looks like this [noob, gullet]. Then someone joins Server#1 and this is his first time playing. So to update the list we need to know what the list looks like so far, so we get the list. Then a split second later someone joins Server#2 also for their first time. So Server#2 gets the list so it can update it. Server#1 adds builderman to the list, in Server#1 it now looks like [noob, gullet, builderman] and it Sets the list to the datastore. Then Server#2 adds guest to the list he got and it now looks like [noob, gullet, guest]. He then Sets the list to the datastore.

The datastore now has a value of [noob, gullet, guest] because that's what was last set, and builderman was lost because Server#1 didn't set the list fast enough before Server#2 needed to get it.

To fix this we instead use Update which can queue functions to be performed on the saved value, if we have a function that appends a name to the list, we don't need to get it to do the calculation on either server they can both send their function to add a certain name and the one that reaches it first will add it first but they will never cancel each other out.

0
Not really the answer I was looking for. Especially because I care more about the function part of the matter. User#21908 42 — 5y
1
What do you mean? In some cases you need a function because you can never be sure you have the latest data when calculating the new one and if you're overwriting or not, then you need a function that can be queued. In set you don't need to send a function because in the scenario in which you would use it you can safely calculate the data. gullet 471 — 5y
0
The element of my question focusing on the usage of functions. As in, when is a good time to say, "oh, I guess I don't need a function here." User#21908 42 — 5y
0
Or "oh, I really should have a function here" although I know a little more about when to use a function. I am more interested in the when to not use a function part of it User#21908 42 — 5y
View all comments (8 more)
0
If you're talking about functions in general it's always good code design to make any repeating code or code that does a certain task a function. gullet 471 — 5y
0
I just said I know more about when to use a function. The main thing I am interested in is when not to use a function. Should I use update async when I don't need the old value, and what is good function convention in general surrounding little to no usage of those created functions? User#21908 42 — 5y
1
If you know when to use a function then when not to use a function would be the inverse of that. If it doesn't matter what was in the datastore before setting the new value, use set not update. I'll update my post with an example. If a function is not used then I'd say it's useless. gullet 471 — 5y
0
posted my update gullet 471 — 5y
0
Final comment, if I created those two functions and used them each once, was it worth it to create them? User#21908 42 — 5y
0
Yes because they had to be created to avoid the overwriting collisions, this doesn't really relate to when you should use functions in general. Here they are needed for a purpose, not for code style. gullet 471 — 5y
0
Ok thanks for the help! User#21908 42 — 5y
0
This is an excellent answer User#21908 42 — 5y
Ad
Log in to vote
-3
Answered by 5 years ago

I don't know, but you can make a table save itself by using any of them even if you mix them in your script.

Answer this question