Faragiri

همهٔ زبان‌ها

آموزش کامنت و مستنداتکد تمیز نوشتن

سه سطر نمونه داخل رشته مستندات که با یک دستور اجرا می‌شوند. روزی که نرخ عوض شود، همان سه سطر شکست را گزارش می‌کنند.

۴بخش
۳دقیقه خواندن
۴عمق

یک تابع، چند لایه مستند

چیزی که خوانده می‌شود و چیزی که فقط نوشته شده

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

  • نام تابعاولین و بیشترین مستندی که خوانده می‌شود
  • امضا و نوع‌هاویرایشگر همان لحظه نشانش می‌دهد
  • سه سطر اول رشته مستنداتهمان چیزی که در راهنمای ویرایشگر جا می‌شود
چیزی که هنگام صدا زدن تابع دیده می‌شود
  • نمونه‌های اجراشدنیتنها بخشی که اگر دروغ شود چیزی گزارشش می‌کند
  • کامنت چراییتصمیمی که گزینه بدیهی‌تری داشت و رد شد
  • فایل راهنمای مخزنبرای کسی که تازه رسیده و باید پروژه را بالا بیاورد
  • ثبت تصمیم‌های معماریبرای کسی که شش ماه بعد می‌پرسد چرا این‌طور شد

این نقشه درباره مقدار نوشتن چیزی نمی‌گوید. یک پروژه کوچک ممکن است فقط دو لایه بالا را داشته باشد و کاملا مستند باشد.

هر کامنتی که با کد همگام نگه داشته نشود دیر یا زود دروغ می‌گوید، و هیچ ابزاری این را گزارش نمی‌کند. تنها استثنا مستندی است که خودش اجرا می‌شود.

سه نمونه داخل رشته مستندات تابع کرایه، درست به همان شکلی که در مفسر تعاملی تایپ می‌شوند:

  • >>> kerayeh_qalam(12)
    54000
  • >>> kerayeh_qalam(8, shekastani=True)
    50400.0
  • >>> kerayeh_qalam(0)
    0

اجرای python3 -m doctest kerayeh.py هر سه را می‌گیرد و اگر همه درست باشند هیچ چیزی چاپ نمی‌کند. حالا نرخ پایه را از چهار هزار و پانصد به چهار هزار و هشتصد عوض کنید و همان دستور می‌گوید:

  • Failed example: kerayeh_qalam(12)
  • Expected: 54000
  • Got: 57600

این تفاوت اصلی است. یک کامنت نمی‌تواند به شکلی غلط شود که چیزی متوجهش شود؛ یک نمونه اجراشدنی می‌تواند و همان لحظه هم می‌شود.

کامنت چه چیزی باید بگوید

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

اگر کامنت دارد نام‌ها را توضیح می‌دهد، مسئله نام‌هاست: ارزان‌ترین مستندی که وجود دارد. و اگر دارد ساختار یک تابع طولانی را توضیح می‌دهد، آن کامنت‌ها معمولا فهرست نام تابع‌هایی هستند که هنوز استخراج نشده‌اند: عوض کردن شکل، بدون عوض کردن رفتار.

مستند در سه سطح، و مخاطب هرکدام

رشته مستندات یک تابع برای کسی است که همین حالا می‌خواهد صدایش بزند و کافی است بگوید چه می‌گیرد، چه برمی‌گرداند، و در چه حالتی خطا می‌دهد. فایل راهنمای مخزن برای کسی است که تازه رسیده و باید در ده دقیقه پروژه را روی ماشین خودش بالا بیاورد. و ثبت تصمیم‌های معماری برای کسی است که شش ماه بعد می‌پرسد چرا این‌طور شد؛ اگر جایی برای آن نباشد، جواب در فایل‌های چت گم می‌شود و عملا وجود ندارد.

جایی که کار گیر می‌کند، فارسی و لاتین در یک فایل است

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

ابزار، و سالی که این حرف درست است

در سال ۲۰۲۶ ماژول doctest در کتابخانه استاندارد و رایگان است و جای نمونه‌ای را گرفته که در مستندات نوشته می‌شود و هیچ‌وقت اجرا نمی‌شود؛ اجرایش هیچ وابستگی‌ای ندارد و در خط لوله هم یک دستور است. برای مستند کردن یک پروژه کامل، mkdocs از همان فایل‌های متنی مخزن سایت می‌سازد و متن‌باز است، اما نصبش از مخزن بسته‌ها انجام می‌شود. اگر فقط یک چیز از این صفحه برمی‌دارید، همان دستور doctest باشد.

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

کنار این

بالای این