Skip to main content
Glama
language-agnostic.mdc10.4 kB
--- description: "Universal programming patterns: SOLID principles, design patterns, clean code, architecture decisions applicable across all languages" alwaysApply: true --- # Language-Agnostic Programming Patterns Universal principles and patterns applicable across all programming languages. ## CRITICAL: Development Workflow ### CLI-First Principle Before manually creating ANY file, check if a CLI tool exists: | Task | Check for CLI | Example | |------|---------------|---------| | New project | Scaffolding CLI | `npm create`, `cargo new`, `flutter create` | | New component | Generator CLI | `npx shadcn-ui add`, `ng generate`, `rails generate` | | New module | Framework CLI | `nest generate module` | | Dependencies | Package manager | `npm install`, `pip install` | ### Verification-First Principle Code is not done until it's verified: ``` 1. Write code 2. Build/compile: Does it compile? 3. Lint: Are there warnings? 4. Run: Does it execute? 5. Test: Does it work correctly? ``` ### Version-Aware Development Always verify package versions before using: ``` <think> Before using package X: 1. What's the current stable version? 2. Is it compatible with my other dependencies? 3. Are there known issues? </think> → web_search("[package] latest stable version [current month year]") ``` --- ## SOLID Principles ### Single Responsibility Principle (SRP) A class/module should have only one reason to change. **Apply when:** - A function does multiple unrelated things - A class has too many dependencies - Changes in one area affect unrelated code **Example Pattern:** ``` Bad: UserService handles auth, profile, notifications, and billing Good: AuthService, ProfileService, NotificationService, BillingService ``` ### Open/Closed Principle (OCP) Open for extension, closed for modification. **Apply when:** - Adding new features requires modifying existing code - Switch statements grow with each new type - Core logic changes for edge cases **Example Pattern:** ``` Bad: if type == "email" ... elif type == "sms" ... elif type == "push" ... Good: NotificationStrategy interface with EmailStrategy, SMSStrategy, PushStrategy ``` ### Liskov Substitution Principle (LSP) Subtypes must be substitutable for their base types. **Apply when:** - Derived classes override behavior in unexpected ways - Code checks for specific types before operating - Inheritance creates illogical hierarchies **Example Pattern:** ``` Bad: Square extends Rectangle but can't independently set width/height Good: Both Square and Rectangle implement Shape interface ``` ### Interface Segregation Principle (ISP) Clients shouldn't depend on interfaces they don't use. **Apply when:** - Classes implement methods they don't need - Interfaces have too many methods - Changes affect many unrelated implementations **Example Pattern:** ``` Bad: Animal interface with fly(), swim(), walk() - Penguin can't fly Good: Flyable, Swimmable, Walkable interfaces ``` ### Dependency Inversion Principle (DIP) Depend on abstractions, not concretions. **Apply when:** - High-level modules import low-level modules directly - Changing database/service requires code changes - Testing requires real dependencies **Example Pattern:** ``` Bad: UserService directly imports MySQLDatabase Good: UserService depends on DatabaseInterface, injected at runtime ``` ## Common Design Patterns ### Creational Patterns #### Factory Pattern Use when object creation logic is complex or needs to be centralized. ``` When to use: - Multiple similar objects with different configurations - Object creation depends on runtime conditions - Hiding complex initialization logic ``` #### Builder Pattern Use for constructing complex objects step by step. ``` When to use: - Objects with many optional parameters - Complex configuration requirements - Need for immutable objects with many fields ``` #### Singleton Pattern Use sparingly for truly global, single-instance resources. ``` When to use: - Configuration managers - Connection pools - Logger instances Avoid when: - It's just for convenience (use DI instead) - Testing would be difficult - Multiple instances might be needed later ``` ### Structural Patterns #### Adapter Pattern Convert one interface to another that clients expect. ``` When to use: - Integrating third-party libraries - Working with legacy code - Unifying different data sources ``` #### Decorator Pattern Add behavior to objects dynamically. ``` When to use: - Adding features without subclassing - Composable behaviors - Middleware-like patterns ``` #### Facade Pattern Provide a simplified interface to a complex subsystem. ``` When to use: - Simplifying complex library usage - Creating API boundaries - Reducing coupling between layers ``` ### Behavioral Patterns #### Strategy Pattern Define a family of interchangeable algorithms. ``` When to use: - Multiple algorithms for the same task - Runtime algorithm selection - Avoiding complex conditionals ``` #### Observer Pattern Notify dependents of state changes. ``` When to use: - Event-driven systems - Pub/sub messaging - Reactive data flows ``` #### Command Pattern Encapsulate requests as objects. ``` When to use: - Undo/redo functionality - Queueing operations - Macro recording ``` ## Clean Code Principles ### Naming Conventions #### Variables and Functions - Use intention-revealing names - Avoid abbreviations unless universally understood - Be consistent with terminology ``` Bad: d, tmp, data, info, process() Good: elapsedTimeInDays, userProfile, activeConnections, validatePayment() ``` #### Booleans - Use positive names (avoid double negatives) - Start with is/has/can/should ``` Bad: notDisabled, flag, status Good: isEnabled, hasPermission, canEdit, shouldRefresh ``` #### Functions - Use verbs for actions - Be specific about what they do ``` Bad: handle(), process(), manage() Good: validateUserInput(), calculateTotalPrice(), sendConfirmationEmail() ``` ### Function Design #### Keep Functions Small - Do one thing well - 5-20 lines is ideal - If you can't name it well, it's probably doing too much #### Limit Parameters - 0-3 parameters is ideal - Use objects for more - Consider builder pattern for complex initialization #### Avoid Side Effects - Functions should be predictable - Clearly document mutations - Prefer pure functions when possible ### Comments #### When to Comment - Explain WHY, not WHAT - Document public APIs - Warn about non-obvious behavior - Link to external resources/tickets #### When NOT to Comment - Explaining what code does (make code clearer instead) - Commented-out code (delete it) - Redundant descriptions - TODOs without tickets ``` Bad: // increment counter by 1 counter += 1; Good: // Retry limit based on SLA requirements (see JIRA-1234) MAX_RETRIES = 3; ``` ### Error Handling #### Fail Fast - Validate inputs early - Throw exceptions for unexpected states - Don't swallow errors silently #### Error Messages - Include context (what was being done) - Include relevant values - Suggest remediation when possible ``` Bad: "Error occurred" Good: "Failed to connect to database 'users' at localhost:5432: Connection refused. Check if PostgreSQL is running." ``` #### Error Categories 1. **Recoverable**: Retry, fallback, or prompt user 2. **Validation**: Return clear error to caller 3. **Programming**: Fail fast, fix the bug 4. **System**: Log, alert, graceful degradation ## Architecture Patterns ### Layered Architecture ``` Presentation → Business Logic → Data Access → Database ``` - Each layer only talks to adjacent layers - Dependencies flow downward ### Clean Architecture ``` Entities → Use Cases → Controllers → Frameworks ``` - Business rules at the center - Frameworks/DB at the edges - Dependency rule: inward only ### Hexagonal Architecture (Ports & Adapters) ``` [Adapters] → [Ports] → [Core Domain] ← [Ports] ← [Adapters] ``` - Core domain is isolated - Ports define interfaces - Adapters implement external concerns ### When to Choose What - **Layered**: Simple CRUD apps, rapid development - **Clean**: Complex business logic, long-lived systems - **Hexagonal**: Multiple interfaces, testability focus ## Testing Principles ### Test Pyramid ``` /\ / \ E2E Tests (few) /----\ Integration Tests (some) /------\ Unit Tests (many) ``` ### Unit Tests - Test one thing in isolation - Fast and deterministic - Mock external dependencies ### Integration Tests - Test component interactions - Use real (or realistic) dependencies - Focus on boundaries ### End-to-End Tests - Test complete user flows - Slowest and most brittle - Use for critical paths only ### Test Quality - Tests are documentation - One assertion per test when possible - Arrange-Act-Assert pattern - Test behavior, not implementation ## Performance Principles ### Measure First - Don't optimize prematurely - Profile before changing - Set performance budgets ### Common Optimizations - **Caching**: Memoization, HTTP caching, query caching - **Batching**: Combine multiple operations - **Lazy Loading**: Defer until needed - **Pagination**: Don't load everything at once ### Database Performance - Index frequently queried columns - Avoid N+1 queries - Use connection pooling - Consider read replicas for scale ## Security Best Practices ### Input Validation - Validate all external input - Whitelist, don't blacklist - Sanitize before use ### Authentication - Use established libraries - Hash passwords with strong algorithms - Implement rate limiting - Use HTTPS everywhere ### Authorization - Check permissions on every request - Fail closed (deny by default) - Log access attempts ### Data Protection - Encrypt sensitive data at rest - Use parameterized queries - Don't log sensitive information - Implement proper session management ## Code Organization ### Module Structure ``` Feature-based (preferred for larger apps): /features /auth - service - controller - repository /products - service - controller - repository Layer-based (simpler for smaller apps): /controllers /services /repositories ``` ### File Naming - Consistent conventions across project - Reflect content purpose - Include type suffix when helpful (e.g., `.service`, `.controller`) ### Import Organization 1. Standard library 2. Third-party packages 3. Local modules 4. Relative imports

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/madebyaris/rakitui-ai'

If you have feedback or need assistance with the MCP directory API, please join our Discord server