Project Design
Completamos todo o material das Fases 1-4. Charlie agora vai integrar todo esse conhecimento para projetar uma plataforma e-commerce MegaShop completa. Da análise de requisitos ao design de arquitetura, e dos modelos de dados às especificações de API, este é o primeiro passo no projeto prático.
1. O Que Você Vai Aprender
- Análise de Requisitos: Funções de Usuário (Alice/Bob/Charlie) e Decomposição de Módulos Funcionais
- Arquitetura: Renderização híbrida SSR + ISR + Nitro API + Prisma + Redis
- Modelo de Dados: Design de Diagrama ER + Prisma Schema
- Especificações de API: Design RESTful API + Gerenciamento de Versão + Códigos de Erro
- Decisões e Justificativas de Escolha Tecnológica
2. Uma História Real de um Arquiteto
(1) Dor: Desenvolvimento Sem Design
Charlie havia instruído a equipe a começar a escrever código imediatamente sem nenhuma documentação de design. Como resultado, a estrutura de dados do carrinho de compras de Alice não correspondia aos dados de pedido de Bob, a nomenclatura da API era caótica, o banco de dados não tinha índices, as consultas eram lentas, e o custo de fazer alterações depois era enorme.
(2) Soluções de Design de Sistema
Design Primeiro, Depois Desenvolver—Use diagramas ER para definir o modelo de dados, especificações RESTful para definir a API, e diagramas de arquitetura para definir os limites do sistema. Gaste uma semana extra na fase de design e economize três semanas durante o desenvolvimento.
(3) Benefícios: Um Roteiro Claro
Quando cada desenvolvedor se refere ao mesmo documento de design—com estruturas de dados consistentes, especificações de API unificadas e limites arquiteturais claros—a eficiência da colaboração triplica.
3. Análise de Requisitos
(1) Funções de Usuário e Necessidades Centrais
| Função | Identidade | Necessidades Centrais | Métricas Chave |
|---|---|---|---|
| Alice | Consumidora | Navegar/Buscar/Adicionar ao Carrinho/Checkout/Avaliar | First Screen < 2s, Busca < 500ms |
| Bob | Administrador | Gerenciamento de Produtos/Processamento de Pedidos/Gerenciamento de Usuários | Resposta CRUD < 200 ms |
| Charlie | Arquiteto | Estabilidade do Sistema/Alta Performance/Escalabilidade | 99.9% disponibilidade, suporta 1 milhão de produtos |
(2) Divisão de Módulos Funcionais
| Módulo | Função | Prioridade | Páginas Afetadas |
|---|---|---|---|
| Autenticação | Cadastro/Login/OAuth2/JWT | P0 | /login, /register |
| Produto | CRUD/Busca/Categorias/Filtros | P0 | /products, /products/[id] |
| Carrinho de Compras | Adicionar/Trocar Quantidade/Remover/Limpar | P0 | /cart |
| Pedido | Criar/Pagar/Verificar Status | P0 | /checkout, /orders |
| Usuário | Informações Pessoais/Endereço/Avaliações | P1 | /profile |
| Administração | CRUD do Painel/Estatísticas/Moderação | P1 | /admin/** |
| Internacionalização | Chinês/Inglês/Japonês + Múltiplas Moedas | P1 | Global |
| SEO | meta dinâmico/Sitemap/JSON-LD | P0 | Página de Produto |
4. Design de Arquitetura
(1) Visão Geral da Arquitetura do Sistema MegaShop
graph TB
subgraph Client["Camada Client"]
Browser[Navegador / Mobile]
Bot[Bot de Mecanismo de Busca]
end
subgraph CDN["Camada CDN"]
CF[Cloudflare / Vercel Edge]
end
subgraph Nuxt["Aplicação Nuxt 3"]
SSR[Motor SSR]
ISR[Cache ISR]
API[Rotas Nitro API]
MW[Middleware / Auth]
end
subgraph Data["Camada de Dados"]
PG[(PostgreSQL)]
Redis[(Cache Redis)]
S3[Armazenamento de Objetos / Imagens]
end
subgraph External["Serviços Externos"]
Stripe[Pagamento Stripe]
Google[Google OAuth2]
Analytics[Serviço de Analytics]
end
Browser --> CDN
Bot --> CDN
CDN --> SSR
CDN --> ISR
SSR --> API
API --> MW
API --> PG
API --> Redis
API --> S3
API --> Stripe
API --> Google
API --> Analytics
ISR --> Redis
(2) Design de Estratégia de Renderização
| Tipo de Página | Modo de Renderização | swr | Motivo |
|---|---|---|---|
| Home | SSG | - | Conteúdo Estável |
| Lista de Produtos | ISR | 3600s | Atualizado a cada hora |
| Detalhes do Produto | ISR | 86400s | Atualizado diariamente |
| Resultados de Busca | SSR | - | Consulta em tempo real |
| Carrinho/Checkout | CSR | - | Apenas para membros |
| Painel Admin | CSR | - | SEO não necessário |
| Rotas de API | Dinâmico | - | Cache sob demanda |
(3) Seleção do Stack Tecnológico
(1) ▶ Exemplo: Integração do Stack Tecnológico no nuxt.config.ts
// nuxt.config.ts - Integração completa do stack tecnológico
export default defineNuxtConfig({
ssr: true,
modules: [
'@pinia/nuxt',
'@nuxtjs/tailwindcss',
'@nuxtjs/i18n',
'@nuxtjs/sitemap',
'@nuxt/image',
'~/modules/analytics'
],
i18n: {
locales: [
{ code: 'en', name: 'English', file: 'en.json', currency: 'USD' },
{ code: 'zh', name: 'Chinese', file: 'zh.json', currency: 'CNY' },
{ code: 'ja', name: 'Japanese', file: 'ja.json', currency: 'JPY' }
],
defaultLocale: 'en',
lazy: true,
langDir: 'locales/'
},
image: { quality: 80, format: ['webp', 'avif'] }
})
Saída:
// Execução bem-sucedida
(2) ▶ Exemplo: Orquestração de Serviços Docker Compose
# docker-compose.yml - Definição de infraestrutura
services:
web:
build: .
ports: ["3000:3000"]
depends_on: [db, redis]
db:
image: postgres:16-alpine
volumes: [postgres_data:/var/lib/postgresql/data]
redis:
image: redis:7-alpine
volumes: [redis_data:/data]
nginx:
image: nginx:alpine
ports: ["80:80", "443:443"]
depends_on: [web]
Saída:
CONTAINER ID IMAGE STATUS PORTS
abc123 nginx:latest Up 2 hours 0.0.0.0:80->80/tcp
| Nível | Tecnologia | Motivo da Escolha |
|---|---|---|
| Framework | Nuxt 3 | Renderização Híbrida SSR/ISR/CSR |
| UI | Vue 3 + TailwindCSS | Reativo + Desenvolvimento Rápido |
| Gerenciamento de Estado | Pinia | Solução Oficial Vue 3 + Suporte SSR |
| Banco de Dados | PostgreSQL + Prisma | ORM Type-safe + Milhões de Consultas |
| Cache | Redis + Nitro KV | Cache de API + Armazenamento ISR |
| Autenticação | JWT + OAuth2 | Stateless + Login Social |
| Internacionalização | @nuxtjs/i18n | Multilíngue + SEO hreflang |
| Imagem | @nuxt/image | WebP/AVIF + Responsivo |
| Testes | Vitest + Playwright | Unitário + E2E |
| Implantação | Docker Compose | Orquestração de Serviços Full-Stack |
| CI/CD | GitHub Actions | Pipelines Automatizados |
5. Design de Modelo de Dados
(1) Diagrama ER
erDiagram
User ||--o{ Order : "faz"
User ||--o{ Review : "escreve"
User ||--o{ CartItem : "tem"
User ||--o{ Address : "possui"
Product ||--o{ OrderItem : "incluído em"
Product ||--o{ CartItem : "adicionado ao"
Product ||--o{ Review : "recebe"
Product ||--o{ ProductImage : "tem"
Product }o--|| Category : "pertence a"
Category ||--o{ Category : "pai-filho"
Order ||--o{ OrderItem : "contém"
Order }o--|| Address : "envia para"
(2) Design de Tabelas Centrais
(1) ▶ Exemplo: Schema Prisma Central
// Modelos-chave do prisma/schema.prisma
model Product {
id Int @id @default(autoincrement())
name String
slug String @unique
price Decimal @db.Decimal(10, 2)
inStock Boolean @default(true)
categoryId Int
category Category @relation(fields: [categoryId], references: [id])
orderItems OrderItem[]
cartItems CartItem[]
@@index([categoryId])
@@index([price])
}
model Order {
id Int @id @default(autoincrement())
userId Int
user User @relation(fields: [userId], references: [id])
total Decimal @db.Decimal(10, 2)
status OrderStatus @default(PENDING)
items OrderItem[]
@@index([userId])
@@index([status])
}
Saída:
// Execução bem-sucedida
(2) ▶ Exemplo: Definições de Códigos de Erro da API
// server/utils/errors.ts
export const ErrorCodes = {
VALIDATION_ERROR: { statusCode: 400, message: 'Validation error' },
AUTH_REQUIRED: { statusCode: 401, message: 'Authentication required' },
TOKEN_EXPIRED: { statusCode: 401, message: 'Token expired' },
FORBIDDEN: { statusCode: 403, message: 'Insufficient permissions' },
NOT_FOUND: { statusCode: 404, message: 'Resource not found' },
CONFLICT: { statusCode: 409, message: 'Resource conflict' },
RATE_LIMITED: { statusCode: 429, message: 'Too many requests' }
} as const
export function throwError(code: keyof typeof ErrorCodes, details?: any) {
const err = ErrorCodes[code]
throw createError({ statusCode: err.statusCode, message: err.message, data: { errorCode: code, details } })
}
Saída:
// Execução bem-sucedida
(3) ▶ Exemplo: Formato Padrão de Resposta da API
// server/utils/response.ts
export function successResponse(data: any, message = 'Success') {
return { data, message, timestamp: Date.now() }
}
export function listResponse(items: any[], total: number, page: number, limit: number) {
return { items, total, page, limit, timestamp: Date.now() }
}
export function errorResponse(statusCode: number, errorCode: string, message: string, details?: any) {
return { statusCode, errorCode, message, details, timestamp: Date.now() }
}
Saída:
// Execução bem-sucedida
(4) ▶ Exemplo: Configuração de estratégia de renderização routeRules
// nuxt.config.ts - Estratégia de renderização por rota
routeRules: {
'/': { prerender: true },
'/products': { swr: 3600 },
'/products/**': { swr: 86400 },
'/admin/**': { ssr: false },
'/cart': { ssr: false },
'/api/**': { cors: true },
'/_nuxt/**': { headers: { 'cache-control': 'public, max-age=31536000, immutable' } }
}
Saída:
// Execução bem-sucedida
(5) ▶ Exemplo: Estrutura do Pipeline CI/CD
# .github/workflows/ci.yml - Pipeline principal
name: CI
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps: [{ uses: actions/checkout@v4 }, { run: npm ci }, { run: npm run lint }]
test:
needs: lint
steps: [{ run: npm run test:coverage }]
build:
needs: test
steps: [{ run: npm run build }]
Saída:
CI/CD pipeline loaded
Pipeline status: passed
Tests: 12 passed, 0 failed
| Tabela | Número de Campos | Índice Principal | Volume Estimado de Dados |
|---|---|---|---|
| Product | 12 | slug, categoryId, price | 1 milhão |
| Category | 6 | slug, parentId | 500 |
| User | 10 | email, role | 500.000 |
| Order | 8 | userId, status, createdAt | 1 milhão |
| OrderItem | 6 | orderId, productId | 5 milhões |
| CartItem | 5 | userId+productId (unique) | 100.000 |
| Review | 7 | productId, userId | 2 milhões |
| Address | 8 | userId | 500 mil |
6. Especificações de API
(1) Design RESTful API
| Método | Path | Descrição | Autenticação |
|---|---|---|---|
| GET | /api/products | Lista de Produtos (Paginação/Filtros) | Nenhuma |
| GET | /api/products/:id | Detalhes do Produto | Nenhuma |
| POST | /api/products | Criar Produto | Admin |
| PUT | /api/products/:id | Atualizar Produto | Admin |
| DELETE | /api/products/:id | Excluir Produto | Admin |
| GET | /api/categories | Lista de Categorias | Nenhuma |
| POST | /api/auth/register | Registro | Nenhuma |
| POST | /api/auth/login | Login | Nenhuma |
| POST | /api/auth/refresh | Renovar Token | Cookie |
| GET | /api/cart | Carrinho de Compras | Usuário |
| POST | /api/cart/add | Adicionar ao Carrinho | Usuário |
| DELETE | /api/cart/remove | Remover | Usuário |
| POST | /api/orders | Criar Pedido | Usuário |
| GET | /api/orders | Lista de Pedidos | Usuário |
| GET | /api/orders/:id | Detalhes do Pedido | Usuário |
(2) Especificações de Códigos de Erro
| Status Code | Código de Erro | Descrição |
|---|---|---|
| 400 | VALIDATION_ERROR | Validação de parâmetros da requisição falhou |
| 401 | AUTH_REQUIRED | Não logado |
| 401 | TOKEN_EXPIRED | Token expirado |
| 403 | FORBIDDEN | Permissões insuficientes |
| 404 | NOT_FOUND | Recurso não existe |
| 409 | CONFLICT | Conflito de recurso (ex: email já registrado) |
| 429 | RATE_LIMITED | Taxa de requisições excedida |
| 500 | INTERNAL_ERROR | Erro interno do servidor |
(3) Formato de Resposta
// Resposta de sucesso
{
"data": { ... },
"message": "Operation successful"
}
// Resposta de lista
{
"items": [...],
"total": 1000000,
"page": 1,
"limit": 20
}
// Resposta de erro
{
"statusCode": 400,
"message": "Validation error",
"errorCode": "VALIDATION_ERROR",
"details": { "field": "email", "reason": "Invalid format" }
}
7. Exemplo Completo: Estrutura do Projeto MegaShop
megashop/
├── nuxt.config.ts
├── prisma/
│ ├── schema.prisma
│ ├── seed.ts
│ └── migrations/
├── pages/
│ ├── index.vue
│ ├── products/
│ │ ├── index.vue
│ │ └── [id].vue
│ ├── categories/
│ │ └── [slug].vue
│ ├── cart.vue
│ ├── checkout.vue
│ ├── login.vue
│ ├── register.vue
│ ├── profile/
│ │ ├── index.vue
│ │ └── orders.vue
│ └── admin/
│ ├── index.vue
│ ├── products/
│ └── orders/
├── components/
│ ├── AppHeader.vue
│ ├── AppFooter.vue
│ ├── product/
│ │ ├── ProductCard.vue
│ │ ├── ProductGrid.vue
│ │ └── ProductReview.vue
│ ├── cart/
│ │ └── CartItem.vue
│ └── common/
│ ├── LanguageSwitcher.vue
│ └── SearchBar.vue
├── composables/
│ ├── useCart.ts
│ ├── useAnalytics.ts
│ ├── useLocalizedPrice.ts
│ └── useProductSearch.ts
├── stores/
│ ├── cart.ts
│ └── user.ts
├── server/
│ ├── utils/
│ │ ├── prisma.ts
│ │ └── jwt.ts
│ ├── middleware/
│ │ └── auth.ts
│ ├── api/
│ │ ├── auth/
│ │ ├── products/
│ │ ├── categories/
│ │ ├── cart/
│ │ └── orders/
│ └── plugins/
│ └── stock.ts
├── middleware/
│ ├── 01-auth.global.ts
│ └── admin.ts
├── plugins/
│ ├── 01-config.ts
│ ├── 02-logger.ts
│ └── 03-stripe.client.ts
├── layouts/
│ ├── default.vue
│ └── sidebar.vue
├── locales/
│ ├── en.json
│ ├── zh.json
│ └── ja.json
├── modules/
│ └── analytics/
├── tests/
│ ├── composables/
│ ├── stores/
│ ├── components/
│ └── api/
├── e2e/
│ ├── cart-flow.spec.ts
│ ├── auth-flow.spec.ts
│ └── admin-flow.spec.ts
├── Dockerfile
├── docker-compose.yml
├── .github/workflows/
│ ├── ci.yml
│ ├── deploy-staging.yml
│ └── deploy-production.yml
└── public/
├── favicon.ico
└── robots.txt
❓ Perguntas Frequentes
📖 Resumo
- Análise de Requisitos: Necessidades Centrais e Métricas Chave para as Três Funções (Alice, Bob e Charlie)
- Arquitetura: CDN → Nuxt (SSR/ISR/CSR) → Nitro API → PostgreSQL/Redis
- Modelo de dados: 8 tabelas centrais; 1 milhão de linhas na tabela "Product"; otimização de consultas usando índices
- Especificações de API: Estilo RESTful + códigos de erro uniformes + formato de resposta padrão
- Stack Tecnológico: Nuxt 3 + Pinia + Prisma + Redis + Docker Compose
📝 Exercícios
- Questão Básica (Dificuldade: ⭐): Desenhe um diagrama mostrando as funções de usuário e módulos funcionais do seu projeto.
- Problema Avançado (Dificuldade ⭐⭐): Projete um schema Prisma completo (com pelo menos 5 modelos), considerando índices e chaves estrangeiras.
- Desafio (Dificuldade: ⭐⭐⭐): Projete um documento completo de especificação de API, incluindo todos os endpoints, formatos de requisição/resposta e códigos de erro.
---|



