local DataSegment = {}
DataSegment.__index = DataSegment
local DataStoreService = game:GetService('DataStoreService')
local HttpService = game:GetService('HttpService')
function DataSegment.create(name: string)
local Segment = {}
Segment.Name = name
Segment.DataStore = DataStoreService:GetDataStore(name)
Segment.DataVersion = 1
Segment.KeyPrefix = ''
Segment.Debug = true
setmetatable(Segment, DataSegment)
return Segment
end
function DataSegment:Save(Player: Player, Data: any)
local FormattedData = HttpService:JSONEncode({
Data = Data,
DataVersion = self.DataVersion
})
local Tries = 0
if self.Debug then
print('['..self.Name..'/Save] Saving data for '..Player.Name)
end
local function Save(Player, TargetData)
local success, res = pcall(function()
self.DataStore:SetAsync(self.KeyPrefix..Player.UserId, TargetData)
end)
if not success then
warn('Cannot save to DataSegment '..self.Name..': '..res)
Tries += 1
if Tries < 5 then
task.wait(1)
Save(Player, TargetData)
else
warn('Reached maximum attempts saving to DataSegment '..self.Name)
return
end
else
Tries = 0
end
end
Save(Player, FormattedData)
end
function DataSegment:Get(Player: Player): any?
local Tries = 0
local function Get(TargetPlayer)
if self.Debug then
print('['..self.Name..'/Get] Getting data for '..TargetPlayer.Name)
end
local Data
local success, res = pcall(function()
Data = self.DataStore:GetAsync(self.KeyPrefix..TargetPlayer.UserId)
end)
if not success then
warn('Cannot get from DataSegment '..self.Name..': '..res)
Tries += 1
if Tries < 5 then
task.wait(1)
Get(TargetPlayer)
else
warn('Reached maximum attempts getting from DataSegment '..self.Name)
return
end
else
if Data then
return HttpService:JSONDecode(Data)
else
return
end
end
end
local Data = Get(Player)
return Data
end
return DataSegment
You definitely do not need OOP for the data module itself. I’d say OOP can be used for individual units of the same thing such as NPCs, houses, tycoon plots, pets, cars, weapons, etc.
Let’s say you have a class for every car in your game. They are all under the same class and have the same attributes but different values. Each car has an attribute of “Owner” and each one has a different owner. OOP would be more practical here than the functional approach.
In your case, you’re using OOP correctly but not exactly for the right purpose. I’d still say its a good first implementation of OOP though.
Just to add, the OOP structure I work with is this:
local House = {}
function House.new() -- Its common to name the constructor function "new"
local self = setmetatable({
-- attributes
Owner = nil,
Price = 400,
Furniture = {}
}, House)
return self
end
-- other methods in between
function House:Destroy()
-- cleanup (reset the house)
-- destroying the class:
setmetatable(self, nil)
self = nil
end
House.__index = House
return House
it’s a superclass or DataStore instance, and created with custom service DataStoreExtended.new(name: string)
edit :
it has automatic retrying and versioning
edit 2 :
i use oop in this non required module cuz I was a java dev and my brain makes me do this with OOP for practice and I like OOP
edit 3 (i can’t remember all details srry)
this module is the internal class, which is created by DataStoreExtended.new(name: string), following the .new convention
The thing is, why should you use OOP to maintain data store? it’s part of the game that can be handled by normal modules&functions, OOP is great for Objects that require invidual maintanance
In your case, this is overcomplication, data store doesn’t require anything invidual object related, it’s simply setting table to a key, before taking on OOP aproach, think about when and why i use this thing in my game, data store have only 2 principles, being saved and then loaded, no need for aditional objects
Also, good tip: avoid repeating requests! roblox do it automatically for you, this is why you should implement autosave and use update async instead of this old practice