Design Principles
Clean Code Principles
Write code that is easy to read, understand, and maintain. Clean code practices that separate professional developers from the rest.
15 min readEssential Skills
1Meaningful Names
Names should reveal intent. If a name requires a comment, then the name doesn't reveal its intent.
✗ Bad Names
int d; // elapsed time in days List<int[]> list1; void doStuff(); boolean flag; String s;
✓ Good Names
int elapsedTimeInDays; List<Cell> flaggedCells; void calculateMonthlyRevenue(); boolean isValid; String customerName;
Naming Rules
- Use intention-revealing names - The name should tell why it exists
- Avoid disinformation - Don't use 'accountList' if it's not a List
- Make meaningful distinctions - 'a1, a2' tells nothing; 'source, destination' does
- Use pronounceable names - 'genymdhms' vs 'generationTimestamp'
- Use searchable names - 'MAX_CLASSES_PER_STUDENT' vs '7'
2Functions
Small
Functions should be small. 20 lines max is a good rule.
Do One Thing
Functions should do one thing. Do it well. Do it only.
One Level of Abstraction
Don't mix high-level and low-level operations.
Few Arguments
Zero is ideal, one or two is fine, three is suspicious.
Function Refactoring Example
// BAD: Does too many things
public void processOrder(Order order) {
// Validate
if (order.getItems().isEmpty()) {
throw new InvalidOrderException("No items");
}
if (order.getCustomer() == null) {
throw new InvalidOrderException("No customer");
}
// Calculate totals
double subtotal = 0;
for (OrderItem item : order.getItems()) {
subtotal += item.getPrice() * item.getQuantity();
}
double tax = subtotal * 0.1;
double total = subtotal + tax;
order.setTotal(total);
// Save to database
orderRepository.save(order);
// Send notification
emailService.sendOrderConfirmation(order);
}
// GOOD: Each function does one thing
public void processOrder(Order order) {
validateOrder(order);
calculateTotals(order);
saveOrder(order);
sendConfirmation(order);
}
private void validateOrder(Order order) {
if (order.getItems().isEmpty()) {
throw new InvalidOrderException("No items");
}
if (order.getCustomer() == null) {
throw new InvalidOrderException("No customer");
}
}
private void calculateTotals(Order order) {
double subtotal = calculateSubtotal(order.getItems());
double tax = calculateTax(subtotal);
order.setTotal(subtotal + tax);
}
private double calculateSubtotal(List<OrderItem> items) {
return items.stream()
.mapToDouble(i -> i.getPrice() * i.getQuantity())
.sum();
}
private double calculateTax(double amount) {
return amount * TAX_RATE;
}
private void saveOrder(Order order) {
orderRepository.save(order);
}
private void sendConfirmation(Order order) {
emailService.sendOrderConfirmation(order);
}4Error Handling
Error Handling Principles
- Use exceptions rather than return codes - Cleaner separation of concerns
- Write try-catch-finally first - Defines the scope
- Provide context with exceptions - Include operation, values, what failed
- Don't return null - Return empty collections, Optional, or throw
- Don't pass null - Leads to NullPointerExceptions everywhere
✗ Bad Error Handling
public List<User> getUsers() {
try {
return userRepo.findAll();
} catch (Exception e) {
return null; // Bad!
}
}
// Caller must check for null
List<User> users = getUsers();
if (users != null) {
for (User u : users) { }
}✓ Good Error Handling
public List<User> getUsers() {
try {
return userRepo.findAll();
} catch (DatabaseException e) {
log.error("Failed to fetch", e);
return Collections.emptyList();
}
}
// Caller doesn't need null checks
List<User> users = getUsers();
for (User u : users) { }5DRY, KISS, YAGNI
DRY
Don't Repeat Yourself
Every piece of knowledge should have a single, unambiguous representation. If you find yourself copying code, extract it.
KISS
Keep It Simple, Stupid
Simplicity should be a key goal. Avoid unnecessary complexity. The simplest solution is usually the best.
YAGNI
You Aren't Gonna Need It
Don't add functionality until it's necessary. Building for hypothetical future needs often wastes time.
6Interview Follow-up Questions
Interview Follow-up Questions
Common follow-up questions interviewers ask
7Key Takeaways
1Use meaningful names that reveal intent.
2Keep functions small and focused on one thing.
3Good code is self-documenting - minimize comments.
4Handle errors properly - don't return or pass null.
5Follow DRY but avoid premature abstraction.
6Apply KISS and YAGNI - don't over-engineer.
3Comments
// Check if employee is eligible // for full benefits if ((e.flags & HOURLY) && (e.age > 65)) // Returns the day of month public int getDayOfMonth() { return dayOfMonth; } // TODO: fix this later // FIXME: hack