لغات النطاق المحدد (DSL): "الكود الذي لا يشبه الكود" في عالم الخلفية
مقدمة
في حالة واقعية، قام المهندس Armin ببناء خدمة بنية تحتية في شركته الجديدة باستخدام الذكاء الاصطناعي، بإجمالي حوالي 40,000 سطر من الكود (Go + YAML + Pulumi + كود SDK اللاصق)، حيث تم إنشاء أكثر من 90% منها بواسطة الذكاء الاصطناعي. ظهرت في هذه الحالة العديد من المصطلحات غير المألوفة للمبتدئين: YAML، Pulumi، HCL، Lua، كود SDK اللاصق… وهي ليست Python ولا JavaScript، لكنها موجودة في كل مكان في مشاريع الخلفية. ستقدم هذه المقالة هذه التقنيات بشكل منهجي من منظور موحد — لغات النطاق المحدد (DSL).
أهداف التعلم لهذه المقالة
في تطوير الخلفية، بالإضافة إلى منطق الأعمال المكتوب بلغات البرمجة العامة (Python، Go، Java، إلخ)، هناك أيضًا كمية كبيرة من الملفات والأكواد ذات الأغراض المختلفة، والقواعد المختلفة، ولكن لا تنتمي إلى لغات البرمجة العامة. لها مفهوم موحد أعلى: DSL (Domain-Specific Language، لغة النطاق المحدد).
بعد دراسة هذه المقالة، ستكون قادرًا على:
- فهم الفرق الجوهري بين DSL ولغات البرمجة العامة (GPL)
- إتقان نظام تصنيف DSL: صيغ تسلسل البيانات، لغات البرمجة النصية المضمنة، لغات تعريف البنية التحتية
- التمييز بين سيناريوهات استخدام XML، JSON، YAML، TOML، CSV، Protobuf وغيرها من صيغ البيانات
- فهم الغرض التصميمي للغات البرمجة النصية المضمنة مثل Lua
- شرح مبدأ واختلاف Terraform (HCL) و Pulumi
- فهم مواصفات OpenAPI ومبدأ عمل التوليد التلقائي لـ SDK
- تحديد أنواع الأكواد المناسبة للتوليد بواسطة الذكاء الاصطناعي
| الفصل | الموضوع | المفاهيم الأساسية |
|---|---|---|
| الفصل 1 | مقدمة عامة عن DSL | تعريف DSL مقابل GPL، نظام التصنيف والصورة الشاملة |
| الفصل 2 | صيغ تسلسل البيانات | XML، JSON، YAML، TOML، CSV، Protobuf وغيرها |
| الفصل 3 | لغات البرمجة النصية المضمنة | فلسفة تصميم Lua وغيرها من اللغات وتطبيقاتها النموذجية |
| الفصل 4 | البنية التحتية ككود | مبدأ Terraform (HCL) و Pulumi والمقارنة بينهما |
| الفصل 5 | الكود اللاصق وتوليد SDK | مواصفات OpenAPI والتوليد التلقائي لكود العميل |
| الفصل 6 | علاقة الذكاء الاصطناعي بـ DSL | لماذا يتفوق الذكاء الاصطناعي بشكل خاص في توليد كود DSL |
1. مقدمة عامة عن DSL: عالم آخر خارج اللغات العامة
1.1 ما هي DSL؟
DSL (Domain-Specific Language، لغة النطاق المحدد) هي لغة مصممة لمجال أو مهمة محددة. في مقابلها تأتي GPL (General-Purpose Language، لغة البرمجة العامة)، مثل Python، Java، Go، C++ وغيرها — وهي مصممة لحل أي مشكلة حسابية.
الفروق الجوهرية بين الاثنين:
| البعد | GPL (لغة البرمجة العامة) | DSL (لغة النطاق المحدد) |
|---|---|---|
| هدف التصميم | حل أي مشكلة حسابية | حل مشكلة في مجال محدد |
| نطاق التعبير | تورينج كاملة، نظريًا يمكنها حساب أي شيء | عادةً ما يكون نطاق التعبير محدودًا عن قصد |
| تكلفة التعلم | مرتفعة، تتطلب فهم نظام اللغة الكامل | منخفضة، تحتاج فقط لفهم مفاهيم المجال |
| أمثلة نموذجية | Python، Java، Go، C++، JavaScript | SQL، HTML/CSS، التعابير النمطية، YAML، HCL |
أنت في الواقع تستخدم DSL منذ فترة طويلة:
- SQL هي DSL لمجال استعلام قواعد البيانات — تستخدم
SELECT * FROM users WHERE age > 18للاستعلام عن البيانات، بدلاً من كتابة منطق تكرار يدوي بلغة Python - HTML/CSS هي DSL لمجال هيكل وأنماط صفحات الويب — تصف الصفحة باستخدام الوسوم والخصائص، بدلاً من التعامل مع البكسلات بلغة C++
- التعابير النمطية هي DSL لمجال مطابقة أنماط النصوص — تستخدم
\d{3}-\d{4}لمطابقة رقم الهاتف، بدلاً من كتابة حلقة مقارنة حرفية يدوية
1.2 تصنيف DSL
يمكن تقسيم DSL إلى فئتين رئيسيتين بناءً على "ما إذا كانت تورينج كاملة":
DSL الخارجية (External DSL)
تمتلك قواعد ومحللًا مستقلين، ولا تعتمد على أي لغة برمجة عامة. تتم معالجة الكود الذي يكتبه المستخدم بواسطة مفسر أو مترجم مخصص.
- نوع وصف البيانات البحت: JSON، YAML، XML، TOML، CSV، Protobuf (لا تحتوي على أي منطق)
- نوع الاستعلام/التشغيل: SQL، GraphQL، التعابير النمطية (قدرة منطقية محدودة)
- نوع نمذجة المجال: HCL (Terraform)، Dockerfile، قواعد تكوين Nginx (وصف تصريحي لحالة مجال محدد)
DSL الداخلية (Internal DSL / Embedded DSL)
تتطفل داخل لغة برمجة عامة، مستفيدة من قواعد اللغة المضيفة لبناء تعبيرات خاصة بالمجال. الكود نفسه هو كود قانوني للغة المضيفة، لكنه يُقرأ كلغة مخصصة.
- Pulumi (مكتوب بلغة TypeScript/Python/Go، لكن واجهة API مصممة لتبدو كتكوين تصريحي)
- تعريف المسارات في Ruby on Rails (
get '/users', to: 'users#index'، كود Ruby قانوني، لكنه يُقرأ كتكوين) - قواعد التأكيد في أطر الاختبار (
expect(value).toBe(42)، JavaScript قانوني، لكنه يُقرأ كلغة طبيعية)
1.3 الصورة الشاملة لـ DSL في مشاريع الخلفية
في مشروع خلفية نموذجي، ستواجه الفئات التالية من DSL:
DSL في مشاريع الخلفية
├── صيغ تسلسل البيانات (وصف هيكل البيانات)
│ ├── الصيغ النصية: JSON، YAML، XML، TOML، CSV، INI
│ └── الصيغ الثنائية: Protobuf، MessagePack، Avro، BSON
├── لغات البرمجة النصية المضمنة (طبقة تكوين قابلة للبرمجة)
│ ├── Lua (محركات الألعاب، Nginx، Redis)
│ ├── GDScript (محرك Godot)
│ └── Jsonnet (توليد قوالب التكوين)
├── DSL البنية التحتية والعمليات (وصف تصريحي لحالة النظام)
│ ├── HCL (Terraform)
│ ├── Dockerfile / Docker Compose YAML
│ └── قواعد تكوين Nginx / Apache
└── لغات وصف الواجهات (وصف عقد API)
├── OpenAPI / Swagger
├── Protocol Buffers (ملفات .proto)
└── GraphQL Schemaبعد فهم هذه الصورة الشاملة، ستتوسع الفصول التالية في كل فرع على حدة.
2. صيغ تسلسل البيانات: وصف البيانات المهيكلة بالنص
2.1 ما هو تسلسل البيانات؟
التسلسل (Serialization) هو عملية تحويل هياكل البيانات في الذاكرة (الكائنات، القواميس، المصفوفات، إلخ) إلى تيار نصي أو بايتي يمكن تخزينه أو نقله. والعكس، إعادة تحويل التيار النصي أو البايتي إلى هياكل بيانات في الذاكرة، يسمى إلغاء التسلسل (Deserialization).
صيغ تسلسل البيانات هي الفئة الأساسية في DSL — تنتمي إلى DSL الخارجية من نوع وصف البيانات البحت، لا تمتلك أي قدرة منطقية، وتقتصر مسؤوليتها على الوصف الثابت لـ "ما هي القيمة".
2.2 لماذا نحتاج إلى هذه الصيغ؟
افترض أنك طورت خدمة خلفية، وعنوان قاعدة البيانات هو localhost:5432. إذا قمت بتضمين هذا العنوان مباشرة في الكود المصدري، فلن يكون هناك مشكلة في التطوير المحلي، لكن عند النشر إلى بيئة الإنتاج، يتغير عنوان قاعدة البيانات إلى db.prod.company.com:5432، وستحتاج إلى تعديل الكود المصدري وإعادة الترجمة.
الممارسة العامة في الهندسة هي: فصل المعاملات القابلة للتغيير عن الكود، وتخزينها في ملفات تكوين مستقلة. يقرأ البرنامج ملف التكوين عند بدء التشغيل، ويتخذ القرارات بناءً على القيم الموجودة فيه.
بالإضافة إلى التكوين، تُستخدم صيغ تسلسل البيانات على نطاق واسع في: تبادل البيانات بين الأنظمة (طلبات/استجابات API)، التخزين المستمر للبيانات، التواصل بين اللغات المختلفة وغيرها من السيناريوهات.
2.3 الصيغ النصية القابلة للقراءة البشرية
فيما يلي صيغ التسلسل النصية الأكثر شيوعًا في الهندسة، مقدمة بالترتيب التاريخي.
INI
أقدم صيغة تكوين، نشأت من أنظمة Windows. هيكل بسيط، يتكون من أقسام (section) وأزواج مفتاح-قيمة:
[database]
host = localhost
port = 5432
[server]
debug = trueالميزة هي قابلية القراءة العالية. القيد هو عدم دعم الهياكل المتداخلة وأنواع المصفوفات، وعدم القدرة على التعبير عن التكوينات المعقدة. تظهر حاليًا بشكل رئيسي في الأنظمة القديمة وبعض تكوينات Linux (مثل php.ini، my.cnf).
CSV
CSV (Comma-Separated Values، القيم المفصولة بفواصل) هي أبسط صيغة للبيانات الجدولية:
name,age,city
Alice,30,Beijing
Bob,25,Shanghaiكل سطر هو سجل، والحقول مفصولة بفواصل. يُستخدم CSV على نطاق واسع في استيراد وتصدير البيانات، تبادل جداول البيانات، وخطوط أنابيب تحليل البيانات. قيده هو أنه يمكنه فقط التعبير عن جداول ثنائية الأبعاد مسطحة، ولا يدعم الهياكل المتداخلة، ويفتقر إلى معلومات النوع (جميع القيم سلاسل نصية).
XML
XML (eXtensible Markup Language، لغة الترميز القابلة للتوسع) وُلدت في عام 1998، وكانت المعيار السائد لتبادل البيانات:
<?xml version="1.0" encoding="UTF-8"?>
<config>
<database>
<host>localhost</host>
<port>5432</port>
</database>
<server>
<debug>true</debug>
<allowed_origins>
<origin>https://example.com</origin>
<origin>https://app.example.com</origin>
</allowed_origins>
</server>
</config>قوة تعبير XML عالية جدًا، وتدعم التداخل، الخصائص، مساحات الأسماء، التحقق بواسطة Schema وغيرها من الميزات المتقدمة. لكن قواعدها مطولة — الكمية الكبيرة من وسوم الفتح والإغلاق تؤدي إلى انخفاض نسبة الإشارة إلى الضوضاء، وتجربة الكتابة والقراءة اليدوية سيئة.
لا تزال XML مستخدمة على نطاق واسع في المجالات التالية:
- نظام Java البيئي (
pom.xmlلـ Maven، تكوين Spring، ملفات تخطيط Android) - خدمات الويب المؤسسية (بروتوكول SOAP)
- صيغ مستندات المكتب (
.docx،.xlsxهي في الأساس مجموعات من ملفات XML مضغوطة بـ ZIP) - خلاصات RSS/Atom، رسوميات SVG المتجهة
JSON
JSON (JavaScript Object Notation) وُلد في عام 2001، وسرعان ما حل محل XML كمعيار فعلي لتبادل البيانات في واجهات Web API بسبب بساطته:
{
"database": {
"host": "localhost",
"port": 5432
},
"server": {
"debug": true
}
}الميزة هي الهيكل الواضح، وتقريبًا جميع لغات البرمجة لديها دعم تحليل أصلي. العيب الرئيسي هو عدم دعم التعليقات، وكثرة الأقواس وعلامات التنصيص تجعل الكتابة اليدوية عرضة للأخطاء. JSON هو أيضًا الصيغة القياسية لتكوين مشاريع الواجهة الأمامية (package.json، tsconfig.json).
YAML
YAML (YAML Ain't Markup Language) وُلد أيضًا في عام 2001، وهو حاليًا صيغة التكوين الأكثر استخدامًا في مجالات الخلفية و DevOps. أدوات مثل Docker Compose، Kubernetes، GitHub Actions تعتمد جميعها على YAML:
# تكوين قاعدة البيانات
database:
host: localhost
port: 5432
# تكوين الخادم
server:
debug: true
allowed_origins:
- https://example.com
- https://app.example.comالميزة هي دعم التعليقات، القواعد المختصرة، والقدرة على التعبير عن الهياكل المتداخلة المعقدة. العيب هو الاعتماد على المسافة البادئة لتمثيل العلاقات الهرمية، حيث تؤدي أخطاء المسافة البادئة إلى فشل التحليل، وهذه هي المشكلة الأكثر شيوعًا التي يواجهها المبتدئون.
ملاحظة: الاسم الكامل لـ YAML "YAML Ain't Markup Language" هو اختصار تعاودي.
TOML
TOML (Tom's Obvious Minimal Language) وُلد في عام 2013، وتم تبنيه من قبل مدير الحزم Cargo في Rust و pyproject.toml في Python:
[database]
host = "localhost"
port = 5432
[server]
debug = true
allowed_origins = [
"https://example.com",
"https://app.example.com"
]تحاول TOML الجمع بين بساطة INI وقوة تعبير YAML، مع تجنب المشاكل الناتجة عن حساسية المسافة البادئة.
2.4 صيغ التسلسل الثنائية
الصيغ المذكورة أعلاه كلها نصوص قابلة للقراءة البشرية. في السيناريوهات التي تتطلب أداءً وحجمًا أعلى، توجد فئة من صيغ التسلسل الثنائية — تضحي بقابلية القراءة مقابل حجم أصغر وسرعة تحليل أسرع.
| الصيغة | المطور | الخصائص | سيناريوهات الاستخدام النموذجية |
|---|---|---|---|
| Protocol Buffers (Protobuf) | تتطلب تعريف ملف Schema .proto مسبقًا، كتابة قوية، حجم صغير جدًا | اتصال gRPC، خدمات Google الداخلية، الخدمات المصغرة عالية الأداء | |
| MessagePack | المجتمع | نسخة ثنائية مشابهة لـ JSON، لا تتطلب Schema | الترميز الداخلي لـ Redis، اتصال عالي الأداء بين اللغات |
| Avro | Apache | يدعم تطور Schema، مناسب لسيناريوهات البيانات الضخمة | تسلسل البيانات في نظام Hadoop / Kafka البيئي |
| BSON | MongoDB | امتداد ثنائي لـ JSON، يدعم أنواع بيانات أكثر | صيغة التخزين الداخلي لقاعدة بيانات MongoDB |
بأخذ Protocol Buffers كمثال، يجب أولاً تعريف Schema:
// user.proto
syntax = "proto3";
message User {
string name = 1;
int32 age = 2;
string email = 3;
}ثم من خلال المترجم (protoc) يتم توليد كود التسلسل/إلغاء التسلسل لكل لغة تلقائيًا. هذا النمط "تعريف Schema أولاً، ثم توليد الكود" يتوافق مع فكرة توليد OpenAPI SDK التي سيتم تقديمها لاحقًا.
2.5 مقارنة شاملة
| الصيغة | النوع | سنة النشأة | قابلية القراءة | دعم التعليقات | سيناريوهات الاستخدام النموذجية |
|---|---|---|---|---|---|
| INI | نصية | 1980s | عالية | ✅ | تكوين النظام، المشاريع القديمة |
| CSV | نصية | 1972 | عالية | ❌ | استيراد وتصدير البيانات، تبادل الجداول |
| XML | نصية | 1998 | متوسطة | ✅ | نظام Java البيئي، خدمات الويب المؤسسية، صيغ المستندات |
| JSON | نصية | 2001 | عالية | ❌ | تبادل بيانات Web API، تكوين الواجهة الأمامية |
| YAML | نصية | 2001 | عالية | ✅ | Docker، K8s، CI/CD، تكوين خدمات الخلفية |
| TOML | نصية | 2013 | عالية | ✅ | تكوين مشاريع Rust / Python |
| Protobuf | ثنائية | 2008 | لا يوجد | — | gRPC، اتصال الخدمات المصغرة عالية الأداء |
| MessagePack | ثنائية | 2008 | لا يوجد | — | اتصال عالي الأداء بين اللغات |
| Avro | ثنائية | 2009 | لا يوجد | — | خطوط أنابيب البيانات الضخمة Hadoop / Kafka |
| BSON | ثنائية | 2009 | لا يوجد | — | التخزين الداخلي لـ MongoDB |
النقطة الأساسية: الوظيفة الجوهرية لجميع هذه الصيغ متطابقة — تحويل البيانات المهيكلة إلى شكل قابل للتخزين والنقل. الصيغ النصية تعطي الأولوية لقابلية القراءة البشرية وسهولة التحرير؛ الصيغ الثنائية تعطي الأولوية لأداء التحليل وحجم النقل. يعتمد اختيار الصيغة المناسبة على مقايضة المتطلبات في السيناريو المحدد.
3. لغات البرمجة النصية المضمنة: طبقة تكوين قابلة للبرمجة
3.1 تعريف المفهوم
لغات مثل Python، JavaScript، Go هي لغات برمجة عامة (General-Purpose Language)، يمكنها العمل بشكل مستقل وبناء تطبيقات كاملة.
على النقيض من ذلك، هناك فئة من اللغات مصممة خصيصًا لتضمينها في برامج مضيفة أخرى، لتوفير قدرات توسعة قابلة للبرمجة للبرنامج المضيف. تسمى هذه الفئة لغات البرمجة النصية المضمنة (Embedded Scripting Language).
المشكلة الأساسية التي تحلها هي: عندما تكون قوة التعبير لملفات التكوين الثابتة (YAML/JSON) غير كافية، وتحتاج إلى إدخال منطق مثل الشروط والحلقات، كيف يمكن تحقيق سلوك ديناميكي دون تعديل الكود المصدري للبرنامج المضيف.
3.2 Lua: أكثر لغات البرمجة النصية المضمنة تمثيلاً
Lua (تعني "القمر" باللغة البرتغالية) هي لغة برمجة نصية خفيفة الوزن للغاية، حجم المفسر المترجم بالكامل لا يتجاوز بضع مئات من الكيلوبايتات. هدفها التصميمي ليس العمل بشكل مستقل، بل أن تكون طبقة توسعة قابلة للتضمين.
سيناريوهات التطبيق النموذجية لـ Lua:
محركات الألعاب: نظام الإضافات في لعبة "World of Warcraft"، وسكربتات الألعاب في "Roblox" تستخدم Lua. محرك اللعبة مطبق بلغة C/C++ للتعامل مع العرض والحسابات الفيزيائية الأساسية، بينما يتم تفويض منطق المستويات وحوارات الشخصيات وغيرها من الأجزاء المتغيرة بشكل متكرر إلى سكربتات Lua. بهذه الطريقة، يمكن للمصممين تعديل محتوى اللعبة دون الحاجة إلى إعادة ترجمة المحرك.
خوادم الويب: يقوم OpenResty بتضمين Lua داخل Nginx، مما يسمح لمسؤولي العمليات بتنفيذ منطق تصفية الطلبات، تحديد المعدل، المصادقة وغيرها باستخدام سكربتات Lua، دون الحاجة إلى تعديل كود Nginx المصدري بلغة C.
قواعد البيانات: يدعم Redis إرسال سكربتات Lua إلى الخادم للتنفيذ، لتحقيق عمليات مركبة تتطلب ضمان الذرية (مثل "القراءة ثم الكتابة").
فيما يلي مثال لسكربت Lua مضمن في Nginx (OpenResty):
-- الوظيفة: مصادقة token لمسار /api/secret
local uri = ngx.var.uri
local token = ngx.req.get_headers()["Authorization"]
if uri == "/api/secret" and token ~= "Bearer my-secret-token" then
ngx.status = 403
ngx.say("Access denied")
return ngx.exit(403)
end3.3 لغات برمجة نصية مضمنة أخرى
| اللغة | البيئة المضيفة | الاستخدامات النموذجية |
|---|---|---|
| Lua | محركات الألعاب، Nginx (OpenResty)، Redis | منطق الألعاب، سياسات البوابة، عمليات التخزين المؤقت |
| VimScript / Lua | محرر Vim / Neovim | تطوير إضافات المحرر |
| Emacs Lisp | محرر Emacs | تخصيص سلوك المحرر |
| GDScript | محرك ألعاب Godot | سكربتات منطق الألعاب |
| Jsonnet | نظام Kubernetes البيئي / أدوات توليد التكوين | توليد كميات كبيرة من تكوينات JSON/YAML المتشابهة باستخدام القوالب |
النقطة الأساسية: لغات البرمجة النصية المضمنة في تصنيف DSL تنتمي إلى المنطقة الحدودية بين DSL الداخلية وDSL الخارجية — إنها لغات مستقلة (لها قواعدها ومفسرها الخاص)، لكن هدفها التصميمي هو التضمين في برنامج مضيف للتشغيل، وليس بناء تطبيقات مستقلة. إنها تملأ الفجوة بين "ملفات التكوين الثابتة" (DSL وصف البيانات البحت) و "لغات البرمجة العامة" (GPL): عندما يحتاج التكوين إلى التعبير عن منطق (شروط، حلقات، استدعاء دوال)، فإن تضمين لغة برمجة نصية خفيفة الوزن هو الحل الهندسي القياسي.
4. البنية التحتية ككود (Infrastructure as Code)
4.1 ما هي "البنية التحتية"
في هندسة الخلفية، تشير "البنية التحتية" (Infrastructure) إلى الموارد الأساسية التي تعتمد عليها التطبيقات للتشغيل:
- موارد الحوسبة: الخوادم (أجهزة افتراضية أو حاويات)
- تخزين البيانات: نسخ قواعد البيانات، حاويات تخزين الكائنات
- الشبكة: قواعد جدار الحماية، موازنات الحمل، تكوين DNS
- البرمجيات الوسيطة: طوابير الرسائل، مجموعات التخزين المؤقت
في عصر الحوسبة السحابية، يتم إنشاء وإدارة هذه الموارد من خلال لوحات تحكم مزودي الخدمات السحابية (مثل AWS، Alibaba Cloud، Tencent Cloud) بواجهة رسومية.
4.2 قيود الإدارة اليدوية
الإدارة من خلال لوحة التحكم اليدوية ممكنة في المشاريع صغيرة الحجم، لكن مع نمو حجم المشروع، تظهر المشاكل التالية:
- غير قابلة للتكرار: خطوات التشغيل غير مسجلة، ولا يمكن إعادة إنتاج نفس البيئة بدقة
- غير قابلة للتدقيق: لا يمكن تتبع "من عدل ماذا ومتى"
- غير قابلة للتعاون: عملية التشغيل لا يمكن إدراجها في نظام التحكم بالإصدارات، ولا يمكن إجراء مراجعة للكود
- عرضة للأخطاء: التشغيل اليدوي في بيئة الإنتاج يحمل مخاطر الأخطاء التشغيلية
الفكرة الأساسية لـ البنية التحتية ككود (Infrastructure as Code، اختصارًا IaC) هي: استخدام الكود لتعريف موارد البنية التحتية بشكل تصريحي، مما يمنحها قدرات التحكم بالإصدارات، التنفيذ الآلي، والنشر القابل للتكرار.
4.3 Terraform
Terraform هي أداة IaC الأكثر استخدامًا حاليًا، طورتها شركة HashiCorp. تستخدم لغة HCL (HashiCorp Configuration Language) المخصصة.
تتبنى Terraform نموذجًا تصريحيًا: يصف المستخدم الحالة النهائية المرغوبة، ويقوم Terraform تلقائيًا بحساب العمليات المطلوبة للانتقال من الحالة الحالية إلى الحالة المستهدفة.
# تعريف خادم سحابي
resource "aws_instance" "my_server" {
ami = "ami-0c55b159cbfafe1f0" # صورة نظام التشغيل
instance_type = "t3.micro" # مواصفات النسخة
tags = {
Name = "my-first-server"
}
}
# تعريف نسخة قاعدة بيانات PostgreSQL
resource "aws_db_instance" "my_database" {
engine = "postgres"
instance_class = "db.t3.micro"
username = "admin"
password = "please-use-secrets-manager"
}سير التنفيذ:
terraform plan # معاينة التغييرات التي سيتم تنفيذها
terraform apply # تأكيد وتنفيذ، إنشاء الموارد تلقائيًا في المنصة السحابية4.4 Pulumi
تقدم Pulumi نهجًا آخر: استخدام لغات البرمجة العامة مباشرة (TypeScript، Python، Go، إلخ) لتعريف البنية التحتية، بدلاً من تعلم قواعد HCL المخصصة.
نفس تعريف الخادم، معبرًا عنه بـ Pulumi + TypeScript:
import * as aws from "@pulumi/aws";
const server = new aws.ec2.Instance("my-server", {
ami: "ami-0c55b159cbfafe1f0",
instanceType: "t3.micro",
tags: { Name: "my-first-server" },
});
const bucket = new aws.s3.Bucket("my-bucket", {
acl: "private",
});
export const serverIp = server.publicIp;نظرًا لاستخدام لغات البرمجة العامة، يمكن للمطورين الاستفادة من ميزات اللغة مثل الحلقات، الشروط، والتجريدات الوظيفية للتعامل مع منطق البنية التحتية المعقد.
4.5 مقارنة بين Terraform و Pulumi
| البعد | Terraform | Pulumi |
|---|---|---|
| اللغة | HCL (لغة مخصصة) | TypeScript / Python / Go وغيرها من اللغات العامة |
| تكلفة التعلم | تحتاج إلى تعلم قواعد HCL | استخدام لغة برمجة متقنة بالفعل، تكلفة تعلم أقل |
| النظام البيئي المجتمعي | ناضج جدًا، يغطي تقريبًا جميع مزودي الخدمات السحابية | ينمو بسرعة، لكنه أصغر حجمًا من Terraform |
| السيناريوهات المناسبة | إدارة البنية التحتية الموحدة بقيادة فريق العمليات | مشاريع بقيادة المطورين، سيناريوهات تحتاج إلى منطق معقد |
| ملاءمة توليد كود الذكاء الاصطناعي | عالية (أنماط ثابتة) | عالية جدًا (هي في جوهرها كود بلغة برمجة عامة) |
النقطة الأساسية: HCL في أدوات IaC هي DSL خارجية نموذجية — لها قواعد ومحلل مستقلان، مصممة خصيصًا للوصف التصريحي لحالة البنية التحتية. بينما تتبنى Pulumi استراتيجية DSL الداخلية — استخدام قواعد لغة البرمجة العامة للتعبير عن مفاهيم خاصة بالمجال. كلاهما لهما نفس الهدف (تحويل إدارة البنية التحتية من التشغيل اليدوي إلى التشغيل بالكود)، لكن بمسارات مختلفة (لغة مخصصة مقابل لغة عامة). يمكن إدراج الكود في نظام التحكم بالإصدارات Git، ومراجعته من قبل الفريق، وتنفيذه آليًا والتراجع عنه.
5. الكود اللاصق وتوليد SDK التلقائي
5.1 ما هو الكود اللاصق
في هندسة البرمجيات، يشير الكود اللاصق (Glue Code) إلى الكود الذي لا يحتوي في حد ذاته على منطق أعمال، ويستخدم فقط لربط نظامين أو وحدتين.
يشمل الكود اللاصق النموذجي:
- كود طلبات HTTP المكتوب عندما تستدعي الواجهة الأمامية API الخلفية (تجميع URL، إعداد رؤوس الطلب، تحليل الاستجابة)
- كود عميل HTTP المكتوب عندما تستدعي الخدمة الخلفية A واجهة الخدمة B
- كود تكييف الواجهات بين لغات البرمجة المختلفة
سمة هذا النوع من الكود هي: متكرر بدرجة عالية، ذو أنماط ثابتة، لكن لا يمكن حذفه.
5.2 مواصفات OpenAPI والتوليد التلقائي للكود
بما أن الكود اللاصق يتميز بدرجة عالية من النمطية، فإن الحل الهندسي هو: أولاً وصف واجهة API بصيغة قياسية، ثم استخدام أدوات لتوليد كود العميل تلقائيًا.
مواصفات OpenAPI (المعروفة سابقًا باسم Swagger) هي المعيار الصناعي لوصف REST API. تستخدم صيغة YAML أو JSON، لتعريف مسارات API، المعاملات، جسم الطلب وهيكل الاستجابة بدقة:
openapi: 3.0.0
info:
title: API خدمة البريد
version: 1.0.0
paths:
/emails:
post:
summary: إرسال بريد إلكتروني
requestBody:
content:
application/json:
schema:
type: object
properties:
to:
type: string
example: "user@example.com"
subject:
type: string
body:
type: string
responses:
'200':
description: تم الإرسال بنجاحبناءً على ملف المواصفات هذا، يمكن استخدام أدوات مثل openapi-generator لتوليد SDK عميل بلغات متعددة تلقائيًا:
- Python:
client.emails.send(to="user@example.com", subject="Hi", body="Hello") - TypeScript:
client.emails.send({ to: "user@example.com", subject: "Hi", body: "Hello" }) - Go:
client.Emails.Send(ctx, &SendEmailRequest{To: "user@example.com", ...})
يقوم SDK المُنشأ بتغليف جميع تفاصيل طلب HTTP، ولا يحتاج المستدعي إلى الاهتمام بمسار URL، طريقة الطلب، صيغة التسلسل وغيرها من التفاصيل منخفضة المستوى.
5.3 إعادة فهم حالة Armin
بالعودة إلى الحالة في بداية المقال، يمكننا الآن فهم كل مكون بدقة:
| المكون | الطبيعة | الوصف |
|---|---|---|
| Go | كود منطق الأعمال | تنفيذ الوظائف الأساسية لخدمة البريد الإلكتروني |
| YAML | ملفات التكوين | تكوين الخدمة، تعريف خط أنابيب CI/CD، ملف مواصفات OpenAPI |
| Pulumi | كود البنية التحتية | تعريف الموارد السحابية (خوادم، قواعد بيانات، شبكة) باستخدام Go/TypeScript |
| كود SDK اللاصق | مكتبة عميل مولدة تلقائيًا | SDK لـ Python و TypeScript مولدة تلقائيًا من مواصفات OpenAPI |
من بينها، تكوينات YAML، تعريفات موارد Pulumi، وكود SDK اللاصق — هذه الفئات الثلاث جميعها تنتمي إلى أكواد ذات أنماط عالية، مقيدة بمواصفات واضحة، وهذا هو المجال الذي تكون فيه قدرة توليد الكود بالذكاء الاصطناعي في أقوى حالاتها. لذلك فإن "90% من 40,000 سطر كود تم توليدها بواسطة الذكاء الاصطناعي" أمر معقول.
6. علاقة الذكاء الاصطناعي بـ DSL
6.1 تحليل ملاءمة توليد الكود بالذكاء الاصطناعي
| بعد الخاصية | مناسب لتوليد الذكاء الاصطناعي | غير مناسب لتوليد الذكاء الاصطناعي |
|---|---|---|
| درجة النمطية | متكرر بدرجة عالية، يوجد قالب ثابت | يحتاج إلى تصميم إبداعي، لا يوجد سابقة |
| القيود المعيارية | يوجد schema أو قواعد نحوية واضحة | متطلبات غامضة، حدود غير واضحة |
| الاعتماد على السياق | مكتفٍ ذاتيًا محليًا، التعريف الواحد لا يعتمد على فهم شامل | يحتاج إلى فهم القصد المعماري للنظام بأكمله |
| قابلية التحقق | يمكن التحقق منه تلقائيًا بالأدوات (مثل terraform validate) | يعتمد فقط على الحكم البشري لمعقولية التصميم |
الفئات الأربع من التقنيات المقدمة في هذه المقالة — ملفات التكوين، السكربتات المضمنة، كود IaC، كود SDK اللاصق — جميعها تمتلك خصائص العمود الأيسر. هذا يفسر لماذا يكون تأثير توليد الكود بالذكاء الاصطناعي في هذه المجالات أفضل بشكل ملحوظ من كود منطق الأعمال.
6.2 إطار التقييم
عند الحكم على ما إذا كان جزء من الكود مناسبًا لتوليده بواسطة الذكاء الاصطناعي، يمكن الرجوع إلى المعايير الثلاثة التالية:
- هل يوجد معيار أو schema جاهز؟ — إذا وجد، فهو مناسب للذكاء الاصطناعي
- هل ينتمي إلى أنماط متكررة بكميات كبيرة؟ — إذا كان كذلك، فهو مناسب للذكاء الاصطناعي
- هل يمكن التحقق من نتيجة التوليد تلقائيًا بواسطة الأدوات؟ — إذا كان ممكنًا، فهو مناسب للذكاء الاصطناعي
الكود الذي يحقق المعايير الثلاثة جميعها (مثل توليد SDK من مواصفات OpenAPI، تعريف موارد متجانسة بشكل جماعي باستخدام Terraform)، يمكن الاعتماد بشكل كبير على الذكاء الاصطناعي في توليده. الكود الذي لا يحقق أيًا من المعايير الثلاثة (مثل تصميم بروتوكول تناسق موزع جديد)، لا يزال بحاجة إلى إنجازه يدويًا من قبل المهندسين.
7. مسرد المصطلحات
| المصطلح | الاسم الكامل / بالعربية | التعريف |
|---|---|---|
| DSL | Domain-Specific Language / لغة النطاق المحدد | لغة مصممة لمجال محدد، مقابل لغة البرمجة العامة |
| GPL | General-Purpose Language / لغة البرمجة العامة | لغة برمجة يمكنها حل أي مشكلة حسابية، مثل Python، Java، Go |
| DSL الخارجية | External DSL | لغة نطاق محدد ذات قواعد ومحلل مستقلين، مثل SQL، HCL، YAML |
| DSL الداخلية | Internal DSL / Embedded DSL | تعبير خاص بالمجال مبني داخل لغة برمجة عامة باستخدام قواعد اللغة المضيفة، مثل Pulumi |
| تسلسل البيانات | Data Serialization | عملية تحويل هياكل البيانات في الذاكرة إلى صيغة قابلة للتخزين أو النقل |
| INI | Initialization | أقدم صيغة تكوين بأزواج مفتاح-قيمة، نشأت من أنظمة Windows |
| CSV | Comma-Separated Values / القيم المفصولة بفواصل | صيغة جداول نصية خالصة تفصل بين الحقول بفواصل |
| XML | eXtensible Markup Language / لغة الترميز القابلة للتوسع | صيغة بيانات نصية مبنية على الوسوم، قوية التعبير لكن قواعدها مطولة |
| JSON | JavaScript Object Notation | صيغة تبادل بيانات خفيفة مبنية على أزواج المفتاح-القيمة، المعيار الفعلي لـ Web API |
| YAML | YAML Ain't Markup Language | صيغة ملفات تكوين مبنية على المسافة البادئة، مستخدمة على نطاق واسع في مجالات الخلفية و DevOps |
| TOML | Tom's Obvious Minimal Language | صيغة تكوين بقواعد صريحة، شائعة في نظامي Rust و Python البيئيين |
| Protobuf | Protocol Buffers | صيغة تسلسل ثنائية طورتها Google، تتطلب تعريف Schema مسبقًا، صغيرة الحجم وسريعة |
| MessagePack | — | صيغة تسلسل ثنائية مشابهة لـ JSON، لا تتطلب Schema |
| Lua | — | لغة برمجة نصية مضمنة خفيفة الوزن، شائعة الاستخدام في محركات الألعاب وخوادم الويب وامتدادات قواعد البيانات |
| IaC | Infrastructure as Code / البنية التحتية ككود | ممارسة هندسية لتعريف وإدارة موارد الحوسبة السحابية باستخدام الكود |
| Terraform | — | أداة IaC طورتها HashiCorp، تستخدم لغة HCL التصريحية |
| HCL | HashiCorp Configuration Language | لغة التكوين المخصصة المستخدمة في Terraform |
| Pulumi | — | أداة IaC تدعم لغات البرمجة العامة |
| OpenAPI | — | معيار صناعي لوصف واجهات REST API (المعروفة سابقًا باسم Swagger) |
| SDK | Software Development Kit / حزمة تطوير البرمجيات | مكتبة عميل تغلف تفاصيل استدعاء API |
| الكود اللاصق | Glue Code | كود لا يحتوي على منطق أعمال، يستخدم فقط لربط نظامين |
الخلاصة
توجد في هندسة الخلفية كمية كبيرة من الأكواد غير المرتبطة بمنطق الأعمال. لها مفهوم موحد أعلى: DSL (لغة النطاق المحدد) — لغة مصممة لمجال محدد، مقابل لغة البرمجة العامة.
يمكن تصنيف DSL المقدمة في هذه المقالة إلى أربع فئات:
- صيغ تسلسل البيانات (XML / JSON / YAML / TOML / CSV / Protobuf وغيرها) — DSL خارجية لوصف البيانات البحت، تحول البيانات المهيكلة إلى شكل قابل للتخزين والنقل
- لغات البرمجة النصية المضمنة (Lua وغيرها) — تقع بين التكوين واللغات العامة، توفر قدرات توسعة قابلة للبرمجة للبرامج المضيفة
- لغات تعريف البنية التحتية (HCL / Dockerfile وغيرها) — DSL خارجية تصريحية، تصف الحالة المرغوبة للنظام؛ Pulumi تحقق نفس الهدف بطريقة DSL الداخلية
- لغات وصف الواجهات وتوليد الكود اللاصق (OpenAPI / .proto) — توليد كود الربط بين الأنظمة تلقائيًا من خلال وصف المواصفات
بعد فهم إطار تصنيف DSL هذا، عند مواجهة أنواع مختلفة من "الكود الذي لا يشبه الكود" في مشاريع الخلفية، يمكنك التعرف بسرعة على طبيعته: إلى أي فئة من DSL ينتمي، ما المشكلة المجالية التي يحلها، ولماذا لا يتم كتابته بلغة برمجة عامة.
في الوقت نفسه، نظرًا لأن كود DSL يتميز بدرجة عالية من النمطية، ومدفوع بالمواصفات، وقابل للتحقق التلقائي، فهو أيضًا أكثر مجالات تطبيق تقنية توليد الكود بالذكاء الاصطناعي فعالية حاليًا.