Lazy در کاتلین | آشنایی با نحوه استفاده و هرآنچه که در کار با آن باید بدانید

Lazy در کاتلین | آشنایی با نحوه استفاده و هرآنچه که در کار با آن باید بدانید

نوشته شده توسط: نگین فاتحی
تاریخ انتشار: ۱۵ شهریور ۱۴۰۳
آخرین بروزرسانی: 16 شهریور 1403
زمان مطالعه: 9 دقیقه
۰
(۰)

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

ما در این مقاله جزئیات بیشتری را درباره Lazy در کاتلین مطرح خواهیم کرد؛ عنوان‌هایی مانند مفهوم Lazy در برنامه نویسی، نحوه استفاده از آن در کاتلین، کاربردهای Lazy، مزایا، مثال‌های کاربردی و غیره، تنها بخشی از مباحث پوشش داده‌شده در این مقاله هستند.

آموزش کاتلین برای برنامه نویسان اندروید نیک آموز

مفهوم Lazy در برنامه‌ نویسی چیست؟

Lazy در برنامه نویسی به‌معنای به تعویق انداختن یک عمل تا زمانی که لازم شود، است. معمولا عمل را در برنامه‌نویسی چهار چیز می‌دانیم:

  • اجرای تابع
  • ایجاد یک شی
  • محاسبه یک مقدار 
  • انجام برخی فرآیندهای سنگین

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

آشنایی با Lazy در کاتلین توسط یک مثال کاملا ساده

Lazy در کاتلین با نام «مقداردهی Lazy» یا “Lazy Initialization” هم شناخته می‌شود؛ اما اجازه دهید تشریح این مفهوم را در قالب یک مثال کاملا ساده و مشهود پیش ببریم:

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

اگر آن کودک را Lazy در کاتلین تصور کنید، احتمالا در این شرایط می‌گوید: «من یک جعبه اسباب‌بازی دارم، اما تا زمانی‌که نیازی به بازی با آن‌ها نداشته باشم، سمت‌شان نمی‌روم.» در این صورت او مجبور نیست تمام جعبه را همیشه با خود حمل کند.

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

برای استفاده از این تکنیک در کاتلین، باید متغیری تعریف کرده و نوع آن را lazy تعریف کنید.

کد زیر یک مثال ساده و واقعی را نشان می‌دهد که متغیر lazyValue از نوع string و lazy تعریف شده است:

 

val lazyValue: String by lazy {
    println("computed!")
    "Hello"
}
fun main() {
    println(lazyValue)
    println(lazyValue)
}

 

lazy() تابعی است که یک lambda را به‌عنوان پارامتر می‌گیرد. lambda پارامتری برای lazy است که در اولین فرصت دسترسی به ویژگی، اجرا می‌شود. نتیجه این دستیابی برای فراخوانی‌های بعدی ذخیره می‌شود.

Lazy پس از اجرای عمل، نمونه‌ای از Lazy<T> را برمی‌گرداند. این نمونه می‌تواند به‌عنوان نماینده‌ای برای اجرای یک ویژگی lazy عمل کند. 

۵ کاربرد Lazy در کاتلین

کاربردهای Lazy در کاتلین منجر به صرفه‌جویی در زمان و انرژی مصرفی توسط پردازنده می‌شود؛ اما این تکنیک کاربردهای دیگری در این زبان برنامه‌نویسی دارد که در ادامه آن‌ها را لیست خواهیم کرد.

  1. استفاده بهینه از مقدار دهی اولیه

Lazy برای مقداردهی اولیه اشیایی که از نظر محاسباتی سنگین هستند یا منابع فشرده‌ای نیاز دارند، بسیار مفید است. 

  1. بارگذاری سریع داده‌ های حجیم 

Lazy را می‌توان برای اجرا و بارگذاری داده‌‌های بزرگ و حجیم استفاده کرد. همچنین می‌توان از این تکنیک زمانی که داده‌ها باید از منابع خارجی مانند SQL Server یا APIها واکشی شوند، بیشترین بهره را برد.

  1. به‌خاطر سپاری نتایج توابع

Lazy را می‌توان برای “Memoization” استفاده کرد؛ تکنیکی برای ذخیره نتایج فراخوانی‌های توابع پیچیده. با استفاده از lazy، نتیجه تابع فقط یک‌بار محاسبه و در حافظه پنهان (Cache) ذخیره می‌شود. در فراخوانی‌های بعدی، تابع نتیجه ذخیره‌شده را برمی‌گرداند.

  1. مقدار دهی مشروط

Lazy مقداردهی اولیه را با توجه به خصوصیات شی و براساس شرایط خاص یا اقدامات کاربر انجام می‌دهد. 

  1. ارائه چند تکنیک برای محافظت از محیط‌ های گوناگون

این تکنیک مشهور حالت‌های مختلف Thread-safety را برای کنترل نحوه مقداردهی اولیه خصوصیت lazy ارائه می‌دهد. این حالت‌ها به شما امکان بهینه‌سازی ایمنی و عملکرد رشته‌ها را براساس نیازهای خاص خودتان می‌دهد.

۵ مورد از مزایای استفاده از Lazy در کاتلین

مهم‌ترین مزایای استفاده از Lazy در کاتلین را می‌توانیم در لیست زیر بگنجانیم:

  1. این امکان را به Runtime کاتلین می‌دهد تا دستورات و فرآیندهای غیرمرتبط با نتیجه نهایی را کنار بگذارد؛
  2. با کنار گذاشتن محاسبات و شرط‌های موقت، پیچیدگی زمانی یک الگوریتم را کاهش می‌دهد؛
  3. Lazy در کاتلین به برنامه‌نویس اجازه می‌دهد تا پس از مقداردهی اولیه، به اجزای ساختارهای داده‌ای نامنظم دسترسی پیدا کند. این دسترسی تا زمانی ممکن است که این ساختارها از هرگونه وابستگی زنجیروار (Circular Dependencies) آزاد باشند؛
  4. Lazy تکنیکی موثر برای بارگیری داده‌هایی است که در طول اجرای برنامه یا سایت، به‌ندرت به آن‌ها نیاز داریم؛
  5. به‌واسطه عدم پردازش و فراخوانی متدها یا متغیرهایی که فعلا به آن‌ها نیازی نیست، سرعت برنامه و سایت را افزایش می‌دهد.

مقایسه Lazy با دیگر الگوهای Initialization

در کنار تکنیک Lazy برای بارگذاری محتوا، سه تکنیک دیگر هم وجود دارند که در ادامه آن‌ها را با Lazy مقایسه خواهیم کرد.

مقایسه Lazy با Eager

Lazy مقداردهی اولیه یک خصوصیت را به تاخیر می‌اندازد؛ اما در بارگذاری به‌روش Eager، به‌محض اجرای کد، یک خصوصیت مقداردهی اولیه یا بارگذاری می‌شود. درواقع تکنیک Eager به‌محض اجرا، خصوصیت موجود را وارد و بارگذاری می‌کند. 

مقایسه Lazy با Lateinit 

  • Lateinit اجازه می‌دهد تا مقداردهی اولیه یک ویژگی را تا زمان دیگری به تاخیر بیندازید؛ در‌حالی‌که lazy خصوصیت را در اولین نیاز و دسترسی، مقداردهی اولیه می‌کند.
  • ویژگی‌های Lateinit باید به‌شکل “non-nullable” تعریف شوند؛ یعنی نمی‌توانند مقادیر null را نگه دارند. در مقابل، ویژگی‌های Lazy می‌توانند هم به‌صورت “nullable” – امکان گرفتن مقدار null – و هم “non-nullable” ساخته شوند.
  • خصوصیات Lazy به‌طور پیش‌فرض از نظر Thread ایمن هستند و تضمین می‌کنند که مقداردهی اولیه فقط یک‌بار، حتی در سناریوهای چندرشته‌ای انجام می‌شود؛ اما ویژگی‌های Lateinit مکانیسم‌های ایمنی داخلی ندارند.

مقایسه Lazy با Greedy

در تکنیک Greedy، ارزیابی به‌محض مواجهه با Expression انجام می‌شود؛ به‌همین‌دلیل یک روش مناسب برای محاسبات ساده و سریع است. همچنین Greedy استراتژی ارزیابی پیش‌فرض در کاتلین است؛ اما در Lazy ما شاهد عملکرد متفاوتی در تمام این موارد هستیم و برای استفاده از آن، باید از کلیدواژه “Lazy” استفاده کنیم.

۴ مثال‌ عملی از استفاده Lazy در کد کاتلین

در این بخش، چهار مثال کاملا عملی را از Lazy به‌همراه کد و توضیحات آن‌ها را آموزش خواهیم داد.

  1. Lazy در مجموعه داده‌ های حجیم

در این مثال، ما از Lazy برای واکشی داده‌های حجیم استفاده می‌کنیم.

 

class DataRepository {
    private val data: List<Data> by lazy {
        // Load data from database or API
        fetchDataFromSource()
    }
    fun getData(): List<Data> {
        return data
    }
}

 

  1. Lazy در ذخیره نتایج توابع

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

 

fun fib(n: Int): Int {
    val memo = mutableMapOf<Int, Int>()
    return fibInternal(n, memo)
}
private fun fibInternal(k: Int, memo: MutableMap<Int, Int>): Int {
    return memo.getOrPut(k) {
        if (k < 2) k else fibInternal(k - 1, memo) + fibInternal(k - 2, memo)
    }
}

 

  1. Lazy برای مقداردهی اولیه مشروط

در این نمونه با کمک Lazy، مقداردهی اولیه خصوصیات را براساس شرایط خاص یا اقدامات کاربر تنظیم می‌کنیم.

 

class SettingsManager {
    val darkMode: Boolean by lazy {
        // Check user preferences or system settings
        isDarkModeEnabled()
    }
    fun isDarkModeEnabled(): Boolean {
        // Implement logic to check if dark mode is enabled
        // ...
    }
}

 

  1. Lazy در مقدار دهی اولیه اشیا سنگین در محاسبات

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

 

class ExpensiveObject {
    companion object {
        val instance: ExpensiveObject by lazy {
            // Perform expensive initialization
            ExpensiveObject()
        }
    }
    // ...
}

 

نکاتی برای بهینه‌ سازی استفاده از Lazy در کدهای کاتلین

در این بخش، نکاتی برای بهینه سازی استفاده از Lazy را لیست کرده‌ایم. پیش از نوشتن هر اپلیکیشن برای اندروید یا وب‌سایت، حتما این لیست را یک‌بار مرور کنید.

  • از Lazy برای محاسباتی که منابع زیادی را صرف می‌کنند یا وقت‌گیر هستند استفاده کنید؛
  • برای مجموعه داده‌های بزرگ حتما از این تکنیک کمک بگیرید؛ زیرا مصرف حافظه را به‌طور موثری کاهش می‌دهد؛
  • برای خصوصیات ساده یا آن‌هایی که حداقل هزینه اضافی دارند، از Lazy استفاده نکنید؛
  • Lazy برای مجموعه داده‌های بی‌نهایت (Infinite Data Sets)، گزینه مناسب‌تری نسبت‌به سایر روش‌های مقداردهی است؛ زیرا مدیریت حجم زیادی از داده‌ها را آسان می‌کند؛
  • منطق مقداردهی اولیه در بلوک Lazy را مختصر و متمرکز نگه دارید. اگر این بلوک گسترده و پیچیده شد، آن را به یک تابع یا کلاس جداگانه تغییر دهید؛
  • هنگام استفاده از خصوصیات Lazy که به یکدیگر وابسته هستند، محتاط باشید؛ زیرا این وابستگی‌های زنجیروار (Circular Dependencies) می‌توانند منجربه بروز رفتارهای غیرمنتظره توسط برنامه یا پلتفرم شوند؛
  • هنگامی که خصوصیات Lazy بیش‌ازحد به یکدیگر وابسته شدند، آن‌ها را خرد کنید و کدهای کوتاه‌تری بسازید؛
  • خصوصیات Lazy برنامه را به‌طور کامل آزمایش کنید و مطمئن شوید که در طول مقداردهی اولیه، همان‌طور که انتظار می‌رود رفتار می‌کنند؛
  • برای شناسایی هرگونه عملکرد اشتباه در خصوصیات Lazy، برنامه خود را به Profile تبدیل کنید.

مشکلات و چالش‌ های استفاده از Lazy

اغلب مهندسان نرم‌افزار و توسعه‌دهندگان، تعدادی معایب را درباره Lazy نام می‌برند که منجربه افت عملکرد آن‌ها در فرآیند توسعه می‌شوند. در ادامه می‌توانید با این مشکلات و چالش‌ های استفاده از Lazy آشنا شوید:

  • زمان اجرا زبان برنامه‌نویسی را وادار می‌کند تا ارزیابی پارامترهای فرعی را به تاخیر بیندازد. این اجبار تا زمانی‌ ادامه پیدا می‌کند که پارامترها در نتیجه نهایی با ایجاد thunks (اشیاء تاخیری) لازم شوند؛
  • گاهی اوقات پیچیدگی فضای یک الگوریتم را افزایش می‌دهد؛
  • تشخیص و ارزیابی عملکرد آن بسیار دشوار است؛ زیرا فرآیندهای کوچک زیادی را شامل می‌شود که پیش از فراخوانی استفاده نمی‌شوند.

آنچه در Lazy در کاتلین خواندیم

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

چه رتبه ای می‌دهید؟

میانگین ۰ / ۵. از مجموع ۰

اولین نفر باش

گوش به زنگ یلدا
title sign
معرفی نویسنده
نگین فاتحی
مقالات
35 مقاله توسط این نویسنده
محصولات
0 دوره توسط این نویسنده
نگین فاتحی

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

title sign
دیدگاه کاربران