Spot the Smells: 7 Code Smells That Make Your Code Look Bad
1. Data Clump 🏋️♂️
When variables stick together like inseparable buddies
Ever find yourself passing the same group of variables around your methods? That's a data clump. It's like carrying groceries individually instead of using a basket—awkward and inefficient.
Why It's a Problem:
How to Fix It:
Apex Example:
Smelly Code:
public void setColor(Integer red, Integer green, Integer blue) {
// Set the color
}
Refactored:
public class RGB {
public Integer red;
public Integer green;
public Integer blue;
public RGB(Integer red, Integer green, Integer blue) {
this.red = red;
this.green = green;
this.blue = blue;
}
}
public void setColor(RGB color) {
// Set the color
}
By creating the RGB class, you've bundled related data together, making your code cleaner and more intuitive.
2. Flag Argument 🚩
Methods shouldn't act like switchboards
Passing a boolean to a method to determine its behavior is like giving it a split personality; it often indicates that the method is trying to do too much.
Why It's a Problem:
How to Fix It:
Apex Example:
Smelly Code:
public void sendNotification(Boolean isEmail) {
if (isEmail) {
sendEmail();
} else {
sendSMS();
}
}
Refactored:
public void sendEmailNotification() {
sendEmail();
}
public void sendSMSNotification() {
sendSMS();
}
Now, each method has a clear purpose, making your code easier to read and maintain.
3. Helper Class Code Smell 🛠
When your class is just a toolbox of unrelated utils
A helper class is often created when additional methods are needed to support existing functionality, but these methods do not quite fit within the existing class. A problem can arise when these helper classes fail to convey their intended purpose, resulting in them becoming a collection of loosely related methods. Instead of enhancing code clarity, they can make it more difficult to identify where specific logic should reside.
Why It's a Problem:
How to Fix It:
Apex Example:
Smelly Code:
public class Utils {
public static Integer add(Integer firstNumber, Integer secondNumber) {
return firstNumber + secondNumber;
}
public static Integer subtract(Integer firstNumber, Integer secondNumber) {
return firstNumber - secondNumber;
}
public void sendSMSNotification() {
sendSMS();
}
}
Refactored:
public class Calculator {
public Integer add(Integer firstNumber, Integer secondNumber) {
return firstNumber + secondNumber;
}
public Integer subtract(Integer firstNumber, Integer secondNumber) {
return firstNumber - secondNumber;
}
}
public class Notificator {
public void sendSMSNotification() {
sendSMS();
}
}
By creating Calculator and Notificator classes, you've given these methods a proper home, enhancing code organization.
4. Long Parameter List 📜
When your method signatures resemble lengthy shopping lists
Have you ever tried to juggle too many items at once? That's similar to handling methods with too many parameters. It not only makes the method difficult to comprehend, but it also heightens the likelihood of making mistakes.
Why It's a Problem:
How to Fix It:
Recommended by LinkedIn
Apex Example:
Smelly Code:
public void registerUser(String firstName, String lastName, String email, String phone, String address) {
// Registration logic
}
Refactored:
public class User {
public String firstName;
public String lastName;
public String email;
public String phone;
public String address;
// Constructor
public User(String firstName, String lastName, String email, String phone, String address) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.phone = phone;
this.address = address;
}
}
public void registerUser(User user) {
// Registration logic
}
By encapsulating user details into a User class, the registerUser method becomes cleaner and more manageable.
5. Magic Number 🎩✨
Numbers in code should be meaningful, not mysterious.
A magic number is a hardcoded numerical value without explanation, which makes the code difficult to understand and modify. These numbers are dispersed throughout the codebase, and their purpose is not immediately clear.
Why It's a Problem:
How to Fix It:
Apex Example:
Smelly Code:
Decimal discount = totalAmount * 0.15;
Refactored:
public static final Decimal DISCOUNT_RATE = 0.15;
Decimal discount = totalAmount * DISCOUNT_RATE;
By defining DISCOUNT_RATE, the purpose of 0.15 is clear, reducing confusion and improving maintainability.
6. Status Variable 🚥
Status Variables: Unnecessary Complexity
A status variable tracks state changes within a method. This often indicates that the method is taking on too many responsibilities, resulting in unclear and harder-to-maintain code.
Why It's a Problem:
How to Fix It:
Apex Example:
Smelly Code:
public Integer findFooIndex(List<String> names) {
Boolean found = false;
Integer i = 0;
while (!found && i < names.size()) {
if (names[i] == 'foo') {
found = true;
} else {
i++;
}
}
return i;
}
Refactored:
public Integer findFooIndex(List<String> names) {
for (Integer i = 0; i < names.size(); i++) {
if (names[i] == 'foo') {
return i;
}
}
return -1;
}
7. "What" Comment 📝
Comments should explain 'why,' not 'what.'
Comments that explain what the code does often suggest that the code isn't self-explanatory. Instead of relying on comments for clarity, aim to enhance the readability of the code itself.
Why It's a Problem:
How to Fix It:
Apex Example:
Smelly Code:
public class ReportGenerator {
public void runReport() {
// Creating Report
Report report = generateReport();
// Sending Report
sendReport(report);
}
}
Refactored:
public class ReportGenerator {
public void executeReport() {
Report report = createReport();
dispatchReport(report);
}
private Report createReport() {
// Logic to generate the report
}
private void dispatchReport(Report report) {
// Logic to send the report
}
}
By renaming methods and breaking down tasks into well-named functions, the code becomes self-explanatory, eliminating the need for 'what' comments.
Final Thoughts
Identifying and removing code smells is crucial for writing clean and maintainable Apex code. By tackling these common issues, you enhance the readability, debuggability, and extensibility of your codebase. Refactoring doesn't have to be a daunting task; instead, small, incremental improvements can lead to significant benefits over time. Be vigilant for these code smells, and both your future self and your teammates will appreciate your efforts! 🚀