Table of Contents
چرا به راهبرد اشکالزدایی نیاز داریم؟
تقریباً هیچ کدی از بار اول «درست» کار نمیکند. فرق برنامهنویس مبتدی و حرفهای این نیست که حرفهای خطا نمیگیرد؛ تفاوت در این است که حرفهای میداند چطور خطا را پیدا و برطرف کند.
در این بخش روی روشها و عادتهایی تمرکز میکنیم که اشکالزدایی را سریعتر و کمدردسرتر میکند.
۱. بازتولید (تکرارپذیر کردن) خطا
اولین قدم اشکالزدایی این است که خطا را قابل تکرار کنید؛ یعنی بتوانید با یک سری ورودی و یک سناریوی مشخص، همان خطا را دوباره ببینید.
- همیشه سعی کنید ورودیهای مشخص را یادداشت کنید:
- چه چیزی کاربر وارد کرده بود؟
- چه فایل یا دادهای استفاده میشد؟
- اگر خطا «گاهی» رخ میدهد، سعی کنید الگو پیدا کنید:
- آیا فقط وقتی ورودی خالی است؟
- فقط وقتی عدد منفی است؟
- فقط وقتی لیست طول مشخصی دارد؟
یک نمونه سناریوی قابل تکرار را در یک کامنت بنویسید:
# سناریوی خطا:
# ورودی: 0
# انتظار: چاپ "عدد صفر است"
# اتفاق واقعی: خطای تقسیم بر صفروقتی خطا را دقیقاً بتوانید تکرار کنید، پیدا کردن علت آن بسیار سادهتر میشود.
۲. سادهسازی مسئله (کوچک کردن مشکل)
گاهی برنامهی شما بزرگ است و پیدا کردن مشکل در آن سخت. یکی از مهمترین راهبردها این است که مشکل را به کوچکترین مثال ممکن تبدیل کنید.
راهکارها:
- قسمتهای اضافی کد را موقتاً حذف کنید تا به بخشی برسید که هنوز همان خطا را تولید میکند.
- اگر از توابع مختلف استفاده میکنید، فقط تابع مشکوک را با یک مثال کوچک فراخوانی کنید:
# بهجای اجرای کل برنامه، مستقیماً فقط تابع را تست کنید
result = calculate_discount(-5)
print(result)این کار را «ساختن مثال حداقلی قابل بازتولید» مینامند. اگر روزی خواستید از دیگران کمک بگیرید، داشتن چنین مثال کوچکی بسیار به شما کمک خواهد کرد.
۳. استفادهی هوشمندانه از `print`
سادهترین و یکی از مؤثرترین ابزارهای اشکالزدایی برای مبتدیان، استفاده از print است.
ایده: در نقاط حساس برنامه، مقدار متغیرها را چاپ کنید تا ببینید واقعاً چه اتفاقی میافتد نه اینکه «فکر میکنید» چه میافتد.
مثال:
age = int(input("سن خود را وارد کنید: "))
print("DEBUG: age =", age) # چاپ مقدار برای بررسی
if age > 18:
print("بزرگسال")
else:
print("نابالغ")نکات مهم:
- در کامنت کنار این
printبنویسید که این برای اشکالزدایی است تا بعداً یادتان نرود حذفش کنید. - میتوانید چند چیز را همزمان چاپ کنید:
print("DEBUG:", x, y, total)- اگر خروجی خیلی شلوغ شد، فقط چند نقطهی کلیدی را چاپ کنید (مثلاً ابتدای حلقه، قبل از
if, و بعد از آن).
۴. بررسی گامبهگام منطق (ذهنی و روی کاغذ)
گاهی بدون اجرا کردن برنامه هم میتوانید خطا را پیدا کنید؛ کافی است کد را خطبهخط مرور کنید و ببینید برای یک ورودی مشخص چه میشود.
روش پیشنهادی:
- یک ورودی نمونه انتخاب کنید (مثلاً
x = 3). - روی کاغذ بنویسید که هر خط کد، با این ورودی، چه تغییری در متغیرها ایجاد میکند.
- بعد از هر خط، وضعیت متغیرها را یادداشت کنید.
مثال کوتاه:
x = 3
y = 2
z = x + y * 2روی کاغذ:
x = 3y = 2z = x + y * 2
یعنی $z = 3 + 2 \times 2 = 7$
اگر انتظار داشتید z برابر ۱۰ شود، میفهمید که مشکل از درک ترتیب عملیات بوده، نه از پایتون.
این نوع «اجرای دستی» برای حلقهها و شرطهای پیچیده بسیار مفید است.
۵. تقسیم و حل (بخشبندی مشکل)
اگر برنامهی شما طولانی است، بهجای اینکه کل برنامه را یکجا در ذهن نگه دارید، آن را به بخشهای کوچکتر منطقی تقسیم کنید و هر بخش را جداگانه بررسی کنید.
مثلاً در یک برنامهی سادهی مدیریت نمرات:
- بخش ورودی نمرات از کاربر
- بخش محاسبهی میانگین
- بخش تصمیمگیری قبول/رد
- بخش چاپ نتیجه
اگر خروجی اشتباه است، ببینید:
- آیا ورودیها درست خوانده میشوند؟
- آیا میانگین درست محاسبه میشود؟
- آیا شرط قبول شدن درست نوشته شده است؟
- آیا خروجی درست چاپ میشود؟
میتوانید بعد از هر بخش، یک print برای کنترل بگذارید:
scores = [18, 12, 15]
print("DEBUG: scores =", scores)
avg = sum(scores) / len(scores)
print("DEBUG: avg =", avg)
if avg >= 10:
status = "قبول"
else:
status = "رد"
print("وضعیت:", status)با این روش، سریع متوجه میشوید خطا در کدام «بخش» است.
۶. تست با ورودیهای مختلف و مرزی
بسیاری از خطاها فقط وقتی ظاهر میشوند که ورودی کمی «غیرعادی» باشد. برای همین خوب است که برنامهتان را با چند نوع ورودی مختلف امتحان کنید:
- ورودیهای معمولی (مثلاً عدد ۵، ۱۰، ۲۰)
- ورودیهای مرزی:
- صفر
- عدد منفی
- بزرگترین یا کوچکترین مقدار منطقی
- ورودیهای خالی یا غیرمنتظره:
- رشتهی خالی
"" - لیست خالی
[]
مثال:
اگر برنامهای دارید که طول یک لیست را تقسیم بر مجموع میکند، حتماً این حالتها را تست کنید:
# لیست معمولی
nums = [1, 2, 3]
# لیست با صفر
nums = [0, 0, 0]
# لیست خالی
nums = []این کار کمک میکند خطاهایی مثل «تقسیم بر صفر» یا «دسترسی به عنصر وجودنداشته» را زودتر پیدا کنید.
۷. خواندن دقیق پیام خطا (و جستوجو)
در بخشهای قبلی فصل با انواع خطا و پیامها آشنا شدهاید. اینجا روی یک نکتهی مهم تأکید میکنیم:
پیام خطا را کامل بخوانید و کلمات کلیدی آن را یادداشت یا جستوجو کنید.
مثال:
ValueError: invalid literal for int() with base 10: 'abc'کارهایی که میتوانید بکنید:
- کلمهی
ValueErrorرا در اینترنت جستوجو کنید به همراهpythonو تکهای از پیام. - اگر انگلیسیتان خیلی خوب نیست، پیام را ترجمه کنید و مفهوم کلی را بفهمید:
invalid literal for int()یعنی «رشتهای که نمیشود به int تبدیلش کرد».
این کار هم به یادگیری شما کمک میکند، هم راهحلهای رایج را سریعتر پیدا میکنید.
۸. استفاده از breakpoint و اشکالزدای (Debugger) IDE
علاوه بر print، بسیاری از محیطهای برنامهنویسی (مثل VS Code) ابزار اشکالزدای گامبهگام دارند.
ایدهی کلی (بدون ورود به جزئیات نصب و تنظیم):
- میتوانید روی یک خط کد نقطه توقف (Breakpoint) بگذارید.
- برنامه تا آن خط اجرا میشود و متوقف میشود.
- سپس میتوانید:
- مقدار متغیرها را ببینید.
- برنامه را خطبهخط جلو ببرید.
- ببینید در هر خط چه اتفاقی میافتد.
برای یک مبتدی، استفاده از print معمولاً راحتتر است، اما کمکم میتوانید یاد بگیرید از قابلیتهای اشکالزدای IDE هم استفاده کنید تا کنترل دقیقتری داشته باشید.
۹. چاپ نوع دادهها
بسیاری از خطاهای مبتدیان به خاطر عدم توجه به نوع داده (int, str, list, ...) است. یک راه ساده برای بررسی این است که نوع متغیرها را در حین اشکالزدایی چاپ کنید.
مثال:
value = input("یک عدد وارد کنید: ")
print("DEBUG: value =", value, "type:", type(value))
شاید فکر میکردید value یک عدد است، اما میبینید که نوع آن <class 'str'> است؛ پس باید آن را با int() تبدیل کنید (که در فصلهای دیگر یاد گرفتهاید).
این کار مخصوصاً وقتی مفید است که با ورودی کاربر، فایلها، یا لیستها کار میکنید.
۱۰. کار با نسخههای مختلف کد (ذخیرهی مرحلهای)
یکی از عادتهای خوب برای اشکالزدایی و توسعه این است که:
- وقتی برنامه درست کار میکند، یک نسخهی ذخیرهشده از آن نگه دارید.
- هنگام ایجاد تغییرات، روی یک نسخهی جداگانه کار کنید.
حتی اگر از سیستمهای مدیریت نسخه (مثل Git) هنوز استفاده نمیکنید، میتوانید:
- فایل را با نامهای مرحلهای ذخیره کنید، مثلاً:
calculator_step1.pycalculator_step2.py
اگر بعد از یک تغییر بزرگ، همهچیز خراب شد و اشکالزدایی سخت شد، میتوانید به نسخهی قبلی که درست کار میکرد برگردید و تفاوتها را مقایسه کنید.
۱۱. پرسیدن سؤال خوب (وقتی گیر میکنید)
گاهی با وجود تلاش، باز هم نمیتوانید مشکل را پیدا کنید. در این حالت، کمک گرفتن از دیگران (دوستان، انجمنها، اینترنت) خیلی مفید است.
اما برای اینکه دیگران بهتر کمک کنند، باید سؤال خوب بپرسید.
برای این کار:
- یک شرح کوتاه و واضح از مشکل بنویسید.
- پیام خطا را کامل کپی کنید.
- یک نمونه کد کوتاه که خطا را تولید کند آماده کنید (همان مثال حداقلی قابل بازتولید).
- توضیح دهید:
- چه انتظاری داشتید؟
- در واقع چه شد؟
نمونه توضیح خوب:
میخواهم میانگین نمرات را حساب کنم، اما وقتی لیست خالی است خطایZeroDivisionErrorمیگیرم.
کد نمونه:
scores = []
avg = sum(scores) / len(scores)
print(avg)با همین اطلاعات ساده، دیگران خیلی سریع میتوانند مشکل را شناسایی و توضیح دهند؛ و شما هم از توضیح آنها چیزهای جدید یاد میگیرید.
۱۲. عادتهای پیشگیرانه برای کاهش خطا
بهترین اشکالزدایی این است که کمتر نیاز به اشکالزدایی داشته باشید. چند عادت ساده کمک میکند:
- نامهای واضح برای متغیرها انتخاب کنید (
ageبهجایa,total_priceبهجایtp). - کد را مرحلهبهمرحله بنویسید و تست کنید، نه اینکه یکدفعه ۵۰ خط بنویسید و بعد اجرا کنید.
- برای بخشهای مهم، کامنت کوتاه بنویسید که این قسمت قرار است چه کاری بکند.
- بعد از اتمام یک بخش، با چند ورودی مختلف آن را تست کنید، حتی قبل از نوشتن بخش بعدی.
این عادتها باعث میشود وقتی خطا پیش میآید، دقیقاً بدانید در کدام تغییر یا بخش کد احتمالاً مشکل ایجاد شده است.
۱۳. ترکیب راهبردها در عمل (یک روند پیشنهادی)
در عمل، معمولاً چند تا از این روشها را با هم استفاده میکنید. یک روند سادهی پیشنهادی:
- پیام خطا را بخوانید و خطی که خطا در آن رخ داده را پیدا کنید.
- سعی کنید خطا را با یک ورودی مشخص و ساده دوباره تولید کنید.
- اطراف خط مشکوک، چند
printبگذارید تا: - مقدار متغیرها
- نوع متغیرها
- مسیر اجرای شرطها (
if/ حلقهها)
را ببینید. - اگر برنامه بزرگ است، آن را به چند بخش تقسیم کنید و هر بخش را جداگانه تست کنید.
- اگر هنوز مشکل مبهم است، کد را کوچک کنید تا به یک مثال حداقلی برسید.
- اگر باز هم گیر کردید، با داشتن:
- مثال کوچک
- توضیح مشکل
- پیام خطا
از دیگران کمک بگیرید.
اگر این روند را چند بار با حوصله انجام دهید، کمکم اشکالزدایی برایتان به یک مهارت طبیعی و نسبتاً راحت تبدیل میشود.
در فصلهای بعدی پروژههای مختلفی مینویسید؛ پیشنهاد میشود هنگام کار روی آنها، آگاهانه از این راهبردها استفاده کنید و برای خودتان یادداشت کنید که کدام روش بیشتر به شما کمک کرده است. با تکرار این کار، بهتدریج «شیوهی شخصی اشکالزدایی» خودتان را پیدا میکنید.