Programming Rules
Here are a list of programming rules which I think are good practices. These rules are designed to help you write code that is:
- Memory Safe
- Is readable, debug-gable, and can be understood by other developers
- Avoid your game from breaking in production to ensure a smooth player experience.
Why you ask?
Well I believe that these practices will help players stay longer and be more accessible to a wide range of devices (this is more for stability so having well designed UI and Controls for different devices is important too).
This is going to give you more favourable data to the Roblox recommendation algorithm meaning your game in theory should be more successful.
1. Bound all loops
Ensure every loop has a predictable exit. Use counters or table limitsâno infinite loops.
2. Limit function size
Keep functions short and focusedâideally under 60 lines. Split logic into helpers.
local persistence = {}
âBad
local function savePlrData(player: Player)
âover 60 lines of code lots to read through to understand everything it is doing.
end
âGood
local function getPlrIdFromPlrInst(player: Player)
local playerId = player.PlayerId
return playerId
end
local function getPlotFromPlrId(playerId: integer)
end
local function serializePlrPlot(playerId: integer)
end
function persistence.savePlrData(player: Player)
local playerId = getPlrIdFromPlrInst(player)
local plot = getPlotFromPlrId(playerId)
local plotData = serializePlrPlot(plot)
return success
end
return persistence
3. Use assertions and warnings
Use assert() or warn() to catch unexpected values or states early.
4. Minimize variable scope
Prefer local variables. Avoid polluting the global environment or using shared state unnecessarily.
5. Always handle return values
Check results from functions like pcall, FindFirstChild, or HttpService:RequestAsync.
6. Limit use of references and pointers
Avoid complex table references or circular structures unless absolutely necessary.
-- Bad
local table = {}
table.self = table -- circular reference
7. Always sanitize input to prevent unexpected data
Validate all inputs to functions, methods, and remote events.
Enforce type checks, value ranges, and fallback defaults to guard against malformed or malicious data.
8. Manage event connections to avoid leaks
Track every :Connect return value, store it with the owning object, and disconnect in Destroying, AncestryChanged, or explicit Destroy() paths. Clear tables after disconnecting so long-lived services donât retain dead UI or model references.
This will prevent memory leaks which can cause your game to crash or run badly. This is especially important if you want your game accessible to mobile platforms as a lot of devices have very low amounts of RAM to work with. Using the micro profiler can help find potential memory leaks. You can also open the dev console and select the âMemoryâ tab. Search for: LuaHeap, Instances. If the value keeps climbing and does not go down it is likely you have a memory leak.
local buttonConnection = button.MouseButton1Click:Connect(function()
print("Clicked")
end)
button.Destroying:Connect(function()
buttonConnection:Disconnect()
end)
9. APIâaccessible methods must be top level
Any function or method that is part of your moduleâs public API (i.e. intended to be called by other scripts, services, or developers) must be defined at the top level of the class or module, not inside another function or method. If you have a function or method which is publicly accessible tools like Moonwave will not be able to correctly document them. This also makes your code easier to read. This best works in practice with big teams with multiple programmers, though it is also useful for small teams or a solo dev as realistically once you have 50,000+ lines of code to maintain it becomes harder to keep track of what everything does.
10. Document every public interface
All modules, classes, and APIâaccessible methods must include clear documentation comments describing their purpose, parameters, return values, and side effects.
11. Zeroâwarning publishing policy
Before publishing your game, ensure that the Roblox Studio Output window and linter are completely free of errors and warnings. Treat warnings as bugs to fix not noise to ignore.
I will continue to improve this guide based on feedback over time and add more snippets of code when I have time.
Here are some of the rules I use. What would you add or change?