مع بداية عام جديد تجري العادة على وضع أهداف شخصية للسنة الجديدة، إن كان أحد أهدافك للسنة الجديدة هو الإرتقاء بمستواك البرمجي والوصول الى فهم أعمق بغية الوصول الى مرحلة أعلى من التمكن من أساسات بناء البرمجيات فهذه المقالة كُتبت لأجلك!
غالبًا إن كنت تعمل في سوقنا المحلي، فأنت بالأغلب تقوم ببناء خدمات على الإنترنت (Web services, APIs) لذا على الأرجح انت تتعامل يوميًا غالبًا مع Framework و ORM وبعيد بشكل كبير عن نظام التشغيل وهذا شيء مريح ولله الحمد..
ولكن في دورة حياة المبرمج هنا أنت تتعامل مع عدة أشياء بشكل شبه يومي، وهي:
Systems Programming Environment
Network
Databases
فهمهم سيعطيك قدرة أكبر على التحول الى مبرمج ذو أساسات متينة. لأنها معرفة لا ترتبط بلغة معينة بحد ذاتها ولكنها على مدى أعمق من ذلك، يمكنك أخذها معك والاعتماد عليها مهما كانت لغة البرمجة او الـ Tech Stack الذي تتعامل معه. أُطر العمل تأتي وتذهب، ولكن الأساسات باقية.
لو قمت ببناء نفس التطبيق بلغات مختلفة ستجد ان النتيجة النهائية واحدة وإن إختلفت الطرق، لذا اذا اخذت التقاطعات بين هذه الاكواد بمختلف اللغات ستجد أنها جميعًا طريقة للتعامل مع هذه أشياء التي ذكرناها. قد يكون هنالك أشياء أكثر ولكن ما لايدرك كله لايترك جلّه.
وهذا يعني تعلمّك لكيف تعمل هذه التقنيات سيكون له عائد كبير جدًا لك على الصعيد الشخصي، لانك ستكون قادر بشكل أكبر لمعرفة وحل المشاكل التي ستواجهك أو تواجه زملائك أثناء العمل. الهدف الأساسي هنا أن يكون لديك نموذج ذهني - Mental Model - في عقلك قادر على توقع عمل هذه التقنيات وبناءً عليه تحليل طريقة عملها.
لماذا عملية بناء النموذج الذهني مهمة؟ لأنك ستكون حينها قادر على تحليل المشكلة والقيام بعملية Elimination Process لكل ماهو غير متعلق بالمشكلة. هذا برأيي ورأي العديدين هو الفرق الكبير من المبرمج الخبير والمبتدئ.
فالمقدرة على تحليل طريقة عمل النظام واماكن وقوع الخلل ذهنيًا دون الحاجة للكثير من Trial and error - بالعامية مايطقها ويلحقها! - هي سمة المبرمج العظيم، برأيي الشخصي.
بسم الله نبدأ:
Systems Programming Fundamentals
طيب ايش يعني Systems Programming؟ وليش تتعلمها؟
هي البرمجة بشكل مباشر على الـ Kernel مثلًا Linux.. الكيرنل هو النظام اللي يتعامل مع الهاردوير، يتحكم بالهاردسكات، الشبكة، الرام، المعالج وغيره. وبرمجة الأنظمة تعني التعامل مع هالكيرنل.
طيب، كيف أتعامل مع الكيرنل؟ حلو، التعامل معه يصير عن طريق استخدام API معينة طالعه منه تعرف بإسم Systems Calls وهي تقدّم لك على شكل مكتبة تحتوي مجموعة Functions مكتوبة بلغة C.
لايستطيع أي تطبيق أن يقدّم لك كمستخدم شيء لا يقدمه له نظام التشغيل، لذا معرفة API المقدمة من نظام التشغيل ذات فائدة عظيمة لكي تعرف كيف تعمل الأشياء حقًا.
هي ليست قصًرا على API الكيرنل، ولكن فهمك للكمبيوتر وهندسته تحتمل أمور عدة مثلًا كيف تعمل الذاكرة العشوائية في نظام التشغيل، كيف تقوم بتحويل مجموعة بايتات إلى أحرف عربية مقروءة unicode. كيف أيضًا يقوم الكيرنل بتتبع الوقت وغيرها من الامور التي نعتمد عليها كل يوم ونتعامل معها كصندوق أسود.
كتب أنصحك بها للتعلم، إختر بينهم مايعجبك:
يوجد كورس يحتوي على محاضرات مسجلة أيضًا عن الكتاب الأخير تجده هنا.
مشاريع جانبية:
Build a daemon process manager
شيء مشابه لـ Supervisord او pm2 . لاتحاول تبني شيء يكون init process لنظام التشغيل ولكن أداة تقدر تستخدمها لتشغيل تطبيقات أخرى وإدارة حياتها تمامًا مثل supervisord.
Network
الهدف الأساسي من الخدمات اللي تبنى هي خدمات إنترنت، يعني الشبكة جزء أصيل متأصل في كل شيء نبنيه في عملنا اليومي. لذا ما أعتقد أحتاج أبيع لك فكرة ليش تحتاج تتعلم كيف TCP/IP يعمل. ولكن بأقول لك وش تحتاج تتعلم ومشاريع مقترحة تبنيها على جنب للإستفادة القصوى. فيه Protocols معينة تحتاج لتعلمها وفهمها وحفظها لانها سبب اغلب المشاكل وفهمها بيساعدك كثير، وهي:
TCP
DNS
HTTP
البروتوكولز الباقية فهمها نظريًا كافي في اغلب الاحوال. ولكن اللي ذكرتهم فوق كل ماتعمقت فيهم كان مردود هذا الإستثمار أعلى بشكل مباشر على عملك.
كتب أنصحك بها للتعلم، إختر بينهم مايعجبك:
مشاريع جانبية:
Build a DNS resolver
الهدف ببساطة تحويل دومين الى IP وهذه تعرف البرامج تعرف باسم DNS Resolver.
في كل نظام تشغيل فيه DNS Resolver ولها System Calls معرفة من POSIX مثل gethostbyname.
ولكن فيه لغات تبني وتستخدم DNS Resolver خاص فيها حتى تضمن طريقة عمل موحدة او تقليل احتمالية حدوث مفاجآت ولتقليل إستهلاك المصادر.
مثلًا في لغة Go الخيار الإفتراضي انها تستخدم Resolver خاص بها حتى يكون الاداء أسرع ولتقليل إستهلاك المصادر. للإستزادة إقرأ هنا.
مصادر ممكن تفيدك:
Build an HTTP Reverse Proxy
شيء مشابه للعظيم NGINX. الهدف منها إنك تعرف كيف تتعامل مع HTTP وخوارزميات Load Balancing أيضًا.
مصادر ممكن تفيدك:
ولخوارزميات الـ Load Balancing بإمكانك الإطلاع على هذا المصدر الذي قمت بكتابته قبل عدة سنوات:
Databases
المصدر: Architecture of a Database System
إن كان هنالك شيء يفوق Network أهمية فهو قاعدة البيانات، لأن العمل الصعب هو إدارة البيانات المدخلة من المستخدمين وكون قاعدة البيانات هي Source of truth فكل المستخدمين قطعًا سيتأثرون إن أصبحت بطيئة، على النقيض تمامًا في Application Server لان كل HTTP Request مستقل بحد ذاته لانها Stateless وهذه ميزة تُعطى لها بفضل قاعدة البيانات (حمّالة الأسية).
لذا معرفة عمل قاعدة البيانات وأخص هنا RDBMS له عوائد أضعاف مضاعفة، لأن في الغالب إن كان النظام بطيء فهي Slow Query.
مصادر أنصحك بها للتعلم، إختر بينهم مايعجبك:
مشاريع جانبية:
Build a key value storage engine
أبسط صورة لقاعدة البيانات هي بشكل Key Value Storage Engine ولها عدة طرق للبناء مع اختلاف في التضحيات مقابل المكتسبات. فإن كنت تريد شيء يخدم الكتابة بشكل أعلى من القراءة ستستخدم Log-structured Merge Tree مثلًا كطريقة LevelDB و RocksDB. ولكن إن كان الهدف تسريع القراءة على حساب الكتابة ستستخدم مثلًا طرق مشابهة لـ LMDB و Sqlite.
مصادر ممكن تفيدك:
Database Internals: Part 1
Designing Data-Intensive Applications: Chapter 3
ختامًا
ماذكرته في الأعلى ليس حصر على مايجب أن تتعلمه، ولكن هي مجموعة أشياء تعلمها لها عائد إستثمار للوقت والجهد عالي جدًا جدًا، حيث أني أكاد أجزم أنها ستغيّر حتى طريقة تفكيرك في حل المشكلات وتصميم وبناء الأنظمة في المستقبل.
في حال كان لديك أسئلة أو مصادر أفضل شاركها معنا في تويتر!
https://twitter.com/byLinker
عجبني فكرة وضع روابط لمشاريع بسيطة ترتكز على وظيفة وحده اساسية
Regarding the Chris Kanich course linked in the Systems Programming section.
Some of the links to the homework and labs are dead. I found this URL that has all working links: https://www.cs.uic.edu/~ckanich/cs361/f20/