آشنایی با نحوهٔ سادهسازی سورسکد با حذف دستورات شرطی
معمولاً یکی از چالشهایی که دولوپرهای مبتدی با آن مواجه میشوند این است که چگونه میتوان مسئلهای را به روشهای دیگری مثلاً بدون استفاده از دستورهای شرطی، اپراتورهای به اصطلاح Ternary و یا دستورات سوئیچ حل کرد و لازم به یادآوری است که تلاش برای مواجهه با چنین چالشهایی برای ایشان مفید است چرا که منجر به یادگیری نحوۀ تفکر و تحلیل مسائل به گونهای متفاوت شده و به تدریج از ذهنی خلاق و الگوریتمیک برخوردار خواهند شد (جهت آشنایی با مفهوم Ternary Operator میتوانید به مقالۀ آشنایی با اپراتور Null Coalesce در PHP مراجعه نمایید.)
البته لازم به یادآوری است که اجتناب از بهکارگیری دستوراتی همچون if
در کدنویسی صرفاً به منظور افزایش خوانایی کد نبوده و دلیلی منطقی نیز دارا است و آن هم مفهومی میباشد موسوم به Code as Data بدین معنی که عدم استفاده از دستورهای شرطی منجر به نزدیکی ساختار منطقی کد به سینتکس زبان برنامهنویسی مد نظر میشود به طوری که اصطلاحاً Business Logic برنامه را به راحتی میتوان از روی سورسکد و سینتکس آن درک کرد و همچنین دیتای حاصل از اجرای کد روند منطقی برنامه را تعیین میکند که در همین راستا قصد داریم تا در ادامهٔ این آموزش برخی از مسائل برنامهنویسی را به دو روش متفاوت (هم بر اساس دستورهای شرطی و هم بدون استفاده از آنها) و با بهکارگیری زبان برنامهنویسی جاوااسکریپت حل کنیم تا ببینیم کدام یک از این راهحلها منجر به افزایش خوانایی سورسکد میشوند.
مسئلۀ اول: شمارش تعداد اعداد صحیح فرد در یک آرایه
ابتدا آرایهای متشکل از چند عدد صحیح تعریف کرده و در ادامه تعداد اعداد فرد موجود در آن را مشخص میکنیم:
const arrayOfIntegers = [1, 4, 5, 9, 0, -1, 5];
let counter = 0;
arrayOfIntegers.forEach((integer) => {
const remainder = Math.abs(integer % 2);
if (remainder === 1) {
counter++;
}
});
console.log(counter);
همانطور که میبینید، ابتدا آرایهای به نام arrayOfIntegers
تعریف کرده و اعداد فوق را به آن اختصاص دادهایم و با بهکارگیری کیورد const
گفتهایم که مقدار این متغیر صرفاً محدود به بلوک جاری بوده و امکان اختصاص آرایۀ جدید و یا به اصطلاح Declare (تعریف) کردن مجدد آن با مقادیر جدید در بلوک جاری فراهم نشود که این امر منجر به کاهش ایجاد باگ در روند اجرای برنامه خواهد شد.
در ادامه متغیری تحت عنوان counter
تعریف کرده و مقدار اولیۀ صفر را به آن اختصاص دادهایم و با بهکارگیری کیورد let
گفتهایم مقدار این متغیر در داخل بلوک جاری اعتبار داشته اما این در حالی است که امکان تغییر آن در روند اجرای برنامه و در صورت لزوم فراهم است و همانطور که در مثال فوق مشاهده میکنید، مقدار متغیر counter
در طی اجرا تغییر پیدا میکند (جهت آشنایی با این کیوردها در زبان برنامهنویسی جاوااسکریپت توصیه میکنیم به مقالۀ درآمدی بر کلیدواژههای let و const مراجعه نمایید.)
در ادامه، فانکشن از پیش تعریفشدۀ ()forEach
را فراخوانی کرده و در آن گفتهایم هر یک از اعداد آرایۀ فوقالذکر را بر عدد 2 تقسیم کرده و در ادامه باقیماندۀ حاصل از تقسیم را به فانکشن ()abs
میدهیم که یک فانکشن از پیش تعریفشده و متعلق به کلاس Math
میباشد که این وظیفه را دارا است تا کلیهٔ مقادیر را به عدد مثبت تبدیل کند که در این مثال نیز باقیماندۀ تقسیم را در قالب یک عدد مثبت ریترن کرده که در ادامه نتیجه را در متغیری به نام remainder
نگاهداری میکنیم.
اما همانطور که میدانیم، باقیماندۀ حاصل از تقسیم هر عدد بر 2 برابر با 1 و یا 0 میباشد و از همین روی در هر بار تقسیم اعداد آرایه بر عدد 2، مقدار ذخیرهشده در متغیر remainder
را بررسی میکنیم بدین صورت که در ادامه گفتهایم اگر چنانچه مقدار متغیر remainder
برابر با 1 بود یک واحد به متغیر counter
اضافه شود و این حلقه تا زمان پایان یافتن مقادیر آرایه ادامه خواهد یافت و در سطر بعد نیز مقدار نهایی متغیر counter
در خروجی چاپ خواهد شد به طوری که داریم:
5
حال در این مرحله قصد داریم تا مسئلۀ فوق را بدون استفاده از دستورات شرطی پیادهسازی کنیم که برای این منظور داریم:
const arrayOfIntegers = [1, 4, 5, 9, 0, -1, 5];
let counter = 0;
arrayOfIntegers.forEach((integer) => {
const remainder = Math.abs(integer % 2);
counter += remainder;
});
console.log(counter);
همانطور که میبینید، این راهحل تا حدودی مشابه حالت قبلی بوده و تنها تفاوت آن در حذف دستور شرطی است که در آن گفتهایم باقیماندۀ تقسیم هر یک از اعداد آرایه بر عدد 2 به مقدار قبلی متغیر counter
اضافه شود و بنابراین در هر بار تقسیم، مقدار ذخیرهشده در متغیر remainder
با مقدار پیشین متغیر counter
جمع میشود و در شرایطی که عدد مد نظر زوج باشد باقیماندۀ تقسیم برابر با 0 بوده و counter
افزایش نمییابد و چنانچه عدد مذکور فرد باشد باقیماندۀ تقسیم برابر با 1 شده و یک واحد نیز به counter
افزوده میشود و در سطر پایانی هم مقدار نهایی متغیر counter
در خروجی چاپ خواهد شد.
نکتۀ قابلتوجه در پیادهسازی مسئلۀ فوق بدون استفاده از دستورهای شرطی این است که در روش دوم از دیتای حاصل از باقیماندۀ تقسیم بر عدد 2 در پیادهسازی منطق برنامۀ خود استفاده کردهایم که این امر اشاره به مفهومی دارد که در ابتدا بیان شد (Code as Data) و بدین ترتیب میتوان گفت در برخی موارد عدم استفاده از دستورهای شرطی در کدنویسی منجر بدین میشود تا دیتای حاصل از اجرای برنامه قابلیت تغییر در روند کلی سورسکد را در زمان اجرا داشته باشد.
جمعبندی
لازم به یادآوری است که کدنویسی با بهکارگیری دستورهای شرطی و یا خلاصهنویسی آنها در برنامهنویسی مانعی ندارد اما این در حالی است که اجتناب از آنها در برخی موقعیتها منجر به سادگی و افزایش خوانایی کد میشود اما در عین حال توجه داشته باشیم که این موضوع یک قاعدۀ کلی نبوده و ممکن است در همۀ موارد صادق نباشد به طوری که اجتناب از دستورات شرطی در برخی مسائل حتی ممکن است موجب کاهش خوانایی سورسکد نیز گردد!