add brain

This commit is contained in:
2026-03-12 15:17:52 +07:00
parent fd9f558fa1
commit e7821a7a9d
355 changed files with 93784 additions and 24 deletions

View File

@@ -0,0 +1,680 @@
# Common API Anti-Patterns and How to Avoid Them
## Introduction
This document outlines common anti-patterns in REST API design that can lead to poor developer experience, maintenance nightmares, and scalability issues. Each anti-pattern is accompanied by examples and recommended solutions.
## 1. Verb-Based URLs (The RPC Trap)
### Anti-Pattern
Using verbs in URLs instead of treating endpoints as resources.
```
❌ Bad Examples:
POST /api/getUsers
POST /api/createUser
GET /api/deleteUser/123
POST /api/updateUserPassword
GET /api/calculateOrderTotal/456
```
### Why It's Bad
- Violates REST principles
- Makes the API feel like RPC instead of REST
- HTTP methods lose their semantic meaning
- Reduces cacheability
- Harder to understand resource relationships
### Solution
```
✅ Good Examples:
GET /api/users # Get users
POST /api/users # Create user
DELETE /api/users/123 # Delete user
PATCH /api/users/123/password # Update password
GET /api/orders/456/total # Get order total
```
## 2. Inconsistent Naming Conventions
### Anti-Pattern
Mixed naming conventions across the API.
```json
Bad Examples:
{
"user_id": 123, // snake_case
"firstName": "John", // camelCase
"last-name": "Doe", // kebab-case
"EMAIL": "john@example.com", // UPPER_CASE
"IsActive": true // PascalCase
}
```
### Why It's Bad
- Confuses developers
- Increases cognitive load
- Makes code generation difficult
- Reduces API adoption
### Solution
```json
Choose one convention and stick to it (camelCase recommended):
{
"userId": 123,
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"isActive": true
}
```
## 3. Ignoring HTTP Status Codes
### Anti-Pattern
Always returning HTTP 200 regardless of the actual result.
```json
Bad Example:
HTTP/1.1 200 OK
{
"status": "error",
"code": 404,
"message": "User not found"
}
```
### Why It's Bad
- Breaks HTTP semantics
- Prevents proper error handling by clients
- Breaks caching and proxies
- Makes monitoring and debugging harder
### Solution
```json
Good Example:
HTTP/1.1 404 Not Found
{
"error": {
"code": "USER_NOT_FOUND",
"message": "User with ID 123 not found",
"requestId": "req-abc123"
}
}
```
## 4. Overly Complex Nested Resources
### Anti-Pattern
Creating deeply nested URL structures that are hard to navigate.
```
❌ Bad Example:
/companies/123/departments/456/teams/789/members/012/projects/345/tasks/678/comments/901
```
### Why It's Bad
- URLs become unwieldy
- Creates tight coupling between resources
- Makes independent resource access difficult
- Complicates authorization logic
### Solution
```
✅ Good Examples:
/tasks/678 # Direct access to task
/tasks/678/comments # Task comments
/users/012/tasks # User's tasks
/projects/345?team=789 # Project filtering
```
## 5. Inconsistent Error Response Formats
### Anti-Pattern
Different error response structures across endpoints.
```json
Bad Examples:
# Endpoint 1
{"error": "Invalid email"}
# Endpoint 2
{"success": false, "msg": "User not found", "code": 404}
# Endpoint 3
{"errors": [{"field": "name", "message": "Required"}]}
```
### Why It's Bad
- Makes error handling complex for clients
- Reduces code reusability
- Poor developer experience
### Solution
```json
Standardized Error Format:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "The request contains invalid data",
"details": [
{
"field": "email",
"code": "INVALID_FORMAT",
"message": "Email address is not valid"
}
],
"requestId": "req-123456",
"timestamp": "2024-02-16T13:00:00Z"
}
}
```
## 6. Missing or Poor Pagination
### Anti-Pattern
Returning all results in a single response or inconsistent pagination.
```json
Bad Examples:
# No pagination (returns 10,000 records)
GET /api/users
# Inconsistent pagination parameters
GET /api/users?page=1&size=10
GET /api/orders?offset=0&limit=20
GET /api/products?start=0&count=50
```
### Why It's Bad
- Can cause performance issues
- May overwhelm clients
- Inconsistent pagination parameters confuse developers
- No way to estimate total results
### Solution
```json
Good Example:
GET /api/users?page=1&pageSize=10
{
"data": [...],
"pagination": {
"page": 1,
"pageSize": 10,
"total": 150,
"totalPages": 15,
"hasNext": true,
"hasPrev": false
}
}
```
## 7. Exposing Internal Implementation Details
### Anti-Pattern
URLs and field names that reflect database structure or internal architecture.
```
❌ Bad Examples:
/api/user_table/123
/api/db_orders
/api/legacy_customer_data
/api/temp_migration_users
Response fields:
{
"user_id_pk": 123,
"internal_ref_code": "usr_abc",
"db_created_timestamp": 1645123456
}
```
### Why It's Bad
- Couples API to internal implementation
- Makes refactoring difficult
- Exposes unnecessary technical details
- Reduces API longevity
### Solution
```
✅ Good Examples:
/api/users/123
/api/orders
/api/customers
Response fields:
{
"id": 123,
"referenceCode": "usr_abc",
"createdAt": "2024-02-16T13:00:00Z"
}
```
## 8. Overloading Single Endpoint
### Anti-Pattern
Using one endpoint for multiple unrelated operations based on request parameters.
```
❌ Bad Example:
POST /api/user-actions
{
"action": "create_user",
"userData": {...}
}
POST /api/user-actions
{
"action": "delete_user",
"userId": 123
}
POST /api/user-actions
{
"action": "send_email",
"userId": 123,
"emailType": "welcome"
}
```
### Why It's Bad
- Breaks REST principles
- Makes documentation complex
- Complicates client implementation
- Reduces discoverability
### Solution
```
✅ Good Examples:
POST /api/users # Create user
DELETE /api/users/123 # Delete user
POST /api/users/123/emails # Send email to user
```
## 9. Lack of Versioning Strategy
### Anti-Pattern
Making breaking changes without version management.
```
❌ Bad Examples:
# Original API
{
"name": "John Doe",
"age": 30
}
# Later (breaking change with no versioning)
{
"firstName": "John",
"lastName": "Doe",
"birthDate": "1994-02-16"
}
```
### Why It's Bad
- Breaks existing clients
- Forces all clients to update simultaneously
- No graceful migration path
- Reduces API stability
### Solution
```
✅ Good Examples:
# Version 1
GET /api/v1/users/123
{
"name": "John Doe",
"age": 30
}
# Version 2 (with both versions supported)
GET /api/v2/users/123
{
"firstName": "John",
"lastName": "Doe",
"birthDate": "1994-02-16",
"age": 30 // Backwards compatibility
}
```
## 10. Poor Error Messages
### Anti-Pattern
Vague, unhelpful, or technical error messages.
```json
Bad Examples:
{"error": "Something went wrong"}
{"error": "Invalid input"}
{"error": "SQL constraint violation: FK_user_profile_id"}
{"error": "NullPointerException at line 247"}
```
### Why It's Bad
- Doesn't help developers fix issues
- Increases support burden
- Poor developer experience
- May expose sensitive information
### Solution
```json
Good Examples:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "The email address is required and must be in a valid format",
"details": [
{
"field": "email",
"code": "REQUIRED",
"message": "Email address is required"
}
]
}
}
```
## 11. Ignoring Content Negotiation
### Anti-Pattern
Hard-coding response format without considering client preferences.
```
❌ Bad Example:
# Always returns JSON regardless of Accept header
GET /api/users/123
Accept: application/xml
# Returns JSON anyway
```
### Why It's Bad
- Reduces API flexibility
- Ignores HTTP standards
- Makes integration harder for diverse clients
### Solution
```
✅ Good Example:
GET /api/users/123
Accept: application/xml
HTTP/1.1 200 OK
Content-Type: application/xml
<?xml version="1.0"?>
<user>
<id>123</id>
<name>John Doe</name>
</user>
```
## 12. Stateful API Design
### Anti-Pattern
Maintaining session state on the server between requests.
```
❌ Bad Example:
# Step 1: Initialize session
POST /api/session/init
# Step 2: Set context (requires step 1)
POST /api/session/set-user/123
# Step 3: Get data (requires steps 1 & 2)
GET /api/session/user-data
```
### Why It's Bad
- Breaks REST statelessness principle
- Reduces scalability
- Makes caching difficult
- Complicates error recovery
### Solution
```
✅ Good Example:
# Self-contained requests
GET /api/users/123/data
Authorization: Bearer jwt-token-with-context
```
## 13. Inconsistent HTTP Method Usage
### Anti-Pattern
Using HTTP methods inappropriately or inconsistently.
```
❌ Bad Examples:
GET /api/users/123/delete # DELETE operation with GET
POST /api/users/123/get # GET operation with POST
PUT /api/users # Creating with PUT on collection
GET /api/users/search # Search with side effects
```
### Why It's Bad
- Violates HTTP semantics
- Breaks caching and idempotency expectations
- Confuses developers and tools
### Solution
```
✅ Good Examples:
DELETE /api/users/123 # Delete with DELETE
GET /api/users/123 # Get with GET
POST /api/users # Create on collection
GET /api/users?q=search # Safe search with GET
```
## 14. Missing Rate Limiting Information
### Anti-Pattern
Not providing rate limiting information to clients.
```
❌ Bad Example:
HTTP/1.1 429 Too Many Requests
{
"error": "Rate limit exceeded"
}
```
### Why It's Bad
- Clients don't know when to retry
- No information about current limits
- Difficult to implement proper backoff strategies
### Solution
```
✅ Good Example:
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1640995200
Retry-After: 3600
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "API rate limit exceeded",
"retryAfter": 3600
}
}
```
## 15. Chatty API Design
### Anti-Pattern
Requiring multiple API calls to accomplish common tasks.
```
❌ Bad Example:
# Get user profile requires 4 API calls
GET /api/users/123 # Basic info
GET /api/users/123/profile # Profile details
GET /api/users/123/settings # User settings
GET /api/users/123/stats # User statistics
```
### Why It's Bad
- Increases latency
- Creates network overhead
- Makes mobile apps inefficient
- Complicates client implementation
### Solution
```
✅ Good Examples:
# Single call with expansion
GET /api/users/123?include=profile,settings,stats
# Or provide composite endpoints
GET /api/users/123/dashboard
# Or batch operations
POST /api/batch
{
"requests": [
{"method": "GET", "url": "/users/123"},
{"method": "GET", "url": "/users/123/profile"}
]
}
```
## 16. No Input Validation
### Anti-Pattern
Accepting and processing invalid input without proper validation.
```json
Bad Example:
POST /api/users
{
"email": "not-an-email",
"age": -5,
"name": ""
}
# API processes this and fails later or stores invalid data
```
### Why It's Bad
- Leads to data corruption
- Security vulnerabilities
- Difficult to debug issues
- Poor user experience
### Solution
```json
Good Example:
POST /api/users
{
"email": "not-an-email",
"age": -5,
"name": ""
}
HTTP/1.1 400 Bad Request
{
"error": {
"code": "VALIDATION_ERROR",
"message": "The request contains invalid data",
"details": [
{
"field": "email",
"code": "INVALID_FORMAT",
"message": "Email must be a valid email address"
},
{
"field": "age",
"code": "INVALID_RANGE",
"message": "Age must be between 0 and 150"
},
{
"field": "name",
"code": "REQUIRED",
"message": "Name is required and cannot be empty"
}
]
}
}
```
## 17. Synchronous Long-Running Operations
### Anti-Pattern
Blocking the client with long-running operations in synchronous endpoints.
```
❌ Bad Example:
POST /api/reports/generate
# Client waits 30 seconds for response
```
### Why It's Bad
- Poor user experience
- Timeouts and connection issues
- Resource waste on client and server
- Doesn't scale well
### Solution
```
✅ Good Example:
# Async pattern
POST /api/reports
HTTP/1.1 202 Accepted
Location: /api/reports/job-123
{
"jobId": "job-123",
"status": "processing",
"estimatedCompletion": "2024-02-16T13:05:00Z"
}
# Check status
GET /api/reports/job-123
{
"jobId": "job-123",
"status": "completed",
"result": "/api/reports/download/report-456"
}
```
## Prevention Strategies
### 1. API Design Reviews
- Implement mandatory design reviews
- Use checklists based on these anti-patterns
- Include multiple stakeholders
### 2. API Style Guides
- Create and enforce API style guides
- Use linting tools for consistency
- Regular training for development teams
### 3. Automated Testing
- Test for common anti-patterns
- Include contract testing
- Monitor API usage patterns
### 4. Documentation Standards
- Require comprehensive API documentation
- Include examples and error scenarios
- Keep documentation up-to-date
### 5. Client Feedback
- Regularly collect feedback from API consumers
- Monitor API usage analytics
- Conduct developer experience surveys
## Conclusion
Avoiding these anti-patterns requires:
- Understanding REST principles
- Consistent design standards
- Regular review and refactoring
- Focus on developer experience
- Proper tooling and automation
Remember: A well-designed API is an asset that grows in value over time, while a poorly designed API becomes a liability that hampers development and adoption.

View File

@@ -0,0 +1,487 @@
# REST API Design Rules Reference
## Core Principles
### 1. Resources, Not Actions
REST APIs should focus on **resources** (nouns) rather than **actions** (verbs). The HTTP methods provide the actions.
```
✅ Good:
GET /users # Get all users
GET /users/123 # Get user 123
POST /users # Create new user
PUT /users/123 # Update user 123
DELETE /users/123 # Delete user 123
❌ Bad:
POST /getUsers
POST /createUser
POST /updateUser/123
POST /deleteUser/123
```
### 2. Hierarchical Resource Structure
Use hierarchical URLs to represent resource relationships:
```
/users/123/orders/456/items/789
```
But avoid excessive nesting (max 3-4 levels):
```
❌ Too deep: /companies/123/departments/456/teams/789/members/012/tasks/345
✅ Better: /tasks/345?member=012&team=789
```
## Resource Naming Conventions
### URLs Should Use Kebab-Case
```
✅ Good:
/user-profiles
/order-items
/shipping-addresses
❌ Bad:
/userProfiles
/user_profiles
/orderItems
```
### Collections vs Individual Resources
```
Collection: /users
Individual: /users/123
Sub-resource: /users/123/orders
```
### Pluralization Rules
- Use **plural nouns** for collections: `/users`, `/orders`
- Use **singular nouns** for single resources: `/user-profile`, `/current-session`
- Be consistent throughout your API
## HTTP Methods Usage
### GET - Safe and Idempotent
- **Purpose**: Retrieve data
- **Safe**: No side effects
- **Idempotent**: Multiple calls return same result
- **Request Body**: Should not have one
- **Cacheable**: Yes
```
GET /users/123
GET /users?status=active&limit=10
```
### POST - Not Idempotent
- **Purpose**: Create resources, non-idempotent operations
- **Safe**: No
- **Idempotent**: No
- **Request Body**: Usually required
- **Cacheable**: Generally no
```
POST /users # Create new user
POST /users/123/activate # Activate user (action)
```
### PUT - Idempotent
- **Purpose**: Create or completely replace a resource
- **Safe**: No
- **Idempotent**: Yes
- **Request Body**: Required (complete resource)
- **Cacheable**: No
```
PUT /users/123 # Replace entire user resource
```
### PATCH - Partial Update
- **Purpose**: Partially update a resource
- **Safe**: No
- **Idempotent**: Not necessarily
- **Request Body**: Required (partial resource)
- **Cacheable**: No
```
PATCH /users/123 # Update only specified fields
```
### DELETE - Idempotent
- **Purpose**: Remove a resource
- **Safe**: No
- **Idempotent**: Yes (same result if called multiple times)
- **Request Body**: Usually not needed
- **Cacheable**: No
```
DELETE /users/123
```
## Status Codes
### Success Codes (2xx)
- **200 OK**: Standard success response
- **201 Created**: Resource created successfully (POST)
- **202 Accepted**: Request accepted for processing (async)
- **204 No Content**: Success with no response body (DELETE, PUT)
### Redirection Codes (3xx)
- **301 Moved Permanently**: Resource permanently moved
- **302 Found**: Temporary redirect
- **304 Not Modified**: Use cached version
### Client Error Codes (4xx)
- **400 Bad Request**: Invalid request syntax or data
- **401 Unauthorized**: Authentication required
- **403 Forbidden**: Access denied (user authenticated but not authorized)
- **404 Not Found**: Resource not found
- **405 Method Not Allowed**: HTTP method not supported
- **409 Conflict**: Resource conflict (duplicates, version mismatch)
- **422 Unprocessable Entity**: Valid syntax but semantic errors
- **429 Too Many Requests**: Rate limit exceeded
### Server Error Codes (5xx)
- **500 Internal Server Error**: Unexpected server error
- **502 Bad Gateway**: Invalid response from upstream server
- **503 Service Unavailable**: Server temporarily unavailable
- **504 Gateway Timeout**: Upstream server timeout
## URL Design Patterns
### Query Parameters for Filtering
```
GET /users?status=active
GET /users?role=admin&department=engineering
GET /orders?created_after=2024-01-01&status=pending
```
### Pagination Parameters
```
# Offset-based
GET /users?offset=20&limit=10
# Cursor-based
GET /users?cursor=eyJpZCI6MTIzfQ&limit=10
# Page-based
GET /users?page=3&page_size=10
```
### Sorting Parameters
```
GET /users?sort=created_at # Ascending
GET /users?sort=-created_at # Descending (prefix with -)
GET /users?sort=last_name,first_name # Multiple fields
```
### Field Selection
```
GET /users?fields=id,name,email
GET /users/123?include=orders,profile
GET /users/123?exclude=internal_notes
```
### Search Parameters
```
GET /users?q=john
GET /products?search=laptop&category=electronics
```
## Response Format Standards
### Consistent Response Structure
```json
{
"data": {
"id": 123,
"name": "John Doe",
"email": "john@example.com"
},
"meta": {
"timestamp": "2024-02-16T13:00:00Z",
"version": "1.0"
}
}
```
### Collection Responses
```json
{
"data": [
{"id": 1, "name": "Item 1"},
{"id": 2, "name": "Item 2"}
],
"pagination": {
"total": 150,
"page": 1,
"pageSize": 10,
"totalPages": 15,
"hasNext": true,
"hasPrev": false
},
"meta": {
"timestamp": "2024-02-16T13:00:00Z"
}
}
```
### Error Response Format
```json
{
"error": {
"code": "VALIDATION_ERROR",
"message": "The request contains invalid parameters",
"details": [
{
"field": "email",
"code": "INVALID_FORMAT",
"message": "Email address is not valid"
}
],
"requestId": "req-123456",
"timestamp": "2024-02-16T13:00:00Z"
}
}
```
## Field Naming Conventions
### Use camelCase for JSON Fields
```json
Good:
{
"firstName": "John",
"lastName": "Doe",
"createdAt": "2024-02-16T13:00:00Z",
"isActive": true
}
Bad:
{
"first_name": "John",
"LastName": "Doe",
"created-at": "2024-02-16T13:00:00Z"
}
```
### Boolean Fields
Use positive, clear names with "is", "has", "can", or "should" prefixes:
```json
Good:
{
"isActive": true,
"hasPermission": false,
"canEdit": true,
"shouldNotify": false
}
Bad:
{
"active": true,
"disabled": false, // Double negative
"permission": false // Unclear meaning
}
```
### Date/Time Fields
- Use ISO 8601 format: `2024-02-16T13:00:00Z`
- Include timezone information
- Use consistent field naming:
```json
{
"createdAt": "2024-02-16T13:00:00Z",
"updatedAt": "2024-02-16T13:30:00Z",
"deletedAt": null,
"publishedAt": "2024-02-16T14:00:00Z"
}
```
## Content Negotiation
### Accept Headers
```
Accept: application/json
Accept: application/xml
Accept: application/json; version=1
```
### Content-Type Headers
```
Content-Type: application/json
Content-Type: application/json; charset=utf-8
Content-Type: multipart/form-data
```
### Versioning via Headers
```
Accept: application/vnd.myapi.v1+json
API-Version: 1.0
```
## Caching Guidelines
### Cache-Control Headers
```
Cache-Control: public, max-age=3600 # Cache for 1 hour
Cache-Control: private, max-age=0 # Don't cache
Cache-Control: no-cache, must-revalidate # Always validate
```
### ETags for Conditional Requests
```
HTTP/1.1 200 OK
ETag: "123456789"
Last-Modified: Wed, 21 Oct 2015 07:28:00 GMT
# Client subsequent request:
If-None-Match: "123456789"
If-Modified-Since: Wed, 21 Oct 2015 07:28:00 GMT
```
## Security Headers
### Authentication
```
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Authorization: Basic dXNlcjpwYXNzd29yZA==
Authorization: Api-Key abc123def456
```
### CORS Headers
```
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type, Authorization
```
## Rate Limiting
### Rate Limit Headers
```
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1640995200
X-RateLimit-Window: 3600
```
### Rate Limit Exceeded Response
```json
HTTP/1.1 429 Too Many Requests
Retry-After: 3600
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "API rate limit exceeded",
"details": {
"limit": 1000,
"window": "1 hour",
"retryAfter": 3600
}
}
}
```
## Hypermedia (HATEOAS)
### Links in Responses
```json
{
"id": 123,
"name": "John Doe",
"email": "john@example.com",
"_links": {
"self": {
"href": "/users/123"
},
"orders": {
"href": "/users/123/orders"
},
"edit": {
"href": "/users/123",
"method": "PUT"
},
"delete": {
"href": "/users/123",
"method": "DELETE"
}
}
}
```
### Link Relations
- **self**: Link to the resource itself
- **edit**: Link to edit the resource
- **delete**: Link to delete the resource
- **related**: Link to related resources
- **next/prev**: Pagination links
## Common Anti-Patterns to Avoid
### 1. Verbs in URLs
```
❌ Bad: /api/getUser/123
✅ Good: GET /api/users/123
```
### 2. Inconsistent Naming
```
❌ Bad: /user-profiles and /userAddresses
✅ Good: /user-profiles and /user-addresses
```
### 3. Deep Nesting
```
❌ Bad: /companies/123/departments/456/teams/789/members/012
✅ Good: /team-members/012?team=789
```
### 4. Ignoring HTTP Status Codes
```
❌ Bad: Always return 200 with error info in body
✅ Good: Use appropriate status codes (404, 400, 500, etc.)
```
### 5. Exposing Internal Structure
```
❌ Bad: /api/database_table_users
✅ Good: /api/users
```
### 6. No Versioning Strategy
```
❌ Bad: Breaking changes without version management
✅ Good: /api/v1/users or Accept: application/vnd.api+json;version=1
```
### 7. Inconsistent Error Responses
```
❌ Bad: Different error formats for different endpoints
✅ Good: Standardized error response structure
```
## Best Practices Summary
1. **Use nouns for resources, not verbs**
2. **Leverage HTTP methods correctly**
3. **Maintain consistent naming conventions**
4. **Implement proper error handling**
5. **Use appropriate HTTP status codes**
6. **Design for cacheability**
7. **Implement security from the start**
8. **Plan for versioning**
9. **Provide comprehensive documentation**
10. **Follow HATEOAS principles when applicable**
## Further Reading
- [RFC 7231 - HTTP/1.1 Semantics and Content](https://tools.ietf.org/html/rfc7231)
- [RFC 6570 - URI Template](https://tools.ietf.org/html/rfc6570)
- [OpenAPI Specification](https://swagger.io/specification/)
- [REST API Design Best Practices](https://www.restapitutorial.com/)
- [HTTP Status Code Definitions](https://httpstatuses.com/)