DSL بلغة جافا: كتابة لغات مخصصة للمجال من الصفر

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

هل يتحدث كودك لغة الأعمال؟ حان الوقت لإنشاء DSL بلغة جافا

\n\n

تخيل: أنت لا تكتب if-else و for المملة، بل تكتب كودًا يُقرأ كتعليمات لزميل. لا تصدق؟ لا داعي. اللغات المخصصة للمجال (DSL) بلغة جافا ليست سحرًا، بل أداة عملية تحول المنطق المعقد إلى تركيبات أنيقة.

\n\n

في هذه المقالة، سنشرح كيفية إنشاء DSL بلغة جافا يجعل كودك أنظف، والعمل به أكثر وضوحًا لمحللي الأعمال. ستتعرف على الفرق بين DSL الداخلي و DSL الخارجي، وكيفية بناء fluent API، ومتى يجب كتابة المحلل النحوي الخاص بك. هيا بنا!

\n\n

ما هو DSL ولماذا يحتاجه مطور جافا؟

\n\n

DSL (لغة مخصصة للمجال) هي لغة تم إنشاؤها لحل مشاكل في مجال معين. على عكس لغة البرمجة العامة (جافا، بايثون)، فإن DSL متخصص بشكل ضيق. أمثلة من الحياة الواقعية: SQL لقواعد البيانات، التعبيرات النمطية للعمل مع السلاسل النصية، HTML لبناء صفحات الويب.

\n\n

في جافا، يُستخدم DSL من أجل:

\n
    \n
  • زيادة قابلية قراءة الكود — يصبح منطق الأعمال تصريحيًا؛
  • \n
  • خفض حاجز الدخول — يمكن للمحللين تعديل القواعد دون معرفة عميقة بجافا؛
  • \n
  • تقليل عدد الأخطاء — بناء الجملة المحدود يمنع ارتكاب الأخطاء؛
  • \n
  • تسريع التطوير — بدلاً من آلاف الأسطر من الكود، عشرات الأوامر الواضحة.
  • \n
\n\n

هام: إنشاء DSL بلغة جافا لا يتطلب كتابة مترجم. غالبًا ما نستخدم DSL الداخلي — وهي طبقات فوق بناء جملة جافا القياسي.

\n\n

DSL داخلي مقابل DSL خارجي: أيهما تختار؟

\n\n

DSL داخلي (Embedded DSL)

\n

هو DSL يعيش داخل جافا. تستخدم الدوال، وسلاسل الاستدعاءات، والدوال lambda، وتحميل المشغلين (من خلال الدوال). مثال: Java Stream API هو DSL داخلي لمعالجة المجموعات.

\n\n
List<String> result = orders.stream()\n    .filter(o -> o.getAmount() > 1000)\n    .map(Order::getCustomerName)\n    .collect(Collectors.toList());
\n\n

الإيجابيات: لا حاجة لكتابة محلل نحوي، متكامل بإحكام مع جافا، سهل التصحيح. السلبيات: بناء الجملة محدود بإمكانيات جافا.

\n\n

DSL خارجي (External DSL)

\n

هي لغة منفصلة ببنائها النحوي الخاص. تكتب محللًا نحويًا (على سبيل المثال، باستخدام ANTLR أو JavaCC) ومفسرًا. مثال: SQL هو DSL خارجي ترسله إلى قاعدة البيانات.

\n\n

الإيجابيات: حرية كاملة في بناء الجملة، يمكن جعلها جميلة جدًا. السلبيات: تحتاج لكتابة وصيانة محلل نحوي، أصعب في التصحيح.

\n\n

معظم المهام تكفيها DSL الداخلي. DSL الخارجي مبرر عندما يستخدم اللغة عدد كبير من الأشخاص (مثل SQL) أو عندما يكون بناء الجملة مهمًا جوهريًا.

\n\n

تطبيق عملي: إنشاء DSL داخلي بلغة جافا لنظام مراقبة

\n\n

لنفترض أننا نبني نظام مراقبة للخوادم. بدلاً من كتابة:

\n\n
AlertRule rule = new AlertRule();\nrule.setMetric("cpu_usage");\nrule.setOperator(GREATER_THAN);\nrule.setThreshold(90.0);\nrule.setDuration(5, TimeUnit.MINUTES);\nrule.setAction(new SendEmailAction("admin@example.com"));
\n\n

نريد أن نكتب هكذا:

\n\n
AlertRule rule = AlertRuleBuilder\n    .whenMetric("cpu_usage")\n    .isGreaterThan(90.0)\n    .forDuration(5, TimeUnit.MINUTES)\n    .thenSendEmail("admin@example.com")\n    .build();
\n\n

جميل، أليس كذلك؟ دعنا ننفذ fluent API هذا.

\n\n

الخطوة 1: إنشاء فئة AlertRule

\n\n
public class AlertRule {\n    private String metric;\n    private String operator;\n    private double threshold;\n    private long duration;\n    private TimeUnit timeUnit;\n    private String actionType;\n    private String actionTarget;\n\n    // تم حذف الدوال الواصلة والموصلة للاختصار\n}
\n\n

الخطوة 2: بناء المُنشئ (builder) مع واجهة fluent

المدونات

توصيات الكتب