اشتباهاتی که به عنوان یک برنامه‌نویسِ مبتدی مرتکب شدم

نویسنده : سید ایوب کوکبی ۲۰ مرداد ۱۳۹۸
اشتباهاتی که به عنوان یک برنامه‌نویسِ مبتدی مرتکب شدم

اولین برنامه‌ام را سالِ دوم دبیرستان (۱۹۹۴) فروختم؛ زمانی که از ویندوز ۳٫۱۱ و نسخه‌های ابتدایی کورل دراو و دلفی استفاده می‌کردم. اولین اپلیکیشن single-page ام را سال ۲۰۰۲ ساختم؛ زمانی که هنوز خبری از جی‌کوئری نبود.

پس حسابی با یک برنامه‌نویس پیر طرفید! برنامه‌نویسی که به اندازۀ کافی فرصتِ اشتباه و سروکله زدن با انواع و اقسام زبان‌ها، کتابخانه و فریم‌ورک‌ها داشته است. من تقریباً انواعِ روش‌های کدنویسی را تست کرده‌ام و افتخار حضور در انواعِ پروژه‌های کوچک و بزرگ را داشته‌ام. با تیم‌های زیادی کار کرده‌ام. برای فرانت‌اند کد نوشته‌ام، برای بک‌اند کد نوشته‌ام و با دیتابیس‌های متعدد کار کرده‌ام.

برنامه‌نویسی را به صورت خودآموز یادگرفتم. در دانشگاه چند کورس آموزشی شرکت کردم؛ ولی بعید می‌دانم این دوره‌ها تأثیری در پیشرفت‌های من داشته باشد. برنامه‌نویسی را فقط با ساختن پروژه‌های واقعی می‌توانید بیاموزید نه سر کلاس‌هایِ درس.

راه رفتن را با قاعده و قانون یاد نمی‌گیرید؛ بلکه با انجام دادن و افتادن می‌آموزید.

Richard Branson

در این مقاله می‌خواهم شما را با اشتباهاتِ دوران جوانی‌ام زمانی که هنوز یک برنامه‌نویس مبتدی و کارنابلد بودم آشنا کنم. چیزهایی که در ادامه می‌خوانید ثمرۀ چندین سال تجربه و شکستِ واقعی بوده؛ بنابراین با دقت کافی بخوانید و سعی کنید از تکرار این اشتباهات جلوگیری کنید. احتمالاً در حین خواندن تعدادی از این اشتباهات را در خودتان خواهید یافت. نگران نباشید؛ فقط شما نیستید؛ بسیاری از برنامه‌نویس‌های دیگر نیز به این خطاها مبتلا هستند. مهم این است که چگونه این خطاها را به عادت تبدیل نکنید.

گفتنی است اشتباهاتِ بیان شده در همۀ افرادِ مبتدی وجود ندارد و هیچ کس همۀ آن‌ها را با هم ندارد. ضمناً ترتیب خاصی برای بیانِ اشتباهات لحاظ نکرده‌ام.

کدنویسی بدونِ برنامه

تولیدِ یک محتوای باکیفیت کار ساده‌ای نیست. این کار نیازمندِ تفکر و پژوهش است. ساخت نرم‌افزار نیز از این قاعده مستثنی نیست.

برای مثال برای نوشتن این مقاله کارهای زیر انجام شده است:

  • چند ساعت برای تأمل در موضوع مقاله و نکاتی که باید بدانها اشاره کنم؛ در این مرحله هر نکته را به صورت خلاصه در چند سطر نوشتم؛
  • چند روز برای فکر کردن در مورد موضوعاتی که ممکن است به صورت اتفاقی از قلم انداخته باشم؛
  • چند ساعت برای مطالعه کتابها و مقالات برای اطمینان از اینکه نکته‌ای را فراموش نکرده باشم؛
  • یک ساعت برای مرتب‌سازی نکات جمع‌آوری شده و دسته‌بندی آنها؛
  • یک ساعت برای بیان افکار خودم در مورد نکاتِ جمع‌آوری شده؛
  • ارسال مقاله به برنامه‌نویسان به منظور دریافت بازخورد و اصلاحاتِ احتمالی. بازخوردها هم شامل مواردی بود که از قلم انداخته بودم و هم مواردِ فنیِ اشتباه را شامل می‌شد.

همانطور که می‌بینید، نوشتن، ساده‌ترین بخش یک مقاله است. بخشِ عمدۀ زمان، صرف پژوهش، بازخوانی و ویرایش مقاله می‌شود. نوشتن یک برنامۀ باکیفیت نیز به پروسۀ مشابهی نیاز دارد یعنی: تفکر، پژوهش، برنامه‌ریزی، نوشتن، اعتبارسنجی و اصلاح. طوری خود را عادت دهید که این مراحل در زندگیِ شما به یک روالِ عادی تبدیل شود.

اشتباهِ بسیاری از برنامه‌نویسان مبتدی این است که بدون تحقیق در مورد اینکه می‌خواهند چه بسازند شروع می‌کنند به کدنویسی. این کار شاید برای پروژه‌های کوچک جواب بدهد ولی در برنامه‌های بزرگ به یک معضلِ تبدیل خواهد شد.

معمولاً پیش از حرف زدن کمی فکر می‌کنید تا احیاناً چیز اشتباهی نگویید که موجبِ پشیمانیِ شما شود. کدنویسی هم دقیقاً همین شکلی است؛ یعنی قبل از اینکه چیزی بنویسید باید خوب دربارۀ آن فکر کنید.

هنگامِ عصبانیت پیش از سخن گفتن از ۱ تا ۱۰ بشمارید. اگر خیلی عصبانی بودید تا ۱۰۰ بشمارید.

توماس جفرسون

توصیۀ جفرسون برای کدنویسی هم کاربرد دارد:

هنگامِ کدنویسی پیش از ریفکتور تا ۱۰ بشمارید. اگر کد بدون تست بود تا ۱۰۰ بشمارید.

سامِر بونا

برنامه‌نویسی یعنی پژوهش در موردِ قابلیت‌هاییِ مورد نیازِ برنامه و برنامه‌ریزیِ درست برای پیاده‌سازیِ تدریجیِ این قابلیت‌ها. برنامه‌نویسی صرفاً کدنویسی نیست. کدنویسی تنها ۱۰% این مراحل است. برنامه‌نویسی یک فعالیت شدیداً منطقی و فکری است که نیازمند بازپروری است.

افراط و تفریط در برنامه‌ریزی

برنامه‌ریزی چیزِ خوبی است ولی زیاده‌روی در آن آسیب‌زا است؛ حتی نوشیدن زیادِ آبِ سالم نیز می‌تواند به عارضه‌ای تحتِ عنوانِ «مسمومیت آبی» منجر شود.

هیچگاه دنبالِ یک برنامه‌ریزی کامل و ایده‌آل نباشید. چنین برنامه‌ای در هیچ جای دنیای برنامه‌نویسی وجود ندارد. یک برنامۀ خوب تدوین کنید ولی بیش از حد روی آن وقت تلف نکنید. واقعیت این است که هیچ برنامه‌ای تا آخر بدون تغییر نمی‌ماند؛ پس در مرحلۀ برنامه‌ریزی وسواس به خرج ندهید.

منظورِ من از برنامه‌ریزی، برنامه‌ریزی برای ساختِ یک فیچر کوچک است. برنامه‌ریزیِ برای همۀ فیچرها کارِ درست و عاقلانه‌ای نیست. نتیجۀ این کار همان بلایی را سرِ شما می‌آورد که روشِ آبشاری بر سرِ شرکت‌های بزرگِ نرم‌افزاری آورد. در حال حاضر شیوه‌های جدیدی مثل توسعۀ چابک (Agile) رونق گرفته که در چرخه‌های کوتاه و به صورت افزایشی فیچرها را پیاده‌سازی و تحویلِ مشتری می‌دهد.

برنامه‌نویسی فعالیتی مداوم و تدریجی است. در روشِ آبشاری همه چیز در یک مسیر خطی از مرحلۀ نیاز تا پیاده‌سازی و تحویل تعریف شده و هیچ انعطافی در دلِ آن وجود ندارد. در روشِ آبشاری بعد از اتمامِ هر فاز، دیگر به راحتی نمی‌توان به فازِ قبلی بازگشت. یعنی اگر در فازِ توزیعِ محصول قابلیتی به ذهنتان رسید دیگر به راحتیِ اجایل نمی‌توانید به مرحلۀ پیاده‌سازی برگردید و تغییرات مورد نظر را اعمال کنید.

اما در روش اجایل چرخۀ توسعه کوتاه و سریع است. شما هر زمان می‌توانید ویژگی‌های مورد نظر را پیاده‌سازی یا بروزرسانی کنید. در این روش مشتری در مرکزِ توجه قرار گرفته و با پروژۀ شما درگیر است. بنابراین توصیه می‌کنیم شما هم در برنامه‌ریزی خود اجایل شوید و شیوۀ سنتی را کنار بگذارید.

البته تفریط در برنامه‌ریزی هم صحیح نیست. قابلیتی که برایش برنامه‌ریزی می‌کنید خیلی نباید کوچک باشد. در چنین مواقعی چند فیچر کوچک را با هم برنامه‌ریزی کنید. تفریط در برنامه‌ریزی به اندازۀ افراط در آن آسیب‌زا است. اعتدال در پیش گرفته و همواره خطِ قرمزِ شما کیفیتِ کد باشد. روی کیفیتِ کد ریسک نکنید. برنامه‌ریزی‌ای که باعثِ پایین آمدن کیفیت کد شود برنامۀ درستی نیست.

سهل‌انگاری در کیفیتِ کد

در کدنویسی، خواناییِ کد بیش از هر چیزی اهمیت دارد. کدِ ناخوانا مثلِ یک زبالۀ غیر قابلِ بازیافت است. هیچگاه در این موضوع سهل‌انگاری نکنید. کدنویسی را به مثابه راهی برای ارتباط با دیگران ببینید. زبانِ مشترکِ شما کدهایی است که می‌نویسید؛ پس سعی کنید واضح حرف بزنید!

یکی از نقل‌قول‌هایِ موردعلاقۀ من در برنامه‌نویسی:

همیشه طوری کد بنویسید که انگار کسی که کدِ شما را نگه‌داری می‌کند بیماری روانی است که از محلِ زندگیِ شما باخبر است.

John Woods

حتی کوچک‌ترین چیزها هم مهم است. تورفتگی‌ها را رعایت کنید. تکلیفتان را با حروفِ کوچک و بزرگ روشن کنید. با یک الگوی مشابه نام‌گذاری کنید. طول هر خط از کد نباید از ۸۰ کاراکتر تجاوز کند چون باعثِ سخت شدن خواناییِ کد خواهد شد. حلقه‌ها و دستوراتِ شرطی اگر طولانی هستند به چند خط بشکنید تا به صورت یکجا دیده شود. تحت هیچ شرایطی از ۸۰ کاراکتر آن طرف‌تر نروید. برای حلِ بسیاری از این مشکلات به راحتی می‌توانید از ابزارهای کمکی که همراهِ IDE ها وجود دارند استفاده کنید.

سایر مشکلاتِ رایجِ در ارتباط با کیفیتِ کد:

توابع و فایل‌هایِ چاق
این قاعده را به خاطر بسپارید: هر تابعی باید یک کار انجام دهد. هیچگاه چند وظیفه را بر دوشِ یک تابع قرار ندهید. این کار اندازۀ تابع را بزرگ کرده و باعثِ کاهشِ خوانایی و تست‌پذیریِ آن می‌شود.

تابعی با بیش از ۱۰ خط کد طولانی است.

استفاده از نام‌های کوتاه و عمومی
نامِ متغیرها باید خودتوصیف و خالی از ابهام باشد.

دو چیز در کامپیوتر سخت است: نام‌گذاری و سروکله زدن با کَش.

Phil Karlton

هارد کد (Hard Code) رشته‌ها و اعداد بدون ذکرِ توضیح.
به جای استفادۀ مستقیم از اعداد و رشته‌ها بهتر است آن‌ها را در متغیری با نامِ مناسب ذخیره کرده و در متنِ کد به آن متغیرها رفرنس دهید. اینطوری هم از یک مکانِ مرکزی به همۀ رشته‌ها دسترسی دارید و هم کسی که کد را می‌خواند راحت متوجۀ منطقِ آن می‌شود مثلاً:

const apiKey="ewrew454sdf6e";

اعتقاد به اینکه کدِ بلند بهتر است
اتفاقاً هرچه کد کوتاه‌تر باشد بهتر است. تنها زمانی کدِ طولانی بنویسید که به خوانایی آن کمک کند. برای مثال از شرط‌های سه بخشی (ternary expressions) که if-else را در یک خط خلاصه می‌کنند استفاده نکنید. این کدها گرچه ظاهرِ هوشمندانه‌تری دارند ولی در عمل خوانایی کد را کاهش می‌دهند.
بعلاوه کدها را در جایی که لازم نیست عمداً طولانی نکنید. هیچگاه سعی نکنید با انجام این کارها هوشمندیِ خود را به دیگران اثبات کنید. وقتی شما کد یک توسعه‌دهندۀ دیگر را می‌خوانید آیا از روی سختیِ کدش به او امتیاز می‌دهید یا به خاطر ساده نوشتن او را تحسین می‌کنید؟ قطعاً سادگی کد ارزشش بالاتر است. پس شما هم روی ساده نوشتن کد تمرکز کنید. من تضمین می‌کنم کسی به شما نگوید خنگ!

ارزیابی پیشرفتِ برنامه از طریق شمردن تعداد خطوطِ آن همانند ارزیابی پیشرفتِ ساخت هواپیما از طریق وزن کردن آن است.

بیل گیتس

استفادۀ نابه‌جا و بیش از حد از دستورات شرطی
گاهی چند شرط را می‌توان با یک دستور شرطی انجام داد. گاهی دستورات شرطی تکراری هستند و گاهی اصلاً ضرورتی به استفاده از آن‌ها نیست.

انتخابِ اولین راهکار

این یکی از نشانه‌های مبتدی بودن برنامه‌نویس‌هاست. آن‌ها با مسئله‌ای برخورد می‌کنند، راه‌حلی می‌یابند و فوراً پیاده‌سازی‌اش می‌کنند؛ یعنی بدونِ تأمل دربارۀ مشکلات بالقوه و سطحِ پیچیدگیِ راه‌حل فوراً به پیاده‌سازی حمله‌ور می‌شوند.

اگرچه اولین راه‌حل وسوسه‌انگیز است ولی بهترین راه‌حل زمانی پیدا می‌شود که تمام راهکارهای موجود را بررسی کنید. اگر برای حل یک مسئله نمی‌توانید به بیش از یک راه‌حل فکر کنید نشانگر آن است که مسئله را به صورت کامل درک نکرده‌اید.

شغل شما به عنوان یک توسعه‌دهنده فقط پیدا کردن راه‌حل نیست بلکه باید بهترین و ساده‌ترین راهکارِ موجود را پیدا کنید. منظور از «ساده» راهکاری است که در عینِ عملکردِ خوانایی خوبی هم داشته باشد.

دو روش برای ساختِ نرم‌افزار وجود دارد: یا آنچنان ساده که به صورت آشکارا هیچ نقصی در آن وجود نداشته باشد یا آنقدر پیچیده که هیچ نقصِ آشکاری در آن پیدا نشود!

C.A.R. Hoare

پافشاری

اشتباهِ بعدی مبتدی‌ها پافشاری روی اشتباهاتشان است. آن‌ها حتی با وجود اشتباه بودن راه‌حل یا ناکارآمدیِ یک روش باز هم به فعالیتِ خود ادامه می‌دهند. پافشاری یا خودمانی‌تر «گیر سه پیچ دادن» در بسیاری از کارها خوب است ولی در برنامه‌نویسی باید در موردش با احتیاط رفتار کرد. در برنامه‌نویسی قاعده این است که زیاد شکست بخورید ولی سریع شکست بخورید و خیلی غرقِ در راهکار نشوید!

بخوانید  چطور در عرض 5 ماه حقوقم را دوبرابر کردم؟

هنگامِ تردید در مورد یک راه‌حل دست نگه دارید و کمی درموردش فکر کنید.اگر مناسب بود که هیچ، اگر نه سریعاً کنار بگذارید. تداومِ کار بدون تأمل نتیجه‌اش چیزی جز درجا زدن نیست. اهمیتی ندارد چقدر روی راهکارِ یافته شده هزینه کنید. این کاری است که اول و آخر باید انجام دهید. ابزارهای سورس کنترل مثل گیت کمک می‌کنند تا روش‌های مختلف را بدون ترک کردن محیط پروژه در انشعاب‌های مختلف امتحان کنید و هر وقت لازم بود به عقب برگردید. هیچگاه به خاطرِ اینکه چند ساعت یا چند روز برای پیاده‌سازی یک راهکار وقت گذاشته‌اید کارِ اشتباه را ادامه ندهید. هر زمان به اشتباه بودن یک روش پی بردید رهایش کنید. هرچقدر زودتر از شرِ یک روش بد دل بکنید فرصتِ بیشتری برای پیاده‌سازی راه‌حل‌های دیگر پیدا می‌کنید.

من ۹۹۹ بار شکست نخوردم. ۹۹۹ روش برای ساخته نشدن لامپ پیدا کردم.

توماس ادویسون

گوگل نکردن

بارها پیش آمده وقتِ زیادی را صرفِ یک مسئله کرده‌ام در حالی که با یک جستجوی ساده می‌توانستم راه‌حل را از اینترنت پیدا کنم. اگر آدمِ خوش شانسی باشید در هر مسئله‌ای که در اینترنت جستجو کنید قبل از شما یک نفرِ دیگر آن مسئله را مطرح کرده و به پاسخ رسیده است.

گاهی با جستجو متوجه می‌شوید مسئلۀ شما راه‌حلی ندارد و باید به شیوه‌ای مسالمت‌آمیز با آن کنار بیایید. فکر نکنید همۀ روش‌ها را خودتان تست کرده‌اید. خرد جمعی هوشِ بسیار بالاتری دارد و درست از همان‌جایی که اصلاً فکر نمی‌کردید راهکاری به شما پیشنهاد می‌دهد.

نشانۀ دیگر افرادِ مبتدی، کپی کردن کدهاست؛ البته این کار فی نفسه چیزِ بدی نیست ولی مشکل زمانی است که کدها را بدون فهم درستشان استفاده کنید. برنامه‌نویسان آماتور معمولاً با جستجو در اینترنت اولین کدی که پیدا کنند در برنامۀ استفاده می‌کنند و همین که کارشان راه افتاد رهایش کرده و از درک آن سر باز می‌زنند. اگر می‌خواهید برنامه‌نویسِ خوبی شوید حتماً باید تمامِ کد در مشتِ شما باشد؛ طوری که اگر کسی در مورد فلان قسمتِ کد سوالی از شما پرسید به راحتی پاسخ دهید.

استفاده نکردن از Encapsulation

کپسوله‌سازی (Encapsulation) فقط مربوط به برنامه‌نویسی شی‌گراء نیست. به همان اندازه که استفاده از این تکنیک منافعی به همراه دارد استفاده نکردن از آن نگه‌داری سیستم را دچارِ مشکل خواهد کرد.

هر تابع، متد یا کلاس باید فقط یک کار انجام دهد و ارتباطش با سایرِ بخش‌های سیستم در کمترین حدِ ممکن باشد. هرچقدر تعدادِ وابستگی‌ها و مسئولیت‌های یک واحد بیشتر شود نگهداری سیستم سخت‌تر خواهد شد.

با افزایشِ وابستگی‌ها تغییر در هر بخش قسمت‌های دیگر را هم تحت تأثیر قرار می‌دهد. شما نمی‌توانید به راحتی بخشی از برنامه را تغییر یا اصلاح کنید. نمی‌توانید ویژگی‌های جدید را بدون خراب شدن عملکردهای قبلی به برنامه اضافه کنید. منظور از واحد یا بخش هر چیزی اعم از مواردِ کوچک مثل تابع یا متد تا موارد بزرگ‌تر مثل کلاس، اینترفیس، ماژول، پکیج و … است.

به عنوان مثال کلاسِ User باید مسئولِ تمامِ کارهای مربوط به کاربر باشد؛ اعم از حذف کاربر، اضافه کردن کاربر، اصلاح کاربر یا نمایش اطلاعات او. هر متد باید فقط و فقط یک کار انجام دهد. این موضوع هم برای خواناییِ برنامه مهم است و هم نوشتن یونیت تست را آسان‌تر می‌کند.

برنامه‌نویسان مبتدی در ابتدا تشخیص درستی از موجودیت‌های سیستم ندارند. نمی‌دانند چه کلاسی باید چه کاری انجام دهد. برای کدام موجودیت باید کلاسِ مجزا تعریف کنند و کدام متدها را در کدام کلاس‌ها قرار دهند. این افراد معمولاً Big Class های زیادی با عناوینی چون UtilityClass و HelperClass و … دارند که مسئولیت‌های زیاد و بی‌ربطی بر دوشِ آن‌هاست. اگر تغییری در کد اعمال کردید و اثرات جانبیِ آن را در قسمتِ دیگری از سیستم دیدید نشانۀ کدنویسیِ یک برنامه‌نویس مبتدی است.

قبل از اضافه کردن یک متد به کلاس یا اضافه کردنِ بار مسئولیت‌های آن کمی در موردش فکر کنید. نگویید فعلاً بروم جلو، حالا بعداً ریفکتور می‌کنم. کار را یکبار و همان اول درست انجام دهید. در کدنویسی هیچ چیزی را به آینده حواله نکنید. ریفکتور تنها یک ابزارِ کمکی در شرایط اضطراری است نه یک مرحله از برنامه‌نویسی.

یک قاعدۀ مهم در طراحی شی‌گراء وجود دارد و آن Keeping Code High Cohesion and Low Coupling است؛ یعنی کدهای مرتبط را در یک واحد (مثلاً کلاس) قرار دهید و تا حدِ امکان میزان وابستگی بیرونیِ آن واحد را کاهش دهید.

برنامه‌ریزی برای چیزهای نامعلوم

همیشه این وسوسه در وجودِ توسعه‌دهندگان هست که به چیزی بالاتر از نیازِ امروزِ خود فکر کنند. مدام با خودشان اگر اگر می‌کنند که اگر اینجا اینطور شد چه؟ اگر این مقدار وارد شد چه؟ اگر عدد خیلی خیلی بزرگ بود چه. اگر فلان چیز وجود نداشت چه. اگر خطایی به وجود آمد چه و همینطور الی آخر.

لطفاً اگر می‌خواهید خودتان و دیگران را اذیت نکنید فقط به نیازِ امروزتان فکر کنید. چرا کدی می‌نویسید که فعلاً به آن نیازی ندارید؟ چرا وقتی کلِ کدِ شما ۵۰۰ خط بیشتر نیست این همه فایل و فولدر درست کرده‌اید؟ معمولاً این کارها را افراد کمال‌طلب انجام می‌دهند. اضافه کردن چیزی صرفاً به این خاطر که در آینده شاید به آن نیاز پیدا کنید کاملاً اشتباه است. خودتان را به خاطرِ آینده‌ای که هنوز نیامده پایبند نکنید. Over-Engineering نکنید!

همیشه برای رفع نیازهای امروزتان کد بنویسید. مواردِ حاشیه‌ای را هم هندل کنید ولی خودتان مواردِ جدیدتری اضافه نکنید.

رشد به خاطرِ رشد! این همان ایدئولوژی سلول‌های سرطانی است.

edward Abbey

استفاده نکردن از ساختمان دادۀ درست

افرادِ مبتدی هنگام آماده شدن برای مصاحبۀ استخدامی، بیشتر روی مباحث مربوط به الگوریتم‌نویسی تمرکز می‌کنند. تشخیصِ الگوریتم‌های خوب از بد خوب است ولی حفظ کردنِ این الگوریتم‌ها از شما یک نابغۀ برنامه‌نویسی نمی‌سازد.

در نقطۀ مقابل، اطلاع از نقاطِ ضعف و قوتِ انواعِ مختلفِ ساختمانِ داده (Data Structure) برای یک توسعه‌دهنده نقطۀ قوت شناخته می‌شود.استفاده از ساختمان دادۀ نادرست به خوبی تفاوتِ یک برنامه‌نویس کارکشته و مبتدی را نشان می‌دهد. به عنوان مثال یک نفر از آرایۀ معمولی برای ذخیره مقادیر استفاده می‌کند، دیگری از لیست و یک نفرِ دیگر از لیست پیوندی. هر یکی از این‌ها بسته به شرایطِ مسئله بهینه‌‌تر از بقیه هستند.

مثالِ رایجش نوشتن کدهایی است که ماهیتِ بازگشتی دارند. افراد که توجهی به پرفرمنس برنامه ندارند مستقیماً از روشِ بازگشتی استفاده می‌کنند. در این روش معمولاً بهینه‌سازی کارِ دشوار و تقریباً غیرممکنی است. تابعی که به صورت تودرتو در حافظه فرخوانی می‌شود تاثیر بسیار بدی روی حافظه و پردازش می‌گذارد.

به همین خاطر توصیه شده تا حدِ امکان از این روش برای حل مسائل استفاده نکنیم. بسیاری از افراد از ساختمان دادۀ پشته (Stack) غافلند. یعنی به جای اینکه خروجیِ متد را مجددا به همان متد پاس کنید درونِ یک استک پوش کنید. اینجا می‌توانید مثالی از این روش را ببینید.

بدتر کردن اوضاع

از شما خواسته شده تا لباسی را در این اتاق سرجایش قرار دهید. احتمالاً اگر با چنین صحنه‌ای برخورد کنید دلتان بخواهد شما هم لباس را به گوشه‌ای پرت کنید. لطفاً این کار را لااقل با یک کدِ شلوغ نکنید؛ یعنی اوضاع را از اینی که هست آشفته‌تر نکنید. در همه حال سعی کنید ذره‌ای اوضاع را نسبت به قبل بهتر کنید.

صرفِ اینکه بقیه آشغال ریخته‌اند شما هم آشغال نریزید. چون کد خودش شلخته و بی در و پیکر است شما هم مرتکب اشتباه نشوید. این کار شرایط را وخیم‌تر می‌کند. کارِ درست این است که سراغِ کمدِ لباس بروید و بعد از تمیز کردن آن، لباس را سرجایش قرار دهید. این یعنی در تاریکی شمعی روشن کردن!

چند نمونه از چیزهایی که اوضاع را بدتر می‌کنند:

کد تکراری. اگر قطعه کدی را صرفاً برای تغییر یک خطِ آن کپی می‌کنید در حالِ آشفته‌تر کردن کدهای موجود هستید. این یعنی به جای سرمایه‌گذاری روی یک صندلی با ارتفاعِ قابلِ تنظیم از صندلیِ مجزایی با پایه‌های کوتاه استفاده کنید. هرجایی که فکر می‌کنید abstraction به آسایشِ بیشترِ شما کمک می‌کند از آن استفاده کنید؛

استفاده نکردن از فایل‌های کانفیگ. اگر مقادیری دارید که بسته به محیطها یا شرایط مختلف متغیر هستند از هارد کد کردنشان داخلِ کد جلوگیری کنید. این مقادیر را در فایل‌های کانفیگ یا پیکربندی قرار دهید. هر مقداری که در چند جایِ کد استفاده می‌کنید متعلق به فایل‌های کانفیگ است.

مثلاً در برنامه‌نویسی اندروید فایلی تحتِ عنوانِ strings.xml هست که تمامِ رشته‌های مورد استفاده در برنامه را می‌توانید درونِ آن ذخیره کنید. بدین ترتیب هر وقت نیاز پیدا کردید رشتۀ «نمره» را در کلِ برنامه به «امتیاز» تغییر دهید کافی است به این فایل مراجعه کنید و فقط یک مقدار را تغییر دهید. همیشه موقعِ تعریفِ مقادیر جدید به این سوال پاسخ دهید که آیا این مقدار در چند جای دیگر نیز استفاده می‌شود؟ آیا در آینده ممکن است تغییر کند؛

استفادۀ نابه‌جا از دستورات شرطی یا متغیرهای موقت. هر شرطِ if شاخۀ جدیدی برای نوشتنِ تست‌های جدید است. هر وقت امکانش بود که بدونِ لطمه وارد شدن به خوانایی برنامه شرطی را حذف کنید حتماً این کار را انجام دهید. مثلاً در کدِ جاوا اسکریپت پایین:

function isOdd(number) {
  if (number % 2 === 1) {
    return true;
  } else {
    return false;
  }
}

به راحتی و بدون آسیب دیدن خوانایی برنامه می‌توان کد را به شکل ساده‌تری و بدون شرط بیان کنید:

function isOdd(number) {
  return (number % 2 === 1);
};

کامنت گذاشتن برای هر چیز بدیهی

من تا حد امکان از نوشتن کامنت خودداری می‌کنم چون فکر می‌کنم بسیاری از کامنت‌ها را می‌توان با نام‌گذاریِ بهترِ توابع، متدها، کلاس‌ها و … جایگزین کرد.

برای مثال در کدِ پایین:

// This function sums only odd numbers in an array
const sum = (val) => {
  return val.reduce((a, b) => {
    if (b % 2 === 1) { // if the current number is odd
      a+=b; // Add current number to accumulator
    }

    return a; // The accumulator
  }, ۰);
};

به جای کامنت‌های اضافه می‌توانید طوری کلمات را نام‌گذاری کنید که نیازی به استفاد از کامنت نباشد:

const sumOddValues = (array) => {
  return array.reduce((accumulator, currentNumber) => {
    if (isOdd(currentNumber)) {
      return accumulator + currentNumber;
    }

    return accumulator;
  }, ۰);
};

همانطور که می‌بینید با یک نام‌گذاری مناسب برای توابع و آرگومان‌ها به راحتی می‌توانید کامنت‌های اضافه را حذف کنید. بنابراین هنگام کدنویسی به نام‌گذاری‌ها توجه داشته باشید. به چنین کدهایی اصطلاحاً self-document گفته می‌شود یعنی از روی خودِ کد می‌توان به کارکردش پی برد.

بخوانید  بایسته‌های یک برنامه‌نویس خوب

با همۀ این‌ها گاهی به کامنت نیاز پیدا می‌کنید. اینجا بحثِ چطور کامنت گذاشتن مطرح می‌شود. قبلاً در مقالۀ «افکار و اندیشه‌های یک برنامه‌نویسِ خوب» متذکر شدیم که در کامنت‌نویسی به جای بیان عملکردِ کد باید به ذکرِ چرایی استفاده از کد بپردازیم. توسعه‌دهنده خودش با بررسی کدها می‌تواند به عملکردش پی ببرد. چیزی که ممکن است برای توسعه‌دهنده مبهم باشد دلیل استفاده از آن قطعه کد است. بنابراین توسعه‌دهنده دنبالِ What نیست بلکه او دنبال Why است. با وجودِ این اگر باز هم دوست داشتید کامنت‌هایی از نوعِ What استفاده کنید لطفاً این کار را برای قسمت‌های بدیهیِ کد انجام ندهید؛ نمونه‌اش این:

// create a variable and initialize it to 0
let sum = 0;

// Loop over array
array.forEach(
  // For each number in the array
  (number) => {
    // Add the current number to the sum variable
    sum += number;
  }
);

اگر به چنین کدهایی برخورد کردید قطعاً بدانید کسی که آن را نوشته یک مبتدی بوده است. شما نیز این کار را انجام ندهید تا در مصاحبه‌های استخدامی رد نشوید!

ننوشتن تست

بگذارید این نکته را ساده بگویم. اگر خودتان را یک برنامه‌نویس حرفه‌ای می‌دانید و به همین خاطر کدهایتان را بدون تست می‌نویسید به نظر من هنوز مبتدی هستید. وقتی برای کدهای خود تست نمی‌نویسید یعنی برنامۀ خود را به روش دیگری تست می‌کنید. یعنی با روش‌هایی مثل تغییر کد و سپس کامپایل و اجرای برنامه سروکله می‌زنید.

من نمی‌گویم این روش اشتباه است. اتفاقاً تست از روش کامپایل یکی از مهم‌ترین قسمت‌های برنامه‌نویسی است. ولی مشکلش این است که اگر فقط به این روش برای تستِ محدود شوید یادتان می‌رود که تست‌های موفقِ قبلی را هر بار بعد از اعمال تغییرات دوباره انجام دهید؛ و اینجا نقطۀ بروزِ مشکلات است. شما هر بار با تغییرِ کد نمی‌توانید تست‌های قبلی که به صورت دستی انجام داده‌اید را انجام دهید. اولاً یادتان می‌رود، دوماً تست کردن ترکیبات مختلفی از مقادیر ورودی زمان زیادی می‌طلبد. اجازه دهید کامپیوتر این کار را دقیق‌تر، کامل‎تر و سریع‌تر انجام دهد.

توصیه می‌کنم اگر می‌خواهید تست کنید از روش TDD بروید. در این روش پیش از آنکه کدی بنویسید تست در ذهن شما شکل می‌گیرد و شما برای پاس کردن آن تست کد می‌نویسید. مثلاً می‌خواهید تابعی بنویسد که دو عدد را با هم جمع کرده و خروجی را به شما نمایش دهد. وقتی هنوزی کدی ننوشتید مسلماً تست قرمز می‌شود. حالا یه اندازه‌ای که این تست پاس شود کدنویسی می‌کنید تا چراغ سبز شود. بعد از پاس کردن تست دوباره مراحل تدوین تست و کدنویسی برای پاس کردن آن را طی می‌کنید. در همین رابطه مطلبِ دیگری در اسکارپ منتشر کرده‌ایم: توسعۀ آزمون محور (TDD)

البته عادت به TDD کارِ ساده‌ای نیست و شاید در همۀ شرایط مقدور نباشد ولی سعی کنید در مواردی که می‌توانید از آن استفاده کنید.

اگر چیزی کار می‌کند پس درست کار می‌کند

کدِ جاوا اسکریپتِ پایین را ببینید. آیا مشکلی در آن وجود دارد؟

const sumOddValues = (array) => {
  return array.reduce((accumulator, currentNumber) => {
    if (currentNumber % 2 === 1) {
      return accumulator + currentNumber;
    }

    return accumulator;
  });
};

console.assert(
  sumOddValues([1, 3, 5]) === 9
);

احتمالاً همینکه assertion (که در Unit Test برای تست کردن ورودی‌های نمونه به کار می‌رود) درست کار کند همه چیز را درست فرض می‌کنید.

ولی مشکل اینجاست که تستِ بالا تابعِ یاد شده را از جنبه‌های متعدد تحت آزمون قرار نمی‌دهد و فقط یک حالتِ خاص را آزمایش کرده است. این تست کامل نیست و ممکن است تابع به ازای مقادیرِ دیگری که هنوز تست نشده دچار مشکل شود.

مشکل اولش این است که مقادیرِ خالی را هندل نمی‌کند. یعنی اگر هیچ عددی به تابع ندهیم خطا می‌دهد.

TypeError: Cannot read property 'reduce' of undefined.

کسی که از این تابع استفاده می‌کند نباید مجبور به بررسی کدهای آن شود. خطا هم چیزِ جالبی نیست. مهم این است که کدِ شما کاری که باید را انجام نمی‌دهد. شاید بد نباشد در چنین شرایطی با ارسال یک اکسپشنِ مناسب مصرف‌کننده را از اتفاقی که افتاده مطلع کنید. یا حتی تابع را طوری طراحی کنید که برای مقادیرِ خالی ۰ برگرداند.

مشکلِ بعدی هندل نکردن ورودی‌های نامناسب است. چه می‌شود اگر به جای آرایه‌ای از اعداد یک رشته یا یک عدد به تابع بفرستیم؟

این خطایی است که هنگامِ وارد کردن یک مقدارِ نامناسب با آن مواجه خواهیم شد:

sumOddValsue(42);
TypeError: array.reduce is not a function

چون نامِ آرگومان را array گذاشته‌ایم هر چیزی که به ورودی بدهیم (از جمله عدد ۴۲) با نامِ array شناخته می‌شود. همانطور که می‌بینید خطای گیج‌کننده‌ای است. شاید با پیغام خطایی مثل «۴۲ یک آرایه نیست» راحت‌تر بتوان جریان را به مصرف‌کننده اطلاع داد.

دو مشکلی که تا الان در مورش حرف زدیم محتمل هستند و حتماً باید فکری به حالشان بکنیم. اصطلاحاً به این‌ها مشکلات edge-case گفته می‌شود. اما مواردی هست که ممکن است کمتر اتفاق بیفتد ولی باز هم نباید آن‌ها را نادیده گرفت. برای مثال رفتارِ این تابع در برابر ورودی منفی چیست. اگر در آرایۀ ورودی عدد منفی ۱۳- حضور داشته باشد تابع چه واکنشی نشان می‌دهد؟ آیا باید خطایی صادر کند؟ آیا ورودِ مقادیر منفی مجاز نیست؟ یا کلاً مقادیر منفی را نادیده می‌گیرد؟ اگر اینطور باشد بهتر است نامِ تابع را به sumPositiveOddNumbers تغییر دهید. اگر برای چنین مقادیری تست کیس ندارید با یک کامنت به مصرف‌کننده اطلاع دهید که چرا در قبالِ فلان ورودی‌ها تابع چنین رفتاری از خود نشان می‌دهد. (بیان چرایی “Why” در کامنت. یادتان که هست؟)

همانطور که می‌بینید مشکلات پیش‌بینی نشدۀ زیادی برای همین تابعِ کوچک وجود دارد. این فقط یک تابعِ کوچک بود؛ وای به حال برنامه‌ای با صدها یا هزاران تابع و متد! شما نمی‌توانید همۀ این حالات را به صورتِ دستی چک کنید. برای هر سناریو باید یک تست کیسِ جدا بنویسید. از نشانه‌های افرادِ آماتور می‌توان به ناقص بودن تست کیس‌های اشاره کرد. آن‌ها برای هر متد تست‌های اندکی برای ورودی می‌نویسند و بسیاری از مقادیرِ ورودی را پوشش نمی‌دهند.

پذیرفتنِ کد به همان شکلی که هست

بعید است برنامه‌نویس باشید و تا الان با کدهای احمقانه مواجه نشده باشید. برنامه‌نویسان آماتور معمولاً خوب یا بد بودن کدها را به خاطرِ تجربۀ کمشان تشخیص نمی‌دهند و صرفِ اینکه کدی مدت‌ها بخشی از یک کدبیس بزرگتر بوده و تا الان درست کار می‌کرده آن را خالی از اشکال می‌بینند.

مشکلِ بدتر این است که این کدها باعث می‌شوند مبتدی‌ها بدعادت شوند. یعنی همان شیوۀ اشتباهِ کد را با فرضِ اینکه آن را یک کد خوب فرض کرده‌اند تکرار کنند. گاهی چنین کدهایی تحتِ شرایطِ خاصی نوشته شده و چیزی نیست که حتماً به دلخواه توسعه‌دهنده بوده باشد. در این حالت حتماً با یک کامنت توضیح دهید که چرا از این شیوه پیروی کرده‌اید.

هر کدی که درکِ درستی از آن ندارید کاندیدای مناسبِ یک کدِ بد است. بنابراین هرجایی با این کدها مواجه شدید در آنِ واحد حکم به درستیِ آن‌ها ندهید. درموردش سوال کنید، با دیگران مشورت کنید و علتِ چنین کدنویسی را جویا شوید.تنها زمانی در مورد خوب یا بد بودن کدها اظهارِ نظر کنید که به خوبی درکش کرده باشید. تا زمانی که اطلاعاتِ کافی در مورد قطعه کدی نداشتید هیچ پیش‌فرضی در نظر نگیرید.

وسواس در مورد Best Practiceها

اصطلاحی در برنامه‌نویسی هست به نامِ Best Practice که احتمالاً شما هم با آن آشنا هستید. این اصطلاح اشاره دارد به استفاده از بهترین روش‌ها، اعم از بهترین الگوهای طراحی، بهترین معماری‌ها، بهترین روش‌هایِ سازمان‌دهیِ فایل‌های پروژه و … . این اصطلاح به همان اندازه که ظاهرِ خوبی دارد می‌تواند باطنِ بدی داشته باشد. هیچ بهترینی وجود ندارد؛ نه‌فقط در دنیای برنامه‌نویسی که در هیچ شاخۀ دیگری نیز «بهترین» وجود ندارد.

«بهترین» واژه‌ای است که در کلامِ افرادِ کمال‌گرا بیشتر دیده می‌شود. آن‌ها همواره دنبالِ بهترین روش‌ها برای انجامِ هر کاری هستند. اما باید بگوییم این سرابی بیش نیست. روش‌های زیادی بوده که در قدیم جزء best practice محسوب میشده ولی امروز از دور خارج شده‌اند. نمونه‌اش روشِ آبشاری که جایش را به متدهای اجایل در توسعۀ نرم‌افزار داده است.

با صرفِ وقت می‌توانید «روش بهتر» را پیدا کنید ولی وقتِ خود را بیهوده برای یافتن «بهترین روش» هدر ندهید. تنها Best Practice های دنیای برنامه‌نویسی آن‌هایی هستند که کلی هستند؛ مثلاً کدها را باکیفیت بنویسید یا آن‌ها را بدونِ تست رها نکنید.

به هیچ عنوان صرفِ اینکه فلانی از فلان روش استفاده می‌کند و روشِ خود را بهترین روش معرفی کرد شما نیز از او پیروی نکنید. هر روشی که انتخاب کنید بالاخره موافقان و مخالفانی دارد و در کنار مزایا، معایبی هم خواهد داشت. شرایط را ارزیابی کرده و روشِ بهتر (نه بهترین روش) را انتخاب کنید.

وسواس در موردِ پرفرمنسِ برنامه

بهینه‌سازی زودهنگام ریشۀ همۀ مشکلاتِ برنامه‌نویسی است (لااقل ریشۀ بسیاری از مشکلات).

Donal Knuth 1974

با وجودِ اینکه از زمانِ دونالد کناث تاکنون کدنویسی تغییرات زیاده پشت سر گذاشته ولی به نظرم هنوز گفتۀ او درست و به‌جاست.

این قاعدۀ خوب را به خاطر بسپارید: اگر کد در شرایطی نیست که به سادگی بتوانید مشکلاتِ مربوط به کارایی آن را تشخیص دهید سراغِ بهینه‌سازی‌اش نروید. اگر پیش از شروعِ کدنویسی یا قبل از بلوغِ نسبیِ پروژه به فکرِ بهینه‌سازیِ آن بیفتید یعنی می‌خواهید بهینه‌سازی زودهنگامِ کنید. البته برخی بهینه‌سازی‌های آشکار را باید قبل از کدنویسی انجام دهید. مثلاً در Node.js نباید Event Loop را بلاک کنید و این موضوعی است که موقعِ کدنویسی همیشه باید به آن دقت کنید.

نوعِ دیگری از بهینه‌سازی از بهینه‌سازی زودهنگام هم بدتر است و آن «بهینه‌سازی غیرضروری» است که اغلب مبتدی‌ها به آن مبتلا هستند. هر نوع بهینه‌‌سازیِ غیرضروری روزی برایتان مکافات خواهد شد. چیزی که شما اسمش را بهینه‌سازی گذاشته‌اید شاید روزی زمینه‌سازِ باگ‌های پیش‌بینی نشده شود. پس تا زمانی که لازم نشده و پروژه آمادگی دریافت بهینه‌سازی ندارد سراغِ بهینه‌سازی نروید.

در نظر نگرفتن نیازِ کاربرانِ نهایی

بهترین روش برای افزودن فیچرهای جدید به برنامه چیست؟

اگر منفعت توسعه‌دهنده را ملاک قرار دهیم بهترین روش کم‌هزینه‌ترین و ساده‌ترین روش است؛ یعنی هر جوری که توسعه‌دهنده راحت‌تر باشد؛ مثلاً از کنترل‌هایی استفاده کنیم که نیازی به سفارشی کردن یا تغییر واسطِ کاربری نداشته باشد. یا اگر می‌خواهید به صفحه‌ای لینک بدهید آن را در منوهای تودرتو که از قبل طراحی کرده‌اید اضافه کنید.

بخوانید  Junior | Mid-Level | Senior

لطفاً این چنین نباشید! یک توسعه‌دهندۀ حرفه‌ای از نگاهِ کاربرانش به برنامه نگاه می‌کند و به این فکر می‌کند که کاربرِ به چه ویژگی‌هایی نیاز دارد و این ویژگی‌ها را چگونه می‌تواند در بهترین شکل به آن‌ها عرضه کند؛ حتی اگر به قیمتِ سخت‌تر شدن پیاده‌سازی باشد.

یک برنامه‌نویسِ بد به این فکر می‌کند که چطور می‌تواند فلان قابلیت را به ساده‌ترین شکلِ ممکن پیاده‌سازی کند و به کاربردپذیری و سهولت استفاده از آن توجهی ندارد. در نقطۀ مقابل یک برنامه‌نویسِ حرفه‌ای فقط نگاهش به کاربرِ نهایی است و به سختی‌هایی که ممکن است با آن‌ برخورد کند توجهی ندارد.

استفاده از ابزارهای نامناسب

هر کسی برای برنامه‌نویسی از ابزارهای مورد علاقۀ خود استفاده می‌کند. بعضی از این ابزارها عالی و بعضی دیگر بد هستند اما بیشترِ ابزارها همه‌چیزتمام نیستند بلکه فقط در یک ویژگیِ مشخص عالی هستند. مثلاً چکش ابزارِ خوبی برای کوبیدن میخ به دیوار است ولی برای پیچ هیچ کاربردی ندارد. هیچگاه به خاطرِ علاقه به چکش نباید برای پیچ از آن استفاده کنید. صرفِ اینکه آن چکش بهترین چکشِ بازار است و امتیازِ بالایی از سوی کاربران گرفته برای پیچ استفاده نکنید. به قولِ مولوی: هر کسی را بهرِ کاری ساختند.

وابستگی به یک ابزار به خاطرِ شهرتِ آن ابزار یا تعصب داشتن به آن از نشانه‌های افرادِ مبتدی است.

نکته اینجاست که شما دقیقاً نمی‌دانید برای چه کاری کدام ابزار مناسب‌تر است. شاید شما به این دلیل که از وجودِ سایرِ ابزارها اطلاع ندارید ابزارِ خود را بهترین می‌دانید. سعی کنید تعصب را کنار بگذارید و با نگاهی باز به این مسائل نگاه کنید. هر زمان ابزارِ بهتری یافتید استفاده کنید و استفاده از چند ابزار را چیزِ بدی ندانید. شاید بهتر باشد برای هر کاری از ابزارِ مناسب آن استفاده کنید.

بعضی برنامه‌نویس‌ها به خاطر سختیِ کار با ابزارهایِ جدید مایل نیستند دل از ابزارِ فعلیِ خود بکنند. البته حق می‌دهم ولی از اشتباه بودنِ این کار نیز نمی‌توانم بگذرم.

شما می‌توانید با ابزارهای ابتدایی هم خانه بسازید ولی با کمی صرفِ وقت و هزینه برای ابزارهای جدید قطعاً خانه را با سرعت بیشتری خواهید ساخت. ابزارها برای سادگیِ کارهای ما ساخته شده‌اند. پس هر وقت به آن‌ها نیاز داشتیم استفاده کنیم.

آگاه نبودن از این موضوع که مشکلاتِ کد می‌تواند به داده‌ها آسیب بزند

یکی از مهم‌ترین موضوعات در برنامه‌نویسی، مدیریت داده‌هاست. در واقع برنامه فقط واسطی برای کار با داده‌هاست. کاربر به راحتی می‌تواند رکوردهای جدید را از طریق رابط گرافیکی وارد پایگاه اطلاعاتی کند و به شکلِ مرتب و قابلِ فهمی در برنامه مشاهده کند.

وجودِ کوچک‌ترین باگ‌ در برنامه می‌تواند داده‌ها را در وضعیتِ ناپایدار و غیرقابل پیش‌بینی قرار دهد. این موضوع به خصوص زمانی حائز اهمیت است که عملیات اعتبارسنجی داده‌ها توسط برنامه‌ای که در آن باگ وجود دارد انجام می‌شود. در این مورد افراد تازه‌وارد سهل‌انگاری بیشتری دارند. آن‌ها صرفِ کم‌اهمیت بودن یک باگ آن را به حالِ خود رها می‌کنند؛ غافل از اینکه ممکن است همان باگِ کوچک روی جامعیت داده‌ها (Data Integrity) اثرِ منفی داشته باشد. همۀ اثراتِ منفی در نگاهِ اول خود را نشان نمی‌دهند و ممکن است زمانی به بدترین شکلِ ممکن بر سرتان آوار شوند.

برای مقابله با چنین مشکلاتی همیشه جامعیت داده‌ها را در چند لایه بررسی کنید. مثلاً در وب‌اپلیکیشن‌ها این کار را در فرانت اند، بکند، ارتباطات شبکه و دیتابیس به صورت جدا انجام دهید. کمترین حدِ انجامِ این کار استفاده از constraint ها در سطحِ دیتابیس است.

Constraints یا محدودیت‌ها بحثِ مهمی در دیتابیس است و هر زمان که ستونی به جداولِ اضافه می‌کنید باید به آن‌ها توجه کنید:

  • Not Null: محدودیتی است که اجازۀ ورودِ مقادیرِ تهی نمی‌دهد. اگر در برنامۀ شما وجودِ مقداری برای یک فیلد اجباری است باید از این محدودیت استفاده کنید؛
  • UNIQUE: این محدودیت باعث می‌شود تا در ستونِ مربوطه هیچ مقدارِ تکراری پذیرفته نشود. این محدودیت کاربردِ زیادی برای ستون‌هایی مثل نامِ کاربری و ایمیل دارد. چون این داده‌ها برای هر کسی منحصر به فرد است. هیچ دو نفری نام کاربری یا ایمیل یکسان ندارد؛
  • CHECK: این constraint مقدارِ ورودی یک ستون را بر اساس یک شرط که تعریف کرده‌ایم پذیرش یا رد می‌کند. برای مثال اگر فیلدی دارید که فقط مقادیرِ بین ۰ تا ۱۰۰ را قبول کند از محدودیت Check استفاده کنید؛
  • RPRIMARY KEY: محدودیتی است که هم تهی نبودن (not-null) مقدار و هم منحصر به فرد بودن آن را چک می‌کند. احتمالاً شما نیز در دیتابیسِ خود از این کلید استفاده می‌کنید. اصولاً هر جدولی در دیتابیس باید یک Primary key داشته باشد تا بتوان رکوردهای آن را تشخیص داد؛
  • FOREIGN KEY: برای ارتباط جداول با هم کاربرد دارد. یعنی ستونی در یک جدول به مقادیری در ستونِ دیگری در جدولی دیگر اشاره می‌کند.

بحث دیگری در جامعیت دیتابیس وجود دارد و آن ACID است که سرنامِ چهار کلمۀ Atomicity, Consistency, Isolation, Durability است. یعنی هر تراکنش یا باید به صورتِ کامل انجام شود یا اصلاً انجام نشود.

اجراِ ناقصِ یک تراکنش می‌تواند تبعاتِ زیادی داشته باشد. مثلاً هنگام کارت به کارتِ پول اگر مبلغی که به دوستِ خود واریز می‌کنید در مقصد به حساب او واریز نشود پول مجددا به حسابِ شما عودت داده می‌شود. در پیامک‌های بانک نیز مشاهده خواهید کرد که مبلغی از حسابتان برداشت شده و چند دقیقه بعد دوباره به حسابتان برگشت داده شده است. این یعنی جامعیت تراکنش‌ها. تصور کنید مبلغ یک حساب کم می‌شد و به حسابِ دیگری منتقل نمی‌شد.

اختراعِ دوبارۀ چرخ

در برنامه‌نویسی بعضی چرخ‌ها ارزشِ دوباره خلق شدن دارند. برای مثال اگر به چرخی نیاز پیدا کنید که بسته به ساعاتِ مختلفِ روز با سرعت‌های متفاوتی بچرخد به جای شخصی‌سازیِ چرخ شاید بازاندیشی در موردِ آن ایدۀ بهتری باشد. بنابراین فقط در شرایطی که نیاز به خلقِ دوبارۀ چرخ داشتید این کار را انجام دهید؛ در سایرِ موارد از همان چرخِ معمولی استفاده کنید.

وقتِ گرانبهایِ خود را صرفِ پیدا کردن بهترین چرخ نکنید. یک جستجویِ ساده و سریع کافی است. تنها زمانی چرخ‌ها را عوض کنید که عملکردِ مورد انتظار شما را برآورده نمی‌کند. نکتۀ جالب در مورد برنامه‌نویسی این است که اغلبِ چرخ‌ها رایگان و متن باز هستند. به راحتی می‌توانید طراحیِ داخلیِ آن را ببینید و در صورتِ لزوم بر اساسِ نیازهایتان سفارشی‌سازی کنید.

تا جایی که می‌توانید از چرخ‌های متن‌باز استفاده کنید! پروژه‌های متن‌باز را آسان‌تر می‌توانید دیباگ کنید. راحت‌تر می‌توانید با مواردِ دیگر جایگزین کنید.

گاهی لازم نیست برای استفاده از یک یا دو عملکردِ کتابخانه، کل آن کتابخانه را در برنامۀ خود استفاده کنید. سعی کنید فقط از همان بخشی که لازم دارید استفاده کنید. اینطوری هم حجمِ برنامه کمتر می‌شود و هم اشکال‌زدایی و نگه‌داری کد آسان‌تر خواهد شد. مثلاً در جاوا اسکریپت کتابخانۀ lodash را داریم. اگر فقط به شافل کردن آرایه نیاز داشتید تنها متدِ شافلِ را ایمپورت کنید نه کلِ کتابخانه.

انتقادپذیر نبودن

یکی از مشکلاتِ افرادِ مبتدی این است که آن‌ها هر نوع Code Review ای را انتقاد فرض کرده و این کار را دوست ندارند. حتی تشکر هم نمی‌کنند.

این تصور اشتباه است و اگر اینگونه هستید باید خودتان را تغییر دهید. هر Code Review را فرصتِ جدیدی برای یادگیری بدانید. این فرصت‌ها را با آغوشِ باز بپذیرید و از اینکه چنین فرصتی در اختیار شما قرار گرفته خوشحال باشید. از افرادی که کدهای شما را بازبینی می‌کنند و در موردش نظر می‌دهند به خاطرِ وقتی که برای این کار گذاشته‌اند تشکر کنید. یک برنامه‌نویسِ خوب همیشه در حالِ یادگرفتن چیزهای جدید است. اشتباهاتِ خود را می‌پذیرد. او به دیگران به عنوانِ منابعی برای یادگیری نگاه می‌کند.

البته گاهی منتقدین اشتباه می‌کنند و حالا نوبتِ شماست که به آن‌ها چیزهای جدید یاد بدهید. آموزش دادن یکی از ارزشمندترین کارهایی است که انسان می‌تواند انجام دهد. به‌خصوص در حوزۀ برنامه‌نویسی که بیشتر از اینکه طرفِ مقابل بیاموزد خودِ شما با تکرار دانسته‌های خود بیشتر خواهید آموخت. من بیش از نیمی از زمانِ خود را صرفِ آموزش به دیگران کرده‌ام. آیا فکر می‌کنید این کار را فقط برای پول انجام می‌دهم؟

استفاده نکردن از سورس کنترل

برنامه‌نویسان تازه‌کار معمولاً قدرتِ ابزارهای سورس کنترل (Source Control) را دستِ کم می‌گیرند. و البته منظورِ ما از سورس کنترل مهم‌ترینِ آن‌ها یعنی گیت است. ابزارهای مدیریت نسخه فقط برای اشتراک کد با سایرِ افراد نیست. سورس‌کنترل‌ها تاریخچۀ تغییرات کد را نگه‌داری می‌کنند. هر کسی با نگاه کردن به کامیت‌های ارسالی متوجه می‌شود که برنامه از کجا به وضعیتِ کنونیِ رسیده است. و از همه مهم‌تر در هر لحظه که با مشکلی مواجه شدید به راحتی می‌توانید به جایی که دوست دارید برگردید.

سعی کنید زود به زود کامیت کنید. در حالت ایده‌آل هر کامیت فقط باید یک موضوع را انعکاس کند و بهتر است از زمانِ حال برای عنوانِ آن استفاده کنید. در بخش جزئیاتِ کامیت نیز می‌توانید توضیحات بیشتری ارائه دهید ولی توجه داشته باشید اینجا نیز باید خلاصه بنویسید. کامیتی که در بخشِ جزئیاتش چند خط توضیح وجود دارد نشان‌دهندۀ آن است که کامیت مناسبی نیست چون در تلاش است تغییراتِ چند کامیتِ را در قالبِ یک کامیت ارسال کند. اینجا دیگر چاره‌ای نیست باید Rebase کنید!

در متنِ کامیت چیزهای غیرضروری را قرار ندهید. به عنوان مثال لیستِ فایل‌های حذف شده یا ویرایش شده را وارد نکنید؛ این فایل‌ها در خودِ کامیت وجود دارند و با دستوراتِ ساده‌ای در گیت به راحتی می‌توان به آن‌ها دسترسی داشت. بنابراین قرار دادنشان در بخشِ summary اضافه‌کاری است. یک قاعدۀ کلی درمورد کامیت‌نویسی وجود دارد و آن این است که هر وقت مجبور شدید طولانی بنویسید یعنی در ارسال کامیت تأخیر داشته‌اید و سعی دارید تغییراتی که به هم ربطی ندارند را ارسال کنید.

کامیت‌ها کمک می‌کنند تا بفهمید کدام بخش‌های کد باعثِ بروز باگ شده‌اند. گیت حتی امکانِ جستجوی باینری هم دارد و به شما امکان می‌دهد کامیتِ مقصر در بروز باگ را پیدا کنید. سورس‌کنترل ابزارِ بسیار مفیدی است که استفاده از آن می‌تواند بهره‌وری شما را افزایش دهد.

در آگهی‌های استخدام بلد بودن ابزارهایی مثل گیت به یک باید تبدیل شده است. سعی کنید استفاده کنید و از امکاناتش لذت ببرید. توصیه می‌کنیم راهنمای ۱۲ قسمتی گیت را را مطالعه کنید. یک آموزشِ جمع‌وجور با مثال‌های متعدد است که اطلاعاتِ زیادی در مورد گیت به شما می‌دهد.

نگرشِ اشتباه در مورد خطاها

خطا چیزِ بدی نیست. اتفاقاً از این حیث که اشتباهاتِ برنامه‌نویسیِ شما را گوشزد می‌کند نشانۀ خوبی برای پیشرفت است. خطاها به شما کمک می‌کند تا نقاط ضعفتان را شناسایی کنید. برنامه‌نویسان حرفه‌ای از خطاها استقبال می‌کنند ولی افرادِ تازه‌کار از آن متنفرند. نگرشِ خود را در مورد آن پیغام‌های قرمز رنگ تغییر دهید. به خطاها به عنوان اهرم‌های یادگیری بنگرید. با آن‌ها مواجه شوید و برای پیشرفتتان استفاده کنید. برخی از انواعِ خطا در کنترلِ شما نیست که باید با اکسپشن هندلینگ مدیریتشان کنید. برخی دیگر را نمی‌توان برطرف کرد و حتماً باید برنامه کرش و دوباره اجرا شود.

استراحت نکردن

شما انسان هستید و به استراحت نیاز دارید. بدنِ شما ماشین نیست، آن هم به استراحت نیاز دارد. برنامه‌نویس‌ها معمولاً آنقدر گرمِ کار می‌شوند که گذرِ زمان را احساس نمی‌کنند. هیچ وقت به کارِ زیاد و خارج از چارچوب افتخار نکنید.

طوری برنامه‌ریزی کنید که مجبور شوید لحظاتی از کامپیوتر دور شوید؛ مثلاً باشگاه، استخر یا سایر فعالیت‌های ورزشی. مدام فعالیت نکنید؛ هر از چندگاهی از صندلی بلند شده و چند قدمی راه بروید و به یک نقطۀ دوردست خیره شوید. بعد از چند دقیقه دوباره با چشم‌های سرحال سراغِ کدنویسی بروید.

مقاله خیلی طولانی شد. کمی استراحت کنید.

منبع: jscomplete

سید ایوب کوکبی

نویسنده و مترجم...

0 دیدگاه

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *