How to Write Professional Code

In fact, luau has encapsulation (metamethods + typing), you just need to be able to do it. For private fields, there are metamethods __index and __newindex, for public fields, there are attributes (or function arguments). By the way, this is easier to do with the separation of logic:

--!strict
local Class = {}
local ClassMeta = {}
ClassMeta.__index = function(self, key)
	if key == "B" then
		error("Handle error")
	else
		return Class[key]
	end
end
ClassMeta.__newindex = function(self, key, value)
	if key == "B" then
		error("Handle error")
	else
		rawset(self, key, value)
	end
end

function Class:GetA()
	return self.A
end

function Class:SetA(value: number)
	self.A = value
end

local _B = newproxy(true)

function Class:getB(): number
	return rawget(self, _B) :: number
end

function Class:setB(number: number): ()
	rawset(self, _B, number)
end

type ClassType = {
	A: number
} & typeof(Class)

local function new(number: number): ClassType
	local self = setmetatable({}, ClassMeta):: ClassType
	self.A = number
	rawset(self, _B, 2)

	return self
end

type Module = {
	new: (number: number) -> ClassType
}

return { new = new } :: Module

By the way, this method does not allow you to call __index cyclically, does not allow you to call a constructor from a constructor, does not break the distribution of annotations “.” and “:”

1 Like

I think they mean by default. That’s from Roblox. You definitely can use metatables to program in access rules.

1 Like

Interesting ressource. If you’re interested, something that’s also very clean and productive is to put things in a same location in a dictionary. I do mostly do this with services, and so you just have to put Services.Players to use the player service. Looks professional, and spares you from an extra “local”!

local Services = {
        ContextActionService = game:GetService("ContextActionService"),
        CollectionService = game:GetService("CollectionService")
}

Services.CollectionService:GetTagged("Lava")

It’s also an extremely simple way to have a good DRY level. Putting your services in a table often reminds me to create a variable where all my modules are located e. g.

please dont do this, just call your services manually with different variables

if you actually want to do something like this, I’d make a module for it, but it’s recommended to create a new variable with GetService at the top of the script for every service

Why? Why is it painful? You can even use the indexer if you forgot how a service’s called.

Like I am not doing this:

local l = "lava" local services = {CAS = game:GetService("ContextActionService"), CS = game:GetService("CollectionService")} services.CS:GetTagged(l)

Source? I think having one place to find every of my services is more comfortable. But it’s pretty subjective.

https://roblox.github.io/lua-style-guide/#file-structure

it is subjective but it just hurts my brain to have a table at the very top of a script ngl

Putting them under your function won’t work either lol.

Anyway, I understand. It might sound strange first, but if used correctly, this can even help sometimes.

RS is a much more commonly used service compared to the only other service that could be abbreviated with RS, which is RunService

It’s used in videos on youtube, posts on devforum and comments on discord, really anywhere, bc its abbreviation is ubiquitous and is known to be associated with ReplicatedStorage. If I see RS in code, I know it’s replicated storage and so do others. So, it doesn’t reduce any self-documentation since anyone who’s been scripting enough on Roblox should know that RS = ReplicatedStorage.

It’s one of the more special abbreviations bc so many ppl use it, maybe the only one.

If you have a variable that u wanna call RS, call it something more meaningful then bc it’s pretty safe to say that it’s not more important than ReplicatedStorage for it to be taking its well known “RS” name.

1 Like

Source:

1 Like

I agree with most of the points made here but personally I think that a casing style like snake_case or PascalCase would be better for readability. For me when I’m reading code that primarily uses camelCase I tend to skip over the first word or the entire variable like 80% of the time which can cause some amount of confusion, but with snake_case each word is very clearly separated and imo much easier to read. Overall though good advice :+1:

According to the naming convention, you should not abbreviate class names. And even more so those classes that need to be allocated (services/singletons)

don’t do comments like this, it looks terrible

1 Like

yes but thats nausea inducing. Just use the underscores at that point :skull:

one naming convention vs another. And I’m only talking about RS in particular, as it’s always used.

Abbreviating variables makes it generally harder to understand your code and you gain next to nothing from doing it. Its a lot easier to understand code with variables which aren’t shortened down to one to three letters, especially for newer scripters trying to learn.

if u know how and when to abbreviate, there should be no trouble.

Something that I noticed, and that is actually pretty cool, is that we all got our preferences. It means that there isn’t actually a “professional” way to script stuff if it’s only aesthetics. If we had to talk about professional code, I’d be more talking about a way to code that helps.

Like, do you call a script with many comments professional? If the comments are really of a true use, like if you want to have a description for a function from another module, well, yea, I do somewhat agree. But if you comment like that:

local Workspace = game.Workspace -- This is where we're going to put the debris of the dead character

All you did is losing 30 seconds to write a comment that will helps a terribly small minority (+ this example with probably cause WW3 for some reasons). And it’s not productive. At all. Comments must only come to help if they are really needed, not to be the script’s mascara.

So, yea, if you want to publish stuff, you’re greatly advised to follow certain norms so most scripters on the internet can help you without being lost. But when it’s up to you, the most professional code is the one that allows you to be efficient.

I think comments are helpful, I personally write them to set the start of “Services”, “Strings”, etc.
But I also use comments to describe functions, which I found helpful when I’m making many functions or just to remember what the function does.

True but false at the same time, asserts, yes do catch bugs but they throw “errors”, which can stop your code functionament, I would not use them always.

The best way to remember what a function does is to give it a descriptive name. Your code should comment itself.

Also the whole point of an assert is to crash your program or in Roblox, throw and error. This is because if an assert is trigger, it means there is a bug in your code, it’s to help you catch bugs quickly.

That’s just an opinion. Countless developers use other programs like just simply Studios in general. I think it’s a personal preference and the scale of the project you’re working on.