مسیر شما: سبز دانش » برنامه نویسی » دیباگ چیست؟ ۷ روش ساده برای پیدا کردن باگ و Debugging
دیباگ فرآیند ارزیابی، پیدا کردن و رفع باگ یا رفتار نادرست یک برنامه است. برای دیباگ کردن الزاماً به یک ابزار خاص نیاز نداریم؛ گاهی ارزیابی مرحلهبهمرحله کد و چاپ متغیرها کافی است. گاهی هم لازم است از ابزارهای جانبی کمک بگیریم تا با سرعتتر یا دقیقتر به برآیند برسیم.
نکته مهم اینجاست که هر مشکلی قرار نیست باعث Crash شدن یا نمایش Error در برنامه شود! مثلاً کد زیر از ابتدا تا انتها اجرا میشود؛ اما منطق محاسبه تخفیف اشتباه است:
price = 200000
discount = 5
final_price = price + discountاگر هدفمان اعمال 5٪ تخفیف باشد، خروجی نهایی باید 190,000 باشد و نه 200,005. پس با اینکه برنامه هیچ خطایی نداشت، ما یک باگ منطقی داریم که باید آن را دیباگ کنیم.
در این آموزش ابتدا میفهمیم که دیباگ چیست و چه تفاوتی با Bug و Debugger دارد. سپس مسیر درست دیباگ کردن را تحلیل میکنیم. در نهایت نیز 7 روش ساده و کاربردی برای پیدا کردن باگها و رفع آنها با مثال یاد میگیریم.
فهرست محتوای آموزش
برای دیباگ کردن کدها، یک روش مشخص و قطعی وجود ندارد!
گاهی برای یک مشکل ساده صرفاً یک print() ما را به برآیند میرساند؛ اما در یک مشکل پیچیدهتر ممکن است لازم باشد از ابزارهای جانبی استفاده کنیم یا Error Stack را به دقت تحلیل کنیم.
دیباگ کردن بیشتر از اینکه یک ابزار باشد، یک روش فکر کردن برای پیدا کردن علت مشکل است. البته این به این معنا نیست که از ابزارها استفاده نکنیم! نه! اتفاقاً خیلی از اوقات استفاده از ابزارهای جانبی و حتی پرسشوپاسخ با دستیارهای هوش مصنوعی به ما بسیار کمک خواهد کرد.
این سه اصطلاح را معمولاً کنار هم میبینیم اما معنی یکسانی ندارند. به زبان خیلی ساده در جدول زیر هر کدام را تعریف کردهام.
بنابراین، Bug همان مشکلی است که در برنامه وجود دارد. Debugging کاری است که برای پیدا کردن و رفع آن انجام میدهیم. Debugger ابزاری است که میتواند این فرآیند را برای ما سادهتر کند.
فکر میکنم به پاسخ این سؤال رسیده باشید که «آیا برای دیباگ کردن حتماً به دیباگر (Debugger) نیاز داریم؟» پاسخ «خیر» است. ما میتوانیم با خواندن کد، پرینت کردن، Log کردن اتفاقات، تحلیل پیام خطا و هر روش دیگری، کد را دیباگ کنیم.
قبل از اینکه سراغ معرفی ابزارها و روشهای مختلف برویم، بهتر است یک مسیر ذهنی مشخص برای دیباگ در زبانهای برنامهنویسی داشته باشیم.
بهطور کلی مسیر هفت مرحلهای زیر را به شما پیشنهاد میکنم:
در همان مثال اعمال کد تخفیفی که در ابتدا زدم، فرض کنید که کاربر یک مبلغ را وارد میکند اما مبلغ نهایی اشتباه نمایش داده میشود.
ابتدا باید مشخص کنیم که مشکل چیست؟
برای مبلغ ۲۰۰ هزار تومان و تخفیف ۵٪ انتظار دارم مبلغ نهایی ۱۹۰ هزار تومان باشد، اما برنامه ۲۰۰,۰۰۵ را نمایش میدهد.
حالا برنامه را با چند ورودی دیگر نیز امتحان میکنیم. مثلاً:
اگر مشکل برقرار بود، در تکتک این سناریوها مقدار متغیرها را در هر مرحله تحلیل میکنیم و روند اجرای کد را قدمبهقدم جلو میبریم. اینطوری تشخیص میدهیم که اشتباه کجا و به چه دلیل اتفاق افتاده است.
یادتان باشد که در فرآیند دیباگ کردن کد، دنبال حدس زدن دلیل خطا نیستیم؛ بلکه دنبال شواهد و چرایی بروز خطا میگردیم.
در این بخش ۷ روش ساده اما کاربردی که میتوانید از آنها برای پیدا کردن باگ برنامه و دیباگ آن استفاده کنید را با هم تحلیل میکنیم. این روشها وابسته به زبان برنامهنویسی خاصی نیستند. از سوی دیگر توجه کنید که روشهای مختلفی میتواند برای دیباگ کد وجود داشته باشند. اینها چند مثال و چند تا از پرکاربردترین روشها هستند.
کدهایی که در ادامه مینویسم به زبان python هستند. شما میتوانید از این روشها در هر زبانی که با آن کار میکنید استفاده کنید. اگر با پایتون کار میکنید نیز پیشنهاد میکنم در دوره جامع آموزش پایتون که تمرین و آزمونهای تعاملی و گواهی خاتمه دوره دارد شرکت کنید.
سادهترین روش دیباگ چیست؟ چاپ مقدار متغیرها در بخشهای مختلف برنامه!
فرض کنید نمیدانیم چرا مبلغ نهایی اشتباه چاپ شده است. در هر جایی که متغیری تعریف شده یا مقدار آن تغییر میکند، یکبار آن را پرینت میکنم:
price = 200000
discount = 5
print("price:", price)
print("discount:", discount)
final_price = price + discount
print("final_price:", final_price)با همین چند خط ساده میتوانیم متوجه شویم که محاسبهی اشتباه در کجا انجام شده تا به سراغ همان خط یا خطوط برویم.
اگر کدهایمان زیاد و طولانی باشد میتوانیم با پرینت کردن، ورود به بخشهای مختلف کد را مشخص کنیم. مثلاً:
print("مرحله 1")
# some code
print("مرحله 2")
# some code
print("مرحله 3")حالا اگر فقط «مرحله 1» و «مرحله 2» در خروجی چاپ شوند، متوجه میشویم که احتمالاً کدی که باعث خطا شده بین «مرحله 2» و «مرحله 3» است؛ چون برنامه به اجرای پرینت «مرحله 3» نرسیده است.
این روش خیلی ساده است؛ اما در پروژههای بزرگ اگر تعداد printها زیاد شود، خودش میتواند باعث شلوغی و گیجشدن ما شود. در چنین شرایطی بهتر است سایر روشها استفاده کنیم.
واضح است که من در این آموزش از مثالها و قطعه کدهای ساده و کوتاه استفاده میکنم. در پروژههای واقعی، معمولاً مقدار متغیرهای price و discount از جای دیگر (نظیر دیتابیس یا درخواستهای کاربر) دریافت میشود.
یکی از کاربردیترین روشهای دیباگ، استفاده از ابزارهای Debugger است. دیباگر اجازه میدهد اجرای برنامه را در یک خط مشخص متوقف کنیم و وضعیت متغیرها را در همان لحظه ببینیم.
برای این کار معمولاً یک Breakpoint روی خط موردنظر قرار میدهیم و برنامه را از طریق Debugger اجرا میکنیم.
مثلاً در کد زیر میتوانیم روی خط محاسبه final_price یک Breakpoint (~ نقطه شکست) قرار دهیم.
price = 200000
discount = 5
final_price = price + discount # اینجابرنامه تا آن نقطه اجرا میشود و موقتاً متوقف میماند. حالا میتوانیم مقدار price و discount را ببینیم که صحیح هستند یا نه. سپس ادامه دهیم. در این مثال، چون مقدار دو متغیر قبل از محاسبه final_price صحیح هستند، پس متوجه میشویم که مشکل از بخش محاسبه مبلغ نهایی است و نه مقداردهی متغیرها.
مزیت اصلی تعریف Breakpoint در Debugger این است که مجبور نیستیم برای هر متغیر یک بار print() اضافه کنیم.
گاهی مشکل با دیدن مقدار یک متغیر مشخص نمیشود و باید ببینیم که برنامه دقیقاً چه مسیری را طی میکند.
در این حالت اجرای مرحلهبهمرحله (Step by Step) بسیار مفید است. ابزارهای Debugging در IDEهای مختلف این قابلیت را به ما میدهند که اجرای برنامه را خطبهخط دنبال کنیم.
مثلاً فرض کنید تابع زیر را داریم:
price = 200000
discount = 5
discount_amount = price * discount / 100
final_price = price - discount_amount
print(final_price)اگر خروجی اشتباه باشد، میتوانیم برنامه را مرحلهبهمرحله اجرا کنیم و ببینیم که:
در واقع دنبال این هستیم که لحظهای را پیدا کنیم که وضعیت برنامه بر خلاف انتظار ما تغییر میکند.
یکی از رایجترین دلیلهای باگ این است که نوع یک متغیر چیزی نیست که فکر میکنیم! مثلاً در قطعه کد زیر به اشتباه فکر میکنیم که age عدد 20 است، اما در واقع آن یک رشته (string) است.
age = "20"
if age >= 18:
print("Adult")بنابراین هنگام دیباگ کردن کدها، فقط به اسم و مقدار ظاهری آنها اعتماد نکنید! بلکه حتماً نوع دادهای آنها را نیز تحلیل کنید. (بیشتر بخوانید: انواع دادهها در برنامهنویسی)
اگر با روش پرینت کردن پیش میروید، در زبانهای مختلف توابعی وجود دارند که نوع دادهای (data type) یک متغیر را به ما بدهند. اینطوری میتوانید از درست بودن نوع آن نیز مطمئن شوید.
مثلاً در پایتون میتوان بهصورت زیر عمل کرد:
age = "20"
print(age) # 20
print(type(age)) # <class 'str'>یکی از مهمترین مهارتها در دیباگ کردن این است که پیام خطا را بهطور دقیق و مناسب بخوانیم.
مثلاً اگر با پیامی شبیه به زیر روبهرو شویم:
TypeError: unsupported operand type(s) ...
به ما میگوید که هنگام انجام یک عملیات، نوع دادههای مورد استفاده با آن عملیات سازگار نیست.
یا اگر چیزی شبیه به پیام زیر ببینیم:
File "app.py", line 25
میفهمیم که سیستم مشکل را در خط 25 فایل app.py گزارش کرده است.
البته شماره خطی که در پیام خطا میبینیم همیشه محل ایجاد خطا نیست؛ اما معمولاً سرنخ بسیار مهمی برای آغاز ارزیابی علت خطا به ما میدهد.
پس هنگام دیدن یک خطا در کد، ابتدا پیام را بخوانید و از خودتان بپرسید:
یکی از دلایلی که در کلاسهای آنلاین برنامهنویسی بسیار تأکید میکنیم که حتماً پیغام خطا را بخوانید و متوجه شوید که چه میگوید همین است! امروزه با وجود دستیارهای هوش مصنوعی خیلی اوقات وسوسه میشویم که پیام خطا را به AI بدهیم و از او نظر بخواهیم. نمیگویم این کار اشتباه است یا نباید انجامش دهید؛ بلکه اگر در مسیر یادگیری برنامهنویسی هستید بهتر است خودتان نیز با پیامهای خطا دست و پنجه نرم کنید.
در پروژههای بزرگ نباید کل برنامه را همزمان ارزیابی کنیم. بهتر است برنامه را به بخشهای کوچکتر تقسیم کنیم و ببینیم خطا دقیقاً در کدام بخش بهوجود آمده است. این رویکرد شباهت زیادی به ایده Divide and Conquer در طراحی الگوریتم دارد.
فرض کنید یک ساختمان چند طبقه داریم و فیوز برق ناگهان قطع میشود. منطقی نیست که ابتدا به سراغ تکتک لامپها برویم و تحلیلشان کنیم. بلکه بهتر است تشخیص دهیم مشکل از کدام طبقه است و سپس آن بخش از آن طبقه را با دقت ارزیابی کنیم.
در برنامهنویسی هم دقیقاً باید همین کار را انجام دهیم. باید سعی کنیم یک محدوده کوچک که خطا در آن اتفاق افتاده را پیدا کنیم.
برای مثال، فرض کنید برنامه من شامل پنج مرحله اصلی است:
دریافت اطلاعات کاربر
↓
اعتبارسنجی
↓
محاسبه
↓
ذخیره در دیتابیس
↓
نمایش خروجی
اگر خروجی اشتباه است، لازم نیست که کل خطوط پروژه را ارزیابی کنیم. بهتر است ابتدا تشخیص دهیم که مشکل در کدام مرحله پیش آمده و سپس به کدهای همان بخش مراجعه کنیم.
هر چه محدوده مشکل را کوچکتر کنیم، پیدا کردن Bug سادهتر و معمولاً با سرعتتر میشود.
این روش شاید در نگاه اول کمی عجیب باشد؛ اما واقعاً مؤثر است!
من همیشه در دورههای آموزشی حضوریام یک ایده ساده مطرح میکنم:
«مشکل و کدت را خطبهخط و با صدای کمی بلند برای یک نفر یا حتی یک فرد فرضی شرح بده.»
مثلاً بگویید:
اینجا بها را میگیرم. بعد ۵ درصد تخفیف را محاسبه میکنم. بعد مقدار تخفیف را از نرخ کم میکنم…
وقتی مجبور میشویم منطق برنامه را مرحلهبهمرحله بیان دهیم، خیلی وقتها خودمان متوجه میشویم که یک فرض اشتباه داشتهایم؛ یا در جایی عملیات اشتباهی انجام دادهایم؛ یا یک مرحله آنطور که تصور میکردیم اجرا نمیشود.
این روش را با نام Rubber Duck Debugging (+) هم میشناسند؛ یعنی مسئله را برای یک شنونده تبیین دهیم؛ حتی اگر آن شنونده یک اردک پلاستیکی باشد!
در این آموزش فهمیدیم که دیباگ چیست و برای پیدا کردن باگ حتماً لازم نیست که سراغ ابزارهای پیچیده برویم. گاهی با چاپ مقادیر، استفاده از breakpoint، اجرای مرحلهبهمرحله یا شرح منطق برنامه میتوانیم باگهای کد را پیدا و رفع کنیم.
شاید بدانید، اما برای یادآوری بهتر است مروری بر سه نوع رایج خطاها در برنامهنویسی داشته باشم:
در واقعیت، بسیاری از مشکلاتی که به آنها «باگ/Bug» میگوییم، یکی از همین نوع خطاها یا ترکیبی از اینهاست.
این پنج نکته را بهعنوان جمعبندی برای دیباگ بهتر کدها به خاطر بسپارید:
در نهایت یادتان باشد که دیباگ کردن بیشتر از اینکه به ابزار وابسته باشد، به نحوه فکر کردن برنامهنویس وابسته است. هر چه بهتر بتوانید مشکل را به بخشهای کوچکتر تقسیم کنید و رفتار واقعی برنامه را ببینید، پیدا کردن باگها نیز با سرعتتر و سادهتر میشود.
امیدوارم از این آموزش نهایت استفاده را برده باشید. اگر دیدگاه یا سؤالی دارید، بخش دیدگاههای پایین صفحه برای شماست.
این آموزش برای همیشه بدون هزینهه! میتونید با اشتراکگذاری لینک این صفحه از ما حمایت کنید یا با خریداری یه فنجون نوشیدنی بهمون انرژی بدید!
جدیدترین اطلاعات و تغییرات مربوط به کردن در این گزارش ارائه شده است.
جزئیات مهم و نکات قابل توجه درباره برنامه در متن مقاله بررسی شده است.
این موضوع به دلیل اطلاعات و کاربردهای مرتبط، مورد توجه کاربران قرار گرفته است.
برچسب:
نویسنده: استخدام کار