في هذا المقال أريد أن أتحدث عن بداية دراستي لعلم الحاسوب والبرمجة بشكل أكاديمي، وقبل دخولي للجامعة.
كنت قد بدأت البرمجة قبلها بمدة طويلة. عملت على الكثير من المشاريع. برمجة تطبيقات الأندرويد. تطوير الألعاب. برمجة المواقع. تحليل البيانات. الذكاء الاصطناعي. الخ
كلٌ منها احتاج لمهارات مختلفة. ولغات برمجة مختلفة. وكل منها عملت عليه كهواية. ربما تطوير الألعاب كان أكثر مجالٍ غصت فيه بعمق. وهو أوسعهم وأكثرهم تعقيدًا.
لذا تعلمت استخدام تقنيات وبرامج متنوعة، تعرفت على طرق واسعة للبرمجة، حللت مشاكل عديدة، صممت نظم برمجية، وربما ابتكرت خوارزميات (كانت سيئة غالبا ولكن أدت المهمة)
ومع كل هذا أحسست بنقص شديد في مهاراتي وفهمي.
كلما قرأت عن حل لمشكلة مستعصية مثلاً، استطعت تطبيقه ولكن دون فهمه بشكل تام.
وهو أمر بديهي في الحقيقة لأنني لم أدرس سوى أساسيات البرمجة.
ولكن المشاريع التي عملت عليها ليست بسيطة، تصعب حتى على خريجي الجامعات. ولست أبالغ ولكن هذا ما شهد به زملائي ممن رأوا أعمالي أو شاركوني في العمل.
إذًا لماذا أحتاج لدارسة علم الحاسوب، إذا كان بإمكاني تصميم وبناء كل هذه البرامج من دون ذلك؟
المحتوى
دراسة علم الحاسوب
.إن مشكلة عدم دراسة علم الحاسوب أكاديميًّا هو تكوّن فراغات معرفية وعدم وجود روابط بين المعلومات
ولم أقع على حقيقة ذلك إلا مؤخرًا عندما توسعت في مجال علم الحاسوب. حسنًا، جزء منها فقط فما زلت أتعلم.
الفراغ في المعرفة منتشر بكثرة بين المبرمجين المتعلمين ذاتيًا.
فمثلا عندما بدأت في تطوير التطبيقات على android studio
كنت أصمم التطبيق في واجهة، وأكتب أكواد xml، وفي الناحية الأخرى أكتب البرنامج بلغة جافا..
ولم يكن لدي أدنى فكرة عن كيفية عمل وترابط هذه الأدوات.
كيف يتعرف ملف الجافا على العناصر في الواجهة؟ كيف يتحول في النهاية إلى تطبيق؟
أي جزء يترجم لغة جافا أساسًا؟ ولماذا نستعمل الxml لتصميم الواجهات؟
بالطبع لست بحاجة لمعرفة ذلك لصناعة تطبيق. ولكن إذا أردتُ أن أصبح ملمًا بآليات عمل الحاسب، وأردت أن أبدع وأخترع وأصنع أدوات أخرى يستعملها غيري..
فكيف لي أن لا أفهم آلية عمل هذه الأمور؟
هل أقصى آمالي أن أستعمل الأدوات من التقنيات ولغات البرمجة، التي يصنعها غيري، ويكون إنتاجي مرهونًا بقدراتها؟
أم سأكون ممن يساهم ببناء هذه الأدوات؟
غير الفوائد العديدة التي يكتسبها المبرمج من التعمق ولو قليلًا في فهم الأدوات التي يستعملها.
ومن التساؤلات الأخرى التي كانت تخطر ببالي كل حين وآخر:
كيف يعمل الحاسب؟ كيف تترجم لغات البرمجة إلى assembly ؟ ثم إلى machine code?
ما الفرق بين أنواع لغات البرمجة المختلفة؟ وما هو أفضلها لمهمة معينة؟
ماهي ال functional programming مثلًا؟ ولماذا نستعمل ال Object Oriented Programming بدلًا منها؟ وهل يمكن الاستفادة من الاثنين معًا؟
كيف يتعامل الحاسب مع الأرقام؟ ماهي ال floating point numbers وكيف تؤثر دقتها على أداء برنامجك؟
ما هي الخوارزميات وكيف نكتب واحدة جيدة؟ أو كيف نختار بين الخوارزميات وهياكل البيانات المعروفة؟
كيف أبدأ بتخطيط مشروعي، وتصميمه، بحيث يصبح العمل عليه سهلًا ومريحًا، وإضافة المميزات أمرًا سلسًا، وتعديله وتصحيح الأخطاء عملاً يسيرًا؟
بالطبع تختلف أهمية المواضيع باختلاف المجال الذي نعمل به، ولكن يصدف أن مجال برمجة الألعاب لا يخلو من معظمها والعمل فيه يجبرك على الاطلاع عليها.
كمثال بسيط، لم أكن أعلم كيف يتعامل الحاسب مع البتات 0,1. فعندما احتجت للتعامل معها بشكل مباشر، وهو ما يحدث كثيرًا في برمجة الألعاب، وجدت نفسي عاجزًا عن فهمها
في محرك Unity نستعمل ما يسمى بـ layerMask لترتيب ال layers في المشروع. وهي عبارة عن نص من 0 و 1.
وكثيرًا ما احتجت لتعديلها بشكل مباشر أو الكشف عنها. وفي كل مرة، أذهب إلى ذات الصفحة على unity answers، لأحصل على الكود المطلوب، وأحل مشكلتي، مع أن الكود ذاته قد يكون موجودًا في المشروع ذاته في مكان آخر!
ولكنني لم أفهمه ولم أحفظه يومًا حتى عندما قرأت شرحه.
ماذا نستفيد من دراسة علم الحاسوب بشكل أكاديمي؟
إن دراسة علم الحاسوب تبني عند الطالب الأساسيات وتجعله يفهم آلية عمل الحاسب، والبرمجة، وتبني مفاهيم المنطق والرياضيات والخوارزميات..
وتعطيه اطلاعًا واسعًا على أفكار مختلفة، وحلول مبدعة لأشخاص واجهوا مشاكل سابقة، واضطروا لحلها في ظروف استثنائية، أو ضمن قواعد ضيقة..
فيصبح على دراية بطريقة التفكير وحل المشاكل التي يستخدمها المبرمجون، وعلماء الحاسوب والمطورون في اختراع الخوارزميات، تصميم البرامج والنظم، وتوظيف البرمجة في شتى المجالات.
وتسمح له بتعلم المواضيع الجديدة بسرعة ويسر، لأن لديه قواعد متينة يرجع إليها عند الحاجة.
بالنسبة لطالب علم الحاسوب المتمكن، فإن تعلم لغة برمجة جديدة، أو الدخول في مجال جديد (الغرافيكس، الذكاء، الألعاب).. مجرد رحلية مسلية لا أكثر.
تَمكُنه من الأساسيات يمكنه منه تحقيق أكبر استفادة من لغات البرمجة والتقنيات، والتطوير عليها وربما إختراع لغات برمجة جديدة..
والتعمق في أي من المجالات الشتى وتحقيق تقدم وحل مسائل معضلة فيها.
التوفيق بين تعلم المواضيع النظرية والتطبيقية
بالنسبة لي كما ذكرت، قضيت معظم أوقاتي في البرمجة في الجانب التطبيقي والعملي، وكان تعلمي للبرمجة أداة لتحقيق غاية.
ثم كلما تعمقت فيها أكثر وأكثر، أدركت حجم العالم الذي دخلت فيه، وأصبحت البرمجة غاية لا أداة.
لذا تعطشي لدراسة الجانب النظري أتى بعد فترة طويل من عدم الاكتراث به.
وحينها بدأت بدراسة كتاب SICP الذي سأتحدث عنه قريبًا
ولكن هناك أناس على الجانب الآخر، درسوا علوم الحاسب وتوسعوا فيها، ثم بعد الضجر أصبحوا يميلون إلى التطبيق وبناء الأشياء بدلاً من التفكير في الأدوات.
وهناك من يوازنون بين الاثنين وهو الأفضل ربما.
وبما أن كل شخص له ظروفه وأهدافه، لا ينطبق ما أكتبه في هذا الموضوع على الجميع، ولكن غالبًا ما ينطبق على من تعلم البرمجة بشكل ذاتي وأمضى فيها شهورًا وسنين كحالي.
وفي النهاية وقتنا محدود. وعلينا اغتنامه في تعلم ما نراه نافعًا فقط، وليس كل شيء. وأظن أن هذه النصيحة موجهة لي أولًا.
متى وأين قررت البدء في الدراسة بشكل جدي؟
كان ذلك عندما وقعت على موقع teachyourselfcs.com. حيث يقدم خطة لدراسة علم الحاسوب من مصادر متوفرة على الانترنت ككتب ودورات.
وهناك نسخة مترجمة للعربية منه هنا.
بعد مقدمات عن أهمية دراسة علم الحاسوب، وتبيان الفرق بين من يدرسه وبين من يتعلم البرمجة بشكل سطحي، نجد قائمة بالمواضيع التي علينا تعلمها وهي:
- Programming – البرمجة
- Computer Architecture – معمارية الحاسب (أنظمته)
- Algorithms & Data Structures – الخوارزميات وهياكل البيانات
- Math for CS – الرياضيات لعلم الحاسب
- Operating Systems – أنظمة التشغيل
- Computer Networking – شبكات الكمبيوتر
- Databases – قواعد البيانات
- Compilers – مترجمي اللغات
- Distributed Systems – الأنظمة الموزعة
بالنسبة البرمجة، أول كتاب ينصح به الكاتب هو SICP أو Structure and Interpretation of Computer Programs.
وهو في الحقيقة ليس كتابًا عن البرمجة وإنما عن علم الحاسوب ككل.
ومع أن علم الحاسوب يعتبر جديدًا (نوعا ما) ومازال يتطور، تعتبر هذه الأمور حقًا الأساس لكل شيء فيه.
أي أن تعلم هذه المواضيع يعتبر استثمارًا مربحًا سيعود بالنفع بشكل كبير على من يتعلم البرمجة، ويبني قاعدة قوية للتعلم المتقدم.
نعم، المصادر المذكورة في الصفحة كافية لتعلم علم الحاسوب كله كما يدرسه طلاب الجامعات، بل أفضل من ما يدرسه الطلاب بكثير من ناحية المحتوى.
فالقائمة جمعت أفضل الأفضل من ناحية الكتب والدورات.
كل ما ينقص وجود زملاء تدرس معهم، وأساتذة تسألهم، وجو يشجع على التعلم.
لذلك بالطبع التعلم الذاتي ليس مناسبًا للجميع وفي كل الحالات.
لكن بالنسبة لطلاب علم الحاسوب في الجامعات فإن بإمكانهم الاستفادة منها كشيء إضافي، يزوّدون باستعمالها أي نقص في منهج جامعاتهم.
دراستي لكتاب SICP
بعد ذلك قررت البدء في الدراسة، وبعد مدة كنت أقرأ في كتاب SICP وأنبهر بكل فكرة جديدة يطرحها وكل تمرين جديد أعمل عليه.
الكتاب يستعمل لغة Scheme. وهي أحد أسرار نجاحه. كانت أول تجربة لي في لغة functional. وأثناء دراستي، لم أدرك أنني أستعمل لغة برمجة وظيفية حتى انتهيت من القسم الثاني.
وهذه اللغة هي “لهجة” عن لغة Lisp الشهيرة (سابقًا).
ما يميزها هو بساطة تركيبها أو الsyntax. فتقريبًا ليس هناك أي قواعد لدراستها! كل ما يقوم به الكتاب هو تقديم اللغة، ثم البدء في الغث والسمين..
دون تضييع نصف الفصل في شرح قواعد كتابة الأكواد في اللغة كما تفعل الدورات والكتب المعتمدة الc++ والجافا وغيرها. أي أن الكتاب يتجه مباشرة للمواضيع المهمة.
وقد تغيرت وجهة نظري عن البرمجة بشكل كبير بعد الدراسة في الكتاب. ويرجع ذلك إلى عدة أمور لا أستطيع تلخيصها.
منها توظيفه لفكرة الـabstraction كل الأوقات. وهي وضع حدود أو مستويات وهمية بين الأجزاء في البرنامج، والتفكير في المستوى الحالي أثناء كتابة الأكواد.
وفكرة first-class procedures. التي تسمح لنا ببناء higher-order procedures بتركيب الدوال وبرمجة أنظمة صعبة ومعقدة بطريقة سهلة.
بمعنى آخر، يحاول الكتاب بناء كل شيء من الصفر، دون الاعتماد إلا على primitives بسيطة. وذلك يزيد من عمق فهم الطالب للبرمجة.
ويتطرق الكتاب لمواضيع لا تكاد تذكر في المحتوى التعليمي هذه الأيام مثل الstreams و lazy evaluation.
وفي القسم الرابع، نقوم ببرمجة evaluator للغة scheme بلغة scheme ذاتها. أي أننا نكتب برنامج ينفذ أوامر اللغة باستخدام نفس اللغة.
أيضًا في القسم الخامس والأخير، يشرح الكتاب برمجة محاكي للـregister machines. أي أننا نحاكي عمل الحاسب، وحتى ما يسمى بـ primitives.
ويشرح أيضًا الترجمة compilation في آخر جزء ثم يقوم الطلاب بتطبيق مترجم يستعمل محاكي الحاسب.
أنصحكم بقراءة المقدمة في الكتاب للحصول على فكرة أوضح أو زيارة أحد الصفحات التي سأذكرها أدناه.
فقرة من المقدمة
أرى أن هذه الفقرة من المقدمة توضح وجهة نظر الكاتب وتوجهه:
Our design of this introductory computer-science subject reflects two major concerns. First, we want to establish the idea that a computer language is not just a way of getting a computer to perform operations but rather that it is a novel formal medium for expressing ideas about methodology. Thus, programs must be written for people to read, and only incidentally for machines to execute. Second, we believe that the essential material to be addressed by a subject at this level is not the syntax of particular programming-language constructs, nor clever algorithms for computing particular functions efficiently, nor even the mathematical analysis of algorithms and the foundations of computing, but rather the techniques used to control the intellectual complexity of large software systems.
Preface
Mathematics provides a framework for dealing precisely with notions of “what is.” Computation provides a framework for dealing precisely with notions of “how to.”
Preface
فالمقصد إذًا أن لغات البرمجة هي طريقة للتواصل وتناقل الأفكار بين المبرمجين. كما أن الرياضيات هي لغة لتناقل الأفكار بين أصحابها.
والاختلاف يكمن أن الرياضيات ترتكز على المعرفة الوصفية – أي مثلا ما هو المشتق؟ – أما الحوسبة مختصة بالمعرفة الضمنية – أي كيف نحصل على المشتق؟
وليس الهدف من تعلم علم الحاسوب فهم طريقة عمل البرمجة فحسب. مع أن هذا جزء مهم وأساسي، فليس الهدف أن تفكر كما يفكر الحاسب فقط.
ولكن أيضًا استعمال لغات الحاسوب للتعامل مع البرامج الكبيرة والمعقدة – بطرق تناسب كلًا من الحاسب والمبرمج الذي يقرأ أكوادك.
مصادر وبدائل
وأعتقد أن أهم شيء في كل هذه القائمة هو قسم البرمجة. لن أقول كتاب SICP فهناك من لا ينسجم معه، والموقع يقترح كتب أخرى بديلة.
لكن على كل من يرغب في التعمق في البرمجة وفهمها على حقيقتها، أن يجرب الكتاب. إذا لم يكن النسخة الأصلية، فنسخة JavaScript
بالنسبة للمقارنة بين النسخة الأصلية ونسخة جافاسكربت، وجدت هذه الصفحة.
أو كتاب Composing Programs كما يذكر الموقع.
كان SICP يدرس في جامعة MIT لطلاب Computer Science & Electrical Engineering في سنتهم الأولى.
وقد أُصدر عام 1984، ثم النسخة الثانية عام 1995.
هناك الكثير ممن حاولوا دراسته وواجهوا صعوبة فيه، ثم كونوا مجموعات ليعينوا بعضهم في الدراسة.
تجدون أحد هذه المجموعات في هذه الصفحة. صاحبها Andrew.
في هذه الصفحة قام بتقسيم المواضيع إلى أسابيع، بناءً على دورة جامعة UC Berkeley التي ينصح بها الموقع teachyourselfcs.
هناك في الصفحة روابط للفيديوهات، للكتاب، لمجموعة discord، ولملفات وأكواد مهمة.
والصعوبة في الكتاب، غير المحتوى، أنه قديم، ولا تعمل كل الأمثلة والأكواد بدون أدوات خاصة. ولكن في هذه الصفحة ستجدون كل ما تحتاجونه لدراسة كل الكتاب.
هل عليّ دراسة كل الكتاب؟
قبل قليل قد بالغت عندما تحدثت عن انبهاري في المحتوى والتمارين. فالقسم الأول كان عاديًّا نوعًا ما، حتى بدأنا في ال recursion.
وبحكم أنني لم أفهم ال recursion وقتها ولم أكن أستعمله، منذ ذلك القسم وأنا أتعلم أمور جديدة.
لذا الأمر يعتمد على معلوماتكم السابقة. يجب الاطلاع على قائمة المحتوى. ولكن لا مانع من قراءة أول قسم في الكتاب كله ولو بسرعة.
بالنسبة للتمارين، هناك نسبة منها تعتمد على مفاهيم رياضيات وإثباتات، وبما أن الكتاب كان موجه لطلاب MIT، فذلك أمر متوقع.
والنصيحة هنا اختصار هذه التمارين في حال عدم الاهتمام بالمفاهيم الرياضية. للحصول على تمارين بديلة، هناك الكثير في الصفحة المذكورة أعلاه.
وأيضًا، الدورة في جامعة UC Berkeley تختصر بعض المواضيع في chapter 5.
وصاحب الموقع يقترح أن الأقسام الثلاثة الأولى هي الأهم.
ومن الأجزاء التي تختصر عادة هو البرمجة المنطقية في القسم الرابع. Logic Programming.
لذا الأفضل اختيار ما يناسب رحلتكم التعليمية مع هذا الكتاب.
ماذا صنعت أثناء الدراسة؟
إن الكتاب يعتمد على التطبيق العملي لفهم المواضيع. وأهميته تكمن في التمارين والمسائل كما ذكرنا، حتى إن بعض التمارين فيه تعتبر مشاريع كاملة.
من المواضيع التي أعجبتني كانت الـHuffman encoding. وقمت بتجربتها على نصوص باللغة العربية لأحصل على حفظ للمساحة بنسبة 40%.
تجدونها في الملف 2.3.4 Huffman Encoding.rkt
ومن البرامج الأخرى كان الـPicture language. وهو من أفضل الأمثلة في الكتاب على الـhigher-order procedures.
وبرنامج الحساب في القسم 2.5 كان من أفضل الأمثلة على الـabstraction ,وعملية تصميم نظام كبير ومرن.
يستطيع البرنامج التعامل مع الأعداد الصحيحة، والكسرية، والحقيقية، والتخيلية (المركبة) وكثيرات الحدود.
أي يمكن القيام بالعمليات الحسابية بين أي من هذه الأنواع مع بعضها دون مشاكل كما هو مبين في الصورة:
وبشكل خاص، أعجبتني البرمجة الوظيفية وصنعت بعض البرامج البسيطة لتساعدني في بعض المهام. منها برنامج يقوم بتحويل الأعداد من أي أساس إلى أي أساس آخر مع شرح الخطوات:
وقد تحدثت عنه هنا على جت هب. YaserAlOsh/SICP-study:
(الـnumber bases هو أحد المواضيع التي نتعلمها في علم الحاسوب بالمناسبة)
وتجدون جميع المسائل والتمارين التي حللتها في هذه الصفحة أيضًا.
برامج أو أدوات مطلوبة
في الصفحة التي ذكرتها أعلاه، تجدون تعليمات تنفيذ أوامر اللغة scheme المستخدمة في الكتاب باستعمال DrRacket.
بالنسبة لي، استعملت drRacket. ووجدته جيدًا، لكن هناك طرق أخرى يمكنكم الاطلاع عليها.
هذه الصفحة، بالإضافة لتلخيص أهمية الكتاب بشكل مبدع، تطرح عدة طرق لتنفيذ أوامر اللغة مع مقارنة وتخوض في التفاصيل.
مدة دراسة الكتاب
لن أذكر المدة التي قضيتها على هذا الكتاب فالأمر محرج بعض الشيء. حتى أنني لم أنهيه كله بعد، ولكن دراستي تقطعت لعدة أسباب فهي لم تكن مستمرة.
وأيضًا كثيرًا ما كنت أنغرس في مسائل وتمارين فوق مستواي وأقضي أيامًا حتى أحلها. وليس عليكم بالطبع فعل ذلك فأنا لدي فضول زائد أحيانا.
لكن قد ذكر بعض الطلاب على مجموعات discord أن دراسته وحل معظم التمارين، بدون تضييع للوقت، يمكن خلال سنة واحدة.
ويختلف الأمر بين شخص وشخص.
بهذا أظن أنني أعطيت الكتاب حقه. حقًا أرى أن أي مبرمج يمكنه الاستفادة منه ولو قليلاً.
عتبي الوحيد عليه هو النظرة الفلسفية التي ينظر بها المؤلفان، والتي لاحظتها بشكل خاص في القسم الثالث. ولا أقول أنها خاطئة ولكن ربما معقدة، أو في غير موضعها؟
وأتمنى ممن درسه سابقًا أو ينوي ذلك أن يشاركني في التعليقات، ما آرائكم عنه أو ما تطلعاتكم لدراسته؟