بازبینی کدی که هوش مصنوعی نوشته: چک‌لیست یک مهندس ارشد

پاسخ کوتاه: کد تولیدشده با هوش مصنوعی را از روی diff بازبینی کنید، نه از روی خلاصه ایجنت، و بیشترین دقت را جایی بگذارید که مدل‌ها بیشتر خطا می‌کنند: خطاهای قورت‌داده‌شده، امنیت، تست‌هایی که ضعیف شده‌اند، APIهای ساختگی و تغییراتی که کسی نخواسته. اگر نمی‌توانید یک خط را توضیح دهید، merge نمی‌شود. چک‌لیست زیر برای هر تغییر ده دقیقه وقت می‌برد و بیشتر چیزهای مهم را می‌گیرد.

یک مثال واقعی: endpoint جستجویی که خوب به نظر می‌رسید

از ایجنت خواستم «یک endpoint برای جستجوی بیمه‌نامه با نام بیمه‌گذار». این را تحویل داد، با یک خلاصه شاد که می‌گفت خطاها را «به‌خوبی مدیریت می‌کند»:

app.MapGet("/policies/search", async (string q, AppDbContext db) =>
{
    try
    {
        var sql = $"SELECT * FROM Policies WHERE HolderName LIKE '%{q}%'";
        return Results.Ok(await db.Policies.FromSqlRaw(sql).ToListAsync());
    }
    catch (Exception)
    {
        return Results.Ok(new List<Policy>());
    }
});

کامپایل می‌شود و در مسیر عادی کار می‌کند. در عین حال SQL injection دارد، هیچ مجوزی چک نمی‌کند، همه ستون‌ها را برمی‌گرداند (از جمله کد ملی و شماره موبایل)، صفحه‌بندی ندارد و قطعی دیتابیس را به «نتیجه‌ای پیدا نشد» تبدیل می‌کند؛ بدترین نوع شکست، یعنی بی‌صدا. نسخه بازبینی‌شده:

app.MapGet("/policies/search",
    async (string q, int page, AppDbContext db, CancellationToken ct) =>
    {
        if (q.Length < 3) return Results.BadRequest("Enter at least 3 characters.");

        var items = await db.Policies
            .AsNoTracking()
            .Where(p => EF.Functions.Like(p.HolderName, $"%{q}%")) // parameterised
            .OrderBy(p => p.Id)
            .Skip(Math.Max(page, 0) * 20).Take(20)
            .Select(p => new PolicySummary(p.Id, p.Number, p.HolderName, p.Status))
            .ToListAsync(ct);

        return Results.Ok(items);
    })
    .RequireAuthorization("PolicyReader");

هیچ‌کدام از مشکلات عجیب نبودند. فقط راحت دیده نمی‌شدند، چون کد تمام‌شده به نظر می‌رسید.

چک‌لیست

  1. دامنه. diff همان کاری را می‌کند که خواسته شده و فقط همان؟ refactorهای ناخواسته، تغییر نام فایل‌ها و «حالا که این‌جا بودم»ها برگردانده یا جدا می‌شوند.
  2. diff را بخوانید، نه چت را. خلاصه، نیت را توصیف می‌کند. diff چیزی است که منتشر می‌شود.
  3. تست‌ها. تستی حذف، skip یا شل شده تا build سبز شود؟ تست‌های جدید رفتار را بررسی می‌کنند یا فقط صدا زده شدن mockها را؟
  4. مدیریت خطا. دنبال catch (Exception)‌ای بگردید که مقدار پیش‌فرض برمی‌گرداند، catch خالی، و خطایی که لاگ می‌شود ولی به بالا نمی‌رسد.
  5. امنیت. SQL ساخته‌شده با رشته، نبودن [Authorize] یا RequireAuthorization، اطلاعات محرمانه در کد یا تنظیمات، داده حساس در لاگ یا پاسخ.
  6. داده و همزمانی. نوشتن چندمرحله‌ای بدون تراکنش، race خواندن‌سپس‌نوشتن روی موجودی، retry بدون idempotency.
  7. APIهایی که وجود دارند. متدها، overloadها و پکیج‌هایی که درست به نظر می‌رسند ولی وجود ندارند یا مال نسخه دیگری‌اند.
  8. کارایی. کوئری داخل حلقه، بارگذاری کل جدول، نبودن CancellationToken، نبودن صفحه‌بندی.
  9. قراردادها. قواعد پروژه (نوع پول، TimeProvider، سبک خطا) رعایت شده؟ اشتباه‌های تکراری جایشان در AGENTS.md است.
  10. می‌توانید توضیحش دهید؟ اگر خطی زیرکانه است و نمی‌توانید بگویید چرا درست است، از ایجنت بخواهید ساده‌اش کند یا توضیح دهد، بعد تصمیم بگیرید.

عادت‌هایی که بازبینی را ارزان‌تر می‌کنند

  • قدم‌های کوچک. هر بار یک تغییر بخواهید؛ diff دویست‌خطی بازبینی واقعی می‌گیرد، diff دوهزارخطی فقط یک نگاه سرسری.
  • اول تست. وقتی تست‌ها رفتار را توصیف می‌کنند، بازبینی به این سؤال تبدیل می‌شود: «تست‌های درستی‌اند؟»
  • دور دوم با یک نشست تازه. قبل از خودتان از یک نشست جدید ایجنت بخواهید diff را با همین چک‌لیست بازبینی کند. بعد بازبینی خودتان را انجام دهید.

مزایا و معایب بازبینی سخت‌گیرانه

مزایا

  • سرعت کد تولیدشده با AI را نگه می‌دارید بدون این‌که نقاط کورش را به ارث ببرید.
  • مشکلات وقتی پیدا می‌شوند که هزینه‌شان چند دقیقه است، نه بعد از یک حادثه.
  • به مرور چک‌لیست به AGENTS.md برمی‌گردد و ایجنت همان اشتباه‌ها را کمتر تکرار می‌کند.

معایب

  • انضباط می‌خواهد: وسوسه merge کردن کدی که «معلوم است درست است» زیاد است.
  • بازبینی از تولید کندتر است و گلوگاه می‌شود. گلوگاه درستی هم هست.

می‌خواهید قبل از رفتن به production یک جفت چشم دیگر کدبیس ساخته‌شده با AI را ببیند؟ ببینید چطور می‌توانم کمک کنم.

پرسش‌های متداول

بازبینی کد AI با بازبینی کد همکار فرق دارد؟

بررسی‌ها شبیه‌اند، الگوی خطاها نه. همکار به‌ندرت یک API از خودش می‌سازد یا بی‌صدا یک تست را ضعیف می‌کند؛ ایجنت گاهی این کار را می‌کند و همه را با کدی مرتب و مطمئن می‌نویسد. پس بیشتر diff را بخوانید و کمتر به خلاصه اعتماد کنید.

می‌توانم از خود AI بخواهم کدش را بازبینی کند؟

بله، به‌عنوان دور اول: از یک نشست تازه بخواهید diff را با چک‌لیستی مثل همین بررسی کند. مقدار خوبی پیدا می‌کند. جای بازبینی شما را نمی‌گیرد، چون همان نقاط کور مدلی را دارد که کد را نوشته.

تغییر تولیدشده با AI چقدر باید بزرگ باشد؟

آن‌قدر کوچک که بتوانید همه خطوطش را یک‌جا بخوانید؛ ترجیحاً حداکثر چند صد خط. از ایجنت هر بار یک قدم بخواهید؛ ده commit کوچک بازبینی‌شده از یک commit بزرگ ناخوانا بهتر است.