عادات برمجية فعالة: كيف تضمن نجاحك المستقبلي كمطور؟

دقائق القراءة: 12
فكر مليًا قبل أن تكتب أي سطر من الكود. أنت تمتلك القدرة على جعل حياتك المستقبلية كمطور إما سهلة ومثمرة، أو معقدة ومحبطة. في هذا المقال، سنستكشف مجموعة من الممارسات التي يمكنك اتباعها لتيسير مهامك المستقبلية وتجنب المتاعب.

مراجعة الأعمال السابقة: دروس من الماضي

لقد مررنا جميعًا بهذا الموقف. بعد ستة أشهر من بدء مشروع ما، تحاول إصلاح خطأ برمجي، وما تكتشفه يكون صادمًا. قد تسأل نفسك، “من كتب هذا النوع من الكود؟” فتبدأ في البحث في سجل التغييرات الخاص بك باستخدام الأمر git log -p filename.js (الذي يعرض التغييرات لملف معين)، محاولًا معرفة من يمكن أن يكون قد أتى بهذا الكود. ثم تنزل الصدمة عليك – أنت من كتبه!
مطور يصاب بالصدمة عند اكتشاف كود قديم كتبه بنفسه
هذا سيناريو شائع لأي مطور، سواء كان ذا خبرة أو مبتدئًا. إذا لم تكن قد مررت بهذا الموقف بعد، فأنا أعدك بأنك ستمر به حتمًا إذا واصلت العمل في مجال البرمجة لفترة كافية.

تنمية الوعي بعادات البرمجة لدينا

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

تحسين قابلية قراءة الكود الخاص بك

ما هو التحدي؟

جزء من متعة حرفتنا هو وجود العديد من الطرق التي يمكنك من خلالها إنجاز نفس الشيء. هل تعتقد أن عبارة if statement تتطلب الكثير من الأسطر؟ حسنًا، يمكننا كتابتها بأسلوب التعبير الشرطي الثلاثي (ternary style)!

 // Example ternary statement
 const isFreezing = temperature <= 32 ? true : false ;

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

 const minutes = 30 ;
 const cookie = { color : 'black' };
 const cookieStatus = minutes > 20 ? cookie.color === 'black' ? 'burned' : 'done' : 'not done' ;

ما الذي يمكننا فعله بشكل أفضل؟

الآن، أتخيل أن معظمنا يمكنه معرفة ما هو المتغير cookieStatus في هذا المثال (تلميح: burned). لكن فكر في الوقت الذي قضيته في معرفة ذلك. سواء كان ثانية أو اثنتين إضافيتين، فإنه يجبرك على إنفاق طاقة معرفية إضافية لقراءة الكود. من ناحية أخرى، انظر إلى هذا المثال:

 const minutes = 30 ;
 const cookie = { color : 'black' };
 let cookieStatus;
 if ( minutes <= 20 ) {
 cookieStatus = 'not done' ;
 } else if ( cookie.color === 'black' ) {
 cookieStatus = 'burned' ;
 } else {
 cookieStatus = 'done' ;
 }

لا، قد لا يكون هذا الكود بنفس النظافة أو الذكاء الذي يتمتع به التعبير الشرطي الثلاثي ذو السطر الواحد، ولكن في المرة القادمة التي تعود فيها إليه، ستقل الحاجة إلى التفكير في الإجابة. كما أنه سيجعل من السهل جدًا على الأخطاء أن تتسلل وتتجاوز مراجعي الكود الخاص بك عندما تكون جميع تغييرات الكود الخاص بك في فرق git diff من سطر واحد. ونعم، هذا مثال بسيط. ولكن تخيل هذا في سيناريو واقعي مع منطق عمل مهم حيث يمكنك مواجهة هذه المواقف بشكل متكرر. لنفترض أنك بحاجة إلى إضافة شرط آخر – سيستمر هذا التعبير الشرطي الثلاثي في أن يصبح أكثر تعقيدًا! أنت بذلك تجعل عملية التصحيح أو التوسيع أكثر صعوبة، حيث يمكن لعبارات if statements أن تستمر بطريقة سهلة القراءة. على الرغم من أن التعبيرات الشرطية الثلاثية والاختصارات الأخرى يمكن أن تكون بسيطة وفعالة في الكود، فلا تفرط في استخدام هذه الفعالية وتجعل الأمور أكثر صعوبة.

الحفاظ على اتساق الكود

ما هو التحدي؟

لدينا جميعًا طريقتنا المفضلة في البرمجة. على الرغم من أنني سأجادل بأن عدم تضمين فاصلة منقوطة في نهاية كود JavaScript الخاص بك هو خطأ تمامًا، فقد تفضل أنت كتابة الكود الخاص بك بالطريقة “الخاطئة” بدونها.

 // Jim's code style
 function MyComponent ( ) {
 function handleOnClick ( ) {
 alert( 'Click!' )
 }
 return (
 < button onClick = {handleOnClick} > My Button </ button >
 )
 }
 // Creed's code style
 const MyComponent = () => < button onClick = {() => alert('Click!')}>My Button </ button > ;

لكن الأمر لا يتعلق دائمًا بما تفضله أنت. عند العمل مع فريق، من المحتمل أن يكون رأي كل شخص حول كيفية ظهور الكود مختلفًا قليلًا. قد تتفق على الفاصلة المنقوطة، لكن تختلف حول المسافات البيضاء (whitespace). ولا أحد مخطئ (باستثناء من لا يستخدمون الفواصل المنقوطة)! هناك حجج صحيحة لمعظم أنماط الكود، سواء كانت مؤيدة أو معارضة، ولكن الحل ليس أن يكتب كل شخص الكود الخاص به بطريقته الخاصة.

ما الذي يمكننا فعله بشكل أفضل؟

يعد الحفاظ على اتساق الكود أمرًا مهمًا للحفاظ على صحة الكود. الهدف النموذجي هو “جعل قاعدة الكود تبدو وكأن شخصًا واحدًا كتبها”. النقطة ليست أن شخصًا واحدًا يحصل على ما يريد، بل أن الفريق توصل إلى استنتاج بشأن مجموعة من القواعد التي سيستخدمونها والتي سيتبعها الجميع. يوفر هذا الاتساق عبئًا معرفيًا أقل حيث يعمل الأشخاص من خلال الكود. يمنح الجميع القدرة على معرفة ما يمكن توقعه عند قراءة الكود.
أخطاء ناتجة عن فحص الكود (linting)
وليس من الضروري أن يكون تحقيق ذلك صعبًا. هناك أدوات يمكنها ببساطة التحقق من هذه التناقضات مثل Eslint لـ Javascript. والأفضل من ذلك، هناك مستوى آخر من الأدوات مثل Prettier التي ستقوم بإصلاحها لك!

التعليقات البرمجية: إضاءة على منطق الكود

ما هو التحدي؟

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

ما الذي يمكننا فعله بشكل أفضل؟

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

 // DONT CHANGE - WILL STOP MAKING MONEY
 const shouldMakeMoney = true ;
 function makeMoney ( ) {
 if ( shouldMakeMoney ) {
 return noMoney;
 }
 return moreMoney;
 }

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

توثيق الحلول البرمجية

ما هو التحدي؟

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

ما الذي يمكننا فعله بشكل أفضل؟

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

 /**
 * DOCUMENTATION
 * Order Total >= 25: Discount %10
 * Order Total >= 50: Discount %15
 * Order Total >= 100: Discount %20
 * Order Total >= 75: Free Shipping
 */
 const orderSubTotal = 84.00 ;
 let orderTotal = orderSubTotal;
 // If the order total is under 75, apply shipping discount
 if ( orderTotal < 75 ) {
 orderTotal = addShipping(orderTotal);
 }
 // If the order total reaches a threshold, apply given discount
 if ( orderTotal >= 100 ) {
 orderTotal = applyDiscount(orderTotal, .2 );
 } else if ( orderTotal >= 50 ) {
 orderTotal = applyDiscount(orderTotal, .15 );
 } else if ( orderTotal >= 25 ) {
 orderTotal = applyDiscount(orderTotal, .1 );
 }

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

إنشاء طلبات سحب (Pull Requests) فعالة

ما هو التحدي؟

تعد طلبات السحب (Pull Requests أو Merge Requests) جزءًا أساسيًا من دورة حياة أي مشروع فريق تطوير. إنها توفر طريقة لتعبئة وتقديم الكود الخاص بك بطريقة قابلة للاستهلاك ليقوم زملاؤك بمراجعتها وفهم عملك. هناك الكثير الذي يمكن أن يتضمنه طلب السحب، من التزام واحد (single commit) إلى مجمل الإصدار التالي لموقع الويب الخاص بك. هذا قدر كبير من السياق لتتوقع من شخص ما فهمه بمجرد قراءة الالتزامات (commits) وحدها.

ما الذي يمكننا فعله بشكل أفضل؟

لا يجب أن تكون طلبات السحب فنًا. يجب أن يكون هناك هدف أساسي واحد للتحضير الذي تضعه فيها – توفير سياق لتغييراتك. كحد أدنى، يجب أن تجيب على أسئلة “ماذا” و “لماذا”. يمكننا حتى استخدام أدوات مثل قوالب طلبات السحب (pull request templates) لدفعنا في الاتجاه الصحيح. حدد مخططًا لما تريد شرحه ومن المحتمل أن يتبع الناس هذا المخطط. يساعد هذا في تجنب الوصف المكون من سطر واحد “يغلق [التذكرة]” أو ما هو أسوأ، وصف فارغ. في مشاريعي، آمل أن يتم الإجابة على بعض الأسئلة قبل أن أتعمق في مراجعة الكود:

  • ما هو التغيير؟
  • ماذا يؤثر؟
  • كيف يمكنني إعادة إنتاج أو اختبار التغيير؟

يمكن لبعض التفاصيل حول مجموعة التغييرات أن توفر سياقًا ضروريًا للغاية لأولئك الذين يراجعون الكود الخاص بك. من السهل النظر إلى الكود، ولكن من الصعب فهمه دون معرفة كيفية تناسبه مع الصورة الأكبر.

تحصين الكود الخاص بك بالاختبارات

ما هو التحدي؟

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

ما الذي يمكننا فعله بشكل أفضل؟

حيث أن التعليقات هي طريقة لتوفير سياق لكيفية عمل شيء ما، فإن الاختبارات هي طريقة لضمان أنها تعمل. توفير حالات اختبار قابلة للتكرار يساعد في فرض ذلك.

 function applyDiscount ( value, discount ) {
 const discountAmount = value * discount;
 return value - discountAmount;
 }
 expect(applyDiscount( 10 , .1 )).toEqual( .9 );
 expect(applyDiscount( 532151235 , .1054 )).toEqual( 476062494.831 );

إذا أخطأت في حسابات دالة applyDiscount أعلاه، فهناك احتمال كبير أن يفشل الاختبار (لا تقل أبدًا “لا يمكن أن يحدث”). لكن الاختبار لا يجب أن يكون صعبًا. هناك العديد من الأدوات المتاحة التي تساعد من وجهات نظر مختلفة. على سبيل المثال، قد تستخدم Jest لتشغيل اختبارات الوحدات (unit tests) الخاصة بك أو إضافة Enzyme فوقها لاختبار مكونات React الخاصة بك. ولكن يمكنك أيضًا إحضار Cypress كحل لاختبار التكامل (integration test) الذي سيعمل كروبوت ينقر عبر تطبيقك للتأكد من أن جميع المكونات تعمل معًا بالفعل. هناك أيضًا منهجيات مختلفة للاختبار. بينما ترى على الأرجح معظم الفرق تكتب اختباراتها بعد أن يكون لديها حل عملي، يقسم بعض الناس بـ “التطوير الموجه بالاختبارات” (test-driven development). قد يكتبون اختباراتهم أولاً حيث يجب أن يجتاز الكود الاختبارات بدلاً من العكس. هذه طريقة رائعة لتحديد متطلبات الكود قبل الغوص فيه مباشرة. مهما كانت الطريقة، التقط النقاط الأكثر عرضة للكسر أو الوظائف التي تضيف أكبر قيمة تجارية. ستساعد في منع خسارة تجارية محتملة أو ببساطة، صداعًا.

الدروس المستفادة من هذه الممارسات

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

الخلاصة التقنية

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

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *