الرئيسية > Visual Basic .Net > التعامل مع الاخطاء في البرمجة الكائنية : الفئة ExecutionCondition مثالاً

التعامل مع الاخطاء في البرمجة الكائنية : الفئة ExecutionCondition مثالاً

يعد اسلوب البرمجة الكانئية افضل اسلوب برمجي تطبقه في معظم اللغات الحديثة والقوية وخصوصا لغات الدوت نت سواء كانت VB.Net او C# ، وعندما تطبق هذا الاسلوب فمن الاكيد بانك ستقوم ببناء فئات Classes وستحتوي بداخلها على اعضاء Members كـ Properties,Function,Subs وغيرها ، ثم تستخدم هذه الفئات في أي جزء رئيسي من الرنامج بإنشاء كائن جديد منها ثم اسناد القيم والخصائص إليه من خلال المشيد Constructor في حالة وجوده او من خلال الخصائص القابلة للكتابة Writable Properties او لاشيء من هذا !

لاحقا وبعد ان تكتب الاكواد داخل الأعضاء الخاصة بفئتك التي انشاتها للتو واللحظة ، فإنك قد تتساءل حول عملية قنص الاستثناءات Exceptions ، فماذا لو حدث استثناء معين او خطاء وقت التنفيذ في الكود ؟ هذا ما سنناقشه هنا .

لنفترض انك قد قمت بعمل فئة بالإسم MyData والتي تمثل بيانات شخصيه معينه يتم اسنادها لها ،كالخصائص التالية مثلا : FirstName,FamilyName,Age  ، بحيث صارت كالتالي :

Public Class MyData

    Dim _FirstName As String

    Public Property FirstName() As String

        Get

            Return _FirstName

        End Get

        Set(ByVal value As String)

            _FirstName = value

        End Set

    End Property

 

    Dim _FamilyName As String

    Public Property FamilyName() As String

        Get

            Return _FamilyName

        End Get

        Set(ByVal value As String)

            _FamilyName = value

        End Set

    End Property

 

    Dim _Age As Byte

    Public Property Age()

        Get

            Return _Age

        End Get

        Set(ByVal value)

            _Age = value

        End Set

    End Property

 

End Class

 ثم طلبت منك ان تضيف لهذه الفئة طريقة Method تقوم بكتابة البيانات الى ملف – وذلك بإضافتها الى بيانات اخرى موجودة سابقا- لتكتب الاسم الاول والعائلة والعمر ، ولنفترض – واقول نفترض- انك كتبت الكود التالي بالضبط ( بما فيه من اخطاء فادحة ! ) :

    Public Sub WriteDataToFile(ByVal FileName As String)

        Dim FileContent As String

        FileContent = “الإسم الأول : ” & Me.FirstName & ” العائلة : ” & Me.FamilyName & ” العمر ” & Me.Age

 

        My.Computer.FileSystem.WriteAllText(FileName, FileContent, True)

 

 

    End Sub

 

الآن لو قمنا بإنشاء كائن جديد من هذه الفئة واعطيناه قيما لخصائصه وطلبنا من الكائن ان يتكرم علينا بتنفيذ الطريقة WriteDataToFile واعطيناه الوسيط المناسب كالتالي :

Module Module1

 

    Sub Main()

 

        Dim Mohammed As New MyData

        Mohammed.FirstName = “Mohammed”

        Mohammed.FamilyName = “AL-Nabhani”

        Mohammed.Age = 20

 

        Mohammed.WriteDataToFile(“C:\Users\Personals\Documents\MyData.txt”)

 

        Console.ReadLine()

 

    End Sub

 

End Module

 

ثم قمنا بتجربة البرنامج ، لكن مهلا هناك استثناء وارد بنسبه كبيرة جدا وهو ان الملف MyData غير موجود ! قد تفكر بان عملية التحقق من وجود الملف اولا افضل وانا اتفق معك في ذلك تماما ، لكن ما هي سيناريوهات العملية القادمة ؟ اذا لم يجد الملف ماذا يفعل البرنامج ؟

 

في حالتي لا اريد انشاء ملف لانني اريد ان اضيف البيانات الى الملف MyData لا أن أققوم بإنشاءه في حالة عدم وجودة ، لذلك فإننا نرغب الآن بإعلام المستخدم بأن الملف غير موجود واجزم انك تتفق معي الان في ذلك ، لكن السؤال كيف سنخبر المستخدم بذلك ؟ ان كنت ستقول لنكتب سطرا مثل التالي في الطريقة المعنية :

    Public Sub WriteDataToFile(ByVal FileName As String)

        Dim FileContent As String

        FileContent = “الإسم الأول : ” & Me.FirstName & ” العائلة : ” & Me.FamilyName & ” العمر ” & Me.Age

 

        If My.Computer.FileSystem.FileExists(FileName) = True Then

            My.Computer.FileSystem.WriteAllText(FileName, FileContent, True)

        Else

            Console.Write(“الملف غير موجود”)

        End If

 

    End Sub

 

فسأقول لك ان الطريقة السابقة خاطئة تماما ، صحيح انها ستعطينا الناتج النهائي المطلوب كما قد تشتهيه ، ولكن في في اسلوب البرمجة الكائنيه ذلك خطأ ، فالمفترض ان الفئة التي انشاناها لا تعرض شيء على الشاشة بدون اذن الطريقة Main ، وافرض او اننا اردنا استخدام هذه الفئة في مشروع من نوع WIndowsApplication بدل ConsoleApplication فماذا ستفعل ؟ الادهى لو قمت بترجمه الفئة الى ملف Dll فكيف ستعرف نوع المشروع الحالي ؟ حتى لو عرفت من خلال الكود فهل يعجبك ان تكتب جملة شرطية للتأكد من نوع المشروع ثم اظهار رسالة الخطأ بالطريقة الخاصة بكل واحد ؟

 

اتمنى انك اقتنعت بذلك ، اما الحل فسيكون بتعديل الطريقة WriteDataToFile لتكون  دالة Function بدل Sub وجعلها تعود بقيمة معينه ، طيب فكر معي ، ما هو النوع Type الخاص بهذه الدالة function والتي ستعيده ؟ هل ستعيد Boolean لنعرف ان حدث خطأ ام لا ؟ ام تعيد String في كل مرة ام أي نوع ؟ طيب لنفكر في كل واحدة على حده :

 

  • 1- النوع Boolean : فكرة جيدة ، لجعل الدالة تعيد قيمة True ان تم تنفيذها كما يجب ، و False في الحالة المعاكسه ولكن يعيبها عدم اعادتها لرسالة الخطأ ، ففي حالة امكانية حدوث اكثر من خطأ واحد فهناك ستواجه مشكلة حول أي رسالة خطأ ستعرض او أي اجراء ستنفذ .
  • 2- النوع String : طريقة جيدة نوعا ما ، لكن لو اردت كتابة دالة تعيد نوع معينا مثلا تقرأ ملفا معينا وتعيد الاسم الاول فكيف ستعرف ان ما اعادته هو الاسم الاول او رسالة الخطأ ؟

لا تقل لي لنضع Field ( حقل ) عام على مستوى المشروع بمثابته متغير من النوع Boolean يعرف اذا حدث خطا ام لا فهذه الطريقة تنتهك OOP من كل النواحي !

 

طيب ما الحل اذا ؟

الحل يتم بعمل نوع جديد خاص بنا لمثل هذه الحالات ، وهو عمل فئة Class تحمل خاصية تخبرنا ان حدث خطا او لا ، وتعطينا ايضا نص رسالة الخطأ او حتى كائن الـ Error بأكمله او أي شيء من هذا القبيل … كما قد نطورها اكثر لتحمل قيمة ما تود ارجاعه كما في الحالة الثانية اعلاه ، وهو الحل الذي سأتبعه في هذا النطاق مع انه قد يوجد حلول افضل ولكن ذلك يعتمد على الحالات التي تواجهها في برامجك .

 

الفئة الجديدة والتي سنعول عليها معرفة حدوث خطأ وحمل قيمة ناتج عملياتنا اسميتها ExecutionCondition وستحمل الخصائص التالية :

  • HasErrors : وهي خاصية للقراءة فقط ReadOnly ومن النوع Boolean
  • ErrorMessage : وهي خاصية للقراءة فقط ايضا ومن النوع Strign
  • Value : وهي خاصية اختيارية لك ، وهي من النوع Object .

 

بالنسبة للطرق فقد وضعت اجرائين فقط :

  • SetErrorMessage : وهو الذي نستخدمه في اعطاء الخاصية ErrorMessage قيمتها وبناءا عليه تتحدد قمية الخاصية HasErrors .
  • Reset : يعيد الكائن الى حالته الاساسية أي بدون خطأ مع عدم المساس بقيمة الكائن المتمثل في الخاصية Value .

 

لن اقوم بشرح كل شيء في هذه الفئة ، فهي واضحة وضوح الشمس لكل من لديه اساسيات ولو بسيطة في OOP :

”’ <summary>

”’ This class is used to return an object with value and error message when error occur

”’ </summary>

”’ <remarks></remarks>

Public Class ExecutionCondition

#Region “Properties”

    Dim _HasErrors As Boolean

    ”’ <summary>

    ”’ Determines if the assosiated process has an errors while executing it

    ”’ </summary>

    ”’ <value></value>

    ”’ <returns></returns>

    ”’ <remarks></remarks>

    Public ReadOnly Property HasErrors() As Boolean

        Get

            If Me._HasErrors = True Then Me._ErrorMessage = “” 

            Return _HasErrors

        End Get

    End Property

 

    Dim _ErrorMessage As String

    ”’ <summary>

    ”’ Gets the error message if the assisiated process has an erors while executing

    ”’ </summary>

    ”’ <value></value>

    ”’ <returns></returns>

    ”’ <remarks></remarks>

    Public ReadOnly Property ErrorMessage() As String

        Get

            Return _ErrorMessage

        End Get

 

    End Property

 

    Dim _Value As Object

    ”’ <summary>

    ”’ Represents the value of the ibject, it could be any type .

    ”’ </summary>

    ”’ <value></value>

    ”’ <returns></returns>

    ”’ <remarks></remarks>

    Public Property Value() As Object

        Get

            Return _Value

        End Get

        Set(ByVal value As Object)

            _Value = value

        End Set

    End Property

#End Region

 

#Region “Methods”

 

    Public Sub New()

 

    End Sub

    ”’ <summary>

    ”’ Sets the Error Message

    ”’ </summary>

    ”’ <param name=”Message”>”the message of the error that will be presented in Error Message property</param>

    ”’ <remarks></remarks>

    Public Sub SetErrorMessage(ByVal Message As String)

        _ErrorMessage = Message

        _HasErrors = True

    End Sub

    ”’ <summary>

    ”’ resets the object so no errors are contained

    ”’ </summary>

    ”’ <remarks></remarks>

    Public Sub Reset()

        Me._HasErrors = False

 

    End Sub

#End Region

End Class

 

الآن لنقم بعمل مثال عملي جديد لنجرب استخدام هذه الفئة ، اما بخصوص مثالنا السابق والفئة MyData فاعتبره تمرينا لك لحل مشكلتنا الأساسية !

 

في الوحدة النمطية Module1 التي تحتوي على الطريقة Main – الجزء الاساسي من البرنامج بطبيعة الحال – فقد قمت باضافة الدالة التالية فيها :

    Function WriteOnTheScreen() As ExecutionCondition

        Dim mExCn As New ExecutionCondition

 

        Try

            Console.WriteLine(5 / 1)

            Console.ReadLine()

 

            mExCn.Reset()

 

        Catch ex As Exception

            mExCn.SetErrorMessage(ex.Message)

        End Try

 

        Return mExCn

    End Function

 

وفي الطريقة Main كتبت الكود التالي :

    Sub Main()

        ‘لنجرب تنفيذ الدالة

        ‘WriteOnTheScreen

        If WriteOnTheScreen.HasErrors = True Then

            Console.WriteLine(WriteOnTheScreen.ErrorMessage)

        End If

        Console.ReadLine()

    End Sub

 

بعد تشغيل البرنامج سيظهر كل شيء على ما يرام هذه المرة وسيطبع 5 ، لنجرب الآن تعديل الطريقة WriteOnTheScreen ولنجعل القسمة مبنية على صفر وهذا خطأ رياضي فادح جدا :

    Function WriteOnTheScreen() As ExecutionCondition

        Dim mExCn As New ExecutionCondition

 

        Try

 

            Dim x As Integer = 5

            Dim y As Integer = 0

            Dim z As Integer = x / y

            Console.WriteLine(z)

            Console.ReadLine()

 

            mExCn.Reset()

 

        Catch ex As Exception

            mExCn.SetErrorMessage(ex.Message)

        End Try

 

        Return mExCn

    End Function

 

 

الآن قم بتنفيذ البرنامج ولاحظ ماسيحدث ، سيطبع نص رسالة الخطأ مهما يكن نوع الخطأ الذي حدث ، سواء القسمة على صفر او أي خطأ آخر وتأكد من كلامي جيدا !

 

ختاما ارجو انني قد وفقت في لفت الانتباء الى مسألة التعامل مع الاخطاء في الكائنات المستقلة واذا وجد هنا أي خطأ فأرجو تنبيهي عليه وجل من لا يسهو .

 

  1. محب سيدنا النبي
    فبراير 15, 2010 الساعة 6:36 م

    جزاك الله خيراً على هذا التوضيح و لعلي إن شاء الله أستخدم هذه المكتبة ExecutionCondition (بنفس الاسم أو غيره!) في تطبيقاتي المختلفة .

    أحسن الله إليك

  1. No trackbacks yet.

أضف تعليقاً

إملأ الحقول أدناه بالمعلومات المناسبة أو إضغط على إحدى الأيقونات لتسجيل الدخول:

WordPress.com Logo

أنت تعلق بإستخدام حساب WordPress.com. تسجيل خروج   / تغيير )

صورة تويتر

أنت تعلق بإستخدام حساب Twitter. تسجيل خروج   / تغيير )

Facebook photo

أنت تعلق بإستخدام حساب Facebook. تسجيل خروج   / تغيير )

Google+ photo

أنت تعلق بإستخدام حساب Google+. تسجيل خروج   / تغيير )

Connecting to %s

%d مدونون معجبون بهذه: