Software D&D Principles


There are many software design & development principles that act as “mental guardrails” for writing clean, maintainable code. Here’s a list, grouped by topic.


1. Code Quality & Simplicity Principles


Principle

Definition

Java Example

KISS – Keep It Simple, Stupid

Keep code straightforward and avoid unnecessary complexity.

Bad Practice:

if(user != null && user.isActive() && user.hasPermission("ADMIN")) {}


Good Practice:

if(isAdmin(user)) {}

DRY – Don’t Repeat Yourself

Avoid duplicating logic. Extract common logic to methods or utilities.

Bad Practice:

double d1 = price - (price * 0.1);

double d2 = price - (price * 0.1);


Good Practice:

double applyDiscount(double price) {

return price - (price * 0.1); 

}

YAGNI – You Aren’t Gonna Need It

Don’t build features you don’t need yet.

 Adding caching logic on day 1 without confirmed performance need.

SLAP – Single Level of Abstraction

A method should operate at one abstraction level.

Bad Practice:

void processOrder() { 

fetchFromDB(); 

calculateDiscount(); 

sendEmail(); 

}


Good Practice:

void processOrder() { 

getOrder(); 

applyDiscount(); 

notifyCustomer(); 

}

Boy Scout Rule

Leave the code better than you found it.

Refactor a messy method when fixing a bug.


2. Object-Oriented Design Principles (SOLID)


Principle

Definition

Java Example

S – Single Responsibility

A class should have one reason to change.

Bad Practice:

class InvoiceService { 

void createInvoice(){}

void sendEmail(){} 

}


Good Practice:

class InvoiceService { void createInvoice(){} }

class EmailService { void sendEmail(){} }

O – Open/Closed

Open for extension, closed for modification.

interface Payment { void pay(double amount); }


class CreditCardPayment implements Payment { 

public void pay(double a) {} 

}


class UpiPayment implements Payment {

public void pay(double a) {} 

}

 

// Add PayPalPayment without changing old code

L – Liskov Substitution

Subclasses should be replaceable by base class.

interface Bird {} 


interface FlyingBird extends Bird { 

void fly(); 


class Sparrow implements FlyingBird {

public void fly() {} 

}


class Ostrich implements Bird {}

I – Interface Segregation

Many small interfaces over one large one.

Bad Practice:

interface Machine { 

print(); 

scan(); 

fax(); 

}


Good Practice:

interface Printer { 

void print(); 


interface Scanner { 

void scan(); 

}

D – Dependency Inversion

Depend on abstractions, not concretions.

interface MessageService { 

void send(String msg); 


class EmailService implements MessageService { 

public void send(String msg) {} 

}


3. Architecture & Maintainability Principles



Definition

Java Example

SoC – Separation of Concerns

Different layers handle different concerns.

@Controller 

class UserController { 

@Autowired UserService service; 


@Service 

class UserService { 

@Autowired UserRepository repo; 

}

High Cohesion, Low Coupling

Modules should be focused and independent.

Logging module works without depending on authentication.

Law of Demeter

Only talk to direct friends.

Bad Practice:

order.getCustomer().getAddress().getCity();


Good Practice:

order.getCustomerCity();

Inversion of Control (IoC)

Framework controls object creation.

Spring creates beans & injects dependencies automatically.

CQRS

Separate read and write models.

OrderQueryService for reads, 

OrderCommandService for writes.


4. Testing & Reliability Principles


Principle

Definition

Java Example

First-class Tests

Tests are as important as production code.

Keep JUnit tests in /src/test/java.

Test Pyramid

More unit tests than UI tests.

70% unit, 20% integration, 10% Selenium tests.

Fail Fast

Detect errors early.

if(user == null) throw new IllegalArgumentException("User required");

AAA – Arrange, Act, Assert

Clear test structure.

// Arrange 

User u = new User("John"); 


// Act 

u.activate();

 

// Assert 

assertTrue(u.isActive());


5. Agile/Lean Development Principles


Principle

Definition

Java Example

Iterate Quickly

Deliver small increments.

Ship a basic Spring Boot REST API before adding caching/security.

Build-Measure-Learn

Release → Collect metrics → Improve.

Deploy MVP, check user API usage, optimize endpoints.

CI/CD

Auto-build & deploy after merges.

GitHub Actions running mvn test & deploy to AWS.

Limit WIP

Reduce active tasks.

Developer works on only 1–2 Jira issues at a time.


6. Performance & Resource Management Principles


Principle

Definition

Java Example

Optimize Last

Make it work before making it fast.

Write a working algorithm before parallelizing it.

Caching

Store expensive results.

Use Spring Cache with Redis for repeated DB queries.

Bulkhead Pattern

Isolate failures.

Separate DB connections for high-priority vs. low-priority tasks.


7. Security & Reliability Principles


Principle

Definition

Java Example

Least Privilege

Minimal permissions.

DB user with read/write but no DROP privilege.

Defense in Depth

Multiple security layers.

Input validation + Spring Security + HTTPS.

Fail Securely

Deny access if unsure.

Default to “access denied” if JWT verification fails.





Master Reference


Principle

Category

Definition

Example

Benefits

When to Use

KISS (Keep It Simple, Stupid)

Code Quality

Keep design/code simple, avoid overengineering.

Replace deeply nested if-else with strategy pattern.

Easy maintenance, fewer bugs.

When writing any new feature or refactoring.

DRY (Don’t Repeat Yourself)

Code Quality

Avoid code duplication; reuse logic.

Move repeated DB queries into DAO method.

Consistency, easier updates.

When seeing repeated code blocks.

YAGNI (You Aren’t Gonna Need It)

Code Quality

Don’t build for hypothetical needs.

Skip creating unused service layers.

Saves time, prevents unused code.

In early dev phases, avoid premature features.

SOC (Separation of Concerns)

Code Quality

Separate functionalities into distinct layers.

MVC keeps UI, logic, and DB separate.

Easier debugging, testing.

In any layered or modular system.

SLAP (Single Level of Abstraction Principle)

Code Quality

Each method should operate at one abstraction level.

Business logic method shouldn’t do DB connections.

Clarity, maintainability.

In method design and refactoring.

SRP (Single Responsibility Principle)

OOP/SOLID

A class has only one reason to change.

UserService handles user ops, not emails.

Modular, easier updates.

Class-level design.

OCP (Open/Closed Principle)

OOP/SOLID

Open for extension, closed for modification.

Add payment type via new class, not modifying core.

Extensible, avoids breaking code.

Feature expansion without altering core.

LSP (Liskov Substitution Principle)

OOP/SOLID

Subclasses must be usable as their base type.

Avoid Penguin extends Bird if fly() is broken.

Correct inheritance.

Designing inheritance hierarchies.

ISP (Interface Segregation Principle)

OOP/SOLID

Smaller, specific interfaces preferred.

Split Animal into Flyable, Swimmable.

Reduces unused methods.

Interface design.

DIP (Dependency Inversion Principle)

OOP/SOLID

Depend on abstractions, not concretions.

Use PaymentProcessor interface, inject via Spring.

Flexibility, testability.

For dependency management.

High Cohesion

Architecture

Related code stays together in modules.

Microservice per domain.

Easier changes, better focus.

Modular design.

Low Coupling

Architecture

Minimal dependency between modules.

API-based service calls.

Reduces ripple effects.

Large-scale systems.

Encapsulation

Architecture/OOP

Hide implementation, expose only needed APIs.

Private fields, public getters.

Prevents misuse, easier updates.

Data-sensitive classes.

Design to Interfaces

Architecture

Code against interfaces for flexibility.

Use List over ArrayList type ref.

Easy swapping implementations.

Library/framework integration.

Event-Driven Architecture

Architecture

Use events instead of direct calls.

Kafka-based microservices.

Decoupling, async handling.

Scalable/distributed systems.

Fail-Fast

Reliability

Detect and stop early when errors occur.

Validation before DB save.

Early bug detection.

In data validation, pipelines.

TDD First Law

Testing

Write tests before code.

JUnit before service logic.

Better design, fewer bugs.

For critical logic.

Testing Pyramid

Testing Strategy

Unit > Integration > UI tests.

70-20-10 split.

Fast feedback, stable tests.

Test planning.

Automate Repetitive Tests

QA Automation

Replace manual runs with automation.

Selenium for UI regression.

Saves time, consistent results.

Regression-heavy projects.

Mock & Stub Isolation

Testing

Simulate dependencies for testing.

Mockito for DB/service calls.

Predictable tests.

Unit testing with dependencies.

Iterative Development

Agile

Deliver in small increments.

2-week sprints.

Continuous feedback.

Any Agile environment.

Continuous Integration (CI)

DevOps

Merge often with automated builds/tests.

Jenkins with Git hooks.

Early detection of errors.

Multi-dev teams.

Continuous Delivery (CD)

DevOps

Keep code deployable anytime.

Auto-deploy to staging after tests.

Faster releases.

Production-ready projects.

Feedback Loops

Agile

Short cycles between feedback & change.

Client review per sprint.

Customer satisfaction.

Agile teams.

Least Privilege Principle

Security

Grant minimal required permissions.

Read-only DB user.

Reduced attack surface.

In security-sensitive systems.

Fail-Secure Defaults

Security

Deny by default, allow explicitly.

Auth required on all APIs.

Stronger security.

Security-first apps.

Defensive Programming

Reliability

Assume failures, guard against them.

Null checks, input validation.

Prevents crashes.

Public APIs, critical systems.

Idempotency

Reliability

Same request multiple times = same result.

Payment API prevents double charge.

Safe retries.

APIs, distributed systems.