اشکال زدایی (Debug کردن) برنامه

در این قسمت در رابطه با فرآیند debug کردن برنامه و حذف خطاها صحبت خواهیم کرد. مراحل کشف و رفع خطا از کدهای یک نرم افزار را debug کردن و یا اشکال زدایی می‌گوییم. مرحله debug کردن، به طور ایده‌آل بخشی از فرآیند تست نرم‌افزار است. اما ممکن است این مرحله در هر قسمتی از روند توسعه نرم افزار انجام گیرد. برنامه نویسان می بایست حتی کوچکترین ماژول ها را قبل از انتشار آنها، اشکال زدایی کنند. این موضوع باعث می‌شود که احتمال ایجاد خطا در روند تست، کاهش پیدا کند. همچنین هزینه‌های تست نرم‌افزار نیز کاهش یابد. در این قسمت در رابطه با انواع خطاهایی که ممکن است در یک نرم افزار رخ دهند صحبت خواهیم کرد.خطاهای syntaxخطاهای مربوط به syntax و یا اصطلاحاً syntax error، خطاهایی هستند که به دلیل اشتباهات برنامه نویس در کدنویسی اتفاق می افتند. این نوع از خطاها به دلیل نقص قوانین مربوط به زبان برنامه نویسی مورد نظر اتفاق می‌افتند. به طور کلی هر زبان برنامه نویسی قوانین خود از قبیل ایجاد کردن متغیرها، نوشتن دستورات و بسیاری موارد دیگر را دارند، که برای ساخت یک نرم افزار موفق در آن، می‌بایست از این قوانین طبیعت شود. زمانی که به هر دلیلی این قوانین نقص می شوند، خطاهایی رخ می‌دهد که اصطلاحاً به آن ها syntax error و یا خطاهای دستوری می‌گوییم.بسیاری از محیط های توسعه یکپارچه و یا همان integrated development environment ها به راحتی syntax errorها را تشخیص داده و برنامه نویس را در روند حل و فصل کردن آنها یاری می‌کنند. منظور از integrated development environment ها، ابزارهای از قبیل visual studio می باشد. اگر یک IDE نتواند در زمان کامپایل شدن برنامه، خطایی را تشخیص دهد، در زمان اجرای برنامه خطای مورد نظر ایجاد خواهد شد. تصویر زیر، کشف شدن یک خطا در کد نوشته شده را نشان می‌دهد که کامپایلر توانسته است آن را به درستی در زمان کامپایل شدن برنامه تشخیص دهد.خطاهای semanticمنظور از خطاهای semantic و یا اصطلاحاً semantic error ها که به آنها logical error نیز می‌گویند؛ خطاهایی هستند که مربوط به syntax برنامه نیستند. به همین دلیل، برنامه به درستی کامپایل و سپس اجرا می‌شود، اما متأسفانه نمی تواند خروجی مورد نظر برنامه نویس را به درستی تولید کند. به همین دلیل به این خطاها، اصطلاحاً خطاهای منطقی و یا logical error می گویند. کدی که در قسمت زیر مشاهده می کنید مثالی از این قضیه را نشان می‌دهد.در این قسمت برنامه نویس اقدام به نوشتن کدی کرده است که متأسفانه در زمان اجرا شدن برنامه، خروجی مورد نظر را تولید نمی کند. دلیل این موضوع نیز این است که به جای استفاده از عملگر مقایسه یا == (دو علامت مساوی)، از عملگر انتساب یا = (یک علامت مساوی)، استفاده کرده است. با نوشتن این کد، نرم افزار به درستی کامپایل و سپس اجرا می‌شود. اما عملیاتی که برنامه نویس مد نظر دارد به درستی انجام نخواهد شد.کشف کردن خطاهای منطقی و یا همان logical error به مراتب سخت‌تر است syntax error ها می باشد. چرا که در این نوع از خطاها، محیط توسعه یکپارچه، هیچ گونه خطایی را تشخیص نمی‌دهد و برنامه نویس می بایست با بررسی های دقیق تر و احتمالاً نوشتن تست، در روند کشف نرم افزار به خود کمک کند.خطای زمان اجراخطای زمان اجرا که اصطلاحاً به آن ها run time error نیز می‌گوییم، خطا هایی هستند که در روند اجرا شدن برنامه رخ می دهند. در واقع، این نوع از خطاها به syntax دستورات هیچگونه ربطی ندارد. در این نوع از دستورات، برنامه به درستی کامپایل شده و اجرا می‌شود. اما در زمان اجرا شدن، به دلیل خطاهایی که ممکن است رخ بدهند برنامه دچار اشکال خواهد شد. برخی از دلایل ایجاد شدن خطای زمان اجرا شامل موارد زیر هستند:حلقه های تکرار بی پایان و یا اصطلاحاً infinity loopتقسیم بر صفرداده های غلط وارد شده توسط کاربر (برای مثال؛ ورود داده عددی یا integer بجای string)بهینه سازی کددر این قسمت در رابطه با بهینه سازی کد و یا code optimization نیز صحبت خواهیم کرد. هر روشی که توسط آن، کد نوشته شده توسط برنامه نویس تغییر داده شود تا کیفیت و کارآمدی آن بیشتر شود را بهینه سازی کد و یا code optimization می گویم. از طرفی، کیفیت کد و یا code quality مشخص کننده طول عمر کد نوشته شده است. اگر کد نوشته شده بتواند برای مدتی طولانی کار و توسط برنامه نویسان مختلف نگهداری شود، می‌گوییم کیفیت کد نوشته شده بالاست. بنابراین، طول عمر نرم افزار افزایش پیدا می‌کند. از طرفی؛ اگر کدی با کیفیت بالا نوشته نشده باشد، نگهداری آن دشوار است. کدهای بی کیفیت، ممکن است از لحاظ خروجی شبیه به کدهای با کیفیت عمل کند و خروجی مورد نظر را تولید نمایند اما عملیات نگهداری آنها به دشواری امکان پذیر است.مورد دیگری که باید به آن دقت کنید کارآمدی کد و یا اصطلاحاً code efficiency است. منظور از code efficiency، قابلیت اطمینان کد و سرعت اجرا شدن آن است. code efficiency یک فاکتور بسیار مهم در تضمین عملکرد نرم افزار می باشد. به طور کلی، دو روش برای پیاده سازی عملیات بهینه سازی کد وجود دارد:روش intuition based optimization و یا IBO: در این روش، برنامه نویس سعی می کند که برنامه نوشته شده را بر اساس مهارت ها و تجارب خود بهینه سازی کند. این روش ممکن است برای نرم افزار های کوچک جواب دهد اما برای نرم‌افزارهای پیچیده امکان پذیر نخواهد بود.روش evidence based optimization و یا EBO: در این روش، ابزارهای خودکاری برای پیدا کردن گلوگاه‌های کارآمدی و یا performance bottleneck های برنامه استفاده می شود و قسمت های مختلفی از برنامه توسط این ابزارها بهینه سازی می گردد. هر زبان برنامه نویسی، مجموعه ابزارهای بهینه سازی کد خود را دارد که در استفاده کردن از آن زبان برنامه نویسی را یاری می کند.کد بهینه سازی شده زمان کمتری را برای اجرا شدن نیاز دارد و همچنین مصرف حافظه کمتری را نیز خواهد داشت. البته بین این دو مورد، یعنی زمان اجرا و مصرف حافظه می بایست تعادل برقرار گردد. منظور این است که اگر بهینه سازی برنامه از لحاظ زمان، باعث افزایش مصرف حافظه و یا کاهش بهینه سازی حافظه شود، عملیات بهینه سازی با شکست روبرو شده است. از طرفی، اگر بهینه سازی حافظه باعث شود که اجرای نرم افزار به کندی رخ بدهد، یک بار دیگر بهینه‌سازی شکست خورده است.بهینه سازی زمان اجرابهینه سازی زمان اجرا و یا اصطلاحاً execution time optimization، یکی دیگر از موارد بهینه سازی است. بهینه سازی کد برای اینکه راحت تر و سریعتر اجرا شود، می‌تواند در عملکرد برنامه تأثیر مثبتی داشته باشد. در قسمت زیر برخی از ترفندهای بهینه سازی برنامه از لحاظ زمانی را قرار داده ایم:استفاده از دستوراتی که از لحاظ زمانی بهینه سازی شده اند.استفاده از جملات switch به جای جملات شرطی ifحداقل کردن فراخوانی توابع درون حلقه های تکرار loopبهینه سازی ساختمان داده هایی که در برنامه استفاده می‌شود. در این رابطه توصیه می‌کنیم از آموزش الگوریتم ها و ساختمان داده ها در سی شارپ سری اول و آموزش الگوریتم ها و ساختمان داده ها در سی شارپ سری دوم استفاده کنید.بهینه سازی حافظههمانطور که می دانید، دستورالعمل های یک نرم افزار و همچنین داده های آن نیاز به مصرف حافظه دارند. زمانی که بحث داده به میان می آید، منظور داده های میانی حاصل از اجرای دستورات نیز می باشد. به همین دلیل، ما نیاز داریم که متوجه باشیم که اجرای یکسری دستورات، چه حجمی از حافظه را به خود اختصاص داده است. به این ترتیب بهتر می توانیم در رابطه با بهینه سازی حافظه تصمیم‌گیری کنیم. در ادامه لیستی از مواردی که می‌توانند در روند بهینه سازی حافظه به ما کمک کنند را قرار دادیم:استفاده از دستوراتی که به صورت درونی از لحاظ حافظه بهینه هستند.استفاده کردن حداقلی از متغیرهایی که می بایست در حافظه ذخیره شوند.جلوگیری از تعریف متغیر های سراسری و یا global در حلقه های تکراری که قرار است به دفعات زیادی اجرا شود.جلوگیری کردن از دستوراتی که نیاز به پردازش زیادی دارند.پس تا به اینجای کار در رابطه با اشکال زدایی و همچنین جنبه‌های مختلف بهینه سازی کد، از لحاظ زمانی و حافظه صحبت کردیم. این موضوع ها نیز از مهمترین مباحث مربوط به توسعه نرم‌افزارهای موفق می باشند.منبع: وبسایت پرووید