#how to prevent spagetti code
1 messages Β· Page 1 of 1 (latest)
Here is an AI assisted attempt to answer your question π€. Maybe it helps! In any case, a human is on the way π. To continue talking to the AI, you can use </chatgpt:1108714622413963314>.
To prevent spaghetti code, especially in a large Minecraft plugin, focus on clean architecture and code organization:
-
Modularize Your Code: Break down your plugin into smaller, well-defined classes and packages. Each class should have a single responsibility (Single Responsibility Principle).
-
Use Design Patterns: Patterns like Command (for handling commands), Listener (for events), and Factory (for object creation) can give structure.
-
Separate Concerns: Keep your game logic, data management, and command handling in separate layers.
-
Consistent Naming & Conventions: Follow consistent naming conventions to make your code easier to navigate.
-
Avoid Large Methods: Refactor long methods into smaller ones that perform one specific task.
-
Use Interfaces and Abstractions: This helps make your code more flexible and testable.
-
Documentation and Comments: Maintain clear comments, and consider adding a README or architecture overview.
Remember, refactoring incrementally works best for large existing projects. Analyze the parts that cause the most confusion or bugs first.
Useful links:
How can i structure the project better
not really tbh
but i just have a lot of classes and packages in packages
cuz the project is getting really big
hmm idk
just don't do more deep than 3 package deep
something arround 100 i think
make your classes do 1 thing with a small surface interface
yea i dont really use interfaces a lot yet
i think i understand what it does but not the use case for it yet
no not really
i vibe coded a lot too
but i started learning how to code more
and i wanna stop
the code is old tbh
cuz the project i made was old and since then i learned al ot
i wanna start all over again
the code has al ot of bugs too and i can do it a lot better now
spigot plugin?
ok
but i use some paper import things
what dod you have right now?
atm and phone system
and some other htings
but those are the biggest things ig
phone system integrates with simplevoicechat etc
your main plugin should look like this
@NullMarked
public class MainPlugin extends JavaPlugin {
public void registerCommands(ReloadableRegistrarEvent<Commands> commands) {
commands.registrar().register(FlySpeedCommand.build(this));
commands.registrar().register(BuildCommand.build(this));
}
@Override
public void onEnable() {
var manager = Bukkit.getPluginManager();
for (var event : eventsToRegister()) {
manager.registerEvents(event, this);
}
this.getLifecycleManager().registerEventHandler(LifecycleEvents.COMMANDS, this::registerCommands);
}
private List<Listener> eventsToRegister() {
List<Listener> events = new ArrayList<>(7);
events.add(new PlayerJoined(this));
events.add(new ServerListPing(this));
events.add(AsyncPlayerChat.configured(this));
events.add(new PlayerDeathAndRespawn(this));
events.add(new PlayerFish(this));
events.add(new PlayerAutoRegen(this));
events.add(new RemoveCreeper(this));
return events;
}
}
just a simple place to link it all
how to prevent spagetti code
experience
theres no magic formula to it
its what differentiates the junior from the senior
its pure experience
okay thx
yea i have different functions to initialise certain stuff
for example listeners
etc
the more u code, the more u know how to code something in a particular situation in the best way, so to speak
public record ServerListPing(JavaPlugin plugin) implements Listener {
public ServerListPing {
plugin.getLogger().info("ServerListPing");
}
@EventHandler
public void onEvent(PaperServerListPingEvent event) {
int numPlayer = Math.max(event.getNumPlayers(), 0);
event.setNumPlayers(numPlayer);
event.setMaxPlayers(100);
event.motd(Component.text("Β§aWelcome to the server!"));
}
}
example listener
why do you add the listeners to an array?
this is a small part of my main class π
I uploaded your attachments as Gist. This makes them more accessible, for example to mobile users.
but i got a lot more experience now
because it allow me later on to have subpackage with a group of listener that work together
then I would just include it all later with addall
many feature require multiple listeners to make work
true
do you have an example?
would you recommend to make a lot of small plugins or 1 big one
cuz the code is seperated then but at the same time i need to manage multiple build.gradles
and i can't access the classes as easy
I just make module with each feature
then make a module in which I include all feature I need
i had a system where the phone should always be in the left slot you weren't allowed to drop it put it in your offhand etc
i had multiple listeners for that too
yes, so I would make a package
different class for each part of the system
then just plug them all in the register
okay i had a gui system in my old plugin and a lot of classes needed it cuz i could make really ez guis with it i should make a package for that too right?
events.addAll(Atm.listeners(this));
something like this
Then I would just add it all in it
yes
group it
and make it 1 thing
then make small method that take max 3-4 parameters and give you a gui all built
some factory methods
the goal is to only use these factory methods elsewhere in other package
huh i see a really weird system now too my plugin extended the gui class π
it become your public api in the rest of the code
and i had a lot of gui's that isn't good right?
no the container gui
it is basically a chest
wait i can send a screen
wow, this look complicated a lot xD
you know dialogs exist?
no im not using dialog
ok
yeah I get it
i extended safegui (the system)
safegui removes your inv when you open it
and restores it when you close it
so it use a plugin?
ok
nice
looks a bit fat now
thank u π
so the system is good but isn't it weird that it extends a class? to make the gui
i prob should use parameters right?
or not idk
π
im confused
not really
it is a bit early too first thing i went to do is made this qusetion
it is a choice
okay
yea okay i realise minecraft extends Screen too for screens (this is mc modding tho)
so that isn't smth weird to do
okay i prob just gotta go start with it
gotta go eat first
okay im done eating
one small question now π
i first wanna make the atm
should i just make a package called GUI then
sure
and put there the gui class in?
and do you recommend a lot of small plugins and then an api
or 1 big one
1 big one that you setup as you want if the plugin is just for your server
if it is for others, lots of small one with configuration
it is 1 big one
but im planning on that it's gonna be a really big server
with a big plugin
but just for you?
yea
1 big is good
yes
it point to spaghetti
im not really gonna turn it into a object
yes
thx
you never need them
true
the problem with static attributes is that it is like a cheat code when you start programming.
but it is a lie.
it is like glue
it make it impossible later to change anything.
and making a object isn't that hard π
but it isn't always bad right
otherwise it wouldn't be a thing π
i made a voicechanger mod for simplevoicechat
i used static there
it was fine ig
package dev.griekseei.simplevoicechanger.config;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import net.fabricmc.loader.api.FabricLoader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class Config {
public static final Config CONFIG = new Config();
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
public static final Path CONFIG_PATH = FabricLoader.getInstance().getConfigDir().resolve("simplevoicechanger.json");
public boolean enabled = true;
public float pitchAmount = 1.0f;
public static void load() {
if (Files.exists(Config.CONFIG_PATH)) {
try {
String json = Files.readString(CONFIG_PATH);
Config loaded = GSON.fromJson(json, Config.class);
CONFIG.enabled = loaded.enabled;
CONFIG.pitchAmount = loaded.pitchAmount;
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void save() {
try {
String json = GSON.toJson(CONFIG);
Files.writeString(CONFIG_PATH, json);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Detected code, here are some useful tools:
package dev.griekseei.simplevoicechanger.config;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import net.fabricmc.loader.api.FabricLoader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class Config {
public static final Config CONFIG = new Config();
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
public static final Path CONFIG_PATH = FabricLoader.getInstance().getConfigDir().resolve("simplevoicechanger.json");
public boolean enabled = true;
public float pitchAmount = 1.0f;
public static void load() {
if (Files.exists(Config.CONFIG_PATH)) {
try {
String json = Files.readString(CONFIG_PATH);
Config loaded = GSON.fromJson(json, Config.class );
CONFIG.enabled = loaded.enabled;
CONFIG.pitchAmount = loaded.pitchAmount;
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void save() {
try {
String json = GSON.toJson(CONFIG);
Files.writeString(CONFIG_PATH, json);
} catch (IOException e) {
e.printStackTrace();
}
}
}
no π
was a really small mod
but getting the values was really ez Config.CONFIG.pitchAmount
just create it when needed.
yes, easy was a lie
but there is only 1 config
so why would i need multiple objects
so yall never use static?
just use 1 object
how can i access that 1 object in other classes
then
if it isn't static
well give them?
or make the structure public
save(Gson gson)
or make the save not in the config class
how would i give it then π
isn't it logical to put it into the config class?
not really
π
you could just have another class that save/load config class/other class
yea ig it could be seperate but it wasn't relaly an issue tbh