قبل ما يكون فيه كود… كان فيه سؤال (سلسلة أصل البرمجة — 1)
قبل ما يكون فيه كود… كان فيه سؤال
أول ما بنبدأ نتعلم برمجة، أغلبنا بيقع في نفس الفخ:
بنفتكر إن “الشطارة” هي إنك تحفظ أسماء الـ Functions، وتعرف الـ Loops بتتكتب إزاي، وترص if/else ورا بعضها لحد ما الكود يشتغل.
بس بعد ما بتعدي أول كام شهر وتبدأ تبني مشاريع حقيقية، بتكتشف المفاجأة:
تكتب كود ملوش حل، والـ Syntax بتاعه سليم 100%، ومفيش أي Error في الكونسول.. ومع ذلك، الأبلكيشن بيطلع نتائج غريبة، أو الـ UI بيضرب في وش اليوزر، أو الداتا بتتسيف غلط في الداتابيز!
تفتكر العيب فين؟
العيب مش في لغة البرمجة، ولا في الكمبيوتر.
العيب إننا بنبدأ نكتب كود قبل ما نسأل السؤال اللي اتعملت البرمجة عشانه أصلاً.
الموقف اللي بيحصل مع كل الديفلوبرز
تعال نبسطها بسيناريو بيحصل كل يوم في الشركات والـ Production.
تخيل الـ Product Manager جالك وقالك:
«يا هندسة، عاوزين نعمل خصم 20% للعميل لو اشترى أكتر من 3 منتجات».
الجملة تبان واضحة وبسيطة جداً، صح؟
المبرمج اللي بيكتب كود من غير ما يفكر، هيروح جاري على الـ Editor ويكتب السطور دي:
function calculateDiscount(cart) {
if (cart.items.length > 3) {
return cart.total * 0.20;
}
return 0;
}
مبروك! الكود شغال، ومفيش Error، والتيم عمل Merge للـ Pull Request.
تاني يوم الصبح في الـ Production، بدأت الكوارث:
- عميل اشترى 4 قطع من نفس التيشيرت: مخدش الخصم! لأن
cart.items.lengthرجعت1(عنصر واحد بس في الـ Array جواهquantity: 4). - عميل حط 3 منتجات بـ 100 جنيه، وضاف هدية مجانية (سعرها 0): الخصم اتطبق على الإجمالي كله مع إنه مشتراش 4 منتجات بفلوس!
- عميل معاه كوبون خصم قديم بـ 90%: لما اتطبق عليه خصم الـ 20%، الإجمالي بقى بالسالب، والسيستم بقى هو اللي مديون للعميل!
الطلب البشري (العايم): "اعمل خصم للي يشتري أكتر من 3 منتجات"
الكود اللي اتكتب: "افحص طول المصفوفة فقط، واضرب في 0.20 بدون حدود"
النتيجة في السيرفر: "عجز في الحسابات، خناقات مع الـ QA، وخسارة فلوس"
الفكرة كلها في سطر واحدالكمبيوتر معندوش “حُسن نية”، ومبيعرفش يقرأ أفكارك، ومبيعرفش يقولك: “أنا فهمت قصدك وهصلحهالك”.
الكمبيوتر بينفذ اللي اتكتب بالمللي، حتى لو اللي اتكتب ملوش علاقة باللي في نيتك!
السؤال اللي غيّر العالم
قبل ما يكون فيه لغات برمجة أصلاً، علماء الرياضيات زمان لاحظوا مشكلة غريبة في عقل البشر:
لما بني آدم بيكلم بني آدم، الكلام بيبقى مليان افتراضات غير معلنة (Hidden Assumptions).
لو قولت لواحد صاحبك: “هاتلي معاك أكل وأنت جاي”.. هو فاهم إنك جعان، وعارف إنت بتحب إيه، وعارف ميزانيتك، وهيجيبلك أكل مناسب.
بس لو جيت تعلّم “آلة” أو نظام حسابي يعمل نفس المهمة، مش هيعرف يتحرك خطوة واحدة!
وهنا سألوا السؤال التاريخي:
«إزاي نحوّل فكرة معقدة في دماغنا، لمجموعة خطوات صريحة، محددة، ومستحيل تحتمل أكتر من معنى؟»
الإجابة على السؤال ده.. هي اللي سموها الخوارزمية (Algorithm).
الخوارزمية مش كود؛ الخوارزمية هي طريقة تفكيرك قبل ما تلمس الكيبورد.
التاتش الـ Advanced: لما الفكرة البسيطة تقابل الواقع المعماري
تعال بقى ننقل التفكير ده لمستوى الـ Software Architecture الحقيقي اللي بنحتاجه النهاردة في 2026.
عشان تضمن إن الكود بتاعك يستحيل يضرب في السيرفر، المهندس المحترف بيطبّق مبدأ رياضي اسمه Design by Contract (التصميم بالعقد)، وبيثبّت 3 حاجات في دماغه قبل ما يكتب سطر كود:
1. الـ Invariants (ثوابت النظام التي لا تنكسر)
الـ Invariant هي قاعدة رياضية لازم تفضل صحيحة في السيستم من أول ثانية لآخر ثانية:
- الخصم مستحيل يكون أقل من الصفر ().
- الخصم مستحيل يتجاوز قيمة المنتجات المؤهلة ().
- السعر والكمية أعداد موجبة دائماً.
2. فخ الـ Floating-Point في الحسابات المالية
في JavaScript و Python ومعظم لغات البرمجة، الأرقام العشرية بتشتغل بمعيار (IEEE 754):
console.log(0.1 + 0.2); // 0.30000000000000004
لو بتعمل حسابات مالية وخصومات، وطلعت الرقم ده وبعته لبوابة دفع زي Stripe أو Paymob، العملية هترفض بسبب كسور السنتات العشوائية!
الحل المعماري: في الأنظمة المالية الحقيقية، بنتعامل مع الفلوس كـ قروش / Cents (Integers) مش أرقام عشرية، وبنقرب الناتج في نهاية المعادلة فقط.
3. نقاء الدالة (Purity & Determinism)
الدالة مينفعش تروح تعدل في الـ Cart الأصلية مباشرة (Mutation)، لأنك لو شغال في Next.js أو بيئة فيها Concurrency أو Server Actions متزامنة، هتلاقي ريكويست بيكتب فوق ريكويست تاني ويحصل كابوس الـ Race Condition.
كود حقيقي محمي بأسس هندسية صلبة
بص بقى على الكود ده بعد ما طبقنا عليه الفكر الرياضي المنضبط:
// 1. تحديد الأنواع بدقة تمنع الغموض
interface CartItem {
id: string;
priceInCents: number; // فلوس بالسنت لتجنب كوارث الـ Floating Point
quantity: number;
}
interface DiscountResult {
discountInCents: number;
eligibleSubtotalInCents: number;
isApplied: boolean;
}
function calculateBulkDiscount(items: readonly CartItem[]): DiscountResult {
// Preconditions: حماية السيستم من الداتا المشوهة
const validItems = items.filter(
(item) => item.quantity > 0 && item.priceInCents > 0
);
// حساب إجمالي عدد القطع الفعلي
const totalPieces = validItems.reduce((acc, item) => acc + item.quantity, 0);
// الشرط الصريح: هل تنطبق عليه شروط العرض؟
const isEligible = totalPieces > 3;
if (!isEligible) {
return { discountInCents: 0, eligibleSubtotalInCents: 0, isApplied: false };
}
// حساب المجموع للمنتجات المؤهلة فقط
const eligibleSubtotal = validItems.reduce(
(acc, item) => acc + item.priceInCents * item.quantity,
0
);
// حساب الخصم كعدد صحيح (Round to nearest integer)
const rawDiscount = Math.round(eligibleSubtotal * 0.20);
// Invariant Guard: تأمين الحدود رياضياً (مستحيل سالب ومستحيل يتجاوز الأصل)
const safeDiscount = Math.min(Math.max(0, rawDiscount), eligibleSubtotal);
return {
discountInCents: safeDiscount,
eligibleSubtotalInCents: eligibleSubtotal,
isApplied: true,
};
}
بص على الفرق:
- عالجنا فخ الـ Length: بقى بيعد قطع (
quantity) مش عناصر مصفوفة. - استبعدنا المنتجات المجانية:
priceInCents > 0. - قفلنا أخطاء التقريب: بالتعامل بالسنت وتقريب الناتج
Math.round. - حطينا صمام أمان رياضي (Guard): مستحيل الخصم يطلع سالب أو يزيد عن الإجمالي حتى لو حصل أي خطأ حسابي في مدخلات العميل.
ليه الـ AI مش هيحميك من الحتة دي؟لو فتحت ChatGPT أو Copilot النهاردة وقولتله: “اكتبلي Function تحسب خصم 20% لو العميل اشترى أكتر من 3 منتجات”.. هيطلعلك الكود الساذج الأولاني اللي فيه
cart.items.length > 3!
ليه؟ لأن الـ AI متدرب على الكود الأكثر انتشاراً على النت، ومعظم الكود المنتشر مليان افتراضات ساذجة.
الـ AI أداة بتسرّع كتابة الكود، بس تحديد الـ Invariants والحدود المنطقية هي مهمتك أنت كمهندس!
الخلاصة المعمارية
المبرمج السطحي: فكرة عايمة ──► كود سريع أو prompt للـ AI ──► كوارث وBugs في الـ Production
المهندس الحقيقي: فكرة عايمة ──► تفكيك الافتراضات وتحديد الحدود ──► كود حتمي مستحيل يضرب
- الـ Syntax أسهل جزء في البرمجة: الأزمة الحقيقية هي الافتراضات المخفية اللي مخدتش بالك منها.
- فكر بالعقد والحدود (Invariants): قبل ما تكتب الـ
return، اسأل نفسك: هل الرقم ده ممكن يبقى سالب؟ هل ممكن يقسم على صفر؟ هل ممكن يفيض عن الذاكرة؟ - الكود النظيف هو كود حتمي (Deterministic): مدخلات واضحة = مخرجات واضحة وثابتة دائماً.
في المقال القادم (اليوم 2):
عرفنا إزاي نترجم الفكرة لخطوات حتمية صريحة..
السؤال المعماري التالي بقى:
لو إحنا لغتنا كلمات وأرقام معقدة، والكمبيوتر في أصله مجرد سيليكون وكهربا.. إزاي قدروا يختزلوا كل أفكار ومنطق الدنيا في حاجتين بس: الصفر والواحد؟ وإيه سر لمبة النور اللي بنت كل الثورة الرقمية؟
موعدنا في المقال القادم مع: «واحد وصفر… لغة الآلة، وقصة لمبة النور اللي بنت كل التكنولوجيا»

