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

على الرغم من ذلك ، أود أن أشير إلى أن بعض التوصيات التي سيتم تقديمها في هذه المادة تهدف إلى تطبيقات React من أي نطاق.
إذا لم تقم مطلقًا بإنشاء تطبيق إنتاج ، فيمكن أن تساعدك هذه المقالة على الاستعداد لتطوير حلول واسعة النطاق. شيء من هذا القبيل يمكن أن يصبح أحد مشاريعك القادمة. إن أسوأ شيء يمكن أن يحدث للمبرمج هو عندما يعمل في مشروع ويدرك أنه بحاجة إلى إعادة تشكيل كميات كبيرة من التعليمات البرمجية لتحسين قابلية التطبيق للتطبيق وقابلية صيانته. يبدو كل شيء أسوأ إذا لم تكن هناك اختبارات وحدة في المشروع قبل إعادة البناء.
يطلب مؤلف هذه المادة من القارئ أن يأخذ كلامه من أجلها. لقد كان في مواقف مماثلة. لذلك ، حصل على العديد من المهام التي تحتاج إلى حل في وقت معين. في البداية ، اعتقد أن كل شيء فعله كان ممتازًا. مصدر هذه الأفكار هو أن تطبيق الويب الخاص به ، بعد إجراء التغييرات ، واصل العمل ، وفي الوقت نفسه واصل العمل بسرعة. كان يعرف كيفية استخدام Redux ، وكيفية إقامة تفاعل طبيعي بين مكونات واجهة المستخدم. بدا له أنه فهم عميق مفاهيم المخفضات والإجراءات. شعر بالضعف.
ولكن هنا تسلل المستقبل.
بعد شهرين من العمل على التطبيق ، تمت إضافة أكثر من 15 ميزة جديدة إليه. بعد ذلك ، خرج المشروع عن السيطرة. أصبح من الصعب للغاية الحفاظ على الكود الذي استخدم مكتبة Redux. لماذا حدث هذا؟ في البداية ، ألا يبدو أن المشروع كان يتوقع حياة طويلة وغائمة؟
يقول مؤلف المقال إنه ، من خلال طرح أسئلة مماثلة ، أدرك أنه زرع قنبلة موقوتة في المشروع بيديه.
مكتبة Redux ، إذا تم استخدامها بشكل صحيح في المشاريع الكبيرة ، تساعد ، مع نمو هذه المشاريع ، على الحفاظ على التعليمات البرمجية الخاصة بهم في حالة معتمدة.
فيما يلي 11 نصيحة لأولئك الذين يرغبون في تطوير تطبيقات React القابلة للتحجيم باستخدام Redux.
1. لا تضع قانون العمل والثوابت في مكان واحد
قد تصادف بعض برامج Redux التعليمية التي يتم فيها تثبيت الثوابت وجميع الإجراءات في نفس المكان. ومع ذلك ، يمكن أن يؤدي هذا الأسلوب ، أثناء نمو التطبيق ، إلى حدوث مشكلات بسرعة. يلزم تخزين الثوابت بشكل منفصل ، على سبيل المثال ، في
./src/constants
. نتيجةً لذلك ، للبحث عن الثوابت ، عليك أن تبحث في مجلد واحد فقط وليس عدة مجلدات.
بالإضافة إلى ذلك ، يبدو إنشاء إجراءات تخزين ملفات منفصلة أمرًا طبيعيًا تمامًا. تتضمن هذه الملفات إجراءات مرتبطة مباشرة ببعضها البعض. الإجراءات في ملف واحد ، على سبيل المثال ، قد يكون لها أوجه تشابه من حيث ماذا وكيف يتم استخدامها.
افترض أنك تقوم بتطوير لعبة الورق أو لعب الأدوار وإنشاء
warrior
الطبقات (المحارب) ،
sorceress
(الساحرة)
archer
(القوس والنشاب). في مثل هذه الحالة ، يمكنك تحقيق مستوى عالٍ من دعم التعليمات البرمجية من خلال تنظيم الإجراءات كما يلي:
src/actions/warrior.js src/actions/sorceress.js src/actions/archer.js
سيكون الأمر أسوأ بكثير إذا وقع كل شيء في ملف واحد:
src/actions/classes.js
إذا أصبح التطبيق كبيرًا جدًا ، فقد يكون من الأفضل استخدام البنية التالية لتقسيم الشفرة إلى ملفات:
src/actions/warrior/skills.js src/actions/sorceress/skills.js src/actions/archer/skills.js
يظهر جزء صغير فقط من هذا الهيكل هنا. إذا كنت تعتقد أن هذا النهج يستخدم على نطاق واسع ومتسق ، فسينتهي بك الأمر إلى مجموعة مثل هذه الملفات:
src/actions/warrior/skills.js src/actions/warrior/quests.js src/actions/warrior/equipping.js src/actions/sorceress/skills.js src/actions/sorceress/quests.js src/actions/sorceress/equipping.js src/actions/archer/skills.js src/actions/archer/quests.js src/actions/archer/equipping.js
إليك ما قد يبدو عليه الإجراء من ملف
src/actions/sorceress/skills
الخاص بالكائن
sorceress
:
import { CAST_FIRE_TORNADO, CAST_LIGHTNING_BOLT } from '../constants/sorceress' export const castFireTornado = (target) => ({ type: CAST_FIRE_TORNADO, target, }) export const castLightningBolt = (target) => ({ type: CAST_LIGHTNING_BOLT, target, })
فيما يلي محتويات ملف
src/actions/sorceress/equipping
:
import * as consts from '../constants/sorceress' export const equipStaff = (staff, enhancements) => {...} export const removeStaff = (staff) => {...} export const upgradeStaff = (slot, enhancements) => { return (dispatch, getState, { api }) => {
السبب في قيامنا بتنظيم الكود بهذه الطريقة هو إضافة ميزات جديدة باستمرار إلى المشاريع. هذا يعني أننا نحتاج إلى الاستعداد لمظهرها وفي الوقت نفسه نسعى جاهدين لضمان عدم تحميل الملفات برمز.
في بداية العمل في المشروع ، قد يبدو هذا غير ضروري. ولكن كلما أصبح المشروع أكبر ، كلما كانت قوة مثل هذا النهج أقوى.
2. لا تضع رمز المخفض في مكان واحد
عندما أرى أن رمز مخفضاتي يتحول إلى شيء مشابه لذلك الموضح أدناه ، أدرك أنني بحاجة إلى تغيير شيء ما.
const equipmentReducers = (state, action) => { switch (action.type) { case consts.UPGRADING_STAFF: return { ...state, classes: { ...state.classes, sorceress: { ...state.classes.sorceress, equipment: { ...state.classes.sorceress.equipment, isUpgrading: action.slot, }, }, }, } case consts.UPGRADED_STAFF: return { ...state, classes: { ...state.classes, sorceress: { ...state.classes.sorceress, equipment: { ...state.classes.sorceress.equipment, isUpgrading: null, current: { ...state.classes.sorceress.equipment.current, [action.slot]: action.staff, }, }, }, }, } case consts.UPGRADE_STAFF_FAILED: return { ...state, classes: { ...state.classes, sorceress: { ...state.classes.sorceress, equipment: { ...state.classes.sorceress.equipment, isUpgrading: null, }, }, }, } default: return state } }
مثل هذا الرمز ، بلا شك ، يمكن أن يؤدي بسرعة كبيرة إلى الكثير من الفوضى. لذلك ، من الأفضل الحفاظ على بنية العمل مع الدولة بأبسط أشكالها الممكنة ، بهدف الحد الأدنى لمستوى تعشيشها. يمكنك ، بدلاً من ذلك ، محاولة اللجوء إلى تكوين المخفضات.
تتمثل إحدى الحيل المفيدة في العمل مع المخفضات في إنشاء مخفض ترتيب أعلى ينتجه المخفضون الآخرون. اقرأ المزيد عنها هنا.
3. استخدام أسماء المتغيرات بالمعلومات
تسمية المتغيرات ، للوهلة الأولى ، قد تبدو مهمة أساسية. ولكن في الواقع ، قد تكون هذه المهمة واحدة من أصعبها.
يرتبط اختيار أسماء المتغيرات بشكل عام بالمبادئ التوجيهية العملية لكتابة التعليمات البرمجية النظيفة. السبب وراء وجود شيء ما باسم "اسم متغير" بشكل عام هو أن هذا الجانب من تطوير الكود يلعب دورًا مهمًا جدًا في الممارسة. يعد الاختيار غير الناجح للأسماء المتغيرة طريقة مؤكدة لإيذاء نفسك وأعضاء فريقك في المستقبل.
هل سبق لك أن حاولت تعديل رمز شخص آخر وفي الوقت نفسه واجهت صعوبات في فهم ما يفعله هذا الرمز بالضبط؟ هل سبق لك تشغيل برنامج أجنبي ووجدت أنه لا يعمل كما هو متوقع؟
أود أن أقول لإثبات أنك واجهت في مثل هذه الحالات "الكود القذر".
إذا كان عليك التعامل مع كود مشابه في التطبيقات الكبيرة ، فهذا مجرد كابوس. لسوء الحظ ، هذا يحدث في كثير من الأحيان.
هنا حالة واحدة من الحياة. لقد قمت بتحرير رمز ربط React من تطبيق واحد وفي تلك اللحظة أرسلوا إلي مهمة. كان لتنفيذ في التطبيق القدرة على عرض معلومات إضافية حول الأطباء. يجب أن تظهر هذه المعلومات للمريض الذي ينقر على صورة الملف الشخصي للطبيب. كان من الضروري إخراجها من الجدول ، وكان عليها الوصول إلى العميل بعد معالجة الطلب التالي على الخادم.
لم تكن هذه مهمة صعبة ، فالمشكلة الرئيسية التي واجهتها هي أنني اضطررت لقضاء الكثير من الوقت في العثور على المكان الذي أحتاج إليه بالضبط في رمز المشروع.
لقد بحثت في الكود عن الكلمات
info
و
dataToSend
و
dataObject
، وللآخرين الذين ، في
dataObject
، يرتبطون بالبيانات الواردة من الخادم. بعد 5-10 دقائق ، تمكنت من العثور على الكود المسؤول عن التعامل مع البيانات التي أحتاجها. الكائن الذي انتهى بهم الأمر كان يسمى
paymentObject
. في رأيي ، قد يحتوي الكائن المرتبط بالدفعات على شيء مثل رمز CVV ورقم بطاقة الائتمان والرمز البريدي دافع ، وغيرها من المعلومات المماثلة. الكائن الذي اكتشفته به 11 خاصية. ثلاثة منهم فقط كانوا مرتبطين بالدفعات: طريقة الدفع ، معرف ملف تعريف الدفع وقائمة رموز الكوبون.
لم يتحسن الموقف لأنني اضطررت إلى إجراء تغييرات على هذا الكائن والتي كانت مطلوبة لحل المهمة التي أمامي.
باختصار ، يوصى بالامتناع عن استخدام أسماء غامضة للوظائف والمتغيرات. فيما يلي رمز مثال لا يكشف فيه اسم دالة
notify
عن معناه:
import React from 'react' class App extends React.Component { state = { data: null }
4. لا تقم بتغيير هياكل البيانات أو أنواعها في تدفقات بيانات التطبيق التي تم تكوينها بالفعل
أحد أكبر الأخطاء التي ارتكبتها على الإطلاق هو تغيير بنية البيانات في دفق بيانات تطبيق تم تكوينه بالفعل. ستحقق بنية البيانات الجديدة زيادة هائلة في الأداء ، حيث إنها تستخدم أساليب سريعة للبحث عن البيانات في الكائنات المخزنة في الذاكرة ، بدلاً من التكرار على المصفوفات. ولكن بعد فوات الأوان.
أنا أطلب منك عدم القيام بذلك. ربما لا يمكن توفير شيء مثل هذا إلا لشخص يعرف بالضبط أجزاء التطبيق التي يمكن أن يؤثر عليها.
ما هي عواقب هذه الخطوة؟ على سبيل المثال ، إذا كان هناك شيء ما كان صفيفًا أولاً ، ثم أصبح كائنًا ، فقد يؤدي ذلك إلى تعطيل تشغيل العديد من أجزاء التطبيق. لقد ارتكبت خطأً كبيرًا اعتقادي أنني تمكنت من تذكر جميع الأماكن الموجودة في الكود والتي يمكن أن تتأثر بتغيير في تقديم البيانات المنظمة. ومع ذلك ، في مثل هذه الحالات ، هناك دائمًا جزء من الكود يتأثر بالتغيير ولا يتذكره أحد.
5. استخدام القصاصات
اعتدت أن أكون من محبي محرر Atom ، لكني تحولت إلى رمز VS بسبب حقيقة أن هذا المحرر كان سريعًا بشكل لا يصدق مقارنةً بـ Atom. وهو ، بسرعته ، يدعم عددًا كبيرًا من الاحتمالات المختلفة.
إذا كنت تستخدم أيضًا VS Code ، فإنني أوصي بتثبيت
ملحق Project Snippets . يتيح هذا الملحق للمبرمج إنشاء قصاصات مخصصة لكل مساحة عمل مستخدمة في المشروع. يعمل هذا الامتداد بنفس طريقة استخدام آلية Snippets المدمجة في VS Code. الفرق هو أنه عند العمل مع Project Snippets ، يتم إنشاء المجلد
.vscode/snippets/
في المشروع. يبدو أن الشكل التالي.
محتويات .vscode / snippets / folder6. إنشاء اختبارات الوحدة ، نهاية إلى نهاية والتكامل
مع زيادة حجم التطبيق ، يصبح الأمر مخيفًا بالنسبة للمبرمج لتحرير التعليمات البرمجية التي لا تغطيها الاختبارات. على سبيل المثال ، قد يحدث أن قام شخص ما بتحرير الكود المخزن في
src/x/y/z/
وقرر إرساله إلى الإنتاج. إذا كانت التغييرات التي تم إجراؤها في الوقت نفسه تؤثر على تلك الأجزاء من المشروع التي لم يفكر فيها المبرمج ، فقد ينتهي كل شيء بخطأ سيواجهه مستخدم حقيقي. إذا كانت هناك اختبارات في المشروع ، فسوف يعرف المبرمج الخطأ قبل وقت طويل من بدء تشغيل الكود.
7. العصف الذهني
المبرمجين ، في عملية إدخال ميزات جديدة في المشاريع ، غالباً ما يرفضون طرح الأفكار. يحدث هذا لأن مثل هذا النشاط لا يرتبط بكود الكتابة. يحدث هذا غالبًا عند تخصيص وقت قليل جدًا للمهمة.
ولماذا ، بالمناسبة ، هل لديك لتبادل الأفكار أثناء تطوير التطبيقات؟
الحقيقة هي أنه كلما زاد تعقيد التطبيق ، زاد اهتمام المبرمجين بأجزائه الفردية. العصف الذهني يساعد على تقليل الوقت الذي يستغرقه رد الفعل refactor code. بعد احتجازهم ، يتم تسليح المبرمج بمعرفة الأخطاء التي قد تحدث أثناء إتمام المشروع. في كثير من الأحيان ، لا يكلف المبرمجون ، أثناء تطوير التطبيق ، عن التفكير قليلاً حول كيفية القيام بكل شيء بأفضل طريقة.
هذا هو السبب في العصف الذهني مهم جدا. خلال مثل هذا الحدث ، يمكن للمبرمج النظر في بنية الكود ، والتفكير في كيفية إجراء التغييرات اللازمة للبرنامج ، وتتبع دورة حياة هذه التغييرات ، ووضع استراتيجية للعمل معهم. لا يستحق الأمر جعله معتادًا على الاحتفاظ بجميع الخطط في يدك. هذا هو ما يفعله المبرمجون الذين لديهم ثقة مفرطة. لكن تذكر كل شيء على الإطلاق أمر مستحيل. وبمجرد حدوث خطأ ما ، ستظهر المشكلات واحدة تلو الأخرى. هذا هو مبدأ الدومينو في العمل.
العصف الذهني مفيد أيضا في الفرق. على سبيل المثال ، إذا واجه شخص ما مشكلة أثناء العمل ، فقد يلجأ إلى مواد جلسة العصف الذهني ، لأن المشكلة التي نشأت من أجله كان من الممكن أن يتم النظر فيها بالفعل. قد تؤدي الملاحظات التي يتم إجراؤها أثناء جلسة العصف الذهني دور خطة لحل المشكلة. تتيح لك هذه الخطة تقييم حجم العمل المنجز بوضوح.
8. إنشاء نماذج بالحجم الطبيعي التطبيق
إذا كنت ستبدأ في تطوير التطبيق ، فأنت بحاجة إلى اتخاذ قرار بشأن كيفية ظهوره وكيف سيتفاعل المستخدمون معه. هذا يعني أنك ستحتاج إلى إنشاء تخطيط تطبيق. يمكنك استخدام أدوات مختلفة لهذا الغرض.
Moqups هي إحدى أدوات
نموذج بالحجم الطبيعي التي أسمع عنها غالبًا. هذه أداة سريعة تم إنشاؤها باستخدام HTML5 و JavaScript ولا تفرض متطلبات خاصة على النظام.
إنشاء تطبيق وهمي يبسط ويسرع عملية التطوير إلى حد كبير. يوفر التخطيط لمطور المعلومات حول العلاقة بين الأجزاء الفردية للتطبيق ، ونوع البيانات التي سيتم عرضها على صفحاته.
9. خطة تدفق البيانات في التطبيقات
سيتم ربط كل مكون من عناصر التطبيق تقريبًا ببعض البيانات. ستستخدم بعض المكونات مصادر البيانات الخاصة بها ، لكن معظم المكونات تتلقى البيانات من الكيانات الموجودة أعلىها في التسلسل الهرمي للمكون. بالنسبة إلى أجزاء التطبيق التي يتم فيها مشاركة نفس البيانات بواسطة عدة مكونات ، من المفيد توفير بعض تخزين المعلومات المركزي الموجود في المستوى الأعلى من التسلسل الهرمي. في مثل هذه الحالات ، يمكن لمكتبة
Redux تقديم مساعدة لا تقدر بثمن للمطور.
أوصي أنه أثناء العمل على التطبيق ، ارسم مخططًا يوضح الطرق التي تنتقل بها البيانات في هذا التطبيق. هذا سوف يساعد في إنشاء نموذج تطبيق واضح ، علاوة على ذلك ، نحن نتحدث عن الكود وتصور التطبيق من قبل المبرمج. مثل هذا النموذج سوف يساعد ، بالإضافة إلى ذلك ، في إنشاء المخفضات.
10. استخدام ميزات الوصول إلى البيانات
كلما زاد حجم التطبيق ، زاد عدد مكوناته. وعندما ينمو عدد المكونات ، يحدث نفس الشيء مع تكرار استخدام المحددات (react-redux ^ v7.1) أو
mapStateToProps
. افترض أنك تجد أن المكونات أو السنانير الخاصة بك غالبًا ما تصل إلى أجزاء الحالة في أجزاء مختلفة من التطبيق باستخدام بنية مثل
useSelector((state) => state.app.user.profile.demographics.languages.main)
. إذا كان الأمر كذلك ، فهذا يعني أنك بحاجة إلى التفكير في إنشاء وظائف الوصول إلى البيانات. يجب تخزين الملفات التي تحتوي على هذه الوظائف في مكان عام يمكن للمكونات والسنانير استيرادها منها. وظائف مماثلة يمكن أن تكون المرشحات ، المحللون ، أو أي وظائف أخرى لتحويل البيانات.
وهنا بعض الأمثلة.
على سبيل المثال ، قد تحتوي
src/accessors
على الكود التالي:
export const getMainLanguages = (state) => state.app.user.profile.demographics.languages.main
في ما يلي الإصدار الذي يستخدم
connect
، والذي يمكن تحديد موقعه على طول مسار
src/components/ViewUserLanguages
:
import React from 'react' import { connect } from 'react-redux' import { getMainLanguages } from '../accessors' const ViewUserLanguages = ({ mainLanguages }) => ( <div> <h1>Good Morning.</h1> <small>Here are your main languages:</small> <hr /> {mainLanguages.map((lang) => ( <div>{lang}</div> ))} </div> ) export default connect((state) => ({ mainLanguages: getMainLanguages(state), }))(ViewUserLanguages)
هنا هو الإصدار الذي يستخدم
useSelector
الموجود في
src/components/ViewUserLanguages
:
import React from 'react' import { useSelector } from 'react-redux' import { getMainLanguages } from '../accessors' const ViewUserLanguages = ({ mainLanguages }) => { const mainLanguages = useSelector(getMainLanguages) return ( <div> <h1>Good Morning.</h1> <small>Here are your main languages:</small> <hr /> {mainLanguages.map((lang) => ( <div>{lang}</div> ))} </div> ) } export default ViewUserLanguages
بالإضافة إلى ذلك ، نسعى جاهدين لضمان أن تكون هذه الوظائف ثابتة ، خالية من الآثار الجانبية. اكتشف لماذا أقدم هذه التوصية
هنا .
11. التحكم في تدفق البيانات في الخصائص باستخدام بناء الجملة ونشرها
ما هي فوائد استخدام
props.something
something
بناء على
something
بناء؟
إليك ما يبدو عليه دون استخدام التدمير:
const Display = (props) => <div>{props.something}</div>
هنا هو نفسه ، ولكن مع استخدام التدمير:
const Display = ({ something }) => <div>{something}</div>
استخدام التدمير يحسن قراءة الكود. لكن هذا لا يحد من تأثيره الإيجابي على المشروع. باستخدام التدمير ، يضطر المبرمج إلى اتخاذ قرارات بشأن ما يحصل عليه المكون بالضبط وما الذي يخرجه بالضبط. يحفظ هذا أي شخص يتعين عليه تعديل رمز شخص آخر من الاضطرار إلى النظر في كل سطر من طريقة
render
بحثًا عن جميع الخصائص التي يستخدمها المكون.
بالإضافة إلى ذلك ، يوفر هذا الأسلوب فرصة مفيدة لتعيين قيم الخصائص الافتراضية. يتم ذلك في بداية رمز المكون ويزيل الحاجة إلى كتابة رمز إضافي في نص المكون:
const Display = ({ something = 'apple' }) => <div>{something}</div>
ربما تكون قد رأيت شيئًا مثل المثال التالي من قبل:
const Display = (props) => ( <Agenda {...props}> {' '} // Agenda <h2><font color="#3AC1EF">Today is {props.date}</font></h2> <hr /> <div> <h3><font color="#3AC1EF">▍Here your list of todos:</font></h3> {props.children} </div> </Agenda> )
هذه الإنشاءات ليست سهلة القراءة ، لكن هذه ليست مشكلتهم الوحيدة. لذلك ، هناك خطأ. إذا كان التطبيق يعرض أيضًا مكونات
props.children
،
props.children
عرض
props.children
على الشاشة مرتين. إذا تم تنفيذ العمل في مشروع ما في فريق ولم يكن أعضاء الفريق حريصين بما فيه الكفاية ، فإن احتمال حدوث مثل هذه الأخطاء كبير جدًا.
إذا قمت بتدمير الخصائص بدلاً من ذلك ، فسيكون رمز المكون أكثر وضوحًا ، وستقل احتمالية حدوث الأخطاء:
const Display = ({ children, date, ...props }) => ( <Agenda {...props}> {' '} // Agenda <h2><font color="#3AC1EF">Today is {date}</font></h2> <hr /> <div> <h3><font color="#3AC1EF">▍Here your list of todos:</font></h3> {children} </div> </Agenda> )
النتائج
في هذه المقالة ، قمنا بمراجعة 12 توصية لأولئك الذين يقومون بتطوير تطبيقات React باستخدام Redux. نأمل أن تجد شيئًا مفيدًا لك هنا.
أعزائي القراء! ما هي النصائح التي تضيفها إلى تلك الموجودة في هذه المقالة؟

