# 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) { ... } ```