Untangling Java, Part 2: How to Refactor Spaghetti Code (Step by Step)
Tired of Java files that look like a plate of pasta? Learn how to clean up your code without writing a single class.
Untangling Java, Part 2: How to Refactor Spaghetti Code (Step by Step)

Photo by Stephen Bedase on Unsplash
TL;DR:
If your main() method is doing all the work, you’re one feature away from chaos. In this beginner-friendly walkthrough, we break a messy Java login script into reusable, easy-to-read pieces—no frameworks or OOP required (yet).
🍝 Quick Recap from Part 1
In Part 1, we met a working Java login app that was tangled, repetitive, and hard to grow.
Here’s the spaghetti:
// SpaghettiLogin.java
public class SpaghettiLogin {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String user, pass;
System.out.println("Enter username:");
user = scanner.nextLine();
if (user.equals("admin")) {
System.out.println("Enter password:");
pass = scanner.nextLine();
if (pass.equals("1234")) {
System.out.println("Access granted.");
System.out.println("Enter new username:");
user = scanner.nextLine();
if (!user.isEmpty()) {
System.out.println("Username updated to: " + user);
} else {
System.out.println("Username can't be empty.");
}
} else {
System.out.println("Wrong password.");
}
} else {
System.out.println("User not found.");
}
}
}
It runs. But it’s:
- Hard to test
- Annoying to modify
- A nightmare to debug once it grows
Today, we clean it up.
🧼 The Refactoring Plan
You don’t need frameworks, advanced Java, or design patterns to write cleaner code. We’ll start with a few small wins:
What we’re aiming for:
- Smaller methods
- Meaningful names
- Less nesting
- Logic that’s easier to reuse, test, and read
🪓 Step-by-Step Refactor
🔹 Step 1: Extract Input & Output
We’re repeating System.out.println() and scanner.nextLine() all over the place. Let’s fix that.
public static String getInput(Scanner scanner, String prompt) {
System.out.println(prompt);
return scanner.nextLine();
}
public static void print(String message) {
System.out.println(message);
}
Why it matters: Cleaner code. Easier to change later. Want to log to a file or sanitize input? Now you only change it once.
🔹 Step 2: Handle Login Logic Separately
We’ll move the username and password checks into tiny, purpose-driven methods:
public static boolean isValidUser(String username) {
return username.equals("admin");
}
public static boolean isValidPassword(String password) {
return password.equals("1234");
}
Why it matters: Easy to test. Clear to read. If you want to switch to database validation later, you only update one place.
🔹 Step 3: Make Username Update Its Own Thing
This chunk was buried deep in the main() method before. Now, it’s isolated:
public static void updateUsername(Scanner scanner) {
String newUsername = getInput(scanner, "Enter new username:");
if (!newUsername.isEmpty()) {
print("Username updated to: " + newUsername);
} else {
print("Username can't be empty.");
}
}
Why it matters: Logic is reusable and testable. It also avoids overwriting the login username by mistake.
💻 The Clean Version: CleanLogin.java
Here’s the cleaned-up, fully refactored version:
import java.util.Scanner;
public class CleanLogin {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Clear and readable — first action: prompt for username
String username = getInput(scanner, "Enter username:");
// Separated logic — checks are done using clean helper methods
if (isValidUser(username)) {
String password = getInput(scanner, "Enter password:");
if (isValidPassword(password)) {
print("Access granted.");
// Update logic is isolated — no more deep nesting
updateUsername(scanner);
} else {
print("Wrong password.");
}
} else {
print("User not found.");
}
scanner.close();
}
// 🧹 Extracted method: handles prompting and reading input
// No repeated Scanner or println logic inside main()
public static String getInput(Scanner scanner, String prompt) {
System.out.println(prompt);
return scanner.nextLine();
}
// 🧹 Extracted method: handles printing
// If we wanted to log instead of print, change it here once
public static void print(String message) {
System.out.println(message);
}
// 🧠 Separated validation logic
// No hardcoded checks buried in if-else blocks anymore
public static boolean isValidUser(String username) {
return username.equals("admin");
}
// 🧠 Also testable and self-explanatory — follows same structure as above
public static boolean isValidPassword(String password) {
return password.equals("1234");
}
// ✨ All logic related to username update is now encapsulated here
// Clear responsibilities = no spaghetti
public static void updateUsername(Scanner scanner) {
String newUsername = getInput(scanner, "Enter new username:");
if (!newUsername.isEmpty()) {
print("Username updated to: " + newUsername);
} else {
print("Username can't be empty.");
}
}
}
🔍 What Improved?
Let’s compare:
[embed]
💡 What You Learn Here
- You don’t need OOP or frameworks to write cleaner Java.
- Breaking code into smaller, named methods = clarity.
- Your code is for humans first, machines second.
🔜 Coming Up in Part 3: Java Meets OOP
Next time, we’ll introduce a basic User class, and see how even a little object-oriented structure can help manage state, encapsulate logic, and future-proof your code.
We’ll walk through:
- Creating a
Userclass - Moving validation into it
- Connecting it with the logic we just refactored
🏁 Final Thought
Bad code runs. Good code survives change.
Clean code doesn’t mean writing fewer bugs — it means writing code that’s easier to fix, explain, and grow. That’s how you level up, one refactor at a time.
메타데이터
- post_id
- 4d6990fa27bf
- slug
- untangling-java-part-2-how-to-refactor-spaghetti-code-step-by-step-4d6990fa27bf
- url
- https://medium.com/javarevisited/untangling-java-part-2-how-to-refactor-spaghetti-code-step-by-step-4d6990fa27bf
- canonical_url
- https://medium.com/javarevisited/untangling-java-part-2-how-to-refactor-spaghetti-code-step-by-step-4d6990fa27bf
- author_url
- https://medium.com/@sourojitdas
- status
- ok
- fetched_at
- 2026-06-09 15:37:30