نتائج البحث

اذهب إلى التنقل اذهب إلى البحث

استخراج الصنف (Extract Class)

المشكلة وجود صنفٍ (class) واحدٍ يقوم بمهامٍ عديدةٍ يمكن توزيعها على صنفين. الحل إنشاء صنفٍ جديدٍ ونقل بعض الحقول (fields) والتوابع (methods) إليه، والتي تتعلَّق بالمهام الوظيفيّة (functionality) لهذا الصنف الجديد. مثال قبل إعادة التصميم يحتوي الصنف Person على عددٍ من الحقول كاسم الشخص (name) ورمز منطقة المكتب (officeAreaCode) ورقمه (officeNumber)، وتابعًا للحصول على هذا الرقم باسم getTelephoneNumber، كما في مخطط الأصناف الآتي: الصنف Person يحتوي على عددٍ من الحقول كاسم الشخص (name) ورمز منطقة المكتب (officeAreaCode) ورقمه (officeNumber)، وتابعًا ...

تحويل التوابع إلى معاملات (Parameterize Method)

المشكلة تؤدي توابع متعددة أعمالًا مماثلة تختلف فقط من حيث قيمها الداخلية أو أرقامها أو عملياتها. الحل تجميع هذه التوابع باستخدام معامل يُمرر القيمة الخاصة الضرورية. مثال قبل إعادة التصميم يؤدي التابعان ()fivePercentRaise و ()tenPercentRaise الغرض ذاته باختلاف النسبة المئوية المراد زيادتها للموظف Employee: يؤدي التابعان أعمالًا مماثلة تختلف فقط من حيث قيمها الداخلية أو أرقامها أو عملياتها. بعد إعادة التصميم تجميع التابعان السابقان في تابع واحد يدعى ()raise مع تمرير النسبة المئوية المتغيرة إليه: يجمع التابعين باستخدام معامل يُمرر ...

إعادة تسمية التوابع (Rename Method)

المشكلة لا يعبِّر اسم التابع عن ما يقوم به. الحل إعادة تسمية التابع. مثال قبل إعادة التصميم لا يفسر اسم التابع ()getsnm في الصنف Customer ما يقوم به. لا يفسر اسم التابع ما يقوم به. بعد إعادة التصميم إعادة تسمية التابع ()getsnm إلى ()getSecondName الذي يصف ما يقوم به. يفسر اسم التابع ما يقوم به. لم إعادة التصميم؟ ربما كانت تسمية تابعٍ ما سيئة من البداية - على سبيل المثال، أنشأ شخصٌ ما التابع في عجلة ولم يهتم كفاية بتسميته ...

إنشاء التوابع (Composing Methods)

تستهدف إعادة التصميم بشكل رئيسيٍّ إنشاء التوابع الصحيحة المناسبة، إذ تكون التوابع الطويلة سببًا للمشاكل في كثيرٍ من الحالات، وتجعل شيفرات بعض التوابع منطق التنفيذ (execution logic) غامضًا ويصبح التابع بهذا عصيَّ الفهم من جهةٍ وصعب التغييرٍ من جهة ثانية. يشمل هذا القسم من الحلول كلَّ ما يتعلق بالتوابع وإزالة التكرار (duplicates) في الشيفرة ليسمح بإجراء التطويرات المستقبليّة، وهذه التقنيات هي: استخراج التوابع (Extract Methods) المشكلة: وجود أجزاء من الشيفرة يُمكن عزلها وتجميعها سويةً. الحل: نقل الشيفرة إلى تابعٍ (method) ...

إنشاء التوابع (Composing Methods)

تستهدف إعادة التصميم بشكل رئيسيٍّ إنشاء التوابع الصحيحة المناسبة، إذ تكون التوابع الطويلة سببًا للمشاكل في كثيرٍ من الحالات، وتجعل شيفرات بعض التوابع منطق التنفيذ (execution logic) غامضًا ويصبح التابع بهذا عصيَّ الفهم من جهةٍ وصعب التغييرٍ من جهة ثانية. يشمل هذا القسم من الحلول كلَّ ما يتعلق بالتوابع وإزالة التكرار (duplicates) في الشيفرة ليسمح بإجراء التطويرات المستقبليّة، وهذه التقنيات هي: استخراج التوابع (Extract Methods) المشكلة: وجود أجزاء من الشيفرة يُمكن عزلها وتجميعها سويةً. الحل: نقل الشيفرة إلى تابعٍ (method) ...

الصنف Method في روبي

يتم إنشاء كائنات الصنف Method بواسطة التابع Object.method، وترتبط بكائن معين (وليس بالصنف وحسب). ويمكن استخدامها لاستدعاء التابع داخل الكائن، أو ككتلة (block) مرتبطة بمكرر (iterator). كما يمكن فك ارتباطها (unbound) من كائن محدد (سيؤدي ذلك إلى إنشاء الكائن UnboundMethod) ثم ربطها بآخر. class Thing def square(n) n*n end end thing = Thing.new meth = thing.method(:square) meth.call(9) #=> 81 [ 1, 2, 3 ...

ازالة توابع الإعدادات (Remove Setting Method)

المشكلة يكون تعيين قيمة الحقل فقط عند إنشائه، ولا تتغير في أي وقت لاحق. الحل إزالة التوابع التي تضبط قيمة الحقل. مثال قبل إعادة التصميم يضبط التابع ()setImmutableValue قيمةً غير قابلة للتغيير أو التعديل في المستقبل: يغيّر التابع من قيمة الحقل. بعد إعادة التصميم حذف التابع ()setImmutableValue من الصنف Customer: إزالة التابع الذي يضبط قيمة الحقل. لم إعادة التصميم؟ إذا كنت تريد منع أي تغييرات في قيمة الحقل. آلية الحل يجب أن تكون قيمة الحقل قابلة للتغيير فقط في الباني. ...

تبسيط استدعاءات التوابع (Simplifying Method Calls)

تجعل التقنيات التي سيشار إليها في هذا القسم استدعاءات التوابع أبسط وأسهل للفهم والاستيعاب. سيؤدي ذلك بدوره إلى تبسيط الواجهات للتفاعل بين الأصناف. هذه التقنيات هي: إعادة تسمية التوابع (Rename Method) المشكلة: لا يعبِّر اسم التابع عن ما يقوم به. الحل: إعادة تسمية التابع. إضافة المعاملات (Add Parameter) المشكلة: لا يملك التابع بيانات كافية لتنفيذ بعض الإجراءات. الحل: إنشاء معامل جديد لتمرير البيانات الضرورية. حذف المعاملات (Remove Parameter) المشكلة: لا يُستخدم معاملٌ ما في متن التابع. الحل: إزالة المعامل غير ...

دفع التابع لأسفل (Push Down Method)

المشكلة هل السلوك المُنفَّذ في الصنف الأب مُستخدمٌ في صنف فرعي واحد فقط (أو أكثر)؟ الحل نقل هذا السلوك إلى الأصناف الفرعية. مثال قبل إعادة التصميم التابع ()getFuel الموجود في الصنف Unit الأب مُستخدم في صنف فرعي واحد فقط الذي هو Tank: التابع الموجود في الصنف الأب مُستخدم في صنف فرعي واحد فقط. بعد إعادة التصميم نقل التابع ()getFuel من الصنف الأب إلى الصنف الفرعي المستخدم فيه: نقل هذا التابع إلى الصنف الفرعي الذي يُستخدم فيه. لم إعادة التصميم؟ في ...

سحب التابع لأعلى (Pull Up Method)

المشكلة تحتوي الأصناف الفرعية على توابع تؤدي نفس العمل. الحل جعل التوابع متطابقة ثم نقلها إلى الصنف الأعلى ذي الصلة. مثال قبل إعادة التصميم يحتوي الصنفان الفرعيان Soldier و Tank على التابع ()getHealth الذي يؤدي نفس العمل: تحتوي الأصناف الفرعية على التابع ()getHealth تؤدي نفس العمل. بعد إعادة التصميم نقل التابع ()getHealth إلى الصنف Unit الأب وإزالته من الأصناف الفرعية: نقل التابع ()getHealth إلى الصنف الأعلى. لم إعادة التصميم؟ تنمو الأصناف الفرعية وتتطور بشكل مستقل عن بعضها البعض، مما يتسبب ...

متى تحتاج إعادة التصميم؟ (When to Refactor)

نحتاج إلى إعادة التصميم (قاعدة المرات الثلاث): عند قيامك بأيّة مهمةٍ للمرّة الأولى، فالمهم هو إنجازها والحصول على النتيجة وحسب. لدى قيامك بمهمةٍ مشابهةٍ للمرّة الثانية قد ترفض بادئ الأمر فكرة التكرار ولكنك ستجد نفسك تقوم بنفس العمل! عند قيامك بالمهمة للمرّة الثالثة، ستحتاج إعادة التصميم. عند إضافة ميّزةٍ (feature) جديدة تساعد عملية إعادة التصميم (refactoring) على فهم شيفرات المبرمجين الآخرين بشكلٍ أفضل، وعند العمل على الشيفرة غير الجيدة لأحدهم فعليك بإعادة تصميمها أولًا، وهذا ضروريٌّ إذ يصبح التحكُّم بالشيفرة ...

الأصناف الواسعة (Large Classes)

توصيف المشكلة احتواء الصنف (class) العديدَ من الحقول (fields) والتوابع (methods) وشيفرةً بأسطرَ كثيرةٍ. أسبابها تبدأ الأصناف صغيرةً ليزداد حجمها مع استمرار تطوُّر البرنامج (كما الحال بالتوابع الطويلة) لأنَّ المبرمج يرى أنَّ إضافة ميِّزاتٍ (features) جديدةٍ في صنفٍ موجودٍ مسبقًا أكثر سهولةً من إنشاء أصنافٍ جديدةٍ مخصَّصةٍ لها. وما الحل؟ الحل بسيطٌ جدًا؛ وهو تقسيم الصنف، وذلك بإحدى الوسائل الآتية: إنشاء صنفٍ جديدٍ (Extract Class) إن كان من الممكن فصلُ بعض مهامّ الصنف الحاليّ ونقلها للصنف الجديد. إنشاء صنفٍ فرعيٍّ ...

تبديل المعاملات باستدعاءات التوابع (Replace Parameter with Method Call)

المشكلة استدعاء تابع استعلام (query method) وتمرير نتائجه كمعاملات لتابع آخر، في حين أنه يمكن لهذا التابع استدعاء الاستعلام مباشرة. الحل بدلًا من تمرير القيمة من خلال المعامل، حاول وضع استدعاء الاستعلام داخل متن التابع. مثال قبل إعادة التصميم تخزين القيمة التي يعيدها كلٌّ من التابعين ()getSeasonalDiscount و ()getFees في متغير ثم تمريرها إلى التابع ()discountedPrice: في لغة Java: int basePrice = quantity * itemPrice; double seasonDiscount = this.getSeasonalDiscount(); double fees = this.getFees(); double finalPrice = discountedPrice(basePrice, seasonDiscount, fees); في لغة C#‎: int basePrice ...

استبدال المعامل بتوابع صريحة (Replace Parameter with Explicit Methods)

المشكلة ينقسم التابع إلى أجزاء، كل منها يتم تشغيله اعتمادًا على قيمة المعامل. الحل استخراج الأجزاء الفردية من التابع إلى توابعها الخاصة واستدعائها بدلًا من استدعاء التابع الأصلي. مثال قبل إعادة التصميم وجود تابع يدعى ()setValue يضبط قيمة الارتفاع والعرض بناءً على تمرير سلسلة نصية صريحة بذلك: في لغة Java: void setValue(String name, int value) { if (name.equals("height")) { height = value; return; } if (name.equals("width")) { width ...

استبدال المُنشئ بتابع التصميم (Replace Constructor with Factory Method)

المشكلة لديك مُنشئ (constructor) معقد يقوم بما هو أكثر من مجرد وضع قيم المعامل في حقول الكائن. الحل إنشاء تابع تصميم واستخدامه لاستبدال استدعاءات المُنشئ. مثال قبل إعادة التصميم وجود منشئ معقد للصنف Employee: في لغة Java: class Employee { Employee(int type) { this.type = type; } //... } في لغة C#‎: public class Employee { public Employee(int type) { this.type = type; } //... } في لغة PHP: class ...

الدليل التطبيقي

لا يفترض هذا الدليل أي معرفة مسبقة بمكتبة React. قبل أن نبدأ بالدليل التطبيقي سنبني لعبة صغيرة خلال هذا الدليل التطبيقي. ربّما قد ترغب بتخطي هذا الدليل لأنّك لا تريد بناء الألعاب، ولكن أعطيها فرصة. إنّ التقنيات التي ستتعلمها في هذا الدليل أساسيّة لبناء أي تطبيق React، وسيعطيك إتقانها فهمًا أعمق لمكتبة React. فائدة: هذا الدليل مُصمَّم للأشخاص الذين يُفضّلون التعلّم بالممارسة. إن كنت تُفضّل تعلّم المفاهيم من البداية فارجع إلى توثيق React من البداية خطوة بخطوة. قد تجد هذا ...

الأصناف في TypeScript

مقدمة تعتمد لغة JavaScript التقليدية على الدوال والوراثة المعتمدة على سلسلة Prototype لبناء مكونات قابلة لإعادة الاستعمال، وقد يجد بعض المبرمجين هذه الطريقة غريبة ومرهقة، خاصّة الذين ألِفوا البرمجة كائنيّة التوجه التي تعتمد على الأصناف التي ترث وظيفة (functionality) الأصناف الأساس (base classes) وتُبنَى فيها الكائنات من هذه الأصناف. بدايةً من الإصدار ECMAScript 2015 المعروف كذلك بالإصدار ECMAScript 6، يُمكن لمبرمجي JavaScript بناء التطبيقات باستخدام البرمجة كائنيّة التوجّه المعتمِدة على الأصناف. وتسمح TypeScript للمطورين باستعمال هذه التقنيات الآن، وتُترجِمها إلى ...

المعامل ===‎ الخاص بالصنف Method في روبي

يستدعي المعامل === كتلة التابع مع تمرير الكائن الواقع على يمينه كوسيط إلى المعامل الواقع على يساره كما هو الحال في Proc.call. هذا يَسمح لكائنٍ من النوع proc أن يكون هدفًا للكتلة when في التعليمة case. البنية العامة proc === obj→ result_of_proc‎ القيمة المعادة تعاد نتيجة الوسيط proc. انظر أيضا التابع ==: يتحقق من تساوي كائنين من النوع Method. مصادر قسم التابع ===‎ في الصنف Method‎ في توثيق روبي الرسمي.

المعامل ‎[]‎‎ الخاص بالصنف Method في روبي

يستدعي معامل الفهرسة [] الكتلة البرمجية للتابع، ويضبط قيم معاملات الكتلة عند القيم المعطاة ضمنه باستخدام صياغة مشابهة لاستدعاء التوابع ثم يعيد قيمة آخر تعبير تم تقييمه في الكتلة. لاحظ أنَّ ‎prc.()‎ يستدعي prc.call()‎ مع تمرير الوسائط المعطاة. وهي صياغة مختصرة لإخفاء التابع "call". بالنسبة للكائنات procs التي تم إنشاؤها باستخدام lambda أو ‎->()‎‎‎، سيُطلق خطأ إذا كان عدد المعاملات الممررة إلى proc غير صحيح. بالنسبة للكائنات proc التي تم إنشاؤها باستخدام Proc.new أو Kernel.proc، سيتم تجاهل المعاملات الإضافية بصمت، ...

المعامل ==‎ الخاص بالصنف Method في روبي

يتحقق المعامل == من تساوي كائنين من النوع Method. يكون كائنان من النوع Method متساويين إن كانا مرتبطين بنفس الكائن، وكانا لهما نفس التعريف، وكان لهما نفس الصنف أو الوحدة (module) المالكة. البنية العامة meth == other_meth → true or false‎ القيمة المعادة تُعاد القيمة true إن كان الكائنان متساويين، وإلا فستُعاد القيمة false. انظر أيضا التابع ===: يستدعي كتلة التابع مع تمرير الكائن الواقع على يمينه كوسيط إلى المعامل الواقع على يساره كما هو الحال في Proc.call. مصادر قسم ...

طريقة الاستعمال وتشغيل الأمثلة في Node.js

البنية العامة node [options] [V8 options] [script.js | -e "script" | - ] [arguments] راجع رجاءً توثيق خيارات سطر الأوامر للمزيد من المعلومات عن الخيارات والطرائق التي يمكن استعمالها لتشغيل السكربتات وتنفيذها مع Node.js. تشغيل الأمثلة سنشرح مثالًا عن إنشاء خادم ويب باستعمال Node.js يُظهِر العبارة 'مرحبًا بالعالم!' في المتصفح. تبدأ الأوامر المستعملة في هذا المثال بالمحرف $ أو < وذلك لمحاكاة كيفيَّة ظهورها في طرفيَّة المستخدم، لذا لا تضف هذين المحرفين إلى الأوامر عند نسخها واستعمالها. توجد الكثير من الدروس ...

التابع Keyboard.move()‎ في أردوينو

يحرك التابع move()‎ مؤشر الفأرة في الحاسوب المتصل. يُحدَّد الموقع الجديد المراد تحريك المؤشر إليه نسبةً إلى الموقع الحالي للمؤشر. قبل استعمال التابع move()‎، يجب استدعاء التابع begin()‎. البنية العامة Mouse.move(xVal, yPos, wheel); المعاملات xVal محرفٌ ذو إشارة (signed char) يحدِّد مقدار انتقال المؤشر على المحور الأفقي (x-axis). yVal محرفٌ ذو إشارة (signed char) يحدِّد مقدار انتقال المؤشر على المحور الشاقولي (y-axis). wheel محرفٌ ذو إشارة (signed char) يحدِّد مقدار تدوير عجلة الفأرة. القيم المعادة لا يعاد أي شيء. أمثلة ...

تعريف الإضافات محليًّا (Introduce Local Extensions)

المشكلة الحاجة إلى بعض التوابع (methods) غير الموجودة في الصنف المساعد (utility class)، ومن غير الممكن إضافتها إلى ذلك الصنف. الحل إنشاء صنفٍ (class) جديدٍ يحتوي التوابع اللازمة، وجعله كصنف تغليفٍ (wrapper) للصنف المساعد أو كصنفٍ فرعيٍّ (subclass) له. مثال قبل إعادة التصميم يعتمد صنف العميل ClientClass على الصنف المساعد Date ولكنّه بحاجة إلى بعض التوابع غير الموجودة فيه (كتابع الحصول على اليوم التالي مثلًا): الصنف العميل ClientClass الذي يعتمد على الصنف المساعد Date. بعد إعادة التصميم أصبح هنالك صنف ...

التابع HTTPRedirectHandler.http_error_301()‎‎ في بايثون

يعيد التابع التوجيه إلى عنوان Location:‎ أو URI:‎. يُستدعى هذا التابع بواسطة كائن OpenerDirector الأب عند الحصول على الاستجابة (moved permanently). البنية العامة HTTPRedirectHandler.http_error_301(req, fp, code, msg, hdrs) مصادر صفحة Extensible library for opening URLs في توثيق بايثون الرسمي.

إخفاء التفويض (Hide Delegate)

المشكلة يصل العميل (client) إلى كائنٍ (object) ما وليكن الكائن B من أحد حقول (fields) أو توابع (methods) كائنٍ آخر وليكن A، ومن ثمّ يستدعي تابعًا لهذا الكائن B. الحل إنشاء تابعٍ جديدٍ في الصنف A والذي يُفضي إلى استدعاءٍ للكائن B، وبهذا لن يعلم العميل تفاصيل التفويض (delegation) للكائن B ولن يعتمد على ذلك. مثال قبل إعادة التصميم يتعامل صنف العميل (client class) مع صنفين، الأول صنف الأقسام (Department) والثاني صنف الأشخاص (Person) واللذان يحتويان تابعين للحصول على كائنٍ ...

الأصناف الخاملة (Lazy Classes)

توصيف المشكلة وجود بعض الأصناف (classes) قليلة الاستخدام ولا أهمية لها في البرنامج، ويجدر التخلُّص منها إذ إنّ فهم وصيانة الأصناف يكلِّفان الوقت والجهد. أسبابها يكون تصميم الصنف بدايةً لأداء مهامٍ (functionality) معيّنة، ولكنّه قد يصبح صغيرًا لا أهميّة له من بعد الكثير من عمليات إعادة التصميم (refactoring). قد تُخصَّص بعض الأصناف لدعم التطوير المستقبلي للبرنامج (كالتخطيط المُسبق لميّزاتٍ ستُضاف لاحقًا)، وتصبح تلك الأصناف خاملةً عندما لا يحدث أيُّ تطويرٍ فيما بعد. وما الحل؟ تضمين الأصناف (inline classes) للعناصر (components) ...

التابع call‎ الخاص بالصنف Method في روبي

يستدعي call كتلة التابع الذي استٌدعي معه، ويضبط وسائط الكتلة عند القيم المُمرَّرة إليه باستخدام صياغة مشابهة لصياغة استدعاء التوابع ثم يعيد قيمة آخر تعبير تم تقييمه في الكتلة. لاحظ أن ‎prc.()‎ يستدعي prc.call()‎ مع تمرير المعاملات المعطاة. وهي صياغة مختصرة لإخفاء التابع "call". بالنسبة للكائنات procs التي تم إنشاؤها باستخدام lambda أو ‎->()‎‎‎، سيُطلق خطأ إذا كان عدد المعاملات الممررة إلى proc غير صحيح. بالنسبة للكائنات proc التي تم إنشاؤها باستخدام Proc.new أو Kernel.proc ، سيتم تجاهل المعاملات الإضافية ...

الشيفرة النظيفة (Clean Code)

تهدف عملية إعادة التصميم (refactoring) للتخلُّص من المتطلَّبات التقنيّة الزائدة، إذ تحوِّل كلَّ الفوضى المنتشرة في الشيفرة إلى شيفرةٍ نظيفةٍ (clean code) ذات تصميمٍ مُبسَّط، وهذا -لا بُدَّ- أمرٌ رائعٌ ولكن بالبداية؛ ما معنى أن تكون الشيفرة نظيفةً؟ مميزات الشيفرة النظيفة فيما يأتي بعضٌ مما يميز الشيفرة النظيفة: واضحةٌ ومقروءةٌ للمبرمجين الآخرين إنّ ما يجعل الشيفرات أكثر تعقيدًا (بعيدَا عن الخوارزميّات فائقة التعقيد) هو اعتمادها على تسمية المتغيِّرات تسميةً ضعيفةً (غير منطقيّةٍ أو بدون معنى) أو احتوائها على أصناف (classes) ...

التابع ThreadGroup.enclose في روبي

يمنع التابع enclose إضافة أو إزالة أي خيط من مجموعة الخيوط التي استدعيت معه. لا يزال بإمكان الخيوط الجديدة أن تُبدَأ في مجموعة خيوط مغلقة. البنية العامة enclose → thgrp القيمة المعادة تعاد مجموعة الخيوط المعطاة بعد إغلاقها. أمثلة مثال على استعمال التابع enclose: ThreadGroup::Default.enclose #=> #<ThreadGroup:0x4029d914> thr = Thread.new { Thread.stop } #=> #<Thread:0x402a7210 sleep> tg = ThreadGroup.new ...

الاستغناء عن الوسيط (Remove Middle Man)

المشكلة احتواء الصنف (class) على العديد من التوابع (methods) التي تنقل (delegate) سياق البرنامج إلى كائنات (objects) أخرى. الحل حذف تلك التوابع وإجبار العميل (client) على الاستدعاء المباشر للتوابع النهائية (التي سيصل إليها بالنهاية وتحتوي المهام الفعليّة). مثال قبل إعادة التصميم يتعامل صنف العميل (client class) مع صنفٍ واحدٍ فقط وهو الصنف Person، والذي بدوره يستدعي كائنًا من صنفٍ آخر باسم Department دون أن يكون العميل على علمٍ بتفاصيل ذلك الاستدعاء، كما هو واضح في مخطط الأصناف الآتي: مخطط يوضح ...

الأعباء التقنية (Technical Debt)

يبذل المبرمج عادةً ما بوسعه لكتابة شيفرةٍ جيدةٍ، ولا ينوي أبدًا -أيًّا كان المبرمج- الحصولَ على شيفرةٍ رديئةٍ تكون السبب في فشل مشروعه البرمجيّ، لذا فلنطرح السؤال: ما هو الحدُّ الذي تصبح عنده الشيفرةُ النظيفةُ رديئةً؟ فخ الأعباء التقنية اقتُرح مصطلح "الأعباء أو الالتزامات التقنيّة" (ويقابله بالانكليزيّة Technical Debt) للمرّة الأولى من قِبل Ward Cunningham، فإنه لدى اقتراضك مبلغًا ماليًا من أحد المصارف تكبُر أمامك فرصة الشراء بشكلٍ أسرع، ويحدث أن تدفعَ علاوةً (وأيّ إضافات أخرى) لتسريع الأمر والحصول على ...

الخاصية cursor

الخاصية cursor في CSS تُحدِّد ما هو شكل مؤشر الفأرة الذي سيُعرَض عندما تمر الفأرة فوق العنصر. بطاقة الخاصية القيمة الابتدائية auto تُطبَّق على جميع العناصر. قابلة للوراثة نعم قابلة للحركة لا القيمة المحسوبة كما حُدِّدَت، لكن مع تحويل روابط URL النسبية إلى مطلقة. /* كلمات محجوزة */ cursor: pointer; cursor: auto; /* استخدام رابط للأيقونة مع إحداثيات */ cursor: url(cursor1.png) 4 12, auto; cursor: url(cursor2.png) 2 2, pointer; /* القيم العامة */ cursor: inherit; cursor: initial; cursor: unset; أمثلة مثال عن استخدام مختلف القيم مع الخاصية cursor: <div ...

المكتبة Mouse في أردوينو

تتيح توابع المكتبة Mouse إمكانية تحكم اللوحات التي تعتمد على متحكمات 32u4 أو SAMD بمؤشر الفأرة في الحاسوب المتصل عبر المنفذ USB الأصلي للمتحكم. يكون موقع مؤشر الفأرة نسبي دومًا؛ فعند تحديث موقع مؤشر الفأرة الحالي وتحريكه، ينتقل المؤشر إلى الموقع الجديد نسبةً إلى موقعه القديم. تسمح المكتبات الأساسية للوحات التي ترتكز على متحكمات 32u4 و SAMD (مثل عائلة Leonardo، و Esplora، و Zero، و Due، و MKR) بجعل الفأرة و/أو لوحة المفاتيح تبدوان عند وصلهما بالحاسوب وكأنَّهما أصليتان. هنالك ...

الكلمة static المفتاحية في أردوينو

تُستعمَل الكلمة المفتاحية static عند إنشاء متغيرات مرئيَّة لدالةٍ واحدة فقط من أجل الحفاظ على محتواها بعد انتهاء تنفيذ تلك الدالة المستدعاة وحتى الاستدعاء التالي لها خلافًا للمتغيرات المحلية التي تُنشَأ وتدمَّر في كل مرة تُستدعَى فيها الدالة. ستُنشَأ وتُهيَّأ المتغيرات الساكنة المصرَّح عنها ضمن الدالة مع الكلمة static المفتاحية أول مرة تُستدعَى فيها تلك الدالة فقط. البنية العامة static dataType var = val; يمثِّل dataType نوع المتغير المراد تعريفه، و var اسم المتغير، و val القيمة المراد إسنادها إلى هذا ...

التابع Keyboard.begin()‎ في أردوينو

يبدأ التابع begin()‎ عملية محاكاة (emulating) لفأرة افتراضية موصولة بالحاسوب المتصل باللوحة. يجب استدعاء هذا التابع قبل بدء التحكم بالحاسوب. إن أردت إنهاء هذه العملية، فاستدعِ التابع end()‎. البنية العامة Mouse.begin() القيم المعادة لا يعاد أي شيء. أمثلة إرسال رسالة إلى الحاسوب عبر لوحة مفاتيح افتراضية متصلة به عند الضغط على زر موصول بالرجل 2: #include <Mouse.h> void setup(){ pinMode(2, INPUT); } void loop(){ // عند الضغط على الزر المتصل بالرجل 2 Mouse تهيئة وبدء المكتبة if(digitalRead(2) == HIGH){ ...

التابع Keyboard.end()‎ في أردوينو

يوقف التابع end()‎ عملية محاكاة (emulating) وصل فأرة افتراضية بالحاسوب المتصل باللوحة. إن أردت إعادة التحكم بالفأرة مجدَّدًا، فاستدعِ التابع begin()‎. البنية العامة Mouse.end() القيم المعادة لا يعاد أي شيء. أمثلة الضغط على زر الفأرة الأيسر في موقع المؤشر الحالي عند الضغط على الزر الموصول بالرجل 2: #include <Mouse.h> void setup(){ pinMode(2,INPUT); // Mouse تهيئة وبدء المكتبة Mouse.begin(); } void loop(){ // إن ضُغِط على الزر المتصل بالرجل 2، فضغط زرالفأرة الأيسر //then end the Mouse emulation ...

Object.create()‎

الدالة Object.create()‎ تُنشِئ كائنًا جديدًا له كائن prototype مُحدَّد، وتكون خاصياته معطية. البنية العامة Object.create(proto[, propertiesObject]) proto الكائن الذي يجب أن يُسنَد إلى خاصية prototype للكائن المُنشأ. propertiesObject هذا الوسيط اختياريٌ، وإذا حُدِّدَت قيمته ولم تكن undefined، فهو كائنٌ فيه خاصياتٌ تابعةٌ له وقابلةٌ للإحصاء تُحدِّد واصفات الخاصيات (property descriptors) التي ستُضاف إلى الكائن المُنشَأ والتي سترتبط بأسماء الخاصيات. وهذه الخاصيات تشبه الوسيط الثاني المُمرَّر إلى الدالة Object.defineProperties()‎ (ارجع إلى تلك الصفحة إن وجدتَ الكلام السابق غامضًا). القيمة المعادة كائن ...

التابع Keyboard.click()‎ في أردوينو

يرسل التابع click()‎ ضغطة سريعة وخاطفة إلى الحاسوب عند موقع مؤشر الفأرة الحالي. يشبه سلوك هذا التابع الضغط بسرعةٍ على زر الفأرة ضغطةً واحدةً. الزر الافتراضي الذي يضغطه هذا التابع هو زر الفأرة الأيسر. البنية العامة Mouse.click(); Mouse.click(button); المعاملات button محرفٌ يحدِّد هذا المعامل زر الفأرة المراد ضغطه. القيم التي يمكن استعمالها مع هذا المعامل هي: MOUSE_LEFT (القيمة الافتراضية) MOUSE_RIGHT MOUSE_MIDDLE القيم المعادة لا يعاد أي شيء. أمثلة الضغط على زر الفأرة الأيسر في موقع المؤشر الحالي عند الضغط على الزر ...

التابع Keyboard.isPressed()‎ في أردوينو

يتحقَّق التابع isPressed()‎ إن كان زر معيَّن من أزرار الفأرة مضغوطًا أم لا. البنية العامة Mouse.isPressed(); Mouse.isPressed(button); المعاملات button محرفٌ يحدِّد هذا المعامل زر الفأرة المراد التحقُّق منه. القيم التي يمكن استعمالها مع هذا المعامل هي: MOUSE_LEFT (القيمة الافتراضية) MOUSE_RIGHT MOUSE_MIDDLE القيم المعادة تعاد القيمة true المنطقية إن كان الزر button (أو الزر الأيسر إن لم يُعطَ) مضغوطًا أم لا. أمثلة استعمال قاطعتين لضغط زر الفأرة الأيسر باستمرار وتحريره: #include <Mouse.h> void setup(){ // قاطعة تستعمل من أجل الضغط على زر ...

التابع Keyboard.release()‎ في أردوينو

يحرِّر التابع release()‎ زر الفأرة الذي ضُغِط عليه مسبقًا باستعمال التابع press()‎. البنية العامة Mouse.release(); Mouse.release(button); المعاملات button محرفٌ يحدِّد هذا المعامل زر الفأرة المراد تحريره. القيم التي يمكن استعمالها مع هذا المعامل هي: MOUSE_LEFT (القيمة الافتراضية) MOUSE_RIGHT MOUSE_MIDDLE القيم المعادة يعاد عدد المفاتيح المُحرَّرة. أمثلة استعمال قاطعتين لضغط زر الفأرة الأيسر باستمرار وتحريره في موقع المؤشر الحالي: #include <Mouse.h> void setup(){ // قاطعة تستعمل من أجل الضغط على زر الفأرة pinMode(2,INPUT); // قاطعة أخرى تستعمل من أجل تحرير ...

التابع Keyboard.press()‎ في أردوينو

يرسل التابع press()‎ ضغطة مستمرة إلى الحاسوب عند موقع مؤشر الفأرة الحالي. يشبه سلوك هذه التابع الضغط باستمرار على زر الفأرة. يُحرَّر زر الفأرة المضغوط عليه عبر استدعاء التابع release()‎. قبل استعمال التابع press()‎، يجب استدعاء التابع begin()‎. البنية العامة Mouse.press(); Mouse.press(button) المعاملات button محرفٌ يحدِّد هذا المعامل زر الفأرة المراد ضغطه باستمرار. القيم التي يمكن استعمالها مع هذا المعامل هي: MOUSE_LEFT (القيمة الافتراضية) MOUSE_RIGHT MOUSE_MIDDLE القيم المعادة لا يعاد أي شيء. أمثلة استعمال قاطعتين لضغط زر الفأرة الأيسر باستمرار وتحريره ...

العوارض في منصة iOS في كوردوفا

يوضح هذا الدليل كيفية تضمين مُكوّن (component) عارض كوردوفا في تطبيقات منصة iOS الكبيرة. للمزيد من التفاصيل حول كيفية جعل تلك المكوّنات تتواصل مع بعضها، راجع دليل تطوير الإضافات. بدأ دعم العوارض في منصة iOS منذ الإصدار 1.4 كوردوفا، باستخدام مكوِّن Cleaver الذي بُنِي على قالب Xcode. منصة كوردوفا 2.0 والإصدارات الأحدث لا تدعم إلا التقديم المستند إلى المشروع الفرعي (subproject-based) للمكُوِّن Cleaver. تتطلب هذه الإرشادات على الأقل الإصدار الرابع من كوردوفا، والثامن من Xcode، بالإضافة إلى الملف config.xml من ...

مدخل إلى TypeScript

يُشار إلى TypeScript على أنّها مجموعة عليا (superset) من JavaScript وتُترجم (compile) إليها. وهذا يعني بأن البرامج المكتوبة بلغة JavaScript هي برامج TypeScript صالحة كذلك، ولأنّها تُترجم إلى لغة JavaScript عاديّة، فيُمكن كتابة برامج بلغة TypeScript وترجمتها وتشغيلها في أي مكان يقبل تشغيل برمجيات JavaScript مثل المتصفّح، أو منصّة Node.js، أو أي مُحرّكٍ (engine) يدعم الإصدار ECMAScript 3 من لغة JavaScript أو أي إصدار أحدث منه. تدعم TypeScript مزايا JavaScript الجديدة والتي قيد التطوير، ما يشمل مزايا الإصدار ECMAScript 2015 ...

التعليقات (Comments)

توصيف المشكلة وجود الكثير من التعليقات في التوابع (methods) بهدف الشرح التفصيليّ للشيفرة. أسبابها غالبًا ما يكون السبب منطقيًّا لإضافة التعليقات وخاصّة عندما تكون الشيفرة مبهمةً غير واضحة، لكن بهذه الحالة لن نعدَّ تلك التعليقات إلا محاولاتٍ بائسةً لتغطية الشيفرة الرديئة بجانبها! ولتكن القاعدة: إنّ أفضل تعليقٍ يمكن أن تضيفه هو تسمية التوابع (methods) والأصناف (classes) تسميةً جيّدةً معبِّرة. وإذا ما وجدتَ أن الشيفرة لن تكون واضحةً بحذف التعليقات المُضافة، فمن المُؤسف القول بضرورة تغيير بُنيتها (structure) إلى الشكل الذي ...

تعليمات التحكم في Sass

تدعم SassScript تعليمات وتعابير التحكم التي تُستعمل لرَهن تفعيل الأنماط بشروط معيّنةٍ أو لتضمين نفس النمط لكن مع تطبيق بعض التنويعات عليه. ملاحظة: تعليمات التحكم هي ميزة متقدمةٌ، كما أنّها غير شائعة الاستخدام. وُجدت أساسًا لتُستعمل في المخاليط (mixins)، لاسيما تلك التي هي جزءٌ من المكتبات مثل Compass، لذلك فهي تتطلب مرونةً كبيرةً في التعامل معها. if()‎ تُعيد الدالة المضمّنة if()‎ إحدى قيمتين محدَّدتين بناءً على شرط معيّن، ويمكن استخدامها في أيّ سياق برمجي. لا تتحقق الدالة if إلا من ...

استخدام التعليمة Switch

توصيف المشكلة وجود تركيبٍ معقَّدٍ لتعليمة switch أو عدّة تعليمات if متسلسلة. أسبابها ما يميِّز البرمجة كائنيّة التوجّه (OO) هو اعتمادها النادر على المعاملين switch و case، إذ تُوزَّع شيفرة switch بمواقع مختلفة من البرنامج بدلًا من تجمعيها في تعليمة switch واحدةٍ، وعند إضافة شرطٍ جديدٍ عليك إيجاد كافّة شيفرات switch لتعديلها، وكقاعدة عامّة: وجود تعليمة switch يعني أن عليك البدء بالتفكير بمبدأ التعدديّة الشكليّة (polymorphism). وما الحل؟ عزل تعليمة switch ووضعها بالصنف الصحيح عبر إنشاء صنفٍ (class) ونقل التابع ...

تكرار الشيفرات (Duplicate Code)

توصيف المشكلة التشابه (أو التطابق المطلق) بين مقطعين من الشيفرة في البرنامج. أسبابها تحدث هذه المشكلة عندما يعمل أكثرُ من مبرمجٍ على كتابة أجزاءَ مختلفةٍ من نفس البرنامج وبنفس الوقت، فلا يدري أحدهم أنّ الشيفرة التي يكتبها قد سبقه بها مبرمجٌ آخر ومن الممكن استخدامها نفسها دون الحاجة لتكرارها. أو قد تنتُج عن وجود جزئين من الشيفرة مختلفين شكليًّا متماثلين ضمنيًا (يؤديان نفس المهمة)، ومن الصعب كشف هذا النوع من التكرار وعلاجه. قد يكون التكرار هادفًا ببعض الأحيان، كأن يكون ...

تبديل المتغير المؤقت إلى استدعاء(Replace Temp with Query)

المشكلة تخزين نتيجة تعبيرٍ ما (expression) في متغيِّر محليٍّ (local variable) لاستخدامه لاحقًا في الشيفرة. الحل نقل التعبير بأكمله إلى تابعٍ (method) مستقلٍ يعيد نتيجته، وعندها سيكون استدعاء هذا التابع بديلًا عن استخدام المتغيِّر (variable)، ومن الممكن أيضًا دمج هذا التابع مع توابع أخرى عند الحاجة للقيام بذلك. مثال قبل إعادة التصميم نلاحظ في الشيفرة الآتية وجود متغيِّرٍ مؤقتٍ باسم basePrice لتخزين القيمة الناتجة عن تنفيذ التعبير الرياضيّ بمعامل الجداء (أي المعامل *)، وسيُستخدَم هذا المتغيِّر لاحقًا في الأجزاء الشرطيّة ...

الحقول المؤقتة (Temporary Fields)

توصيف المشكلة تحتوي الحقول المؤقَّتة على قيمٍ (وتُستخدَم وفقًا لها في الكائنات [objects]) ضمن شروطٍ مُحدَّدة، وتبقى فارغةً عند عدم تحقٌّق تلك الشروط. أسبابها تُخصَّصُ الحقول المؤقتة لاستخدامها في الخوارزميات التي تتطلَّب عددًا كبيرًا من المُدخلات (inputs)، فبدلًا من إنشاء الكثير من المعاملات في التابع (method parameters) يلجأ المُبرمِج لإنشاء حقولٍ مؤقَّتة لاحتواء البيانات المطلوبة في الصنف (class)، وبهذا فإنّ استخدام تلك الحقول لا يتعدّى تنفيذَ الخوارزميّة المُحدَّدة (ولا وظيفة أخرى لها خارج ذلك النطاق)، ويجعل وجودُ تلك الحقول من ...

القائمة الطويلة للمعاملات (Long Parameter List)

توصيف المشكلة وجود ما يزيد عن ثلاثة أو أربعة معاملات (parameters) مُمرَّرة للتابع (method). أسبابها قد تحدث هذه المشكلة عند دمج عدّة خوارزمياتٍ بنفس التابع (method)، إذ تُستخدَم المعاملات (parameters) الكثيرة لتحديد الخوارزمية التي ستُنفَّذ وآليّتها. أو قد تنتج المشكلة عن محاولة المبرمج أو المطوِّر لجعل الأصناف (classes) أكثر استقلاليةً عن بعضها البعض. فمثلًا: عند نقل الشيفرة التي تنشِئ الكائنات (objects) -اللازمة لأحد التوابع- من داخل التابع إلى الشيفرة التي تستدعي ذلك التابع سيتطلَّبُ تمرير تلك الكائنات إلى التابع كمعاملاتٍ ...

التخطيط الشمولي المفرط (Speculative Generality)

توصيف المشكلة وجود أصنافٍ (classes) أو توابعَ (methods) أو حقولٍ (fields) أو معاملاتٍ (parameters) غير مُستخدَمة في الشيفرة. أسبابها إنشاء عناصرَ إضافيّةٍ "قد" يحتاجها المبرمج مستقبلًا لميّزات يُخطِّط لها (وقد لا تُنفَّذ أصلًا)، وغير مستخدمةٍ بالوقت الحاليّ، مما يجعل الشيفرة أكثر صعوبةً بالفهم والدعم. وما الحل؟ هدم الهيكليّة الهرميّة (collapse hierarchy) لإزالة الأصناف المُجرَّدة (abstract classes) غير المُستخدَمة. دمج الأصناف (inline classes) للحدُّ من عمليات تفويض المهامّ (delegation) غير الضروريّة لصنفٍ آخر. دمج التوابع (inline methods) للتخلُّص من التوابع عديمة ...

الأجزاء الفائضة (Dispensables)

وهي الأجزاء عديمة النفع في الشيفرة، وسيجعلُ التخلُّصُ منها الشيفرةَ نظيفةً يسيرة الفهم وأكثر فعاليّة، منها: التعليقات (comments) المشكلة: وجود الكثير من التعليقات في التوابع (methods) بهدف الشرح التفصيليّ للشيفرة. الحل: يكون الحل بناءً على الحالة المستعملة وهو: تقسيم التعبير الواحد إلى تعابيرَ فرعيّة (subexpressions) بالاعتماد على استخراج المتغيِّرات، أو عزل ذلك المقطع في تابعٍ (method) جديدٍ باسمٍ معبِّر، أو إعادة تسمية التابع (rename method) لاسمٍ يشرح ذاته بذاته، أو إضافة التأكيدات. تكرار  الشيفرة (duplicates) المشكلة: التشابه (أو التطابق المطلق) بين مقطعين من الشيفرة ...

المبالغة والإطالة (Bloaters)

قد يزداد حجم الشيفرات والتوابع (methods) والأصناف (classes) ازديادًا كبيرًا ليصل لمرحلةٍ يصعُب التعامل معها، ولا يحدث هذا بشكلٍ فجائيِّ دفعةً واحدةً، بل يكون ناتجًا عن تراكم الإضافات أثناء تطوير البرنامج (وخاصةً عندما لا يبذل أحدٌ جهدًا للحدِّ من ذلك التشعب)، ويبدو هذا التضخم واضحًا. التوابع الطويلة (long methods) المشكلة: تنتُج عن احتواء شيفرة التابع على الكثير من الأسطر. الحل: يشمل: إنشاء توابعَ جديدةٍ، أو تبديل المتغيَّرات المؤقَّتة إلى استداعاءات للدوال أو الاعتماد على كائن المعاملات، أو التعامل مع الكائن ككُلٍّ، أو ...

المبالغة والإطالة (Bloaters)

قد يزداد حجم الشيفرات والتوابع (methods) والأصناف (classes) ازديادًا كبيرًا ليصل لمرحلةٍ يصعُب التعامل معها، ولا يحدث هذا بشكلٍ فجائيِّ دفعةً واحدةً، بل يكون ناتجًا عن تراكم الإضافات أثناء تطوير البرنامج (وخاصةً عندما لا يبذل أحدٌ جهدًا للحدِّ من ذلك التشعب)، ويبدو هذا التضخم واضحًا. التوابع الطويلة (long methods) المشكلة: تنتُج عن احتواء شيفرة التابع على الكثير من الأسطر. الحل: يشمل: إنشاء توابعَ جديدةٍ، أو تبديل المتغيَّرات المؤقَّتة إلى استداعاءات للدوال أو الاعتماد على كائن المعاملات، أو التعامل مع الكائن ككُلٍّ، أو ...

تبديل قيم البيانات إلى كائنات (Replace Data Values with Objects)

المشكلة وجود حقلٍ (field) مٌخصَّص للبيانات في صنفٍ (class) ما (أو في عددٍ من الأصناف)، ولهذا الحقل بياناته وسلوكه (behaviour) المرتبط به. الحل إنشاء صنفٍ جديدٍ ليُوضَع فيه الحقل (field) بالإضافة إلى سلوكه المرتبط به، وتخزين كائنٍ (object) من هذا الصنف الجديد في الصنف الأصليّ للحقل. مثال قبل إعادة التصميم يحتوي الصنف Order على الحقل customer الذي يحتوي بيانات نصيّة (من النوع String) كما هو واضح في مخطط الأصناف الآتي: الصنف Order يحتوي على الحقل customer الذي يحتوي بيانات نصيّة. ...

حذف المعاملات (Remove Parameter)

المشكلة لا يُستخدم معاملٌ ما في متن التابع. الحل إزالة المعامل غير المستخدم. مثال قبل إعادة التصميم تعريف المعامل Date في بداية التابع ()getContact وعدم استخدامه. تعريف المعامل Date في بداية التابع ()getContact وعدم استخدامه. بعد إعادة التصميم إزالة المعامل Date من التابع ()getContact لعدم استخدامه: إزالة المعامل Date من التابع ()getContact. لم إعادة التصميم؟ يفرض كل معامل موجود في استدعاء التوابع على المبرمج أن يقرأه لمعرفة ما هي المعلومات الموجودة في هذا المعامل. وإذا كان المعامل غير مستخدم على ...

الشيفرة الميتة (Dead Code)

توصيف المشكلة وجود العديد من المتغيِّرات (variables) أو المعاملات (parameters) أو الحقول (fields) أو التوابع (methods) أو الأصناف (classes) غير المستخدمة في الشيفرة. أسبابها عدم توفُّر الوقت الكافي لتوضيب الشيفرة وإزالة ما لم يعُد مستخدَمًا فيها، وذلك بعد تغيُّر متطلَّبات البرنامج أو إجراء بعض الإصلاحات به. وجود تعابيرَ شرطيَّةٍ معقَّدةٍ لا يتحقَّقُ شرطُ أحد فروعها (بسبب خطأٍ ما أو بحالاتٍ خاصّةٍ لن تحدث). وما الحل؟ الطريقة الأسرع لإيجاد الشيفرة الميتة هي استخدام بيئةٍ تطويريّةٍ متكاملةٍ (IDE) قويّةٍ وجيدة، ويتلخَّص الحل ...

دمج المتغير المؤقت (Inline Temp)

المشكلة وجود متغيِّرٍ مؤقَّت (temporary) لحفظ قيمة تعبيرٍ (expression) بسيطٍ ولا شيء آخر سواه. الحل تبديل كلُّ مرجعيّةٍ (reference) للمتغيِّر ليحلَّ محلَّها التعبيرُ نفسه. مثال قبل إعادة التصميم نلاحظ في الشيفرة الآتية وجود متغيِّرٍ مؤقتٍ باسم basePrice لتخزين القيمة الناتجة عن تعبير استدعاء التابع order.basePrice()‎، والذي سيُستخدَم في التعليمة التالية لتعريفه: في لغة Java: boolean hasDiscount(Order order) { double basePrice = order.basePrice(); return basePrice > 1000; } في لغة #C: bool HasDiscount(Order order) { double basePrice = order.BasePrice(); return ...

اختلال الشيفرات ومشاكلها (Code Smells)

قد تعاني الشيفرات الكثير من الاختلالات والمشاكل الشكلية؛ فبمجرد اكتشاف تلك الاختلالات الظاهرية، يسهل علينا معرفة العلاج (التقنيات) وتطبيقه (إعادة التصميم) للحصول على شيفرة سليمة نظيفة. من هذه الاختلالات: المبالغة والإطالة قد يزداد حجم الشيفرات والتوابع (methods) والأصناف (classes) ازديادًا كبيرًا ليصل لمرحلةٍ يصعُب التعامل معها، ولا يحدث هذا بشكلٍ فجائيِّ دفعةً واحدةً، بل يكون ناتجًا عن تراكم الإضافات أثناء تطوير البرنامج (وخاصةً عندما لا يبذل أحدٌ جهدًا للحدِّ من ذلك التشعب)، ويبدو هذا التضخم واضحًا التوابع الطويلة (long methods): ...

تبديل رموز الأنواع بالحالة/الاستراتيجية (Replace Type Code with State/Strategy)

ما هو رمز النوع؟ يحدث رمز النوع عندما يوجد مجموعة من الأرقام أو السلاسل النصية التي تشكل قائمة بالقيم المسموح بها لبعض العناصر بدلًا من استخدام نوع بيانات منفصل. وغالبًا ما تُعطَى هذه الأرقام والسلاسل المحددة أسماءً مفهومة عن طريق الثوابت، وهو السبب في استخدام هذه الرموز بشكل كبير. المشكلة يؤثر نوع مُرمَّز على سلوك البرنامج ولكن لا يمكن استخدام الأصناف الفرعية للتخلص منه. الحل استبدال رمز النوع بكائن حالة. إذا كان من الضروري استبدال قيمة حقل برمز النوع، فسيكون ...

تنقيح تطبيقات ريلز

يقدّم هذا الدليل التقنيات اللازمة لتنقيح تطبيقات ريلز. بعد قراءة هذا الدليل، ستتعلّم: الغرض من التنقيح. كيفة تتبّع العلل والأخطاء التي لا تتعرّف عليها الاختبارات في تطبيقك. طرقًا مختلفة للتنقيح. كيفيّة تحليل أثر المكدس. مساعدي العرض للتنقيح احدى المهام الشائعة في التنقيح هي فحص محتويات متغيّر معيّن، لذا يوفر ريلز ثلاثة طرائق لفعل ذلك: Debug To_yaml Inspect debug سيعيد المساعد debug الوسم <pre> الذي يصدّر الكائن باستخدام تنسيق YAML، وسيؤدي هذا إلى توليد بيانات يمكن للإنسان قراءتها من أي كائن. ...

استخراج الأصناف الفائقة (Extract Superclass)

المشكلة وجود صنفين لهما حقول وتوابع مشتركة. الحل إنشاء صنف أب مشترك لهما ونقل جميع الحقول والتوابع المتطابقة إليه. مثال قبل إعادة التصميم يملك الصنفين Department و Employee توابعًا مشتركة فيما بينهما: وجود صنفين لهما حقول وتوابع مشتركة. بعد إعادة التصميم إنشاء صنف أب لهما يدعى Party يحوي التوابع المشتركة: إنشاء صنف فائق مشترك لهما ونقل جميع الحقول والتوابع المتطابقة إليه. لم إعادة التصميم؟ يحدث نوع من تكرار الشيفرة عندما يؤدي صنفان نفس المهام بنفس الطريقة أو بطرق مختلفة. وتتيح ...

التعامل مع التعميم (Dealing with Generalization)

يملك التجريد (Abstraction) تقنيات إعادة التصميم الخاصة به والمرتبطة بشكل أساسي بوظيفة النقل على طول التسلسل الهرمي لوراثة الصنف (class inheritance hierarchy)، وبإنشاء أصناف وواجهات جديدة، وبتبديل التفويض مكان الوراثة أو العكس. تقنيات هذا القسم هي: استخراج الأصناف الفرعية (Extract Subclass) المشكلة: يكون للصنف ميزات تستعمل فقط في حالات معينة. الحل: إنشاء صنف فرعي واستخدامه في هذه الحالات. استخراج الأصناف الفائقة (Extract Superclass) المشكلة: وجود صنفين لهما حقول وتوابع مشتركة. الحل: إنشاء صنف أب مشترك لهما ونقل جميع الحقول والتوابع ...

الوراثة الفائضة (Refused Bequest)

توصيف المشكلة استفادة الصنف الفرعيّ (subclass) من القليل فقط ممّا ورِثه عن الصنف الأعلى (superclass) من توابعَ (method) وحقولٍ (fields)، لتبقى التوابع الأخرى غيرَ مُستخدَمةٍ أو قد يُعاد تعريفها (redefined) مع الكثير من الاختلافات. أسبابها إنشاء علاقة الوراثة (inheritance) ما بين صنفين مختلفين كليًّا بدافع إعادة استخدام الشيفرة الموجودة في الصنف الأعلى (superclass) في الصنف الفرعيّ (subclass). وما الحل؟ إن لم يشترك الصنف الفرعيّ (subclass) مع الصنف الأعلى (superclass) بشيءٍ، فالوراثة غير منطقيّةٍ بالأصل، والأفضلُ التخلي عنها بتبديلها إلى تفويض ...

البيانات المُجمَّعة (Data Clumps)

توصيف المشكلة تكرار مجموعةٍ من المتغيِّرات (variables) (كتلك المُستخدَمة كمعاملاتٍ [parameters] للربط مع قاعدة البيانات مثلًا) بشكلٍ متطابقٍ تمامًا في عدّة أجزاء من الشيفرة، إذ يجب تحويل تلك المجموعات إلى أصنافها (classes) الخاصّة بها. أسبابها تُعزى المشكلة عمومًا للبُنية (structure) البرمجيّة الضعيفة (أو ما يُعرف بمصطلح copypasta programming)، وللتحقُّقِ من وجود هذه المشكلة بالشيفرة احذف إحدى القيم، فإنْ حدث خللٌ نتيجة الحذف فالمشكلة قائمة ويجب علاجها، وإلّا فتلك إشارةٌ حسنةٌ ومن المحبَّذ تجميعُ هذه المتغيِّرات في كائنٍ واحدٍ. وما الحل؟ ...

أصناف المكتبة غير الكافية (Incomplete Library Classes)

توصيف المشكلة لا تلبِّي أصناف المكتبة (library classes) كافّة احتياجات البرنامج مع استمرار تطوُّره، ولا يمكن تعديلها لأنّها مُخصَّصةٌ للقراءة فقط (read-only). أسبابها عدم تزويد مُطوِّر المكتبة كافَّةَ الميّزات (features) التي تحتاجها في البرنامج أو امتناعه عن تعريفَ استخدامها (implement). وما الحل؟ لتعريف بعض التوابع (methods) في المكتبة عليك بتعريف التوابع الدخيلة (introduce foreign methods). أمّا لإجراء تغييراتٍ واسعةٍ في صنف المكتبة فعليك بتعريف الإضافات المحليّة (introduce local extensions). إليك المزيد سيكون حلُّ المشكلة كفيلًا بالتقليل من تكرار الشيفرات (duplications)، ...

استبدال الخوارزمية (Substitute Algorithm)

المشكلة الحاجة إلى استبدال خوارزميّة ما بخوارزميّة أخرى. الحل تعديل محتوى التابع (method body) الذي يُنفِّذ الخوارزمية السابقة ليُنفِّذ الخوارزمية الجديدة. مثال قبل إعادة التصميم تتلخَّص مهمة التابع foundPerson بالبحث عن الأشخاص ذوي الأسماء "Don" أو "John" أو "Kent" وذلك بالمرور بعناصر المصفوفة النصّيّة people باستخدام حلقة for كما في الشيفرة: في لغة Java: String foundPerson(String[] people){ for (int i = 0; i < people.length; i++) { if (people[i].equals("Don")){ return "Don"; ...

إضافة المعاملات (Add Parameter)

المشكلة لا يملك التابع بيانات كافية لتنفيذ بعض الإجراءات. الحل إنشاء معامل جديد لتمرير البيانات الضرورية. مثال قبل إعادة التصميم لا يملك التابع ()getContact في الصنف Customer لجدولة موعدٍ للتواصل مع الزبون: لا يملك التابع بيانات كافية لتنفيذ بعض الإجراءات. بعد إعادة التصميم أصبح بالإمكان تمرير تاريخ إلى التابع ()getContact لتصبح بيانات جدولة تاريخ مناسب مع الزبون مكتملة: إنشاء معامل جديد لتمرير البيانات الضرورية. لم إعادة التصميم؟ تحتاج إلى إجراء بعض تغييرات على أحد التوابع، وتتطلب هذه التغييرات إضافة معلومات ...

توحيد التعبير الشرطي (Consolidate Conditional Expression)

المشكلة وجود عدة شروط تؤدي إلى نفس النتيجة أو الإجراء. الحل توحيد جميع هذه الشروط في تعبير وحيد. مثال قبل إعادة التصميم وجود عدة شروط يتم التحقق منها في الشيفرة: في لغة Java: double disabilityAmount() { if (seniority < 2) { return 0; } if (monthsDisabled > 12) { return 0; } if (isPartTime) { return 0; } // حساب مقدار العجز //... } في ...

الحفاظ على الكائن كاملًا (Preserve Whole Object)

المشكلة جلب عدة قيم من أحد الكائنات، ثم تمريرها كمعاملات إلى أحد التوابع. الحل حاول تمرير الكائن بالكامل بدلًا من ذلك. مثال قبل إعادة التصميم جلب قيمة درجة الحرارة المنخفضة low والمرتفعة high من الكائن daysTempRange ثم تمريرهما إلى التابع ()withinTange: في لغة Java: int low = daysTempRange.getLow(); int high = daysTempRange.getHigh(); boolean withinPlan = plan.withinRange(low, high); في لغة C#‎: int low = daysTempRange.GetLow(); int high = daysTempRange.GetHigh(); bool withinPlan = plan.WithinRange(low, high); في لغة PHP: $low = $daysTempRange->getLow(); $high = $daysTempRange->getHigh(); $withinPlan = $plan->withinRange($low, $high); في لغة Python: ...

تبديل رموز الأنواع بالأصناف الفرعية (Replace Type Code with Subclasses)

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

الوسيط (Middle Man)

توصيف المشكلة عندما يكون للصنف (class) مهمةٌ واحدةٌ فقط وهي تفويض المهام (delegation) لصنفٍ آخر، فما أهمية وجوده بالأصل؟ أسبابها قد تنتج المشكلة عن التخلُّص المفرط من الاستدعاءات المتسلسلة كعلاجٍ لمشكلة سلاسل الرسائل (message chains). أو قد تنتُج عن النقل التدريجيّ للصنف (class) إلى أصناف أخرى ليبقى الصنف الأصليّ فارغًا إلا من أوامر التفويض (delegation). وما الحل؟ حذف الوسيط (remove middle man) إن كانت معظم أصناف التابع (method's classes) تفوِّض المهام (delegate) إلى صنفٍ آخر. إليك المزيد ستحصل بحلِّ المشكلة ...

إزالة الإسناد إلى المعاملات (Remove Assignments to Parameters)

المشكلة إسناد قيمةٍ ما إلى أحد المعاملات (parameter) داخل التابع (method body). الحل استخدام متغيِّرٍ محليٍّ (local variable) بدلًا من المعامل. مثال قبل إعادة التصميم نلاحظ وجود عمليّة إسنادٍ (من بعد الإنقاص بمقدار 2) إلى معامل التابع الوارد باسم inputVal: في لغة Java: int discount(int inputVal, int quantity) { if (inputVal > 50) { inputVal -= 2; } //... } في لغة #C: int Discount(int inputVal, int quantity) { if (inputVal > 50) ...

تجزئة المتغير المؤقت (Split Temporary Variable)

المشكلة وجود متغيِّرٍ محليّ يُستخدَم لتخزين عدّة قيمٍ مؤقتةٍ (مرحليّة) داخل التابع. الحل استخدام متغيِّراتٍ منفصلةٍ ومستقلّةٍ للقيم المختلفة، بحيث يكون كلَُ متغيِّرٍ مسؤولًا عن تخزين البيانات لمهمةٍ واحدةٍ فقط. مثال قبل إعادة التصميم نلاحظ في الشيفرة الآتية استخدام المتغيِّر temp لتخزين ناتج كلِّ من تعبيريّ المحيط والمساحة: في لغة Java: double temp = 2 * (height + width); System.out.println(temp); temp = height * width; System.out.println(temp); في لغة #C: double temp = 2 * (height + width); Console.WriteLine(temp); temp = height * width; Console.WriteLine(temp); في لغة PHP: $temp ...

دفع الحقل لأسفل (Push Down Field)

المشكلة هل يستخدم الحقل في بعض الأصناف الفرعية فقط؟ الحل نقل الحقل إلى هذه الأصناف الفرعية. مثال قبل إعادة التصميم يُستخدَم الحقل fuel الموجود في الصنف Unit الأب في صنف فرعي واحد فقط الذي هو Tank: يستخدم الحقل في بعض الأصناف الفرعية فقط. بعد إعادة التصميم نقل الحقل من الصنف الأب إلى الصنف الفرعي المستخدم فيه: نقل الحقل إلى هذه الأصناف الفرعية. لم إعادة التصميم؟ على الرغم من أنه كان من المقرر استخدام حقل بشكل عام لجميع الأصناف، في الواقع ...

سحب الحقل لأعلى (Pull Up Field)

المشكلة يحتوي صنفان على نفس الحقل. الحل إزالة الحقل من الأصناف الفرعية ونقله إلى الصنف الأعلى. مثال قبل إعادة التصميم يحتوي الصنفان Tank و Soldier المتفرعان من الصنف Unit على الحقل المشترك health: يحتوي الصنفان Soldier و Tank على نفس الحقل health. بعد إعادة التصميم إزالة الحقل health من الأصناف الفرعية (الصنف Soldier والصنف Tank) ونقله إلى الصنف Unit الأب: إزالة الحقل health من الأصناف الفرعية ونُقل إلى الصنف الأب. لم إعادة التصميم؟ تنمو الأصناف الفرعية وتتطور بشكل منفصل، مما ...

استخرج الواجهات (Extract Interface)

المشكلة يستخدم العديد من العملاء نفس الجزء من واجهة الصنف. حالة أخرى: عندما يوجد نفس الجزء من الواجهة في صنفين. الحل نقل هذا الجزء المتطابق إلى الواجهة الخاصة به. مثال قبل إعادة التصميم استخدام التابعين ()getRate و ()hasSpecialSkill في الصنف Employee بكثرة: يستخدم العديد من العملاء نفس الجزء من واجهة الصنف. بعد إعادة التصميم استخراج هذين التابعين إلى واجهة خاصة بهما تدعى Billable: تقل هذا الجزء المتطابق إلى الواجهة الخاصة به. لم إعادة التصميم؟ تكون الواجهات مناسبة جدًا عندما تلعب ...

استبدال التفويض بالتوريث (Replace Delegation with Inheritance)

المشكلة يحتوي الصنف على العديد من التوابع البسيطة التي تفوِّض إلى كل التوابع في صنفٍ آخر. الحل جعل الصنف مفوِّض وارث، الأمر الذي يجعل تابع التفويض غير ضروري. مثال قبل إعادة التصميم التابع الموجود في الصنف Employee مفوَّض إلى التابع ()getName في الصنف Person: يحتوي الصنف على العديد من التوابع البسيطة التي تفوِّض إلى كل التوابع في صنفٍ آخر. بعد إعادة التصميم جعل الصنف Employee يرث من الصنف Person والتخلص من التفويض: أصبح الصنف مفوِّض وارث، الأمر الذي يجعل تابع ...

تجزئة الشَرطيات (Decompose Conditional)

المشكلة يوجد شَرط مُعقد (if-then/else أو switch). الحل فصل الأجزاء المعقدة من الشَرط إلى توابع منفصلة: الشرط، then و else. مثال قبل إعادة التصميم وجود شرط معقد ناتج عن دمج شرطين باستعمال المعامل || الثنائي في البنية if: في لغة Java: if (date.before(SUMMER_START) || date.after(SUMMER_END)) { charge = quantity * winterRate + winterServiceCharge; } else { charge = quantity * summerRate; } في لغة C#‎: if (date < SUMMER_START || date > SUMMER_END) { charge = quantity * winterRate + winterServiceCharge; } else ...

الاستخدام الخطأ لمبادئ البرمجة كائنية التوجه (Object-Orientation Abusers)

من مشاكل الشيفرات أيضًا التطبيقُ الخطأ وغير المكتمل لمبادئ البرمجة كائنية التوجّه (Object-Oriented)، مثل: استخدام الأصناف البديلة (alternative) ذات الواجهات (interfaces) المختلفة المشكلة: التطابق بالمهام ما بين صنفين ولكن بأسماءٍ مختلفةٍ لتوابعهما. الحل: حذف أحد الصنفين بعد تنفيذ إحدى الحلول الآتية: إعادة تسمية التوابع (methods) لتصبح متطابقةً بكافّة الأصناف البديلة، أو توحيد التوقيع (signature) وتعريف الاستخدام ما بين التوابع (إمّا بنقل التابع أو إضافة المعاملات أو دمج التوابع عبر المعاملات)، أو استخراج صنفٍ أعلى وجعلهما صنفين فرعيين له (إن كان التطابق جزئيًا). الوراثة الفائضة (refused bequest) ...

تعريف كائن المُعامل (Introduce Parameter Object)

المشكلة تحتوي التوابع على نفس المجموعة المتكررة من المعاملات. الحل استبدال هذه المعاملات بكائنٍ واحد. مثال قبل إعادة التصميم تمرير نفس مجموعة المعاملات إلى توابع الصنف Customer: تحتوي التوابع على نفس المجموعة المتكررة من المعاملات. بعد إعادة التصميم تبديل كائن واحد بتلك المعاملات وتمريره إلى توابع الصنف Customer التي تشترك بنفس مجموعة المعاملات: استبدال هذه المعاملات بكائنٍ واحد. لم إعادة التصميم؟ غالبًا ما تُصادَف مجموعات متطابقة من المعاملات داخل العديد من التوابع. الأمر الذي يؤدي إلى تكرار الشيفرة البرمجية للمعاملات ...

هدم التسلسل الهرمي (Collapse Hierarchy)

المشكلة في التسلسل الهرمي لصنف، يكون صنفٌ فرعي هو عمليًا نفس صنفه الأب. الحل دمج الصنف الفرعي والصنف الأب. مثال قبل إعادة التصميم الصنف الفرعي Salesman هو عمليًّا نفس الصنف Employee له: الصنفٌ الفرعي هو عمليًا نفس صنفه الأب. بعد إعادة التصميم دمج الصنف الفرعي Salesman في الصنف الأب: دمج الصنف الفرعي والصنف الأب. لم إعادة التصميم؟ قد يؤدي نمو البرنامج مع مرور الوقت إلى أن يصبح كلٌ من الصنف الفرعي والصنف الأب تقريبًا نفس الشيء. فتُزال ميزة من الصنف ...

تغيير الاقتران ثنائي الاتجاه إلى أحادي الاتجاه (Change Bidirectional Association to Unidirectional)

المشكلة وجود اقتران ثنائي الاتجاه (bidirectional association) بين الأصناف، ولكن لا يستخدم أحد الأصناف الميزات الأخرى. الحل إزالة الاقتران غير المستخدم. مثال قبل إعادة التصميم وجود اقتران ثنائي الاتجاه بين الصنفين Order و Customer، ولكن لا يستخدم أحدهما ميزات الآخر: وجود اقتران ثنائي الاتجاه بين الصنفين Order و Customer. بعد إعادة التصميم يحتاج الصنفان Customer و Order أحدهما الآخر ولكن الاقتران بينهما أحادي الاتجاه: وجود اقتران ثنائي الاتجاه بين الصنفين Order و Customer. لم إعادة التصميم؟ يكون من الصعب المحافظة على الاقتران ثنائي الاتجاه ...

هوس الحقول الأساسية (Primitive Obsession)

توصيف المشكلة تظهر المشكلة بعدَّة جوانب: استخدام الحقول الأساسيّة (primitives) بدلًا من الكائنات (objects) لأداء المهامّ البسيطة (مثل: عمليات العملة [currency] والمجالات [ranges] والسلاسل النصية [strings] المُخصَّصة للأرقام الهاتفية، …إلخ.). استخدام الثوابت (constants) لترميز المعلومات (مثل استخدام الثابت USER_ADMIN_ROLE = 1 للدلالة على المستخدمين ذوي الصلاحيّات الإداريّة). استخدام الثوابت النصيّة (string constants) كأسماءٍ للحقول (fields) في مصفوفات البيانات (data arrays). أسبابها تنشأ هذه المشكلة بسبب العبارة المُدمِّرة التي يفكّر بها المبرمجون بلحظة ضعفٍ: "حقلٌ واحدٌ فقط، ولتخزين معلومةٍ بسيطةٍ وحسب!"ولأنهم ...

تغليف الحقول (Encapsulate Field)

المشكلة لديك حقل عام. الحل جعل الحقل خاصًّا وإنشاء توابع وصول له. مثال قبل إعادة التصميم وجود الحقل العام name في الصنف Person: في لغة Java: class Person { public String name; } في لغة C#‎: class Person { public string name; } في لغة PHP: public $name; في لغة TypeScript: class Person { name: string; } بعد إعادة التصميم جعل الحقل name خاصًّا وإنشاء تابع جلب getName وضبط setName له: في لغة Java: class Person { private String name; public ...

استبدال شيفرات الأخطاء باستثناءات (Replace Error Code with Exception)

المشكلة يعيد التابع قيمة خاصة تشير إلى خطأ. الحل إطلاق استثناء بدلًا من ذلك. مثال قبل إعادة التصميم يعيد التابع ()withdraw القيمة 1- التي تمثِّل خطأً إن تحقق شرط محدَّد: في لغة Java: int withdraw(int amount) { if (amount > _balance) { return -1; } else { balance -= amount; return 0; } } في لغة C#‎: int Withdraw(int amount) { if (amount > _balance) { ...

تكرار البيانات المرُاقَبة (Duplicate Observed Data)

المشكلة هل بيانات النطاق المخزَّنة في أصناف هي المسؤولة عن واجهة المستخدم الرسومية (GUI)؟ إذًا، إليك الحل. الحل فصل البيانات في أصناف منفصلة لضمان الاتصال والتزامن بين صنف النطاق وواجهة المستخدم الرسومية (GUI). مثال قبل إعادة التصميم إليك المخطط التالي لبيانات نطاق مخزَّنة في أصناف والمسؤولة عن الواجهة الرسومية: بيانات النطاق مخزَّنة في أصناف. بعد إعادة التصميم يصبح المخطط السابق بالشكل التالي بعد إعادة التصميم: فصل البيانات في أصناف منفصلة لضمان الاتصال والتزامن بين صنف النطاق وواجهة المستخدم الرسومية. لم ...

الخاصيات العامة

الخاصيات العامة هي الخاصية التي يمكن استعمالها في جميع عناصر HTML، على الرغم من أنَّها قد لا يكون لها تأثير إن استعملت على بعض العناصر. يمكن أن تستعمل الخاصيات العامة على جميع عناصر HTML حتى لو لم تكن هذه العناصر موجودةً في المعيار، وهذا يعني أنَّ العناصر غير المعيارية يجب أن تسمح باستخدام هذه الخاصية، حتى لو كان استخدام هذه العناصر سيؤدي إلى جعل المستند غير متوافق مع معيار HTML5. فمثلًا ستخفي المتصفحات التي تدعم HTML5 المحتوى الموجود ضمن العنصر ...

استخراج المتغيرات (Extract Variables)

المشكلة وجود تعبيرٍ (expression) معقِّد يصعُب فهمه. الحل وضع ناتج التعبير أو جزءٍ منه في متغيِّرات (variables) واضحةٍ تُسهِّل الفهم. مثال قبل إعادة التصميم نلاحظ وجود تعبيرٍ شرطيٍّ (conditional expression) معقَّدٍ وبعدّة أجزاء كما في الشيفرة الآتية: في لغة Java: void renderBanner() { if ((platform.toUpperCase().indexOf("MAC") > -1) && (browser.toUpperCase().indexOf("IE") > -1) && wasInitialized() && resize > 0 ) { // افعل شيئًا ...

سحب متن المُنشِئ لأعلى (Pull Up Constructor Body)

المشكلة تحتوي الأصناف الفرعية على مُنشِئات لها شيفرة متطابقة في أغلبها. الحل إنشاء مُنشئ صنف أب ونقل الشيفرة المماثلة في الأصناف الفرعية إليه. استدعاء مُنشئ الصنف الأب في مُنشِئات الصنف الفرعي. مثال قبل إعادة التصميم احتواء الصنف الفرعي Manager المشتق من الصنف Employee على منشئ متطابق بنسبة كبيرة: في لغة Java: class Manager extends Employee { public Manager(String name, String id, int grade) { this.name = name; this.id = id; ...

تبديل رموز الأنواع بالأصناف (Replace Type Code with Class)

ما هو رمز النوع (type code)؟ يحدث رمز النوع عندما يوجد مجموعة من الأرقام أو السلاسل النصية التي تشكل قائمة بالقيم المسموح بها لبعض العناصر بدلًا من استخدام نوع بيانات منفصل. غالبا ما تُعطى هذه الأرقام والسلاسل المحددة أسماءً مفهومة عن طريق الثوابت، وهو السبب في استخدام هذه الرموز بشكل كبير. المشكلة يحتوي الصنف على حقل يحتوي على رموز الأنواع. ولا تُستخدم قيم هذا النوع في شروط المُشغِّل ولا تؤثر على سلوك البرنامج. الحل إنشاء صنف جديد واستخدام كائناته بدلًا ...

تخزين الملفات (File storage) في Laravel

مقدمة يوفّر Laravel تجريدًا قويًا لنظام الملفات بفضل الحزمة Flysystem. يوفّر تضمين أنظمة الملفات في Laravel مشغّلات سهلة الاستعمال للتعامل مع الأنظمة المحلية و Amazon S3 والتخزين السحابي Rackspace، بل من السهل جدًا تغيير خيارات التخزين إذ تبقى وصلة API نفسها مع كل الأنظمة. الضبط يوجد ملف ضبط نظام الملفات في config/filesystems.php. يمكنك في هذا الملف ضبط كل الأقراص "disks". يمثّل كل قرص مشغّل تخزين ومكان تخزين خاص. يحتوي الملف على أمثلة ضبط لكل مشغّل مدعوم. لذا غيّر الملف حسب ...

فصل الاستعلامات عن المُعدِّلات (Separate Query from Modifier)

المشكلة هل لديك تابعٌ يُعيد قيمةً ما ولكن يغيِّر أيضا شيئًا ما داخل الكائن؟ الحل تقسيم التابع إلى تابعَين منفصلَين. كما يمكن أن نتوقع، يجب على أحدهما أن يعيد القيمة ويُغيِّر الآخر الكائن. مثال قبل إعادة التصميم ينفذ التابع ()getTotlaOutstandingAndSetReadyForSummaries في الصنف Customer مهمتين، إذ يعيد قيمة ويضبط قيمة أخرى في الكائن: تابع يُعيد قيمة ويغيِّر شيئًا ما داخل الكائن. بعد إعادة التصميم فصل التابع التابع ()getTotlaOutstandingAndSetReadyForSummaries إلى تابعين هما: الأول ()getTotlaOutstanding لجلب قيمة، والآخر ()setReadyForSummaries لضبط حالةٍ في الكائن: ...

استبدال الاستثناءات بالاختبارات (Replace Exception with Test)

المشكلة إطلاق استثناء يمكن لاختبار بسيط أن يحل محله. الحل يستعاض عن الاستثناء باختبار الحالة. مثال قبل إعادة التصميم معالجة الاستثناء الحاصل عند وقوع الفهرس periodNumber خارج حدود مصفوفة القيم values وإعادة القيمة 0 آنذاك: في لغة Java: double getValueForPeriod(int periodNumber) { try { return values[periodNumber]; } catch (ArrayIndexOutOfBoundsException e) { return 0; } } في لغة C#‎: double GetValueForPeriod(int periodNumber) { try { return values[periodNumber]; ...

التابع Method.parameters‎ في روبي

يعيد التابع parameters معلومات عن معاملات الكائن Method الذي استُدعي معه. البنية العامة parameters → array‎ القيمة المعادة تعاد مصفوفة تحوي معلومات عن وسائط الكائن Method المعطى. أمثلة مثال على استخدام التابع parameters‎: def foo(bar); end method(:foo).parameters #=> [[:req, :bar]] def foo(bar, baz, bat, &blk); end method(:foo).parameters #=> [[:req, :bar], [:req, :baz], [:req, :bat], [:block, :blk]] def foo(bar, *args); end method(:foo).parameters #=> [[:req, :bar], [:rest, :args]] def foo(bar, baz, *args, &blk); end method(:foo).parameters #=> [[:req, :bar], [:req, :baz], [:rest, :args], [:block, :blk]]‎ انظر أيضا التابع owner: يعيد الصنف ...

الدالة weakref.WeakMethod()‎ في بايثون

صنف فرعي خاصّ من الصنف ref يحاكي إشارة ضعيفة إلى تابع مرتبط bound method (أي تابع معرف في صنف وجرى البحث عنه في نسخة من ذلك الصنف). ملاحظة: هذا الصنف جديد في الإصدار 3.4. البنية العامة class weakref.WeakMethod(method) المعاملات dict التابع المراد إنشاء محاكاة لإشارة ضعيفة إليه. التوابع المرتبطة سريعة الزوال ما يمنع من تمسّك الإشارات الضعيفة العادية بها. يمتلك الصنف WeakMethod طريقة خاصة لإعادة إنشاء التابع المرتبط والإبقاء عليه إلى أن يموت الكائن أو الدالة الأصلية: >>> class C: ... ...

التابع Object.method في روبي

يبحث التابع method عن تابعٍ باسمٍ محدَّد في الكائن المعطى بوصفه مستقبلًا (receiver)، ثمَّ يعيد كائنًا من النوع Method لذلك التابع (أو يرمي الاستثناء NameError). يتصرَّف الكائن Method كتعبيرٍ مغلق (closure) في نسخ الكائن الخاصة بالكائن الذي يبحث فيه؛ لذلك، تبقى متغيِّرات النسخة (instance variables) وقيمة self متاحةً. البنية العامة method(sym) → method المعاملات sym رمزٌ يشير إلى اسم التابع المراد البحث عنه. القيم المعادة يُعاد كائنًا من النوع Method يمثِّل التابع الموافق للاسم sym الموجود في الكائن المعطى، أو ...

التابع Method.to_proc‎ في روبي

يعيد التابع to_proc الكائن Proc المقابل للكائن Method الذي استُدعي معه. البنية العامة to_proc → proc‎ القيمة المعادة يعاد كائنٌ من النوع Proc الذي يقابل الكائن Method المعطى. انظر أيضا التابع super_method: يعيد كائنًا من النوع Method للصنف الأب (superclass) للكائن Method الذي استدعي معه. التابع to_s: يعيد اسم التابع الأصلي (underlying method). مصادر قسم التابع to_proc‎ في الصنف Method‎ في توثيق روبي الرسمي.

التابع Method.super_method‎ في روبي

يعيد التابع super_method كائنًا من النوع Method للصنف الأب (superclass) للكائن Method الذي استدعي معه لاستدعائه عند استخدام super، أو يعيد nil إن لم يكن هناك تابع في الصنف الأب. البنية العامة super_method → method‎ القيمة المعادة يعاد كائن من النوع Method للصنف الأب للكائن Method المعطى، أو تعاد القيمة nil إن لم يكن هناك تابع في الصنف الأب. انظر أيضا التابع source_location: يعيد اسم الملف المصدر لروبي ورقم السطر الذي يحتوي هذا التابع، التابع to_proc: يعيد كائنًا من النوع Proc المقابل ...

التابع Object.define_singleton_method في روبي

يُعرِّف التابع define_singleton_method تابعًا منفردًا (singleton method) في المستقبل (receiver). البنية العامة define_singleton_method(symbol, method) → symbol define_singleton_method(symbol) { block } → symbol المعاملات symbol الرمز المُمرَّر إلى التابع والذي سيُعرِّف التابع المنفرد. method التابع المُمرَّر كمعامل. يمكن أن يكون هذا التابع كائنًا من النوع proc، أو Method، أو UnboundMethod. block وسيط اختياري يمثِّل الكتلة المُمرَّرة إلى التابع. إذا أعطي، فستُنفَّذ الكتلة المعطاة كما لو أنَّها من جسم التابع method. القيم المعادة يُعاد تابعٌ منفردٌ يمكن استدعائه في المستقبل. أمثلة مثالٌ عن ...

عرض (500 السابقة | 500 التالية) (20 | 50 | 100 | 250 | 500).