How is my first OOP module?

For data store module of mine

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
2 Likes

I’m OOPtimistic: as long as it works, it’s a great start. You have a couple of OOPortunities for improving it. For example,

local Segment = {} -- Replace this with this:
local self = setmetatable({},DataSegment)
2 Likes

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
1 Like

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

2 Likes