DON'T use magic-strings, use Enum/Constants instead!

Hello community :wave:

It’s me back with another tutorial for the developer community.

This Topic is specially made for new or intermediate scripters. And remember that if you use or used to use magic-strings, it doesn’t make you a bad programmer, you just didn’t know how to avoid them and didn’t know that they are a bad idea!

NOTE: By Enum or constant, I mean the same thing, by Enum I mean the same thing with a constant but with a different naming convention than constants (enums are normally used in modulescripts).


What are magic strings?

In programming, a “magic-string” is a term for those text strings that are put directly into code, for example: "i'm a string!". These strings have a special use in the code and are used to control the behavior of the program.

But what are the problems with magic-strings?

There are several problems with magic-string, one of them is that if you have written the same string many times, and you need to change it for some reason or another, you will need to change each string by hand and it is too tedious if it is a lot of code.

  • “but I can use find & replace”

That’s a good idea, but: what if the string is “local” (for example)?

This task can be very tedious if you are using a string that matches for example a LUAU keyword or the name of a function in your script. It can also make your code unscalable and unreadable, since you don’t know where that string comes from or what it means (hence the term “magic-string”, since you don’t know where it came from or what it is used for).


How can I fix this?

One way to fix this is to create your own constants or enums which contain the text string you want to use in your code, for example:

local DATABASE_PASSWORD = "ilovepizza1234" -- Our constant

local password = "wrong password" --[[ thinking "wrong password" as a dynamic value given by the user ]]

if password == DATABASE_PASSWORD then
	print("You can access the database!")
else
	warn("Nuh uh")
end

The reason for using constants/enums is to have a single “SOURCE OF TRUTH” for strings that we use throughout the code. This also helps us that in case we want to change the text string, we only need to do it in one place and it will be changed in all the code without having to do a lot of work.

What other use is there for constants/enums?

A very useful use, is to be able to use the constants/enums outside the original code to, for example, pass them as parameters to functions or to use them in different scripts, for example, let’s say we have a modulescript in ReplicatedStorage called “DatabaseEnums” which contains constants (or enums, whatever you want to call them) that are used inside another script.

-- DatabaseEnums.lua
local DatabaseEnums = {}

DatabaseEnums.DatabaseKey = "random key"
DatabaseEnums.DatabasePassword = "bla bla bla" 

return DatabaseEnums

-- Database.lua
local Enums = require(DatabaseEnums-path)

local function LogInDatabase(password: string)
    if password == Enums.DatabasePassword then
        print("Logged in!")
    else
        warn("nuh uh")
    end
end

LogInDatabase("hi") --  nuh uh

This is very useful in case we have many strings that we use in our script to change its flow or behavior, the code becomes more understandable and you avoid having the problems previously mentioned.


Did you use or know about magic-strings?

  • Yes
  • No

0 voters

If you didn’t understand something, you can ask me for help in the comments and I’ll help you!

15 Likes

ctrl + shift + r in question (/J NO DISRESPECT INTENDED)

nice tutorial

3 Likes

its Ctrl + H, but yeah i get it lol

2 Likes

He talks about find and replace in the guide. And I was talking about variables for some reason instead of strings
image

4 Likes

Ohh you’re right lol, i still do it the old way

1 Like

A better way would be to use string literal types to annotate what a string could be. This way you don’t need to add any runtime checks because you get warned about possible mistakes while editing.

local function GetResult(): "Yes" | "No"
	if math.random(1, 2) == 1 then
		return "Yes"
	end
	
	return "No"
end

if GetResult() == "Maybe" then -- Nope! Can't be "Maybe"
	print("Never Happens")
end
5 Likes

As someone mentioned above, I think the advice is good, but enums are typically numbers. You could use them for this case, but string literals would be better, and Roblox Staff seems to say the same as well.

1 Like

I know what this is, but I’ve never heard someone call it “magic-strings” lol. Great explanation!

3 Likes

Magic strings really are just use case specific

also, you can still use find and replace as long as you keep your string syntax consistent if you use quotations
image

plus, string literals give you a lot more power when it comes to typing

as an example, function overloads!
image

image

image

4 Likes

As for typing and type aliases, it is the only way to create singleton-types, but I understand your point, but remember that this topic talks about what magic-strings are and why they should be avoided as much as possible, but I understand your point, thanks for commenting!

1 Like

oh sorry, I see what you mean about magic strings now, and I wholeheartedly agree! They are like functions, if you can share just one value instead of a bunch of values its easier to manage!

I didn’t know what they were called and just thought you just meant any string you use in code.
like here

Instance.new("part")
--             ^^
--[[
I thought something like this would be a magic string
because it's put directly in the code and it changes how it works
]]--
2 Likes

Such uses of strings are totally correct, they should be avoided only when we are using them to control the flow or behavior of our scripts, but when passing them as a parameter, for example to Instance.new, there is no problem :happy4:

1 Like

One of the “I was today years old” type of posts. I always noticed this glaring urge when I was first programming and felt like I was doing some poor design by introducing magic-strings.

I’d be curious to learn about many of the other pattern names we may have coincidentally or accidentally ran into. Dependency injection was one for me.

3 Likes