OOZOU
تواصلوا معنا
العودة إلى المدونة

ما يحبه مطوّر Ruby مخضرم في Elixir وPhoenix

أعمل مطوّرًا بلغة Ruby منذ أكثر من عشر سنوات، وبدأت مؤخرًا استخدام Elixir. أشارككم هنا بعض ما أحببته في هذه اللغة.

27 ديسمبر 2020
8 دقائق للقراءة
ما يحبه مطوّر Ruby مخضرم في Elixir وPhoenix

بالنسبة لمطوّر Ruby، تبدو لغات كثيرة غريبة جدًا. لم أجد بعد لغة تهتم بسهولة القراءة بقدر ما تهتم بها Ruby، فهي تتيح لكم كتابة كود جميل بسهولة. صحيح أن Elixir تسمح بكتابة كود فوضوي وصعب القراءة بسهولة أكبر من Ruby، لكنها قادرة أيضًا على إنتاج كود أنيق وسلس. كما أن كثيرًا من صياغتها مألوف، وهذا رائع في البداية. أما الصعوبة الحقيقية فهي الانتقال من التفكير بأسلوب البرمجة كائنية التوجه (OOP) إلى التفكير بالدوال. وحين تتجاوزون ذلك، يمكنكم بناء أشياء رائعة حقًا.

Pipes

أضافت Ruby عامل pipeline في الإصدار 2.7، لكن لا تنخدعوا، فهو يختلف عن المفهوم الأكثر شيوعًا في لغات أخرى كثيرة. بل يمكن القول إن pipes في Ruby ليست pipes حقيقية، وقد اشتكى كثيرون من محدودية فائدتها. في Elixir ولغات أخرى عديدة، يمرّر الـ pipe نتيجة الدالة السابقة بوصفها الوسيط الأول للدالة التالية. وهذا يتيح لكم بناء سلسلة من الخطوات للمهام التي تشبه العمليات المتتابعة. فالـ pipes في جوهرها آلية لتركيب الدوال.

"Elixir rocks"
  <strong>|></strong> String<strong>.</strong>upcase()
  <strong>|></strong> String<strong>.</strong>split()
=> ["ELIXIR", "ROCKS"]

ملاحظة مهمة هنا: يجب إحاطة النصوص (strings) في Elixir بعلامات اقتباس مزدوجة، أما النصوص بين علامات اقتباس مفردة فتُفسَّر على أنها charlist. أنا متأكد أن كثيرًا من مطوّري Ruby يقعون في هذا الخطأ، وما زلت أقع فيه أحيانًا. الكود أعلاه مثال بسيط، لكنه يوضح مدى سهولة فهم ما يحدث.

مطابقة الأنماط

من أكثر ما أحبه في Elixir مطابقة الأنماط (pattern matching). أضافت Ruby مطابقة أنماط تجريبية في الإصدار 2.7، ولم تتح لي الفرصة لتجربتها بعد. أما مطابقة الأنماط في Elixir فقد جرّبتها كثيرًا، وأحببتها.

# check if variable contains what we expect
[1, 2, 3] = podium_positions
# check tuple response from a function
{:ok, response} = function()
{:error, response} = function()
# Handle cases based on arguments
case function()
{:ok, :done} -> do_something()
{:ok, result} -> process()
{:error, :unauthorized} -> raise Something
{:error, reason} -> check_reason()

تعريف الدوال

من الأشياء التي أحبها حقًا في Ruby الحديثة إمكانية وضع علامتي protected وprivate مباشرة على سطر تعريف الـ method. وفي Elixir هذا جزء من تصميم اللغة نفسها: إما أن تعرّفوا الدالة عامة أو خاصة، وذلك باستخدام def أو defp. هذا كل شيء. أسلوب بسيط وسهل القراءة، وأفضّله لتحديد إمكانية الوصول إلى الدوال لأنه أوضح بكثير، خصوصًا في الملفات الكبيرة.

تتيح Elixir أيضًا شيئًا أتمنى لو أستطيع فعله في Ruby. ففي Ruby لا يمكن للـ class أو الـ module أن يحتوي إلا على method واحدة بالاسم نفسه، أما في Elixir فتُميَّز الدوال أيضًا بعدد وسائطها (arity). لذلك سترون كثيرًا إشارات مثل String.upcase/1، والمقصود بها دالة upcase في String التي تأخذ وسيطًا واحدًا. وهذا يسمح لكم بإنشاء دوال بالاسم نفسه مع وسائط إضافية. يمكن فعل شيء مشابه في Ruby بإعطاء الوسيط قيمة افتراضية nil ثم التحقق من وجوده، لكن صياغة Elixir تجعل تعريف الدوال أنظف بكثير.

def call_function(function_name, arguments) do
  apply(__MODULE__, function_name, arguments)
end

def call_function(module, function_name, arguments) do
  apply(module, function_name, arguments)
end

ويمكننا فعل المزيد بالدوال، إذ نستطيع استخدام guards لإنشاء عدة نسخ من الدالة نفسها بحسب الوسائط الممرَّرة

def empty_map?(map) when map_size(map) == 0, do: true
def empty_map?(map) when is_map(map), do: false
def empty_map?(map), do: raise NotAMapError

تأتي Elixir مع كثير من الـ guards المدمجة، ويمكنكم أيضًا إنشاء guards خاصة بكم. لكن لأن Elixir لغة مُترجَمة (compiled)، هناك بعض القواعد، فاحرصوا على الاطلاع عليها عند ذلك.

العمليات في Elixir

بنية العمليات (processes) في Elixir مذهلة حقًا، أو بعبارة أدق: BEAM هو المذهل. فبفضل طريقة تصميم BEAM، يمكن تشغيل عدد كبير جدًا من العمليات وكأنها تعمل بالتوازي. وحتى لو بدأت إحدى العمليات تستهلك 100% من المعالج، تظل العمليات الأخرى تعمل بكفاءة تقارب 100%. والسبب أن BEAM يبدّل بين العمليات تلقائيًا وباستمرار، فيضمن لكل عملية حصة عادلة من الموارد المتاحة. هذا وحده يدهشني. ففي Ruby، إذا كانت لديكم عملية تستهلك المعالج بالكامل، فقد تخسرون خادمًا كاملًا. بالطبع ما زلتم بحاجة إلى ملاحظة أن إحدى العمليات تعمل بنسبة 100% ومعالجة ذلك، لكن على المدى القصير يبقى نظامكم كله سليمًا.

كما أن كل عملية مستقلة تمامًا، فلا داعي للقلق بشأن thread safety كما في Ruby. صحيح أنكم ما زلتم بحاجة إلى التفكير في أقفال قاعدة البيانات مثلًا، وفي كيفية تعديل الملفات من عدة عمليات، لكن هذه الأمور تُعالَج بطرق مختلفة.

البساطة

لا تُخفي Elixir شيئًا، ولا تعتمد على أي "سحر" خاص. في Rails قد تمضون سنوات دون فهم بعض الآليات التي تعمل في الخلفية، أما Elixir فسهلة الفهم فعلًا. التجريدات واضحة، ولأننا نتعامل مع بنى غير قابلة للتغيير (immutable) تمرّ عبر الدوال، فلا توجد آثار جانبية غريبة وغير متوقعة تربكنا.

التوثيق

توثيق Elixir شامل جدًا وسهل الفهم بمجرد أن تفهموا اللغة. وهناك أيضًا دليل ممتاز عن اللغة نفسها. يُكتب التوثيق مع تعريفات الدوال مباشرة، على غرار RDoc أو Yard، لكنه مدمج في اللغة نفسها ويحظى بتشجيع المجتمع. وعند نشر حزمة على Hex، يُبنى التوثيق تلقائيًا ويصبح متاحًا على hexdocs.pm

يمكنكم أيضًا كتابة أمثلة في التوثيق تتحول إلى اختبارات حقيقية، وتُسمّى DocTests يجعل نظام التوثيق هذا توثيق الـ modules بشكل جيد أمرًا سهلًا، ويجعل قراءة التوثيق في متناولكم أثناء التعديل أو التنفيذ في أماكن أخرى.

Ports

كيف نسيت Ports! تتعامل Elixir مع التواصل مع النظام الخارجي بأسلوب أنيق. فباستخدام Ports يمكنكم إرسال أوامر إلى النظام الأساسي عبر الرسائل، تمامًا كما نفعل مع العمليات (Processes). ومع Port يمكنكم تشغيل ملف تنفيذي داخل عملية، ثم إرسال الرسائل مباشرة إلى ذلك الملف. وهذا يتيح لكم التعامل مع Python وRuby وNode.js وغيرها كما لو كنتم تتحدثون إلى عملية Elixir.

هل هناك ما لا أحبه؟

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

البحث عن تعريفات الدوال في Elixir مقارنة بالبحث عن تعريفات الـ methods في Ruby

في Ruby، توفّر لنا أداة pry المساعد show-source الذي يعرض مكان تعريف الـ method والتعريف نفسه. ويمكننا أيضًا استدعاء object.methods لعرض جميع الـ methods المعرّفة في الكائن. لكن لأن Elixir لغة مُترجَمة، فالدوال التي نعرّفها لا توجد وقت التشغيل، إذ تتحول إلى BEAM bytecode. وهذا يجعل العثور على التعريفات من داخل جلسة pry أمرًا مستحيلًا. لذا يعتمد العثور على الدوال في Elixir على قدرتكم على البحث في الأماكن الصحيحة. فإذا استوردتم modules إلى الـ module الحالي، فعليكم البحث فيها لمعرفة مكان تعريف الدالة. ولحسن الحظ يحظى التوثيق باحترام كبير في مجتمع Elixir، لذا لا يسبب هذا مشكلات تُذكر في 99% من الحالات.

التصحيح باستخدام Pry أثناء معالجة طلب في Phoenix

افتراضيًا، عند تشغيل الخادم في جلسة Elixir تفاعلية (أي iex -S phx.server)، لا يتوفر لكم سوى وقت قصير للتصحيح قبل أن ينتهي الطلب ويكمل التنفيذ. يمكنكم زيادة مهلة الـ timeout في الإعدادات، لكن إن كنتم تحتاجون إلى مهلة قصيرة فسيصبح ذلك مشكلة بحد ذاته. أما في Rails فلا نواجه هذه المشكلة، إذ يوقف pry التنفيذ إلى أجل غير محدد.

ملاحظة ختامية

هذه القائمة ليست شاملة بالتأكيد، فبإمكاني الاستمرار لصفحات. إنها مجرد بعض الميزات التي لفتت انتباهي خلال انتقالي من البرمجة كائنية التوجه في Ruby إلى البرمجة الموجهة بالعمليات (POP) في Elixir والبرمجة الوظيفية عمومًا. حين بدأت كتابة Elixir، لم أتوقع أن أستمتع بها إلى هذا الحد. العمل بها ممتع حقًا، وربما لأنني ما زلت أكتشف مفاهيم مثيرة كثيرة تحفّزني على التعلّم. وفي كل الأحوال، إنها لغة رائعة بلا شك. وPhoenix إطار عمل رائع، ولديّ آمال كبيرة في live-view.

Related Articles

كيف أصمّم برمجيات؟ دليل المبتدئين لأصحاب الأعمال

كيف أصمّم برمجيات؟ دليل المبتدئين لأصحاب الأعمال

تصميم البرمجيات عملية ممتعة لكنها معقدة، تتطلب الإبداع والتفكير المنطقي ومهارات حل المشكلات.

اقرأوا المزيد
مستقبل الحوسبة الطرفية: ما تحتاج الشركات إلى معرفته

مستقبل الحوسبة الطرفية: ما تحتاج الشركات إلى معرفته

يتطور المشهد الرقمي بسرعة، وعلى الشركات أن تتكيّف لتواكب الطلب المتزايد على السرعة والكفاءة والمعالجة في الوقت الفعلي.

اقرأوا المزيد
مستقبل قطاع التجزئة: الذكاء الاصطناعي والواقع المعزّز واتجاهات التحوّل الرقمي

مستقبل قطاع التجزئة: الذكاء الاصطناعي والواقع المعزّز واتجاهات التحوّل الرقمي

يتطور قطاع التجزئة بوتيرة غير مسبوقة بفضل الذكاء الاصطناعي (AI) والواقع المعزّز (AR) وتقنيات التحوّل الرقمي. فلم تعد المتاجر التقليدية مجرد أماكن لبيع المنتجات، بل أصبحت متاجر ذكية وتفاعلية.

اقرأوا المزيد

Have a Project in Mind?

Let's discuss how we can help bring your ideas to life with our expertise in web and mobile development.

ابدأوا المحادثةhello@oozou.com
OOZOU Logo

بانكوك · سنغافورة · هونغ كونغ

X
Facebook
Instagram
LinkedIn
OOZOU Co., Ltd.
548 One City Centre
Ploenchit Road
Bangkok 10330
Thailand
+66 2544 0000
hello@oozou.com

الخدمات

  • تطوير الويب
  • وكلاء الذكاء الاصطناعي والذكاء الاصطناعي التوليدي
  • تطوير تطبيقات الجوال
  • تحليلات البيانات وهندستها
  • تصميم تجربة المستخدم وواجهته (UX/UI) وتصميم المنتجات
  • التحوّل الرقمي

الشركة

  • من نحن
  • الوظائف
  • المدونة
  • دراسات الحالة
  • عروض حية
  • تعلّمت اليوم
  • تواصل معنا

المزيد

  • القطاعات
  • شبكة الشركاء
© 2026 OOZOU. جميع الحقوق محفوظة.
سياسة الخصوصيةمدونة قواعد السلوكسياسة مكافحة الرشوة والفساد