كم مرة سمعت جملة «Python بطيئة» أو «Java ملك لشركة Oracle وسوف تدفع لها» أو «JavaScript هي نسخة مبسطة من Java»؟ هذه الجمل تتكرر في النقاشات بين المطورين وفي اجتماعات اختيار التقنية، وكلها تخلط بين شيئين مختلفين: اللغة نفسها، وهي وثيقة تصف ما يعنيه كل سطر تكتبه، والبرنامج الذي يقرأ هذا السطر ويشغله، وهو برنامج مستقل له شركة أو مجتمع يطوره ورخصة تحكم استخدامه وجدول إصدارات ودعم. وعندما تفصل بين الاثنين تصبح أسئلة كثيرة في عملك اليومي واضحة: لماذا يعمل الكود مع مترجم ولا يعمل مع آخر، وهل يلزمك ترخيص لتشغيل Java على سيرفراتك، ومن الذي سوف يقرر شكل اللغة التي تبني عليها منتجك بعد خمس سنوات، وأي نسخة من بين عشرات النسخ المتاحة تختار.
في مقال أنماط البرمجة وأنظمة الأنواع تكلمنا عن شكل اللغات من الداخل، وفي مقال قصص لغات البرمجة ومن صنعها تكلمنا عن الأشخاص الذين صنعوها، أما هذا المقال فيتناول الجانب الذي ينساه أغلبنا: من يكتب تعريف اللغة، ومن يطبقه، ومن يقرر مستقبلها، وماذا يعني هذا لك. وسوف نناقش في هذا المقال ما يلي:
- ثلاث جمل نسمعها كل يوم، ولماذا لا تصح أي منها كما تقال.
- الفرق بين المواصفة Specification والتطبيق Implementation، مع تجربة حقيقية لبرنامج C واحد يعطي نتيجتين مختلفتين مع GCC وClang.
- كيف تعرف كل لغة مشهورة وتطبق: C وC++ وJavaScript وJava وPython وGo وRust وC# وPHP وTypeScript.
- من يقرر مستقبل اللغة: الشخص الواحد، ومجلس التوجيه، والشركة، ولجنة المعايير، مع جدول مقارنة.
- لماذا يهمك هذا: رخصة المترجم أو ال Runtime مقابل رخصة كودك، وإصدارات الدعم الطويل LTS، واختيار التوزيعة، وقابلية النقل بين التطبيقات.
ثلاث جمل نسمعها كل يوم
لنبدأ بالجملة الأولى: «Python بطيئة». وقد يتساءل البعض: أليست هذه حقيقة يعرفها الجميع؟ والإجابة أن Python كلغة لا سرعة لها، فهي وثيقة اسمها The Python Language Reference تصف ماذا يعني كل تعبير وكل جملة، والذي له سرعة هو البرنامج الذي ينفذ الكود، وأشهرها CPython المكتوب بلغة C، وهو البرنامج الذي تنزله من python.org وتقصده غالباً عندما تكتب python3. وهناك تطبيقات أخرى للغة نفسها، فمشروع PyPy مثلاً يحتوي على مترجم JIT ويدعم Python 3.12 و3.11، ويذكر موقعه أنه أسرع من CPython في المتوسط على مجموعة اختباراته. وحتى قفل GIL الذي يتكلم عنه الجميع هو تفصيل في CPython وليس في اللغة، وقد شرحناه في مقال المعالج والخيوط والتزامن. لذلك فالجملة الدقيقة هي «CPython أبطأ من غيره في هذا النوع من المهام»، وهي جملة لها حل.
والجملة الثانية: «Java ملك Oracle». والصحيح أن هناك ثلاثة أشياء مختلفة: مواصفة Java SE التي تقرها عملية مجتمعية اسمها Java Community Process، والكود المصدري للتطبيق المرجعي OpenJDK وهو مفتوح المصدر برخصة GPLv2 مع استثناء Classpath، ثم منتج تجاري اسمه Oracle JDK له رخصته الخاصة. وOracle تقود مشروع OpenJDK وتملك العلامة التجارية Java، ولكن الكود نفسه مفتوح، وتبني منه Amazon وMicrosoft ومؤسسة Eclipse وغيرها نسخاً مجانية، وسوف نراها بأعيننا في التجربة.
والجملة الثالثة: «JavaScript هي Java». والحقيقة أن اللغتين لا يجمعهما إلا الاسم، فاللغة التي اخترعها Brendan Eich في Netscape وحدت مواصفتها تحت اسم ECMAScript في معيار ECMA-262، والسبب في الاسم الغريب أن كلمة JavaScript علامة تجارية، وهي اليوم مسجلة باسم Oracle التي ورثتها من Sun، وقد وقع أكثر من 27 ألف مطور على رسالة مفتوحة تطالب بتحريرها.
والقاسم المشترك بين الجمل الثلاث هو الخلط بين اللغة وتطبيقها، وهو موضوع المقال.
المواصفة والتطبيق: الوثيقة والبرنامج
المواصفة Specification هي وثيقة تعرف اللغة: ما هي الكلمات المسموحة وكيف تكتب، أي القواعد Syntax، وماذا يحدث عند تنفيذ كل جملة، أي المعنى Semantics، وما هي المكتبة القياسية Standard Library التي يجب أن تتوفر. والتطبيق Implementation هو برنامج يقرأ الكود المكتوب بهذه اللغة ويشغله، سواء كان مترجماً Compiler مثل GCC ينتج ملفاً تنفيذياً، أو مفسراً Interpreter مثل CPython، أو محركاً Engine فيه JIT مثل V8. وقد شرحنا الفرق بين هذه الأنواع في مقال ماذا يحدث عندما تكتب برنامج Hello World وتشغله.
وأقرب مثال لك كمدير سيرفرات هو بروتوكول HTTP، فهو مواصفة مكتوبة في وثائق RFC، وNginx وApache وCaddy برامج مختلفة تطبق هذه المواصفة، ولكل منها شركة أو مجتمع ورخصة وأداء مختلف، ولا يقول أحد «HTTP بطيء» لأن سيرفراً معيناً كان بطيئاً. وبالشكل نفسه فاللغة الواحدة لها تطبيقات كثيرة، والصورة التالية تبين أربعة أمثلة: مواصفة لكل لغة في الأعلى، وتحتها ثلاثة تطبيقات مستقلة لكل منها رخصتها:

ولاحظ أن بعض اللغات ليس لها مواصفة مستقلة بالمعنى الرسمي، وإنما لها تطبيق مرجعي Reference Implementation يعتبر سلوكه هو التعريف، فإذا اختلف تطبيق آخر عنه فالتطبيق الآخر هو المخطئ. وهذا حال PHP عملياً، وحال TypeScript اليوم كما سيأتي، بينما Python في المنتصف: لها وثيقة مرجعية مكتوبة، ولكن مقدمتها تقول إن CPython هو التطبيق الأصلي الذي تظهر فيه الميزات الجديدة أولاً، وإن كل تطبيق آخر يختلف عن الوثيقة في بعض النقاط.
ما الذي تتركه المواصفة للتطبيق؟
قد تبدو الفكرة من الوهلة الأولى بسيطة: مواصفة دقيقة، وكل التطبيقات تتبعها، فيعطي الكود النتيجة نفسها في كل مكان. لكن في الواقع فالمواصفات تترك بعض الأمور عمداً للتطبيق، والسبب أن تحديد كل شيء يمنع المترجم من اختيار الطريقة الأسرع على كل معالج. ومعيار C مثلاً يفرق بين ثلاثة أنواع من السلوك: سلوك يحدده التطبيق ويوثقه Implementation-defined مثل حجم النوع long، وسلوك غير محدد Unspecified يختار فيه التطبيق بين احتمالات دون أن يوثق اختياره، مثل ترتيب حساب معاملات الدالة، وسلوك غير معرف Undefined Behavior لا تقدم فيه المواصفة أي ضمان، مثل القراءة خارج حدود المصفوفة. والتجربة التالية تبين النوع الثاني بأعيننا.
تجربة عملية: برنامج C واحد ومترجمان
سوف نشغل Container من Ubuntu 24.04 ونثبت فيه المترجمين GCC وClang من مستودعات التوزيعة، وإذا لم يكن Docker مثبتاً لديك فقد شرحنا تثبيته في دليل تثبيت Docker على Ubuntu:
docker run -it --rm --name lab-specs-c ubuntu:24.04 bash
apt-get update
apt-get install -y gcc clang
mkdir /lab && cd /labثم نكتب برنامجاً صغيراً يطبع اسم المترجم الذي بناه، ونسخة معيار C التي يعمل بها، وحجم النوع long، ثم يستدعي الدالة printf بمعاملين كل منهما استدعاء لدالة تطبع رقمها عند حسابها. احفظ الملف التالي باسم order.c:
#include <stdio.h>
static int say(int n)
{
printf("evaluating argument %d\n", n);
return n;
}
int main(void)
{
#if defined(__clang__)
printf("compiler: Clang %s\n", __clang_version__);
#elif defined(__GNUC__)
printf("compiler: GCC %s\n", __VERSION__);
#endif
printf("__STDC_VERSION__ = %ldL\n", (long)__STDC_VERSION__);
printf("sizeof(long) = %zu\n", sizeof(long));
printf("result: %d %d\n", say(1), say(2));
return 0;
}الآن سوف نعرض إصدار كل مترجم، ثم نبني البرنامج مرتين ونشغل الناتجين:
gcc --version | head -1
clang --version | head -2
gcc order.c -o order-gcc && clang order.c -o order-clang
./order-gcc
./order-clangوالمخرج سوف يكون كما يلي:
gcc (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0
Ubuntu clang version 18.1.3 (1ubuntu1)
Target: x86_64-pc-linux-gnu
compiler: GCC 13.3.0
__STDC_VERSION__ = 201710L
sizeof(long) = 8
evaluating argument 2
evaluating argument 1
result: 1 2
compiler: Clang 18.1.3 (1ubuntu1)
__STDC_VERSION__ = 201710L
sizeof(long) = 8
evaluating argument 1
evaluating argument 2
result: 1 2في المخرج أعلاه لاحظ التالي:
- الكود نفسه والمعيار نفسه C17 (القيمة
201710L) والمعالج نفسه، ومع ذلك حسب GCC المعامل الثاني قبل الأول، وحسب Clang الأول قبل الثاني. وكلاهما صحيح تماماً، لأن معيار C لا يحدد ترتيب حساب معاملات الدالة، فإذا كان برنامجك يعتمد على هذا الترتيب فهو برنامج يعمل بالصدفة، وسوف يتغير سلوكه عندما يتغير المترجم أو حتى خيارات التحسين. - النتيجة النهائية
result: 1 2واحدة في الحالتين، فالمعيار يضمن أن كل قيمة تذهب إلى مكانها الصحيح، والذي لم يضمنه هو ترتيب الآثار الجانبية Side Effects، أي سطور الطباعة داخلsay. - القيمة
sizeof(long) = 8من النوع الأول الذي يحدده التطبيق، فهي 8 بايت على Linux بمعالج 64 بت، بينما هي 4 بايت في مترجم Microsoft على Windows، لذلك لا تفترض حجمlongفي كود ينقل بين الأنظمة، واستخدم الأنواع ذات الحجم الثابت مثلint64_t.
وسطر sizeof(long) في MSVC ليس من تجربتنا، وإنما من جدول أنواع البيانات في وثائق Microsoft الذي يذكر أن long حجمه 4 بايت.
عندما يسبق المعيار المترجم
والآن لنكسر شيئاً عن قصد: معيار C23 صدر رسمياً من ISO في 2024، فلنطلب من المترجمين العمل به:
gcc -std=c23 order.c -o o23; echo "exit=$?"
gcc -std=c2x order.c -o o2x && ./o2x | grep STDC
clang -std=c23 order.c -o o23c && ./o23c | grep STDCوالمخرج سوف يكون كما يلي:
gcc: error: unrecognized command-line option '-std=c23'; did you mean '-std=c2x'?
exit=1
__STDC_VERSION__ = 202000L
__STDC_VERSION__ = 202311Lلاحظ أن GCC 13 لا يعرف الاسم c23 أصلاً، ويقترح الاسم القديم c2x الذي كان يستخدم قبل اكتمال المعيار، وعند استخدامه يعطي القيمة المؤقتة 202000L، بينما يعرف Clang 18 الاسم الجديد ويعطي القيمة الرسمية 202311L. والسبب أن GCC 13 صدر قبل نشر المعيار، ووثائقه تصف هذا الوضع بأنه تجريبي وغير مكتمل، وأن الوضع الافتراضي هو gnu17، أي C17 مع إضافات GNU، ثم جاء GCC 15 وغير الوضع الافتراضي إلى gnu23. وهذا يعني أن صدور المعيار لا يعني أن مترجمك يدعمه، فكل تطبيق يلحق بالمواصفة في وقته، لذلك قبل أن تستخدم ميزة جديدة في مشروع تأكد من دعمها في المترجم الموجود فعلاً على سيرفر البناء، وليس في آخر إصدار على موقع المشروع.
وعند الانتهاء اكتب exit، فال Container يحذف نفسه بسبب الخيار --rm.
كيف تعرف كل لغة وتطبق
الآن سوف نمر على اللغات المشهورة واحدة واحدة، ونسأل في كل منها الأسئلة نفسها: أين تعريف اللغة، ومن يكتبه، وما هي التطبيقات، وكيف تدخل ميزة جديدة، وما هي رخصة التطبيق الرئيسي.
C وC++: معايير ISO
لغة C تعرفها المنظمة الدولية للمعايير ISO في المعيار ISO/IEC 9899، وتكتبه لجنة عمل اسمها WG14، وصفحة اللجنة تذكر أن آخر إصدار هو C23 الذي اعتمدته ISO وIEC في 2024. ولغة C++ تعرفها لجنة WG21 في المعيار ISO/IEC 14882، وآخر إصدار منشور هو C++23 واسمه الرسمي ISO/IEC 14882:2024، والسبب في اختلاف الرقمين أن العمل الفني اكتمل في 2023 والنشر الإداري تم في 2024، والعمل جار على C++26. ولاحظ أن نص المعيار الرسمي يباع في متجر ISO، بينما المسودات التي تعمل عليها اللجنة منشورة مجاناً.
والتطبيقات المشهورة ثلاثة: GCC من مشروع GNU برخصة GPLv3، وClang المبني على LLVM برخصة Apache 2.0 مع استثناءات LLVM، وMSVC من Microsoft وهو مترجم مغلق المصدر. وعندما تكتب كوداً يلتزم بالمعيار ولا يستخدم إضافات خاصة بمترجم معين، فإنك تستطيع بناءه بأي منها.
JavaScript: معيار ECMA-262 ولجنة TC39
تعرف JavaScript في المعيار ECMA-262 الذي تصدره منظمة Ecma International، وتكتبه لجنة فنية اسمها TC39 تضم مندوبين من الشركات التي تصنع المتصفحات والمحركات وغيرها. ومنذ 2015 تصدر طبعة جديدة كل سنة، وآخر طبعة منشورة هي ECMAScript 2026 وهي الطبعة السابعة عشرة الصادرة في يونيو 2026، والمسودة الحية على tc39.es/ecma262 هي ECMAScript 2027.
وأهم ما في TC39 هو طريقة دخول الميزات، فلا تدخل ميزة إلى اللغة بقرار من شركة واحدة، وإنما تمر بمراحل تحددها وثيقة العملية الرسمية، واللجنة توافق على انتقال المقترح من كل مرحلة إلى التي بعدها. والصورة التالية تبين المراحل الست من فكرة إلى ميزة في الطبعة السنوية:

في الصورة أعلاه لاحظ التالي:
- المرحلة 2.7 أضيفت حديثاً بين 2 و3، وفيها يكون النص كاملاً وتكتب اختبارات Test262 التي تتحقق من أي محرك.
- شرط الوصول إلى المرحلة 4 هو وجود تطبيقين متوافقين يجتازان اختبارات Test262، وخبرة حقيقية في محركات تعمل للمستخدمين، وهذا يعني أن المواصفة هنا تتبع التطبيقات ولا تسبقها، على عكس ما رأيناه في C23.
- بحسب الوثيقة تتجمع الميزات التي وصلت إلى المرحلة 4 في مارس، ثم تعتمد الجمعية العامة لمنظمة Ecma الطبعة الجديدة في الصيف.
والتطبيقات هنا نوعان يخلط بينهما الكثير: المحرك Engine الذي ينفذ لغة ECMAScript نفسها، وال Runtime الذي يضع المحرك داخل برنامج ويضيف له ما ليس في المواصفة، مثل قراءة الملفات والشبكة. فالمحركات الثلاثة الكبرى هي V8 من Google وهو في Chrome وNode.js برخصة BSD، وSpiderMonkey من Mozilla وهو في Firefox برخصة MPL 2.0، وJavaScriptCore من مشروع WebKit وهو في Safari، وأجزاء WebKit برخصتي LGPL وBSD. أما ال Runtimes على السيرفر فأشهرها Node.js المبني على V8 برخصة MIT وهو مشروع في مؤسسة OpenJS، وDeno المبني على V8 أيضاً برخصة MIT، وBun المبني على JavaScriptCore، وملف رخصته يذكر أن Bun نفسه برخصة MIT وأنه يربط JavaScriptCore برخصة LGPL-2 ربطاً ثابتاً. لذلك عندما تقرأ أن الدالة fetch أو الكائن process موجود في Node وغير موجود في المتصفح، فهذا ليس اختلافاً في اللغة، وإنما في ال Runtime.
Java: المواصفة وعملية JCP وOpenJDK
Java لها مواصفتان: مواصفة اللغة Java Language Specification واختصاراً JLS، ومواصفة الآلة الافتراضية Java Virtual Machine Specification، ويقر كل إصدار من منصة Java SE عبر طلب في عملية JCP يسمى JSR، فإصدار Java SE 25 مثلاً عرفه JSR 400 الذي ينص على أن تطبيقه المرجعي هو JDK 25، وصفحة JDK 25 في مشروع OpenJDK تقول الشيء نفسه. أما الميزات فتقترح وتتابع داخل OpenJDK على شكل وثائق تسمى JEP.
والكود المصدري ل OpenJDK مفتوح برخصة GPLv2 مع استثناء Classpath، ومنه تبنى توزيعات Distributions كثيرة، والفرق بينها في من يبني ومن يختبر ومن يقدم التحديثات الأمنية وكم سنة، وليس في اللغة. والصورة التالية تبين هذه السلسلة من المواصفة إلى التوزيعات:

ولنرى ذلك عملياً، سوف نشغل الأمر java -version في ثلاث Docker Images رسمية لثلاث توزيعات من الإصدار 25:
docker run --rm --name lab-specs-temurin eclipse-temurin:25-jdk java -version
docker run --rm --name lab-specs-corretto amazoncorretto:25 java -version
docker run --rm --name lab-specs-msopenjdk mcr.microsoft.com/openjdk/jdk:25-ubuntu java -versionوالمخرج سوف يكون كما يلي:
openjdk version "25.0.4.1" 2026-08-18 LTS
OpenJDK Runtime Environment Temurin-25.0.4.1+1 (build 25.0.4.1+1-LTS)
OpenJDK 64-Bit Server VM Temurin-25.0.4.1+1 (build 25.0.4.1+1-LTS, mixed mode, sharing)
openjdk version "25.0.4.1" 2026-08-18 LTS
OpenJDK Runtime Environment Corretto-25.0.4.10.1 (build 25.0.4.1+10-LTS)
OpenJDK 64-Bit Server VM Corretto-25.0.4.10.1 (build 25.0.4.1+10-LTS, mixed mode, sharing)
openjdk version "25.0.4.1" 2026-08-18 LTS
OpenJDK Runtime Environment Microsoft-14951822 (build 25.0.4.1+1-LTS)
OpenJDK 64-Bit Server VM Microsoft-14951822 (build 25.0.4.1+1-LTS, mixed mode, sharing)في المخرج أعلاه لاحظ التالي:
- السطر الأول متطابق في الثلاثة:
openjdk version "25.0.4.1" 2026-08-18 LTS، أي أن الثلاثة مبنية من الكود نفسه في الإصدار نفسه وتاريخ التحديث نفسه. - الاختلاف في اسم المورد Vendor في السطرين الثاني والثالث:
Temurinمن مؤسسة Eclipse عبر مشروع Adoptium، وCorrettoمن Amazon، وMicrosoftمن Microsoft، ورقم البناء بعد علامة+يختلف بحسب طريقة كل مورد. - الثلاثة مجانية برخصة OpenJDK نفسها، وصفحة أسئلة Corretto وصفحة Microsoft تذكران أنها اجتازت اختبارات التوافق TCK التي تتحقق من مطابقة مواصفة Java SE، وكذلك Temurin.
أما Oracle JDK فهو منتج Oracle التجاري برخصة مختلفة، وتنشر Oracle بجانبه بناءً آخر باسم Oracle OpenJDK برخصة GPLv2 مع الاستثناء ولكن لفترة قصيرة، فتحديثاته للإصدار 25 مثلاً توقفت في يناير 2026. وقصة رخصة Oracle JDK هي مصدر أغلب الخوف من Java، لذلك سوف نذكرها كما هي في صفحة الأسئلة الرسمية: منذ سبتمبر 2021 تستخدم Oracle رخصة No-Fee Terms and Conditions واختصاراً NFTC، وهي تسمح بالاستخدام المجاني حتى في الإنتاج Production، وتسمح بإعادة التوزيع بشرط ألا تكون مقابل رسوم. ولكن هذه الرخصة مؤقتة لكل إصدار LTS: تحديثات JDK 17 بعد سبتمبر 2024 (من 17.0.13) انتقلت إلى رخصة OTN التي تسمح بالاستخدام الشخصي والتطوير والاختبار فقط دون رسوم، وتحديثات JDK 21 تنتقل إليها بعد سبتمبر 2026، وتحديثات JDK 25 تبقى تحت NFTC حتى سبتمبر 2028، أي سنة بعد إصدار LTS القادم Java 29 المخطط له في سبتمبر 2027. وهذا يعني أن من ينزل Oracle JDK ويستمر في تحديثه بعد هذه التواريخ يحتاج اشتراكاً مدفوعاً لاستخدامه في الإنتاج، ومن يستخدم إحدى توزيعات OpenJDK المجانية لا يتأثر بهذا.
وهناك أيضاً من يغير الأجزاء الداخلية وليس فقط طريقة البناء، مثل Eclipse OpenJ9 وهي آلة افتراضية JVM مختلفة أصلها من IBM، وOracle GraalVM الذي يضيف مترجم Graal وأداة Native Image التي تحول تطبيق Java إلى ملف تنفيذي.
Python: وثيقة مرجعية وPEPs ومجلس توجيه
تعرف Python في The Python Language Reference، والتغييرات الكبيرة تقترح في وثائق تسمى PEP، وPEP 1 تقول إنها الآلية الأساسية لاقتراح الميزات الجديدة. والتطبيق المرجعي هو CPython برخصة Python Software Foundation License وهي رخصة متساهلة متوافقة مع GPL، ومن التطبيقات الأخرى PyPy الذي ذكرناه، وMicroPython المصمم للمتحكمات الدقيقة Microcontrollers، وGraalPy الذي يعمل على GraalVM ويقول مشروعه إنه متوافق مع Python 3.13، وJython المكتوب ب Java.
أما من يقرر، فقد كان Guido van Rossum صاحب الكلمة الأخيرة لعقود بلقب «الدكتاتور الخير مدى الحياة» Benevolent Dictator For Life واختصاراً BDFL، حتى أعلن في 12 يوليو 2018 أنه يمنح نفسه «إجازة دائمة» من هذا الدور. وبعد تصويت بين المطورين الأساسيين Core Developers اعتمدت PEP 8016 نموذج مجلس التوجيه Steering Council، وتفاصيله اليوم في PEP 13: مجلس من خمسة أعضاء ينتخبه المطورون الأساسيون من جديد بعد كل إصدار رئيسي Feature Release من Python، ويقرر في المقترحات بعد النقاش العلني.
Go: مواصفة قصيرة وفريق في Google
Go لها مواصفة مكتوبة قصيرة نسبياً، والتطبيق الرئيسي هو المترجم gc الذي يأتي مع الأمر go برخصة BSD، والأسئلة الشائعة تذكر وجود مترجم آخر مبني على GCC اسمه gccgo. وهنا مثال آخر على أن التطبيقات لا تسير بالسرعة نفسها: صفحة gccgo تذكر أن إصدارات GCC 12 و13 تحتوي على مكتبة Go 1.18 كاملة، ولكنها لا تدعم الأنواع العامة Generics حتى الآن، بينما دخلت Generics في gc منذ Go 1.18. أما الميزات الجديدة فتمر عبر عملية المقترحات Proposal Process، حيث تجتمع مجموعة من أعضاء فريق Go في اجتماعات مراجعة دورية وتقرر قبول المقترح أو رفضه.
Rust: وثيقة مرجعية وRFCs ومؤسسة
لم يكن ل Rust معيار رسمي، وإنما The Rust Reference التي تقول عن نفسها إنها المرجع الأساسي للغة، وتطلب ممن يجد اختلافاً بينها وبين سلوك المترجم أن يفتح بلاغاً لتحديد أيهما الصحيح. وفي مارس 2025 أعلن مشروع Rust أنه سوف يتبنى مواصفة FLS، وهي وصف للغة كتبته Ferrous Systems مع AdaCore واستخدم لاعتماد مترجمات Rust في الصناعات التي تحتاج سلامة عالية، والمواصفة اليوم منشورة تحت مشروع Rust. والتغييرات الكبيرة تمر عبر عملية RFC التي تنتهي بفترة تعليق أخيرة Final Comment Period قبل القرار، والقيادة منذ يونيو 2023 بيد مجلس القيادة Leadership Council الذي حل محل الفريق الأساسي Core Team، والفرق المختصة هي التي تقرر في مجالاتها.
وفي 8 فبراير 2021 أعلن عن تأسيس Rust Foundation كمؤسسة مستقلة غير ربحية، ونقلت إليها Mozilla العلامة التجارية والبنية التحتية بما فيها سجل الحزم crates.io. والمترجم rustc برخصة مزدوجة MIT وApache 2.0.
C# و.NET: معايير Ecma وتصميم في Microsoft
C# لها معيار في Ecma هو ECMA-334 وآخر طبعة منشورة منه هي السابعة في ديسمبر 2023، والبيئة التي تشغلها لها معيار آخر هو ECMA-335 للبنية Common Language Infrastructure. ووثائق Microsoft تذكر أن لجنة Ecma المختصة TC49-TG2 تعمل على إنهاء الإصدار الثامن من المعيار، أي أن المعيار يتأخر عن اللغة التي تستخدمها اليوم بعدة إصدارات. أما تصميم الميزات الجديدة فيتم علناً في مستودع dotnet/csharplang الذي يقوده فريق Microsoft.
والتطبيق الرئيسي هو .NET الذي أعلنت Microsoft فتح مصدره في نوفمبر 2014 تحت رعاية مؤسسة .NET Foundation، والكود اليوم برخصة MIT.
PHP: التطبيق هو التعريف، والتصويت هو القرار
PHP لا تعتمد على مواصفة مستقلة، فالتطبيق php-src هو التعريف العملي للغة، والتغييرات تمر عبر عملية RFC تبدأ بالنقاش في القائمة البريدية internals ثم التصويت، وقواعد التصويت تشترط أغلبية الثلثين لقبول المقترح. وفي نوفمبر 2021 أعلنت مجموعة من الشركات منها JetBrains تأسيس PHP Foundation لتمويل المطورين الذين يعملون على اللغة. ومن الأخبار الحديثة أن مقترح تحديث رخصة PHP قبل، وهو يعتمد رخصة BSD المعدلة BSD-3-Clause كإصدار رابع لرخصة PHP بدلاً من الرخصة الخاصة القديمة التي لم تكن معتمدة من OSI، وملف الرخصة في الفرع الرئيسي أصبح بنص BSD.
TypeScript: المترجم هو المواصفة
نشرت Microsoft في البداية مواصفة ل TypeScript، ولكن آخر نسخة منها كانت للإصدار 1.8 في يناير 2016، ثم نقلت إلى الأرشيف، ومنذ ذلك الوقت فالتعريف العملي للغة هو سلوك المترجم tsc نفسه، والكود برخصة Apache 2.0 وليس MIT كما يظن البعض. وفي مارس 2025 أعلن الفريق عن نقل المترجم إلى لغة Go للحصول على سرعة أكبر، ثم صدر TypeScript 7 في يوليو 2026 كأول إصدار من المترجم الجديد، ويذكر الإعلان أنه أسرع بين 8 و12 مرة في البناء الكامل. ولاحظ أن هذا مثال واضح على الفكرة كلها: اللغة لم تتغير، والذي تغير هو التطبيق ولغة كتابته، وفي مستودع المترجم الجديد الرخصة نفسها Apache 2.0.
من يقرر مستقبل اللغة؟
بعد هذه الجولة نستطيع أن نجمع طرق اتخاذ القرار في أربعة نماذج، والصورة التالية تبينها مع أمثلة لكل منها:

- الشخص الواحد BDFL: القرار سريع وتصميم اللغة متسق لأن ذوقاً واحداً يحكمه، ولكن نقطة الضعف أن كل شيء معلق بشخص واحد، فإذا تعب أو ترك كما حدث في Python في 2018 احتاج المجتمع إلى بناء نظام جديد في وقت صعب.
- مجلس التوجيه Steering Council: مجموعة صغيرة منتخبة من المطورين أنفسهم، وهو حل وسط بين سرعة الفرد وشرعية الانتخاب، ونقطة ضعفه أن النقاشات الكبيرة تأخذ وقتاً أطول.
- الشركة القائدة Company-led: فريق مدفوع الأجر يعمل على اللغة كل يوم، والتمويل مضمون ما دامت الشركة مهتمة، ونقطة الضعف أن مصلحة الشركة قد تختلف يوماً عن مصلحتك، ولذلك تهمك الرخصة المفتوحة للتطبيق، فهي التي تسمح للمجتمع بالاستمرار إذا تغيرت الشركة.
- لجنة المعايير Standards Committee: أبطأ النماذج، فإصدار C++ يأخذ ثلاث سنوات، ولكنها أكثرها استقراراً، والكود الذي يلتزم بالمعيار يعيش عقوداً، وهذا سبب اختيار الأنظمة المدمجة والصناعات الحساسة للغات المعيارية.
أما المؤسسات غير الربحية Foundations مثل PSF وRust Foundation وOpenJS Foundation وPHP Foundation و.NET Foundation، فأغلبها لا تقرر تصميم اللغة، وإنما تمول المطورين وتحمي العلامة التجارية وتدير البنية التحتية مثل سجلات الحزم، بينما يبقى قرار التصميم بيد المجلس أو الفريق أو اللجنة. أما حوكمة المشاريع مفتوحة المصدر بشكل عام، من الأدوات الصغيرة إلى المشاريع التي تستضيفها المؤسسات، مع سلم المساهمة وقواعد السلوك، فقد خصصنا لها مقال من يدير المشروع مفتوح المصدر؟. والجدول التالي يجمع ما سبق:
| اللغة | المواصفة | التطبيق المرجعي أو الرئيسي | الحوكمة | طريقة الاقتراح | رخصة التطبيق الرئيسي |
|---|---|---|---|---|---|
| C | ISO/IEC 9899:2024 (C23) | لا يوجد مرجعي: GCC وClang وMSVC | لجنة ISO WG14 | أوراق اللجنة والتصويت | GCC: GPLv3، Clang: Apache 2.0 مع استثناء LLVM |
| C++ | ISO/IEC 14882:2024 (C++23) | لا يوجد مرجعي: GCC وClang وMSVC | لجنة ISO WG21 | أوراق اللجنة والتصويت | كما في C |
| JavaScript | ECMA-262 (ECMAScript 2026) | لا يوجد مرجعي: V8 وSpiderMonkey وJavaScriptCore | لجنة Ecma TC39 | مراحل TC39 من 0 إلى 4 | V8: BSD، Node.js: MIT |
| Java | JLS ومواصفة JVM عبر JSR 400 | OpenJDK | عملية JCP، وOpenJDK بقيادة Oracle | JEP داخل OpenJDK | GPLv2 مع استثناء Classpath |
| Python | The Python Language Reference | CPython | مجلس توجيه منتخب من خمسة أعضاء | PEP | PSF License |
| Go | The Go Programming Language Specification | gc | فريق Go في Google | Proposal Review | BSD |
| Rust | The Rust Reference، وFLS قيد التبني | rustc | مجلس القيادة والفرق | RFC | MIT أو Apache 2.0 |
| C# | ECMA-334 وECMA-335 | .NET | Microsoft، ومعيار في Ecma TC49 | dotnet/csharplang | MIT |
| PHP | لا توجد مواصفة مستقلة | php-src | تصويت المطورين | RFC بأغلبية الثلثين | رخصة PHP، وتنتقل إلى BSD-3-Clause |
| TypeScript | مؤرشفة منذ الإصدار 1.8 | tsc، والمترجم الجديد في Go منذ TypeScript 7 | Microsoft | Issues ومقترحات في GitHub | Apache 2.0 |
لماذا يهمك هذا كمطور أو كمدير سيرفر؟
قد يتساءل البعض: أنا أكتب الكود وأشغله، فما علاقتي باللجان والرخص؟ والإجابة أن هذه التفاصيل تظهر لك فجأة في أسوأ الأوقات: عند تدقيق التراخيص في شركتك، أو عند انتهاء دعم الإصدار الذي يعمل عليه نظامك، أو عندما ينتقل المشروع إلى سيرفر جديد بمترجم آخر. وفيما يلي أهم الحالات.
رخصة المترجم ليست رخصة كودك
الخطأ الشائع هو الظن بأن رخصة الأداة تنتقل إلى ما تنتجه، فيخاف البعض من بناء برنامج تجاري ب GCC لأن GCC برخصة GPL، أو من تشغيل Java لأن رخصة OpenJDK هي GPL. والحقيقة أن هذه الحالات محسوبة في الرخص نفسها، والصورة التالية تبين الطبقات الثلاث والحالات الثلاث الشائعة:

- البناء بمترجم GPL: المكتبات الصغيرة التي يضيفها GCC إلى برنامجك عند البناء لها استثناء خاص، والأسئلة الرسمية تقول إن هذه الاستثناءات موجودة دائماً لتسمح بتوزيع الكود الناتج من GCC بأي رخصة.
- تشغيل كودك على Runtime مفتوح: استثناء Classpath في OpenJDK ينص على أن ربط مكتبات Java بوحدات مستقلة لإنتاج برنامج يسمح بتوزيع الناتج بالشروط التي تختارها، وهذا الاستثناء هو الذي يجعل تطبيقات Java التجارية ممكنة.
- توزيع ال Runtime نفسه مع منتجك: هنا يجب أن تقرأ رخصة ال Runtime، فتوزيعات OpenJDK المجانية تسمح بذلك بشروط GPL مع الاستثناء، أما Oracle JDK فبشروط NFTC أو OTN بحسب الإصدار كما ذكرنا أعلاه.
أما الطبقة الوسطى، أي المكتبات التي تستوردها من npm أو PyPI أو Maven، فهي التي تحتاج انتباهك أكثر من المترجم، وقد شرحنا الفرق بين الرخص المتساهلة ورخص Copyleft وما تعنيه عند التوزيع في مقال البرمجيات مفتوحة المصدر وتراخيصها.
إصدارات الدعم الطويل وجداول الإصدار
كل تطبيق له جدول إصدارات خاص به، وعندما تختار إصداراً لنظام سوف يعمل سنوات فعليك أن تعرف متى ينتهي دعمه، والسبب أن الإصدار الذي انتهى دعمه لا يحصل على إصلاحات أمنية. والجداول الحالية من المصادر الرسمية هي:
- Java: إصدار جديد كل ستة أشهر، وإصدار LTS كل سنتين، فبعد JDK 21 جاء JDK 25 في سبتمبر 2025، وJDK 27 صدر في 15 سبتمبر 2026 وهو ليس LTS، والإصدار LTS القادم بحسب Oracle هو Java 29 في سبتمبر 2027. ومدة الدعم تختلف بحسب مورد التوزيعة، فهي ليست صفة في اللغة.
- Node.js: بحسب صفحة الإصدارات كانت الإصدارات الزوجية فقط تصبح LTS حتى Node.js 26، وابتداءً من Node.js 27 يصبح الإصدار سنوياً وكل إصدار رئيسي يتحول إلى LTS بعد ستة أشهر، ومدة الدعم الكلية نحو 30 شهراً. وتوصي الصفحة بألا تستخدم في الإنتاج إلا الإصدارات في مرحلة Active LTS أو Maintenance LTS.
- Python: بحسب PEP 602 إصدار جديد كل أكتوبر، يحصل على سنتين من الإصلاحات الكاملة ثم ثلاث سنوات من الإصلاحات الأمنية، أي خمس سنوات، وجدول Python 3.15 يحدد صدوره في 9 أكتوبر 2026.
- .NET: بحسب سياسة الدعم إصدار جديد كل نوفمبر، والإصدارات الزوجية LTS بدعم ثلاث سنوات، والفردية STS بدعم سنتين.
كيف تختار التوزيعة؟
عندما تكون اللغة واحدة والتوزيعات كثيرة كما في Java، فالسؤال ليس «أيها أسرع» لأنها مبنية من الكود نفسه، وإنما أسئلة تشغيلية:
- مدة الدعم Support Lifetime: كم سنة سوف يقدم المورد تحديثات أمنية لهذا الإصدار، وهل تكفي عمر مشروعك.
- الرخصة Licence: هل هي GPLv2 مع الاستثناء مثل Temurin وCorretto وMicrosoft Build، أم شروط خاصة مثل Oracle JDK، وهل تحتاج إعادة توزيع ال Runtime مع منتجك.
- اختبار التوافق TCK: هل اجتازت التوزيعة اختبارات التوافق مع مواصفة Java SE.
- المنصة Platform: هل تتوفر Docker Image رسمية ونسخ للمعمارية التي تستخدمها مثل ARM، ونسخ لمكتبة musl إذا كنت تستخدم Alpine.
- القرب من بيئتك Ecosystem Fit: إذا كان نظامك على AWS فقد تجد Corretto مثبتاً ومدعوماً في خدماتها، وإذا كان على Azure فقد تجد Microsoft Build، وإذا أردت توزيعة محايدة من مؤسسة غير ربحية فهناك Temurin.
والأهم من التوزيعة التي تختارها أن تثبت اختيارك في ملف واضح، مثل سطر FROM eclipse-temurin:25-jdk في ملف Dockerfile، حتى لا يعمل فريق التطوير بتوزيعة وسيرفر الإنتاج بأخرى دون أن يعلم أحد.
قابلية النقل والارتباط بمورد واحد
اكتب كودك على المواصفة وليس على التطبيق، وهذا يعني عملياً أن تتجنب الاعتماد على سلوك لم تضمنه المواصفة كما رأينا في ترتيب المعاملات، وأن تعرف متى تستخدم إضافة خاصة بمترجم معين، مثل إضافات GNU التي يفعلها GCC افتراضياً في الوضع gnu17. والسبب أن الكود الذي يعمل على تطبيق واحد فقط يربطك بمورده، فإذا تغيرت رخصته أو توقف دعمه أو أردت الانتقال إلى معمارية لا يدعمها، فسوف تجد نفسك أمام إعادة كتابة بدلاً من إعادة بناء.
والارتباط بمورد واحد Vendor Lock-in في اللغات له درجات: لغة لها معيار دولي وعدة تطبيقات مفتوحة مثل C وJavaScript هي الأقل خطراً، ثم لغة لها تطبيق مرجعي مفتوح المصدر برخصة واضحة وعدة موردين مثل Java وPython، ثم لغة تقودها شركة واحدة بتطبيق واحد، وحتى هذه تبقى آمنة نسبياً ما دام الكود مفتوحاً برخصة متساهلة، لأن المجتمع يستطيع الاستمرار في تطويره إذا تغيرت أولويات الشركة. لذلك لا تقيم لغة لمشروع طويل الأمد بسرعتها وشعبيتها فقط، وإنما أضف إلى الميزان من يملك القرار فيها ورخصة تطبيقها الرئيسي.
ويجدر التفريق أخيراً بين المكتبة القياسية Standard Library والنظام البيئي Ecosystem: المكتبة القياسية جزء من المواصفة أو من التطبيق ويحكمها من يحكم اللغة، أما الحزم التي تنزلها من npm أو PyPI أو crates.io فلكل منها مطور ورخصة وجودة مختلفة، ولا يضمنها أحد من لجان اللغة، وهذا سبب أن أكثر المشكلات الأمنية والقانونية تأتي من الحزم وليس من اللغة نفسها.
تدريب عملي
- غير البرنامج
order.cليستدعيsay(1) + say(2)داخل تعبير واحد، وابنه ب GCC وClang، ثم قارن الترتيب، ثم جرب الخيار-O2وانظر هل يتغير. - شغل
java -versionعلى سيرفراتك أو داخل Docker Images التي تستخدمها، واكتب في جدول اسم المورد ورقم الإصدار، ثم ابحث في موقع كل مورد عن تاريخ انتهاء دعم هذا الإصدار.
وعند الانتهاء احذف ال Docker Images التي نزلناها إذا لم تعد تحتاجها:
docker rmi eclipse-temurin:25-jdk amazoncorretto:25 mcr.microsoft.com/openjdk/jdk:25-ubuntuالخلاصة
وصلنا لنهاية الموضوع، وأهم ما فيه:
- اللغة مواصفة أو تطبيق مرجعي، والتطبيقات برامج مستقلة لكل منها مورد ورخصة وجدول دعم، فالسرعة والرخصة والأخطاء صفات في التطبيق وليست في اللغة.
- المواصفات تترك بعض السلوك للتطبيق عمداً، وفي تجربتنا حسب GCC وClang معاملات الدالة بترتيب معاكس، وكلاهما صحيح.
- صدور المعيار لا يعني دعمه، فقد رفض GCC 13 الخيار
-std=c23بينما قبله Clang 18، وgccgo لا يدعم Generics حتى الآن. - JavaScript تتطور عبر مراحل TC39، ولا تدخل الميزة إلا بعد تطبيقين متوافقين، والطبعة الأخيرة ECMAScript 2026.
- Java مواصفة عبر JCP، وتطبيق مرجعي OpenJDK برخصة GPLv2 مع استثناء Classpath، وتوزيعات مجانية مثل Temurin وCorretto وMicrosoft Build، أما Oracle JDK فرخصته NFTC لفترة محددة لكل إصدار ثم OTN.
- القرار في اللغات بيد واحد من أربعة: شخص، أو مجلس منتخب، أو شركة، أو لجنة معايير، والمؤسسات غالباً تمول ولا تصمم.
- رخصة المترجم أو ال Runtime لا تنتقل إلى كودك في الحالات العادية، والذي يحتاج انتباهك هو توزيع ال Runtime مع منتجك ورخص المكتبات التي تستوردها.
- اختر الإصدار بحسب جدول الدعم، وثبت التوزيعة في ملفات البناء، واكتب على المواصفة وليس على تطبيق واحد.
دليلأنماط البرمجة وأنظمة الأنواع: لماذا تختلف اللغات؟نحل مسألة واحدة بعدة أساليب برمجة، ونرى هل تكتشف اللغة أخطاءك قبل التشغيل أم بعده، وماذا يعني ذلك عند اختيار لغة لمشروعك.
دليلقصص لغات البرمجة ومن صنعها، من Fortran إلى Rustمن صنع اللغات التي نكتب بها كل يوم، وما المشكلة التي دفعته إلى ذلك، وكيف تشرح قصة كل لغة قراراتها.
دليلما هي البرمجيات مفتوحة المصدر؟ القصة وأشهر الرخصكيف بدأت البرمجيات الحرة والمفتوحة، وما الفرق بين الحر والمجاني، وكيف تعرف ما تسمح به رخصة أي مشروع قبل أن تبني عليه.
دليلماذا يحدث عندما تشغل برنامج Hello World؟نتتبع برنامج C صغيراً من المحرر إلى الشاشة، فترى كل طبقة يمر بها في الجهاز حتى تظهر الجملة أمامك.سجل التحديثات
- أكتوبر 2026: كتابة المقال، وتنفيذ التجارب داخل Containers على Docker Engine 29.8.0: GCC 13.3.0 وClang 18.1.3 على Ubuntu 24.04، وjava -version من Eclipse Temurin وAmazon Corretto وMicrosoft Build of OpenJDK بالإصدار 25.0.4.1.
- أكتوبر 2026: إضافة رابط في قسم الحوكمة إلى مقال حوكمة المشاريع مفتوحة المصدر والمساهمة فيها.