*****
****
***
**
*
الطريقة التقليدية، التي رأيتها تتكرر كثيراً، هي الآتي:
- المعيد يعطي الطلبة فرصة لكتابة البرنامج بأنفسهم.
- الوقت ينتهي، بعض الطلبة كتبوا البرنامج والبعض لا.
- المعيد يري الطلبة الحل الصحيح، ويشرح لماذا يقوم هذا البرنامج بعمله وأنه يرسم بالفعل المثلث.
اشعر ان هذا الاسلوب يوحي للطلبة ان البرمجة الهام مثل الإلهام الشعري: ان المبرمج هو شخص يجلس ويتأمل في المشكلة بعض الوقت، ثم فجأة يكتب الحل كاملاً مثلما يكتب الناس خطاباً. البرمجة مثل أي عملية فكرية لا تخلو من الإلهام والحلول الفجائية، لكن في كثيرها هي سلسلة من الخطوات تطبق بصورة علمية، وإن أردنا أن نحقق تقدما في تعليم البرمجة فلابد أن نبدأ في التفكير الجدي في ماهية هذه الخطوات وكيفية عرضها.
عملاً بمبدأ اظهر ولا تخبر تعالوا الآن نقدم طريقة مختلفة لشرح هذا المثال.
اولا سوف نصف المشكلة:
- نريد كتابة برنامج يكتب مثلث نجوم ارتفاعه 5 سطور.
- أدوات حل المشكلة لدينا هي (أ) امر cout الذي يعرض اشياء على الشاشة. (ب) امكانية الانتقال لسطر جديد بإضافة endl في امر cout وأخيراُ (ج)ادوات التحكم البرمجية التقليدية من loops، conditions، variables
الأمر إذاً مثل الفوازير على غرار "لديك حبل طوله كذا وصندوق وماعز وتريد ان تعبر من النافذة ذات ارتفاع كذا" الفرق الوحيد ان الأدوات المستخدمة هي افكار غير ملموسة وليس حبالاً (ولا ماعز من حسن الحظ).
الآن نفكر في الحل:
(من اجل التبسيط لن اكتب "طقوس" برامج السي من #include وما شابه)
من الواضح أنه مهما كان شكل الحل فإنه لابد أن يكتب سطوراً على الشاشة. ولابد أن يكون عدد هذه السطور خمسة:
main() {
for(int i=0; i<5; i++) {
draw_line();
}}
مهلاً! لا يوجد في السي++ أمر اسمه draw_line! انا تخيلت ان هذا الأمر موجود لسبب بسيط جداً هو أنني أريد ان احل المشكلة على أجزاء. سوف نفكر الآن فقط في عدد السطور المطلوبة ثم لاحقاً نفكر في شكل كل سطر.
العقل البشري يسهل على نفسه بأن يتجاهل بعض مكونات المشكلة ويركز في مكونات اخرى: هذا سلاح المفكرين في كل زمان ومكان وأحد أسباب التقدم العلمي الإنساني، وهذه العملية اسمها abstraction.
الآن نكتب الأمر المطلوب:
void draw_line() {
// ???????
}
علامات الاستفهام هذه محيرة: ما المطلوب ان نفعل هنا؟؟؟؟؟ الطبيعي اننا سنرسم عدداً معينا من النجوم، ولا ننسى الانتقال لسطر جديد لأن الاستدعاء القادم للدالة لابد أن يرسم من اول السطر التالي.
ما هو عدد النجوم المطلوب؟ اوه ألا تعرف؟ إنه n بالطبع!
void draw_line() {
for(int j=0; j<n; j++) {
cout << "*";
}
cout << endl;
}
هل تذكر الabstraction؟ لقد افترضت في الجزء السابق ان البرنامج "يعرف" كيف يرسم السطر. الآن أنا افترض انه "يعرف" كم نجمة ترسم في كل سطر. الآن نفكر: من أين سنأتي بهذه القيمة؟ نعود مرة اخرى ونتأمل الشكل:
*****
****
***
**
*
الذي نلاحظه أن العدد المطلوب يبدأ بخمسة ويتناقص مع كل سطر. التحول من سطر إلى سطر يحدث في الدالة main ، إذن هذا هو مكان المتغير المطلوب:
main() {
int n = 5;
for(int i=0; i<5;i++) {
draw_line();
n--;
}
}
الكود تبدو طبيعية جدا: طول السطر يبدأ بخمسة، ثم نرسم السطر، ثم ننقص الطول بمقدار واحد، وهكذا. لكن الدالة draw_line هي التي تحتاج لطول السطر، وليس main!
لا بأس، من أجل هذا هناك إمكانية تمرير الparameters. أولا نعدل main:
main() {
int n = 5;
for(int i=0; i<5;i++) {
draw_line(n);
n--;
}
}
وثانيا نعدل draw_line:
void draw_line(int n) {
for(int j=0; j< n; j++) {
cout << "*";
}
cout << endl;
}
وانتهى البرنامج! ماذا لو لم يكن الطالب قد اخذ الfunctions من قبل؟ مشكلة قابلة للحل: يمكن تقديم الfunctions قليلاً أو استخدام comments هكذا:main() {
for(int i=0; i<5;i++) {
// draw line
}}
ثم التساؤل "ماذا نكتب مكان التعليق" بدلاً من "كيف نكتب الدالة المطلوبة".
- لم تعد الخطوات بين المشكلة والبرنامج شيئاً غامضاً، وكسرنا قشرة البرنامج ونظرنا داخلها.
- الآن يمكن للطالب أن يقلد نفس الطريقة حين يأتي عليه الدور ليكتب برنامجاً بنفسه (في السكشن او خارجه).
- البرنامج الناتج منظم جداً ويتبع منهج structured programming، ليس لأننا فرضنا هذا على الطالب فرضاً ولكن لأن هذه كانت اسهل طريقة للتفكير في المشكلة.
- لم نكتب البرنامج مرة واحدة لكن جزءاً جزءاً وهذه هي طريقة العمل في البرامج الحقيقية: البدء بكود تبدو صغيرة (لدرجة التفاهة احياناً) ثم تزويدها وتنقيحها تدريجيا لتصل للبرنامج المطلوب.
- تعلم الطالب التفكير بطريقة top down والانتقال من مستوى اعلى من الabstraction لمستوى اقل.
ارجو أن يفيد هذا المثال من هو في موقف تعليمي.
هناك 3 تعليقات:
حلوه دى (Y)
بس انا اُفضل نسيبلهم حبه وقت يطحنوا فى دماغهم شويه و يجربوا و يغلطوا و يوصلوا
و عاجبنى العنوان قوى! :D
و بعد كده نقولهم على الحل بالطريقه دى قصدى
@Abdalla Hassan
لم اكن انوي اقتراح تقديم الطريقة كما هي بالضرورة، بل هي مقدمة ليضيف إليها الآخرون تنويعات ويطوروا فيها، والتغيير الذي تقترحه جذاب طبعا ويستحق التفكير :)
والعنوان يعجبني أنا أيضاً :)
إرسال تعليق