تصميم المشروع
لقد أكملنا الآن جميع مواد المراحل 1-4. سيقوم Charlie الآن بدمج كل هذه المعرفة لتصميم منصة MegaShop تجارية الإلكترونية كاملة. من تحليل المتطلبات إلى التصميم المعماري، ومن نماذج البيانات إلى مواصفات API، هذه هي الخطوة الأولى في المشروع العملي.
1. ما ستتعلمه
- تحليل المتطلبات: أدوار المستخدمين (Alice/Bob/Charlie) وتفصيل الوحدات الوظيفية
- البنية: تقديم SSR + ISR الهجين + Nitro API + Prisma + Redis
- نموذج البيانات: تصميم مخطط ER + مخطط Prisma
- مواصفات API: تصميم RESTful API + إدارة الإصدارات + رموز الأخطاء
- قرارات اختيار التقنيات ومبرراتها
2. قصة حقيقية لمهندس معماري
(1) نقطة الألم: تطوير بدون تصميم
كان Charlie قد أمر الفريق سابقًا بالبدء في كتابة الكود مباشرة بدون أي وثائق تصميم. نتيجة لذلك، لم تتطابق بنية بيانات سلة التسوق الخاصة بـ Alice مع بيانات طلبات Bob، وكان تسمية API فوضويًا، وكانت قاعدة البيانات تفتقر إلى فهارس، وكانت الاستعلامات بطيئة، وتكلفة إجراء التعديلات لاحقًا كانت هائلة.
(2) حلول تصميم النظام
صمم أولاً، ثم طوّر—استخدم مخططات ER لتعريف نموذج البيانات، ومواصفات RESTful لتعريف API، ومخططات البنية لتعريف حدود النظام. اقضِ أسبوعًا إضافيًا في مرحلة التصميم، ووفّر ثلاثة أسابيع أثناء التطوير.
(3) الفوائد: خارطة طريق واضحة
عندما يشير كل مطور إلى نفس وثيقة التصميم—مع هياكل بيانات متسقة ومواصفات API موحدة وحدود بنية واضحة—تزداد كفاءة التعاون ثلاثة أضعاف.
3. تحليل المتطلبات
(1) أدوار المستخدمين والاحتياجات الأساسية
| الدور | الهوية | الاحتياجات الأساسية | المقاييس الرئيسية |
|---|---|---|---|
| Alice | مستهلك | تصفح/بحث/إضافة إلى السلة/الدفع/مراجعة | الشاشة الأولى < 2 ثانية، البحث < 500 مللي ثانية |
| Bob | مسؤول | إدارة المنتجات/معالجة الطلبات/إدارة المستخدمين | استجابة CRUD < 200 مللي ثانية |
| Charlie | مهندس معماري | استقرار النظام/أداء عالي/قابلية التوسع | توافر 99.9%، يدعم مليون منتج |
(2) تقسيم الوحدات الوظيفية
| الوحدة | الوظيفة | الأولوية | الصفحات المتأثرة |
|---|---|---|---|
| المصادقة | تسجيل/تسجيل دخول/OAuth2/JWT | P0 | /login، /register |
| المنتجات | CRUD/بحث/فئات/تصفية | P0 | /products، /products/[id] |
| سلة التسوق | إضافة/تغيير الكمية/إزالة/مسح | P0 | /cart |
| الطلبات | إنشاء/دفع/التحقق من الحالة | P0 | /checkout، /orders |
| المستخدم | معلومات شخصية/عنوان/مراجعات | P1 | /profile |
| الإدارة | CRUD خلفي/إحصائيات/إشراف | P1 | /admin/** |
| التدويل | صيني/إنجليزي/ياباني + عملات متعددة | P1 | عالمي |
| SEO | meta ديناميكي/Sitemap/JSON-LD | P0 | صفحة المنتج |
4. التصميم المعماري
(1) نظرة عامة على بنية نظام MegaShop
graph TB
subgraph Client["طبقة العميل"]
Browser[متصفح / هاتف محمول]
Bot[روبوت محرك البحث]
end
subgraph CDN["طبقة CDN"]
CF[Cloudflare / Vercel Edge]
end
subgraph Nuxt["تطبيق Nuxt 3"]
SSR[محرك SSR]
ISR[تخزين مؤقت ISR]
API[مسارات Nitro API]
MW[وسائط / مصادقة]
end
subgraph Data["طبقة البيانات"]
PG[(PostgreSQL)]
Redis[(تخزين مؤقت Redis)]
S3[تخزين كائنات / صور]
end
subgraph External["خدمات خارجية"]
Stripe[دفع Stripe]
Google[Google OAuth2]
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) تصميم استراتيجية التقديم
| نوع الصفحة | وضع التقديم | swr | السبب |
|---|---|---|---|
| الرئيسية | SSG | - | محتوى مستقر |
| قائمة المنتجات | ISR | 3600 ثانية | تحديث كل ساعة |
| تفاصيل المنتج | ISR | 86400 ثانية | تحديث يومي |
| نتائج البحث | SSR | - | استعلام في الوقت الفعلي |
| السلة/الدفع | CSR | - | للأعضاء فقط |
| لوحة الإدارة | CSR | - | لا حاجة لـ SEO |
| مسار API | ديناميكي | - | تخزين مؤقت حسب الطلب |
(3) اختيار المكدس التقني
(1) ▶ مثال: تكامل المكدس التقني في nuxt.config.ts
// nuxt.config.ts - تكامل المكدس التقني الكامل
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'] }
})
الناتج:
// التنفيذ ناجح
(2) ▶ مثال: تنسيق خدمات Docker Compose
# docker-compose.yml - تعريف البنية التحتية
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]
الناتج:
CONTAINER ID IMAGE STATUS PORTS
abc123 nginx:latest Up 2 hours 0.0.0.0:80->80/tcp
| المستوى | التقنية | سبب الاختيار |
|---|---|---|
| الإطار | Nuxt 3 | تقديم SSR/ISR/CSR الهجين |
| واجهة المستخدم | Vue 3 + TailwindCSS | تفاعلي + تطوير سريع |
| إدارة الحالة | Pinia | حل Vue 3 الرسمي + دعم SSR |
| قاعدة البيانات | PostgreSQL + Prisma | ORM آمن بالنوع + ملايين الاستعلامات |
| التخزين المؤقت | Redis + Nitro KV | تخزين مؤقت API + تخزين ISR |
| المصادقة | JWT + OAuth2 | عديم الحالة + تسجيل دخول اجتماعي |
| التدويل | @nuxtjs/i18n | متعدد اللغات + SEO hreflang |
| الصور | @nuxt/image | WebP/AVIF + متجاوب |
| الاختبار | Vitest + Playwright | وحدة + E2E |
| النشر | Docker Compose | تنسيق خدمات المكدس الكامل |
| CI/CD | GitHub Actions | خطوط أنابيب مؤتمتة |
5. تصميم نموذج البيانات
(1) مخطط ER
erDiagram
User ||--o{ Order : "يقدّم"
User ||--o{ Review : "يكتب"
User ||--o{ CartItem : "يمتلك"
User ||--o{ Address : "يملك"
Product ||--o{ OrderItem : "مضمّن في"
Product ||--o{ CartItem : "مضاف إلى"
Product ||--o{ Review : "يتلقى"
Product ||--o{ ProductImage : "لديه"
Product }o--|| Category : "ينتمي إلى"
Category ||--o{ Category : "أب-ابن"
Order ||--o{ OrderItem : "يحتوي على"
Order }o--|| Address : "يشحن إلى"
(2) تصميم الجداول الأساسية
(1) ▶ مثال: مخطط Prisma الأساسي
// نماذج رئيسية من 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])
}
الناتج:
// التنفيذ ناجح
(2) ▶ مثال: تعريفات رموز أخطاء 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 } })
}
الناتج:
// التنفيذ ناجح
(3) ▶ مثال: تنسيق استجابة 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() }
}
الناتج:
// التنفيذ ناجح
(4) ▶ مثال: تكوين استراتيجية تقديم routeRules
// nuxt.config.ts - استراتيجية تقديم على مستوى المسار
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' } }
}
الناتج:
// التنفيذ ناجح
(5) ▶ مثال: بنية خط أنابيب CI/CD
# .github/workflows/ci.yml - خط الأنابيب الأساسي
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 }]
الناتج:
تم تحميل خط أنابيب CI/CD
حالة الخط الأنابيب: ناجح
الاختبارات: 12 ناجح، 0 فاشل
| الجدول | عدد الحقول | الفهرس الأساسي | حجم البيانات المقدر |
|---|---|---|---|
| Product | 12 | slug, categoryId, price | مليون |
| Category | 6 | slug, parentId | 500 |
| User | 10 | email, role | 500,000 |
| Order | 8 | userId, status, createdAt | مليون |
| OrderItem | 6 | orderId, productId | 5 ملايين |
| CartItem | 5 | userId+productId (فريد) | 100,000 |
| Review | 7 | productId, userId | 2 مليون |
| Address | 8 | userId | 500 ألف |
6. مواصفات API
(1) تصميم RESTful API
| الطريقة | المسار | الوصف | المصادقة |
|---|---|---|---|
| GET | /api/products | قائمة المنتجات (ترقيم/تصفية) | بدون |
| GET | /api/products/:id | تفاصيل المنتج | بدون |
| POST | /api/products | إنشاء منتج | مسؤول |
| PUT | /api/products/:id | تحديث منتج | مسؤول |
| DELETE | /api/products/:id | حذف منتج | مسؤول |
| GET | /api/categories | قائمة الفئات | بدون |
| POST | /api/auth/register | تسجيل | بدون |
| POST | /api/auth/login | تسجيل دخول | بدون |
| POST | /api/auth/refresh | تحديث Token | Cookie |
| GET | /api/cart | سلة التسوق | مستخدم |
| POST | /api/cart/add | إضافة إلى السلة | مستخدم |
| DELETE | /api/cart/remove | إزالة | مستخدم |
| POST | /api/orders | إنشاء طلب | مستخدم |
| GET | /api/orders | قائمة الطلبات | مستخدم |
| GET | /api/orders/:id | تفاصيل الطلب | مستخدم |
(2) مواصفات رموز الأخطاء
| رمز الحالة | رمز الخطأ | الوصف |
|---|---|---|
| 400 | VALIDATION_ERROR | فشل التحقق من معلمات الطلب |
| 401 | AUTH_REQUIRED | غير مسجل الدخول |
| 401 | TOKEN_EXPIRED | انتهت صلاحية Token |
| 403 | FORBIDDEN | صلاحيات غير كافية |
| 404 | NOT_FOUND | المورد غير موجود |
| 409 | CONFLICT | تعارض الموارد (مثل البريد الإلكتروني مسجل مسبقًا) |
| 429 | RATE_LIMITED | تجاوز معدل الطلبات |
| 500 | INTERNAL_ERROR | خطأ داخلي في الخادم |
(3) تنسيق الاستجابة
// استجابة ناجحة
{
"data": { ... },
"message": "Operation successful"
}
// استجابة قائمة
{
"items": [...],
"total": 1000000,
"page": 1,
"limit": 20
}
// استجابة خطأ
{
"statusCode": 400,
"message": "Validation error",
"errorCode": "VALIDATION_ERROR",
"details": { "field": "email", "reason": "Invalid format" }
}
7. مثال شامل: هيكل مشروع 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
❓ أسئلة شائعة
📖 ملخص
- تحليل المتطلبات: الاحتياجات الأساسية والمقاييس الرئيسية للأدوار الثلاثة (Alice وBob وCharlie)
- البنية: CDN → Nuxt (SSR/ISR/CSR) → Nitro API → PostgreSQL/Redis
- نموذج البيانات: 8 جداول أساسية؛ مليون صف في جدول "المنتجات"؛ تحسين الاستعلامات باستخدام الفهارس
- مواصفات API: أسلوب RESTful + رموز أخطاء موحدة + تنسيق استجابة قياسي
- المكدس التقني: Nuxt 3 + Pinia + Prisma + Redis + Docker Compose
📝 تمارين
- سؤال أساسي (الصعوبة: ⭐): ارسم مخططًا يوضح أدوار المستخدمين والوحدات الوظيفية لمشروعك.
- مسألة متقدمة (الصعوبة ⭐⭐): صمم مخطط Prisma كاملاً (بخمسة نماذج على الأقل)، مع الأخذ بعين الاعتبار الفهارس والمفاتيح الأجنبية.
- تحدي (الصعوبة: ⭐⭐⭐): صمم وثيقة مواصفات API كاملة، تشمل جميع نقاط النهاية وتنسيقات الطلب/الاستجابة ورموز الأخطاء.
---|



