اذهب إلى المحتوى

لوحة المتصدرين

  1. Wael Aljamal

    Wael Aljamal

    الأعضاء


    • نقاط

      12

    • المساهمات

      6975


  2. Ayoub Battah

    Ayoub Battah

    الأعضاء


    • نقاط

      5

    • المساهمات

      29


  3. سامح أشرف

    سامح أشرف

    الأعضاء


    • نقاط

      3

    • المساهمات

      2934


  4. Nour Al Sabbagh

    Nour Al Sabbagh

    الأعضاء


    • نقاط

      2

    • المساهمات

      119


المحتوى الأكثر حصولًا على سمعة جيدة

المحتوى الأعلى تقييمًا في 12/27/21 في كل الموقع

  1. مرحبا, اود فصل قسمين عن بعضهما البعض وجعل كل قسم على سطر منفرد. لقد استعملت خاصية display: block ولكن لم تنجح هذه الطريقة. هل هنااك اي طريقة اخرى؟
    2 نقاط
  2. السلام عليكم لدي إستفسار شيخصي أنا إشتريت هده الدورة مدة أكتر من 8 أشهر ودائما متردد في البدء فيها لأنني أقول دائما أنني حتى لو أكملة هده الدورة وأردة أن أبحت عن عمل كمطور ويب باتشب لأيمكنني المسايرة مع أناس درسو في الجامعات ولديهم الأساسيات البرمجة وأيضا لديهم مستوى عالي في التحليل و المنطق هل أنا على حق أم أنني فقط يجب علي أن أبداء ومع الوقت ساصبح محترفا ششكرا لكم
    2 نقاط
  3. هذا السؤال مجاب عليه من قبل:
    2 نقاط
  4. أهلا بك أيوب، هل تقصد أنك اشتركت في دورة تطوير واجهات المستخدم؟ هذه الدورة تركز على تصميم مواقع الويب وجعلها متوافقة مع الشاشات بجمع أحجامها Responsive Design باستخدام أدوات حديثة و المستخدمة في سوق العمل، وبنفس الوقت تصميم صفحات الويب لا يحتاج لمهارات برمجية أو خوارزميات أو تفكير منطقي عالي المستوى، حتى أن HTML - CSS ليست لغات برمجة بل توصيف لما تريد من المستعرض أن يعرضه. على كل حال إن أردت البدء بأساسيات البرمجة و التفكير المنطقي و دراسة بعض الخوارزميات و التطبيق عليهم يمكنك الانضمام لدورة علوم الحاسب و التركيز على الأساسيات التي ذكرتها أنت و قلت أنت قلق من عدم إتقانها، ثم بعدها عد إلى دورة تطوير الواجهات و ستلاحظ أنها سهلة. يمكنك التواصل مع (مركز المساعدة) لتبديل الدورة أو يمكنك شراء الدورة الأخرى أرجو عدم الخوف و القلق والبدء بالتعلم. بالتوفيق
    2 نقاط
  5. يمكننا بناء دالة تجلب عدد المنتجات المباع ضمن مجال من الوقت، طبعا يمكنك استدعاء الدالة عدة مرات، وفي كل مرة تمرر لها مجال مختلف public function itemsInHour($builder, $from, $to) { return $builder ->withCount(['transactions' => function ($transaction) use ($from, $to) { $transaction ->whereDate('created_at', '>', $from) ->whereDate('created_at', '<', $to); }]) // ->orderBy('transactions_count', 'desc'); } حيث أن: builder: باني الاستعلام transactions: جدول المناقلات أو المشتريات from تاريخ بدء البحث to تاريخ انتهاء البحث كما يمكن كالتالي: بمساعدة حزمة Carbon لجلب مشتريات آخر يوم تجميع و ترتيب بتعليمات SQL use Carbon\Carbon; $productsByDay = transactions::where('created_at', '>=', Carbon::now()->subDays(1)) ^^^^^^^^^^^^^^ يوم واحد ->groupBy('date') // تجميع حسب التاريخ ->orderBy('date', 'DESC') ->get([ DB::raw('DATE(created_at) as date'), DB::raw('COUNT(*) as "products"') ])->pluck('products','date')->toArray();
    2 نقاط
  6. رغم أن الأفكار التي كانت وراء البرمجة الكائنية التوجه طُورت في ستينيات القرن الماضي إلا أنها لم تشتهر في الوسط البرمجي إلا بعد ذلك بعقدين، أي في الثمانينيات، بعد إطلاق Smalltalk-80 ومجموعة متنوعة من تطبيقات لغة Lisp، ولم تكن وقتها اتجاهًا سائدًا في البرمجة وإنما كانت تثير الفضول فقط، ثم تغير ذلك عندما انتشرت الواجهات الرسومية في الحواسيب الشخصية على حواسيب أبل أولًا، ثم على الحواسيب العاملة بنظام ويندوز ونظام نوافذ X في يونكس، إلى أن اقتربنا من نهاية الألفية السابقة، حيث صارت البرمجة الكائنية التوجه Object Oriented Programming -والتي تعرف اختصارًا OOP- التقنية الأبرز لتطوير البرمجيات. وتتجسد مفاهيم البرمجة الكائنية التوجه في لغات مثل جافا وC++‎ وبايثون بحيث لا تكاد تفعل شيئًا فيها إلا وتقابل كائنًا في مكان ما، ونريد في هذا المقال أن نتعرف على هذه التقنية وننظر في المفاهيم الأساسية لها، مثل تعريف الكائن والصنف وتعددية الأشكال polymorphism والوراثة inheritance، وكيفية إنشاء الكائنات وتخزينها واستخدامها، والبرمجة الكائنية التوجه موضوع كبير قد كُتبت فيه كتب، فإذا أردت التعمق فيه أكثر مما هو مذكور في هذا المقال فانظر هذه الكتب باللغة الإنجليزية: كتاب Object Oriented Analysis لبيتر كود Peter Coad وإد يوردون Ed Yourdon. كتاب Object Oriented Analysis and Design with Applications لجريدي بوش Grady Booch (الطبعة الأولى أو الثالثة). كتاب Object Oriented Software Construction لبرتراند ماير Berterand Meyer (الطبعة الثانية). تختلف هذه الكتب عن بعضها في العمق والحجم والدقة الأكاديمية بالترتيب، فالكتاب الأول مناسب للأغراض العامة التي هي خارج نطاق العمل البرمجي، والحق أنها كلها ليست كتبًا في البرمجة، بل كتب تحليل وتصميم برمجي، لأن أفضل تطبيق للبرمجة الكائنية التوجه يكون بتطبيق المبادئ خلال دورة حياة المشروع، وهذه طريقة مختلفة لحل المشاكل عن الطريقة العادية للبرمجة. أما في هذا المقال فسنتحدث باختصار عن مفاهيم البرمجة الكائنية التوجه التي ذكرناها، ولا مشكلة إذا لم تستوعبها في البداية، فلا تزال تستطيع استخدام الكائنات بدون أن تستوعب المفهوم الذي بُنيت عليه، ثم ستتضح الأمور بالتدريج مع التدرب والوقت،كما يمكن استخدام تصميم كائني التوجه في لغة غير كائنية من خلال الاصطلاحات البرمجية، لكن لا يُنصح بهذا الأسلوب، وإنما يستخدَم ملاذًا أخيرًا عندما لا نجد حلًا آخر، حيث تُستخدم التقنيات الكائنية التوجه إذا كانت المشكلة توافقها وتُحل بها، ويُفضل أن تُستخدم لغة كائنية التوجه أيضًا عندها، وتدعم أغلب اللغات الحديثة البرمجة الكائنية التوجه جيدًا، بما فيها اللغات الثلاثة التي نتدرب عليها، لكننا سنستخدم بايثون في الأمثلة الواردة هنا، ثم سنعرض المفاهيم الأساسية فقط في جافاسكربت وVBScript. جمع البيانات والدوال الكائنات هي تجميعات من البيانات والدوال التي تنفذ مهامًا على تلك البيانات، وتوضعان معًا بحيث يمكن تمرير كائن من جزء ما في البرنامج كي نحصل تلقائيًا على وصول إلى العمليات المتاحة وسمات البيانات، وهذا الجمع بين البيانات والدوال هو أصل البرمجة الكائنية التوجه، ويُعرف باسم التغليف encapsulation، لأن بعض لغات البرمجة تخفي البيانات عن مستخدمي الكائن، وبناءً عليه تتطلب توابع الكائن للوصول إليها، وتسمى هذه التقنية باسم إخفاء البيانات، ويطلق عليها التغليف أحيانًا، وكمثال على التغليف، قد يخزن كائن سلسلة نصية سلسلة محارف، لكنه يوفر كذلك توابع للعمل على هذه السلسلة؛ لتنفيذ أمور مثل البحث وتغيير حالة الأحرف وحساب الطول وغير ذلك، وتستخدم الكائنات مجازًا تمرير الرسالة message passing، حيث يمرر كائنٌ رسالةً إلى كائن آخر، ويرد الكائن المستقبل بتنفيذ تابع -وهو إحدى عملياته-، وهكذا يُستدعى التابع عند استقبال الرسالة الموافقة له بواسطة الكائن المالك، ويمكن تمثيل ذلك بصيغ مختلفة، وأكثرها شيوعًا الصيغة النقطية . التي تحاكي الوصول إلى العناصر التي في الوحدات، فبالنسبة إلى صنف widget وهمي: w = Widget() # widget جديدة من w أنشئ نسخة w.paint() # paint أرسل إليها الرسالة ستستدعي هذه التعليمات التابع paint الخاص بكائن widget. تعريف الأصناف يمكن للكائنات أن تحتوي على أنواع مختلفة، كما أن للبيانات أنواعًا مختلفةً، وتُعرَّف تجميعات الكائنات التي لها صفات متطابقة باسم الأصناف classes، ونستطيع تعريف هذه الأصناف وإنشاء نسخ منها، حيث تكون تلك النسخ هي الكائنات الفعلية، كما يمكن تخزين مراجع إلى تلك الكائنات في المتغيرات داخل برامجنا، لننظر الآن في مثال حقيقي لنرى إن كنا نستطيع تفسيره وشرحه، حيث سننشئ صنف رسالة يحتوي على سلسلة نصية -تمثل نص الرسالة- وتابع لطباعة الرسالة. class Message: def __init__(self, aString): self.text = aString def printIt(self): print( self.text ) الملاحظة الأولى: يسمى أحد توابع هذا الصنف باسم __init__، وهو تابع خاص يسمى الباني constructor، وسبب هذا الاسم أنه يُستدعى عند إنشاء أو بناء نسخة جديدة من كائن ما، وستكون المتغيرات المسندة داخل هذا التابع -والتي أنشئت داخل بايثون- متغيرات فريدة للنسخة الجديدة، وتوجد عدة توابع خاصة مثل هذا التابع في بايثون، وجميعها مميزة بصيغة التسمية التي فيها شرطتان سفليتان عن يمينها وشمالها __xxx__، ويطلق عليها مستخدمو بايثون أحيانًا اسم التوابع السحرية magic methods أو التوابع المحاطة بشرطين سفليتين dunder methods (إذ dunder اختصار إلى double under)؛ أما وقت استدعاء الباني الدقيق فيختلف بين اللغات، حيث يُستدعى التابع init في بايثون بعد إنشاء النسخة في الذاكرة، لكنه في لغات أخرى يعيد النسخة نفسها، والفرق في هذا بين اللغات طفيف ولا يستحق الانتباه له. الملاحظة الثانية: يحتوي كلا التابعين المعرفين على معامل أول هو self، والاسم مجرد اصطلاح يشير إلى نسخة الكائن، وسنرى قريبًا أن هذا المعامِل لا يملؤه المبرمج، بل يُملأ بواسطة المفسر في وقت التشغيل، وعلى هذا يُستدعى printIt على نسخة للصنف -انظر أدناه-، بدون وسطاء بالشكل m.printIt()‎. الملاحظة الثالثة: لقد استدعينا الصنف Message بحرف M كبير كما نرى، وهذا للسهولة فقط، لكن هذا الاصطلاح يُستخدم بكثرة في لغات البرمجة الكائنية التوجه، وليس في بايثون وحدها، ويوجد اصطلاح قريب من هذا يقتضي أن تبدأ أسماء التوابع بحرف صغير ثم تبدأ الكلمات التالية في الاسم بحرف كبير، فإذا كان لدينا تابع اسمه calculate current balance، فسيُكتب بالشكل calculateCurrentBalance. ننصحك عند هذه النقطة بالعودة إلى مقال البيانات وأنواعها، لقراءة قسم الأنواع المعرَّفة من قِبل المستخدم، حيث ستفهم مثال دليل جهات الاتصال في بايثون فهمًا أفضل بعد هذا الشرح هنا، فالنوع الوحيد الذي يعرّفه المستخدم في بايثون هو الصنف، والصنف الذي له سمات attributes وليس له توابع -ما عدا __init__- يكافئ الباني المسمى record أو struct في بعض لغات البرمجة. الصيغة الرسومية تبنّى مجتمع هندسة البرمجيات صيغةً مرئيةً لوصف الأصناف والكائنات وعلاقاتها بعضها ببعض، وتسمى هذه الصيغة باسم لغة النمذجة الموحدة Unified Modelling Language أو UML اختصارًا، وهي أداة تصميم قوية وتحتوي على العديد من المخططات والأيقونات، وسننظر في بعضها هنا بما يعيننا على فهم المبادئ التي نريد شرحها فقط، وأول أيقونة سنقابلها في UML هي وصف الصنف، وهي أهم الأيقونات، وتتكون من صندوق من ثلاثة أجزاء، يحتوي الجزء العلوي على اسم الصنف، والأوسط على سماته أو البيانات فيه، أما الجزء السفلي فيحتوي على توابع الصنف أو دواله، وبناءً عليه سيبدو صنف Message المعرَّف أعلاه كما يلي: سنرى في هذا المقال أيقونات UML أخرى، ونتعرض لمفاهيم جديدة تدعمها هذه الصيغة. استخدام الأصناف بما أننا عرّفنا الصنف Message فنستطيع إنشاء نسخ منه الآن والعمل عليها: m1 = Message("Hello world") m2 = Message("So long, it was short but sweet") notes = [m1, m2] # ضع الكائنات في قائمة for msg in notes: msg.printIt() # اطبع الرسائل متتابعة وبهذا نعامل الصنف كما لو كان نوع بيانات قياسيًا في بايثون، وهو الغرض من التدريب ابتداءً. كما توجد أيقونة للكائن أو النسخة في UML، وهي مثل أيقونة الصنف إلا أننا نترك الجزئين السفليين في الصندوق فارغين، ويتكون الاسم من اسم الكائن أو النسخة متبوعًا بنقطتين رأسيتين ثم اسم الصنف، وعليه فإن m1:Message تخبرنا أن m1 ما هي إلا نسخة من الصنف Message، ويمكن رسم مثال الرسالة الخاص بنا الآن كما يلي: نلاحظ أن الصنف List يمثل نوع القائمة القياسي في بايثون، كما هو موضح من وضع كلمة builtin بين أقواس حادة، وهي بنية معروفة في UML باسم القالب النمطي stereotype، وتشير الخطوط ذوات الرؤوس الماسية في الصورة إلى القائمة التي تحتوي على كائنات Message، وبالمثل فإن كائن MyProg يُنمَّط stereotyped على أنه صنف مساعد utility class، مما يعني في هذه الحالة أنه غير موجود مثل صنف داخل البرنامج، لكنه منتج من منتجات البيئة نفسها، وتُظهَر أدوات نظام التشغيل عادةً بهذه الطريقة، مثل مكتبات لدوال. أما الخطوط المستقيمة التي تخرج من myProg إلى Message فتوضح أن الكائن myProg يرتبط بـكائنات Message أو يشير إليها، وتشير الأسهم المرافقة لتلك الخطوط أن كائن myProg يرسل رسالة printIt إلى كل كائن من كائنات Message، وتُنقل رسائل الكائنات من خلال ارتباطات associations. المعامل self يطرح من يبدأ حديثًا في البرمجة الكائنية التوجه ببايثون سؤالًا هو: ما هو المعامل self؟ لأن تعريف أي تابع في صنف ما في بايثون يبدأ به، ويجب أن نبين أن الاسم نفسه مجرد اصطلاح، ولم يتغير إلى الآن لأن الثبات أمر محمود في الاصطلاحات البرمجية، فلغة جافاسكربت مثلًا لديها مفهوم مشابه لكنها تستخدم اسم this بدلًا من self. أما self نفسه فهو مرجع إلى النسخة الحالية، فحين ننشئ نسخةً من الصنف فإنها تحتوي على بياناتها الخاصة كما أنشأها الباني، لكنها لا تحوي التوابع، لذا عندما نرسل رسالةً إلى نسخة وتستدعي التابع الموافق؛ فإنها تستدعيه إلى الصنف من خلال مرجع داخلي، فتمرر مرجعًا إلى نفسها self إلى التابع لتعرف شيفرة الصنف أي نسخة يجب أن تستخدمها. لننظر الآن في مثال مألوف، فإذا كان لدينا تطبيق رسومي فيه كائنات أزرار كثيرة، فسيُفعَّل التابع المرتبط بكل زر عندما يضغطه المستخدم، ويعرف تابع الزر أي زر ضغِط بالإشارة إلى قيمة self التي ستكون مرجعًا إلى نسخة الزر الحقيقي الذي ضُغط، وسنرى ذلك عمليًا في مقال لاحق. وعند إرسال رسالة إلى كائن يحدث ما يلي: تستدعي شيفرة العميل النسخة، أي ترسل الرسالة إذا أردنا الحديث باصطلاح البرمجة الكائنية التوجه. تستدعي النسخة تابع الصنف، وتمرر مرجعًا إلى نفسها self. يستخدم تابع الصنف بعدها المرجع الممرَّر ليأخذ بيانات النسخة للكائن المستقبِل. يمكن رؤية تلك النقاط عمليًا في تسلسل الشيفرة التالي، ونلاحظ أننا نستطيع استدعاء تابع الصنف صراحةً كما فعلنا في السطر الأخير: >>> class C: ... def __init__(self, val): self.val = val ... def f(self): print ("hello, my value is:", self.val) ... >>> # create two instances >>> a = C(27) >>> b = C(42) >>> # first try sending messages to the instances >>> a.f() hello, my value is 27 >>> b.f() hello, my value is 42 >>> # now call the method explicitly via the class >>> C.f(a) hello, my value is 27 نستطيع استدعاء التوابع كما نرى في المثال أعلاه من خلال النسخة، وتملأ بايثون معامِل self في تلك الحالة لنا، أو من خلال الصنف صراحةً، وفي تلك الحالة نحتاج إلى تمرير قيمة self صراحةً. لدينا سؤال يطرح نفسه الآن، فإذا كانت بايثون تستطيع توفير مرجع بين النسخة وصنفها، ألا تستطيع أن تملًا self بنفسها أيضًا؟ ربما يكون هذا سؤالًا منطقيًا لكن الإجابة عليه هي أن Guido Van Rossum -منشئ اللغة- صممها هكذا. لكن مع هذا فإن العديد من لغات البرمجة الكائنية التوجه تخفي معامِل self، لكن بايثون تعتمد الصراحة explicity وتفضلها على الضمنية implicity، ويتعود المبرمج على هذا المبدأ مع كثرة العمل. تعددية الأشكال polymorphism لدينا الآن القدرة على تعريف أصنافنا الخاصة وإنشاء نسخ منها وإسنادها إلى متغيرات، ثم تمرير رسائل إلى تلك الكائنات تؤدي إلى تشغيل التوابع التي عرفناها، لكن هناك عنصر أخير يتعلق بالبرمجة الكائنية التوجه هنا، وهو الأهم فيها من نواحٍ عدة، فإذا كان لدينا كائنان من صنفين مختلفين لكنهما يدعمان نفس مجموعة الرسائل، لكن مع التوابع الموافقة لها، فنستطيع عندئذ أن نجمع تلك الكائنات معًا ونعاملها معاملةً واحدةً في برنامجنا، لكنها ستتصرف تصرفًا مختلفًا، وتُعرف تلك القدرة على التصرف المختلف لنفس رسائل الدخل باسم تعددية الأشكال، تُستخدم هذه الخاصية عادةً لجعل عدد من الكائنات الرسومية المختلفة ترسم نفسها عند استلام رسالة paint، فترسم الدائرة شكلًا مختلفًا تمامًا عن المثلث، لكن بما أن لهما نفس تابع paint فنستطيع -نحن المبرمجين- أن نتجاهل الاختلافات ونراهما على أنهما مجرد أشكال، لننظر الآن في مثال نحسب فيه مساحة الأشكال بدلًا من رسمها: ننشئ أولًا الصنفين Square وCircle: class Square: def __init__(self, side): self.side = side def calculateArea(self): return self.side**2 class Circle: def __init__(self, radius): self.radius = radius def calculateArea(self): import math return math.pi*(self.radius**2) نستطيع الآن أن ننشئ قائمةً من الأشكال -دوائر أو مربعات- ثم نطبع مساحاتها: shapes = [Circle(5),Circle(7),Square(9),Circle(3),Square(12)] for item in shapes: print "The area is: ", item.calculateArea() إذا جمعنا هذه الأفكار مع وحدات modules فسنحصل على آلية بالغة القوة لإعادة استخدام الشيفرة، حيث نضع تعريفات الصنف في وحدة ولتكن shapes.py مثلًا، ثم نستورد تلك الوحدة حين نرغب في التعديل على الأشكال، وهذا بالضبط ما حصل مع العديد من وحدات بايثون القياسية، وهو السبب الذي يجعل الوصول إلى توابع كائن ما يشبه استخدام الدوال في وحدة. نرى في الصورة أعلاه مخطط كائن أكثر تعقيدًا، ونلاحظ أن الكائنات التي داخل القائمة في هذه الحالة ليس لها أسماء لأننا لم ننشئ متغيرات لها صراحةً، ففي تلك الحالة نعرض مسافةً فارغةً قبل النقطين الرأسيتين واسم الصنف، لكن هذا يجعل المخطط مزدحمًا، لذا لا نرسم مخططات الكائنات إلا عند الضرورة لتوضيح بعض المزايا غير المألوفة للتصميم، أما في الأحوال العادية فنستخدم خصائص معقدةً أكثر من مخططات الأصناف لعرض العلاقات التي لدينا، كما سنرى في الأمثلة التالية. الوراثة inheritence تُستخدم الوراثة (أو الاكتساب) عادةً لتنفيذ تعددية الأشكال واستخدامها، وقد تكون هي الآلية الوحيدة لذلك في العديد من لغات البرمجة الكائنية، ويمكن للصنف أن يرث السمات والعمليات من صنف أب parent class أو صنف رئيسي super class، وهذا يعني أن الصنف الجديد المطابق لصنف آخر في أغلب جوانبه لا يجب أن يعيد تنفيذ جميع التوابع التي في الصنف الأول، بل يمكن أن يرث تلك الإمكانيات ثم يغيرها لتنفيذ أمور مختلفة، كما في تابع calculateArea أعلاه، وسنستخدم للتوضيح مثالًا فيه هرمية أصناف حسابات بنكية، حيث نستطيع إيداع المال والحصول على الرصيد والقيام بعمليات سحب، ولبعض الحسابات نسبة ربوية (فائدة) سنفترض أنها تُحسب عند كل إيداع، إضافةً إلى بعض الرسوم الأخرى لعمليات السحب. الصنف BankAccount لنرى الآن كيف سيبدو هذا المثال، سننظر في السمات والعمليات الخاصة بالحساب البنكي في أكثر مستوىً عام له، ومن الأفضل هنا أن ننظر في العمليات أولًا، ثم نوفر السمات حسب الحاجة لدعم تلك العمليات، فمع الحساب المصرفي نستطيع القيام بما يلي: إيداع المال. سحب المال. التحقق من الرصيد الحالي. تحويل الأموال إلى حساب آخر. وسنحتاج إلى معرِّف الحساب المصرفي ID للحساب الآخر والرصيد الحالي، بالنسبة للمعرِّف فسنستخدم المتغير الذي نسند الكائن إليه، لكن إذا كنا في مشروع حقيقي فيجب إنشاء سمة خاصة بالمعرِّف تخزن مرجعًا فريدًا، كما سنحتاج إلى تخزين الرصيد، وعند تمثيل ذلك بلغة النمذجة الموحدة UML فسيبدو كما يلي: نستطيع الآن أن ننشئ صنفًا يدعم ذلك: # ‫ننشئ صنف اعتراض Exception مخصص class BalanceError(Exception): value = "Sorry you only have $%6.2f in your account" class BankAccount: def __init__(self, initialAmount): self.balance = initialAmount print( "Account created with balance %5.2f" % self.balance ) def deposit(self, amount): self.balance = self.balance + amount def withdraw(self, amount): if self.balance >= amount: self.balance = self.balance - amount else: raise BalanceError() def checkBalance(self): return self.balance def transfer(self, amount, account): try: self.withdraw(amount) account.deposit(amount) except BalanceError: print( BalanceError.value % self.balance ) الملاحظة الأولى: نتحقق من الرصيد قبل السحب، ونستخدم اعتراضًا لمعالجة الأخطاء، وبما أنه لا يوجد خطأ من النوع BalanceError في بايثون فسنحتاج إلى إنشاء واحد، وهو صنف فرعي من الصنف Exception مع قيمة نصية، وتُعرَّف قيمة السلسلة value سمةً لصنف الاعتراض لمجرد الاصطلاح فقط، وهي تضمن أننا نولد رسائل خطأ في كل مرة نرفع فيها اعتراضًا، ونلاحظ هنا أننا لم نستخدم self عند تعريف القيمة في BalanceError لأن value سمة مشتركة بين كل النسخ، وهي معرَّفة على مستوى الصنف وتُعرف بمتغير الصنف، ونصل إليها باستخدام اسم الصنف متبوعًا بنقطة BalanceError.value كما رأينا أعلاه، فعندما يولّد خطأ التعقب العكسي traceback -أي مسار مكان وقوع الخطأ ورجوعًا ضمن سلسلة الاستدعاءات- فسينتهي بطباعة سلسلة الخطأ المصاغة مع عرض الرصيد الحالي. الملاحظة الثانية: يستخدم التابع transfer الدالة التابعة withdraw/deposit الخاصة بالصنف BankAccount أو توابعه لتنفيذ عملية التحويل، وهذا أمر شائع في البرمجة الكائنية التوجه ويُعرف بالمراسلة الذاتية self messaging، ويعني أن الأصناف المشتقة تستطيع تنفيذ نسخها الخاصة من deposit/withdraw لكن يظل التابع transfer كما هو لجميع أنواع الحسابات. بما أننا عرّفنا BankAccount صنفًا قاعديًا فنستطيع أن نعود إلى الوراثة التي كنا نشرحها، ولننظر في أول صنف فرعي لنا فيما يلي. الصنف InterestAccount نستخدم الوراثة الآن لتوفير حساب يضيف نسبة ربوية -سنفترض أنها ‎3%- عند كل عملية إيداع، وستكون مطابقةً لصنف BankAccount القياسي عدا تابع الإيداع وبدء معدل النسبة، لذا نعيد كتابة تنفيذ هذه التوابع كما يلي: class InterestAccount(BankAccount): def __init__(self, initialAmount, interest=0.03): super().__init__(initialAmount) self.interest = interest def deposit(self, amount): super().deposit(amount) self.balance = self.balance * (1 + self.interest) الملاحظة الأولى: نمرر الصنف الرئيسي (أو الأب) معامِلًا في تعريف الصنف، ويكون هذا الصنف الأب في حالتنا هو BankAccount. الملاحظة الثانية: نستدعي super().__init__()‎ في بداية التابع ‎__init__()‎، والدالة super()‎ هي دالة خاصة وظيفتها معرفة الصنف الرئيسي، ويفيدنا ذلك عند وراثة أكثر من صنف رئيسي واحد فيما يسمى بالوراثة المتعددة، حيث نتجنب بعض المشاكل الغريبة التي قد تظهر إذا حاولنا استدعاء الصنف الرئيسي باسمه، لذلك يُفضل استخدام super()‎. ونبدأ الصنف الموروث باستدعاء التابع __init__ الخاص بالصنف الرئيسي، ولا نحتاج هنا إلا إلى بدء السمة interest التي قدمناها هنا، وبالمثل في استخدام super()‎ في تابع الإيداع، إذ يستدعي التابع deposit الخاص بالصنف الأب فلا نحتاج إلا إلى إضافة المزايا الجديدة للصنف InterestAccount. وهكذا نرى قوة البرمجة الكائنية التوجه وإمكانياتها، فبما أننا وضعنا BankAccount داخل الأقواس بعد اسم الصنف فقد صارت جميع التوابع موروثةً من BankAccount، ونلاحظ أن deposit تستدعي التابع deposit الخاص بالصنف الرئيسي بدلًا من نسخ الشيفرة، وسيحصل الصنف الفرعي على تلك التعديلات تلقائيًا إذا عدّلنا deposit الخاص بالصنف BankAccount بحيث يحوي تحققًا من بعض الأخطاء. الصنف ChargingAccount هذا الصنف مطابق للصنف BankAccount عدا أنه يطلب رسومًا افتراضية مقدارها ‎3$ لكل عملية سحب، وبالنسبة لـ InterestAccount فيمكن إنشاء صنف يرث من BankAccount ويعدّل التابعين init و withdraw: class ChargingAccount(BankAccount): def __init__(self, initialAmount, fee=3): super().__init__(initialAmount) self.fee = fee def withdraw(self, amount): super().withdraw(amount+self.fee) الملاحظة الأولى: نخزن الرسوم مثل متغير نسخة intance variable لنستطيع تغييره لاحقًا عند الحاجة، ونلاحظ أننا نستدعي __init__ مرةً أخرى مثل أي تابع آخر. الملاحظة الثانية: نضيف الرسوم إلى عملية السحب المطلوبة في استدعاء التابع الموروث withdraw الذي ينجز العمل الفعلي. الملاحظة الثالثة: نضيف أثرًا جانبيًا هنا حيث تُفرض رسوم تلقائيًا على عمليات التحويل، لكن هذا مطلوب على الأرجح لذا لا بأس به، وتجدر الإشارة هنا إلى أن إعادة الاستخدام هذه تحمل في طياتها احتمالية الآثار الجانبية غير المتوقعة التي يجب الحذر منها. ونمثل هذه الوراثة في UML بسهم مصمت من الصنف الفرعي إلى الصنف الرئيسي، فتُمثَّل هرمية الحساب البنكي الآن كما يلي: نلاحظ أننا سردنا التوابع والسمات التي تغيرت فقط أو أضيفت إلى الأصناف الفرعية. اختبار النظام للتحقق من عمل الهرمية السابقة بكفاءة، جرب تنفيذ الشيفرة التالية في محث بايثون أو بإنشاء ملف اختبار منفصل: from bankaccount import * # الحساب البنكي العادي a = BankAccount(500) b = BankAccount(200) a.withdraw(100) # a.withdraw(1000) a.transfer(100,b) print( "A = ", a.checkBalance() ) print( "B = ", b.checkBalance() ) # حساب للنسبة الربوية c = InterestAccount(1000) c.deposit(100) print( "C = ", c.checkBalance() ) # حساب للرسوم المفروضة d = ChargingAccount(300) d.deposit(200) print( "D = ", d.checkBalance() ) d.withdraw(50) print( "D = ", d.checkBalance() ) d.transfer(100,a) print( "A = ", a.checkBalance() ) print( "D = ", d.checkBalance() ) # حوّل من حساب الرسوم إلى حساب النسبة الربوية # حساب الرسوم سيطلب رسومًا، وحساب النسبة الربوية # يضيف نسبة ربوية print( "C = ", c.checkBalance() ) print( "D = ", d.checkBalance() ) d.transfer(20,c) print( "C = ", c.checkBalance() ) print( "D = ", d.checkBalance() ) أزل علامة التعليق الآن من السطر (a.withdraw(1000 لترى الاعتراض عمليًا. وبهذا نكون أتممنا مثالًا بسيطًا يظهر كيفية استخدام الوراثة لتوسيع إطار بسيط وإضافة مزايا قوية إليه، وقد رأينا كيف يبنى المثال على مراحل ويوضع برنامج اختبار للتحقق من نجاحه، مع أن اختباراتنا لم تكن كاملةً لأننا لم نغطِّ كل الحالات الممكنة، وكان من الممكن إدراج المزيد من الاختبارات، كما في حالة إنشاء حساب برصيد سالب. تجميعات الكائنات إحدى المشاكل التي قد تواجهها هي كيفية التعامل مع كائنات كثيرة، أو كيفية التعامل مع كائنات تنشئها في وقت التشغيل، فمن السهل إنشاء حسابات بنكية ثابتة كما فعلنا أعلاه: acc1 = BankAccount(...) acc2 = BankAccount(...) acc3 = BankAccount(...) etc... لكن في العالم الحقيقي لا تكون لدينا بيانات عن عدد الحسابات التي يجب إنشاؤها، فكيف نحل هذه المشكلة؟ لننظر فيها بتفصيل أكبر: نريد شكلًا ما من قواعد البيانات التي تسمح لنا بإيجاد أي حساب بنكي باسم مالكه أو رقم حسابه -بما أنه قد يكون للشخص الواحد عدة حسابات-، والعكس صحيح، ولكن ألا يشبه البحث عن شيء له معرّف خاص به القاموس؟ لنجرب استخدام قاموس في بايثون للاحتفاظ بكائنات منشأة ديناميكيًا: from bankaccount import BankAccount import time # أنشئ دالة جديدة لتوليد أرقام معرّفات فريدة def getNextID(): ok = input("Create account[y/n]? ") if ok[0] in 'yY': # check valid input id = time.time() # use current time as basis of ID id = int(id) % 10000 # حول إلى عدد صحيح وقلله إلى 4 أرقام else: id = -1 # وذلك سيوقف الحلقة التكرارية return id # أنشئ بعض الحسابات وخزنها في القاموس accountData = {} # قاموس جديد while True: # كرر حلقيًا بلا نهاية id = getNextID() if id == -1: break # تخرج إجباريًا من الحلقة التكرارية bal = float(input("Opening Balance? ")) # حول السلسلة إلى عدد ذي فاصلة عائمة accountData[id] = BankAccount(bal) # استخدم المعرِّف لإنشاء إدخال جديد في القاموس print( "New account created, Number: %04d, Balance %0.2f" % (id, bal) ) # دعنا نصل الآن إلى بعض الحسابات for id in accountData.keys(): print( "%04d\t%0.2f" % (id, accountData[id].checkBalance()) ) # ونبحث عن واحد فيها # أدخل محرفًا غير رقمي لرفع اعتراض وإنهاء البرنامج while True: id = int(input("Which account number? ")) if id in accountData: print( "Balance = %0.2d" % accountData[id].checkBalance() ) else: print( "Invalid ID" ) لا شك أن المفتاح الذي نستخدمه للقاموس قد يكون أي شيء يعرّف الكائن تعريفًا فريدًا، فقد يكون أحد سماته -مثل الرصيد balance- لكن الرصيد قد يتشابه بين الحسابات، ويتغير بالزيادة والنقص، وهكذا نفكر في الخيارات المتاحة إلى أن نصل إلى معرّف لا يتكرر، وهنا يمكن الرجوع إلى مقال البيانات وأنواعها، لقراءة القسم الخاص بالقاموس مرةً أخرى. يمثَّل هذا مرئيًا في UML باستخدام مخطط الصنف، ويُعرض القاموس مثل صنف له علاقة مع العديد من الحسابات البنكية، ونرى ذلك موضحًا بمحرف النجمة على الخط الموصل بين الأصناف، ونستخدم محرف النجمة هنا لأنه الرمز المستخدم في التعابير النمطية للإشارة إلى عدد من العناصر مقداره صفر أو أكثر، وهذا يُعرف بعدد عناصر العلاقة cardinality of the relationship، ويمكن رؤيته بعد طرق، لكن المجالات العددية للتعابير النمطية هي المستخدمة بكثرة لثرائها ومرونتها. نلاحظ استخدام القالب النمطي stereotype على القاموس Dictionary لإظهار أنه صنف مضمَّن، كما نلاحظ وجود الصندوق الملحق بالارتباط، والذي يوضح أن المفتاح هو قيمة المعرّف ID، فإذا كنا نستخدم قائمةً بسيطةً فلن يكون لدينا الصندوق ولكان الخط وصل بين الصنفين مباشرةً، وبهذا يتضح أننا نتجنب الحاجة إلى مخططات الكائنات الكبيرة والمعقدة باستخدام علاقات الأصناف وعدد العناصر في المجموعة cardinality، حيث نركز على العلاقات المجردة بين الأصناف بدلًا من التعامل مع عدد كبير من العلاقات الحقيقية بين النسخ المفردة. حفظ الكائنات إن فقد البيانات عند انتهاء المخطط هو أحد مشاكل السلوك السابق، لذا نريد طريقةً لحفظ الكائنات، ويمكن فعل ذلك باستخدام قواعد البيانات لكنه أسلوب متقدم، أما الآن فسنستخدم ملفًا نصيًا بسيطًا لحفظ الكائنات واسترجاعها، ورغم أن بايثون تحتوي على وحدتين لتنفيذ ذلك بكفاءة، وهما pickle وshelve، إلا أننا سنشرح الطريقة العامة التي تصلح لأي لغة، والطريقة العامة التي نقصدها هي إنشاء التابعين save وrestore في الكائن ذي المستوى الأعلى، ثم إعادة كتابتهما في كل صنف ليستدعيا النسخة الموروثة ثم يضيفا السمات المعرفة محليًا، وبالمناسبة يُستخدم مصطلح الثبات Persistence للإشارة إلى القدرة على حفظ الأشياء واستعادتها. class A: def __init__(self,x,y): self.x = x self.y = y self.f = None def save(self,fn): f = open(fn,"w") f.write(str(self.x)+ '\n') # convert to a string and add newline f.write(str(self.y)+'\n') return f # for child objects to use def restore(self, fn): f = open(fn) self.x = int(f.readline()) # convert back to original type self.y = int(f.readline()) return f class B(A): def __init__(self,x,y,z): super().__init__(x,y) self.z = z def save(self,fn): f = super().save(fn) # call parent save f.write(str(self.z)+'\n') return f # in case further children exist def restore(self, fn): f = super().restore(fn) self.z = int(f.readline()) return f # أنشئ النُسخ a = A(1,2) b = B(3,4,5) # احفظ النُسخ a.save('a.txt').close() # تذكر أن تغلق الملف b.save('b.txt').close() # اجلب النسخ newA = A(5,6) newA.restore('a.txt').close() # تذكر أن تغلق الملف newB = B(7,8,9) newB.restore('b.txt').close() print( "A: ",newA.x,newA.y ) print( "B: ",newB.x,newB.y,newB.z ) نلاحظ أن القيم المطبوعة هي القيم المسترجعة، وليست القيم التي استخدمناها لإنشاء النسخ. والمهم هنا هو إعادة كتابة التابع save والتابع restore في كل صنف واستدعاء التابع الرئيسي في خطوة أولى، ثم لا نتعامل في الصنف الفرعي إلا مع سمات ذلك الفرعي فقط، ومن البديهي أن تحويل السمة إلى سلسلة نصية وحفظها أمر متروك لك كونك مبرمجًا، لكن يجب إخراجها على سطر واحد، أما عند الاستعادة فببساطة يمكن عكس عملية التخزين، لكن تظهر هنا عقبة كبيرة في هذا الأسلوب، وهي أننا نحتاج إلى إنشاء ملف منفصل لكل كائن، وهذا قد يعني آلاف الملفات الصغيرة إذا كنا في بيئة برمجية لسوق حقيقي، حيث سيتعقد العمل بوتيرة متسارعة، وسنحتاج إلى استخدام قاعدة بيانات لحفظ الكائنات، وسنبحث في ذلك في مقال لاحق، أما الآن فيكفي أن تعلم أن المفاهيم الأساسية ستظل كما هي. دمج الأصناف والوحدات توفر الأصناف والوحدات آليات للتحكم في تعقيد البرنامج، ومن المنطقي مع ازدياد حجم البرنامج ازدياد الحاجة إلى دمج المزايا بوضع أصناف داخل وحدات، وتنصح بعض الهيئات بوضع كل صنف في وحدة منفصلة، لكن هذا يؤدي إلى وحدات كثيرة جدًا ويزيد التعقيد بدلًا من تقليله، والبديل الذي لدينا هو تجميع الأصناف معًا، ووضع المجموعة في وحدة، وإذا عدنا إلى مثالنا أعلاه فسنضع كل تعريفات أصناف الحساب المصرفي في وحدة واحدة هي bankaccount مثلًا، ثم ننشئ وحدةً منفصلةً لشيفرة التطبيق التي تستخدم الوحدة. يمكن تمثيل ذلك مرئيًا بواسطة UML بطريقتين، حيث يمكن تمثيل الجمع المنطقي للأصناف باستخدام حزمة، أو نستطيع تمثيل الملف الحقيقي مثل مكوّن: والهدف هنا أن تبدو أيقونة الحزمة مثل مجلد في أي برنامج مدير ملفات، أما الأيقونة الصغيرة التي في أعلى اليمين في أيقونة المكون فهي رمز المكون القديم في UML، وبما أن رسمها صعب في المخططات عند رسم الخطوط التي تظهر العلاقات بين المكونات فقد صغِّر شكلها في UML 2.0. هذا ما سنغطيه حول UML في هذه السللسلة، ويمكن الرجوع لمحركات البحث والويب للاستزادة من المراجع والتدريبات وأدوات رسم UML، رغم أن الأشكال سهلة الرسم في أي برنامج رسم متجهي. إذا أردنا تمثيلًا بسيطًا لذلك التصميم فسيكون كما يلي: # File: bankaccount.py # # Implements a set of bank account classes ################### class BankAccount: .... class InterestAccount: ... class ChargingAccount: ... ثم إذا أردنا استخدامه: import bankaccount newAccount = bankaccount.BankAccount(50) newChrgAcct = bankaccount.ChargingAccount(200) # هنا يمكن تنفيذ المهام التي تريدها لكن ماذا لو أراد صنفان في وحدتين الوصول إلى بيانات بعضهما بعضًا؟ إن أبسط حل لهذا هو استيراد كلتا الوحدتين وإنشاء نُسخ للأصناف التي نريدها، وتمرير نُسخ أحد الصنفين إلى توابع النسخة الأخرى، وتمرير الكائنات كاملةً من مكان لآخر ما هو إلا برمجة كائنية التوجه، وهنا ندرك أحد أسباب التسمية لهذا النوع من البرمجة، فلا نحتاج إلى استخراج سمات كائن وتمريرها إلى كائن آخر، بل نمرر الكائن كله، وإذا كان الكائن يستخدم رسالةً متعددة الأشكال للوصول إلى المعلومات التي يحتاج إليها فسيصلح التابع مع أي نوع من الكائنات التي تدعم الرسالة. لننظر في مثال واقعي لتوضيح ذلك، حيث ننشئ وحدةً قصيرةً نسميها logger تحتوي صنفين، هما Logger الذي يسجل النشاط داخل ملف، ويحتوي هذا الصنف على تابع واحد هو log()‎ الذي يأخذ معاملًا كائنًا قابلًا للتسجيل، أما الصنف الآخر فهو Loggable الذي تستطيع الأصناف الأخرى أن ترثه لتعمل مع logger: # File: logger.py # # Create Loggable and Logger classes for logging activities # of objects ############ class Loggable: def activity(self): return "This needs to be overridden locally" class Logger: def __init__(self, logfilename = "logger.dat"): self._log = open(logfilename,"a") def log(self, loggedObj): self._log.write(loggedObj.activity() + '\n') def __del__(self): self._log.close() نلاحظ أننا وفرنا تابع تدمير destructor هو __del__ لإغلاق الملف عند حذف كائن التسجيل أو كنسه garbage collected، وهو أحد التوابع السحرية الموجودة في بايثون كما نرى من الشرطتين السفليتين حوله، واللتين تشبهان ‎__init__()‎، مع فرق أن init يُستدعى عند إنشاء نسخة ما، أما del فيستدعى عندما يحذف كانس المخلفات النسخة، وقد لا يُستدعى إذا خرجت بايثون خروجًا غير متوقع، حيث سيكون لدينا في هذه الحالة مشاكل أكبر من استدعاء del أو عدم استدعائه. كما استدعينا سمة السجل ‎_log مع شرطة سفلية قبلها، وهو اصطلاح للتسمية في بايثون، كما في استخدام الكلمات ذات الأحرف الكبيرة لأسماء الأصناف، فالشرطة السفلية المفردة تعني أن السمة ليست مصممةً لنصل إليها مباشرةً، بل من خلال توابع الصنف. سننشئ الآن وحدةً جديدةً تعرِّف النسخ القابلة للتسجيل لأصناف حساباتنا المصرفية السابقة، لنستطيع استخدام وحدتنا: # File: loggablebankaccount.py # # Extend Bank account classes to work with logger module. ############################### import bankaccount, logger class LoggableBankAccount(bankaccount.BankAccount, logger.Loggable): def activity(self): return "Account balance = %d" % self.checkBalance() class LoggableInterestAccount(bankaccount.InterestAccount, logger.Loggable): def activity(self): return "Account balance = %d" % self.checkBalance() class LoggableChargingAccount(bankaccount.ChargingAccount, logger.Loggable): def activity(self): return "Account balance = %d" % self.checkBalance() استخدمنا الوراثة المتعددة في المثال أعلاه، حيث ورثنا صنفين رئيسيين وليس صنفًا واحدًا، وهذا غير ضروري في بايثون بما أننا نستطيع إضافة التابع activity()‎ إلى أصنافنا الأصلية ونحقق نفس الأثر، أما في لغات برمجة كائنية التوجه ثابتة مثل جافا أو C++‎ فسيكون هذا ضروريًا، لذا سنشرح التقنية هنا، قد تلاحظ أن التابع activity()‎ متطابق في الأصناف الثلاثة، وهذا يعني أننا نستطيع توفير بعض الكتابة على أنفسنا بإنشاء نوع وسيط من صنف حساب قابل للتسجيل يرث Loggable وله تابع activity فقط، ثم ننشئ ثلاثة أنواع حسابات قابلة للتسجيل بوراثتها من ذلك الصنف الجديد ومن صنف Loggable، كما يلي: class LoggableAccount(logger.Loggable): def activity(self): return "Account balance = %d" % self.checkBalance() class LoggableBankAccount(bankaccount.BankAccount, LoggableAccount): pass class LoggableInterestAccount(bankaccount.InterestAccount, LoggableAccount): pass class LoggableChargingAccount(bankaccount.ChargingAccount, LoggableAccount): pass لا يوفر هذا علينا الكثير من الكتابة، لكنه يعني أن علينا اختبار تعريف تابع واحد فقط والاحتفاظ به بدلًا من ثلاثة توابع متطابقة، وهذا النوع من البرمجة الذي يكون فيه لصنف رئيسي وظيفةً مشتركةً يسمى بالبرمجة الخليطة mixin programming، ويسمى الصنف الأدنى بالصنف الخليط mixin class، والناتج المتوقع من ذلك الأسلوب أن يكون لتعريفات الصنف النهائي متن صغير أو ليس لها متن أصلًا، لكنها تحوي قائمةً طويلةً من الأصناف الموروثة كما رأينا هنا. ومن الشائع أيضًا أن الأصناف المختلطة لا ترث من أي شيء بنفسها، رغم أننا فعلنا هذا هنا، فما هي إلا طريقة لإضافة تابع مشترك أو مجموعة من التوابع إلى صنف أو مجموعة أصناف باستخدام الوراثة، ويأتي مصطلح المختلطة mixin، من مجال صناعة المثلجات، حيث تضاف نكهات مختلفة إلى الفانيليا لإنتاج نكهة جديدة، وكانت أول لغة تدعم هذا الأسلوب هي لغة Flavors، والتي كانت إحدى لغات Lisp المشهورة وقتها. نأتي الآن إلى النقطة التي نُظهر فيها شيفرة التطبيق الخاص بنا بإنشاء كائن مسجل logger وبعض الحسابات المصرفية، ثم تمرير الحسابات إلى المسجل، رغم أنها معرّفة في وحدات مختلفة: # Test logging and loggable bank accounts. ############# import logger import loggablebankaccount as lba log = logger.Logger() ba = lba.LoggableBankAccount(100) ba.deposit(700) log.log(ba) intacc = lba.LoggableInterestAccount(200) intacc.deposit(500) log.log(intacc) نلاحظ هنا كلمة as المفتاحية التي تُستخدم لإنشاء اسم مختصر عند استدعاء loggablebankaccount. لا نحتاج إلى استخدام سابقة الوحدة module prefix بعد إنشاء النسخ المحلية، وبما أنه لا يوجد وصول مباشر من كائن إلى آخر بل من خلال الرسائل، فلا حاجة أن تشير وحدتا تعريف الصنف إلى بعضهما البعض مباشرةً، كما يعمل المسجل مع نسخ كل من LoggableBankAccount وLoggableInterestAccount لأنهما يدعمان واجهة Loggable، فالتوافق بين واجهات الكائنات من خلال تعددية الأشكال هو الأساس الذي تبنى عليه جميع البرامج الكائنية التوجه. يوجد نظام تسجيل أكثر تعقيدًا في وحدة المكتبة القياسية logging، لإظهار بعض التقنيات فقط، ونذكره هنا لتكون هذه المكتبة أول خيار نبحث فيه عند الحاجة إلى أدوات تسجيل في البرامج التي نكتبها. نأمل أن يكون هذا الشرح كافيًا لفهم البرمجة كائنية التوجه، مع الاستزادة من المصادر الموجودة في الويب أو قراءة أحد الكتب المذكورة في بداية المقال، أما الآن فسننظر في كيفية تنفيذ البرمجة كائنية التوجه في جافاسكربت وVBScript. البرمجة الكائنية في VBScript تدعم VBScript مفهوم الكائنات وتسمح بتعريف الأصناف وإنشاء نسخ منها، لكنها لا تدعم مفهوم الوراثة ولا تعددية الأشكال، وعلى هذا تكون لغة VBScript لغةً كائنية الأساس object based وليست كائنية التوجه، لكن مفهوم دمج البيانات والدوال في كائن واحد لا يزال صالحًا هنا، ويمكن تنفيذ صورة محدودة من الوراثة باستخدام تقنية تسمى التفويض delegation. تعريف الأصناف يُعرَّف الصنف في VBScript باستخدام تعليمة Class كما يلي: <script type=text/VBScript> Class MyClass Private anAttribute Public Sub aMethodWithNoReturnValue() MsgBox "MyClass.aMethodWithNoReturnValue" End Sub Public Function aMethodWithReturnValue() MsgBox "MyClass.aMethodWithReturnValue" aMethodWithReturnValue = 42 End Function End Class </script> وهذا يعرِّف صنفًا جديدًا اسمه MyClass مع سمة تسمى anAttribute تكون مرئيةً فقط للتوابع التي في الصنف، كما نرى من كلمة Private المفتاحية، ومن المتعارف عليه أن نصرح عن سمات البيانات بأنها Private، وعن أغلب التوابع بأنها Public، ويُعرف هذا باسم إخفاء البيانات، وميزته أنه يسمح لنا بالتحكم في الوصول إلى البيانات بإجبار استخدام التوابع التي تتحقق من جودة البيانات على القيم التي تمرَّر إلى داخل وخارج الكائن، وتوفر بايثون آليةً خاصةً بها لتنفيذ هذا لكنها خارج نطاق شرحنا. إنشاء النسخ ننشئ النسخ في VBScript بدمج الكلمتين المفتاحيتين Set وNew، ويجب أن يكون المتغير الذي أُسندت إليه النسخة الجديدة قد صرِّح عنه باستخدام كلمة Dim كما هو متبع في VBScript: <script type=text/VBScript> Dim anInstance Set anInstance = New MyClass </script> يؤدي هذا إلى إنشاء نسخة من الصنف مصرح عنها في القسم السابق وإسنادها إلى متغير anInstance، لاحظ أننا يجب أن نسبق اسم المتغير بـ Set، وأننا نستخدم كلمة New لإنشاء الكائن. إرسال الرسائل تُرسَل الرسائل إلى النسخ باستخدام نفس الصيغة النقطية . التي تستخدمها بايثون: <script type=text/VBScript> Dim aValue anInstance.aMethodWithNoReturnValue() aValue = anInstance.aMethodWithReturnValue() MsgBox "aValue = " & aValue </script> يُستدعى التابعان المصرح عنهما في تعريف الصنف، ولا توجد في الحالة الأولى قيمة معادة، أما في الحالة الثانية فسنسند القيمة المعادة إلى المتغير aValue، ولا يوجد شيء غير اعتيادي هنا باستثناء أن البرنامج الفرعي subroutine والدالة مسبوقان باسم النسخة. الوراثة وتعددية الأشكال لا تدعم VBScript أي آلية للوراثة أو تعددية الأشكال، لكن نستطيع محاكاة ذلك إلى حد ما باستخدام تقنية تسمى التفويض، وهذا يعني أننا نعرف سمةً للصنف الفرعي ليكون نسخةً من الصنف الرئيسي المفترض، ثم نعرف تابعًا لجميع التوابع الموروثة التي تستدعي تابع النسخة الرئيسية أو تفوض إليه، لننشئ صنفًا فرعيًا من MyClass كما هو معرَّف أعلاه: <script type=text/VBScript> Class SubClass Private parent Private Sub Class_Initialize() Set parent = New MyClass End Sub Public Sub aMethodWithNoReturnValue() parent.aMethodWithNoREturnVAlue End Sub Public Function aMethodWithReturnValue() aMethodWithReturnValue = parent.aMethodWithReturnValue End Function Public Sub aNewMethod MsgBox "This is unique to the sub class" End Sub End Class Dim inst,aValue Set inst = New SubClass inst.aMethodWithNoReturnVAlue aValue = inst.aMethodWithReturnValue inst.aNewMethod MsgBox "aValue = " & CStr(aValue) </script> نلاحظ هنا استخدام السمة الخاصة parent والتابع الخاص المميز Class_Initialise، فالأولى هي سمة تفويض الصنف الأب، والثاني هو المكافئ للتابع __init__ في بايثون لبدء النسخ عند إنشائها، أي أنه الباني في لغة VBScript. البرمجة الكائنية في جافاسكربت تدعم جافاسكربت الكائنات باستخدام تقنية تسمى النمذجة الأولية prototyping، وهذا يعني عدم وجود بنية صنف صريحة في جافاسكربت، بل نستطيع تعريف الصنف بمجموعة من الدوال أو مثل مفهوم شبيه بالقاموس يُعرف بالمهيئ initializer. تعريف الأصناف من أكثر الطرق شيوعًا لتعريف الأصناف في جافاسكربت هي إنشاء دالة بنفس اسم الصنف، ويكون هو الباني، لكنه لا يُحتوى داخل أي بنية أخرى: <script type=text/JavaScript> function MyClass(theAttribute) { this.anAttribute = theAttribute; }; </script> ربما تلاحظ كلمة this التي تُستخدم بنفس طريقة استخدام self في بايثون مثل مرجع نائب placeholder reference إلى النسخة الحالية، رغم أننا لا نحتاج في الغالب إلى إدراج this صراحةً في قائمة المعامِلات لتوابع الصنف، ونستطيع إضافة سمات جديدة إلى الصنف لاحقًا باستخدام السمة prototype المضمَّنة كما يلي: <script type=text/JavaScript> MyClass.prototype.newAttribute = null; </script> ويعرِّف هذا سمةً جديدةً لـ MyClass اسمها newAttribute، وتضاف التوابع من خلال تعريف دالة عادية؛ ثم إسناد اسم الدالة إلى سمة جديدة مع اسم التابع، ويكون للتابع والدالة نفس الاسم عادةً، لكن لا مانع من تغيير اسم التابع إلى شيء مختلف، كما يلي: <script type=text/JavaScript> function oneMethod(){ return this.anAttribute; } MyClass.prototype.getAttribute = oneMethod; function printIt(){ document.write(this.anAttribute + "<BR>"); }; MyClass.prototype.printIt = printIt; </script> ولا شك أن الأسهل تعريف الدوال ثم الباني، ثم إسناد التوابع داخل الباني، وهذا هو الأسلوب الافتراضي، لذا سيبدو تعريف الصنف كاملًا كما يلي: <script type=text/JavaScript> function oneMethod(){ return this.anAttribute; }; function printIt(){ document.write(this.anAttribute + "<BR>"); }; function MyClass(theAttribute) { this.anAttribute = theAttribute; this.getAttribute = oneMethod; this.printIt = printIt; }; </script> لكن ثمة طريقة أخرى في جافاسكربت، باستخدام صيغة مختلفة قليلًا لإنشاء دوال التابع، حيث تسمح جافاسكربت بتعريف الدالة كما يلي: square = function(x){ return x*x;} ثم نستدعي ذلك كما يلي: document.write("The square of 5 is: " + square(5)) فإذا طبقناه على تعريف الصنف الخاص بنا نحصل على: <script type=text/JavaScript> function MyClass(theAttribute) { this.anAttribute = theAttribute; this.getAttribute = function(){ return this.anAttribute; }; this.printIt = function printIt(){ document.write(this.anAttribute + "<BR>"); }; }; </script> يفضل بعض المبرمجين هذا الأسلوب لأنه يبقي تعريفات التابع داخل الصنف دون تلويث فضاء الاسم الخارجي، بينما يرى آخرون أن هذا أسلوب فوضوي وأصعب في القراءة، وأنت حر في اختيار أي الأسلوبين تفضل. إنشاء النسخ تُنشأ نسخ الأصناف باستخدام كلمة new المفتاحية كما يلي: <script type=text/JavaScript> var anInstance = new MyClass(42); </script> مما ينشئ نسخةً جديدةً اسمها anInstance. إرسال الرسائل لا يختلف إرسال الرسائل في جافاسكربت عن اللغات الأخرى، إذ نستخدم الصيغة النقطية: <script type=text/JavaScript> document.write("The attribute of anInstance is: <BR>"); anInstance.printIt(); </script> الوراثة وتعددية الأشكال يمكن استخدام آلية النمذجة الأولية في جافاسكربت للوراثة من صنف آخر -على عكس VBScript-، مع أنها أعقد من تقنية بايثون لكن يمكن التعامل معها وضبطها، لكنها ليست منتشرةً بين مبرمجي جافاسكربت، إن أساس الوراثة في جافاسكربت هو الكلمة المفتاحية prototype التي استخدمناها في التمرير في الشيفرة أعلاه، حيث يمكن إضافة مزايا إلى كائن ما بعد تعريفه، كما يلي: <script type="text/javascript"> function Message(text){ this.text = text; this.say = function(){ document.write(this.text + '<br>'); }; }; msg1 = new Message('This is the first'); msg1.say(); Message.prototype.shout = function(){ alert(this.text); }; msg2 = new Message('This gets the new feature'); msg2.shout(); /* msg1 وبالمثل بالنسبة لـ ...*/ msg1.shout(); </script> الملاحظة الأولى: أضفنا تابع alert جديد باستخدام prototype بعد إنشاء نسخة msg1 للصنف، غير أن الخاصية كانت متاحةً للنسخة الحالية ونسخة msg2 التي أنشئت بعد الإضافة، أي أن الخاصية الجديدة تضاف إلى جميع نسخ Message الحالية والجديدة، وتؤدي خاصية النمذجة الأولية هذه إلى إمكانية تغيير سلوك كائنات جافاسكربت المضمَّنة، بإضافة مزايا جديدة أو تغيير الطريقة التي تتصرف بها المزايا الحالية، لذا استخدمها بحرص إذا لم ترد أن تضيع وقتك مع زلات برمجية يصعب تعقبها. ومع ذلك لاستخدام prototype آليةً لإضافة وظائف إلى الأصناف الحالية عيوبه، التي منها تغيير سلوك النسخة الحالية، وتغيير تعريف الصنف الأصلي. ويوجد أسلوب تقليدي أكثر من الوراثة يمكن استخدامه، كما يلي: <script type="text/javascript"> function Parent(){ this.name = 'Parent'; this.basemethod = function(){ alert('This is the parent'); }; }; function Child(){ this.parent = Parent; this.parent(); this.submethod = function(){ alert('This from the child'); }; }; var aParent = new Parent(); var aChild = new Child(); aParent.basemethod(); aChild.submethod(); aChild.basemethod(); </script> يجب أن نلاحظ أن كائن child هنا له وصول إلى basemethod، دون أن يُعطى ذلك الوصول صراحةً، وإنما يرثه من الصنف الرئيسي بحكم أسطر الإسناد/الاستدعاء داخل تعريف الصنف Child: this.parent = Parent; this.parent(); وبهذا نكون ورثنا basemethod من الصنف الرئيسي Parent. يمكن استخدام نفس حيلة التفويض التي استخدمناها في VBScript، كما يلي: <script type=text/JavaScript> function noReturn(){ this.parent.printIt(); }; function returnValue(){ return this.parent.getAttribute(); }; function newMethod(){ document.write("This is unique to the sub class<BR>"); }; function SubClass(){ this.parent = new MyClass(27); this.aMethodWithNoReturnValue = noReturn; this.aMethodWithReturnValue = returnValue; this.aNewMethod = newMethod; }; var inst, aValue; inst = new SubClass(); // عرِّف الصنف الرئيسي document.write("The sub class value is:<BR>"); inst.aMethodWithNoReturnValue(); aValue = inst.aMethodWithReturnValue(); inst.aNewMethod(); document.write("aValue = " + aValue); </script> سنرى استخدام الكائنات والأصناف في دراسات الحالات والفصول التالية، ورغم أنه من الصعب أن يرى المبرمج المبتدئ كيف أن هذه البنية المعقدة تسهل كتابة وفهم البرامج، إلا أننا نأمل أن يتضح هذا المفهوم إذا رأيت استخدام الأصناف في البرامج الحقيقية، على أن ذلك ليس له فائدة كبيرة في البرامج الصغيرة، وإنما سيجعلها أعقد وأطول، لكن كلما زاد حجم البرنامج -أكثر من 100 سطر مثلًا-، فستعين الأصناف والكائنات على تنظيمه وتقليل كمية الشيفرات المكتوبة، ومن المهم أن تعلم أنه من الممكن تعلم البرمجة وكتابة برامج دون الحاجة إلى مفهوم البرمجة الكائنية التوجه أصلًا، فكم من مبرمج كتب برامج دون إنشاء صنف واحد طيلة حياته، لكن إذا استطعت استيعابها فإن فيها مزايا وتقنيات قويةً ومفيدةً. خاتمة نأمل في نهاية هذا المقال أن تكون تعلمت ما يلي: تغلِّف الأصناف البيانات والدوال في كيان واحد. تشبه الأصناف قاطعات البسكويت، حيث تُستخدم لإنشاء النسخ أو الكائنات. تتواصل الكائنات من خلال إرسال رسائل إلى بعضها البعض. عندما يستقبل كائن ما رسالةً فإنه ينفذ تابعًا موافقًا لها. التوابع هي دوال تُخزَّن مثل سمات للصنف. تستطيع الأصناف أن ترث التوابع والبيانات من أصناف أخرى، مما يسهل توسيع إمكانيات الصنف دون تغيير الصنف الأصلي. تعددية الأشكال هي القدرة على إرسال نفس الرسالة إلى عدة أنواع مختلفة من الكائنات، وسيستجيب كل منها بطريقته الخاصة. التغليف وتعددية الأشكال والوراثة كلها خصائص للغات البرمجة كائنية التوجه. تسمى لغة VBScript لغةً كائنية الأساس، لأنها لا تدعم الوراثة وتعددية الأشكال دعمًا كاملًا، رغم دعمها للتغليف. ترجمة -بتصرف- للفصل السابع عشر: Object Oriented Programming من كتاب Learning To Program لصاحبه Alan Gauld. اقرأ أيضًا المقال التالي: البرمجة الحدثية Event Driven Programming المساقة بالأحداث المقال السابق: التعابير النمطية في البرمجة التوابع السحرية (Magic Methods) في PHP البرمجة كائنية التوجه (Object Oriented Programming) في PHP البرمجة كائنية التوجه (Object Oriented Programming) في لغة سي شارب #C تطبيق البرمجة كائنية التوجه في لغة سي شارب #C - الجزء الثالث
    1 نقطة
  7. يوجد لدي سكربت قمت بتطويره يقوم بجلب أخر المشاركات من مدونات بلوجر أو اخر المشاركات من قسم معين ما أريده هو التحكم في قيمة المعرف (demo) وربطه بالمتغير printId الموجود ضمن الوظيفة createLastPosts بحيث يتم استدعاء هذه الوظيفة مع تحديد المعرف اللى هيتم طباعة البيانات بداخلها حتى اتمكن من استخدام هذه الوظيفة عدة مرات وفي أماكن مختلفة function lastPosts(json) { var jfe = json.feed.entry; for (i = 0; i < jfe.length; i++) { var jfei = jfe[i]; for (j = 0; j < jfei.link.length; j++) { if (jfei.link[j].rel == "alternate") { break; } } var postUrl = jfei.link[j].href; var postTitle = jfei.title.$t; var thumbnail; var thumbnailDefualt = "#"; try { thumbnail = jfei.media$thumbnail.url; } catch (h) { s = jfei.content.$t; a = s.indexOf("<img"); b = s.indexOf('src="', a); c = s.indexOf('"', b + 5); d = s.substr(b + 5, c - b - 5); if (a != -1 && b != -1 && c != -1 && d != "") { thumbnail = d; } else { thumbnail = thumbnailDefualt; } } var fixThumbnail = thumbnail.replace("s72-c", "s1600"); var printThumbnail = '<a class="grid-thumbnail" href="' + postUrl + '"><img class="lazyload" loading="lazy" src="' + fixThumbnail + '" alt="' + postTitle + '"></a>'; var printArticle = '<article class="grid-col article-posts swiper-slide"><div class="grid-fix-height"><div class="grid-box">' + printThumbnail + '<div class="grid-content"><h3 class="grid-title"><a href="' + postUrl + '">' + postTitle + "</a></h3></div></div></div></article>"; var printall = document.getElementById("demo"); printall.innerHTML += printArticle; } } function createLastPosts(url, count, printId) { var createScript = document.createElement("script"); var createAttrSrc = document.createAttribute("src"); createAttrSrc.value = url + "/feeds/posts/default?alt=json-in-script&max-results=" + count + "&callback=lastPosts"; createScript.setAttributeNode(createAttrSrc); document.getElementsByTagName("head")[0].appendChild(createScript); } function createLastPostsLabel(url, labelName, count) { var createScript = document.createElement("script"); var createAttrSrc = document.createAttribute("src"); createAttrSrc.value = url + "/feeds/posts/default/-/" + labelName + "?alt=json-in-script&max-results=" + count + "&callback=lastPosts"; createScript.setAttributeNode(createAttrSrc); document.getElementsByTagName("head")[0].appendChild(createScript); } <div id="demo1"></div> <div id="demo2"></div> // أريد عند استدعاء الدالة /* createLastPosts( 'url', رابط المدونة 'count', عدد المقالات اللى هيتم طباعتها 'printId' المكان اللى هيتم طباعة فيه المقالات ); */ // مثال createLastPosts( 'https://mo-222.blogspot.com', '3', 'demo1' ); last-post.html
    1 نقطة
  8. انا معرفش حاجة خالص عن البرمجة وكنت رايح معسكر لتعلم التصميم بس هما شغالين بلغة pHp وانا سألت حد قلي انا اللغة دي بلاش ابدء بيها وكده قالي الاحسن يأمة paython او javascript فانا كنت عايز اسأل حد فاهم يعني
    1 نقطة
  9. ليس من الحكمة أن تحصر عمليات تسويق كل منتجاتك وخدماتك في قناة إعلامية واحدة، بغض النظر عن مدى نجاحها الحاليّ، إذ تتغير المنصات واهتمامات العملاء باستمرار، وإن توقفت تلك القناة عن تحقيق النتيجة المطلوبة، فستكون في موقف لا تُحسد عليه. وأفضل نهج يمكنك اتباعه هو تطوير مزيج تسويقي يدمج الرسائل والتوعية ومتابعة العملاء عبر منصات تواصل اجتماعي متعددة، ومع أن هناك العديد من قنوات التسويق التقليدية الفعّالة، إلا أننا سنركّز على قنوات التسويق الرقمية في هذا المقال. فيما يلي الخطوات الرئيسية لتطوير مزيج تسويقي فعّال وبعض الاقتراحات المهمة لتطبيقها. الفت الانتباه قد يكون لفت الانتباه عبر الإنترنت صعبًا، حيث تحتاج إلى التفوق على منافسيك واستخدام منصات مختلفة وعرض قيمة منتجاتك وخدماتك، ولكن الخبر الجيد هو أن استخدام قنوات متعددة يزيد من فرصك في التفاعل مع العملاء الحاليين والمحتملين. إليك بعض وسائل لفت الانتباه عبر الإنترنت: استخدم إعلانات محرك البحث المدفوعة والمجانية يبحث الناس عن طلباتهم عبر الإنترنت باستخدام محرك بحث مثل جوجل Google أو بينج Bing أو ياهو Yahoo، لذا يمكنك شراء الإعلانات التي ستظهر لهم حسب المصطلحات التي يبحثون عنها، وعادةً ما تستخدم هذه الإعلانات نظام الدفع لكل نقرة pay-per-click والذي تدفع به مقابل كل نقرة على الإعلان فقط، ولكن عليك تحديد ميزانية حتى لا تسرف في الإنفاق. يمكنك كذلك إضافة منتجاتك مجانًا إلى خدمة جوجل شوبينج Google Shopping باستخدام إضافة ووكومرس WooCommerce الذي يُدعى Google Listings & Ads، حيث تتيح لك هذه الإضافة توصيل متجرك الإلكتروني بخدمة Google Merchant Center وGoogle Ads لتتمكن من إنشاء الحملات التسويقية من لوحة التحكم في WooCommerce. استخدم إعلانات الفيديو والعرض الرقمي يمكن أن تساهم الإعلانات على منصات الوسائط المتدفقة مثل يوتيوب Youtube وتويتش Twitch في لفت الانتباه إلى علامتك التجارية وزيادة المبيعات، لذا استخدم أداة Google Ads وغيرها لإنشاء إعلانات العرض الرقمي في مختلف المواقع ومنصات البريد الإلكتروني، وتميل هذه الإعلانات إلى أن تكون منخفضة الأداء لأنها إعلانات غير مخصصة، لكنها طريقة رائعة لعرض علامتك التجارية إلى المستخدمين الذي لم يسمعوا بنشاطك التجاري من قبل. استخدم إعلانات وسائل التواصل الاجتماعي تقدم جميع شبكات التواصل الاجتماعي الكبرى نظام إعلانات مدفوعة، ولكلّ نظام محاسن ومساوئ، فبعضها أسهل من ناحية الوصول إلى العملاء طبيعيًا من دون إنفاق الكثير من الوقت والمال، وبعضها أصعب في ذلك، ومع ذلك تجدها تتميز بإمكانية استهداف وإعادة استهداف عملائك وأكثر العملاء المحتمَلين، لذا ركّز أولًا على الاستفادة من بعض المنصات قبل التركيز على العديد منها. إحدى أفضل وسائل استهداف العملاء هي تقنية الجمهور المشابه Lookalike Audiences، حيث تتضمن قواعد بيانات العملاء الخاصة بك عناوين بريدهم الإلكتروني، أو أنهم قد اشتركوا في قائمة البريد الإلكتروني، أو أنهم من زوّار موقعك، ولما كانت هذه الجماهير تهتمّ بمنتجاتك، فغالبًا ما تؤدي الحملات الإعلانية التي تستخدم تقنية الجمهور المشابه Lookalike Audiences إلى معدلات تحويل أعلى موازنةً مع أنواع أخرى من الإعلانات. تحسين محركات البحث SEO إذا لم تكن تريد شراء الإعلانات، يمكنك أن تتعلم أساليب تحسين محركات البحث SEO حتى يظهر موقعك في نتائج البحث مجانًا، فباستخدام مزيج من الكلمات المفتاحية المختارة بعناية والمحتوى الذي يستهدف حاجات وتساؤلات ومشكلات عملائك، سيحظى موقعك بفرصة الظهور حين يبحث المستخدمون عنه، ويتطلب تحسين محركات البحث وقتًا طويلًا، لذلك لا تتوقع رؤية نتائج فورية، لكنه طريقة فعّالة وقليلة التكلفة لتوليد الزيارات موازنةً مع استخدام ميزانية حملة إعلانية ضخمة. حول الزوار إلى عملاء إن عدد الزوّار غير مهم إن لم تتمكن من تحويلهم إلى عملاء مفيدين لنشاطك التجاري، ففي النهاية، يجب أن توجّه جميع قنوات التسويق الخاصة بك العملاء إلى نقطة مركزية وهي موقعك الإلكتروني. وفي هذه المرحلة، ركّز على تحسين عملية تحويل الزوّار إلى عملاء يشترون منتجاتك أو خدماتك. وذلك يعني توفير العناصر التالية: صور جيدة للمنتج. إعلان احترافي. عرض واضح. إجراءات سهلة التطبيق. دعوات تحفيزية إلى إجراء. تذكرأنه يجب أن يقدم موقعك الإلكتروني الميزات التي وعدت المستخدم بها في أي قناة إعلامية جاء عبرها. المتابعة يُقال إن النجاح يكمن في المتابعة، لذا مهما كان نوع النشاط التجاري الذي تديره، فمتابعة العملاء الحاليين والمحتملين هي مفتاح تحقيق النمو الكبير الذي تسعى إليه، وبالنسبة إلى الأعمال القائمة على الاستجابة الفورية للحاجات العاجلة، تساعد المتابعة في البيع إلى العملاء مرات عديدةً وليس مرةً واحدةً؛ أما بالنسبة إلى الأعمال ذات دورة المبيعات الأطول، تساعد المتابعة في تحويل الزوّار الفضوليين إلى مشترين متحمّسين. تتضمن بعض قنوات شبكات التواصل الاجتماعي وسائل للمتابعة على عكس العديد من القنوات الأخرى، فمثلًا تستحيل إمكانية المتابعة في إعلان فيديو أو عرض رقمي، فهدفك النهائي هو توجيه المستخدمين إلى منصاتك الأساسية حتى تتمكن من إجراء محادثات أكثر تخصيصًا وتأسيس علاقة تسويقية دائمة. الرسائل الفورية تُعَد منصات التواصل الاجتماعي أداةً رائعةً لتحقيق تواصل أكثر تخصيصًا مع العملاء المحتملين، وخاصةً باستخدام الرسائل الفورية، إذ تضيف الطابع الإنساني على الشركات وتنشئ تواصلًا عاطفيًا بين شركتك والعملاء المحتملين، ويمنحك المستخدم موافقته على التواصل معه عبر الاشتراك بها. البريد الإلكتروني يُعَد البريد الإلكتروني أفضل منصة لتطبيق المتابعة التسويقية المستمرة، حيث يمكنك إرسال العروض المميزة والقسائم إلى كافة العناوين في قائمتك، أو يمكنك إرسال رسائل مستهدفة لشرائح أو أفراد معينين، كما يمكنك استخدام البريد الإلكتروني للاهتمام بالمسائل الحساسة، مثل عربات التسوق المهجورة، أو الطلبات الملغاة، أو الأسئلة المرسلة عبر النماذج الإلكترونية، أو مشكلات خدمة العملاء. وتساعدك أتمتة الردود في إدارة تلك المسائل بصورة أفضل، حيث تُرسَل من تلقاء نفسها. تتكامل أداة MailPoet مع WooCommerce بسلاسة، مما يمكّنك من أداء مهماتك بفعالية، ويمكنك أن تسأل المشترين عن رغبتهم بالاشتراك في قائمة البريد الإلكتروني الخاصة بك في صفحة الدفع، فهذا أفضل وقت لسؤالهم، لأنهم ملتزمون بالشراء وغالبًا ما يرغبون بتلقّي المزيد من الرسائل من شركتك، وبمجرد أن يشتركوا في قائمة البريد الإلكتروني، يمكنك مواصلة إرسال الصفقات والعروض والمحتوى المفيد. التتبع وإعادة الاستهداف يساعدك التتبع في متابعة العملاء الحاليين والمحتملين بفعالية أكبر، لذا استفد من الأدوات المتوفرة في أي قناة إعلامية تستخدمها لإعادة توجيه الإعلانات إلى جماهير معينة وإعادة البيع إلى مشترين سابقين، ولفهم عملائك فهمًا أفضل، تستخدم كل منصات الإعلانات علامات التتبع، إلا أن لها تسميات مختلفةً. في تحليلات جوجل Google Analytics وإعلانات جوجل Google Ads، يُشار إليها بعلامات التتبع tracking tags؛ أما في منصات التواصل الاجتماعي مثل فيسبوك Facebook وتويتر Twitter وتيك توك Tik Tok، فتُدعى بعلامات البكسل Pixel، وتطلق عليها خدمات التسويق بالبريد الإلكتروني أحيانًا اسم منارات الويب Web Beacons، وتستخدمها في تتبع معدلات التحويل والنقر، لذا يساعدك التتبع في إعادة استهداف عملائك، ومن ثم إيصال رسالة تسويقية أكثر ملاءمةً وتذكيرهم بمنتجاتك وتحسين معدلات التحويل. خدمة العملاء أخيرًا، يجري التسويق الأكثر تخصيصًا خلال التواصل المباشر مع عملائك عبر البريد الإلكتروني أو خدمة الدردشة المباشرة. قد تستفيد من هذه النصائح في خدمة العملاء: قدّم خدمةً رائعةً. كن ودودًا. كن مساعدًا. قدّم الحلول للمشكلات. أجب على التساؤلات. كن استباقيًا في التعامل. استغل الوقت. امنح الأولوية للعميل. ستساهم خدمة العميل المتميزة في تحسين نتائج كافة جهود المتابعة تحسينًا كبيرًا. الخلاصة يتمحور التسويق الناجح حول تجريب أساليب جديدة وقياس النتائج والتحسين المستمر، ولا يتمحور فقط حول زيادة عدد زوّار متجرك، لذا حسّن صفحات المنتج لزيادة معدل التحويل، واستخدم الأدوات التي تساعدك في متابعة الزوّار ومن ثم تحويلهم إلى عملاء. تحتاج معظم المتاجر إلى استخدام مجموعة من المنصات لتحقيق أهدافها من الانطباع الأول على العميل المحتمل إلى المتابعة بعد إنهاء عملية البيع، لذلك لا تعتمد على قناة تسويقية واحدة وكن مستعدًا لتجربة كل جديد. ترجمة -وبتصرّف- للمقال Find Your Online Marketing Mix: Tools You Need to Succeed. اقرأ أيضًا كيف يضاعف ترابط التسويق الرقمي الخاص بك من تأثير النتائج ما هي أفضل استراتيجية تسويق رقمي؟ 4 طرق لتسويق منتجاتك الرقمية على الانترنت المعايير العشرة لتقييم أداء التسويق الإلكتروني
    1 نقطة
  10. هل هناك أي طريقة للعثور على أسماء العلم وال Possessive Nouns باستخدام NLTK ؟ حيث أنه لدي نصوص وأريد استخراج أسماء العلم وال Possessive Nouns منها؟
    1 نقطة
  11. مرحبا", كيف الحال؟ أريد أن أستفسر كيف يمكن أن أعمل المشروع رابط للتجربة الحية للمشروع ؟
    1 نقطة
  12. من رسالة الخطأ يبدو أن git غير مثبت بشكل صحيح على جهازك، تحققي من تثبيته أولًا يمكنك مراجعة الفيديو التالي لمعرفة خطوات التثبيت
    1 نقطة
  13. شكرا" كثيرا" و لاكن لم أستطيع تنزيل الملف على github و لم أعرف السبب
    1 نقطة
  14. عندي مشروع تخرج موضوعه عن تصنيف مستخدمي شبكه بتكوين اريد مساعده
    1 نقطة
  15. انا لدي خبره في البرمجه هل من الممكن ان اتقدم عن سكراتش
    1 نقطة
  16. بالعكس تماما فدورة تطوير التطبيقات بإستعمال لغة php و إطار Laravel من بين أفضل الدورات و ذلك لأنها تحتوي على عدة مسارات تطبيقية التي ستُكسبك خبرة في التعامل مع المشاريع ستتعلم من خلال هذه المشاريع كيفية التحليل و البدأ في مراحل إنشاء المشروع و هذا الأمر سيُساعدك في الدخول إلى سوق العمل. و الشيء الجيد أنك ستحصل على متابعة من طرف مختصين لتحسين سيرتك الذاتية و حسابك الشخصي على مواقع العمل الحر. من الأفضل لك تحديد و تسطير الأهداف التي تريد أن تصل إليها و البدأ في مشوارك التعليمي و إذا واجهتك مُشكلة ما إبحث و استفسر عنها لأن ذلك هو السبيل في التطور، دع عنك التخوف و التردد لأنك ستبقى دائما في نفس النُقطة إذا لم تتخلص من مخاوفك فمسيرة الألف ميل تبدأ بخطوة، أنا متأكد تماما لو أنك إغتنمت الثمانية أشهر الماضية لكنت اليوم في مستوى آخر. تأكد أيضاً أن المجال واسع جدا و دائماً هناك أشياء جديدة فيجب على المطور دائما أن يواكب هذا التطور. @اسماعيل صدوقي يُمكن أن يُضيف بعض النصائح لك فهو متخرج من نفس الدورة.
    1 نقطة
  17. توضيح الفرق بين استخدام protected & private & public في الوراثة
    1 نقطة
  18. شكرا لك أخي الكريم على كل هدا الوقت ساستعيد إستكمال هده الدورة
    1 نقطة
  19. الخوارزميات هي طرق حل للمشكلات بطريقة فعالة، تستخدم في البرمجة عن طريق كتابة أكواد تحاكي عمل الخوارزمية، لن تحتاج للخوارزميات خلال العمل ولا تجعلها عائقاً أماك، ويوجد العديد من المصادر لتعمل الخوارزمية أو البحث في الانترنت لتطبيقها، أي عليك فقط فهم عام للمنطق المطلوب.
    1 نقطة
  20. يعني لأ أبدء بالخورزميا أدخل في دورة وسوف أتعلم أساسيات البرمجة
    1 نقطة
  21. حسنا، لن يختلف الأمر كثيراً أقدم نفس النصيحة، يوجد مسار أساسيات PHP يشرح كل ما تحتاجه للبدء في الدورة.
    1 نقطة
  22. 1 نقطة
  23. بداية نحتاج أن نوضح مما تتكون المواقع, أي موقع تراه يتكون من واجهتين الواجهة الامامية (front-end): وهي تتمثل في شكل الموقع والألوان المستخدمة وشكل الخطوط والصور وحجمها والمسافات بين العناصر , بمعنى آخر هو ما يظهر للمستخدم ويتفاعل معه وهو المتعلق بتصميم صفحات الانترنت , يتم فيه استخدام العديد من التقنيات ولكن الأساسية منها :Html Css , جافاسكربت وهناك العديد من التقنيات الأخرى المستخدمة في تصميم الواجهات الامامية الواجهة الخلفية (back-end): وهي ما تتعلق ب التعامل مع قواعد البيانات مثل اضافة وتعديل وحذف البيانات ,على سبيل المثال عند تسجيل عضوية جديدة في الموقع يتم اضافة البيانات المدخلة الى قاعدة البيانات الخاصة بالموقع لكي يتم حفظها, ويتعامل أيضا مع حماية الموقع من الهجمات وغيرها من الأمور التي تحدث في الواجهة الخلفية , يمكنك استخدام لغة php او جافاسكربت أو بايثون , وكل لغة من اللغات الثلاثة لديها نقاط القوة والضعف , لمعرفة الفروقات بينها يمكنك مشاهدة التعليقات الموجودة أسفل السؤال التالي
    1 نقطة
  24. مرحبا, استخدم PHP/laravel لدي جدول للطلبيات و ارغب في معرفة أكثر وقت تتم فيه الطلبات, مثلا اليوم يتم شراء العديد من المنتجات في فترة من 4 مساءا الى 6 مساءا هذا ما قمت بالمحاولة فيه: $collection = $this->totalOrders->get()->map(function ($query) { return $query->created_at->format('H:i:s'); }); dd($collection); بحيث تحصلت على كل تواريخ الطلبات هذا اليوم: Illuminate\Support\Collection {#1979 ▼ #items: array:6 [▼ 0 => "10:56:47" 1 => "17:19:27" 2 => "17:19:27" 3 => "00:15:41" 4 => "00:15:41" 5 => "00:15:41" ] #escapeWhenCastingToString: false } هل يوجد طريقة افضل للقيام بذلك؟ او كيف يمكنني الاكمال من هنا؟ شكرا لكم.
    1 نقطة
  25. المصفوفة العادية هي كائن برمجي يحوي عدد ثابت من العناصر ويتم تحديد عدد العناصر عن كتابة البرنامج بقيمة ثابتة (أو ضمن متغير)، فمن المساوئ الناتجة هي: حجز عدد عناصر أكبر من اللازم مما يؤدي لحجز ذاكرة بشكل غير ضروري حجز عدد أقل من اللازم وهنا لا يمكن تخزين العناصر الأخرى Vector هو صنف يسمح بتعريف مصفوفات ديناميكية الحجم أي تحوي عدد متغير من العناصر، أي عند التهيئة يمكن إنشاء مصفوفة Vector بطول 0 ثم إضافة العناصر إليها حسب الطلب، أو حتى إضافة عناصر لمصفوفة Vector قد تم إنشائها مسبقاً باستخدام التابع ADD، نلاحظ أن عدد العناصر غير ثابت، ويمكن حذف العناصر بالتابع remove والحصول على قيمة عنصر من التابع get يمكن الحصول على مثال من السؤال:
    1 نقطة
  26. عند عمل أي برنامج حاسوبي يمكن أن يعترضه بعض الأخطاء البرمجية (خطأ كتابة في الشيفرات) أو أخطاء منطقية (خطأ في جلب قيمة من مصفوفة باستعمال دليل أكبر من حجم المصفوفة أو قسمة على 0) وغيرها الفئات التي تم وضعها في السؤال: Checked Exception: يعتبر خطأ برمجي يحدث أثناء ترجمة البرنامج وقبل تشغيله مثل تخزين نص في متغير من نوع رقمي java.lang.String cannot be converted to int Unchecked Exception: تعني خطأ منطقي يحدث أثناء تشغيل البرنامج مثل الوصول للعنصر رقم 10 من مصفوفة فيها 5 عناصر java.lang.ArrayIndexOutOfBoundsException: 10 Error: وهو خطأ يحدث بسبب الجهاز الذي نشغل البرنامج عليه مثل عدم وجود ذاكرة كافية JVM is out of Memory
    1 نقطة
  27. عند إرسال بيانات إلى جهاز حاسب عبر الشبكة يتم إرساله عبر عنوان الشبكة ip address, ومن ثم عند الوصول إلى الشبكة المحددة يتم البحث عن الحاسب عبر العنوان المادي physical address أو mac address ومن ثم يتم إرسال البيانات له السؤال هنا, كيف يتم تحديد أي برنامج سوف يستقبل تلك المعلومات؟ حيث أن لدينا مئات البرامج والخدمات التي تعمل على الحاسوب في نفس ذات الوقت فكيف نستطيع تحديد أي واحد منهم يقوم بإستقبال تلك المعلومات؟ الإجابة هي المنفذ Port حيث أن عنوان الشبكة يستخدم لتحديد أي شبكة تسمع الطلب, والعنوان المادي لتحديد أي جهاز داخل الشبكة يستمع إلى الطلب, بينما المنفذ لتحديد أي برنامج داخل الجهاز يستمع إلى الطلب, فإذًا في حالتنا تلك لن تقوم الmysql بالإستماع إلى أية طلبات إلا االطلبات التي يتم إرسالها إلى المنفذ 3306
    1 نقطة
  28. عندما تقوم بإستضافة تطبيقات ذات الصفحة الواحدة Single Page Application (SPA) فسيتم إدارة أغلب المسارات من خلال كود الواجهة الأمامية عبر JavaScript (لكي لا يتم إعادة تحميل الصفحة من الخادم) وبالتالي يجب أن يقوم الخادم بإرسال ملف index.html عند زيارة أي مسار (حتى إن لم يوجد هذا المسار في تطبيق فلاسك Flask) وذلك من خلال الكود التالي: from flask import Flask, send_from_directory import os # يجب تحديد المجلد الصحيح الذي يحتوي على ملفات الواجهة الأمامية هنا app = Flask(__name__, static_folder='client/build') @app.route('/', defaults={'path': ''}) @app.route('/<path:path>') def serve(path): if path != "" and os.path.exists(app.static_folder + '/' + path): return send_from_directory(app.static_folder, path) else: return send_from_directory(app.static_folder, 'index.html') if __name__ == '__main__': app.run() بهذا الشكل سوف يتم إرجاع الملف index.html في كل المسارات غير المحددة بالفعل في التطبيق، أي أن أي مسار آخر موجود في فلاسك Flask سوف يعمل بدون مشكلة.
    1 نقطة
  29. عندما تحاول الوصول إلى التطبيق الحالي current_app أو أي شيء يستعمله سوف تحصل على رسالة الخطأ التالية: RuntimeError: Working outside of application context. وهي مشابهة لرسالة الخطأ التي لديك، حيث أنك تحتاج إلى إستخدام app_context لعمل Push للـ context الخاص بالتطبيق بالشكل التالي: # في ملف app.py app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'My connection string' db.init_app(app) # لاحظ كيفية إستخدام الجملة with لتمرير app_context with app.app_context(): db.create_all() يمكنك أيضًا أن تقوم بإستخدام التابع push مباشرة (في حالة كنت تستعمل سطر الأوامر)، كالتالي: from flask import Flask from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy() def create_app(): app = Flask(__name__) db.init_app(app) return app في سطر الأوامر: >>> from yourapp import create_app >>> app = create_app() >>> app.app_context().push() الطريقة الأخرى هي تمرير app نفسه إلى db.create_all: db.create_all(app=create_app())
    1 نقطة
  30. يمكنك استخدام مكتبة جافا التي تتيح لك التعامل مع ملفات PDF ومن هذه المكتبات يوجد pdfbox يمكنك تحميلها من الموقع الرسمي لهم، ثم تضمينها في مشروعك، وبعدها عليك قراءة التوثيق لكيفية التعامل معها لإنتاج ملف PDF وتحويل مخرجات تطبيقك عن طريقها للملف PFD الخاص بك مثال بسيط import java.io.IOException; import org.apache.pdfbox.pdmodel.PDDocument; public class Document_Creation { public static void main (String args[]) throws IOException { //إنشاء غرض برمجي للتعامل مع الملف PDDocument document = new PDDocument(); //حلف الوثيقة ي مسار معين document.save("C:/PdfBox_Examples/my_doc.pdf"); System.out.println("PDF created"); //Closing the document document.close(); } } يوجد بعض الأغراض البرمجية الهامة في المكتبة // تمثل الملف بالكامل PDDocument document = new PDDocument(); // تمثل صفحة واحدة PDPage my_page = new PDPage(); // إضافة الصفحة لملف الوثيقة document.addPage(my_page);
    1 نقطة
  31. يمكن استخدام الكلمة المفتاحية ORDER BY التي تعمل على ترتيب القيم المختلفة حسب عمود ما في الجدول مثال لاستعلام يعيد بيانات المستخدمين مرتبة حسب العمر SELECT DISTINCT name FROM users ORDER BY age; الشكل التلقائي يعيد البينانات بترتيب تصاعدي ascending من الأصغر للأكبر بدون وضع ASC (لا حاجة له)، ولعمل العكس نضيف DESC في نهاية الاستعلام ليصبح ترتريب تنازلي descending إقرأ عن الخاصية من توثيق موسوعة حسوب SQL/order_by
    1 نقطة
  32. ليست هناك قواعدُ تنجح بالنسبة لجميع الناس؛ وبما أني عملتُ مستقلًا على نحو متقطع لأكثر من عشر سنوات، فقد أنشأتُ قائمةً تتضمن أفضل النصائح حول كيفية تحقيق النجاح في هذا المجال. ربما تكون أيها القارئ تطبّق فعلًا بعضَ تلك النصائح أو أمورًا مشابهة لها، وهذا عظيم، ويَحدُوني أملٌ في أن تعثرَ على نصيحة على الأقل، أو على ثلاث، يمكن أن تساعدك على النجاح فيما تفعله. وبهذا الصدد، إليك أهم نصيحة على الإطلاق في هذا الشأن: أنت الآن في عصر صناعة تصميم الويب سريعةِ التغيُّر، وهذا يجعل لزامًا عليك ألا تتوقف عن التعلُّم، ولكنّ في نفس الوقت عليك أن تُحِبَّ ما تفعله للنجاح فيه؛ وعندما تحقق ذلك النجاح، ستتمكن من تقديم خدماتٍ نهائية أعلى مستوىً لعملائك، وتضاغف بفضل ذلك ما تتفاضاه من مال لقاء عملك مستقلًا في نهاية المطاف. 1. أنشئ خطة تجارية أو تسويقية هذا أول ما عليك فعلُه؛ وحتى لو جمّعت في ذهنك الأفكارَ المطلوبة، فستحقق كتابتُها على الورق الكثيرَ من التقدم، وستستحق بلا شك الجهدَ الإضافي المبذول لهذا الغرض، فإنجاز ذلك لا "يدفعُكَ" فقط إلى التفكير مليًّا في مختلف المسائل المهمة ذات الصلة، وفي استشراف التحديات المحتمَلِ ظهورُها قبل أن تحدُث، ولكنه أيضًا قد يسهِّلُ عليك كثيرًا الحصولَ على المساعدة المطلوبة من الشركاء أو المستثمرين التجاريين المحتملين عندما تكون بحوزتك خطة تجارية جيدة تعرضها عليهم. عليك معرفة كيف ستعثر على عملاء، وأن تمتلك خطةً قابلةً للتطبيق. 2. خطط لأيامك مسبقا خصِّص لنفسك ساعةً أو ما شابه عند بداية كل أسبوع عمل، أو في آخر ساعة عمل من الأسبوع، وذلك للتخطيط للأسبوع المقبِل. بذلك سيسهُل عليك التخطيطُ للكيفية التي ستُمضي فيها ذلك الوقت بهدف التقيّد بالمواعيد النهائية المستقبلية المحدَّدة لإنهاء العمل. تزداد أهميةُ ذلك بازدياد المشاريع المستمرة التي تعمل عليها. 3. استخدم برمجيات مجانية ولكن اشتر بعض الأدوات الفاخرة التي ستجعلك أكثر إنتاجية قد يمثّلُ البدءُ بالعمل بصفتك مستقلًا تحدّيًا من الناحية الاقتصادية؛ ومن شأن انتقائك لبرمجيات مجانية وجيدة أن يوفّر عليك كثيرًا من التكاليف دون أن تضطرّ بالضرورة إلى التخلّي عن كثير من المقومات الوظيفية. فمجانيةُ البرمجيات لا تعني دائمًا أنها غير جيدة، وهناك المزيد والمزيد من الخيارات المتاحة كل يوم؛ لذا فلتحرِص على التحقق مما يمكن استخدامه منها بشأن عملك. وعندما تشتري جهاز حاسوب أو كاميرا أو جهازًا لوحيًا أو طابعة، تحقق أيضًا من البرمجيات التي تأتي مع كل من تلك الأجهزة؛ فقد تكون بصدد تلقّي مفاجأة إيجابية. لا تحاول شراء كل شيء، بل اشترِ فقط الأدوات الفاخرة التي سوف تستخدمها كل يوم؛ فأنا مثلًا لا أستخدم إطلاقًا قوالبًا مجانيةً عند تأسيس موقع إلكتروني؛ بل أختار دائمًا قوالب وإطارات عمل ووردبريس ذات جودة. ولكن، أكرر القول إنك لا تحتاج إلى تكبُّد النفقات على ما تحدثنا عنه في المثال السابق إذا كنت تعمل في تصميم الرسومات مثلًا؛ أما إن كنت تصمم مواقعًا إلكترونيةً بانتظام لعملائك، فيهمّك كثيرًا فعلُ ذلك لتزيد إنتاجيتك بعشرة أضعاف. 4. صمم شعارا جذابا يتطلب تكريسُ هُوية احترافية فريدة لنفسك تضمنُ لك التميُّزَ، ضرورة بذلَ جهد شاقّ لكي تظهر بمظهر احترافي وتجذبَ العملاء المحتملين، فتصميمك لشعار جذّاب (أو الطلب من مختصٍ إنجاز ذلك لك، إذا لم يكن لديك المهارات اللازمة لفعله بنفسك) مِن شأنه جعلُك تبدو أكثر احترافيةً وأسهل اكتشافًا من جانب العملاء المحتملين، فامتلاك شعار مميز، واستخدامه على بطاقات العمل Business Cards، والمواقع الإلكترونية وغير ذلك، سيمنحك تلك الإطلالة الاحترافية التي قد تُكمِل النقصَ المطلوب للحصول على عملاء جدد. 5. تعلم أن تقول لا إن لم يكن لديك الوقت الكافي لعميل آخر في الوقت الحالي، فمن المهم أن تدرك ذلك وتقول لا؛ فذلك هو الخيار الأنسب لك، وللعميل الذي تُنجِز له عملًا في الوقت الحالي، وللعميل أو العملاء الذين يقصدونك للحصول على خدماتك. ومن أسوأ الخيارات أن تقبل العمل لصالح عدة عملاء في آن معًا، بحيث يتضرر العميل أو العملاء الذين تنجز لهم عملًا في ذلك الوقت. إذًا عليك الحرص دائمًا على تكريس وقت كافٍ لتقدّم أفضل ما تستطيع من خدمة لعملائك الحاليين؛ فعملُك لعدد كبير من العملاء في الوقت ذاته قد يُضعِف جودة أدائك في جميع تلك المهام التي تنجزها. 6. أنشئ مدونة أو موقعا إلكترونيا في عصر الإنترنت الذي نعيش فيه، يمكن أن يضيف امتلاكُك موقعًا إلكترونيًا الكثير إلى عملك، فلا يجعلك ذلك تبدو أكثر احترافيةً فحسب، بل يفتح لك الباب أيضًا إلى جذب عملاء جدد، فالكثير من العملاء يتصفحون الإنترنت بحثًا عن أشخاص ينجزون لهم مشاريعهم المستقبلية، وإذا لم يجدوك هناك، فلن يعلم بك أحد. 7. حدث موقعك الإلكتروني بانتظام هل تمتلك بالفعل مدوَّنة أو موقعًا إلكترونيًا؟ عظيم إن كان جوابك هو نعم، ولكن ذلك لا يكفي؛ بل عليك تحديث ذلك الموقع أو المدوّنة بانتظام إن أردت زيادة قيمة أيٍّ منهما، فإذا زار عميلٌ موقعكَ الإلكتروني، ثم وجد أنك لم تحدّّثه منذ زمن طويل جدًا، فقد يدفعه ذلك إلى اختيار مستقلٍ غيرك لإنجاز عمله. يتطلب تحديث موقعك الإلكتروني حوالي ساعة من وقتك بين الفينة والأخرى، لكنه يمكن أن يعود عليك بنتائج ممتازة تتمثّل في اجتذاب عملاء جدد. 8. امنح زوارك على الإنترنت شيئا مجانيا من الجيد دائمًا أن تمنح مزايا إضافية لزائري موقعك الإلكتروني، فإذا كنت تعمل في مجال التصميم، يمكنك التفكير في إضافة ملمس بصري أو أزرار مجانًا؛ فمن شأن ذلك أن يجذب مزيدًا من الزوّار إلى موقعك الإلكتروني، وقد يستقطب أيضًا عملاء جدد يطلبون الحصول على خدماتك. أو ما رأيك في أن تمنح خصمًا -في حدود نسبة مئوية محددة- لكل مَن يزور موقعك الإلكتروني على أول طلب يكلّفك بإنجازه له؟ نؤكد لك مجددًا أن ذلك قد يجعلك تغدو مميزًا بحيث تجذب عملاء جدد. 9. استخدم وسائل التواصل الاجتماعي باتت وسائلُ التواصل الاجتماعي في يومنا هذا مكانًا تُنسَج فيه العلاقات بين الأشخاص؛ فباستخدام تلك المنصات يمكنك التواصل مع عملاء وشركاء محتملين من حول العالم بصرف النظر عن مكان إقامتك. ومن الأساسيّ أن تمتلك حسابًا على تويتر Twitter، كما عليك التفكير بإنشاء حساب على فيسبوك Facebook، والاشتراك بمنتديات ذات صلة بالخدمة التي تقدّمها والعمل الذي تمارسه بوصفك مستقلًا. وإذا كنت تعمل في مجال التصميم، فلتطلع على يوتيوب YouTube، وعلى الشبكة الاجتماعية ديفيانت آرت deviantArt أيضًا. بوسعك الترويج لعملك على العديد من وسائل التواصل الاجتماعي مثل التي أتينا على ذِكرها أعلاه، بشرط ألا تُرسل عددًا كبيرًا من الرسائل على تلك المنصات لأشخاص لم يطلبوها، كما هو الحال بالنسبة لرسائل البريد الإلكتروني المزعجة غير المرغوب فيها Spam. 10. اعثر على حلفاء قد يعني الكثيرَ وجودُ حلفاء لك؛ فالتواصل مع الآخرين عبر وسائل التواصل الاجتماعي، أو حتى نشرُ سمعة حسنة لعملك من خلال أفراد أسرتك وأصدقائك، قد يروّج لعملك على النحو الذي تحتاج إليه، كما قد يُفيدك إنشاءُ علاقات مع أشخاص بوسعهم تقديم خدمات للعملاء لا يمكنك أنت تقديمُها؛ إذ تغدو بذلك قادرًا على توفير حزمة خدمات أوسع يحتاج إليها عملاؤك. فإذا أحلتَ أحد عملائك إلى شخص تعرفه وبوسعه تقديم خدمة مناسبة لذلك العميل، فقد يأتي يومٌ تجد فيه أن أحد أولئك الحلفاء وصَلَك بعميل يحتاج إلى خدمتك. 11. ادخر للأيام الصعبة رغم أن عملك قد يسير على خير ما يُرام، فلا بد كل فترة من أن يمرّ شهر أو اثنان لا يكون الوضع فيهما كذلك. فكونُك مستقلًا يعني أنك ستتأثر بالتغيرات التي تطرأ على السوق، ونصيحتي لك هنا أن تدخر جزءًا من المال الذي تجنيه كل شهر؛ ادّخر ذلك المال في حساب توفيرٍ خاص بك تجعله بمثابة حاجز أمانٍ مالي عندما تمر فترات لا تحصل فيها على عمل. وتأكّد أنك لن تندم على فعل ذلك؛ إذ لا يليق بك أن تُفسِدَ عليك بعضُ الفواتير القليلة كلَ شيء في حياتك في شهر لا تحصل فيه على عمل. 12. كن مبدعا هناك عدة طرق لتكون مبدعًا، ولتحصل على عملاء جدد، ولتحقيق استغلال أفضل للتجهيزات والمساحة المكتبية. تتضمن بعضُ الأمثلة الإبداعية تحديثَ حاسوبك إذا لم تكن قادرًا على شراء واحد جديد، أو إعادة ترتيب غرفتك في المنزل لتحصل على مساحة كافية للعمل إذا لم تستطع تحمل تكاليف استئجار مكتب خارج منزلك، أضف منتجًا أو خدمةً جديدةً إلى القائمة الحالية التي تتضمن المنتجات والخدمات التي تقدمها، أو اسأل أفراد أسرتك وأصدقاءك إذا كانوا يعرفون أحدًا بحاجة إلى خدماتك. وهنا ستكون أمامك خيارات عديدة، وكل ما تحتاج إليه أن تفكّر بإبداع. 13. كافئ العملاء ذوي الولاء في سوق تشهد تنافسًا مستعِرًا، عليك بذل جهدك لضمان أن يعود إليك العملاء الذين قدّمتَ لهم خدمات طالبين الاستعانة بك مجددًا. إن التعامل بودٍّ مع العملاء، وتبنّي ذهنية تقديم الخدمات على نحو يترك انطباعًا حسنًا لديهم، شرطان ينبغي توافرهما لديك دائمًا، ولا تنازُلَ عنهما بأي شكل، لكن ما رأيك بتقديم حسم للعميل الذي يقصدك مرةً أخرى طالبًا خدماتك؟ أو ما رأيك بإرسال عروضٍ خاصة لهم متعددة الأنواع؟ استخدِم خيالك، وطبِّق هذه الأمور ضمن خطة العمل الخاصة بك. اجعل العميل راغبًا في العودة إليك؛ وستحظى بأفضل فرص الاستمرارية الممكنة. 14. عامل كل عميل كما لو أنه الوحيد لديك من المهم إذًا تقديم عروض لعملائك كما أشرنا في النصيحة السابقة، ولكن تذكَّر أن عليك أن تتبنى ذهنية تقديم الخدمات لعملائك على نحو يجعلهم راضين؛ فإذا أحسَّ العميل بأنه مُحاطٌ باهتمام وتقدير، فسيغدو ذا ولاء لك. استخدِم لغةً إيجابيةً لدى الحديث مع العميل أو الكتابة له. ولا تخشَ القول له إنك ستبذل جهودًا استثنائيةً لضمان أن تحظى الخدمة أو المنتج الذي تقدمه له برضاه التام، واحرص على إشعار عميلك بأنك تقدّر التقييم والملاحظات التي يوجهها لك. إنّ اتباعك لما سبق ذِكره يتيح لك جعلَ خدماتك جذّابة، ويحقق رضا عملائك. ولا تنسَ أنّ عملاءك الحاليّين قد يمثّلون أفضَل مَن يروِّج لك. 15. لا تشتت نفسك في وقت العمل إذا قررتَ العمل من الساعة الثامنة صباحًا إلى الرابعة بعد الظهر مثلًا، فلتنفّذ ذلك، وإذا كانت هناك حوائج عليك قضاؤها، أو حسابات بريدية خاصة تود تفقّدها، أو مكالمات هاتفية شخصية أو غيرها، فمن شأن تلك الأمور أخذ كثير من وقتك الذي أنت بحاجة ماسّة إليه في عملك. تعهّد لنفسك بألا تفعل ذلك إلا عندما لا يكون لديك عمل، أو قبل البدء به أو بعد الانتهاء منه، أو أثناء استراحة الغداء. قد لا يبدو ذلك عبئًا ثقيلًا عليك، ولكنني رأيتُ العديد من المستقلين الناجحين الذين تُفسد الفوضى يومهم لأنهم لم يكونوا ماهرين في إدارة وقتهم على نحو صحيح. 16. اعرف متى تبدأ ومتى تتوقف لا يقل أهميةً عما ذكرناه في الفقرة السابقة، أن تبدأ عندما يجب أن تبدأ، وتتوقف عندما ينبغي لك أن تتوقف. قد يكون عليك الاستعداد للعمل لساعات إضافية بين الفينة والأخرى للحفاظ على استمرارية عملك، ولكنّ من الضروري أن تخصص لنفسك وقت فراغ أيضًا؛ فأنت بحاجة إلى التعافي، وإشغال ذهنك بأمور أخرى، وإلا أُصِبتَ بالاحتراق الوظيفي burnout وأفسدتَ حياتك. فكما طالت ساعاتُ عملك في كل مرة، قلَّت إنتاجيتُك. لذا احرص على اتّباع قواعدك الخاصة حول توقيت بدء العمل من جهة والتوقف عنه من جهة أخرى. 17. رتب أمورك المالية يبدو تحقيق ذلك سهلًا، ويمكن أن يكون كذلك فعلًا ما دمتَ تراقب أمورك المالية بانتظام. وبصرف النظر عن حجم المشروع التجاري أو العمل الذي تُديره، فستقع في مأزق إن كنت لا تنفق المال على دفع فواتيرك وحساباتك إلا مرةً أو مرتين في السنة. حدد مواعيدًا تدفع فيها الفواتير المترتبة عليك، وأخرى ترسل فيها فواتيرَ إلى عملائك، وتواريخَ تعدّ فيها ميزانيتك الشهرية. إن التزامك بذلك لن يسهّل الأمور عليك طول العام فحسب، بل من شأنه أيضًا أن يمكّنك من تصحيح الأخطاء على نحو أسرع، وإجراء التعديلات كلما دعتِ الحاجة. 18. لا تنس أن تتنفس هل سمعتني؟ أقول "تتنفس"؛ وأقصد بذلك أنك بحاجة إلى الاعتناء بنفسك. قد تكون تنجز عملك الحر باستخدام حاسوب أو اثنين، أو كاميرا، أو غير ذلك من أدوات؛ لكن الأداة الأهم من ذلك كله هو "أنت". لا تنسَ قضاء وقتٍ تمارس فيه هواياتك، والالتقاء بأصدقائك وأفراد عائلتك، حتى ولو كان جدول عملك يغُصُّ بالمهام. 19. اخرج من منزلك بين الحين والآخر (خاصة إن كنت تعمل من المنزل) إذا كان منزلك هو مكان عملك، فمن المهم أن تخرج منه من وقت لآخر. رتِّب بعضَ اجتماعاتك في مكان آخر، والتقِ بشركاء العمل خارجًا على الغداء، أو اعمل لساعة أو ساعتَين من مكتبة أو مقهى باستخدام حاسوبك المحمول إن أمكنك ذلك؛ فتغيير المشاهد المحيطة بك يمكن أن يعزز مستوى طاقتك وإبداعك، ويعيد لك كثيرًا مما فقدتَ. 20. اصنع خيطا تحفيزيا لا تستمرُّ الأيامُ العصيبة أبدًا، بل تأتي وتذهب. وبهذه البساطة، فإنّ وجود شيء ما حولك، يذكّرك بالسبب الذي تعمل من أجله بهذا الجِدّ. قد يكون كل ما تحتاج إليه للحصول على طاقة إضافية في أحد تلك الأيام الصعبة، لذا كوِّن ذلك الخيط التحفيزي. خذ قطعة خيط واستخدم لوحَ فلّين أو لوحًا أبيضًا حسب المتوفر لديك. ضع صورةً لأطفالك أو للوجهة التي تود قضاء العطلة فيها والتي تدّخر المال من أجلها، أو ربما للسيارة التي تحلم في شرائها. أضِف بعض الاقتباسات أو الصور التحفيزية، أو أي شيء من شأنه أن يمدك بذلك التحفيز حقًا؛ وها أنت ذا قد كوّنتَ ذلك الخيط التحفيزي الذي يصنعُ العجائبَ النظرُ إليه في كل مرة تكون فيها على وشك الاستسلام، أو عندما تمرّ بيوم ترزح فيه تحت ضغطٍ هائل. 21. تحل بالتواضع لم يُولَد أحدٌ خبيرًا أو بطلًا للعالم؛ فإذا سارت الأمور معك جيدًا أو شعرتَ بأنك تسيطر على الوضع، فمن السهل أن تكتسب ثقةً زائدةً بنفسك، وهو ما يمكن أن يسيئ إلى سُمعتك وإلى وجودة عملك أيضًا. عليك دائمًا التحلّي بالتواضع، والإصغاء إلى عملائك حول ما يريدون منك. أعطهم رأيك الاحترافي عند الحاجة، ولكنّ هُم مَن يضمنون استمرارية حصولك على أجر. احرص دائمًا على طلب نصيحة من زملائك أو غيرهم ممن لهم باعٌ طويل نسبيًا في السوق التي تعمل فيها. 22. اظهر بمظهر احترافي بكل الطرق الممكنة بات الآن لديك شعارٌ وموقع إلكتروني وغيرهما، وبدأت الأمور تبدو على ما يُرام بالنسبة لك. احرص على معاملة عملائك باحترام والظهور بمظهر لائق، وكن مهذَّبًا؛ فأن تكون مديرَ نفسِك، لا يعني أنّ بوسعك التحدُّث أو التصرُّف بأي طريقة كانت والمحافظة على عملائك في الوقت ذاته. لا تنسَ ذلك؛ فعدم مراعاة ما سبقَ ذِكرُه كفيلٌ بجعل عملائك يَنفضُّون من حولك ويبحثون عن مستقل غيرك. 23. اطلب تقييما لا يكفي أن تحصل على تعلقيات تتيح إبداءها على موقعك الإلكتروني؛ لكن عليك طلب تقييمات من أصدقائك أو أفراد أسرتك أو حلفائك حول عملك. والأهم من ذلك كله هو أن تطلب من عميلك الذي أنهيتَ له مشروعًا ما أن يخبرك برأيه في عملك على ذلك المشروع بالتحديد؛ فذلك لا يعطيك فرصةً ممتازةً لتطوير نفسك فحسب، بل ويُشعِر العميلَ بالأهمية وبأنك تُفرِد لرأيه مساحةً مهمة. ومن الجيد أيضًا أن تأخذ دائمًا رأيَ شخص آخر غير المذكورين أعلاه، وهو ما من شأنه مساعدتك في أن تغدوَ أكثر نجاحًا. 24. احمل دفترا معك حيثما ذهبت عليك دائمًا حملُ دفترٍ معك؛ سواءٌ أكان دفترًا ورقيًا، أو باستخدام هاتفك الجوال، أو غيره من الصور الرقمية للدفتر، وتذكّر أن تدوّن عليه ملاحظات. ولذلك أسباب عديدة؛ إذ لا تقتصر فائدته على أنك قد تصادف عميلًا محتملًا أو حاليًا، بل قد تخطر ببالك أفكار قيّمة عندما تكون مستقلًا الحافلة، أو على متن الطائرة، أو في أي مكان آخر، فقد خطرت لي أفكار عظيمة في مرات عديدة، ثم نسيتُها لأنني لم أكن أحمل دفترًا، وتفاجأت بأنّ أحدًا غيري استخدم تلك الأفكار في مكان ما بعدها بسنة. 25. خذ ما تحتاج إليه من وقت هذه نصيحة بالغة الأهمية، ولا يمكن الاكتفاء بالتشديد عليها؛ فمثلما هو الحال بالنسبة للنصيحة التي تعلّمك أن تقول لا، التي ذكرناها أعلاه؛ عليك عندما تستلم مشروعًا أن تحرص كل الحرص على أخذ الوقت المطلوب لتقديم أفضل ما لديك في سبيل إنجازه، فتسليم مشروعٍ بجودةٍ دون المطلوبة لن يجعل العميل يمتنع عن تسليمك مشاريع مستقبليةً فقط، بل وسيضرّ بسمعتك إلى حد بعيد، فعملاؤك هم أهم جهة مرجعية حولك مستقبلًا، ولا أحد يريد العمل مع مستقل لا يُنهي عمله على النحو الذي يفترَض به تقديمه. وفي الخلاصة، أضمن لك أن اتباعك لما سبق مِن نصائح سيوفر عليك كثيرًا من العناء المرتبط بالعمل المستقل، وستتلمس الأثر الذي يتركه اتباعُ كل نصيحة منها في تحسين جودة عملك وحياتك عمومًا. ترجمة وبتصرف للجزء اﻷول من مقال How To Become a Freelancer That Is On Track Of Success. اقرأ أيضًا كيف تُدير وقتك لتتقن عملك كعامل مُستقل كيف تصبح كاتبًا مستقلًا مدفوع الأجر كيف تبدو الشّهور الأولى من العمل ككاتبٍ مستقل؟ الأدوات والخطوات اللّازمة لانطلاقة صحيحة في عالم العمل الحر ما هو العمل الحر وما هي أهم منصّات العمل للمُستقلّين
    1 نقطة
  33. إن كنت تقصد Office 365، فإن شركة مايكروسوفت (الشركة المالكة لـ Office 365) لا توفر تخفيضات في الوقت الحالي، وتبدأ أسعار الحزم من 5$ شهريًا (بدون الضرائب)، وبفضل دائمًا أن تشتري البرامج من الشركة الأم بدلًا من محاولة الحصول على الخدمات من خلال مواقع أخرى حيث قد يعرضك هذا الأمر لخطر الوقوع كضحية لعملية إحتيال. إن كان لديك بريد إلكتروني جامعي فيمكنك الحصول على الحزمة Office 365 A1 التي توفر العديد من برامج Office 365 مثل Microsoft Word و Microsoft Excel و Microsoft PowerPoint وغيرها من الخدمات بشكل مجاني بالكامل، إن كنت طالب وليس لديك بريد إلكتروني فيمكنك التواصل مع مركز الخدمات التقينة في جامعتك/كليتك للحصول عليه، أيضًا سوف تحصل على تخفيض كبير إن أردت الحصول على حزمة مختلفة عن Office 365 A1. يمكنك أن تقرأ كل المعلومات المتوفرة عن خطط الأسعار المتاحة للطلبة من هذه الصفحة. إن لم تكن طالب أو لم تتمكن من الحصول على بريد إلكتروني جامعي فيمكنك ان تقوم بتجربة أي حزمة من حزم Office 365 بشكل مجاني لمدة شهر واحد فقط.
    1 نقطة
  34. كيف نتمكن من معرفة ما إذا كان جهاز الأندرويد يحتوي برامج تجسس -للتنصت على الصوت أو فتح الكاميرا- أم لا؟ هل هناك تطبيقات تساعد على كشف هذه البرمجيات؟ شكرًا لكم.
    1 نقطة
  35. need, want, demand الحاجة والرغبة والطلب الحاجة هي نقص لدى الإنسان يحول بينه وبين هدف ما أو شعور ما، مثل الجوع هو حاجة للطعام، العطش هو حاجة للشرب، حاجة التواصل أو الوصول لمكان ما، كل هذه حاجات.الرغبة: هو ما يريده الإنسان بشكل أكثر دقّة لإشباع هذه الحاجات، مثلًا أريد تناول الخبز، الخبز هو رغبتي لسد حاجة الطعام، أرغب بالشاي، الشاي هو رغبتي الخاصة لريّ العطش، أريد هاتف جالكسي، جالكسي هو اختياري الشخصي لحاجتي للاتصال.الطلب: هو أن يريد الإنسان شراء "منتج محدد" ويطلبه، مع وجود القدرة على شرائه والرغبة بذلك.الحاجات تكون ثابتة في العموم، لكن الرغبات تختلف من شخص لآخر ومن ثقافة لأخرى، وهذا يفسّر الأشكال والأحجام والأصناف لنفس أنواع المنتجات في الأسواق. تلعب الشركات على أوتار الحاجات والرغبات لتزيد الطلب على منتجاتها، فهي إما تتوجه لجمهور لديه حاجة ما وتسدّها بمختلف الأصناف الملبّية للرغبات المختلفة، أو أنها تتوجه لما يعجب الناس ويرغبون به اليوم من صرغات وصيحات بغض النظر عن حاجتهم الحقيقية له، أو قد تخلق لديهم حاجات وهمية ورغبات وهمية أيضًا. للمزيد
    1 نقطة
×
×
  • أضف...