Essential Coding Philosophies & Principles¶
SOLID Principles¶
The foundation of object-oriented design, ensuring maintainable and scalable code.
Single Responsibility Principle (SRP)¶
Each class or module should have one, and only one, reason to change. A class should do one thing well.
Example: A User class should handle user data, not also handle email sending or database operations.
Benefits: Easier testing, reduced coupling, clearer purpose
Open/Closed Principle (OCP)¶
Software entities should be open for extension but closed for modification. Add new functionality without changing existing code.
Implementation: Use inheritance, interfaces, or composition patterns
Benefits: Reduces risk of breaking existing functionality, promotes code reuse
Liskov Substitution Principle (LSP)¶
Objects of a superclass should be replaceable with objects of its subclasses without breaking the application. Subtypes must honor the contract of their base types.
Example: If Bird has a fly() method, Penguin shouldn't inherit from Bird since penguins can't fly.
Benefits: Ensures proper inheritance hierarchies, prevents unexpected behaviors
Interface Segregation Principle (ISP)¶
Clients should not be forced to depend on interfaces they don't use. Many small, specific interfaces are better than one large, general-purpose interface.
Example: Instead of one IWorker interface with work(), eat(), sleep(), create separate IWorkable, IFeedable, IRestable interfaces.
Benefits: Reduces dependencies, increases flexibility, clearer contracts
Dependency Inversion Principle (DIP)¶
High-level modules should not depend on low-level modules. Both should depend on abstractions. Abstractions should not depend on details; details should depend on abstractions.
Implementation: Use dependency injection, depend on interfaces rather than concrete implementations
Benefits: Loose coupling, easier testing with mocks, more flexible architecture
Core Design Principles¶
DRY (Don't Repeat Yourself)¶
Every piece of knowledge should have a single, unambiguous representation in the system. Avoid code duplication by abstracting common functionality.
How to apply: - Extract repeated code into functions or classes - Use inheritance or composition for shared behavior - Create utility libraries for common operations - Use configuration files for repeated values
Warning: Don't over-DRY. Sometimes a little duplication is better than the wrong abstraction.
KISS (Keep It Simple, Stupid)¶
Simplicity should be a key design goal. Most systems work best if kept simple rather than made complex.
Guidelines: - Write code that's easy to understand, not just clever - Avoid premature optimization - Use straightforward algorithms unless complexity is justified - Prefer clear naming over comments - Break complex problems into simpler sub-problems
Remember: Simple doesn't mean simplistic or feature-poor; it means elegant and understandable.
YAGNI (You Aren't Gonna Need It)¶
Don't implement functionality until it's actually needed. Avoid building features based on speculation about future requirements.
Why it matters: - Reduces code bloat and maintenance burden - Saves development time - Prevents over-engineering - Requirements often change anyway
When to ignore: Infrastructure decisions that would be expensive to change later (e.g., database choice, major architectural patterns).
Development Methodologies¶
Test-Driven Development (TDD)¶
Write tests before writing the actual code. Follow the Red-Green-Refactor cycle.
Process: 1. Red: Write a failing test for new functionality 2. Green: Write minimal code to make the test pass 3. Refactor: Clean up code while keeping tests green
Benefits: - Better test coverage - Forces you to think about design upfront - Tests serve as documentation - Easier refactoring with confidence - Fewer bugs in production
Behavior-Driven Development (BDD)¶
Extension of TDD that focuses on the behavior of the application from the end user's perspective.
Key aspects: - Uses natural language descriptions (Given-When-Then) - Bridges communication between developers, testers, and business stakeholders - Tests describe what the system does, not how it does it
Code Review Culture¶
Systematic examination of code by peers before merging to the main branch.
Best practices: - Keep reviews small (under 400 lines) - Review promptly (within 24 hours) - Focus on logic, not style (use linters for style) - Be respectful and constructive - Ask questions rather than making demands - Explain the "why" behind suggestions
Benefits: Knowledge sharing, bug detection, consistent code quality, team learning
Software Development Approaches¶
Agile Development¶
Iterative approach that emphasizes flexibility, collaboration, and customer feedback.
Core values: - Individuals and interactions over processes and tools - Working software over comprehensive documentation - Customer collaboration over contract negotiation - Responding to change over following a plan
Scrum Framework¶
Agile framework with defined roles, events, and artifacts.
Key components: - Sprints: Fixed time-boxes (1-4 weeks) for development - Roles: Product Owner, Scrum Master, Development Team - Ceremonies: Sprint Planning, Daily Standups, Sprint Review, Retrospective - Artifacts: Product Backlog, Sprint Backlog, Increment
Benefits: Faster delivery, adaptability, transparency, continuous improvement
Kanban¶
Visual workflow management method focusing on continuous delivery.
Principles: - Visualize work on a board - Limit work in progress (WIP) - Manage flow - Make policies explicit - Continuous improvement
Clean Code Principles¶
Guidelines for writing readable, maintainable code (from Robert C. Martin's "Clean Code").
Meaningful Names¶
- Use intention-revealing names
- Avoid disinformation
- Make meaningful distinctions
- Use pronounceable and searchable names
- Avoid mental mapping
Example:
Bad: int d; // elapsed time in days
Good: int elapsedTimeInDays;
Functions¶
- Should be small (typically under 20 lines)
- Do one thing well
- Use descriptive names
- Prefer fewer arguments (0-2 ideal, 3+ questionable)
- No side effects
- Command-Query Separation
Comments¶
- Code should be self-explanatory
- Use comments for "why," not "what"
- Avoid redundant comments
- Explain intent and rationale
- TODO comments for temporary solutions
Error Handling¶
- Use exceptions rather than return codes
- Provide context with exceptions
- Don't return null (use Optional/Maybe patterns)
- Don't pass null
Formatting¶
- Consistent indentation and spacing
- Vertical openness (separate concepts with blank lines)
- Related code should be vertically close
- Keep files and classes small
Additional Important Principles¶
Separation of Concerns (SoC)¶
Divide a program into distinct sections, each addressing a separate concern. Related to Single Responsibility but applied at a higher level (modules, layers, systems).
Examples: MVC pattern, microservices architecture, layered architecture
Law of Demeter (Principle of Least Knowledge)¶
A module should not know about the internal workings of the objects it manipulates. Only talk to immediate friends.
Rule: An object's method should only call methods on: - The object itself - Objects passed as parameters - Objects it creates - Its direct properties
Composition Over Inheritance¶
Favor object composition over class inheritance to achieve code reuse and flexibility.
Why: Inheritance creates tight coupling and can lead to fragile base class problems. Composition is more flexible.
Fail Fast¶
Detect and report errors as early as possible. Validate inputs immediately, throw exceptions early, use assertions.
Benefits: Easier debugging, prevents error propagation, clearer error messages
Convention Over Configuration¶
Provide sensible defaults and follow common conventions to reduce the number of decisions developers need to make.
Examples: Ruby on Rails, Spring Boot
Principle of Least Astonishment (POLA) / Principle of Least Surprise (POLS)¶
A component should behave in a way that most users expect it to behave, minimizing surprise and confusion.
Core idea: Design should match the user's experience, expectations, and mental models. Leverage existing knowledge to minimize the learning curve.
Guidelines: - Function/method names should intuitively match their behavior - Follow platform conventions (keyboard shortcuts, UI patterns) - Apply sensible defaults - Borrow from functionally similar programs users are familiar with - When behavior is ambiguous, choose what will least surprise the user
Examples:
- F1 key opens help in most applications
- API methods named getUserById() should return a user, not delete one
- JavaScript's parseInt("08") originally parsed as octal (base 8), violating POLA—fixed in later versions
- Keyboard shortcuts like ? for help on websites (Gmail, YouTube)
Benefits: Reduced learning curve, fewer bugs from misunderstanding, better user experience, intuitive interfaces
Premature Optimization is the Root of All Evil¶
Don't optimize code before you have evidence it's a bottleneck. Write clear code first, then profile and optimize only what matters.
Process: Make it work → Make it right → Make it fast
Practical Application Tips¶
- Start small: Don't try to apply all principles at once
- Context matters: Not every principle applies to every situation
- Balance: Sometimes principles conflict; use judgment
- Refactor regularly: Apply principles when touching existing code
- Team alignment: Discuss and agree on which principles to emphasize
- Continuous learning: These principles evolve with experience
- Pragmatism over dogmatism: Break rules when you have good reasons
Remember: These principles are guidelines, not laws. The goal is writing maintainable, understandable, and robust software that delivers value.