# Feature-First Architecture

Organize code by features instead of layers for better maintainability and team scalability.

## Overview

**Feature-first** organizes code by business features, with each feature containing all layers needed for that feature.

```
lib/
├── features/
│   ├── auth/
│   │   ├── data/
│   │   │   ├── repositories/
│   │   │   └── services/
│   │   ├── domain/
│   │   │   ├── models/
│   │   │   └── use-cases/
│   │   └── presentation/
│   │       ├── views/
│   │       └── viewmodels/
│   ├── todos/
│   │   ├── data/
│   │   ├── domain/
│   │   └── presentation/
│   └── settings/
│       ├── data/
│       ├── domain/
│       └── presentation/
├── shared/
│   ├── core/
│   │   ├── constants/
│   │   ├── theme/
│   │   └── utils/
│   ├── data/
│   │   ├── models/
│   │   └── services/
│   └── ui/
│       ├── widgets/
│       └── components/
└── main.dart
```

## Feature-First vs Layer-First

### Layer-First (Traditional)

```
lib/
├── data/
│   ├── repositories/
│   ├── services/
│   └── models/
├── domain/
│   ├── use-cases/
│   └── entities/
├── presentation/
│   ├── views/
│   └── viewmodels/
└── shared/
```

**When to use:**
- Small to medium apps
- Few features (<10)
- Solo developers or small teams
- Simple business logic

**Pros:**
- Clear separation by layer
- Easy to find components by type
- Less nesting

**Cons:**
- Harder to delete features
- Changes often span multiple folders
- Tangled dependencies between layers

### Feature-First (Recommended for teams)

```
lib/
├── features/
│   ├── auth/
│   │   ├── data/
│   │   ├── domain/
│   │   └── presentation/
│   └── todos/
│       ├── data/
│       ├── domain/
│       └── presentation/
└── shared/
```

**When to use:**
- Medium to large apps
- Many features (10+)
- Team development (2+ developers)
- Complex business logic
- Frequently adding/removing features

**Pros:**
- Features are self-contained units
- Easy to add/remove entire features
- Clear feature boundaries
- Reduced merge conflicts
- Teams work independently on features

**Cons:**
- More nesting in folder structure
- Shared code requires careful organization
- Can duplicate similar code across features

## Feature Structure

Each feature contains all layers for that feature:

```
features/
└── todos/
    ├── data/
    │   ├── repositories/
    │   │   └── todo_repository.dart
    │   └── services/
    │       └── todo_api_service.dart
    ├── domain/
    │   ├── models/
    │   │   └── todo.dart
    │   └── use-cases/
    │       └── fetch_todos.dart
    │       └── create_todo.dart
    │       └── delete_todo.dart
    └── presentation/
        ├── views/
        │   └── todo_list_view.dart
        └── viewmodels/
            └── todo_list_viewmodel.dart
```

### Naming Conventions

**Feature folders:** Plural, lowercase, underscore-separated
- `auth/`, `todos/`, `user_profile/`

**Component folders:** Plural, lowercase
- `data/`, `domain/`, `presentation/`
- `repositories/`, `services/`, `models/`
- `views/`, `viewmodels/`

**Files:** snake_case for regular files, camelCase for classes
- `todo_repository.dart` → `class TodoRepository`
- `todo_list_view.dart` → `class TodoListView`
- `fetch_todos.dart` → `class FetchTodos`

## Shared Code

Code used across multiple features goes in `shared/`:

```
shared/
├── core/
│   ├── constants/
│   │   └── app_constants.dart
│   ├── theme/
│   │   ├── app_colors.dart
│   │   └── app_text_styles.dart
│   └── utils/
│       ├── extensions.dart
│       ├── validators.dart
│       └── formatters.dart
├── data/
│   ├── models/
│   │   └── common_models.dart
│   └── services/
│       ├── network_service.dart
│       ├── local_storage_service.dart
│       └── analytics_service.dart
└── ui/
    ├── widgets/
    │   ├── app_scaffold.dart
    │   ├── loading_indicator.dart
    │   └── error_widget.dart
    └── components/
        ├── app_button.dart
        ├── app_text_field.dart
        └── app_card.dart
```

### What goes in `shared/core/`

- **Constants**: App-wide constants (API URLs, timeouts)
- **Theme**: Colors, text styles, themes
- **Utils**: Extensions, validators, formatters used across features

### What goes in `shared/data/`

- **Models**: Domain models used by multiple features (User, etc.)
- **Services**: Platform services (network, storage, analytics)

### What goes in `shared/ui/`

- **Widgets**: Reusable UI components (scaffolds, indicators)
- **Components**: Reusable UI elements (buttons, cards, inputs)

## Dependency Rules

### Within a Feature

```
presentation/ -> domain/ -> data/
presentation/ -> data/        // simple flows can skip domain
presentation/ -> shared/ui/
data/ -> shared/data/
```

- **Presentation ViewModels** can use Domain, Data for simple flows, and
  Shared/UI. Views should still talk to ViewModels, not Services.
- **Domain layer** can use feature data abstractions and shared pure utilities.
- **Data layer** can use Shared/Data services or models.
- **Domain layer is optional**. Add use-cases only for complex, reused, or
  multi-repository business logic.

### Between Features

**Features should NOT import each other's implementation files.**

If Feature A needs Feature B's functionality:
1. Move common logic to `shared/`
2. Use dependency injection with a stable interface
3. Consider if features should be merged

```dart
// ❌ BAD: Feature depending on another feature
import 'package:my_app/features/auth/data/repositories/auth_repository.dart';

// ✅ GOOD: Using shared service
import 'package:my_app/shared/data/services/auth_service.dart';

// ✅ GOOD: Depending on a stable shared interface provided through DI
import 'package:my_app/shared/data/auth_session.dart';
```

## When to Add a New Feature

1. **Create feature folder:**
   ```
   features/new_feature/
   ├── data/
   └── presentation/
   ```

2. **Add subfolders based on complexity:**
   - Simple: Skip `domain/`, use only `data/` and `presentation/`
   - Complex: Add `domain/` for use-cases

3. **Implement bottom-up:**
   - Add models in `data/` or `domain/models/`
   - Add services in `data/services/`
   - Add repositories in `data/repositories/`
   - Add viewmodels in `presentation/viewmodels/`
   - Add views in `presentation/views/`

4. **Add exports:**
   ```dart
   // features/new_feature/new_feature.dart
   export 'data/repositories/new_feature_repository.dart';
   export 'presentation/views/new_feature_view.dart';
   export 'presentation/viewmodels/new_feature_viewmodel.dart';
   ```

5. **Register in DI container** (main.dart)

## Best Practices

### 1. Barrel Files

Export feature contents from barrel file:

```dart
// features/todos/todos.dart
library todos;

export 'data/repositories/todo_repository.dart';
export 'domain/models/todo.dart';
export 'domain/use-cases/fetch_todos.dart';
export 'presentation/views/todo_list_view.dart';
export 'presentation/viewmodels/todo_list_viewmodel.dart';
```

Usage:
```dart
import 'package:my_app/features/todos/todos.dart';

// Now have access to Todo, TodoRepository, etc.
```

### 2. Lazy Loading

For large apps, use lazy loading:

```dart
// In router
GoRoute(
  path: '/todos',
  builder: (context, state) => const LazyLoad(
    builder: () => const TodosView(),
  ),
);
```

### 3. Feature Scoping

Keep feature dependencies minimal:
- Use `shared/` for common code
- Avoid imports from another feature's `data/` or `presentation/`
- When needed, use dependency inversion through an interface

### 4. Testing

Each feature is testable independently:

```
features/
└── todos/
    ├── data/
    │   └── repositories/
    │       └── todo_repository_test.dart
    ├── domain/
    │   └── use-cases/
    │       └── fetch_todos_test.dart
    └── presentation/
        └── viewmodels/
            └── todo_list_viewmodel_test.dart
```

## Migration from Layer-First

Gradual migration strategy:

1. **Start with new features:**
   - Add new features using feature-first
   - Keep old code in layer-first

2. **Migrate one feature at a time:**
   ```
   // Before (layer-first)
   data/
     ├── todo_repository.dart
     └── user_repository.dart
   presentation/
     ├── todo_view.dart
     └── user_view.dart

   // After (feature-first)
   features/
     ├── todos/
     │   ├── data/repositories/todo_repository.dart
     │   └── presentation/views/todo_view.dart
     └── users/
         ├── data/repositories/user_repository.dart
         └── presentation/views/user_view.dart
   ```

3. **Move shared code to `shared/`:**
   - Identify cross-feature code
   - Move to appropriate `shared/` folder
   - Update imports

4. **Update barrel files** for clean imports

## Example: Complete Feature

```
features/
└── todos/
    ├── todos.dart                    // Barrel file
    ├── data/
    │   ├── models/
    │   │   └── todo_model.dart       // DTOs from API
    │   ├── repositories/
    │   │   └── todo_repository.dart  // SSOT for todos
    │   └── services/
    │       └── todo_api_service.dart   // API calls
    ├── domain/
    │   ├── models/
    │   │   └── todo.dart             // Domain entity
    │   └── use-cases/
    │       ├── fetch_todos.dart
    │       ├── create_todo.dart
    │       └── update_todo.dart
    │       └── delete_todo.dart
    └── presentation/
        ├── viewmodels/
        │   └── todo_list_viewmodel.dart
        └── views/
            └── todo_list_view.dart
```

This structure provides:
- Complete feature encapsulation
- Clear layer separation within feature
- Easy to add/remove entire feature
- Minimal dependencies on other features
