۱۳۸۸/۰۶/۰۱

آشنايي با Defensive programming - قسمت دوم


در ادامه يك سري از خط مشي‌هاي متداول در defensive programming را با هم مرور خواهيم كرد:

1- بررسي نال بودن اشياء
سعي در استفاده از اشياء نال، به يك NullReferenceException منتهي خواهد شد. اگر به هر دليلي امكان نال بودن يك شيء وجود داشت، پيش از استفاده از آن، حتما اين وضعيت ‌را بررسي نمائيد.
بهترين ابزاري هم كه براي اين منظور مي‌توان استفاده كرد، نگارش جديد افزونه‌ي ReSharper است كه زير شيء‌ايي را كه احتمال نال بودن آن مي‌رود يك خط آبي رنگ مي‌كشد.



2- بررسي آرگومان‌هاي دريافتي
براي نمونه اگر متد شما تاريخي را بر اساس DateTime دريافت مي‌كند، حتما حدود آن‌را بررسي نمائيد. براي مثال دريافت تاريخ 31 اسفند از كاربر، به يك ArgumentOutOfRangeException منتهي خواهد شد. بنابراين آرگومان‌هاي دريافت شده بايد انتظارات مربوطه را برآورده كنند و پيش از استفاده حتما بررسي گردند تا بتوان مشكلات را به كاربر به صورت واضحي گوشزد كرد. (خطاي ArgumentOutOfRangeException براي كاربر نهايي بي‌معني است)

3- وضعيت اشياء را بررسي كنيد
براي مثال بستن يك كانكشن به ديتابيس در صورت بسته بودن آن،‌ به يك InvalidOperationException منتهي مي‌شود. بنابراين بهتر است ابتدا وضعيت اين شيء بررسي شده و سپس عمليات خاصي بر روي آن صورت گيرد.

4- هنگام كار با آرايه‌ها دقت كنيد
اگر انديس فراخواني شده كمتر از صفر يا بيشتر از اندازه‌ي آرايه باشد به يك IndexOutOfRangeException بر خواهيد خورد. بنابراين همواره بهتر است كه اين بررسي پيش از بروز واقعه انجام شود.

5- مراقب الگوريتم‌هاي بازگشتي باشيد
هر چند متدهاي بازگشتي در بعضي از موارد كار راه انداز هستند اما اگر بدون دقت از آن‌ها استفاده شود ممكن است سبب ايجاد يك حلقه‌ي بي نهايت شده و نهايتا برنامه با يك StackOverFlowException خاتمه مي‌يابد (اين مورد در دات نت فريم ورك تنها حالتي است كه با try و catch قابل مهار نيست).

6- هنگام تبديل اشيايي از نوع object‌ مراقب باشيد
اگر قصد تبديل يك شيء را به نوعي داشته باشيد كه با مقدار ذخيره شده در آن مطابقت ندارد، يك InvalidCastException حاصل خواهد شد. بنابراين در اينگونه موارد بهتر است از اپراتورهاي as و يا is استفاده كنيد. هنگام استفاده از as اگر عمليات تبديل با موفقيت صورت نگيرد، حاصل عمليات تنها يك شيء نال خواهد بود و استثنايي رخ نخواهد داد.

7- بجاي متد Parse از TryParse استفاده كنيد
براي مثال در دات نت جهت تبديل يك رشته به مقداري عددي مي‌توان از int.Parse و يا int.TryParse استفاده كرد. در حالت اول اگر عمليات تبديل ميسر نباشد حتما يك FormatException رخ خواهد داد اما در حالت دوم در صورت موفقيت آميز بودن عمليات تبديل، خروجي true خواهد بود و حاصل اصلي را با يك پارامتر از نوع out در اختيار شما قرار مي‌دهد.


و به صورت خلاصه
- ورودي‌هاي كاربر را محدود كرده (مثلا اگر قرار است عددي را وارد كند، از يك تكست باكس عددي (masked edit controls) استفاده كنيد) و يا آن‌ها را دقيقا بررسي نمائيد تا احتمال بروز خطاهاي بعدي را كاهش دهيد.
- زمانيكه مي‌توان از بروز يك exception جلوگيري كرد، بهتر است مديريت آن‌را به قسمت catch بلاك try/catch واگذار نكرد.
- و هنگاميكه با برنامه نويسي نمي‌توانيد تمامي خطاهاي ممكن را پيش بيني كرده و آن‌ها را مديريت كنيد، براي مديريت استثناء‌ها برنامه داشته باشيد.