Loading...
Loading...
Compare original and translation side by side
-- PascalCase: Types, Classes, Services, Modules
type PlayerData = { ... }
local ShopService = {}
local PlayerController = require(...)
-- camelCase: Variables, functions, methods
local playerCount = 0
local function getPlayerData() end
function ShopService:purchaseItem() end
-- SCREAMING_SNAKE_CASE: Constants
local MAX_PLAYERS = 50
local DEFAULT_HEALTH = 100
-- Private with underscore prefix
local function _validateInput() end
local _cache = {}-- PascalCase:类型、类、服务、模块
type PlayerData = { ... }
local ShopService = {}
local PlayerController = require(...)
-- camelCase:变量、函数、方法
local playerCount = 0
local function getPlayerData() end
function ShopService:purchaseItem() end
-- SCREAMING_SNAKE_CASE:常量
local MAX_PLAYERS = 50
local DEFAULT_HEALTH = 100
-- 以下划线开头表示私有
local function _validateInput() end
local _cache = {}--!strict
-- 1. Services/imports at top
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Signal = require(ReplicatedStorage.Packages.Signal)
local Types = require(script.Parent.Types)
-- 2. Constants
local MAX_RETRIES = 3
local TIMEOUT = 5
-- 3. Types
type Config = {
enabled: boolean,
maxItems: number,
}
-- 4. Module table
local MyModule = {}
-- 5. Private state
local _initialized = false
local _cache: { [string]: any } = {}
-- 6. Private functions
local function _helperFunction()
end
-- 7. Public API
function MyModule.init()
end
function MyModule.doSomething()
end
-- 8. Return
return MyModule--!strict
-- 1. 服务/导入放在顶部
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Signal = require(ReplicatedStorage.Packages.Signal)
local Types = require(script.Parent.Types)
-- 2. 常量定义
local MAX_RETRIES = 3
local TIMEOUT = 5
-- 3. 类型定义
type Config = {
enabled: boolean,
maxItems: number,
}
-- 4. 模块表
local MyModule = {}
-- 5. 私有状态
local _initialized = false
local _cache: { [string]: any } = {}
-- 6. 私有函数
local function _helperFunction()
end
-- 7. 公开API
function MyModule.init()
end
function MyModule.doSomething()
end
-- 8. 返回模块
return MyModule--!strict
local MyService = {}
local _started = false
function MyService:Start()
assert(not _started, "MyService already started")
_started = true
-- Initialize connections, load data
end
function MyService:Stop()
-- Cleanup for hot-reloading
end
return MyService--!strict
local MyService = {}
local _started = false
function MyService:Start()
assert(not _started, "MyService already started")
_started = true
-- 初始化连接、加载数据
end
function MyService:Stop()
-- 热重载时的清理逻辑
end
return MyService--!strict
local MyController = {}
local _player = game:GetService("Players").LocalPlayer
function MyController:Init()
-- Setup without yielding
end
function MyController:Start()
-- Connect events, start loops
end
return MyController--!strict
local MyController = {}
local _player = game:GetService("Players").LocalPlayer
function MyController:Init()
-- 无阻塞初始化
end
function MyController:Start()
-- 连接事件、启动循环
end
return MyControllerlocal _data: PlayerData? = nil
local function getData(): PlayerData
if not _data then
_data = loadExpensiveData()
end
return _data
endlocal _data: PlayerData? = nil
local function getData(): PlayerData
if not _data then
_data = loadExpensiveData()
end
return _data
end-- DataStore, HTTP, any Roblox API that can fail
local success, result = pcall(function()
return dataStore:GetAsync(key)
end)
if not success then
warn("DataStore failed:", result)
return nil
end
return result-- DataStore、HTTP、任何可能失败的Roblox API
local success, result = pcall(function()
return dataStore:GetAsync(key)
end)
if not success then
warn("DataStore failed:", result)
return nil
end
return resulttype Result<T> =
{ ok: true, value: T } |
{ ok: false, error: string }
local function fetchData(id: string): Result<Data>
local success, data = pcall(function()
return dataStore:GetAsync(id)
end)
if not success then
return { ok = false, error = tostring(data) }
end
return { ok = true, value = data }
endtype Result<T> =
{ ok: true, value: T } |
{ ok: false, error: string }
local function fetchData(id: string): Result<Data>
local success, data = pcall(function()
return dataStore:GetAsync(id)
end)
if not success then
return { ok = false, error = tostring(data) }
end
return { ok = true, value = data }
end-- Use assert for things that should never happen
function processPlayer(player: Player)
assert(player, "player is required")
assert(player:IsA("Player"), "expected Player instance")
-- ...
end-- 对绝不应该发生的情况使用assert
function processPlayer(player: Player)
assert(player, "player is required")
assert(player:IsA("Player"), "expected Player instance")
-- ...
endlocal connection: RBXScriptConnection
connection = event:Connect(function()
-- handler
end)
-- Later, cleanup:
connection:Disconnect()local connection: RBXScriptConnection
connection = event:Connect(function()
-- 事件处理逻辑
end)
-- 后续清理:
connection:Disconnect()local Maid = require(Packages.Maid)
local maid = Maid.new()
maid:GiveTask(event:Connect(handler))
maid:GiveTask(instance)
maid:GiveTask(function()
-- Custom cleanup
end)
-- Cleanup everything at once
maid:Destroy()local Maid = require(Packages.Maid)
local maid = Maid.new()
maid:GiveTask(event:Connect(handler))
maid:GiveTask(instance)
maid:GiveTask(function()
-- 自定义清理逻辑
end)
-- 一次性清理所有资源
maid:Destroy()local cache = setmetatable({}, { __mode = "v" })
-- Values are garbage collected when no other references exist
cache[key] = expensiveObjectlocal cache = setmetatable({}, { __mode = "v" })
-- 当没有其他引用时,值会被垃圾回收
cache[key] = expensiveObject-- BAD: Client tells server what happened
RemoteEvent.OnServerEvent:Connect(function(player, damage)
target.Health -= damage -- Client controls damage!
end)
-- GOOD: Server calculates everything
RemoteEvent.OnServerEvent:Connect(function(player, targetId)
local target = getValidTarget(player, targetId)
if not target then return end
local damage = calculateDamage(player) -- Server calculates
target.Health -= damage
end)-- 错误示例:客户端告知服务器发生了什么
RemoteEvent.OnServerEvent:Connect(function(player, damage)
target.Health -= damage -- 客户端可以随意控制伤害!
end)
-- 正确示例:服务器负责所有计算
RemoteEvent.OnServerEvent:Connect(function(player, targetId)
local target = getValidTarget(player, targetId)
if not target then return end
local damage = calculateDamage(player) -- 服务器计算伤害
target.Health -= damage
end)RemoteFunction.OnServerInvoke = function(player, itemId, quantity)
-- Type validation
if typeof(itemId) ~= "string" then return end
if typeof(quantity) ~= "number" then return end
-- Range validation
if quantity < 1 or quantity > 99 then return end
if quantity ~= math.floor(quantity) then return end
-- Business logic validation
if not Items[itemId] then return end
if not canAfford(player, itemId, quantity) then return end
-- Now safe to process
return purchaseItem(player, itemId, quantity)
endRemoteFunction.OnServerInvoke = function(player, itemId, quantity)
-- 类型验证
if typeof(itemId) ~= "string" then return end
if typeof(quantity) ~= "number" then return end
-- 范围验证
if quantity < 1 or quantity > 99 then return end
if quantity ~= math.floor(quantity) then return end
-- 业务逻辑验证
if not Items[itemId] then return end
if not canAfford(player, itemId, quantity) then return end
-- 此时处理请求是安全的
return purchaseItem(player, itemId, quantity)
end)local lastAction: { [Player]: number } = {}
local COOLDOWN = 0.5
local function isRateLimited(player: Player): boolean
local now = os.clock()
local last = lastAction[player] or 0
if now - last < COOLDOWN then
return true
end
lastAction[player] = now
return false
endlocal lastAction: { [Player]: number } = {}
local COOLDOWN = 0.5
local function isRateLimited(player: Player): boolean
local now = os.clock()
local last = lastAction[player] or 0
if now - last < COOLDOWN then
return true
end
lastAction[player] = now
return false
end-- Using wait() - use task.wait()
wait(1) -- BAD
task.wait(1) -- GOOD
-- spawn() - use task.spawn()
spawn(fn) -- BAD
task.spawn(fn) -- GOOD
-- delay() - use task.delay()
delay(1, fn) -- BAD
task.delay(1, fn) -- GOOD
-- Polling when events exist
while true do
if something then break end
task.wait()
end
-- GOOD: Use events/signals instead
-- String concatenation in loops
local s = ""
for i = 1, 1000 do
s = s .. tostring(i) -- O(n²)
end
-- GOOD: Use table.concat
-- FindFirstChild chains
workspace.Folder.SubFolder.Part -- Errors if missing
-- GOOD: Safe navigation
local folder = workspace:FindFirstChild("Folder")
local part = folder and folder:FindFirstChild("SubFolder")
and folder.SubFolder:FindFirstChild("Part")-- 使用wait() - 改用task.wait()
wait(1) -- 错误用法
task.wait(1) -- 正确用法
-- spawn() - 改用task.spawn()
spawn(fn) -- 错误用法
task.spawn(fn) -- 正确用法
-- delay() - 改用task.delay()
delay(1, fn) -- 错误用法
task.delay(1, fn) -- 正确用法
-- 已有事件时仍使用轮询
while true do
if something then break end
task.wait()
end
-- 正确用法:使用事件/信号替代
-- 循环中拼接字符串
local s = ""
for i = 1, 1000 do
s = s .. tostring(i) -- 时间复杂度O(n²)
end
-- 正确用法:使用table.concat
-- 链式调用FindFirstChild
workspace.Folder.SubFolder.Part -- 若中间节点不存在会报错
-- 正确用法:安全导航
local folder = workspace:FindFirstChild("Folder")
local part = folder and folder:FindFirstChild("SubFolder")
and folder.SubFolder:FindFirstChild("Part")-- Generalized iteration
for _, v in ipairs(array) do end -- OLD
for _, v in array do end -- MODERN (Luau)
-- If expressions
local x = if condition then a else b -- Clean ternary
-- Continue in loops
for _, item in items do
if not item.valid then continue end
process(item)
end
-- Optional chaining with and
local name = player and player.Character and player.Character.Name-- 通用迭代
for _, v in ipairs(array) do end -- 旧写法
for _, v in array do end -- 现代写法(Luau)
-- 条件表达式
local x = if condition then a else b -- 简洁的三元表达式
-- 循环中使用continue
for _, item in items do
if not item.valid then continue end
process(item)
end
-- 使用and进行可选链式调用
local name = player and player.Character and player.Character.Namesrc/
├── Server/
│ ├── init.server.luau # Bootstrap
│ ├── Services/ # Game services
│ │ ├── DataService.luau
│ │ └── CombatService.luau
│ └── Components/ # Server components
├── Client/
│ ├── init.client.luau # Bootstrap
│ ├── Controllers/ # Client controllers
│ └── UI/ # UI components
├── Shared/
│ ├── Types.luau # Shared type definitions
│ ├── Constants.luau # Shared constants
│ └── Util/ # Shared utilities
└── Packages/ # Wally packagessrc/
├── Server/
│ ├── init.server.luau # 启动文件
│ ├── Services/ # 游戏服务
│ │ ├── DataService.luau
│ │ └── CombatService.luau
│ └── Components/ # 服务器组件
├── Client/
│ ├── init.client.luau # 启动文件
│ ├── Controllers/ # 客户端控制器
│ └── UI/ # UI组件
├── Shared/
│ ├── Types.luau # 共享类型定义
│ ├── Constants.luau # 共享常量
│ └── Util/ # 共享工具类
└── Packages/ # Wally包| Do | Don't |
|---|---|
| |
| |
| |
| |
| Validate on server | Trust client data |
| Use types | Use |
| Disconnect events | Leave connections dangling |
| Use constants | Magic numbers/strings |
| Early return | Deep nesting |
| Small functions | 200+ line functions |
| 推荐做法 | 避免做法 |
|---|---|
| |
| |
| |
| |
| 在服务器端验证 | 信任客户端数据 |
| 使用类型定义 | 到处使用 |
| 断开事件连接 | 让连接悬空 |
| 使用常量 | 魔法数字/字符串 |
| 提前返回 | 深层嵌套 |
| 小函数 | 超过200行的函数 |