Salta al contenuto principale

04 - Struttura del Codice e Organizzazione

Organizza il codice per la manutenibilità: folder structure, naming conventions, separation of concerns e gestione configurazioni con Copilot.

Cosa ne pensi di questo articolo?

04 - Struttura del Codice e Organizzazione
GitHub CopilotFoto:Christina MorilloPexels

In Breve

Organizza il codice per la manutenibilità: folder structure, naming conventions, separation of concerns e gestione configurazioni con Copilot.

Organizzare il Codice con Copilot

Una struttura del codice ben organizzata è fondamentale per la manutenibilità a lungo termine. In questo articolo vedremo come usare Copilot per definire folder structure, naming conventions, gestione delle configurazioni e pattern per un codebase pulito e professionale.

🗂️ Principi di Organizzazione del Codice

  • Coesione: File correlati stanno vicini tra loro
  • Prevedibilità: Facile trovare dove sta ogni cosa
  • Scalabilità: La struttura funziona anche quando il progetto cresce
  • Consistenza: Stesse convenzioni applicate ovunque
  • Discoverability: Un nuovo developer trova subito ciò che cerca

Panoramica della Serie

# Modulo Stato
1Foundation – Copilot come Partner✅ Completato
2Ideazione e Requisiti✅ Completato
3Architettura Backend e Frontend✅ Completato
4Struttura del Codice e Organizzazione📍 Sei qui
5Prompt Engineering e Agenti MCP⏳ Prossimo
6Testing e Qualità⏳
7Documentazione⏳
8Deploy e DevOps⏳
9Evoluzione e Manutenzione⏳

Folder Structure Backend Completa

Prompt - Backend Structure
Create a detailed folder structure for a Node.js + Express + TypeScript backend.

PROJECT: TaskFlow (time tracking + task management)
ARCHITECTURE: Layered (Controller → Service → Repository)

Requirements:
- Clean Architecture layers clearly separated
- Modular organization by feature/domain
- Clear separation of concerns
- Support for unit, integration, and e2e testing
- Environment-based configuration
- Database migrations and seeds
- Shared utilities and helpers
- API documentation structure

Show the complete tree with explanations for each folder/file.

Struttura Backend Consigliata

Backend Folder Structure
backend/
├── src/
│   ├── config/                     # 🔧 Application configuration
│   │   ├── index.ts                # Main config export (loads from env)
│   │   ├── database.config.ts      # Database connection settings
│   │   ├── auth.config.ts          # JWT, OAuth settings
│   │   ├── cors.config.ts          # CORS policy
│   │   └── rate-limit.config.ts    # Rate limiting rules
│   │
│   ├── modules/                    # 📦 Feature modules (domain-driven)
│   │   ├── users/
│   │   │   ├── users.controller.ts # HTTP handling
│   │   │   ├── users.service.ts    # Business logic
│   │   │   ├── users.repository.ts # Data access
│   │   │   ├── users.routes.ts     # Route definitions
│   │   │   ├── dto/                # Data Transfer Objects
│   │   │   │   ├── create-user.dto.ts
│   │   │   │   ├── update-user.dto.ts
│   │   │   │   └── user-response.dto.ts
│   │   │   ├── entities/           # Domain entities
│   │   │   │   └── user.entity.ts
│   │   │   └── __tests__/          # Module-specific tests
│   │   │       ├── users.service.spec.ts
│   │   │       └── users.controller.spec.ts
│   │   │
│   │   ├── auth/
│   │   │   ├── auth.controller.ts
│   │   │   ├── auth.service.ts
│   │   │   ├── strategies/         # Passport strategies
│   │   │   │   ├── jwt.strategy.ts
│   │   │   │   └── local.strategy.ts
│   │   │   ├── dto/
│   │   │   └── auth.routes.ts
│   │   │
│   │   ├── tasks/
│   │   │   ├── tasks.controller.ts
│   │   │   ├── tasks.service.ts
│   │   │   ├── tasks.repository.ts
│   │   │   ├── tasks.routes.ts
│   │   │   ├── dto/
│   │   │   ├── entities/
│   │   │   └── __tests__/
│   │   │
│   │   └── time-entries/
│   │       └── ... (same structure)
│   │
│   ├── shared/                     # 🔄 Shared across modules
│   │   ├── middleware/
│   │   │   ├── auth.middleware.ts
│   │   │   ├── validation.middleware.ts
│   │   │   ├── rate-limit.middleware.ts
│   │   │   └── request-logger.middleware.ts
│   │   ├── guards/
│   │   │   ├── roles.guard.ts
│   │   │   └── ownership.guard.ts
│   │   ├── decorators/
│   │   │   ├── current-user.decorator.ts
│   │   │   └── roles.decorator.ts
│   │   ├── errors/
│   │   │   ├── app-error.ts
│   │   │   ├── validation.error.ts
│   │   │   ├── not-found.error.ts
│   │   │   └── unauthorized.error.ts
│   │   ├── utils/
│   │   │   ├── hash.util.ts
│   │   │   ├── jwt.util.ts
│   │   │   ├── pagination.util.ts
│   │   │   └── date.util.ts
│   │   └── types/
│   │       ├── express.d.ts        # Express type extensions
│   │       └── common.types.ts
│   │
│   ├── database/                   # 💾 Database setup
│   │   ├── connection.ts           # DB connection pool
│   │   ├── migrations/             # Schema migrations
│   │   │   ├── 001_create_users.ts
│   │   │   ├── 002_create_tasks.ts
│   │   │   └── 003_create_time_entries.ts
│   │   ├── seeds/                  # Test/dev data
│   │   │   ├── users.seed.ts
│   │   │   └── tasks.seed.ts
│   │   └── queries/                # Complex SQL queries
│   │       └── reports.queries.ts
│   │
│   ├── api/                        # 🌐 API versioning
│   │   ├── v1/
│   │   │   └── index.ts            # v1 router aggregator
│   │   └── index.ts                # Main API router
│   │
│   ├── app.ts                      # Express app setup
│   └── server.ts                   # Entry point (starts server)
│
├── tests/                          # 🧪 Test files (by type)
│   ├── unit/                       # Isolated unit tests
│   ├── integration/                # API integration tests
│   │   └── users.integration.spec.ts
│   ├── e2e/                        # End-to-end tests
│   ├── fixtures/                   # Test data
│   │   └── users.fixture.ts
│   └── helpers/                    # Test utilities
│       ├── db.helper.ts            # Test DB setup/teardown
│       └── auth.helper.ts          # Get test tokens
│
├── scripts/                        # 📜 Utility scripts
│   ├── migrate.ts                  # Run migrations
│   ├── seed.ts                     # Seed database
│   └── generate-types.ts           # Generate TS from DB
│
├── docs/                           # 📚 Documentation
│   ├── api/                        # OpenAPI specs
│   │   └── openapi.yaml
│   └── adr/                        # Architecture Decision Records
│       └── 001-database-choice.md
│
├── .env.example                    # Environment template
├── .env.test                       # Test environment
├── tsconfig.json
├── jest.config.js
├── package.json
└── README.md

Folder Structure Frontend Completa

Frontend Folder Structure
frontend/
├── src/
│   ├── app/
│   │   ├── core/                   # 🔧 Singleton services (providedIn: 'root')
│   │   │   ├── services/
│   │   │   │   ├── api.service.ts           # HTTP client wrapper
│   │   │   │   ├── auth.service.ts          # Auth state management
│   │   │   │   ├── storage.service.ts       # LocalStorage/SessionStorage
│   │   │   │   ├── toast.service.ts         # Notification service
│   │   │   │   └── theme.service.ts         # Dark/light mode
│   │   │   ├── guards/
│   │   │   │   ├── auth.guard.ts            # Protect routes
│   │   │   │   ├── guest.guard.ts           # Redirect if logged in
│   │   │   │   └── unsaved-changes.guard.ts # Prevent accidental navigation
│   │   │   ├── interceptors/
│   │   │   │   ├── auth.interceptor.ts      # Add JWT to requests
│   │   │   │   ├── error.interceptor.ts     # Global error handling
│   │   │   │   ├── loading.interceptor.ts   # Show/hide loading
│   │   │   │   └── retry.interceptor.ts     # Retry failed requests
│   │   │   └── models/
│   │   │       ├── api-response.model.ts
│   │   │       └── user.model.ts
│   │   │
│   │   ├── shared/                 # 🔄 Reusable components (import in features)
│   │   │   ├── components/
│   │   │   │   ├── ui/                      # Design system primitives
│   │   │   │   │   ├── button/
│   │   │   │   │   │   ├── button.component.ts
│   │   │   │   │   │   ├── button.component.html
│   │   │   │   │   │   ├── button.component.scss
│   │   │   │   │   │   └── button.component.spec.ts
│   │   │   │   │   ├── input/
│   │   │   │   │   ├── select/
│   │   │   │   │   ├── checkbox/
│   │   │   │   │   ├── modal/
│   │   │   │   │   ├── tooltip/
│   │   │   │   │   └── dropdown/
│   │   │   │   ├── layout/                  # Layout components
│   │   │   │   │   ├── card/
│   │   │   │   │   ├── page-header/
│   │   │   │   │   └── empty-state/
│   │   │   │   └── feedback/                # Feedback components
│   │   │   │       ├── loading-spinner/
│   │   │   │       ├── skeleton/
│   │   │   │       ├── error-message/
│   │   │   │       └── toast/
│   │   │   ├── directives/
│   │   │   │   ├── click-outside.directive.ts
│   │   │   │   ├── autofocus.directive.ts
│   │   │   │   ├── debounce-click.directive.ts
│   │   │   │   └── tooltip.directive.ts
│   │   │   ├── pipes/
│   │   │   │   ├── time-ago.pipe.ts
│   │   │   │   ├── duration.pipe.ts
│   │   │   │   ├── truncate.pipe.ts
│   │   │   │   └── highlight.pipe.ts
│   │   │   └── index.ts                     # Barrel export
│   │   │
│   │   ├── features/               # 📦 Feature modules (lazy loaded)
│   │   │   ├── auth/
│   │   │   │   ├── components/
│   │   │   │   │   ├── login-form/
│   │   │   │   │   ├── register-form/
│   │   │   │   │   └── forgot-password-form/
│   │   │   │   ├── pages/
│   │   │   │   │   ├── login.page.ts
│   │   │   │   │   ├── register.page.ts
│   │   │   │   │   └── forgot-password.page.ts
│   │   │   │   ├── services/
│   │   │   │   │   └── auth-api.service.ts
│   │   │   │   ├── models/
│   │   │   │   │   └── auth.model.ts
│   │   │   │   └── auth.routes.ts
│   │   │   │
│   │   │   ├── tasks/
│   │   │   │   ├── components/
│   │   │   │   │   ├── task-list/
│   │   │   │   │   ├── task-item/
│   │   │   │   │   ├── task-form/
│   │   │   │   │   ├── task-timer/
│   │   │   │   │   └── task-filters/
│   │   │   │   ├── pages/
│   │   │   │   │   ├── tasks-list.page.ts
│   │   │   │   │   └── task-detail.page.ts
│   │   │   │   ├── services/
│   │   │   │   │   └── tasks-api.service.ts
│   │   │   │   ├── state/                   # Feature-specific state
│   │   │   │   │   └── tasks.store.ts       # Signals-based store
│   │   │   │   ├── models/
│   │   │   │   │   └── task.model.ts
│   │   │   │   └── tasks.routes.ts
│   │   │   │
│   │   │   ├── dashboard/
│   │   │   │   ├── components/
│   │   │   │   │   ├── stats-card/
│   │   │   │   │   ├── recent-tasks/
│   │   │   │   │   ├── time-summary/
│   │   │   │   │   └── quick-actions/
│   │   │   │   ├── pages/
│   │   │   │   │   └── dashboard.page.ts
│   │   │   │   └── dashboard.routes.ts
│   │   │   │
│   │   │   └── settings/
│   │   │       ├── components/
│   │   │       ├── pages/
│   │   │       └── settings.routes.ts
│   │   │
│   │   ├── layouts/                # 🖼️ Layout components
│   │   │   ├── main-layout/
│   │   │   │   ├── main-layout.component.ts
│   │   │   │   ├── components/
│   │   │   │   │   ├── header/
│   │   │   │   │   ├── sidebar/
│   │   │   │   │   └── footer/
│   │   │   └── auth-layout/
│   │   │       └── auth-layout.component.ts
│   │   │
│   │   ├── app.component.ts
│   │   ├── app.routes.ts           # Root routes
│   │   └── app.config.ts           # App providers
│   │
│   ├── assets/
│   │   ├── images/
│   │   ├── icons/
│   │   │   └── svg/                # SVG icons
│   │   └── fonts/
│   │
│   ├── styles/
│   │   ├── _variables.scss         # Design tokens
│   │   ├── _mixins.scss            # SCSS mixins
│   │   ├── _typography.scss        # Typography rules
│   │   ├── _utilities.scss         # Utility classes
│   │   └── global.scss             # Global styles
│   │
│   └── environments/
│       ├── environment.ts
│       └── environment.prod.ts
│
├── angular.json
├── tsconfig.json
└── package.json

Naming Conventions

Naming consistente aiuta Copilot a generare codice coerente e rende il codebase più leggibile per tutti i membri del team (incluso te stesso tra 6 mesi).

📝 Convenzioni di Naming

Tipo Convenzione Esempio
File (general) kebab-case user-profile.component.ts
Classe PascalCase UserProfileComponent
Variabile/Funzione camelCase getUserProfile()
Costante SCREAMING_SNAKE_CASE MAX_RETRY_COUNT
Interfaccia PascalCase (no I prefix) UserProfile
Type PascalCase TaskStatus
Enum PascalCase UserRole
Enum member SCREAMING_SNAKE_CASE UserRole.ADMIN
Boolean variable is/has/can prefix isLoading, hasError
Event handler on/handle prefix onSubmit, handleClick
Observable $ suffix users$, isLoading$
Signal no suffix (Angular 18+) users, isLoading

Suffissi Consigliati per File

Backend

Naming Patterns - Backend
// Controllers
user.controller.ts     → UserController

// Services
user.service.ts        → UserService

// Repositories
user.repository.ts     → UserRepository

// Entities
user.entity.ts         → User

// DTOs
create-user.dto.ts     → CreateUserDto
update-user.dto.ts     → UpdateUserDto

// Middleware
auth.middleware.ts     → authMiddleware

// Guards
roles.guard.ts         → RolesGuard

// Routes
user.routes.ts         → userRoutes

Frontend (Angular)

Naming Patterns - Frontend
// Components
user-list.component.ts → UserListComponent

// Pages (Smart Components)
users-list.page.ts     → UsersListPage

// Services
user.service.ts        → UserService
user-api.service.ts    → UserApiService

// Models
user.model.ts          → User (interface)

// Guards
auth.guard.ts          → authGuard (function)

// Interceptors
auth.interceptor.ts    → authInterceptor

// Pipes
time-ago.pipe.ts       → TimeAgoPipe

// Directives
tooltip.directive.ts   → TooltipDirective

Separation of Concerns

Ogni file/classe dovrebbe avere una singola responsabilità chiara. Questo rende il codice più testabile, riutilizzabile e manutenibile.

❌ Sbagliato: God Controller

// user.controller.ts - TUTTO insieme
class UserController {{ '{' }}
  async create(req, res) {{ '{' }}
    // 1. Validation (dovrebbe essere in middleware)
    if (!req.body.email) {{ '{' }}
      return res.status(400).json(...);
    {{ '}' }}
    if (!/^[^\s@]+@[^\s@]+$/.test(req.body.email)) {{ '{' }}
      return res.status(400).json(...);
    {{ '}' }}

    // 2. Business logic (dovrebbe essere in service)
    const exists = await db.query('SELECT...');
    if (exists) throw new Error('...');

    const hashedPassword = await bcrypt.hash(...);

    // 3. Database (dovrebbe essere in repository)
    await db.query('INSERT INTO users...');

    // 4. Send email (dovrebbe essere in service)
    await sendgrid.send({{ '{' }}
      to: req.body.email,
      subject: 'Welcome!',
      ...
    {{ '}' }});

    res.json({{ '{' }} success: true {{ '}' }});
  {{ '}' }}
{{ '}' }}

✅ Corretto: Responsabilità Separate

// Controller: SOLO HTTP handling
async create(req, res, next) {{ '{' }}
  try {{ '{' }}
    const user = await this.userService
      .createUser(req.body);
    res.status(201).json({{ '{' }} data: user {{ '}' }});
  {{ '}' }} catch (err) {{ '{' }}
    next(err);
  {{ '}' }}
{{ '}' }}

// Service: SOLO business logic
async createUser(dto: CreateUserDto) {{ '{' }}
  await this.validateUniqueEmail(dto.email);
  const user = new User(dto);
  const saved = await this.userRepo.save(user);
  await this.emailService.sendWelcome(saved);
  return saved;
{{ '}' }}

// Repository: SOLO data access
async save(user: User): Promise<User> {{ '{' }}
  return this.db.users.create(user);
{{ '}' }}

// EmailService: SOLO email
async sendWelcome(user: User) {{ '{' }}
  await this.mailer.send({{ '{' }}...{{ '}' }});
{{ '}' }}

Gestione Configurazioni

Centralizza le configurazioni per ambiente con validazione e type safety.

TypeScript - Config Management
// config/index.ts
import dotenv from 'dotenv';
import {{ '{' }} z {{ '}' }} from 'zod';

// Load .env file
dotenv.config();

// Define schema with validation
const configSchema = z.object({{ '{' }}
  // Environment
  NODE_ENV: z.enum(['development', 'test', 'production']).default('development'),
  PORT: z.string().transform(Number).default('3000'),

  // Database
  DATABASE_URL: z.string().url(),
  DATABASE_POOL_MIN: z.string().transform(Number).default('2'),
  DATABASE_POOL_MAX: z.string().transform(Number).default('10'),

  // Authentication
  JWT_SECRET: z.string().min(32),
  JWT_EXPIRES_IN: z.string().default('7d'),
  BCRYPT_ROUNDS: z.string().transform(Number).default('12'),

  // CORS
  CORS_ORIGIN: z.string().default('http://localhost:4200'),

  // External Services (optional in dev)
  SENDGRID_API_KEY: z.string().optional(),
  SENTRY_DSN: z.string().optional(),
{{ '}' }});

// Parse and validate
const parsed = configSchema.safeParse(process.env);

if (!parsed.success) {{ '{' }}
  console.error('❌ Invalid environment variables:');
  console.error(parsed.error.format());
  process.exit(1);
{{ '}' }}

// Export typed config
export const config = {{ '{' }}
  env: parsed.data.NODE_ENV,
  port: parsed.data.PORT,
  isProduction: parsed.data.NODE_ENV === 'production',
  isDevelopment: parsed.data.NODE_ENV === 'development',

  database: {{ '{' }}
    url: parsed.data.DATABASE_URL,
    pool: {{ '{' }}
      min: parsed.data.DATABASE_POOL_MIN,
      max: parsed.data.DATABASE_POOL_MAX,
    {{ '}' }},
  {{ '}' }},

  jwt: {{ '{' }}
    secret: parsed.data.JWT_SECRET,
    expiresIn: parsed.data.JWT_EXPIRES_IN,
  {{ '}' }},

  bcrypt: {{ '{' }}
    rounds: parsed.data.BCRYPT_ROUNDS,
  {{ '}' }},

  cors: {{ '{' }}
    origin: parsed.data.CORS_ORIGIN.split(','),
  {{ '}' }},

  sendgrid: {{ '{' }}
    apiKey: parsed.data.SENDGRID_API_KEY,
  {{ '}' }},

  sentry: {{ '{' }}
    dsn: parsed.data.SENTRY_DSN,
  {{ '}' }},
{{ '}' }} as const;

// Type for config
export type Config = typeof config;

File .env.example

.env.example
# ═══════════════════════════════════════════════════════════
# TaskFlow Backend Configuration
# Copy this file to .env and fill in your values
# ═══════════════════════════════════════════════════════════

# ─────────────────────────────────────────────────────────────
# Environment
# ─────────────────────────────────────────────────────────────
NODE_ENV=development
PORT=3000

# ─────────────────────────────────────────────────────────────
# Database (PostgreSQL)
# ─────────────────────────────────────────────────────────────
DATABASE_URL=postgresql://user:password@localhost:5432/taskflow
DATABASE_POOL_MIN=2
DATABASE_POOL_MAX=10

# ─────────────────────────────────────────────────────────────
# Authentication
# ─────────────────────────────────────────────────────────────
# Generate with: openssl rand -base64 32
JWT_SECRET=your-super-secret-key-at-least-32-chars
JWT_EXPIRES_IN=7d
BCRYPT_ROUNDS=12

# ─────────────────────────────────────────────────────────────
# CORS
# ─────────────────────────────────────────────────────────────
CORS_ORIGIN=http://localhost:4200

# ─────────────────────────────────────────────────────────────
# External Services (optional for development)
# ─────────────────────────────────────────────────────────────
# SENDGRID_API_KEY=SG.xxxxx
# SENTRY_DSN=https://xxxxx@sentry.io/xxxxx

Index Files e Barrel Exports

Usa file index.ts per export puliti e import semplificati.

TypeScript - Barrel Exports
// ═══════════════════════════════════════════════════════════
// shared/components/index.ts - Barrel Export
// ═══════════════════════════════════════════════════════════
// UI Components
export {{ '{' }} ButtonComponent {{ '}' }} from './ui/button/button.component';
export {{ '{' }} InputComponent {{ '}' }} from './ui/input/input.component';
export {{ '{' }} SelectComponent {{ '}' }} from './ui/select/select.component';
export {{ '{' }} ModalComponent {{ '}' }} from './ui/modal/modal.component';

// Layout Components
export {{ '{' }} CardComponent {{ '}' }} from './layout/card/card.component';
export {{ '{' }} PageHeaderComponent {{ '}' }} from './layout/page-header/page-header.component';
export {{ '{' }} EmptyStateComponent {{ '}' }} from './layout/empty-state/empty-state.component';

// Feedback Components
export {{ '{' }} LoadingSpinnerComponent {{ '}' }} from './feedback/loading-spinner/loading-spinner.component';
export {{ '{' }} SkeletonComponent {{ '}' }} from './feedback/skeleton/skeleton.component';
export {{ '{' }} ToastComponent {{ '}' }} from './feedback/toast/toast.component';

// ═══════════════════════════════════════════════════════════
// Usage in feature module
// ═══════════════════════════════════════════════════════════
// PRIMA (senza barrel)
import {{ '{' }} ButtonComponent {{ '}' }} from '../../../shared/components/ui/button/button.component';
import {{ '{' }} InputComponent {{ '}' }} from '../../../shared/components/ui/input/input.component';
import {{ '{' }} CardComponent {{ '}' }} from '../../../shared/components/layout/card/card.component';

// DOPO (con barrel) ✅
import {{ '{' }}
  ButtonComponent,
  InputComponent,
  CardComponent
{{ '}' }} from '@shared/components';

// ═══════════════════════════════════════════════════════════
// tsconfig.json - Path aliases
// ═══════════════════════════════════════════════════════════
{{ '{' }}
  "compilerOptions": {{ '{' }}
    "baseUrl": "./src",
    "paths": {{ '{' }}
      "@shared/*": ["app/shared/*"],
      "@core/*": ["app/core/*"],
      "@features/*": ["app/features/*"],
      "@environments/*": ["environments/*"]
    {{ '}' }}
  {{ '}' }}
{{ '}' }}

Organizzazione degli Import

TypeScript - Import Order
// ═══════════════════════════════════════════════════════════
// Ordine consigliato degli import
// ═══════════════════════════════════════════════════════════

// 1. Angular/Framework imports
import {{ '{' }} Component, OnInit, inject {{ '}' }} from '@angular/core';
import {{ '{' }} CommonModule {{ '}' }} from '@angular/common';
import {{ '{' }} RouterModule {{ '}' }} from '@angular/router';
import {{ '{' }} FormBuilder, ReactiveFormsModule {{ '}' }} from '@angular/forms';

// 2. Third-party library imports
import {{ '{' }} Observable {{ '}' }} from 'rxjs';
import {{ '{' }} map, catchError {{ '}' }} from 'rxjs/operators';

// 3. Core/Shared imports (using path aliases)
import {{ '{' }} AuthService {{ '}' }} from '@core/services/auth.service';
import {{ '{' }} ButtonComponent, CardComponent {{ '}' }} from '@shared/components';
import {{ '{' }} TimeAgoPipe {{ '}' }} from '@shared/pipes';

// 4. Feature-specific imports (relative paths)
import {{ '{' }} TasksApiService {{ '}' }} from './services/tasks-api.service';
import {{ '{' }} TaskItemComponent {{ '}' }} from './components/task-item/task-item.component';
import {{ '{' }} Task {{ '}' }} from './models/task.model';

// 5. Constants and types
import {{ '{' }} TASK_STATUS {{ '}' }} from './constants/task.constants';
import type {{ '{' }} TaskFilters {{ '}' }} from './types/task.types';

File Templates per Copilot

Crea template che Copilot può usare come riferimento per generare codice consistente.

Template - Angular Component
// ═══════════════════════════════════════════════════════════
// Template: Angular Standalone Component
// ═══════════════════════════════════════════════════════════
import {{ '{' }} Component, Input, Output, EventEmitter, ChangeDetectionStrategy {{ '}' }} from '@angular/core';
import {{ '{' }} CommonModule {{ '}' }} from '@angular/common';

/**
 * [ComponentName] - [Brief description]
 *
 * @example
 * <app-[component-name]
 *   [inputProp]="value"
 *   (outputEvent)="handler($event)"
 * />
 */
@Component({{ '{' }}
  selector: 'app-[component-name]',
  standalone: true,
  imports: [CommonModule],
  templateUrl: './[component-name].component.html',
  styleUrl: './[component-name].component.scss',
  changeDetection: ChangeDetectionStrategy.OnPush,
{{ '}' }})
export class [ComponentName]Component {{ '{' }}
  // ─────────────────────────────────────────────────────────
  // Inputs
  // ─────────────────────────────────────────────────────────
  @Input() inputProp: string = '';

  // ─────────────────────────────────────────────────────────
  // Outputs
  // ─────────────────────────────────────────────────────────
  @Output() outputEvent = new EventEmitter<void>();

  // ─────────────────────────────────────────────────────────
  // Public methods
  // ─────────────────────────────────────────────────────────
  onAction(): void {{ '{' }}
    this.outputEvent.emit();
  {{ '}' }}
{{ '}' }}

Checklist Organizzazione Codice

✅ Checklist

Item Completato
Folder structure definita e documentata☐
Naming conventions documentate☐
Path aliases configurati in tsconfig☐
Barrel exports per shared modules☐
Config management centralizzato con validazione☐
.env.example con tutte le variabili☐
ESLint/Prettier configurato☐
Husky + lint-staged per pre-commit hooks☐

Conclusione

Una struttura del codice ben organizzata paga dividendi per tutta la vita del progetto. Investire tempo nella definizione di convenzioni chiare rende lo sviluppo più veloce, il codice più manutenibile e l'onboarding di nuovi contributor (o di te stesso tra 6 mesi) molto più semplice.

🎯 Punti Chiave dell'Articolo

  • Feature-Based Structure: Organizza per feature, non per tipo di file
  • Naming Conventions: kebab-case per file, PascalCase per classi
  • Separation of Concerns: Controller → Service → Repository
  • Config Management: Centralizza con validazione schema (Zod)
  • Barrel Exports: Index.ts per import puliti
  • Path Aliases: @shared, @core, @features per evitare ../../../

📚 Prossimo Articolo

Nel prossimo articolo "Prompt Engineering e Agenti MCP" vedremo tecniche avanzate per scrivere prompt efficaci e come configurare agenti MCP per contesto persistente nel progetto.

Prova Questi Strumenti

Strumenti gratuiti correlati a questo argomento.

Commenti

Caricamento commenti...

Accedi per commentare

Discuti questo articolo nella community

Unisciti al gruppo Telegram per discutere con altri sviluppatori, fare domande e condividere le tue esperienze.

Ti è piaciuto questo articolo?

Esplora altri contenuti sul blog o scopri i miei progetti