Introduction
Organise Roblox code by feature, not by where it runs.
A bad folder structure slows development. Remembering where the related pieces are increases cognitive load. And finding files wastes time.
The Problem: Technical Grouping
Most Roblox codebases group files by what kind of code they are, not by what they're about. That's technical grouping, and it comes in two forms:
- By type: folders for each technical role, such as
Controllers,ServicesandUtils. Codebases in every industry do this, and it's a well-known anti-pattern. - By runtime, at the root:
server,clientandsharedfolders at the top of the tree. Rojo maps folders one-to-one onto instances, so Roblox tooling forces this form on you. This is the one Rogen removes.
Either way, one feature is spread across the whole tree. Updating an Inventory system means searching three folders for its pieces, and deleting it means finding all of them.
This was named as a mistake in 1972. David Parnas argued that modules should hide design decisions, not follow the order the program runs in:
Since, in most cases, design decisions transcend time of execution, modules will not correspond to steps in the processing.
— D. L. Parnas, On the Criteria To Be Used in Decomposing Systems into Modules (1972)
On Roblox, where code runs is that step. A feature has server, client and shared code, so the feature is the module, and where each piece runs is a detail inside it.
The Solution: Package by Feature
Keep all the code for one feature (client, server and shared) in a single feature folder, named after what it does in your game. This is package by feature. Domain-driven design gives the same advice: name modules after the concepts of your domain (Trading, Quests), not after technical roles.
Rogen reads the folder layout and the file names, and generates a Rojo project file that places every script in the Roblox service where it needs to run. Rogen doesn't sync anything itself: Rojo or Argon reads the generated project file and syncs the files into Roblox Studio.
The routes in the config say where each kind of code goes:
{
"routes": {
"Server": "ServerScriptService",
"Client": "StarterPlayer/StarterPlayerScripts",
"Shared": "ReplicatedStorage/Shared",
"*": "ReplicatedStorage/Shared"
}
}The Result: Developers maintain a clean repository, while Roblox Studio receives the scripts in the right containers.
Feature folders are a starting point, not the only option. Layers are fine too, as long as dependencies point one way and each layer is organised by feature. Architectures compares the layouts that work well with Rogen.