بررسی کد با هوش مصنوعی: وقتی چند بازبین سرِ یک تغییر بحث میکنند
چطور کد یا مخزنِ گیتهابت را به چند مدل با نقشهایِ جدا بدهی، چه چیزی را بخواهی بگردند، و با فهرستِ یافتهها چه کنی تا هشدارِ واقعی از هشدارِ بیپایه جدا شود.
بررسی کد با هوش مصنوعی یعنی کد یا تغییرِ تازهات را به یک مدلِ زبانی بدهی تا پیش از ادغام، باگها، حفرههایِ امنیتی و بخشهایِ سختخوان را پیدا کند. یک مدل بهتنهایی معمولاً چند نکتهی درست، چند نکتهی بیربط و چند جایِ خالی تحویل میدهد و تو راهی نداری بفهمی کدام کدام است. وقتی چند مدل با نقشهایِ متفاوت همان کد را مستقل بخوانند و بعد یافتههایِ هم را نقد کنند، هم پوشش بیشتر میشود و هم هشدارهایِ بیپایه زودتر کنار میروند؛ خروجی جایِ تست و بازبینِ انسانی را نمیگیرد، اما فهرستِ دقیقتری از جاهایی است که باید با چشمِ خودت ببینی.
چرا بررسی کد با هوش مصنوعی با یک مدل کم است
هر مدلِ زبانی عادتهایِ خودش را دارد. یکی رویِ نامگذاری و قالببندی حساس است، دیگری زود سراغِ امنیت میرود، سومی دوست دارد کلِ ماژول را بازنویسی کند. این عادتها با هر نسخهی تازه هم عوض میشوند، پس از قبل نمیشود گفت کدام مدل برایِ کدِ تو بهتر است؛ باید رویِ همان کد امتحانشان کنی.
مشکلِ جدیتر این است که مدل گاهی با اطمینانِ کامل حرفِ نادرست میزند: میگوید فلان تابعِ کتابخانه منسوخ شده، یا گزینهای را پیشنهاد میکند که اصلاً وجود ندارد. این همان پدیدهای است که در مقالهی توهم هوش مصنوعی بازش کردهایم. وقتی فقط یک بازبین داری، این هشدارهایِ ساختگی درست کنارِ هشدارهایِ واقعی مینشینند و وقتِ تو صرفِ جدا کردنشان میشود.
مشکلِ دوم موافقتطلبی است. اگر بنویسی «فکر میکنم این کد تمیز است، فقط یک نگاه بینداز»، خیلی از مدلها همان را تأیید میکنند و چند پیشنهادِ ظاهری اضافه میکنند. در چرا هوش مصنوعی همیشه با من موافق است توضیح دادهایم این رفتار از کجا میآید و صندلیِ مخالف چطور جلویش را میگیرد.
وقتی چند مدل اول بدونِ دیدنِ جوابِ هم کد را بخوانند و بعد یافتههایِ یکدیگر را نقد کنند، دو اتفاقِ مفید میافتد. مشکلی که فقط یکی دیده، در دورِ نقد یا تأیید میشود یا با دلیل رد. و هشدارِ بیپایه معمولاً از طرفِ صندلیِ دیگری زیرِ سؤال میرود. خودِ اختلاف هم اطلاعات است: جایی که دو بازبین سرِ یک خط به توافق نمیرسند، دقیقاً همانجایی است که باید خودت با دقت بخوانی.
چه چیزی را رویِ میز بگذاری
کیفیتِ بازبینی بیش از هر چیز به زمینهای بستگی دارد که میدهی. مدلی که نداند کد قرار است چه کند، فقط میتواند بگوید کد «چه میکند»، نه اینکه «درست» است یا نه. این چهار چیز را آماده کن:
- خودِ کد: مخزنِ گیتهاب را وصل کن تا صندلیها ساختارِ پروژه را ببینند، یا اگر تغییر کوچک است، تکهی مربوط را مستقیم در متنِ موضوع بچسبان. در هر دو حالت بگو کدام فایلها یا تابعها محورِ بحثاند. «کلِ پروژه را بررسی کن» معمولاً بازبینیِ سطحی و پراکنده تحویل میدهد.
- نیت: یکی دو جمله دربارهی رفتارِ مورد انتظار. مثلاً «این تابع باید بعد از بازگشت از درگاه، سفارش را پرداختشده علامت بزند و فقط یک بار کیفِ پول را شارژ کند.»
- قیدها: زبان و چارچوب، اینکه کد زیرِ درخواستهایِ همزمان اجرا میشود یا نه، و ورودی از کجا میآید و چقدر قابلِ اعتماد است.
- نگرانیِ خودت: اگر به بخشی شک داری، بگو؛ اما آن را به شکلِ سؤال بنویس، نه نتیجه. «آیا این قفل کافی است؟» بهتر از «این قفل کافی است، درسته؟» است، چون جوابِ صندلیها را از پیش جهت نمیدهد.
یک هشدارِ جدی: پیش از وصل کردنِ مخزن یا چسباندنِ کد، مطمئن شو هیچ رمز، کلیدِ API (کلیدِ دسترسی به سرویسهایِ بیرونی) یا فایلِ تنظیماتِ محرمانه داخلش نیست. این قاعدهی عمومیِ کار با هر ابزارِ بیرونی است. اگر رمزی قبلاً در تاریخچهی گیت ثبت شده، امنترین کار عوض کردنِ خودِ رمز است، نه فقط پاک کردنِ فایل.
تقسیمِ کار بین صندلیها
در چندهوش هر صندلی یک نقش میگیرد و برایِ کارِ فنی، قالبِ نقشهایِ حرفهایِ «برنامهنویسی» آماده است. لازم نیست همهی صندلیها همهچیز را بگردند؛ بهتر است در متنِ موضوع برایِ هر نقش یک تمرکز بنویسی تا کار تکراری نشود. یک تقسیمبندیِ کاربردی:
| نقش | تمرکز در بازبینی | سؤالِ نمونه |
|---|---|---|
| معمار | ساختار، مرزِ ماژولها، وابستگیها | این منطق در لایهی درستی نشسته یا کنترلر دارد کارِ سرویس را میکند؟ |
| منتقد | باگِ منطقی، حالتهایِ مرزی، امنیت | اگر ورودی خالی، خیلی بزرگ یا دستکاریشده باشد چه میشود؟ |
| عملگرا | خوانایی، تستپذیری، هزینهی نگهداری | نفرِ بعدی که این فایل را باز میکند، بدونِ پرسیدن میفهمد چه خبر است؟ |
| وکیلِ مدافعِ شیطان | زیرِ سؤال بردنِ خودِ تغییر | اصلاً این پیچیدگی لازم است یا مسئله جایِ دیگری است؟ |
اگر وسطِ بحث دیدی یک صندلی سراغِ حاشیه رفته، با «@نامِصندلی» مستقیم خطابش کن و تمرکزش را برگردان. یک مدل را هم میتوانی در دو صندلی با دو نقشِ متفاوت بنشانی؛ گاهی همان مدل در نقشِ منتقد چیزی میبیند که در نقشِ معمار از کنارش رد میشد.
چکلیستی که ارزش دارد به میز بدهی
مدلها وقتی فهرستِ مشخصی داشته باشند، دقیقتر میگردند و کمتر به نکتههایِ سلیقهای میچسبند. این فهرست را کامل یا بخشی از آن را در موضوع بیاور:
- حالتهایِ مرزی: فهرستِ خالی، صفر و عددِ منفی، رشتهی خیلی بلند، تاریخهایِ مرزِ ماه و سال، منطقهی زمانی و تبدیلِ تقویم.
- مدیریتِ خطا: آیا خطایی بیصدا بلعیده میشود؟ آیا پیامِ خطا جزئیاتِ داخلیِ سیستم را به کاربر نشان میدهد؟
- اعتبارسنجیِ ورودی و تزریق: هر جا ورودیِ کاربر به کوئریِ پایگاهداده، دستورِ سیستمعامل یا خروجیِ HTML میرسد، باید پارامتری یا خنثیسازیشده باشد (یعنی نویسههایِ خاص بیاثر شوند).
- مجوز، نه فقط ورود: اینکه کاربر وارد شده کافی نیست؛ آیا مالکِ همین سفارش یا همین فایل است؟ حفرهای که در آن کاربر با عوض کردنِ یک شناسه در آدرس به دادهی دیگران میرسد، زیاد دیده میشود.
- همزمانی و تکرار: اگر همین درخواست دو بار پشتِ سرِ هم یا همزمان برسد چه؟ برایِ هر چیزی که با پول، موجودیِ انبار یا شمارنده سروکار دارد، این سؤال حیاتی است.
- کارایی: کوئری داخلِ حلقه (مشکلِ معروفِ N+1، یعنی بهازایِ هر آیتم یک درخواستِ جدا به پایگاهداده)، بارگذاریِ کلِ جدول در حافظه، یا نبودِ ایندکس رویِ ستونی که مدام رویش جستوجو میشود.
- تست: آیا تستی هست که اگر این باگ برگردد، شکست بخورد؟ اگر نه، از صندلیها بخواه موردهایِ تستِ لازم را فهرست کنند.
- خوانایی: نامهایِ گویا، تابعهایِ بیش از حد بلند، و توضیحهایی که دیگر با کد نمیخوانند.
یک نمونهی فرضی: راستیآزماییِ تغییری در پرداخت
این بخش یک نمونهی فرضی است تا شکلِ کار روشن شود؛ نشستِ واقعی، کاربرِ واقعی یا نتیجهی واقعی نیست.
فرض کن تیمت تابعی نوشته که بعد از بازگشتِ کاربر از درگاهِ پرداخت، تراکنش را تأیید و کیفِ پولش را شارژ میکند، و میخواهی پیش از ادغام مطمئن شوی. نوعِ نشست را «راستیآزمایی» میگذاری و ادعا را اینطور مینویسی: «تابعِ تأییدِ پرداخت در این مخزن امن است و آمادهی ادغام است.» مخزنِ گیتهاب را وصل میکنی و در موضوع میگویی فقط فایلهایِ تأییدِ پرداخت و مدلِ کیفِ پول محورند.
- صندلیها: چهار صندلی از خانوادههایِ مختلف با قالبِ «برنامهنویسی»: یک معمار، دو منتقد (در متنِ موضوع یکی را به امنیت و دیگری را به همزمانی سپردهای) و یک عملگرا. صندلیِ «وکیلِ مدافعِ شیطان» هم روشن است.
- عمق: «عمیق»، چون کد با پول سروکار دارد و ارزش دارد دورِ نقد کاملتر باشد.
- پیش از شروع: «تأییدِ فرضها» را میزنی. یکی از فرضهایی که فهرست میشود این است که «درگاه هر بازگشت را فقط یک بار صدا میزند». ردش میکنی، چون کاربر ممکن است صفحه را تازه کند یا درگاه درخواست را دوباره بفرستد.
حکمِ نوشتهشده در چنین نمونهای میتواند این شکل را داشته باشد:
- نتیجه: تا حدی درست. منطقِ اصلی درست است، اما ادعایِ «آمادهی ادغام» پذیرفته نمیشود.
- توافق: اگر دو بازگشتِ همزمان برسد، هر دو وضعیتِ «در انتظار» را میخوانند و کیفِ پول دو بار شارژ میشود. راهِ پیشنهادی: قفل کردنِ ردیفِ تراکنش هنگامِ خواندن، یا بهروزرسانیِ شرطی که فقط وقتی وضعیت هنوز «در انتظار» است اثر کند و بعد بررسیِ اینکه واقعاً ردیفی تغییر کرده یا نه.
- توافقِ دوم: مبلغی که درگاه برمیگرداند با مبلغِ ذخیرهشدهی سفارش مقایسه نمیشود و به پاسخِ بیرونی بیش از حد اعتماد شده.
- اختلاف: معمار میخواهد منطقِ شارژ از کنترلر به یک سرویسِ جدا برود؛ عملگرا آن را برایِ این تغییر زیادی میداند. حکم این را اختلافی با اولویتِ پایین ثبت میکند که جلویِ ادغام را نمیگیرد.
- قویترین مخالفتِ باقیمانده: وکیلِ مدافعِ شیطان میگوید حتی با قفل، اگر تغییرِ وضعیتِ سفارش و شارژِ کیف در یک تراکنشِ پایگاهداده نباشند، خطا در میانهی راه داده را ناسازگار میکند. بقیه قبول دارند که خطر واقعی است، اما سرِ اینکه کدِ فعلی گرفتارش هست یا نه همنظر نیستند.
- توصیه: پیش از ادغام، دو اصلاحِ مورد توافق بهعلاوهی یک تست که همان درخواست را دو بار همزمان میفرستد و بررسی میکند موجودی فقط یک بار زیاد شده باشد.
بعد از حکم میتوانی سؤالِ پیگیری بپرسی، مثلاً «تستِ همزمانی را با چارچوبِ تستِ فعلیِ پروژه چطور بنویسم؟»؛ همان صندلیها کوتاه جواب میدهند و بحث از نو شروع نمیشود. اگر قویترین مخالفت هنوز ذهنت را درگیر کرده، «حالتِ دقتِ بالا» آن را مستقیم با دو صندلیِ منتقد به چالش میکشد.
با خروجیِ بازبینی چه کنی
در بررسی کد با هوش مصنوعی، فهرستِ یافتهها تازه اولِ کار است. این ترتیب کمک میکند وقتت هدر نرود:
- اول بازتولید کن. برایِ هر باگِ ادعاشده یک تست یا سناریویِ دستی بساز که نشانش بدهد. اگر نتوانستی، شاید هشدار بیپایه است؛ آن را با سؤالِ پیگیری از همان صندلیها بپرس.
- یافتههایِ مورد توافق را جدیتر بگیر، اما کورکورانه نه. توافقِ چند مدل احتمالِ درستی را بالا میبرد، ولی درستی را قطعی نمیکند.
- اختلافها را خودت بخوان. «نقشهی تصمیم» نشان میدهد کجا توافق بود، کجا نه و چرا؛ معمولاً ظریفترین مشکلها همانجا پنهاناند.
- سلیقه را از باگ جدا کن. پیشنهادِ تغییرِ نام یا جابهجاییِ کد را در یک فهرستِ جدا بگذار تا با اصلاحهایِ واقعی قاطی نشود.
- حکم را به اشتراک بگذار. آن را به PDF یا Word ببر یا لینکِ فقطخواندنی بساز و کنارِ درخواستِ ادغام (Pull Request) برایِ همتیمیها بگذار.
محدودیتهایِ بررسی کد با هوش مصنوعی
- صندلیها کد را میخوانند و دربارهاش استدلال میکنند؛ هر ادعایی دربارهی رفتارِ زمانِ اجرا استنتاج است، نه مشاهده. تستِ واقعی را خودت اجرا کن.
- قواعدِ کسبوکارت را نمیدانند مگر بگویی. کدی که از نظرِ فنی بینقص است، ممکن است قانونِ تخفیفِ شرکتت را اشتباه پیاده کند.
- هر پیشنهادی که به تابع یا گزینهی خاصی از یک کتابخانه اشاره میکند، با مستنداتِ رسمیِ همان نسخه چک کن.
- همهی مدلها ممکن است یک اشتباهِ رایج را با هم تکرار کنند؛ برایِ همین است که اختلافها و قویترین مخالفت در حکم ثبت میشوند تا ادعاها قابلِ وارسی بمانند.
- برایِ کدی که با سلامت، پول یا دادهی حساسِ مردم سروکار دارد، بازبینِ انسانیِ باتجربه و تستِ واقعی لازم است.
دربارهی هزینه: برایِ یک تابعِ کوچک، عمقِ «سریع» یا «عادی» و مدلهایِ سبکتر معمولاً کافی است. پیش از شروع برآوردِ هزینه را میبینی و میتوانی «سقفِ هزینه» بگذاری؛ ترفندهایِ بیشتر در کاهش هزینه استفاده از هوش مصنوعی آمده است.
جمعبندی
بررسی کد با هوش مصنوعی وقتی ارزش دارد که زمینهی کافی بدهی، کار را بینِ نقشها تقسیم کنی و خروجی را فهرستِ فرضیههایی برایِ وارسی ببینی، نه حکمِ نهایی. چند بازبینِ مستقل که هم را نقد میکنند، هشدارِ بیپایه را زودتر کنار میزنند و جاهایِ مبهم را با اختلافشان نشانت میدهند. اگر میخواهی ببینی سه مرحلهی نظرِ مستقل، نقد و حکم دقیقاً چطور پیش میرود، روندِ کارِ میزگرد را بخوان، و برایِ کاربردهایِ دیگر سری به کاربردهایِ چندهوش در تصمیمگیری بزن.
اگر بازبینی به سؤالِ بزرگتری رسید، مثلاً «این ماژول اصلاً باید سرویسِ جدا باشد؟»، سراغِ انتخاب معماری نرمافزار با هوش مصنوعی برو. و اگر محصولی که کدش را مینویسی هنوز بازارش ثابت نشده، شاید وقتِ بررسیِ خودِ ایدهی کسبوکار باشد.