Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

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

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!

4 comments

0

This is also just a general question about the convention of using functions.

0

please UpdateAsync erhggg

1

Don't arbitrarily use Update it has a purpose. It is not better, it is different!

2 answers

✓ Accepted answer

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.

12 comments

0

Not really the answer I was looking for. Especially because I care more about the function part of the matter.

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.

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."

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

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.

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?

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.

0

posted my update

0

Final comment, if I created those two functions and used them each once, was it worth it to create them?

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.

0

Ok thanks for the help!

0

This is an excellent answer

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.

This discussion is preserved as it was. New answers, comments, and votes are closed.