همان چند باگ همیشگی که در کتابخانه‌های مورد اعتماد شما پنهان شده‌اند

من وقت خود را صرف ارسال اصلاحات کوچک به مخازن بزرگ مانند Langchain، Vite و Bat می‌کنم.

این پروژه‌ها از زبان‌ها و حوزه‌های مختلفی استفاده می‌کنند. نگهدارندگان آن‌ها متخصص هستند.

بخش غافلگیرکننده، تعداد باگ‌ها نیست؛ بلکه الگوها هستند. بیشتر باگ‌ها در واقع همان چند شکل همیشگی هستند که لباس‌های متفاوتی به تن کرده‌اند.

وقتی این الگوها را بشناسید، می‌توانید آن‌ها را پیش از رسیدن به مرحله تولید (production) شناسایی کنید. در اینجا پنج الگوی رایجی که پیدا کرده‌ام آورده شده است:

  • کلیدهای ورودی اشتباه در Langchain، یک تابع تغییر نام (rename) به دنبال کلیدی به نام old_path می‌گشت، در حالی که سیستم در واقع کلیدی به نام path ارسال می‌کرد. این باعث کرش کردن کد می‌شد. چرا از بررسی‌ها (review) جان سالم به در می‌برد: تست واحد (unit test) با موفقیت پاس می‌شد، زیرا توسعه‌دهنده ورودی مورد نیاز تابع را به صورت دستی ساخته بود، نه ورودی‌ای که سیستم در واقع ارسال می‌کند. راه بررسی: اگر تابعی یک کلید را می‌خواند، بررسی کنید که آن شیء (object) کجا ساخته می‌شود. اگر هیچ‌چیز آن کلید را مقداردهی نمی‌کند، یک باگ پیدا کرده‌اید. آن را در برابر فراخواننده واقعی (real caller) تست کنید.

  • تله‌های Truthiness یک اشتباه رایج، استفاده از بررسی truthiness است در حالی که منظور شما این است که «آیا این مقدار مقداردهی شده است یا خیر». مثال: const clause = defaultValue ? \DEFAULT ${defaultValue}` : '';` اگر مقدار 0 باشد، کد از آن شاخه عبور می‌کند. عدد 0 یک مقدار واقعی است، اما "falsy" محسوب می‌شود. راه بررسی: همیشه مقادیر 0، رشته‌های خالی و false را تست کنید. اگر کد شما نمی‌تواند تفاوت بین «نبودن مقدار» و «موجود بودن اما با مقدار صفر» را تشخیص دهد، خراب است.

  • سرریز منفی در اعداد صحیح بدون علامت (Unsigned Integer Underflow) در پروژه Bat، از محاسبات ریاضی برای محاسبه عرض ترمینال استفاده می‌شد. اگر عرض خیلی کم بود، تفریق منجر به underflow می‌شد. در انواع بدون علامت (unsigned types)، این اتفاق باعث می‌شود مقدار به یک عدد بسیار بزرگ تبدیل شود یا برنامه کرش کند. راه بررسی: هرگونه تفریق روی یک نوع بدون علامت که از ورودی کاربر استفاده می‌کند، نیاز به یک تفریق اشباع‌شونده (saturating subtraction) دارد. با مقادیر 0 و 1 تست کنید.

  • کدگذاری (Encoding) و موارد خاص (Edge Cases) قوانین متنی ساده به نظر می‌رسند تا زمانی که با کاراکترهای غیر ASCII مواجه شوید. Mistune با مشکلاتی در مورد جداکننده‌های (delimiters) انباشته شده که ممکن است یک مولد (generator) تولید کند، روبرو بود. Wenmode هنگام مدیریت علائم ترکیبی Unicode با شکست مواجه می‌شد. چرا از بررسی‌ها جان سالم به در می‌برد: کاراکترهای ASCII از هر تستی عبور می‌کنند. باگ‌ها فقط با ورودی‌هایی ظاهر می‌شوند که شما با دست تایپ نمی‌کنید. راه بررسی: از تست تفاضلی (differential test) استفاده کنید. خروجی خود را با یک پیاده‌سازی متفاوت و اثبات‌شده مقایسه کنید.

  • تجزیه (Parsing) ناامن Vite دارای یک میان‌افزار (middleware) بود که URLها را بدون هیچ حفاظی رمزگشایی (decode) می‌کرد. یک URL بدشکل (malformed) باعث پرتاب خطای URIError و کرش کردن میان‌افزار می‌شد. راه بررسی: هر چیزی که رمزگشایی یا تجزیه می‌کنید و خودتان آن را نساخته‌اید، نیاز به یک بلوک try/catch دارد. رشته‌های خراب را به سمت کد خود پرتاب کنید تا ببینید آیا کد منعطف است یا از هم می‌پاشد.

عادت من ساده است. وقتی یک باگ را اصلاح می‌کنم، به کدی که دقیقاً در کنار آن قرار دارد نگاه می‌کنم. اگر یک هندلر (handler) باگی داشته باشد، هندلر هم‌خانواده آن اغلب همان الگوی باگ را دارد.

منبع: https://dev.to/greymothjp/the-same-few-bugs-keep-hiding-in-libraries-you-already-trust-1pgp