إعـــــــلان

تقليص
لا يوجد إعلان حتى الآن.

انت تعرف الكثير ! اكتب برامجك الشخصية !.

تقليص
X
 
  • تصفية - فلترة
  • الوقت
  • عرض
إلغاء تحديد الكل
مشاركات جديدة

  • [مقال] انت تعرف الكثير ! اكتب برامجك الشخصية !.

    بسم الله الرحمن الرحيم ،،


    الكثير منا يعرف مباديء البرمجة و الكثير منا قد يكون تخرج من الجامعة بدرجة بكالريوس في تقنية المعلومات او حتى دبلوم و لكن في النهاية لا يستطيع ان يبرمج برنامجا متكاملا او لنقل اي مشروع برمجي فنحن على ما نملكه من معرفة ينقصنا معرفة كيفية دمج ما تعلمناه في وحدة واحدة لنخرج بشيء جميل ..
    لنأخذ مثال : شخص يعرف اوامر قواعد البيانات و لكنه لا يستطيع ان ينشيء برنامج مدير مقالات .. لماذا ؟..
    اولا ماذا نعني ببرنامج متكامل؟
    هنا نحن لا نقصد متكامل بمعنى كامل لا نقص و لا عيب فيه فلا يوجد مثل هذا البرنامج الى الان ، و لكن ما نقصده انه متكامل بحيث انه يؤدي مجموعة من الوظائف المختلفة ، المبرمجة بمهارات مختلفة ، المؤطرة في اطار واحد سهل الاستخدام .
    لهذا يمكن ان نرجع سبب عجز الكثير منا عن برمجة برنامج متكامل الى عدم الالمام بكل جوانب تطوير البرامج التي لا تشمل البرمجة فحسب بل التخطيط و الاختبار و التصحيح و التعامل مع المستخدم ..الخ . فكتابة الاكواد ما هي الا جزء من عملية البرمجة و هي الجزء الممتع و لكن مع تطوير برنامج متكامل نحتاج الى اكثر من المتعة نحتاج الى الروتين و التعامل مع اشياء لا يلاحظها المستخدم النهائي و لكنها تعمل بصمت خلف الستار ..
    هذه الاشياء المملة تشمل مثلا رسم الواجهة الرسومية و التعامل مع كل الاحداث بشكل مناسب و التعامل مع الاخطاء و ليس تجاهلها .. فمن السهل ان نأخذ قيمة من المستخدم و لكن المشكلة و الملل تبدا حينما نريد ان نتأكد من ان المستخدم ادخل القيمة المناسبة من حيث النوع مثلا ..
    اذا نلاحظ ان برنامج ذو واجهة رسومية بسيط يأخذ عدد من المستخدم و يقسمه على اخر بدل ان يكون مهمة سريعة و سهلة اصبح امرا مملا و رتيبا حيث سنكتب الكثير من الاسطر البرمجية لرسم الواجهة و التأكد من ظهورها بشكل صحيح ثم نتأكد من ان المستخدم ادخل رقما و ليس حرفا و نتأكد ان الرقم المقسوم عليه ليس صفرا ..الخ.


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


    1- حدد فكرة البرنامج !.


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


    التطبيق ( فكرة البرنامج) : في هذا الموضوع مبدئيا قررت ان نبرمج برنامج عميل لتويتر على سطح المكتب ، و لكني عدلت برايي و اخترت ان يكون قاموسا او لنقل برنامج ترجمة .


    2-خطط للبرنامج مسبقا : فبدلا من انشاء جداول قاعدة البيانات مباشرة هكذا و من ثم اعادة كتابتها كلما اردت اضافة ميزة بسيطة و اعادة كتابة الاكواد البرمجية التابعة لهذه الجداول ، خطط مسبقا للميزات و الاختيارات المطلوبة و ستقل الحاجة الى التعديل بعد ذلك .
    لا بأس باستخدام برامج تخطيط جداول قواعد البيانات و طريقة اتصالها و ايضا استخدام uml لتخطيط سير البرنامج او تخطيط الكلاسات و طريقة تفاعلها . و لكن لا يجب ان نعقد المسألة اكثر من اللازم فاذا كان البرنامج بسيط فعلا فلا داعي لاضاعة الكثير من الوقت في هذه المرحلة .
    ايضا يمكن استخدام التخطيط اليدوي بقلمك و دفتر ملاحظاتك !. و هذه طريقتي المفضلة خاصة اذا كان البرنامج صغير او متوسط الحجم لانني اجد متعة في ذلك فالمهم ان نجعل من العملية متعة خاصة اذا كان المشروع شخصي و لا ينتظر منه ربح مادي مقابلا لاتعابك !.


    التطبيق (التخطيط) :


    طبعا هناك الكثير من الخيارات تعتمد على نقاط تلي هذه النقطة لذلك لن ندخل في تفاصيل المخطط الان و لكن بما لدينا من معلومات الان يمكننا ان نرسم مخطط بسيط لسير البرنامج باستخدام uml او هكذا على طريقة الخوارزميات :


    حدد اللغات المطلوبة للترجمة -> اطلب النص من المستخدم ->اتصل بقاعدة البيانات -> ارجع قيمة النص المترجم -> اعد العملية


    بسيط اليس كذلك ؟ يبدو ذلك في بداية الامر !.


    يتبع ان شاء الله ،،،،،
    Static files
    alyassen.github.io

  • #2
    الجزء الثاني

    3- حدد ادواتك و اعرف قدراتك :


    تحديد الادوات المناسبة للمهام المناسبة هو مرحلة حساسة في بناء اي مشروع ..
    ما هي اللغة البرمجية المناسبة؟
    ما هو الـ IDE المناسب ؟
    ما هي المكتبات المساعدة التي ساحتاجها ؟
    ما هي المصادر المتوافرة للدعم ؟
    ما هي الية التعامل مع المستخدم ؟
    ما هي قاعدة البيانات المستخدمة ؟
    ..الخ
    هذه الاسئلة حساسة جدا و تضمن الى حد كبير ان لا تقع في متاعب كثيرة في مرحلة التطبيق .. و تختلف الاجابات بالطبع حسب متطلبات المشروع البرمجي ..
    السؤال الاول مثلا في حال كان المشروع تطبيق ويب هل سي خيار مناسب ؟ في اغلب الاحيان لا .. في حال برمجة برنامج ويدجت هل ( هاسكل ) مناسبة ؟ لا اعتقد ذلك.. php و بيرل و روبي خيارات افضل في الحالة الاولى و جافاسكربت في الحالة الثانية ..
    السؤال الثالث ما هي المكتبات التي سأحتاجها ؟ كلما كان البرنامج اكبر و يحتاج الى اشياء معقدة كلما كانت الحاجة الى المكتبات اكثر .. قبل ان ابدء في مشروع كتابة برنامج سطح مكتب يجب ان ادرس الخيارات التي تقدمها لي لغة البرمجة هل توفر لي Wxwidgets ، GTK ..الخ ؟ اي مكتبة سأختار هل سيكون برنامجي لويندوز او لينكس او ماك ؟ ..
    ما هي المصادر المتوافرة ؟ هل اذا واجهتني مشكلة سأجد من يساعدني ؟ هل تتوافر مصادر غنية ؟ هل يوجد توثيق كامل؟ …


    لا تنسى ان تعرف قدراتك بعض المكتبات ليست مجرد مكتبات بل عالم في حد ذاتها فتوافر مكتبة sdl لا يعني انني استطيع كتابة لعبة فقط من خلال قراءة التوثيق بل تتعدى الى مهارات و تقنيات و مفاهيم اضافية تحتاج الى وقت كبير لتعلمها يوازي ربما الوقت الذي قضيته لتعلم لغة البرمجة نفسها !.


    التطبيق (حدد ادواتك ) :
    سأكتفي بالاجابة عن الاسئلة المطروحة سلفا فقط ، و ذلك على حسب حاجة برنامجنا .
    ما هي اللغة البرمجية المناسبة؟
    بما انني اجيد بيرل و المشروع شخصي و اللغة مناسبة لهكذا نوع من المهام فلا بأس من استخدامها .
    ما هو الـ IDE المناسب ؟
    Padre + wxGlade و ذلك لان glade سيرسم لنا الواجهة الرسومية و بادري سيساعدنا في تطوير اكواد بيرل خاصة انه برنامج مكتوب بها و بمكتبة wx !
    ما هي المكتبات المساعدة التي ساحتاجها ؟
    سنحتاج بعض المكتبات و لكن المهم الان هو مكتبة wxPerl التي ستوفر لنا امكانية انشاء الواجهة الرسومية ، طيب لماذا لا نستخدم GTK او QT او حتى سوينج ؟!..
    هنا نحتاج ان نعمل دراسة سريعة قبل اتخاذ القرار فمكتبة كيوت مكتبة ممتازة جدا و لكن في بيرل هي خيار سيء لقلة المصادر و قدم الاصدار المتوافر .. GTK ايضا ممتازة لو كنا سنكتفي بلينكس و لكن ربما احب ان انقل البرنامج الى ويندوز و تشغيل هذه المكتبة هناك ليس بالامر السهل .. سوينج ؟ سنحتاج الى مكتبات اضافية كثيرة لكي نستطيع تشغيلها من بيرل فلا داعي لكل هذا .. Tk افضل المكتبات المتوفرة لبيرل من ناحية التوثيق و لكنها لا تدعم العربية !. اذا الخيار الافضل هو wxPerl فالتوثيق موجود و المكتبة قوية جدا و متعددة المنصات في حال رغبنا في تشغيلها في اي نظام تشغيل لكي تظهر و كأنها من نفس برامج نظام التشغيل ..
    ما هي المصادر المتوافرة للدعم ؟
    بيرل لا يوجد لها دعم مادي خاصة في عالمنا العربي لذلك قد لا تكون خيار مناسب للشركات هنا و لكن المصادر المتوافرة ممتازة جدا للمشاريع الشخصية من كتب و توثيق و منتديات و غرف مساعدة و مجموعات بريدية ..
    ما هي الية التعامل مع المستخدم ؟
    سطر الاوامر ؟ صفحات ويب؟ واجهة رسومية ؟ يبدو انكم خمنتم الخيار الثالث لاننا تكلمنا عن المكتبة التي سنستخدمها !.


    ما هي قاعدة البيانات المستخدمة ؟
    فلات فايل ؟ مايسكوال ؟ اوراكل ؟! SQLight ؟
    يمكن اختيار الفلات فايل في المشاريع الصغيرة و المتوسطة و لكنها خيار سيء للمشاريع الكبيرة و لن اختارها لكي لا احتاج للكثير من الاسطر البرمجية لفتح و قفل و اغلاق الملفات النصية ..
    مايسكوال لن استخدمها لان برنامجي لا يحتاج الى سيرفر فهو ليس تطبيق ويب ..
    اوراكل ليس لدي المال الكافي !.
    SQLight كنت ساستخدمها لو كنت ساصنع قاعدة الكلمات بنفسي و لكني لاني كسول سأستخدم قاعدة كلمات جاهزة !.


    اذا الان لدي خيارين ان استخدم قاعدة بيانات جاهزة للكلمات مثل ما توفره Arabeyes و هي من نوعية الملفات النصية او ان استخدم قاعدة بيانات موجودة على الويب مثل ما توفره BabelFish؟ و لكنه لا يوفر اللغة العربية اذا ساختار مترجم جوجل !.


    4- رسم الواجهة الرسومية GUI :


    طبعا يمكن البدء بعملية كتابة الاكواد و الدوال الحقيقية اولا ثم رسم الواجهة الرسومية خاصة لمن يحبون طريقة الاختبار قبل البرمجة و هذا ما فعلته انا عندما كنت اكتب الاكواد التي سنستخدمها في هذا الموضوع و لكن في المقالة هنا فضلت ان نرسم الواجهة الرسومية بشكل سريع و ننتهي منها اولا ..


    التطبيق :
    اولا و قبل كل شيء ارسم الواجهة بيدك كما تحب ان تظهر لاحقا لكي ترتاح في عملية وضع الاشياء في اماكنها الصحيحة لاحقا!...
    هنا رسمي المتواضع ..:


    اضغط على الصورة لعرض أكبر. 

الإسم:	sketch.jpg 
مشاهدات:	1 
الحجم:	25.6 كيلوبايت 
الهوية:	835603
    بعدها يمكنني البدء في استخدام wxGlade للرسم الحقيقي و لن اتكلم عن هذه النقطة خوف التطويل و برجاء ان يشاهد المهتمين الشروحات التي عملتها لهذا البرنامج ..




    يتبع ان شاء الله
    Static files
    alyassen.github.io

    تعليق


    • #3
      تصحيح SQLight إلى SQLite
      يرجى جعل الخط غير مائل و غير عريض على مدونتك

      تعليق


      • #4
        المشاركة الأصلية بواسطة zaher مشاهدة المشاركة
        تصحيح SQLight إلى SQLite
        يرجى جعل الخط غير مائل و غير عريض على مدونتك
        احسنت اخي Zaher ، دائما اكرر خطأ الكتابة هذا لانهما تلفظان بنفس الطريقة .. too - to

        تحية لك ...
        Static files
        alyassen.github.io

        تعليق


        • #5
          part 3

          5- ربط الواجهة الرسومية مع الاكواد الحقيقية :


          بعد رسم الواجهة الرسومية باستخدام برنامج wxGlade او اي برنامج تصميم واجهات مثل Glade و Tk builder ..الخ نأتي الى مرحلة الربط بين الواجهة و الكود البرمجي … قبل ان استرسل يجب ان انوه انني كنت من المعارضين لاستخدام برامج رسم الواجهات الرسومية لانها تضيف اكواد اضافية كثيرة يمكن اختصارها و لكن الميزة التي تجعلني افضل استخدامها هو اولا سرعة التصميم بالطبع فننتهي من هذه المرحلة المملة بسرعة و ايضا توفيرها اليات جيدة لفصل الكود البرمجي عن الكود المرئي و ذلك سواء باستخدام ملف وصفي منفصل ( مثلا xml) او حتى تضمين الكود البرمجي في الكود المرئي و لكن بتوفير اليات مريحة لتحديث الكود المرئي بشكل منفصل عن الكود البرمجي .
          نعود مرة اخرى ، انتهينا من تصميم الواجهة الرسومية و هكذا تبدو :


          اضغط على الصورة لعرض أكبر. 

الإسم:	gui.jpg 
مشاهدات:	1 
الحجم:	63.8 كيلوبايت 
الهوية:	835611


          ماذا نفعل الان ؟
          الخطوة الاساسية الان هي ان نربط الواجهة بالكود و ذلك يتم عن طريق وضع متنصت Action listener (handler) لكل حدث Event ..
          طيب عندما اشاهد كل جزء من برنامجي اعرف انه يمكن ان تحدث احداث كثيرة في برنامجي و لكن يمكنني فقط الاهتمام بالاحداث التي لها تأثير مباشر على سير البرنامج .. مثلا يمكنني وضع متنصت لتحرك الماوس على منطقة الكتابة و عليه اخذ اكشن معين و لكن لا يوجد كثير جدوى من فعل ذلك في برنامجنا الان ..


          اذا سألخص اهم النقاط التي يجب ان اهتم بها كالتالي:


          1- سأضع متنصت للنقر على زر الخروج لانهاء كل عمليات البرنامج.
          2- سأضع متنصت للنقر على زر Credit كي اظهر معلومات البرنامج.
          3- سأضع متنصت لزر Swap و لكي يقوم باستبدال اماكن اللغتين .
          4- سأضع متنصت لزر Tran و لكي يقوم بمهمة الترجمة و عرضها في مكانها الصحيح .


          ملاحظات :
          1- الجزء الذي سيظهر فيه النص المترجم سيتم اقفاله بحيث لا يمكن للمستخدم الكتابة فيه و لكن يمكنه النسخ منه و ايضا سيتم اظهار رسائل الاخطاء في هذا المكان.
          2- لدينا خيارات كثيرة في كيفية توفير الية اختيار اللغات و لكن سنختار ComboBox لسهولته و لتوفيره المكان فهو لا يأخذ مكان كبير في البرنامج و انما يتوسع فقط في حالت النقر عليه ليظهر اللغات المتوفرة ( سنقوم باضافة 30+ لغة و لكن لن نضيف كل اللغات التي يوفرها جوجل فبعضها الى الان في حالة تجريبية ) ..
          3- لن نضع متنصت خاص بكل صندوق اختيار بل سنطلبها يدويا في دالة الترجمة، لان هذا الحدث ليس مهما الا في حالة النقر على زر الترجمة .


          التطبيق :
          سيكون لدينا ملف بيرل جاهز بعد توليده من برنامج wxGlade حيث سنكون جاهزين لبدء الربط بين البرنامج و الواجهة من خلال تطبيق Implement الدوال التي قمنا بالاعلان عنها مبدئيا :


          كود PHP:
          #!/usr/bin/perl -w --  
           # generated by wxGlade 0.6.3 on Fri Oct  8 21:50:29 2010 
           # To get wxPerl visit http://wxPerl.sourceforge.net/ 
           
           
          use Wx 0.15 qw[:allclasses]; 
           use 
          strict
           
           
          package MyFrame1
           
           use 
          Wx qw[:everything]; 
           use 
          base qw(Wx::Frame); 
           use 
          strict
           
           
          sub new { 
               
          my$self$parent$id$title$pos$size$style$name ) = @_
               
          $parent undef              unless defined $parent
               
          $id     = -1                 unless defined $id
               
          $title  ""                 unless defined $title
               
          $pos    wxDefaultPosition  unless defined $pos
               
          $size   wxDefaultSize      unless defined $size
               
          $name   ""                 unless defined $name
           
           
          # begin wxGlade: MyFrame1::new 
           
               
          $style wxCAPTION|wxCLOSE_BOX|wxFRAME_NO_TASKBAR|wxCLIP_CHILDREN  
                   unless defined $style

           
               
          $self $self->SUPER::new( $parent$id$title$pos$size$style$name ); 
               
          $self->{label_1} = Wx::StaticText->new($self, -1"From : "wxDefaultPositionwxDefaultSize, ); 
               
          $self->{origin} =  Wx::ComboBox->new($self, -1""wxDefaultPositionwxDefaultSize,  ["AutoDetect""Arabic""English""French""Dutch""German",  "Persian""Turkish""Japanese""Italian""Slovak""Serbian",  "Thai""Hindi""Hebrew""Spanish""Greek""Russian""Swedish",  "Croation""Polish""Portuguese""Filipino""Irish""Malay",  "Belarusian""Czech""Norwegian""Swahili""Catalan""Bulgarian",  "Korean""Indonesian""Chinese""Vietnamese""Yiddish",  "Afrikaans"],  wxCB_DROPDOWN|wxCB_SIMPLE|wxCB_DROPDOWN|wxCB_READONLY|wxCB_SORT); 
               
          $self->{Swap} = Wx::Button->new($self, -1"Swap <->"); 
               
          $self->{label_2} = Wx::StaticText->new($self, -1"To :"wxDefaultPositionwxDefaultSize, ); 
               
          $self->{destination} =  Wx::ComboBox->new($self, -1""wxDefaultPositionwxDefaultSize,  ["Arabic""English""French""Dutch""German""Persian""Turkish",  "Japanese""Italian""Slovak""Serbian""Thai""Hindi""Hebrew",  "Spanish""Greek""Russian""Swedish""Croation""Polish",  "Portuguese""Filipino""Irish""Malay""Belarusian""Czech",  "Norwegian""Swahili""Catalan""Bulgarian""Korean""Indonesian",  "Chinese""Vietnamese""Yiddish""Afrikaans""Ukrainian"],  wxCB_DROPDOWN|wxCB_SIMPLE|wxCB_DROPDOWN|wxCB_READONLY|wxCB_SORT); 
               
          $self->{Trans} = Wx::Button->new($self, -1"Trans!"); 
               
          $self->{origin_text} = Wx::TextCtrl->new($self, -1""wxDefaultPositionwxDefaultSizewxTE_MULTILINE|wxHSCROLL); 
               
          $self->{translated_text}  = Wx::TextCtrl->new($self, -1""wxDefaultPositionwxDefaultSize,  wxTE_MULTILINE|wxTE_READONLY); 
               
          $self->{Credits} = Wx::Button->new($self, -1"Credits"); 
               
          $self->{Exit} = Wx::Button->new($self, -1"Exit"); 
           
               
          $self->__set_properties(); 
               
          $self->__do_layout(); 
           
               
          Wx::Event::EVT_COMBOBOX($self$self->{origin}->GetId, \&OnSelection); 
               
          Wx::Event::EVT_BUTTON($self$self->{Swap}->GetId, \&OnSwap); 
               
          Wx::Event::EVT_COMBOBOX($self$self->{destination}->GetId, \&OnSelection); 
               
          Wx::Event::EVT_BUTTON($self$self->{Trans}->GetId, \&OnTrans); 
               
          Wx::Event::EVT_BUTTON($self$self->{Credits}->GetId, \&OnCredit); 
               
          Wx::Event::EVT_BUTTON($self$self->{Exit}->GetId, \&OnExit); 
           
           
          # end wxGlade 
               
          return $self
           
           } 
           
           
           
          sub __set_properties 
               
          my $self shift
           
           
          # begin wxGlade: MyFrame1::__set_properties 
           
               
          $self->SetTitle("GTranslate"); 
               
          $self->{origin}->SetSelection(0); 
               
          $self->{destination}->SetSelection(0); 
               
          $self->{origin_text}->SetMinSize(Wx::Size->new(42877)); 
           
           
          # end wxGlade 
           

           
           
          sub __do_layout 
               
          my $self shift
           
           
          # begin wxGlade: MyFrame1::__do_layout 
           
               
          $self->{sizer_2} = Wx::BoxSizer->new(wxVERTICAL); 
               
          $self->{sizer_3} = Wx::BoxSizer->new(wxVERTICAL); 
               
          $self->{sizer_4} = Wx::BoxSizer->new(wxHORIZONTAL); 
               
          $self->{sizer_5} = Wx::BoxSizer->new(wxHORIZONTAL); 
               
          $self->{sizer_5}->Add($self->{label_1}, 0wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL0); 
               
          $self->{sizer_5}->Add($self->{origin}, 0wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL0); 
               
          $self->{sizer_5}->Add($self->{Swap}, 0wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL0); 
               
          $self->{sizer_5}->Add($self->{label_2}, 0wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL0); 
               
          $self->{sizer_5}->Add($self->{destination}, 0wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL0); 
               
          $self->{sizer_5}->Add($self->{Trans}, 0wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL0); 
               
          $self->{sizer_3}->Add($self->{sizer_5}, 1wxEXPAND0); 
               
          $self->{sizer_3}->Add($self->{origin_text}, 0wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL0); 
               
          $self->{sizer_3}->Add($self->{translated_text}, 0wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL0); 
               
          $self->{sizer_4}->Add($self->{Credits}, 0wxALIGN_RIGHT0); 
               
          $self->{sizer_4}->Add($self->{Exit}, 0wxALIGN_RIGHT0); 
               
          $self->{sizer_3}->Add($self->{sizer_4}, 1wxEXPAND0); 
               
          $self->{sizer_2}->Add($self->{sizer_3}, 1wxEXPAND0); 
               
          $self->SetSizer($self->{sizer_2}); 
               
          $self->{sizer_2}->Fit($self); 
               
          $self->{sizer_2}->SetSizeHints($self); 
               
          $self->Layout(); 
           
           
          # end wxGlade 
           

           
           
          sub OnSelection 
               
          my ($self$event) = @_
           
          # wxGlade: MyFrame1::OnSelection <event_handler> 
           
               
          warn "Event handler (OnSelection) not implemented"
               
          $event->Skip
           
           
          # end wxGlade 
           

           
           
           
          sub OnSwap 
               
          my ($self$event) = @_
           
          # wxGlade: MyFrame1::OnSwap <event_handler> 
           
               
          warn "Event handler (OnSwap) not implemented"
               
          $event->Skip
           
           
          # end wxGlade 
           

           
           
           
          sub OnTrans 
               
          my ($self$event) = @_
           
          # wxGlade: MyFrame1::OnTrans <event_handler> 
           
               
          warn "Event handler (OnTrans) not implemented"
               
          $event->Skip
           
           
          # end wxGlade 
           

           
           
           
          sub OnCredit 
               
          my ($self$event) = @_
           
          # wxGlade: MyFrame1::OnCredit <event_handler> 
           
               
          warn "Event handler (OnCredit) not implemented"
               
          $event->Skip
           
           
          # end wxGlade 
           

           
           
           
          sub OnExit 
               
          my ($self$event) = @_
           
          # wxGlade: MyFrame1::OnExit <event_handler> 
           
               
          warn "Event handler (OnExit) not implemented"
               
          $event->Skip
           
           
          # end wxGlade 
           

           
           
           
          # end of class MyFrame1 
           
           
          1
           
           
          1
           
           
          package main
           
           
          unless(caller){ 
               
          local *Wx::App::OnInit sub{1}; 
               
          my $app Wx::App->new(); 
               
          Wx::InitAllImageHandlers(); 
           
               
          my $frame_2 MyFrame1->new(); 
           
               
          $app->SetTopWindow($frame_2); 
               
          $frame_2->Show(1); 
               
          $app->MainLoop(); 
           } 
          قد يسألني البعض الان كنت تدعي ان العملية ستكون سهلة و اننا بمعرفة الاساسيات يمكن ان ننشيء برنامج فما هذه الاكواد الطويلة و المعقدة ؟..
          و لكن في حقيقة الامر ان استخدامنا لبرامج تصميم الواجهات وفر لنا هذه المزايا :
          1- ازالة الحاجة الى كتابة الاكواد الطويلة للوصول الى شكل مبدئي للبرنامج ! خاصة مثلا لو كانت المكتبة سوينج مثلا .
          2- تسهيل عملية اعادة ترتيب مواضع الاشياء و رسمها.
          3- ازالة الحاجة الى حفظ خصائص العناصر المرئية و الاحداث المرتبطة بها . فأنا لست مضطر لان احفظ ما هي خصائص العنصر ( زر) و ما هي نوعية الاحداث التي يستجيب لها
          .4- سهولة تعلمها فهي لا تأخذ الا قليلا جدا من الوقت حتى يتم تعلمها بخلاف تعلم المكتبة نفسها. بالاضافة الى كون تعلم برنامج تصميم واحد يسهل عملية الانتقال الى برنامج تصميم اخر الى حد كبير جدا.


          5- و اخيرا الشيء المهم يزيل عنا الى حد كبير عناء تعلم المكتبة الرسومية خاصة فيما يتعلق برسم العناصر و طريقة العرض، مثلا هذا الكود الان ليس كل مبرمج بيرل يعرف كتابته بنفسه و لكن الان بسهولة يستطيع ان يعمل تطبيق لكل دالة فقط و ينتهي من البرنامج..


          اذا الى الان نحن في الحقيقة لم نبرمج بل نصمم كأي برنامج تصميم مثل Gimp او فوتوشوب او فرونت بيج ...الخ. و اغلب المكتبات الرسومية الان يتوافر لها عدة برامج تصميم تزيل هذا العبء عن المبرمج.


          يتبع ان شاء الله ..
          Static files
          alyassen.github.io

          تعليق


          • #6
            صحيح
            أعتقد أن "المخطط الأنسابي" أهم من البرنامج نفسة
            لأن المخطط يعطي الفكرة التي تبني برنامج أخر
            قريبا ... مدونة جافاسكربت

            تعليق


            • #7
              بسم الله الرحمن الرحيم

              كعادتك علي كتاباتك ممتازة

              معك بكل شيء ،

              لكني أخالفك بالرتائب ،التي ذكرتها /
              فقد تنشئ فكرة البرنامج أثناء تعلم لغة برمجة معينة ،
              وليس اختيار اللغة بعد الفكرة ،

              وأحب أن أضيف
              إن إنشاء برنامج معين والأفكار اللاحقة تحدث أثناء كتابة البرنامج والتخطيط المسبق قد يتعارض مع الواقع المبرمج حاليا ،

              وأضيف :

              لا بأس من الاستعانة ببرامج جاهزة (سورسات) للتعلم بداية الأمر ، وملفات مساعدة كالمكتبات أمر يختصر الكثير من الوقت على المبرمج

              وأضيف :
              الموضوع سهل يا إخوتي خريجي الحواسيب ،/ لكن الفرق بين المبرمج وغيره من عارفي البرمجة ،
              كالفرق بين الشاعر والانسان العادي ،
              فكلاهما يعرف الحروف والكلمات ويفهمها ويقولها ،

              لكن الشاعر ينظم هذه الكلمات في نسق جميل ،


              بصراحة الموضوع يحتاج الكثير من الوقت للدراسة (وهذا الوقت غير متاح لي الآن بسبب الامتحانات)

              متابع إن شاء الله (نظرة كل أسبوع )
              (لَا تَحْسَبَنَّ الَّذِينَ يَفْرَحُونَ بِمَا أَتَوا وَّيُحِبُّونَ أَن يُحْمَدُوا بِمَا لَمْ يَفْعَلُوا فَلَا تَحْسَبَنَّهُم بِمَفَازَةٍ مِّنَ الْعَذَابِ وَلَهُمْ عَذَابٌ أَلِيمٌ)
              آل عمران 188
              قال رسول الله صلى الله عليه و سلم :
              {لا يشكر الله من لا يشكر الناس}
              {من كان يؤمن بالله واليوم الآخر،فليقل خيراً أو ليصمت}

              جميع المساهمات الحاملة لهذا التوقيع تخضع لرخصة وقف
              أسأل الله العظيم رب العرش العظيم أن يحسن من حال أمتي

              تعليق


              • #8
                الجزء الرابع

                6- كتابة الكود الحقيقي ( تطبيق الدوال):


                مع هذه المرحلة يمكننا ان ان نقول بأن البرمجة الحقيقية بدأت فمثلا لو ان برنامجنا يقوم بعمليات حسابية معقدة فكل ما فعلناه الى الان مجرد تمهيد و البداية الفعلية هي في كتابة هذه المعادلات الرياضية في الدوال الموجودة في البرنامج .
                الان ، بما ان البرنامج ذو واجهة رسومية فهو يحتوي على دوال لا بأس بها افتراضيا و ذلك للتعامل مع كل حدث مهم في البرنامج . و بما ان البرمجة الحدثية لا تبدا من اتجاه معين و لا تتبع سير عمل ثابت ( مثلا يمكن ان نبدا برنامج رسومي ما باختيار فتح ملف جديد او يمكن ان نبدا باستحضار ملف تم انشاؤه سابقا و من ثم تتوالى الاحداث بشكل مختلف في كل مرة تشغيل تقريبا.) ، فأنا شخصيا افضل البدء في تطبيق الدوال التي :
                1- لا تحتاج الى وقت و جهد طويل لانشائها
                2- لا تؤثر او تتفاعل مباشرة مع الاحداث الاخرى في البرنامج (او على الاقل تتفاعل و تتأثر بشكل اقل من غيرها).
                و بالنظر الى برنامجنا يمكن ترتيب الدوال ( من الاقل الى الاكثر) هكذا :
                1- onExit
                2- onCredit
                3- onSwap
                4- onTrans


                النقطة التي احب ان اشير اليها هنا هو ان الاكواد التي سأكتبها في التطبيق ليست بهدف تعليم لغة البرمجة بيرل او مكتبة wx و انما هي وسيلة لتجسيد المباديء المجردة و الافكار فقط فعليه لا تهتم عزيزي القاريء بكيفية كتابة الامر المعين و لكن ركز على خطوات الوصول الى نتيجة معينة .


                التطبيق (كتابة الاكواد) :


                1- نبدا بدالة الخروج و هي دالة بسيطة مهمتها انهاء جميع عمليات البرنامج و الخروج بشكل سليم حسب طلب المستخدم :
                كود PHP:
                 sub OnExit {
                     
                my ($self$event) = @_;
                 
                # wxGlade: MyFrame1::OnExit <event_handler>
                 

                     
                $self->Close();
                 

                 
                # end wxGlade
                 

                2- onCredit و مهمتها هي توفير معلومات عن البرنامج مثل : تاريخ الاصدارة و رقمها و حقوق النشر مثلا ..الخ) و يمكن ان تكتب بطرق مختلفة كثيرة و في مثالنا سأقوم بانشاء مربع حوار (Dialog box) يقوم بمهمة اظهار هذه المعلومات بحيث عندما ينقر المستخدم على زر كردت يقفز له مربع حوار صغير فيه معلومات بدائية عن البرنامج ، و عندما ينتهي المستخدم من القراءة ينقر زر موافق ليرجع الى البرنامج الاساسي، هذا كل ما في الامر :
                كود PHP:

                 sub OnCredit 
                {
                     
                my ($self$event) = @_;
                 
                # wxGlade: MyFrame1::OnCredit <event_handler>
                 

                     
                my $credit Wx::MessageDialog->new(
                         
                $self,
                         
                "All Credit goes to : \n
                         Google : http://translate.google.com \n
                         CPAN : Lingua::Translate - Lingua::Translate::Google \n
                         wxPerl & wxGlade : perl_sourcer\@yahoo.com \n
                         Still under testing ;)
                         "
                ,
                         
                "Credits");  
                 

                     
                $credit->ShowModal;
                       
                 

                 
                # end wxGlade
                 

                3- OnSwap : و هذه الدالة مهمتها فقط ان تقوم بتغيير اماكن لغتي الترجمة مثلا لو كانت اللغة المترجم منها العربية و اللغة المستهدفة الانجليزية سيقوم اتوماتيكيا بتغيير اماكن اللغتين .
                اذا بكل بساطة ما نحتاجه هو:
                1- نحصل على قيمة اللغة الاولى و نسندها الى متغير .
                2- نحصل على قيمة اللغة الثانية و نسندها الى متغير2.
                3- نقوم باسبتدال القيم في المتغيرات .
                4- نحدث اللغتين في الواجهة الرسومية بالقيم الجديدة.
                كود PHP:
                 sub OnSwap {
                     
                my ($self$event) = @_;
                 
                # wxGlade: MyFrame1::OnSwap <event_handler>
                 

                      
                my $first $self->{origin}->GetValue();
                      
                my $second $self->{destination}->GetValue();
                     (
                $first$second) = ($second$first);
                     
                $self->{origin}->SetValue($first);
                     
                $self->{destination}->SetValue($second);  
                 

                 
                # end wxGlade
                 

                4- onTrans و هي الدالة التي تقوم بعمل الشيء المهم الا و هو الترجمة .
                خطوات العمل :
                1- في بداية الملف سنستورد المكتبة اللازمة للترجمة :
                كود PHP:
                use Lingua::Translate
                و ايضا في بداية الملف و ليس داخل هذه الدالة سننشيء كائن جديد من هذه المكتبة بهذا الشكل :
                كود PHP:
                 Lingua::Translate::config
                      
                (
                          
                back_end => 'Google',
                          
                referer  => 'http://dheeb.wordpress.com',
                          
                format   => 'text',
                          
                userip   => '192.168.1.1',
                      ); 
                2- نعود الى داخل الدالة .. بما ان جوجل لا تتعامل مع اللغات باسمائها بل باختصاراتها فعلينا اولا استبدال كل لغة باختصارها … مثلا arabic ستصبح ar.
                اذا اول سطرين :
                كود PHP:
                 my $tag_1 getTag($self->{origin}->GetValue());
                      
                my $tag_2 getTag($self->{destination}->GetValue()); 
                نلاحظ اننا استدعينا دالة اسمها getTag و هي دالة مساعدة كتبتها لتقوم بعملية الحصول على الاختصار سأضع الكود الخاص بها بعد الانتهاء من هذه الدالة .
                3- الان ننشيء الكائن بما ان لدينا كل المعلومات :
                كود PHP:
                 $object Lingua::Translate->newsrc => $tag_1dest => $tag_2 ); 
                4- الان انتهينا سنأخذ قيمة النص الموجود و من ثم ننفذ ميثود الترجمة و سنحدث خانة النص المترجم بالقيمة الجديدة :
                كود PHP:
                  my ($message$trans);
                 
                $message $self->{origin_text}->GetValue();
                      
                $trans =  $object->translate($message);  
                  
                $self->{translated_text}->SetValue($trans); 
                ** الدالة المساعدة getTag : كما قلنا هذه الدالة تقوم بمقارنة كل اسم مع اختصاره و ترجع قيمة الاختصار . اذا سنمرر لها قيمة اللغة الموجودة و عليها ان ترجع لنا الاختصار المناسب و يوجد العديد من الاساليب للوصول الى هذه النتيجة ، و هكذا كتبتها انا :
                كود PHP:
                 sub getTag {
                     
                my $value shift;
                     
                my %tags qwAutoDetect auto Arabic ar English en French fr Dutch nl German de   
                      Persian fa Turkish tr Japanese ja Italian it Slovak sk Serbian sr Thai th
                      Hindi hi Hebrew iw Spanish es Greek el Russian ru Swedish sv Croation hr
                      Polish pl Portuguese pt Filipino tl Irish ga Malay ms Belarusian be Czech cs
                      Norwegian no Swahili sw Catalan ca Bulgarian bg Korean ko Indonesian id
                      Chinese zh
                -CN    Vietnamese vi Yiddish yi Afrikaans af Ukrainian uk/;
                     return 
                my $tag  $tags{$value};
                     } 
                الان بحمد الله تم الانتهاء من البرنامج فهو يقوم بوظائفه الاساسية المطلوبة و لكن هل فعلا البرنامج جاهز للاستخدام ؟ بالطبع لا فنحن بعيدون كل البعد ان يكون البرنامج الان شبه متكامل! لماذا؟ اليس مهمته فقط ان يقوم بالترجمة و انتهينا ؟ اليس كل الازرار تعمل بالشكل المطلوب؟ …
                مع الاسف هذا البرنامج الى الان و هو برنامج ناقص بقوة لانه لم يخضع الى المرحلة الاكثر اهمية و التي ربما كانت الهدف الاساسي من هذا الموضوع :
                مرحلة الاختبار و التجريب و التعامل مع الاخطاء و الاستثناءات .
                اعطيكم مثال بسيط :
                هذا البرنامج مثلا يفترض ان الانترنت متوافرة للاتصال بجوجل و ارجاع القيمة دائما و هذا خطا جسيم جدا !. لا مكان للافتراضات و مع الاسف كثير منا يترك هذه المرحلة اما لانه غير مبالي او لانه لا يعرف او لانه لا يدرك اهميتها . ففي مثال الانترنت هذا، ما سيحدث هو ان البرنامج عندما نطلب منه الترجمة سيتصل بالانترنت لثواني معدودة فاذا كان هناك اتصال جرت الامور على احسن ما يرام و لكن لو كان المستخدم غير متصل بالشبكة فسينهار البرنامج و يختفي هكذا بدون سابق انذار بمجرد النقر على زر الترجمة . ربما البعض لا يهمه فهو يفترض ان المستخدم مدرك لوجوب وجود اتصال قبل تشغيل البرنامج و لكن مع الاسف هذه نقطة تحسب على المبرمج و تجعل برنامجه ناقصا و غير احترافي .. اذا دع عنك الافتراضات و تعامل مع الاخطاء …






                7- التعامل مع الاخطاء و الاستثناءات :


                قلنا ان من الاهمية بمكان ان يقوم البرنامج بالتعامل مع الاخطاء و الاستثناءات التي قد تحصل وقت تشغيل البرنامج ، و هذا الامر هو من الامور التي تمايز بين المبرمجين فكلما كان المبرمج مهتم بالتفاصيل و معالجها كان ذلك افضل لبرنامجه و لسمعته كمبرمج .

                الان اين نبحث عن الاخطاء و الاستثناءات التي يمكن ان تحصل؟
                في الغالب هناك حالتين يكثر جدا ظهور الاخطاء و الاستثناءات فيها :
                1- التعامل مع النظام
                2- التعامل مع المستخدم.
                الحالة الاولى مثالها عندما نحاول ان نفتح ملف : قد تنجح العملية او قد لا تنجح بسبب وجود قفل او صلاحية معينة على الملف لذلك يجب اخذ هذا الامر بالحسبان و التعامل معه .
                الحالة الثانية مثالها طلب قيمة من المستخدم : قد نكون نريد قيمة رقمية لعمل حسابات مثلا فيدخل المستخدم قيمة نصية ، عليه يجب ان نتأكد من القيمة المدخلة قبل الشروع في العمل عليها .
                في النهاية هناك انواع من الاخطاء لا يمكن التعامل معها مثل نفاذ الذاكرة من نظام التشغيل فلن يكون هناك مفسر لغة اصلا كي يتعامل مع هذا الخطأ...
                ايضا في بعض الاحيان لا يتوقع ان نحصي جميع الاخطاء التي قد تحصل خاصة في المشاريع الكبيرة و لكن مهمتنا ان نقللها الى حد معقول جدا و لا نترك عملية اكتشاف الاخطاء للمستخدم خاصة في برامج الويب التي قد تكون النتيجة غالية جدا حينها ان تم استخدام احد هذه الاخطاء كثغرة في البرنامج .
                و بما ان لكل لغة برمجة طريقة في التعامل مع الاستثناءات و الاخطاء ليس الهدف من التطبيق هنا هو كيفية كتابة الاكواد و انما البحث عنها و طريقة محاصرتها و مدى اهميتها ..


                التطبيق (البحث عن الاستثناءات):


                الان سآتي الى برنامجي و اخذ كل دالة على حدى و ابحث عن وجود الاخطاء و الاستثناءات التي يجب التعامل معها ..
                1- دالة الخروج لا تحتاج الى اضافة اكواد و دالة اظهار المعلومات ايضا ، لذلك سأكتفي بالتجريب المباشر و ملاحظة سلوك الدالتين عند النقر على الزر المعين . و يبدو ان الاثنتين تعملان بشكل جيد . و المهم ايضا انهما لا يطلبان اي قيم من المستخدم.
                2- جميل نأتي الى دالة onSwap : هكذا مبدئيا من مجرد الملاحظة نعرف انها قد تسبب مشكلة اساسية جدا تسبب انهيار البرنامج، المشكلة هي في حالة ان قيم مربع الاختيارات الاول لا يساوي قيم المربع الاختيارات الثاني فهناك قيمة موجودة زائدة في اختيارات لغة المصدر و هي AutoDetect هذه القيمة تخبر جوجل ان عليه هو البحث عن اللغة في المصدر و هذه ميزة جيدة فربما نحن لا نعرف اللغة التي نريد الترجمة منها . و لكن دالة سواب ستقوم بنقل اي قيمة الى الخانة الاخرى لان القيمة الموجودة في داخل المربع لا تعنيها فهي غير مهتمة بالترجمة و انما ما يهمها هو فقط تبديل اماكن القيمتين . و لان autodetect لا تنفع ان تكون قيمة للغة المترجمة ( فكيف يخمن جوجل ما هي اللغة التي نريد ان نترجم اليها؟) سيظهر خطأ في البرنامج .
                و لكي نتعامل مع هذا الخطا فقط نتأكد من القيمة انها ليست AutoDetect قبل القيام بعملية التحويل و اذا كانت القيمة فعلا autodetect فسنقوم باظهار رسالة تنبيه للمستخدم في خانة النص المترجم ننبه الى هذا الخطا و نرجو منه محاولة الترجمة مرة اخرى بعد تغير قيمة اوتو و ذلك بدلا من ان ينهار البرنامج بخطأ لا يعلم عنه المستخدم … اذا :
                كود PHP:
                      my $first $self->{origin}->GetValue();
                      
                my $second $self->{destination}->GetValue();
                      if(
                $first eq "AutoDetect"){
                      
                $self->{translated_text}->SetValue("Can't use AutoDetect on destination ! Please choose a language & try again ..");}
                      else {   
                     (
                $first$second) = ($second$first);
                     
                $self->{origin}->SetValue($first);
                     
                $self->{destination}->SetValue($second); } 
                3- دالة getTag ايضا قد تسبب مشاكل فهي تستقبل قيمة و ترجع قيمة مقابلة لها و لكن لو كانت القيمة المستقبلة لا يوجد لها مقابل ؟.. ماذا سنفعل الان !.
                يجب علينا اذا ان نحرص على ايجاد الية لضمان عدم ارسال اي قيمة غير القيم التي يوجد لها مقابل .. و ذلك قد فعلناه سابقا فعلا !. نعم فعلناه في مرحلة تصميم البرنامج حيث عندما قمنا بتصميم مربعي الاختيارات قمنا بتوفير قيم افتراضية للغات معينة هي فقط ما يوفره البرنامج للمستخدم و لكي لا يقوم المستخدم باضافة اي لغة غير موجودة او اي نص لا معنى له قمنا بقفل مربع الاختيارات حيث لا يمكن البتة ان يكتب المستخدم قيمة مربع الاختيار بنفسه و انما عليه ان يختار من الموجود فقط و فقط .. القيمة التي وفرت لنا هذه الميزة في الكود كانت :
                wxCB_READONLY


                يتبع ان شاء الله ...
                Static files
                alyassen.github.io

                تعليق


                • #9
                  الجزء الاخير

                  متابعة رحلة البحث عن الاخطاء !.


                  4- دالة OnTrans :
                  هذه الدالة هي اهم دوال البرنامج و هي اكثر الدوال عرضة للاخطاء، النقطة الاولى التي يجب الانتباه اليها اننا بالنقر على زر الترجمة نقوم باستدعاء الدالة و تنفيذ كل خطوات الترجمة حتى لو كان المستخدم لم يدخل نص للترجمة اصلا ( ترك الخانة فارغة) هذه العملية لا تسبب مشاكل و لا ترجع اخطاء لان محرك جوجل سيرجع قيمة فارغة ايضا و بذلك لن يلاحظ المستخدم اي شيء! و لكن لا معنى لهذا فلماذا نقوم بتنفيذ اوامر لا تعطينا نتيجة في نهاية المطاف؟
                  لذلك سنعدل على الدالة بحيث انها لا تقوم بالتنفيذ الا اذا كانت هناك قيمة للترجمة و ذلك ببساطة يتم بالتأكد من ان قيمة خانة النص المصدر صحيحة True.
                  اذا:
                  كود PHP:
                    if ($self->{origin_text}->GetValue())
                       {
                   
                  Rest of code here
                   
                  }
                   

                   else {
                  $event->Skip;} 
                  الان بكل بساطة سيتجاهل امر الترجمة اذا لم يتوافر نص للترجمة.


                  النقطة الثانية الاكثر خطورة التي تكلمنا عنها سابقا هي في حال عدم توافر اتصال بالانترنت سينهار البرنامج وقت النقر على زر الترجمة ..
                  قد يسأل البعض لماذا ينهار البرنامج كاملا؟
                  ينهار البرنامج لان دالة الترجمة تحاول انشاء كائن من نوع جوجل ترانسليتر و هذا يحتاج الى اتصال بالانترنت فعندما يفشل البرنامج في انشاء هذا الكائن سيرجع خطأ من النوع الذي يجب التعامل معه Fatal و ليس اختياري . طيب لماذا هذا الخطا يجب التعامل معه ؟ لانه بكل بساطة كل الاسطر البرمجية التي تعتمد على هذا الكائن ستفشل لانه لا يوجد كائن اساسا ..
                  مثلا هذا الامر :
                  كود PHP:
                   $trans =  $object->translate($message); 
                  نحن نريد تنفيذ ميثود translate الخاص بالكائن و لكن كائن object اساسا غير معرف عندنا لاننا لم ننشئه بنجاح في العملية السابقة ..
                  طيب كيف نتاكد من وجود اتصال بالانترنت ..؟ اقترح احد الاعضاء في منتدى بيرل ان نقوم بعملية اختبار للاتصال قبل محاولة انشاء الكائن ..
                  و لكن هذه العملية مكلفة لان المستخدم عندما ينقر على زر الترجمة ما سيحدث ان الدالة في بداية الامر ستختبر وجود الاتصال و هذا يستغرق بضع ثوان و من ثم تقوم بانشاء الكائن باتصال جديد و اخيرا تقوم بتنفيذ الميثود و ستزيد ثوان الانتظار هكذا ..
                  فكرتي كانت مغايرة :
                  البرنامج كله لا يحتاج اتصال لكن هذا الامر يحتاج اتصال :
                  كود PHP:
                  $object Lingua::Translate->newsrc => $tag_1dest => $tag_2 
                  اذا يمكنني ان اعرف هل يوجد اتصال او لا من خلال هذا الامر نفسه و لا داعي لاضافة المزيد من الاوامر للتأكد من وجود اتصال .
                  اذا كان الكائن انشيء بنجاح فالطبع هناك اتصال و ان كان الكائن فشل فهذا يعني انه لا يوجد اتصال او نوع اخر من الاخطاء .. و لكن كما قلنا سابقا ان الخطا هذا لا يصلح ان نضعه في جملة شرطية if (object )
                  لانه في هذه الحالة لو كان خطا false سينهار البرنامج و لن يتابع الجملة الشرطية ..
                  اذا الحل ان نعمل تقيم لهذا الامر و بناء على النتيجة ناخذ الاكشن المناسب و لكي لا تبدو الاسطر البرمجية القادمة غريبة فكروا بها على طريقة try في لغة جافا و لكننا هنا في بيرل نستخدم eval … اذا :
                  كود PHP:
                    eval {
                        
                  $object Lingua::Translate->newsrc => $tag_1dest => $tag_2 ) or die "Cannot Create an instance";
                        
                  $message $self->{origin_text}->GetValue();
                        
                  $trans =  $object->translate($message);
                        };
                        if ([email protected]){
                  $self->{translated_text}->SetValue("An Error occured : [email protected]  \n Perhaps your not online.");
                        }
                        else{
                        
                  $self->{translated_text}->SetValue($trans);
                        } 
                  شرح الكود :
                  في داخل eval نضع الاوامر التي قد ترجع اخطاء مميتة للبرنامج و هي امر انشاء الكائن و الامر الذي يوجد فيه method translate لانه معتمد على امر الكائن.
                  بعد الدالة نتاكد هل حصل خطا ؟
                  اذا كان هناك خطاء نرجع رسالة الخطا الى المستخدم . و لكن سيبقى البرنامج يعمل بشكل طبيعي ( هذه الحالة تشبه حالة المتصفحات مثل فايرفوكس فاذا لم يكن هناك اتصال بالانترنت سيذهب البرنامج الى حالة Offline و ينتظر من المستخدم محاولة اعادة الاتصال ).
                  اما اذا لم يوجد خطا فنتابع البرنامج كما المعتاد و نرجع النص المترجم .


                  8- مرحلة التحزيم :


                  هذه المرحلة النهائية في تطوير البرنامج حيث بعد الانتهاء من التخطيط و البرمجة و التصحيح و بعد التأكد من ان البرنامج وصل مرحلة نضج مناسبة يمكننا ان نقوم بتحزيمه و القيام بنشره .
                  طبعا اساليب التحزيم تختلف كثيرا جدا بحسب اللغة و نظام التشغيل و نوع البرنامج . و لكن الهدف من هذه المرحلة هي توفير الية سهلة للمستخدمين النهائين كي يجربوا البرنامج فلا يعقل مثلا ان اوزع برنامجي على اصدقائي بشكل كود C و اقول لهم عليكم ببناءه ( Compile ) من المصدر! فالمستخدم النهائي غالبا لا يعرف كيف يقوم بانشاء ملف تنفيذي من ملف المصدر، و الحقيقة ان هذه ليست مشكلة المستخدم النهائي بل حتى المستخدمين المتقدمين في الاغلب سيحتاجون بعض الوقت و البحث كي يستطيعوا تشغيل برامج مكتوبة بلغة لم يتعاملوا معها من قبل فاللغات كثيرة جدا. اسهل البرامج هي البرامج المترجمة Compiled و يمكن استخدام برامج لتسهيل عملية التنصيب للمستخدم كما نراه في الويندوز و لكن يعيبها ان الملف التنفيذي المبني لنظام معين سيحتاج الى اعادة بناء في حال الرغبة بتغشيله في نظام اخر .
                  هناك ايضا برامج الويب و لها طريقة تشغيل مختلفة و في هذه الحالة يجب ان يكون هناك توثيق جيد لطريقة التنصيب على السيرفر و يفضل انشاء سكربت يقوم بمهمة التنصيب بدلا من ان نترك هذه المهمة للمستخدم فهذا السكربت يجب ان يهتم بانشاء جداول قواعد البيانات و اسناد القيم المناسبة للاختيارات المناسبة حسب طلب المستخدم و اعطاء التصاريح المناسبة ...ألخ.


                  الخلاصة ايا يكن نوع البرنامج يجب ان نحاول قدر المستطاع ان نوفر الية سهلة لتشغيل البرنامج بدلا من ترك المستخدم في متاهة التشغيل و البحث عن المترجم او المفسر المناسب و بعدها البحث عن المكتبات التي يحتاجها البرنامج ..الخ فيترك البرنامج لانه لا يستاهل العناء .


                  التطبيق :


                  في حالتنا استخدمنا لغة مفسرة و هي بيرل ( امثلة اخرى هي بايثون و روبي ..ألخ) و التي تعطينا ميزة جيدة و هي الانتقالية بين انظمة التشغيل المختلفة و لكن يعيبها هو وجوب وجود المفسر على جهاز المستخدم . اذا سيكون هناك خيارين بالنسبة لبرنامج بيرل ( باستنثاء طبعا خيار توفير المصدر فقط) :
                  1- الاول ان نرفق المفسر (حجمه صغير نسبيا) مع برنامجنا فيقوم المستخدم بتنصيب المفسر ثم تشغيل البرنامج .
                  2- الثاني ان نستخدم PAR او PerlApp او Perl2exe و هذه كلها ادوات لانشاء ملف تنفيذي جاهز لبرامج بيرل . و بهذا لن يحتاج المستخدم الى تنصيب اي شيء فقط دبل كليك على البرنامج و سيتم التشغيل . ( ملاحظة هامة : هذه الادوات في حقيقة الامر لا تقوم بعملية compile كل ما في الامر انها تحلل البرنامج و تستورد الاجزاء المطلوبة فقط من مفسر بيرل و المكتبات اللازمة و تحزمها مع بعض)












                  ملاحظات بخصوص البرنامج :


                  1- في السنوات الاخيرة وجدنا توجه كبير الى نقل البرامج من سطح المكتب الى الويب و لكن ايضا هناك توجه الى نقل برامج الويب الى سطح المكتب فأغلب المدونين في تويتر مثلا لا يدخلون الى موقع تويتر و انما يقومون باستخدام برامج سطح مكتب للقيام بهذه المهمة و هناك الكثير من هكذا برامج او ما يسمى بالعميل .
                  في اغلب الاحيان الهدف منها هو اضافة ميزات جديدة الى الخدمة الام او الاستفادة من قدرات الجهاز بشكل افضل و لكن هناك ايضا سبب اخر و هو ان البعض يفضل استخدام برامج سطح المكتب بدلا من تكرار عمليات الدخول و الخروج الى المتصفح لذلك هناك رواج كبير لبرامج الرفع المباشر الى فلكر مثلا و غيرها من الخدمات.
                  2- في هذا الموضوع قمت بتمثيل بناء البرنامج على شكل برنامج سطح مكتب و لكن كان بالامكان ان نستهدف منصات اخرى مثلا ان نجعل البرنامج خاص للموبايلات كاندريود و ايفون ..ألخ بهذه الفكرة .
                  ايضا كان بالامكان ان نستهدف جعل البرنامج يعمل كاضافة لمتصفح كفايرفوكس او كــودجت Widget لسطح المكتب . بل حتى كان يمكن ان نضمن البرنامج في برنامج اكبر مثلا لو كان لدينا برنامج ويب صممناه ليعمل كمجلة او مدير مقالات كان بالامكان ان نضمن هذه الميزة في البرنامج .
                  فعلينا البحث عن المنصات التي سيلاقي فيها البرنامج شعبية اكثر.
                  3- طبعا كان بالامكان اضافة المزيد من الخيارات لهذا البرنامج مثل ترجمة موقع او ترجمة ملف ورد موجود في الجهاز ..ألخ و لكن هذا ليس هدف الموضوع.
                  4- تعمدت الغاء مرحلة كتابة الاختبارات Tests لانها طويلة و خاصة جدا بلغة بيرل و ستختلف كليا مع اي لغة اخرى فلن تقع في فائدة الاعضاء كثيرا خصوصا انني اريد من المقالة ان تكون عامة.


                  Our App In Action


                  اضغط على الصورة لعرض أكبر. 

الإسم:	final.jpg 
مشاهدات:	1 
الحجم:	136.6 كيلوبايت 
الهوية:	835622




                  ملاحظات عامة :


                  تكلمنا عن بعض المراحل المهمة في تطوير البرامج ، و لكن هناك الكثير من النقاط المهمة التي يجب الانتباه لها :


                  1- لا تعد اختراع العجلة !. من الاشياء المهمة التي يجب ان ننتبه لها و التي قمنا بتطبيقها في هذا الموضوع هو عدم تكرار الجهود ، فهذا البرنامج مثلا كان بالامكان ان اطور له قاعدة كلمات بنفسي و لكن هذا شيء مكلف جدا بالنسبة لشخص واحد و في النهاية سأترك الاضافة الى قاعدة الكلمات عندما ادرك ان هذا الامر فوق طاقتي . فهذه المهمة تحتاج الى متطوعين و مساهمين الامر الذي قد لا يتوفر لي .
                  و في الجهة المقابلة بدلا من استخدام المكتبة الجاهزة التي استخدمتها للاتصال بجوجل كان ايضا بامكاني ان اقوم بعملية الاتصال بنفسي و ذلك باستخدم LWP و لكن هذا سيحتاج الى مزيد جهد و عناء و في اغلب الاحيان لن تكون نتيجة اكوادي افضل من المبرمجين الذين قاموا بانشاء المكتبة التي استخدمناها لانها طورت من قبل مجموعة من الاشخاص المحترفين و تم اختبارها بشكل مكثف من اشخاص اخرين.
                  و لو على فرض كانت اكوادي افضل من اكواد هذه المكتبة فالعناء الذي سأتحصل عليه اكبر من الفائدة العائدة .


                  2- تقسيم البرنامج الى وحدات :
                  في هذا الموضوع مجموع الاسطر البرمجية كانت 224 سطر برمجي و لكن لاحظنا سهولة البحث عن الاخطاء و التعديل على اي شيء في البرنامج بسهولة تامة ( و سيظل الامر هكذا حتى لو ضاعفنا عدد هذه الاسطر مرات و مرات) و هذا راجع لكون البرنامج مقسم الى وحدات منطقية تسهل عملية البحث و التصحيح و تتبع الاخطاء بدلا من ان يكون البرنامج كله وحدة واحدة فتصعب عملية تتبع مصدر الاخطاء و معرفة ماذا يؤثر على ماذا !؟
                  و سنذكر بعض اهم الامور الاساسية التي تساعد على جعل البرنامج قابل للتطوير Scalable و التعديل Maintainable :


                  1- تقسيم البرنامج الى وحدات منطقية
                  2- تقليل اعتمادية كل وحدة على وحدات اخرى Dependecy.
                  3- عدم جعل المتغيرات مشاعة Global بل جعلها محصورة في اضيق مجال ممكن بحيث لا يمكن تغيرها من خارج مداها و لاحظنا هذا طوال البرمجة التي قمنا بها في هذا الموضوع و لم نستخدم متغير عام الا مرة واحدة و ذلك بهدف الاعلان المبكر.
                  4- استخدام تسميات واضحة للمتغيرات و الدوال و الكلاسات .
                  5- كتابة الملاحظات على الاجزاء التي فيها صعوبة او فكرة .


                  و سأكتفي بهذا القدر فالمقالة طالت كثيرا و اعتذر من هذا .. و لكن سأختم بملاحظات بسيطة و هي في طلب المساعدة في المنتديات العربية او الاجنبية :
                  1- تجنب الطلبات العامة مثلا : كيف ابرمج موقع ويب ؟ او كيف استخدم المكتبة الفلانية ؟ بل الافضل تحديد السؤال في امر او دالة معينة …
                  2- البحث قبل السؤال .
                  3- المحاولة قبل السؤال فالتفاعل مع السائل يزيد كثيرا عندما يرون انه بحث و سعى بنفسه ثم عرض مشكلته .
                  4- عرض الكود البرمجي و هذه كثيرا ما تتكرر فالكثير لا يقبل بعرض كامل الكود المصدري ، ربما هو خوف الاحراج او خوف ان يسرق الكود او شيء من هذا القبيل . و لكن عرض الكود البرمجي كاملا و ليس جزء منه يساعد كثيرا على حل المشكلة .
                  5- اجعل سؤالك طلبا و ليس امرا !.
                  6- و في النهاية السؤال في طلب العلم لا يوجد به احراج ..


                  تم الموضوع بحمد الله و فضله و ما ابريء نفسي ان النفس لامارة بالسوء الا ما رحم ربي...
                  Static files
                  alyassen.github.io

                  تعليق


                  • #10
                    جميل جدا علي

                    استفسار على السريع؛ مالفرق بين eval و try...catch ؟

                    بارك الله فيكم

                    تعليق


                    • #11
                      المشاركة الأصلية بواسطة أمين روخ مشاهدة المشاركة
                      جميل جدا علي

                      استفسار على السريع؛ مالفرق بين eval و try...catch ؟

                      بارك الله فيكم
                      اهلا استاذنا امين ..

                      eval في بيرل لها عدة استخدامات احداها هي اصطياد الاستثناءات و محاصرت الاخطاء بطريقة مشابهة جدا للـ try & catch الخاصة بجافا ..

                      و لها طرق كتابة مختلفة و لكن بشكل عام :
                      كود PHP:
                      eval {                           # try    
                       
                      ...run the code here... }; 
                      if( [email protected] ) {                       
                      # catch
                           
                      ...handle the error using [email protected] } 
                      و عادة ما تستخدم مع die و warn ...
                      اما بخصوص الفرق في الية العمل فاليك استاذي هذه المقطوعة من كتاب Advanced perl prog.:

                      Java goes through the same two phases as Perl: (1) compilation to an intermediate byte-code form, and (2) execution of this intermediate code. What it doesn't allow, however, is the production and evaluation of new code on the fly. There is really no reason why this isn't technically feasible, because the javac compiler itself is written in Java, and it should be possible to package it as a library instead of a standalone program without violating new security constraints.For error handling, Java has a try/catch syntax that is equivalent to the eval BLOCK approach in Perl, in that all the code is known at compile-time. Exceptions are true first-class objects in Java, so you can discriminate between them much better than the string comparison required in Perl. Java has the throw keyword to raise a user-defined exception, similar to Perl's die.
                      Java does strict type-checking and requires that a function enumerate the exceptions it might throw (this is considered part of the signature of the function). So if you call a function that throws an exception, Java either requires your function to either not rethrow it or, if you want to pass it on, you have to include that exception as part of your function's signature. This way, when you see a function, you know the exact list of exceptions you have to deal with, which is very important for big applications written by a team of people. Depending on your viewpoint, Perl doesn't have any such feature or restriction.
                      تجدر الاشارة الى انه يمكن القيام بعملية التعامل مع الاستثناءات في بيرل على طريقة جافا try & finally & catch باستخدام Error.pm.

                      و هذا مثاله :
                      كود PHP:
                      use Error qw(:try);

                      throw 
                      Error::Simple"A simple error");

                      sub xyz {
                              ...
                              
                      record Error::Simple("A simple error")
                                  and return;
                          }
                       
                      unlink($file) or throw Error::Simple("$file: $!",$!);

                          try {
                              
                      do_some_stuff();
                              die 
                      "error!" if $condition;
                              throw 
                      Error::Simple "Oops!" if $other_condition;
                          }
                          catch 
                      Error::IO with {
                              
                      my $E shift;
                              print 
                      STDERR "File "$E->{'-file'}, " had a problem\n";
                          }
                          
                      except {
                              
                      my $E shift;
                              
                      my $general_handler=sub {send_message $E->{-description}};
                              return {
                                  
                      UserException1 => $general_handler,
                                  
                      UserException2 => $general_handler
                              
                      };
                          }
                          
                      otherwise {
                              print 
                      STDERR "Well I don't know what to say\n";
                          }
                          finally {
                              
                      close_the_garage_door_already(); # Should be reliable
                          
                      }; # Don't forget the trailing ; or you might be surprised 
                      Static files
                      alyassen.github.io

                      تعليق

                      يعمل...
                      X