بسم الله الرحمن الرحیم
در این مطلب با مدل فکری فانکشنال آشنا میشین. این مدل فکری وابستگی به زبان برنامهنویسی خاصی نداره اما در اینجا از زبان سیشارپ استفاده میکنیم.
توی برنامهنویسی روش فکر کردن خیلی مهمه. اگر درست فکر کنیم میتونیم هم مسائل رو بهتر حل کنیم و هم اینکه کدهای تمیزتر، خواناتر، مطمئنتر و قابلاستفادهتر تولید کنیم. اینکار لطف بزرگی به خودمون و دیگران هستش و باعث صرفهجویی بسیاری در وقت و هزینهها میشه.
یکی از روشهای خوب فکر کردن، مدل فانکشنال (Functional) هستش. برخلاف تصور خیلیها فانکشنال صرفا مجموعهای از اصول مثل SOLID نیست. بلکه الگو و مدل متفاوتی از نحوه فکر کردن و حل مسئله هستش.
خیلیهامون برنامهنویسی رو با الگوریتم شروع کردیم و اونجا بهمون گفتن تک تک کارهایی که باید انجام بشه رو به کامپیوتر بگیم. تمرکز این مدل روی چطوری انجام دادن کارها هستش. مثلا اول اینکار رو بکن، بعد اگر فلان حالت بود اینکار رو بکن، اگر نبود اون کار رو بکن... مجموعهای از ifها و forها و...
اما در مدل تفکری فانکشنال، تمرکز بر اینه که ما چی میخوایم؟ نه اینکه چطور انجام بشه. اینکه چطور انجام بشه رو به مجموعهای از توابع پایه واگذار میکنیم که تست شده، مطمئن، قابل استفاده و خوانا هستن. حالا برای اینکه چنین توابعی (فانکشن/متد) درست کنیم لازمه از اصول و قواعد فانکشنال استفاده کنیم.
برنامهنویسی فانکشنال صرفا مجموعهای از قواعد کدنویسی نیست بلکه مدل متفاوتی از روش فکر کردن هستش. تمرکز فانکشنال بر روی اینه که چی میخوایم نه اینکه چطوری باید انجام بشه.
فرض کنید «لیستی از اعداد داریم که باید مرتب بشن.»
چی میخوایم؟ میخوایم این لیست مرتب بشه
چطور باید انجام بشه؟ برای مرتب سازی الگوریتمهای مختلفی داریم که بعضا هر الگوریتم ممکنه به روشهای مختلف پیادهسازی بشن.
تمرکز تفکر فانکشنال روی اینه که چی میخوایم نه اینکه چطور باید انجام بشه. ما میخوایم این لیست مرتب بشه. حالا اینکه پشت پرده قراره چطوری پیادهسازی بشه، با چه الگوریتمی، به چه روشی و.. به ما ربطی نداره! یا لااقل در ابتدای کار ربطی نداره! اینجا دیگه خبری از پیادهسازی کلی if و for و... نیست.
فرض کنید «لیستی از دانشجوها داریم که باید دانشجوهایی که بالای ۲۲ سال هستن (بزرگتر مساوی ۲۲) رو پیدا کنیم».
روش اول:
var target = new List<Student>(); foreach (var student in students) { if (student.Age < 22) continue; target.Add(student); }
در این مسئله چی میخواستیم؟ اما چی کار کردیم؟! بجای اینکه بگیم ای کامپیوتر! برو و دانشجوهای بالای ۲۲ سال رو پیدا کن برام، گفتیم ببین کامپیوتر عزیز! اول یه لیست خالی از دانشجوها تعریف میکنی بگو خب! بعدش با یه حلقه foreach میری تک تک دانشجوها رو نگاه میکنی بگو خب! بعد اگر سن دانشجو کوچکتر از ۲۲ بود continue میکنی درغیراینصورت اون دانشجو رو به لیست target اضافه میکنی.
به کامپیوتر نگفتیم چی میخوایم، بهش گفتیم چطور انجام بده.
حالا روش دوم که سیشارپ کارها به خوبی باهاش آشنا هستن و فانکشنال هستش نگاه کنید.
روش دوم:
var target = students.Where(student => student.Age >= 22).ToList();
من میخوام دانشجوهایی که (where) بزرگتر مساوی ۲۲ هستن رو پیدا کنی و در آخر به لیست تبدیل کنی. من اینو میخوام دیگه چطوریش بهم ربطی نداره! (یا قبلا پیادهسازی شده یا بعدا پیادهسازی میکنم)
در این مثال، متد Where یه متد پایه، تستشده، خوانا و قابل استفاده هستش که میتونه در خیلی جاها استفاده بشه.
تفاوتها:
این روش به ما کمک میکنه با تمرکز کردن بر منطق برنامه، توابع/متدهای پایه و خوبی تولید کنیم که خوانایی بسیار بالایی دارن، تست شده و مطمئن هستن، قابلیت استفاده بسیار بیشتری دارن و سرعت کدنویسی ما رو بیشتر میکنن.
بیایین مثال قبلی رو کمی تعمیم بدیم. فرض کنید «لیستی از دانشجوها داریم که باید از بین دانشجوهای بالای ۲۲ سال، نفر دوم و سوم اونها رو از نظر معدل پیدا کنیم و اسمشون رو نمایش بدیم.»
اگر بخوایم به روش فانکشنال فکر کنیم، توی این مسئله چی میخوایم؟
ای کامپیوتر! میخوام دانشجوهایی که ۲۲ سال یا بزرگتر هستن رو پیدا کنی، بعد براساس معدل (زیاد به کم) مرتب کنی، بعد نفر اول رو بیخیال بشی، نفر دوم و سوم رو بگیری، بعد اسمشون رو برام جدا کنی.
خب بیایین همین چیزی که گفتیم رو بنویسیم. خوشبختانه اینجا زبان قدرتمند و مدرن سیشارپ رو هم داریم و میتونیم از متدهای خوبش استفاده کنیم.
var result = students .Where(student => student.Age > 22) .OrderByDescending(student => student.Average) .Skip(1) .Take(2) .Select(student => student.Name);
هورا! به همین سادگی. :)
اگر بخواین میتونید سورس کامل این مثال رو توی این لینک ببینید. توی متدی به نام Solution1 سعی کردم این مسئله رو به روش قدیمی حل کنم و در Solution2 به روش تفکر فانکشنال.
امیدوارم براتون مفید بوده باشه. :)
انشاءالله در پناه خدا همیشه صبور و شاد و موفق باشین.