# Engineering Guidelines

## General Principles

### DRY (Don't Repeat Yourself)

- Eliminate repetitive code patterns.
- Extract common logic into reusable functions/composables.

### Co-location of Concerns

- Keep related logic together in the same file/module.
- Group all operations for a domain in one composable/service.
- Example: all trace data operations (reload, list, get) in `useTraces`.

## Backend Patterns

### Layered Architecture

Follow the 3-layer architecture:

1. Routes (controllers): thin handlers, request/response only.
2. Services: business logic and orchestration.
3. Repositories: data access/storage with thread safety.

### Thread Safety

- Flask dev server runs via `app.run(..., debug=True)` without explicit threading config.
- Use `RWLock` for shared mutable state:
  - multiple concurrent reads
  - single exclusive write
- Module-level service instances are safe if repositories are thread-safe.

### Module-Level Initialization

- Service initialization at module level is acceptable after imports.
- Preferred over lazy initialization when dependencies are stable.

```python
trace_service = TraceService(
    repository=TraceRepository(),
    parser=TraceParser(),
    dataiku_api=dataiku_api,
    logger=logger,
)
```

## Frontend Patterns

### TanStack Query Best Practices

- Use composables for all data operations: `useTraces()`, `useTrace(id)`, `useReloadTraces()`.
- Prefer cache invalidation/refetch over manual `ref` state.
- Use `useMutation` for server actions (POST/PUT/DELETE).
- Use `enabled` to orchestrate query execution.

```typescript
export function useReloadTraces() {
  const queryClient = useQueryClient()
  return useMutation({
    mutationFn: tracesService.reload,
    onSuccess: () => {
      queryClient.refetchQueries({ queryKey: ['traces'] })
    },
  })
}
```

### Vue Composable Design

- Single responsibility per composable.
- Co-locate tightly coupled functions (`useReloadTraces`, `useTraces`, `useTrace`).

### State Management

- Pinia: UI/client state (selection, filters, local preferences).
- TanStack Query: server data, cache, loading/error state.
- Avoid duplicating server data in Pinia.

## Component Development Patterns

### UI Component File Structure (shadcn-vue pattern)

```text
src/components/ui/<component-name>/
├── ComponentName.vue
└── index.ts
```

```typescript
export { default as ComponentName } from './ComponentName.vue'
export type { ComponentNameProps } from './ComponentName.vue'
```

### Composable Extraction Guidelines

Extract when:
- logic is reused across 2+ components
- state management is involved (`ref`, `reactive`)
- side effects/error handling are involved

Keep duplicated when:
- only small template markup differs
- CSS is small and likely to diverge
- abstraction would reduce flexibility

### Shared CSS Styles

When styles are reused across components, move them to `resource/frontend/src/assets/base.css`.

Examples:
- transition classes
- third-party override classes
- global typography/scrollbar styles

Keep component-specific styles inside scoped style blocks.

## Code Quality Checklist

Before submitting:

- [ ] DRY: repetitive patterns extracted
- [ ] Idiomatic: framework/library patterns respected
- [ ] Co-located: related logic grouped together
- [ ] Thread-safe: backend shared state protected
- [ ] Type-safe: TypeScript types are explicit
- [ ] Layered: routes -> services -> repositories
- [ ] Testable: logic isolated from framework glue
- [ ] Documented: complex logic includes rationale comments

## Comment Style Guidelines

### JSDoc for Functions/Composables

Use multi-line JSDoc with `@param` and `@returns`.

```typescript
/**
 * Composable for managing node highlight state in the explorer tree
 *
 * @param node - The current trace node
 * @param selectedNodeId - The ID of the currently selected node
 * @returns Computed properties for highlight state and children with highlight info
 */
```

### JSDoc for Types/Fields

Use single-line JSDoc for short field descriptions.

```typescript
/** Depth level in the tree structure, used for visual indentation */
```

### Section Headers

Use dash separators.

```typescript
// -----------------------------------------------------------------------------
// Section Name
// -----------------------------------------------------------------------------
```

### Inline Explanation Comments

- start with lowercase
- no ending period
- keep brief and descriptive

```typescript
// attempt to parse dates
// if no end time, assume instantaneous event
// filter using centralized shouldShowNode
```

### Vue Template Comments

Use HTML comments with title case.

```html
<!-- Empty State -->
<!-- Node Inspector -->
```
