
الذكاء الاصطناعي لم يستبدل المطورين المبتدئين. بل صنع كودًا يبدو خبيرًا.
ليس من الصعب رفض الكود الخلفي المُولّد بالذكاء الاصطناعي عندما يكون معيبًا بشكل واضح. أما الحالة الأصعب فهي الكود الذي يبدو منظمًا ولكنه مع ذلك يتجاهل قواعد الإنتاج.
هذه الدراسة تستخدم مشروع Laravel صغير: مستخدم يحول رصيدًا إلى مستخدم آخر. الميزة نفسها نُفذت بطريقتين. الأولى تبدو نظيفة لكنها ناقصة. الثانية تضيف التحقق، الصلاحيات، المعاملات، قفل الصفوف، سجلات الفشل، التسجيل، والاختبارات.
تم تشغيل 16 سيناريو على الخدمتين. الخدمة المزيفة اجتازت 9 وفشلت في 7، وحققت 51.7 من 100. الخدمة الإنتاجية اجتازت 16 من 16 وحققت 100 من 100.
الفكرة
الخطر ليس أن الذكاء الاصطناعي قد يولد كودًا سيئًا. هذا كان ممكنًا قبل الذكاء الاصطناعي. الخطر هنا أن الكود قد يبدو مكتملًا قبل أن يثبت أنه يتحمل شروط التشغيل الفعلية.
الخدمة المزيفة في هذا المشروع ليست عبثية. فيها service class، ونتيجة موحدة، وأسماء واضحة، وفحص رقمي للمبلغ، ورفض للمبلغ السالب، وسجل نجاح عند اكتمال التحويل. المسار السعيد يعمل.
لكن تحويل الرصيد يحتاج أكثر من ذلك. يجب معرفة من يملك حق الإنفاق. يجب رفض الصفر. يجب منع التحويل إلى الذات. يجب تسجيل الفشل. ويجب تحديث محفظتي المرسل والمستقبل داخل معاملة قاعدة بيانات واحدة.
السياق الخارجي
نتائج الدراسات حول أدوات البرمجة بالذكاء الاصطناعي ليست باتجاه واحد. دراسة GitHub Copilot حول الإنتاجية وجدت تحسنًا في مهمة JavaScript محدودة. في المقابل، دراسة METR على مطوري open-source ذوي خبرة وجدت أن استخدام أدوات AI أبطأ العمل في مستودعات يعرفها المطورون مسبقًا.
استبيان Stack Overflow لعام 2025 حول AI أظهر أن عدد المطورين الذين لا يثقون بدقة مخرجات AI أكبر من الذين يثقون بها. كما أن تقرير DORA 2025 عن تطوير البرمجيات بمساعدة AI يربط النتائج بجودة النظام الهندسي المحيط بالأداة، لا بالأداة وحدها.
هذه الدراسة أضيق من ذلك كله. السؤال هنا محدد: هل تصمد خدمة Laravel واحدة أمام 16 فحصًا خلفيًا واضحًا؟
شكل المشروع
اسم المشروع fake-senior-code-laravel-wallet. هو تطبيق Laravel قابل للتشغيل، وفيه migrations، models، services، policy، tests، scoring helper، وأمر Artisan.
النطاق يستخدم جدول users الافتراضي في Laravel وجدولين إضافيين:
wallets: محفظة واحدة لكل مستخدم، وفيها الرصيد.wallet_transactions: سجل لكل محاولة تحويل ناجحة أو فاشلة.
الخدمتان تملكان نفس الواجهة:
public function transfer(
User $actor,
int $senderId,
int $receiverId,
mixed $amount
): TransferResult;هذا يجعل المقارنة واضحة. نفس المدخلات، نفس السلوك المتوقع، اختلاف في جودة التنفيذ.
عقد التحويل
المشروع لا يحاول بناء نظام مدفوعات كامل. الاختبار هنا على قواعد خلفية أساسية لا يجب أن تغيب عن تحويل رصيد بسيط.
| العنصر | القاعدة |
|---|---|
actor | يجب أن يملك حق الإنفاق من محفظة المرسل. |
sender_id | يجب أن يشير إلى محفظة موجودة وفيها رصيد كاف. |
receiver_id | يجب أن يشير إلى محفظة موجودة وألا يساوي المرسل. |
amount | يجب أن يكون رقميًا، أكبر من صفر، وبدقة منزلتين عشريتين. |
| تحديث الرصيد | الخصم والإضافة يجب أن يحدثا داخل معاملة قاعدة بيانات واحدة. |
| صفوف المحافظ | يجب قفل الصفوف قبل حساب الرصيد الجديد. |
| مسار الفشل | محاولات الفشل يجب أن تسجل مع سبب واضح. |
الخدمتان
FakeSeniorTransferService تبدو مقبولة في القراءة الأولى. تتحقق أن المبلغ رقمي، ترفض السالب، تبحث عن محفظتي المرسل والمستقبل، تفحص الرصيد، تحدث الأرصدة، وتسجل عملية ناجحة.
النواقص هي المشكلة:
لا يوجد تحقق صلاحيات. يمكن لمستخدم أن ينفق من محفظة غيره.
0.00يعامل كتحويل ناجح.التحويل إلى الذات مسموح وقد يفسد الرصيد.
لا يوجد
DB::transaction.لا يوجد
lockForUpdate.معظم حالات الفشل لا تكتب في
wallet_transactions.
RealSeniorTransferService تنفذ الميزة نفسها مع حدود واضحة: تطبيع المبلغ، رفض التحويل إلى الذات، التحقق من ملكية المرسل، policy للمحفظة، التحقق من وجود المحافظ، transaction، row locking، سجلات فشل، وتحذيرات في logs.
بروتوكول السيناريوهات
الأمر php artisan wallet:fake-senior-study ينشئ مستخدمين ومحافظ جديدة لكل حالة. ثم يشغل الخدمتين على نفس السيناريو ويحسب النتيجة.
عدد السيناريوهات المقاسة:
S = 16أهم السيناريوهات:
تحويل ناجح
رصيد غير كاف
تحويل إلى الذات
مبلغ صفري
مبلغ سالب
غياب محفظة المرسل
غياب محفظة المستقبل
محاولة غير مصرح بها
محاولة تحويل متكررة
اتساق سجل العمليات
تسجيل سبب الفشل
ثبات الأرصدة بعد فشل التحويل
التقييم
درجة الجاهزية الإنتاجية مبنية على checklist موزون:
PRS =
0.20 Validation
+ 0.20 Authorization
+ 0.20 Database Consistency
+ 0.15 Failure Handling
+ 0.15 Test Coverage
+ 0.10 Maintainabilityكل فئة تحسب بهذه الطريقة:
Category Score = Passed Checks / Total Checks x 100النتائج المقاسة
تم تشغيل المشروع محليًا بالأوامر:
php artisan test
php artisan wallet:fake-senior-study --jsonالاختبارات نجحت: 20 اختبارًا و 72 assertion.
| الخدمة | نجح | فشل | الدرجة |
|---|---|---|---|
| Fake Senior Code | 9 | 7 | 51.7 / 100 |
| Real Senior Code | 16 | 0 | 100 / 100 |
نتائج السيناريوهات الأساسية:
| السيناريو | المزيف | الحقيقي |
|---|---|---|
| التحويل الناجح | PASS | PASS |
| التحويل إلى الذات | FAIL | PASS |
| المبلغ الصفري | FAIL | PASS |
| المبلغ السالب | PASS | PASS |
| الرصيد غير الكافي | PASS | PASS |
| غياب محفظة المرسل | FAIL | PASS |
| غياب محفظة المستقبل | FAIL | PASS |
| محاولة غير مصرح بها | FAIL | PASS |
| محاولة تحويل متكررة | PASS | PASS |
| اتساق سجل العمليات | FAIL | PASS |
| تسجيل سبب الفشل | FAIL | PASS |
| ثبات الأرصدة بعد الفشل | PASS | PASS |
لماذا تشابهت بعض الدرجات؟
الخدمة المزيفة حصلت على 100% في فئة اتساق قاعدة البيانات المقاسة. هذا لا يعني أنها آمنة تحت ضغط إنتاجي.
هذه الفئة اختبرت حالات متسلسلة فقط: الرصيد بعد نجاح، بعد رصيد غير كاف، بعد محاولة متكررة، وبعد فشل. الخدمة المزيفة اجتازت هذه الحالات. لكنها ما زالت بلا DB::transaction وبلا lockForUpdate. الاختبار الحالي لا يشغل طلبات متوازية على نفس المحفظة.
النسخة القادمة من المعيار يجب أن تفصل بين:
الاتساق المتسلسل
السلامة تحت التزامن
التغطية الاختبارية وقابلية الصيانة تشابهتا أيضًا لأن الخدمتين لهما نفس الواجهة وتعيدان TransferResult. هذه نقطة مهمة: الكود الخبير المزيف يمكن أن يكون له شكل جيد ومع ذلك يترك قواعد أساسية خارج التنفيذ.
قراءة الأرقام
الخدمة المزيفة اجتازت 9 من 16. هذه النجاحات حقيقية. المسار السعيد يعمل. المبلغ السالب مرفوض. حالة الرصيد غير الكافي لا تغير الأرصدة.
لكن الفشل يهم أكثر عند الشحن. التحويل غير المصرح يعمل. الصفر يقبل كتحويل ناجح. التحويل إلى الذات قد يفسد الرصيد. فشل غياب المحافظ لا يسجل. سبب الفشل لا يحفظ. ومسار التحديث لا يملك transaction أو row lock.
الخدمة الحقيقية اجتازت 16 من 16. هذا لا يجعلها نظام دفع كاملًا. يعني فقط أنها حققت العقد المحدد في هذا المشروع.
ملاحظات عملية
المعيار يستخدم SQLite. يجب فحص سلوك الأقفال والأداء على MySQL أو PostgreSQL قبل استخدام النمط في إنتاج حقيقي.
سيناريو التزامن هنا ليس اختبار ضغط متوازٍ كامل. هو يتحقق من وجود transaction وrow-locking في الخدمة الحقيقية، ويفحص محاولة التحويل المتكررة بشكل متسلسل. النسخة القادمة يجب أن تشغل طلبات متوازية ضد المحفظة نفسها.
نظام محفظة حقيقي يحتاج أيضًا idempotency keys، ledger غير قابل للتلاعب، قواعد عملات، retry behavior، reconciliation، وقواعد تدقيق أقوى.
الخاتمة
النتيجة المباشرة: الخدمة المزيفة اجتازت 9 من 16 وحققت 51.7. الخدمة الحقيقية اجتازت 16 من 16 وحققت 100.
الخدمة المزيفة مفيدة كمثال لأنها ليست سيئة في كل شيء. لديها بنية. تجتاز فحوصًا بسيطة. تفشل عندما يسأل الاختبار عن الملكية، المدخلات غير الصالحة، سجل الفشل، وحدود قاعدة البيانات.
في backend code بمساعدة AI، لا يكفي service class ورسالة نجاح. حدد قواعد الإنتاج واختبرها. في هذا المشروع، 16 سيناريو كانت كافية لإظهار الفرق.
لمن يرغب في التعمق أكثر، أرفقت هنا ملف PDF يضم الدراسة كاملة بكل تفاصيلها.

