79 lines
2.2 KiB
Markdown
79 lines
2.2 KiB
Markdown
# Coding Style (Extended)
|
|
|
|
Extends the style guidelines in CLAUDE.md with patterns from ECC.
|
|
|
|
## Immutability
|
|
|
|
Create new objects — never mutate existing ones:
|
|
|
|
```typescript
|
|
// WRONG: mutation
|
|
user.name = newName;
|
|
items.push(newItem);
|
|
|
|
// RIGHT: immutable update
|
|
const updated = { ...user, name: newName };
|
|
const updatedItems = [...items, newItem];
|
|
```
|
|
|
|
```python
|
|
# WRONG: mutation
|
|
user["name"] = new_name
|
|
items.append(new_item)
|
|
|
|
# RIGHT: immutable (when it matters)
|
|
updated = {**user, "name": new_name}
|
|
updated_items = [*items, new_item]
|
|
```
|
|
|
|
Exception: Pydantic models and SQLAlchemy ORM objects are designed for mutation — use them as intended.
|
|
|
|
## File Organization
|
|
|
|
- 200-400 lines typical, 800 max per file
|
|
- High cohesion, low coupling — one concept per file
|
|
- Backend: module structure is fixed (models, schemas, repository, service, router) — don't add extra files
|
|
- Frontend: FSD layers are fixed — don't add files outside the layer structure
|
|
|
|
## Error Handling
|
|
|
|
### Frontend
|
|
- API errors: handle in TanStack Query `onError` callbacks or error boundaries
|
|
- Form validation: `react-hook-form` with inline `register()` validation rules and `Controller` for controlled components. Error messages in Russian.
|
|
- Never show raw error strings to users — map to user-friendly Russian messages
|
|
|
|
### Backend
|
|
- Raise `HTTPException` with appropriate status codes in routers
|
|
- Service layer returns data or raises domain exceptions
|
|
- Repository layer lets SQLAlchemy exceptions propagate (service handles them)
|
|
- Store error messages as named constants with `ERROR_` prefix
|
|
|
|
## Input Validation
|
|
|
|
- Frontend: TypeScript interfaces + `react-hook-form` inline rules for form data, OpenAPI-generated types for API responses
|
|
- Backend: Pydantic schemas validate all request bodies — never trust raw input
|
|
- File uploads: validate extension + MIME type in files module
|
|
- Never construct SQL from user input — SQLAlchemy handles parameterization
|
|
|
|
## Named Constants
|
|
|
|
```python
|
|
# WRONG
|
|
if status == "completed":
|
|
...
|
|
|
|
# RIGHT
|
|
JOB_STATUS_COMPLETED = "completed"
|
|
if status == JOB_STATUS_COMPLETED:
|
|
...
|
|
```
|
|
|
|
```typescript
|
|
// WRONG
|
|
if (job.status === "completed") { ... }
|
|
|
|
// RIGHT
|
|
const JOB_STATUS_COMPLETED = "completed" as const;
|
|
if (job.status === JOB_STATUS_COMPLETED) { ... }
|
|
```
|