Products
العودة إلى المقالات
التعلم
٢٤ أغسطس ٢٠٢٦
٦ دقائق قراءة

هل تحتاج إتقان الأساسيات لتبدأ البرمجة؟

نظرة نقدية حول وهم حتمية التأسيس المسبق في البرمجة؛ كيف يعمل التجريد البرمجي، ولماذا لا تحتاج لمعرفة كل شيء عن العتاد حتى تبدأ في البناء؟

لاحظتُ أن بعض المبرمجين يشددون دائمًا على "التأسيس" ويعدّونه شرطًا لازمًا لتعلم البرمجة. في تقديري، هذا الرأي مجرد انطباع يفتقر إلى السند العلمي؛ لكن لكونه يبدو منطقيًا وبديهيًا للوهلة الأولى، يقتنع به الكثيرون.

والسؤال هنا: هل التأسيس ضروري حقًا للبدء في تعلم البرمجة؟

في الحقيقة، لا توجد إجابة قطعية بالأبيض والأسود، ولكن ثمة مفهوم محوري ستصادفه كثيرًا في عالم البرمجة: التجريد (Abstraction).

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

قصة تشارلز شتاينميتز

تعطل في أحد مصانع هنري فورد مولدٌ كهربائي ضخم ومحوري للإنتاج، وعجز مهندسو المصنع وخبراؤه عن معرفة سبب العطل أو إعادة تشغيله لعدة أيام، مما كبّد المصنع خسائر فادحة.

استعان فورد حينها بـ «شتاينميتز»، مهندس الكهرباء العبقري في شركة General Electric. حضر شتاينميتز إلى المصنع، وقضى يومين يتجول حول المولد، يستمع لأصواته ويدوّن حسابات ومعادلات دقيقة في دفتره.

وفي نهاية اليوم الثاني، طلب سلمًا وقطعة طباشير، وصعد إلى نقطة معينة على الهيكل الخارجي للمولد ووضع علامة (X) بالطباشير، ثم قال لمهندسي فورد: «فكّوا الغطاء من هنا، واستبدلوا 16 لفة من ملفات السلك في هذا الموضع تحديدًا». نفّذ المهندسون التعليمات، فعاد المولد للعمل فورًا وبكفاءة تامة.

بعد بضعة أيام، أرسل شتاينميتز فاتورة إلى هنري فورد بمبلغ 10,000 دولار. استغرب فورد من ضخامة المبلغ بالنظر إلى أن العمل الظاهري لم يستغرق سوى وضع علامة طباشير، وطلب فاتورة مفصلة.

أعاد شتاينميتز إرسال الفاتورة مقسمة كالتالي:

  • رسم علامة بالطباشير: 1 دولار.

  • معرفة أين تضع العلامة: 9,999 دولار.

تجسد هذه القصة جوهر التجريد؛ فشتاينميتز كان يعرف موضع الخلل بدقة لأنه يفهم نظامه بعمق ومن المبادئ الأولى. لكن في المقابل، أنت لست بحاجة إلى معرفة كل تفصيلة في البرمجة إلا عندما تواجه مشكلة تتطلب ذلك.

البرمجة في جوهرها تجريد (Abstraction)

في الواقع، المعالج لا يفهم لغات البرمجة ولا حتى لغة C، بل يتعامل فقط مع الإشارات الثنائية (الأصفار والآحاد). ولكل معمارية معالج لغتها الخاصة؛ فإذا كنت تقرأ هذا المقال من هاتفك المحمول فالمعمارية على الأرجح هي ARM، وإذا كنت تقرؤه من كمبيوتر أو لابتوب فهي x86، وهما المعماريتان الأكثر انتشارًا اليوم.

إذا أردت تخزين بيانات أو معالجتها على مستوى المعالج، فأنت بحاجة لكتابة تعليمات تتعامل مباشرة مع مسجلات المعالج أو الرام على سبيل المثال:

add eax, 5

هذه هي اللغة الحقيقية التي يفهمها الكمبيوتر مباشرة هذا السطر يضيف رقم 5 الى المسجل EAX في المعالج

هذه هي التعليمات المباشرة التي يترجمها المعالج إلى أصفار وآحاد بالشكل الآتي:

00000101 00000101 00000000 00000000 00000000

هنا يأتي دور لغة C، فهي تفترض وجود حاسوب افتراضي يُعرف بـ C Abstract Machine. فبدلًا من التعامل المباشر مع المعالج بالأصفار والآحاد أو عبر لغة الاسمبلي ، تتيح لك C التخاطب معه بلغة مجردة فبدلًا من حجز المسجلات يدويًا، تكتب ببساطة:

int num = 5;

وكذلك الأمر في الجمل الشرطية؛ ففي المعالج الحقيقي تُنفذ الشروط عبر عمليات القفز والمقارنة. فلو كتبت في C:

if (20 > 18) {  
  printf("20 is greater than 18");  
}

فإن المقابل المباشر لها على مستوى المعالج يبدو هكذا:

mov eax, 20
cmp eax, 18
jg printf

حيث تُخزن القيمة 20 في المسجل eax، ثم تُقارن بالرقم 18 عبر cmp، وأخيرًا يقوم الأمر jg (أي Jump if Greater) بالقفز إلى تنفيذ الدالة printf إذا تحقق الشرط.

لغة C ولغات البرمجة عمومًا تخفي عنك هذه التفاصيل الدقيقة وتجعلك تتعامل مع آلة مجردة، ولهذا السبب تحديدًا لست بحاجة لتعلم لغة المعالج، أو تصميم المنطق الرقمي، أو معمارية الحاسوب لكي تبدأ في بناء البرمجيات.

قانون تسرب التجريدات (The Law of Leaky Abstractions)

هل يعني هذا أنك لن تحتاج لتعلم هذه المواد إطلاقًا؟ بالتأكيد لا.

صاغ مهندس البرمجيات جويل سبولسكي (Joel Spolsky) هذا القانون في مقال تقني شهير عام 2002 ليدحض وهمًا هندسيًا وتسويقيًا كان سائدًا حينها؛ وهو الادعاء بأن أطر العمل الحديثة ستغني المطور تمامًا عن فهم الطبقات الدنيا، ونصّ القانون على:

«جميع التجريدات غير التافهة (Non-trivial abstractions) تُسرّب تفاصيلها بدرجة ما».

وهذا يعني أنك ستواجه حتمًا مشكلات معقدة تفرض عليك فهم أساسيات أنظمة التشغيل، وهياكل البيانات، ومعمارية الحاسوب.

public List<CategoryDTO> getTree(@NonNull List<Category> all) {  
    Map<Long, CategoryDTO> map = all.stream()  
            .collect(Collectors.toMap(  
                    Category::getId,  
                    c -> new CategoryDTO(c.getId(), c.getNameAr(), c.getNameEn(), c.getSlug(), new ArrayList<>())  
            ));  
  
    List<CategoryDTO> roots = new ArrayList<>();  
  
    for (Category c : all) {  
        CategoryDTO dto = map.get(c.getId());  
        if (c.getParentId() == null) {  
            roots.add(dto);  
        } else {  
            CategoryDTO parent = map.get(c.getParentId());  
            if (parent != null) {  
                parent.children().add(dto);  
            } else {  
                roots.add(map.get(c.getId()));  
            }  
        }  
    }  
    return roots;  
}

مثال من واقع عملي: عندما أردت بناء نظام تصنيفات هرمي في الباك اند، احتجت لهياكل البيانات لتمثيل الشجرة وتخزينها في قاعدة البيانات. وعند استرجاع البيانات وإعادة تشكيلها كشجرة داخل التطبيق، احتجت إلى خوارزمية Flat List to Tree، واستخدمت بداخلها هيكل HashMap لتقليل التعقيد الزمني للخوارزمية من O(n2) إلى O(n). ميزة واحدة تطلبت توظيف هيكلي بيانات وخوارزمية مخصصة.

والأمثلة كثيرة؛ فأغلب ما تنفذه برمجياً يعتمد في جوهره على نداءات النظام (System Calls) وإدارة الذاكرة.

لذلك، ستصل حتمًا إلى مرحلة تحتاج فيها لتعلم الأساسيات بعمق؛ لكنّ القول بأنك لن تتعلم البرمجة إلا بالبدء من الأساسيات وإتقانها أولاً هو زعمٌ غير دقيق، وغالبًا ما تقف خلفه دوافع تسويقية بحتة.

شارك المقال:

المزيد من المقالات

صُنع بـ

باستخدام

Next.js

© 2026 فيصل الحربي

faisalalharbi9915@gmail.com

القصيم 🇸🇦