<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های davud hosseiny</title>
        <link>https://virgool.io/feed/@hosseinydavid</link>
        <description></description>
        <language>fa</language>
        <pubDate>2026-04-15 10:34:11</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/7181/avatar/1pkUI5.jpg?height=120&amp;width=120</url>
            <title>davud hosseiny</title>
            <link>https://virgool.io/@hosseinydavid</link>
        </image>

                    <item>
                <title>مهاجرت از دگر به Hilt به صورت دوره ای(شامل برنامه های Multi-module)</title>
                <link>https://virgool.io/@hosseinydavid/%D9%85%D9%87%D8%A7%D8%AC%D8%B1%D8%AA-%D8%A7%D8%B2-%D8%AF%DA%AF%D8%B1-%D8%A8%D9%87-hilt-%D8%A8%D9%87-%D8%B5%D9%88%D8%B1%D8%AA-%D8%AF%D9%88%D8%B1%D9%87-%D8%A7%DB%8C%D8%B4%D8%A7%D9%85%D9%84-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%87%D8%A7%DB%8C-multi-module-srwt4geau3nw</link>
                <description>Hiltاگر پروژه ای دارید که توش از دگر استفاده میکنید و نمیدونید مهاجرت به هیلت رو از کجا شروع کنید جای درستی اومدید. مخصوصا اگه پروژتون بزرگه و وقت مایگریت(مهاجرت) کردن همه قسمت ها به هیلت رو ندارید یا می‌خواید فقط قسمت های جدید رو با هیلت انجام بدید.ما توی این مقاله می‌خوایم راهی برای مهاجرت به هیلت به صورت قسمت قسمت برای پروژه هایی که با Component Dependencies کار میکنن معرفی کنیم.این مقاله برای کسایی که با دگر و هیلت ی مقداری آشنایی دارن مناسب هست. اگر شما با این کتابخونه‌ها آشنایی کافی ندارید میتونید قبلش سری به اینجا بزنید تا آشنایی بیشتری پیدا کنید.کمی پیش Google کتابخونه ی جدیدش به اسم hilt رو برای DI معرفی کرد. از ویژگی های این کتابخونه میشه به سادگیش و learning curve پایینش نسبت به دگر اشاره کرد.هیلت بر پایه ی دگر ساخته شده و در درونش از دگر استفاده میکنه. بخاطر همین این دوتا کتابخونه میتونن در کنار هم در ی پروژه استفاده بشن.این مقاله کمکتون میکنه پروژه ای که بر پایه ی دگر هست رو به صورت دوره ای به هیلت مایگریت کنید. یعنی مجبور نیستیم همه ی کدهای DI رو به هیلت مایگریت کنید و تیکه تیکه این کارو انجام می‌دیم.پیش فرض این مقاله اینه که پروژمون بر پایه ی Dagger Componentها ست و نه SubComponentها و ممکنه همش یا قسمت هاییش برای SubComponentها جواب نده.ما می‌تونیم یک یا چند component رو به هیلت مایگریت کنیم ولی بقیه componentها دگری باشند و کدهای قسمت هیلت و دگر با هم دیگه کار میکنن ولی این نکته رو باید بدونیم که کدهای قسمت دگر میتونن از کدهای هیلت استفاده کنن ولی برعکسش صادق نیست. کدهای هیلت نمیتونن به componentهای دگری وابستگی داشته باشن. بر همین اساس مهاجرت به هیلت رو باید از قسمت های پایه ای کدمون شروع کنیم. در درجه اول باید از کلاس Application شروع کنیم، چون این کلاس پایه ی ساخت گراف دگر هست.قبل شروع قسمت اصلی میخوام چندتا مفهوم رو که تو مقاله استفاده شدن با هم مرور کنیم:یک Binding: به طور کلی به هر شی که به گراف دگر اضافه میشه Binding میگیم. این مفهوم رو با انوتیشن Binds@ قاطی نکنید که یکسان نیستن.دوم EntryPoint: عنصری در هیلت وجود داره به اسم Entrypoint و این عنصر باعث میشه بتونیم Bindingها رو به خارج گراف هیلت ارائه بدیم (مثلا برای اینکه در دگر ازشون استفاده کنیم). از این لحاظ عملکرد Entrypoint شبیه Componentها ست. EntryPointها با انوتیشن EntryPoint@ مشخص میشن.سوم Componentهای پیش فرض هیلت: در هیلت ی سری Component به صورت پیش فرض وجود داره که با کلاس های اندرویدی متناظر هستن و LifeCycle یکسانی دارن(با هم ساخته و پاک میشن). مثلا FragmentComponent با Fragment متناظر هست. این Componentها که در زیر لیست شون اومده برای بسیاری از کاربردها کافیه و دیگه معمولا ما نیاز به نوشتن Custom Component نداریم. همچنین این Componentها Scopeهای متناظر‌شون رو هم دارن که تو جدول زیر لیست شدن:جدول تطابق Android class به Component/Scopeدر نتیجه ما دیگه در هیلت (معمولا) Component نمی‌نویسیم و فقط Module و EntryPoint می‌نویسیم و مشخص می‌کنیم که این  Module یا EntryPoint مربوط به کدوم یکی از Componentهای جدول بالا هست. برای مثال برای اینکه ماژول زیر در SingletonComponent اضافه بشه به صورت زیر عمل می‌کنیم:افزودن Bindingها به SingletonComponentخوب تعاریف تموم شد. بریم که پروژه رو هیلتی کنیم :)Let&#039;s Hilt thisبا فرض داشتن ی پروژه ی دگری که شامل ی سری Component که به هم Depend هستن شروع میکنیم و مراحل رو پیش می‌بریم.1. افزودن Dependencyهادر مرحله اول دیپندنسی های هیلت رو اضافه میکنیم: https://gist.github.com/DHosseiny/138a8d6b4e1a6d20dcdc23f2192cafea اگر از kapt استفاده نمیکنید kapt رو با annotationProcessor جایگزین کنید.اگر در گریدل-ماژولی که دارید روش کار میکنید کل کدهای اون ماژول رو به هیلت مایگریت خواهید کرد میتونید دپندنسی های دگر رو هم پاک کنید:هر کدوم از این dependencyها رو که دارید پاک کنید.اگر در ماژول تون از Workerها استفاده میکنید این دپندنسی ها رو هم اضافه کنید: https://gist.github.com/DHosseiny/8d5f6e2c1b03ec48d40e6b7d494523e3 اگر کامپوننت اندرویدی از جمله Activity, Service, Fragment یا BroadcastReceiver دارید plugin dagger.hilt.android.plugin رو هم به گریدل ماژول‌تون تو قسمت pluginها اضافه کنید: https://gist.github.com/DHosseiny/22cff05017dd42c4771907d3b3005248 حالا میریم سراغ کلاس Application و انوتیشن HiltAndroidApp رو بالاش اضافه می‌کنیم: https://gist.github.com/DHosseiny/f348e3e52809bfabdf88cefcd25d8ef6 اگر کلاس Applicationتون اینترفیس Configuration.Providerرو پیاده سازی میکنه و میخواید Workerی رو به Hilt مایگریت کنید به نکته آخر مقاله مراجعه کنید.۲- مهاجرت کامپوننتما اینجا یک کامپوننت رو به هیلت مایگریت میکنیم و بعد می‌بینیم که چطور یک کامپوننت دگر ازش میتونه استفاده کنه.نکته: فقط میتونید کامپوننت‌هایی رو به هیلت مایگریت کنید که dependency به ی کامپوننت دگری نداشته باشن(با استفاده از انوتیشین Component@ قسمت dependencies کامپوننت‌ها رو به هم depend می‌کنیم). اگر دارن اول باید اون dependency رو مایگریت کنید.برای مثال کامپوننت زیر رو در نظر بگیرید:مثال برای کامپوننتدر مرحله‌ی اول سراغ قسمت modules میریم. اگر در بین ماژول ها ماژول AndroidInjectionModule وجود داره پاکش کنید(در dagger-android ازش استفاده میشه).بعد میریم سراغ تک تک moduleها و اونها رو هم به هیلت مایگریت می‌کنیم. مایگریت ماژول ها رو پایین‌تر در مرحله ۳ گفتم و اگر ماژولی رو میخواید مایگریت بدید همین حالا سراغ مرحله ی ۳ برید. ?بعد مایگریت کردن همه ی ماژول‌ها می‌تونیم کل قسمت modules رو پاک کنیم:modules حذف قسمتدر مرحله‌ی بعد میریم سراغ bindingهایی(متدهایی) که کامپوننت تعریف کرده، که اینجا دوتا هستند.اگر کامپوننتی به این کامپوننت وابستگی داره، این متدها باید بمونن، اگر نه می‌تونیم حذفشون کنیم. تو این مثال فرض می‌کنیم که همچین کامپوننتی وجود داره.در مرحله بعد اگر کامپوننت اینترفیس AndroidInjector رو پیاده سازی میکنه اون رو هم حذف میکنیم:AndroidInjector پاک میشهدر مرحله‌ی بعد انوتیشن Component@ و هر چیزی که داخلش هست رو حذف میکنیم.حتی اگه Component@ قسمت dependencies داره اون رو هم حذف میکنیم. چون فرضمون این هست که کامپوننت‌های داخل قسمت dependencies قبلا به هیلت مایگریت شدن.اگر کامپوننت انوتیشن Scope داره اون رو هم حذف میکنیم و بجاش دوتا انوتیشن جدید میذاریم:انوتیشن EntryPoint@و انوتیشن InstallIn@. در این انوتیشن قراره مشخص کنیم که این کامپوننت برای چه کلاس اندرویدیی کار می‌کنه. مثلا اگه این کامپوننت قرار فیلدهای ی Activity رو Inject کنه از ActivityComponent استفاده می‌کنیم. به همین منوال برای همه کلاس های اندرویدی دیگه هم component از پیش تعریف شده‌ای وجود داره که همه شون رو توی جدول پایین آووردم:جدول کلاس های اندرویدی و کامپوننت متناظرشونحالت قبل و بعد از تغییر انوتیشن ها رو زیر میبینیم:قبل و بعدحالا دیگه DiscountCodeComponent ی کامپوننت نیست و در واقع EntryPoint هست ولی همونطور که بالاتر گفتیم کاربردی مشابه کامپوننت داره. در نتیجه اگر در ی کامپوننت دگری ازش به عنوان dependency استفاده شده لازم نیست روی قسمت دگر کاری بکنید. دگر میتونه از  Entrypoint جدیدمون مثل component قدیمی استفاده کنه. مثل بنز کار می‌کنه. حالا می‌تونید کامپوننت رو Renameش کنید و بجای Component، بنویسید EntryPoint.۳- مهاجرت ماژولخود حالا می‌خوایم ی ماژول رو مایگریت کنیم. برای مثال ماژول زیر رو در نظر بگیرید:مثال Module ۱. اگر ماژول دارای متدهایی هست که ViewModelی رو محیا میکنن اون متد رو حذف می‌کنیم و میریم سر کلاس ViewModel انوتیشن HiltViewModel@ رو اضافه می‌کنیم:حذف متد نشان شده۲. اگر ماژول دارای متدی هست که ViewModelFactoryی رو محیا میکنه اون رو هم پاک می‌کنیم:حذف متد نشان شده ۳. اگر ماژول دارای متدهایی هست که انوتیشن ContributesAndroidInjector@ دارند میریم سراغ کلاسی که داره return میکنه(Activity, Service, Fragment یا BroadCastReceiver) و کارهای زیر رو روش انجام میدیم:    ۱. بالای کلاس انوتیشن AndroidEntryPoint@ می‌زاریم.    ۲. اگر از ViewModelی در این کلاس استفاده شده که به هیلت مایگریت شده یا میخواد مایگریت بشه و برای ساختنش از ViewModelFactoryیی که Inject شده استفاده کردیم دیگه لازم نیست از ViewModelFactory استفاده کنیم. پس مثلا این:قبلمیشه این:بعدبه صورت پیش فرض برای ساختن ViewModelها از defaultViewModelProviderFactory استفاده میشه و خود هیلت defaultViewModelProviderFactory رو تغییر میده تا ViewModelها رو بتونه Inject کنه. اگر جایی به ViewModelFactory نیاز داشتیم(مثلا وقتی از StoreOwner غیر پیش فرض استفاده میکنیم)، میتونیم از defaultViewModelProviderFactory استفاده کنیم.نهایتا متد دارای ContributesAndroidInjector@رو هم از ماژولی که روش کار می‌کردیم پاک می‌کنیم:حذف متد نشان شده۳. اگر ماژول دارای متدی هست که Workerی رو می‌سازه مراحل زیر رو روش انجام میدیم:    ۱. میریم سراغ Worker و بالاش انوتیشن HiltWorker@ می‌زاریم.    ۲. اگر دارای اینترفیس با انوتیشن  AssistedInject.Factory@ هست اینترفیس رو پاک میکنیم.    ۳. متد مربوط به Worker در ماژول رو هم پاک میکنیم.    ۴. انوتیشن AssistedModule@ رو از بالای ماژول پاک می‌کنیم.تغییرات Worker (مراحل ۱ و۲)برای ادامه ماژول زیر رو به عنوان مثال در نظر بگیرید:۵. اگر بعد انجام مراحل قبل ماژول خالی از متد شد پاکش می‌کنیم. در غیر این صورت بالای ماژول بجز انوتیشن Module@ انوتیشن InstallIn@ رو با کامپوننت متناظرش اضافه می‌کنیم.در ماژول بالا داریم ی سرویس Retrofit رو محیا میکنیم که نمیشه حذفش کرد. به این ماژول در Activity نیاز داریم، در نتیجه InstallIn@رو با پارامتر ActivityComponent بهش اضافه می‌کنیم: افزودن InstallIn۶. اگر ماژول دارای متدهای هست که Custom Scope داره Scopeش رو به Scope متناسب با کامپوننت داخل InstallIn@تغییر می‌دیم. Scope متناسب با ActivityComponent اسکوپ ActivityScoped@ هست(بالاتر تو جدول لیست componentها و scopeهای جفت باهاشون رو آووردیم) :افزودن ActivityScopedتوجه داشتیم باشید که اگر از Scope اشتباهی استفاده کنید پروژه بیلد نمیشه. مثلا نباید وقتی از InstallIn(ActivityComponent::class)@ استفاده کردید، از اسکوپ FragmentScoped@ بالای متدی استفاده کنید.۴- حذف Scopeهمونطور که بالاتر در مثال کامپوننت دیدید ممکنه برای کامپوننت از Custom Scope استفاده کرده باشیم. مثلا اینجا از DiscountCodeScope استفاده شده: Custom Scope کامپوننت دارایگفتیم که در هیلت معمولا نیازی به Custom Scope نداریم. در نتیجه باید کارکردهای Custom Scope مورد نظر رو پیدا کرده و با Scope مناسب جابه جا کنیم. مثلا روی ی کلاس که با constructor Injection ساخته میشه هم از DiscountCodeScope استفاده کرده بودیم که به ActivityScoped تغییرش می‌دیم:استفاده از scopeهای پیش فرض هیلت در constructor injectionهمه ی استفاده‌های Custom Scope مورد نظر رو پیدا می‌کنیم و با scope مناسب جابه‌جاشون می‌کنیم تا استفاده ای از اون نمونه. بعد می‌تونیم خود اون scope رو هم پاک کنیم.5- دیگر نکاتدوتا نکته مونده که بهتون میگم:۱- اگر در ی گریدل ماژول هم از دگر و هم از Hilt استفاده می‌کنید باید به Hilt بگید که با Moduleهای دگری کاری نداشته باشه و اونها رو پروسس نکنه. این کارو با اضافه کردن یک flag در فایل buildمون انجام می‌دیم: https://gist.github.com/DHosseiny/03e6c172f91306b9d6ef11fb6bc64f0c ۲- اگر کلاس Applicationتون interface Configuration.Provider رو پیاده‌سازی می‌کنه و میخواید همه Workerها رو از دگر به هیلت مایگریت کنید باید کلاس HiltWorkerFactory رو inject کنید و در getWorkManagerConfiguration ازش استفاده کنید: https://gist.github.com/DHosseiny/406443373d8c495fda09026711f293b0 ولی اگر میخواید قسمتی از workerها رو به هیلت مایگریت کنید و از ی همچین کلاسی برای WorkerFactory در دگر استفاده می‌کنید، باید WorkerFactoryیه هیلت رو هم با دگر ترکیب کنید. این کلاس رو برای این منظور نوشتم: https://gist.github.com/DHosseiny/c3737d933133db10845bb2bd82de6770 حالا کلاس Application رو اینجوری تغییر بدید تا از AggregatorWorkerFactory استفاده کنه: https://gist.github.com/DHosseiny/f13c0a2fd00b327912d3dcacaf4d7124 احتمال داره ی سری متد با انوتیشن Binds@ در ماژول هاتون باقی مونده باشه. من پیشنهادم اینه که از لایببری hilt-binder استفاده کنید که خودش براتون این متدهای Binds@ رو تولید میکنه. این لایببری ی Hilt-extention هست و با استفاده از انوتیشنی که شما سر کلاساتون میزنید متوجه میشه که باید برای اون کلاس ماژول و متد Binds@ تولید کنه تا کار شما راحتتر بشه.و تمام :) تونستیم ی کامپوننت رو به هیلت مایگریت کنیم.مطالعه بیشتر:https://dagger.dev/hilt/migration-guide.htmlhttps://developer.android.com/codelabs/android-dagger-to-hilt</description>
                <category>davud hosseiny</category>
                <author>davud hosseiny</author>
                <pubDate>Thu, 08 Jun 2023 13:47:49 +0330</pubDate>
            </item>
                    <item>
                <title>تست نویسی چرا و چطور سری اول - &quot;چرا تست بنویسیم؟&quot;</title>
                <link>https://virgool.io/MobileLab/%D8%AA%D8%B3%D8%AA-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-%DA%86%D8%B1%D8%A7-%D9%88-%DA%86%D8%B7%D9%88%D8%B1-%D8%B3%D8%B1%DB%8C-%D8%A7%D9%88%D9%84-%DA%86%D8%B1%D8%A7-%D8%AA%D8%B3%D8%AA-%D8%A8%D9%86%D9%88%DB%8C%D8%B3%DB%8C%D9%85-m2rawqsgdsds</link>
                <description>داود ی برنامه نویس اندرویده. اون تازه کار نوشتن ی امکان جدید تو برنامه رو به اتمام رسونده و صدها خط کد به کدبیس برنامه اضافه کرده. داود برنامه رو اجرا میکنه، میره به صفحه مورد نظر که تغییرش داده و… کرشبرمیگرده سر کد با تعجب دقایقی صفحه مانیتور رو نگاه میکنه ی کم میخوندش و… آها. فراموش کرده که ی متغیر رو پر کنه. ی بار دیگه اجراش می­کنه و به همون صفحه میره. ورودی رو تو editText وارد می­کنه. هوم… برنامه &quot;سود&quot; رو درست محاسبه نکرده.دوباره برمی­گرده سر کد و این دفعه debuggerو روشن می­کنه. بعد از مدتی مشکلو می­فهمه. نسبت به دفعه قبل وقت بیشتری ازش میگیره.. این دفعه برنامه درست کار میکنه.این کار یعنی اجرا، تست دستی و رفع باگ حدود 20 دقیقه ای ازش وقت میگیره.زهرا، در مقابل کارش رو به روش دیگه ای انجام میده. اون هر بار که تغییر کوچیکی تو کد میده ی unit test هم براش می­نویسه که از سالم بودنش مطمئن بشه. زهرا بعد نوشتن هر تیکه­​ ی کد تستاش رو اجرا میکنه، تست ها در عرض چند ثانیه اجرا میشن بهمین خاطر نیازی نیست زهرا زیاد منتظر بمونه تا متوجه بشه میتونه بره سراغ تیکه ی بعدی یا نه.اگه مشکلی باشه زهرا سریع متوجه مشکل میشه و حلش میکنه. حل مشکلات تو روش اون نسبت به روش داود راحت ­تره، چون فقط لازمه تو قسمت کوچیکی از کد دنبال مشکل بگرده.اون تست هاش رو تو کدبیس ذخیره میکنه تا هر بار که تغییری تو قسمت خاصی داد، مطمئن بشه تغییر جدید امکانات قبلی برنامه رو خراب نمیکنه. اینطوری دیگه لازم نیست کلی زمان برای تست دستی امکانات موجود برنامه بزاره.(چون تست های قبلی هست و زهرا اونها رو همراه تست های جدید اجرا میکنه)در مورد فهم نحوه کار سیستم هم، تست های زهرا، برای بقیه اعضای تیم زمان می خره. وقتی علی می­پرسه: &quot;وقتی X و Y ترکیب میشن سیستم چطور کار میکنه؟&quot;، داود میگه: &quot;اوممم… اینطوریه که… راستش نمیدونم بزار کدو نگاه کنم.&quot; بعضی وقتا این کارش چند دقیقه زمان میبره، ولی اکثرا نیم ساعت یا بیشتر ازش زمان می گیره. ولی زهرا میره سراغ unit-testهاش و به جواب های لحظه ای می­رسه.(تست ها مفهوم کد نوشته شده رو آسون­​ تر از خود کد می­رسونن)اجرای روش زهرا به این آسونی هام نیست و مشکلاتی داره، ولی اگه دانش تست نویسی رو داشته باشیم، میشه از پس این مشکلات بر بیایم. ی راه خوب خوندن کتاب &quot;Pragmatic Unit Testing in Java 8 with JUnit&quot; که این داستان از این کتاب برگرفته شده.این سری اول از مجموعه ی &quot;تست نویسی چرا و چطور&quot; هست. منتظر قسمت های بعدی باشید.لینک کتاب نوشته Jeff Langr</description>
                <category>davud hosseiny</category>
                <author>davud hosseiny</author>
                <pubDate>Mon, 21 Dec 2020 21:52:29 +0330</pubDate>
            </item>
                    <item>
                <title>چطور از دست &quot;!!&quot; خلاص شیم</title>
                <link>https://virgool.io/@hosseinydavid/how-to-get-rid-of-null-assertion-bhyavpranqib</link>
                <description>اگر نیاز به آشنایی اولیه با کاتلین و نحوه تعریف نوع‌ها در اون رو دارید توصیه میکنم اول این مقاله رو بخونید. لازم هست قبل از خواندن با چند اصطلاح آشنا بشیم:mutable : تغییر پذیرimmutable : تغییر ناپذیرا NullSafety یکی از بهترین ویژگی های کاتلین هست. این ویژگی باعـث میشه که شما در سطح زبان برنامه نویسی به تهی پذیری (nullability) فکر کنید در نتیجه میتونید از بسیاری NullPointerException های مخفی که در جاوا معموله، خلاص بشید. وقتی از ابزارهای اتوماتیک برای تبدیل کد جاوا به کاتلین استفاده میکنید کلی !!(بخوانید دو علامت تعجب) میبینید. تا حد ممکن باید تعداد اونها رو کم کرد دلیلش اینه که !! به این معنی هست که &quot;در این نقطه پتانسیل وجود KotlinNullPointerException هندل نشده وجود داره&quot;.کاتلین مکانیزم های هوشمندانه ای برای رفع این مشکل داره، شاید با یکی یا چندتا از اونها آشنا باشید. ما اینجا 6 راه برای حل این مشکل معرفی میکنیم.1- استفاده از val به جای varکاتلین باعث میشه شما در سطح زبان به immutability فکر کنید و این خیلی عالیه. val فقط خواندنی و var (متغیر variable) قابل تغییر هست. توصیه میشه تا حد ممکن متغیرهاتون رو فقط خواندنی تعریف کنید. چون Thread safe هست و با برنامه نویسی تابعی هماهنگه. اگه متغیرهای val رو به صورت immutable به کار ببریم لازم نیست دیگه نگران تهی پذیری باشیم. در نظر داشته باشید val میتونه mutable هم باشه(اگر برای متغیرتون getter ننوشتید متغیرتون immutable هست و لازم نیست نگران چیزی باشید).2- استفاده از lateinitگاهی شما نمی‌تونید از متغیرهای immutable استفاده کنید. برای مثال در اندروید متغیری رو در نظر بگیرید که در onCreate مقداردهی میشه. برای این مورد kotlin کلمه کلیدی lateinit رو داره.شما میتونید این کد رو: https://gist.github.com/77c47875f9f758f872e13dd2987bfda7.git به این تغییر بدید https://gist.github.com/4b60a9be3917011db7d8f55ec7ca72d0.git در نظر داشته باشید اگه متغیر lateinit رو قبل از مقدار دهی استفاده کنید باعث خطا از نوع  UninitializedPropertyAccessException میشه.متاسفانه نمی​‌​​​​​توان متغیر lateinit از انواع داده primitive(مثل Int) تعریف کرد. برای این نوع داده‌ها میتونید از Delegates استفاده کنید:private var mNumber: Int by Delegates.notNull&lt;Int&gt;()3. استفاده از lazyبا استفاده از by lazy می​​​‌تونید متغیرهای immutable و تهی ناپذیر تعریف کنید، که در زمان مناسب مقدار دهی بشوند.مثال: https://gist.github.com/78e00bd6dac15ea8d577e8b79bcf8b09.git ا messageView فقط در اولین استفاده، با اجرای بلاک کد lazy مقداردهی میشه و در استفاده‌های بعدی همون مقدار مورد استفاده قرار میگیره.این طوری ما می‌تونیم حتی متغیرهایی که در لحظه ایجاد شدن شی آماده مقداردهی نیست‌اند(مثل ویوها در اندروید) رو هم immutable تعریف کنیم.4. استفاده از letکد زیر نمونه معمولی از ارورهای زمان کامپایل  تو کاتلین هست:اینجا Smart cast ممکن نیست.شاید همیشه براتون سوال شده باشه که چرا کامپایلر کاتلین اینجا نمیتونه Smart cast رو انجام بده. دلیلش اینه که ممکنه thread دیگه ای غیر از threadی که null بودن رو داره چک میکنه این متغیر رو null کنه.این مشکل آزار دهنده است. من این رو مطمئن ام که این متغیر نمیتونه بعد از چک برای null نبودن تغییر کرده باشه. خیلی از برنامه نویس‌ها این مشکل رو با !! سریع حل میکنن: https://gist.github.com/dd5ad562bf28c9ebaee5de088b4dc3f6.git اما راه حل بهتر برای این مشکل استفاده از متد let هست: https://gist.github.com/f7f4bf39089f0cfdfff470c9c580d718.git اگه mPhotoUrl نال باشه کد داخل let اجرا نمیشه.5. استفاده از Elvis operatorاگر ممکنه متغیر null باشه و ی مقدار پیش فرض جایگزین برای موقع null بودن در نظر گرفته اید Elvis operator خیلی به درد می‌خوره. ما میتونید این کد رو: https://gist.github.com/bc57427e3a931bcb376619143742628e.git به این تغییر بدیم: https://gist.github.com/731df413c7a04decc44c25ec92ff925f.git نتیجه اش اینه میشه که علاوه بر حل مشکل !! کد کمتر و تمیزتری داریم.(کد کمتر اکثرا با کد بهتر مترادفه :) )6. زیر پا گذاشتن مقرراتباز هم مواردی وجود داره که شما مطمئنید که متغیر با اینکه تهی پذیر هست نمی‌تونه null باشه و اگر null باشه ی باگی تو کدتون وجود داره که باید اصلاح بشه. با این حال !! به شما چیزی جز ی Exception بدون پیام که دیباگ کردنش مشکله نمیده. پس بهتره از متدهایی مثل requireNotNull یا checkNotNull به همراه پیغام خطای مناسب استفاده کنید که دیباگ کردن رو هم راحتتر میکنه.تغییر این کد: https://gist.github.com/b768016f18024427b3c788988f7e1dbb.git به این کد: اhttps://gist.github.com/35ba25bc013e7c5738f9f14d58e30993.git نتیجه گیریاگر از 6 تکنیک بالا استفاده کنید می‌توانید همه !!ها رو از کدتون حذف کنید. وقتی با این کار کد شما مطمئن‌تر، تمیزتر و دیباگ آن راحتتر خواهد بود. اگر راههای دیگه ای برای حذف !! میشناسید یا مشکلی در این مطلب هست تو کامنت ها بهم اطلاع بدید.</description>
                <category>davud hosseiny</category>
                <author>davud hosseiny</author>
                <pubDate>Sat, 19 May 2018 20:08:08 +0430</pubDate>
            </item>
            </channel>
</rss>