Writing Great Code: The Five Principles of Clean Code
Explore clean code practices such as using meaningful names and focused functions, avoiding code duplication, and eliminating side effects.
Join the DZone community and get the full member experience.
Join For FreeOne of the finest ways to make the code easy to read, maintain, and improve can be done by writing clean code. Clean code helps to reduce errors, improves the code quality of the project, and makes other developers and future teams understand and work with the code. The well-organized code reduces mistakes and maintenance a lot easier.
1. Use Meaningful Names
Clean code should have meaningful names that describe the purpose of variables, functions, and classes. The name itself should convey what the code does. So, anyone who is reading it can understand its purpose without referring to any additional documentation.
Example
- Bad naming:
int d; // What does 'd' represent?
- Good naming:
int daysSinceLastUpdate; // Clear, self-explanatory name
- Bad method name:
public void process() {
// What exactly is this method processing?
}
- Good method name:
public void processPayment() {
// Now it's clear that this method processes a payment.
}
2. Write Small Functions
Functions should be small and focused on doing just one thing. A good rule of thumb is the Single Responsibility Principle (SRP) which is each function should have only one reason to change.
Example
- Bad example (a large function doing multiple things):
public void processOrder(Order order) {
validateOrder(order);
calculateShipping(order);
processPayment(order);
sendConfirmationEmail(order);
}
- Good example (functions doing only one thing):
public void processOrder(Order order) {
validateOrder(order);
processPayment(order);
confirmOrder(order);
}
private void validateOrder(Order order) {
// Validation logic
}
private void processPayment(Order order) {
// Payment processing logic
}
private void confirmOrder(Order order) {
// Send confirmation email
}
Each function now handles only one responsibility, making it easier to read, maintain, and test.
3. Avoid Duplication
Duplication is one of the biggest problems in messy code. Avoid copying and pasting code. Instead, look for common patterns and extract them into reusable methods or classes.
Example
- Bad example (duplicated code):
double getAreaOfRectangle(double width, double height) {
return width * height;
}
double getAreaOfTriangle(double base, double height) {
return (base * height) / 2;
}
- Good example (eliminated duplication):
double getArea(Shape shape) {
return shape.area();
}
abstract class Shape {
abstract double area();
}
class Rectangle extends Shape {
double width, height;
@Override
double area() {
return width * height;
}
}
class Triangle extends Shape {
double base, height;
@Override
double area() {
return (base * height) / 2;
}
}
Now, the logic for calculating the area is encapsulated in each shape
class, eliminating the need for duplicating similar logic.
public void updateOrderStatus(Order order) {
if (order.isPaid()) {
order.setStatus("shipped");
sendEmailToCustomer(order); // Side effect: sends an email when the status is changed
}
}
4. Eliminate Side Effects
Functions should avoid change of state outside their scope which causes unintended side effects. When functions have side effects, they become harder to understand and can act in unpredictable behavior.
Example
- Bad example (function with side effects):
public void updateOrderStatus(Order order) {
if (order.isPaid()) {
order.setStatus("shipped");
sendEmailToCustomer(order); // Side effect: sends an email when the status is changed
}
}
- Good example (no side effects):
public void updateOrderStatus(Order order) {
if (order.isPaid()) {
order.setStatus("shipped");
}
}
public void sendOrderShippedEmail(Order order) {
if (order.getStatus().equals("shipped")) {
sendEmailToCustomer(order);
}
}
In the above case, the function's main job is to update the status. Sending an email is another task that is handled in a separate method.
5. Keep Code Expressive
Keeping the code expressive includes structure, method names, and overall design which should be easy to understand to the reader what the code is doing. Comments are rarely used if the code is clear.
Example
- Bad example (unclear code):
if (employee.type == 1) {
// Manager
pay = employee.salary * 1.2;
} else if (employee.type == 2) {
// Developer
pay = employee.salary * 1.1;
} else if (employee.type == 3) {
// Intern
pay = employee.salary * 0.8;
}
- Good example (expressive code):
if (employee.isManager()) {
pay = employee.calculateManagerPay();
} else if (employee.isDeveloper()) {
pay = employee.calculateDeveloperPay();
} else if (employee.isIntern()) {
pay = employee.calculateInternPay();
}
In the above good example, method names are made clear to express the intent. It makes user to read easier and understand the code without any comments.
Conclusion
Here are some of the key principles for writing clean code: use of meaningful names, use small functions, avoid repeating code, remove side effects, and write clear and expressive code. Following these practices makes the code easier to understand and fix.
Opinions expressed by DZone contributors are their own.
Comments