تصور کنید یک برنامهنویس در تیمی کوچک است که حالا میتواند یک API را در چند ثانیه پیادهسازی کند، اما هر تغییر کوچک در یک بخش، سه جای دیگر سیستم را میشکند. این سرعت خیرهکننده در تولید کد، در واقع پوششی برای بحران گستردهای از کدهای غیرقابل نگهداری است. طبق یک راهنمای جامع که در ۷ آگوست ۲۰۲۶ در وبسایت dev.to منتشر شد، عاملهای هوش مصنوعی ظرفیت پیادهسازی را بهشدت بالا بردهاند، اما همزمان سرعت ایجاد سیستمهایی با طراحی ضعیف و معماری ناقص را نیز شتاب بخشیدهاند. این روند را میتوان در راستای تغییر رویکرد تیمهای مدرن دید که در آن حاکمیت دادهها و ساختارها بهجای سرعت محض کدنویسی به اولویت اصلی تبدیل شده است.

این وضعیت یک پارادوکس خطرناک در مهندسی نرمافزار مدرن ایجاد کرده است. ابزارهایی مثل GitHub Copilot و OpenAI Codex قادرند چندین فایل را بهطور همزمان تغییر دهند، تستهای واحد بنویسند، دستورات سیستم را اجرا کنند، خطاها را عیبیابی (Debug) نمایند و بهطور خودکار Pull Request آماده کنند. با این حال، این ابزارها فاقد درک زمینهای (Contextual Awareness) لازم برای اتخاذ تصمیمات سطح بالای معماری هستند. اگر به یک عامل (Agent) — شبیه به دستیاری که دستورات را سریع اجرا میکند اما نقشه کلی ساختمان را نمیبیند — دستور داده شود که «یک بکاند کامل برای SaaS بسازد»، ممکن است با خوشحالی کنترلرها، مدلها، مایگریشنها، سرویسها، کارهای پسزمینه (Background Jobs)، سیستمهای احراز هویت، کشینگ و صفهایی تولید کند که امروز بهدرستی کار میکنند، اما تا شش ماه دیگر به دلیل پیچیدگی بیش از حد و نبود ساختار، بهطور کامل فرو میریزند.
وقتی معماری مبهم است، تغییر یک ویژگی ساده ممکن است باعث شکست سه ویژگی دیگر شود، کوئریهای پایگاهداده بهمرور گرانتر و کندتر میشوند و منطق کسبوکار در پنج جای مختلف سیستم پخش میشود. در چنین وضعیتی، کارهای پسزمینه ممکن است دو بار اجرا شوند و APIها متناقض گردند، زیرا هر برنامهنویس (یا عامل AI) هر بخش را به روش متفاوتی پیاده میکند. در نهایت، عاملهای AI ممکن است تغییرات بهمراتب خطرناکتری ایجاد کنند، زیرا در خلأی از شفافیت معماری عمل میکنند. برای مقابله با این مشکل، صنعت به سمتی میرود که مخزن کد را به عنوان یک «محیط عملیاتی» برای هر دو گروه برنامهنویسان انسانی و عاملهای مهندسی نرمافزار تعریف کند. این کار مستلزم عبور از پرامپتهای ساده و جایگزینی آنها با یک «قرارداد معماری» (Architecture Contract) است؛ مجموعهای از قوانین ثابت و پایدار که نحوه تعامل عاملهای AI با کد را مدیریت و محدود میکند.
ابعاد ششگانه مقیاسپذیری
مقیاسپذیری اغلب بهاشتباه تنها به معنای مدیریت ترافیک بیشتر تلقی میشود. در واقعیت، یک سیستم عملیاتی باید در شش بُعد متمایز رشد کند:
- مقیاسپذیری ترافیک (Traffic Scalability): مدیریت رشد کاربران از ۱۰۰ نفر به ۱,۰۰۰,۰۰۰ نفر بدون فروپاشی سیستم. این مورد نیازمند تمرکز بر سرورهای اپلیکیشن، عملکرد پایگاهداده، کشینگ، صفها، توزیع بار (Load Balancing)، مدیریت اتصالات ذخیرهسازی و مقیاسپذیری افقی است.
- مقیاسپذیری داده (Data Scalability): حفظ عملکرد در حالی که حجم دادهها از ۱۰ هزار سفارش به ۵۰۰ میلیون مورد میرسد. کوئریهایی که در محیط توسعه بیضرر به نظر میرسند، در این حجم از داده به گلوگاههای (Bottlenecks) جدی تبدیل میشوند.
- مقیاسپذیری تیم (Team Scalability): پاسخ به این سوال که آیا ۲۰ برنامهنویس میتوانند بدون اینکه مدام تغییرات یکدیگر را خراب کنند، بر روی یک مخزن کد کار کنند؟
- مقیاسپذیری قابلیت (Feature Scalability): توانایی افزودن ویژگیهای جدید بدون نیاز به تغییر نیمی از اپلیکیشن. یک معماری خوب، تعداد اجزای غیرمرتبطی را که تحت تأثیر یک تغییر واحد قرار میگیرند، به حداقل میرساند.
- مقیاسپذیری عملیاتی (Operational Scalability): توانایی تیم در درک شکستهای محیط Production. این بُعد شامل پاسخ به سوالاتی چون: «چرا پرداخت کند است؟»، «کدام سرویس شکست خورده؟»، «کدام درخواست باعث این Exception شد؟»، «چند جاب (Job) در صف گیر کردهاند؟» یا «کدام Deployment باعث این رگرسیون شد؟»
- مقیاسپذیری هوش مصنوعی (AI Scalability): اطمینان از اینکه چندین عامل کدنویس AI میتوانند بدون ایجاد تناقضات ساختاری در مخزن مشارکت کنند. این امر مستلزم استفاده از دستورالعملهای سطح مخزن است که اطلاعات پایداری درباره ساختار پروژه، قراردادهای کدنویسی و روشهای اعتبارسنجی ارائه میدهد.
قرارداد معماری در قالب AGENTS.md
یکی از موثرترین روشهای مهار رفتار هوش مصنوعی، استفاده از دستورالعملهای مهندسی در سطح مخزن (Repository-level) است. OpenAI بهطور مشخص استفاده از یک فایل به نام AGENTS.md را برای تأمین زمینه (Context) دائمی به Codex توصیه میکند و خاطرنشان میکند که این فایلها میتوانند قراردادهای نامگذاری، منطق کسبوکار و وابستگیهایی را مستند کنند که عاملها نمیتوانند بهطور قابلاعتمادی آنها را تنها از روی کد استنباط کنند. GitHub Copilot نیز به همین ترتیب از دستورالعملهای سراسری مخزن، دستورالعملهای مسیر-محور (Path-specific) و فایلهای AGENTS.md پشتیبانی میکند.
این فایلها در واقع به عنوان یک «زمینه اجرایی» عمل میکنند. یک قرارداد کاربردی میتواند شامل دستورات زیر باشد:
قوانین کنترلر و پایگاهداده:
- کنترلرها: فقط مسئول اعتبارسنجی درخواست، احراز هویت، فراخوانی سرویسهای اپلیکیشن و فرمتبندی پاسخ هستند. نوشتن هرگونه منطق کسبوکار در این لایه اکیداً ممنوع است.
- پایگاهداده: تمامی نقاط پایانی (Endpoints) که لیست برمیگردانند باید از صفحهبندی (Pagination) پشتیبانی کنند. از اجرای کوئریها در داخل حلقهها پرهیز شود و برای روابط از Eager Loading استفاده گردد. تمام کوئریهای جدید روی جداول با حجم بالا باید حتماً ایندکسها را در نظر بگیرند.
دستورات امنیتی و شغلی:
- کارهای پسزمینه (Background Jobs): فراخوانی APIهای خارجی باید بهصورت غیرهمزمان (Asynchronous) اجرا شوند، مگر در مواردی که پاسخ فوری مورد نیاز باشد. جابها باید بهگونهای طراحی شوند که در صورت شکست، تکرار (Retry) آنها ایمن باشد.
- امنیت: هرگز شناسههای عددی پایگاهداده را در محیط عمومی افشا نکنید؛ بهجای آنها از UUIDهای عمومی استفاده کنید. هرگز رمزهای عبور، توکنها، اسرار (Secrets) یا اطلاعات پرداخت را در لاگها ثبت نکنید.
با کدگذاری این قوانین، «سطح تصمیمگیری» برای AI کاهش مییابد. بهجای پرامپت ضعیفی مثل «یک نقطه پایانی برای ایجاد سفارش بساز» که AI را مجبور میکند درباره اعتبارسنجی و تراکنشها حدس بزند، برنامهنویس محدودیتهای دقیق را دیکته میکند: «از CreateOrderRequest برای اعتبارسنجی استفاده کن»، «کنترلر نباید شامل منطق کسبوکار باشد»، «منطق کسبوکار متعلق به OrderService است»، «رزرو موجودی و ایجاد سفارش را در یک تراکنش پایگاهداده قرار بده»، «رویداد OrderCreated را فقط پس از ذخیرهسازی موفق ارسال کن»، «درخواستهای تکراری با یک کلید Idempotency نباید سفارشات متعددی ایجاد کنند»، «پاسخ را در قالب OrderResource برگردان» و «از پیادهسازی موجود در CreateInvoice الگو بگیر».
استراتژی Monolith ماژولار در برابر تله میکروسرویسها
برای جلوگیری از «تله میکروسرویس» — وضعیتی که در آن AI بهسرعت سرویسهای تکه تکه (مانند سرویسهای مجزای Auth، Billing و Order) تولید میکند که منجر به دوازده Deployment، دوازده سیستم لاگ، دوازده خط لوله CI، کابوسهای رهگیری توزیعشده (Distributed Tracing)، شکستهای شبکهای، تکرار منطق احراز هویت، مشکلات Service Discovery و قراردادهای نسخهبندی شده میشود — این راهنما پیشنهاد میکند با یک Modular Monolith شروع کنید.
در این ساختار، کد در ماژولهای مجزا (مثلاً src/Modules/Accounts, Billing, Projects, Notifications, Reporting) اما در قالب یک استقرار واحد سازماندهی میشود. هر ماژول شامل موارد زیر است:
- کنترلرها
- سرویسها
- مدلها
- ریپازیتوریها (Repositories)
- رویدادها (Events)
- جابها (Jobs)
- پالیسیها (Policies)
- تستها
این مدل مزایای جداسازی سرویسها را بدون تحمیل سربار شکستهای شبکهای فراهم میکند. اگر بعداً ماژول خاصی (مثلاً Billing) از نظر محاسباتی سنگین شود یا نیاز به مدیریت مستقل داشته باشد، بهراحتی قابل استخراج است. هوش مصنوعی بهویژه در مرحله استخراج مفید است، زیرا مرزهای شفاف ماژولار به عامل اجازه میدهد وابستگیها را بهطور سیستماتیک شناسایی و منتقل کند.
ناورداهای مهندسی و طراحی پایگاهداده
سیستمهای مقیاسپذیر بر اساس «ناورداها» (Invariants) یا قوانینی بنا میشوند که باید همیشه درست بمانند. عاملهای AI باید بهطور صریح از طریق لیستی با عنوان «ناورداهای حیاتی دامنه» از این قوانین آگاه شوند:
- موجودی: هرگز نباید منفی شود.
- پرداختها: وبهوکهای بازگشتی (Callbacks) ممکن است چندین بار ارسال شوند، بنابراین باید هندلینگ Idempotent داشته باشند.
- چند مستاجری (Multi-tenancy): کاربر مستاجر A هرگز نباید به دادههای مستاجر B دسترسی داشته باشد؛ تمام کوئریها باید بر اساس
tenant_idمحدود شوند. - امور مالی: فاکتورهای پرداخت شده نباید حذف شوند؛ تغییرات وضعیت اشتراک حتماً باید از طریق
SubscriptionServiceصورت گیرد.
طراحی پایگاهداده همچنان مسئولیت اصلی انسان است. AI میتواند Migrationها را در لحظه تولید کند، اما نمیتواند مفروضات محصول را تعیین نماید. انسانها باید بپرسند: «این جدول احتمالاً چه تعداد ردیف خواهد داشت؟»، «سفارشها چگونه کوئری میشوند؟»، «آیا اطلاعات مشتری باید Snapshot شوند؟»، «مرجوعهها چگونه نمایش داده شوند؟»، «ارزها چگونه مدیریت شوند؟»، «چه ایندکسهایی ضروری هستند؟»، «شناسهها راهانداز (Sequential) باشند یا عمومی؟»، «آیا نیاز به پارتیشنبندی مستاجر داریم؟» و «سوابق تا چه زمانی باید نگهداری شوند؟»
علاوه بر این، راهنما نسبت به الگوهای «N+1 query» تولید شده توسط AI هشدار میدهد. برای مثال، یک حلقه ساده که AI تولید کرده و در هر تکرار $order->customer->name را فراخوانی میکند، برای ۲۰ سفارش بهخوبی کار میکند اما برای ۱۰۰ هزار سفارش سیستم را مختل میکند. مهندسان باید به عاملها دستور دهند که مواردی چون صفحهبندی، ایندکسها، مشکل N+1، انتخاب ستونهای خاص، هزینه تجمیع (Aggregation cost)، پلان کوئری، مصرف حافظه، مرتبسازی و فیلتر کردن را در نظر بگیرند؛ مثلاً با استفاده از: Order::query()->with('customer:id,name')->latest()->paginate(50).
خط لولۀ تأیید و نظارت
چون AI میتواند با اطمینان کامل مفروضات نادرست خود را تأیید کند، تأیید خودکار غیرقابل مذاکره است. یک گردش کار مقیاسپذیر AI نیازمند چندین لایه تست است:
- تستهای واحد (Unit Tests): اعتبارسنجی قوانین ایزوله کسبوکار (مثلاً اطمینان از اینکه تخفیف نمیتواند از مبلغ کل سفارش بیشتر شود).
- تستهای یکپارچهسازی (Integration Tests): بررسی تعاملات اجزاء با پایگاهداده، صفها و رابطهای سرویسهای خارجی.
- تستهای API: اطمینان از اینکه قراردادهای واقعی (مثلاً
POST /api/ordersکه کد ۲۰۱ برمیگرداند) پایدار میمانند. - تستهای سرتاسری (End-to-End): اعتبارسنجی مسیرهای حیاتی کاربر، مانند: ثبتنام $ \rightarrow $ ایجاد سازمان $ \rightarrow $ خرید اشتراک $ \rightarrow $ ایجاد پروژه $ \rightarrow $ دعوت از همکار.
نکته حیاتی این است که هر رفع باگ باید منجر به یک «تست رگرسیون» شود. اگر باگی پیدا شد — مثلاً کاربرانی که در درخواستهای همزمان دوبار از یک کوپن استفاده میکنند — برنامهنویس باید از AI بخواهد: «ابتدا با یک تست شکستخورده (Failing Test) باگ را بازسازی کن و سپس پیادهسازی را اصلاح کن». این کار مجموعه تستها را به یک سیستم حافظه دائمی برای عاملهای AI تبدیل میکند که در حادثه اصلی حضور نداشتند.
زیرساخت بدون وضعیت (Stateless) و مشاهدهپذیری
مقیاسپذیری نیازمند مشاهدهپذیری (Observability) است. این یعنی عبور از لاگهای ساده و حرکت به سمت «لاگهای ساختاریافته». بهجای عبارت سادهی «پرداخت شکست خورد»، سیستم باید شیئی شامل event ،payment_id ،order_id ،provider ،error_code و duration_ms (مثلاً ۵۰۲۱ میلیثانیه) ثبت کند.
مشاهدهپذیری عملیاتی همچنین نیازمند موارد زیر است:
- متریکها (Metrics): رهگیری تعداد درخواست در ثانیه، نرخ خطا، تأخیر (Latency)، اتصالات پایگاهداده، عمق صف، نرخ شکست جابها، نرخ Hit کش، حافظه CPU و تأخیر APIهای خارجی.
- رهگیری (Tracing): شناسایی اینکه آیا یک درخواست در مرحله API، سرویس سفارش، سرویس پرداخت یا پایگاهداده دچار تأخیر شده است، از طریق دنبال کردن مسیر درخواست.
برای پشتیبانی از مقیاسپذیری افقی، اپلیکیشن باید بدون وضعیت (Stateless) بماند. باید به عاملهای AI صراحتاً دستور داد که هرگز وضعیتهای حیاتی (مانند user_123_session در حافظه محلی سرور A) را ذخیره نکنند، زیرا وقتی Load Balancer درخواست را به سرور B میفرستد، سیستم شکست میخورد. بهجای آن، باید از ذخیرهسازهای مشترک مانند Redis، نشستهای مبتنی بر پایگاهداده یا توکنهای بدون وضعیت امضاشده (Signed Stateless Tokens) استفاده شود.
در مورد ذخیرهسازی، راهنما پیشنهاد میکند سیستمها را با الگوهای دسترسی تطبیق دهید:
- دادههای تراکنشی: PostgreSQL / MySQL
- کش: Redis
- فایلهای Object: ذخیرهسازهای سازگار با S3
- جستجو: OpenSearch / Elasticsearch
- تحلیل داده (Analytics): دیتابیسهای تحلیلی یا انبار داده (Warehouse)
- رویدادها: Kafka یا سیستمهای صف
برای امکان تکامل سیستم، اینها باید پشت رابطها (Interfaces) مخفی شوند. برای مثال، ایجاد یک اینترفیس FileStorage اجازه میدهد سیستم بدون بازنویسی هر ویژگی، از LocalFileStorage به S3FileStorage تغییر وضعیت دهد.
گردش کار جدید انسان-ماشین
بهجای اینکه از AI بخواهید «یک سیستم بسازد»، این مسیر ساختاریافته را دنبال کنید:
۱. توصیف محصول: تعریف کاربر و مسئله (مثلاً SaaS چند مستاجری برای آژانسها که سازمانها شامل کاربران و پروژهها هستند).
۲. تعریف مقیاس مورد انتظار: تعیین مفروضات. مقدار اولیه: ۱,۰۰۰ سازمان و ۱۰,۰۰۰ کاربر. مقدار مورد انتظار: ۵۰ هزار سازمان، ۵۰۰ هزار کاربر، ۵۰ میلیون تسک و پیک ترافیک API معادل ۲ هزار درخواست در ثانیه.
۳. شناسایی دامنهها: تخصیص مالکیت به بخشهایی مانند حسابها (Accounts)، سازمانها، پروژهها، صورتحساب (Billing)، اعلانات و گزارشها.
۴. تثبیت قوانین معماری: الزام به استفاده از Monolith ماژولار، گرههای بدون وضعیت و عدم وجود منطق کسبوکار در کنترلرها. اطمینان از اینکه دسترسی به دیتابیس در داخل ماژولهای مالک باقی میماند و کارهای پسزمینه از طریق صفها اجرا میشوند.
۵. تعریف ناورداهای حیاتی: مستندسازی قوانینی مانند Idempotency برای وبهوکهای پرداخت و عدم منفی شدن شمارندههای مصرف.
۶. ایجاد دستورالعملهای AI: تکمیل فایل AGENTS.md یا فرمتهای دستورالعمل مخزن با دستورات، الگوها، استانداردهای تست و قراردادهای امنیتی.
۷. ساخت یک ماژول بهصورت صحیح: پیادهسازی یک ماژول «استاندارد طلا» (مثلاً Accounts) برای تثبیت الگوها.
۸. تکثیر الگوها: دستور به AI برای پیادهسازی سایر ویژگیها (مثلاً عضویت در پروژه) با پیروی دقیق از لایهبندی، اعتبارسنجی، تست و احراز هویت ماژول اول.
۹. اتوماسیون تأیید: استفاده از CI برای اعمال فرمتبندی، Linting، تایپها و تستهای معماری از طریق ابزارهایی مانند PHPStan، Psalm، ESLint، Ruff، mypy، SpotBugs، SonarQube یا ArchUnit.
۱۰. اندازهگیری پیش از بهینهسازی: استفاده از دادههای واقعی تأخیر و توان عملیاتی (Throughput) برای شناسایی گلوگاهها پیش از اقدام به بهینهسازیهای پیچیده.
مالکیت انسانی در عصر AI
هوش مصنوعی در اکتشاف مخزن، کشف الگوها و رфакتورینگ (Refactoring) — مانند انتقال منطق دامنه از کنترلرها به سرویسها — فوقالعاده است. میتوان از آن برای شناسایی پیچیدگیهای غیرضرور مانند انتزاعهای تکراری (Duplicate Abstractions)، کدهای مرده (Dead Code)، پوششهای Redundant یا وابستگیهای استفادهنشده کمک گرفت تا کدبیس سبک بماند.
با این حال، انسانها باید مسئول اهداف محصول، موازنههای معماری (Trade-offs)، تحمل ریسک، مدلهای امنیتی (شامل ایزولاسیون مستاجران و مدیریت اسرار) و محدودیتهای هزینه باقی بمانند. بازبینی کدهای AI اکنون نیازمند لنز جدیدی است. بازبینها باید بپرسند: «آیا AI بهطور غیرضروری الگوی جدیدی معرفی کرده است (مثلاً OrderDataAccessor در حالی که OrderRepository وجود دارد)؟» یا «آیا سناریوهای شکست مانند Timeoutها، تکرارها (Retries)، درخواستهای تکراری، نوشتنهای ناقص و شکستهای شبکهای هندل شدهاند؟»
بازبینها باید نسبت به تغییرات حجیم (مثلاً ۳,۲۰۰ خط در ۴۷ فایل) محتاط باشند و برای هر فایل تغییریافته توجیه بخواهند تا از انباشت بدهی فنی پنهان جلوگیری شود. هدف این نیست که AI نرمافزار بنویسد، بلکه هدف طراحی محیطی است که AI بتواند در آن بهصورت ایمن کمک کند تا سیستمی ساخته، تست و تکامل یابد که تبدیل به یک آشفتگی غیرقابل نگهداری نشود.
گام بعدی شما
- یک فایل
AGENTS.mdدر ریشه مخزن خود ایجاد کنید و قوانین سختگیرانه نامگذاری و جداسازی لایهها را در آن بنویسید. - تمام منطقهای حساس (مثل موجودی منفی نشدن) را در لیستی به نام «ناورداهای دامنه» تعریف کرده و به هر پرامپت ارجاع دهید.
- از AI بخواهید برای هر باگ گزارششده، ابتدا یک تست شکستخورده (Failing Test) بنویسد تا حافظه فنی سیستم شما تقویت شود.
اما چالش واقعی زمانی شروع میشود که بخواهید این مدلهای متمرکز را به زیرساختهای توزیعشده ببرید — به تحلیل ما دربارهی پروتکلهای جدید ارتباطی مدلها مراجعه کنید.




گفتگو