Master KISS, DRY, and SOLID: Practical Tips and Real‑World Code Examples
This article explains the core software design principles KISS, DRY, and SOLID, shows why they matter for readability and maintainability, provides concrete Java examples and step‑by‑step guidelines, and lists actionable rules developers can follow to write cleaner, more reusable code.
Introduction
When you graduate from university you may know Java, C, or C++, but real‑world development requires more than language syntax. Understanding and applying fundamental programming principles—KISS, DRY, and SOLID—greatly improves code readability, maintainability, and extensibility.
KISS Principle
Keep It Simple, Stupid!
The KISS principle urges developers to keep code as simple as possible. Simple code is easier to read, debug, and modify because bugs are harder to hide and quicker to fix.
How to write KISS‑compliant code?
Consider three ways to validate an IP address:
Implementation 1 uses a complex regular expression.
Implementation 2 leverages StringUtils and Integer utility methods for clear logic.
Implementation 3 processes each character manually, which is error‑prone.
Implementation 1 has the fewest lines but the regex is hard to understand and maintain, violating KISS.
Implementation 2 uses well‑known utility classes, making the logic clear and maintainable.
Implementation 3 avoids external tools but is difficult to read and prone to bugs.
Key guidelines for writing KISS‑friendly code:
Avoid obscure language features that teammates may not understand.
Prefer existing libraries over reinventing the wheel; custom implementations often introduce bugs.
Do not over‑optimize with clever tricks that sacrifice readability.
Always consider the reader’s perspective when writing code.
DRY Principle
Don't Repeat Yourself
DRY means eliminating duplicated logic, not just identical code. Repeating the same logic in multiple places leads to bugs when a change is applied to only some copies.
How to write DRY‑compliant code?
Two colleagues independently implement IP validation, resulting in duplicated logic even though the semantics are the same.
Both implementations perform the same checks (null, length, etc.) but are written separately.
Practical advice for DRY:
Extract common validation into a shared utility method or class.
Use existing helper classes (e.g., StringUtils) instead of copying logic.
Separate business logic from generic validation to improve reuse.
SOLID Principles
SOLID is a collection of five design principles that help create high‑cohesion, low‑coupling, and extensible software.
S – Single Responsibility Principle
A class should have only one reason to change.
Each class should encapsulate a single responsibility. For example, a Person class stores personal data, while an Account class handles account information. Changing a person's state should not require modifying the account class.
public class Person {
private Long personId;
private String firstName;
private String lastName;
private String age;
private List<Account> accounts;
// ...
}
public class Account {
private Long guid;
private String accountNumber;
private String accountName;
private String status;
private String type;
// ...
}Large classes that handle many responsibilities become hard to maintain and test.
O – Open/Closed Principle
Software entities should be open for extension but closed for modification.
Instead of adding if‑else branches for new notification channels, define an abstraction.
public interface NotificationService {
void sendOTP();
}
public class EmailNotification implements NotificationService {
public void sendOTP() { /* email logic */ }
}
public class MobileNotification implements NotificationService {
public void sendOTP() { /* SMS logic */ }
}Adding a new WechatNotification class implements the same interface without touching existing code, satisfying the Open/Closed principle.
L – Liskov Substitution Principle
Derived classes must be substitutable for their base classes.
If a subclass cannot fulfill the contract of its superclass, it violates LSP. For instance, Weibo does not support video calls, yet it inherits the groupVideoCall method from SocialMedia. Using a Weibo instance where a SocialMedia is expected will cause runtime errors.
public abstract class SocialMedia {
public abstract void chatWithFriend();
public abstract void publishPost(Object post);
public abstract void sendPhotosAndVideos();
public abstract void groupVideoCall(String... users);
}To fix the violation, split responsibilities into separate interfaces:
public interface SocialMedia {
void chatWithFriend();
void publishPost(Object post);
}
public interface VideoCallManager {
void groupVideoCall(String... users);
}I – Interface Segregation Principle
Clients should not be forced to depend on methods they do not use.
A monolithic UPIPayments interface forces implementations like AliPay to provide a cash‑back method they do not support. Splitting the interface resolves the issue.
public interface CashbackManager {
void getCashBackAsCreditBalance();
}Now AliPay can implement only the methods it needs.
D – Dependency Inversion Principle
High‑level modules should depend on abstractions, not concrete implementations.
Instead of a ShoppingMall class directly depending on DebitCard, define a BankCard abstraction.
public interface BankCard {
void doTransaction(int amount);
}
public class DebitCard implements BankCard {
public void doTransaction(int amount) { System.out.println("tx done with DebitCard"); }
}
public class CreditCard implements BankCard {
public void doTransaction(int amount) { System.out.println("tx done with CreditCard"); }
}
public class ShoppingMall {
private BankCard bankCard;
public ShoppingMall(BankCard bankCard) { this.bankCard = bankCard; }
public void doPayment(Object order, int amount) { bankCard.doTransaction(amount); }
}This design allows the mall to work with any BankCard implementation without being tightly coupled to a specific class.
Conclusion
The KISS, DRY, and SOLID principles together form a solid foundation for writing clean, maintainable, and extensible software. By keeping code simple, eliminating duplication, and adhering to well‑defined design rules, developers can reduce bugs, improve readability, and build systems that evolve gracefully.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
