<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های SAJAD noroozi</title>
        <link>https://virgool.io/feed/@sjd.noroozi91</link>
        <description>کمی اندروید دولوپر کمی کنجکاو</description>
        <language>fa</language>
        <pubDate>2026-06-07 10:50:35</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/18312/avatar/avatar.png?height=120&amp;width=120</url>
            <title>SAJAD noroozi</title>
            <link>https://virgool.io/@sjd.noroozi91</link>
        </image>

                    <item>
                <title>Orchestrator Class</title>
                <link>https://virgool.io/@sjd.noroozi91/orchestrator-layer-nxzf8gty5e4n</link>
                <description>بعد از مدتها یه یادداشت کوچیک نوشتم تا یه مفهوم جذاب رو بررسی کنیم باهم اونم در سطح اپ های بزرگ پس اون چیزی که در ادامه پست بهتون ارائه میشه به شکل مشخص مختص اپ هایی هست که ساختار ماژولار بزرگ با ماژول های متعدد و در هم تنیدگی غیر قابل انکاری دارن پیش فرض:ما یه اپلیکیشن Clean Architect داریم اپ ما لاجیک نسبتا زیادی تو هر قسمت داره به شکلی که چند یوزکیس مختلف میتونن درگیر یک فلوی بیزنسی بشنچی شد که به این جا رسیدم؟درگیر یه مشکل معماری تو ذهنم بودم من یک فلو دارم تو پروژه ام که چندتا یوزکیس درگیرش میشن! تو ویو مدل مدیریتش کنم ؟ به نظرم نهبریم یه یوزکیس براش بسازیم ولی آخه این یوزکیسه واقعا؟؟ آره هست ولی مگه بست پرکتیس های ما همیشه نمیگن که یوزکیس باید اتمیک باشه حس میکنم هم هست هم نیست !   کلی هم گشتم و چرخیدم که ببینم ساختار دامین ماژول ها و ترکیب و تفکیک شون چطوری میتونه بهترین حالت رو تو پروژه های بزرگ ایجاد کنه چون حس میکردم یه چیزی هست که نمیدونم ! یا یادم رفته بعداز کلی سر و کله زدن با ai بهم گفت که ترکیب ماژول مشترک دامین و لوکال دامین ها راه حل خوبیه برای چیزی که تو ذهنته حالا برای مشکلت بهتره بعد با Orchestrator ترکیبش کنی و این ترکیب برنده ایه که توی UBER و SPOTIFY داره استفاده میشه و من اینجوری بودم که  فععععک نکنم  ولی بگو ببینم داستان این Orchestrator Layer چیه ؟؟یکم توضیح داد منم شروع کردم چرخیدن تو مدیوم و اینور اونور ببینم داستان چیه ! که خروجیش شد این پست حالا بریم سراغ اصل داستانمشکل چیه ؟ بیاید با یه سناریوی واقعی کار رو پیش ببریم تا بفهمیم مشکلمون چیه ! ماژول login شامل  LoginUseCaseماژول SharedDomains شامل  GetUserProfileUseCaseماژول settings شامل ApplyUserPreferencesUseCaseحالا یه نیاز بیزینسی داریم: «بعد از لاگین، پروفایل کاربر رو بگیر، تنظیماتش رو نگه دار  و بعد بفرستش به Home.»اگر این فلو رو تو LoginUseCase انجام بدی باید به SharedDomains  و settings دسترسی داشته باشی اولی اوکی ولی دومی وابستگی نابجا ایجاد میکرد یعنی login به همه چی وابسته می‌شه و از طرفی  فقط لاگین رو مدیریت نمیکنه(Violation of Separation of Concerns) خب من میخوام در لایه دامین بتونم این رو مدیریت کنم و انجامش بدم (چون به نظرم بیزنس لاجیکه) بدون اینکه لقمه رو دور سرم بچرخونم و باانتقالش به لایه های بالاتر بیزنس لاجیک رو در ویو مدل ویو یا جاهای دیگه دخیل کنم ! اژدها وارد میشود : اژدها وارد میشود  اژدها که بود و چه کرد؟ Orchestrator یه لایه یا کلاس واسطه که از UseCaseهای مختلف (از ماژول‌های مختلف) استفاده می‌کنه و اون‌ها رو طبق یک  (business flow) با هم هماهنگ می‌کنه  بدون اینکه این UseCaseها مستقیماً از وجود همدیگه خبر داشته باشن. بهش Composite UseCase یا Flow-Level UseCase هم میگن در اصل تو همیشه نیاز خواهی داشت که ترکیبی از عملکرد یوزکیس ها رو تو یه فلو داشته باشی و تجربه من میگه اکثرا این لاجیک رو بدون توجه به جنس بیزنسیش میارن لایه های بالاتر مدیریت میکنن ! مثلا ویو مدل !! در حالی که وظیفه ویو مدل باید محدود به مدیریت state  باشه نه منیج کردن ارتباط یوزکیس ها برای پیاده سازی بیزنس فلواینجا بود که فهمیدم بله کامپوزیت یوزکیس رو قبلا دیدم !چجوری هست حالا ؟مثلا اینجوری :     class LoginFlowOrchestrator @Inject constructor(
private val loginUseCase: LoginUseCase,
private val fetchProfileUseCase: FetchProfileUseCase,
private val applyUserSettingsUseCase: ApplyUserSettingsUseCase) {
 suspend fun execute(email: String, password: String): Result&lt;Unit&gt; {
     val loginResult = loginUseCase(email, password)
 if (loginResult.isFailure) return Result.failure(loginResult.exceptionOrNull()!!)
 val profile = fetchProfileUseCase()
 applyUserSettingsUseCase(profile.preferences)
 return Result.success(Unit)
 }
}خب حالا این هماهنگ کننده جاش کجاست در معماری کلین معمولا بین لایه دامین و UI قرار میگیره  پس میشه Ui به Orchestrator به Domainیه چیزی شبیه همون شوخی معروف باقرزاده تو اون فیلمه ! بهرحال راه درست بردن این لاجیک تو ویو مدل نیست و کار خوبی هم نیستدر اصل ما تو این حالت میایم Composite UseCase یا Flow-Level UseCase یا همون Orchestrator هامون رو از یوزکیس های ساده مون جدا میکنیم و تبدیلشون میکنیم به یه لایه جدید که در سطح بالاتری از یوزکیس هامون جا میگیرن تا بتونیم فلو ها رو کنترل کنیم و کنترل فلو های مربوط به بیزنس لاجیک رو نبرین تو لایه های بالاتر ! هرچند میشه تو خود دامین هم انجامش داد ولی اگر پروژه از یه حدی بزرگتر باشه و تعداد فلوی های پیچیده مون از یه اندازه ای بیشتر بشه منطقی تر اینه که لایه جداگانه ای داشته باشه به دلیل اینکه به نظر نمیرسه همیشه تو تمام ماژول هامون یک فلوی پیچیده رو تکرار کنیم ! ترجیحم این بود که لایه Orchestrator بیاد و بخشی از ماژول هامون بشه نه بخشی از دامین ماژول مشترک اپ که شامل یوزکیس های پر تکراره در نتیجه تو هر فیچر ماژولم از لایه دامین شروع کردم ( یوز کیس هایی اختصاصی فیچر ) و بعد تو لایه Orchestrator  میتونستم ترکیبی از یوز کیس های اشتراکی و اختصاصی رو باهم ترکیب کنم ! در نهایت یه نکته راجع‌به اسم Orchestrator:اینجا وقتی می‌گم Orchestrator یا Orchestrator Layer، منظورم یه لایه رسمی و مفصل توی معماری پیچیده و سطح بالا مثل میکروسرویس یا DDD نیست. منظورم صرفاً یه سری کلاس ساده‌ست که بین پرزنتیشن و دامین قرار می‌گیره و وظیفه‌ش اینه که چندتا یوزکیس از ماژول‌های مختلف رو کنار هم بچینه و با هم اجراشون کنه.یه جورایی نقش هماهنگ‌کننده‌ی یه بیزینس‌فلو رو بازی می‌کنه، بدون اینکه لاجیکش بره توی ویومدل یا یکی از یوزکیس‌ها.</description>
                <category>SAJAD noroozi</category>
                <author>SAJAD noroozi</author>
                <pubDate>Sun, 25 May 2025 10:18:07 +0330</pubDate>
            </item>
                    <item>
                <title>شی گرایی بدون خونریزی یاS.O.L.I.D  برای آنان که می اندیشند</title>
                <link>https://virgool.io/@sjd.noroozi91/solidprinciples-lpt7aaogncax</link>
                <description>مقداری پیش درآمد:از کجا و چطوری میشه گفت یه کد تمیزه و درست نوشته شده اصن قصه چیه به یه توسعه دهنده یه کد نشون میدی و میگه وای وای وای چه کد آزار دهنده و کثیفی و همون کد به یکی دیگه نشون میدی میگه نه خوب نوشته شده ! اصن کد تمیز یعنی چی؟ زمانی که داشتم برای پیداکردن موضوع پست جدید میگشتم دوتا موضوع توجهم رو جلب کرد یکی Tensorflow در اندروید و یکی هم معماری MVI ولی همین سوال کد تمیز یعنی چی؟ یه دفعه منو کشوند به سمت نوشتن این پستخب تا اونجایی که من بلدم کد تمیز پارامترهای خاص خودشو داره قابل تست بودن داشتن کامنت و نامگذاری های قابل درک و.... از نظر من کدی تمیزه که بشه طیف وسیعی از برنامه نویس های پلتفرم و زبان بدون تغییر ساختار و گیج شدن توسعه اش بدن این توسعه میتونه شامل اضافه کردن ویژگی های جدید برداشتن بخشی از کد به عنوان ماژول و.... باشه البته من نه صاحب نظر میدونم خودمو نه اونقدر سابقه و تجربه در خودم میبینم که بخوام بیام و یکی یکی توضیح و تفسیر ارائه بدم همین موضوع منو کشوند سمت کتابی که دوسال پیش خوندم The Clean Coder یا کد نویس تمیز که ترجمه هم شده و چقدر هم کتاب خوبی بود یکی از چیزیهایی که بی قید و شرط درکتاب ذکر شده که هربرنامه نویس عاقل و حرفه ای باید بلد باشه SOLID هست. ربطش به کد تمیز چیه؟ خب SOLID کمک میکنه یونیت تست رو راحتتر بنویسیم توسعه پذیری به شکل اصولی انجام بشه و تا حد زیادی کد خوانا تر بشه( این آخری رو براساس تجربه گفتم) خب من رفتم سراغ SOLID و تمام هم و غمم رو گذاشتم سر این موضوع که SOLID رو تا جایی که میتونم توی کد نویسیم رعایت کنم و بکار بگیرم نتیجه این شد که علاوه بر شفاف شدن پوستم دیدم خوانایی کدم برای خودم وقتی بعد از مدتها برمیگردم سر یه ماژول بالاتر رفته و عملا با تفکیک و تکنیک هایی که سالید داره کد واقعا تمیز تر میشه بگذریم از بحث تست نوشتن و اینکه تا چه اندازه قابل تست بودن کد با SOLID بالا میره .البته اینو بگم میشه به جرات گفت حتی توی بهترین نرم افزارهای دنیا هم سالید به شکل صددرصد و ایده آل خودش پیاده سازی نمیشه پس اگر فردا روزی رفتید پیش برنامه نویس ارشد تیم و ازش ایراد گرفتید چرا فلان فانکشن اصل دوم رو نقض میکنه ممکنه خیلی سخت باهاتون برخورد کنه در کل سالید وحی منزل نیست خیلی کمک میکنه که کد خوانا تر باشه قابل تست تر باشه و قابل توسعه تر شه ولی به جرات میتونم بگم توی این موضوع مته به خشخاش گذاشتن خیلی کار جالبی نیست ولی بطور کلی رعایت کردنش خیلی خیلی کمک میکنه و اگر قابل اندازه گیری باشه معمولا نه صددرصد استفاده میشه نه صفر بلکه کد هر نرم افزار حرفه ای بسته به نوع پروژه و توسعه دهنده اش میتونه خیلی کم یا خیلی زیاد رعایتش کنهخلاصه دیدم بهتره یه نیم نگاهی بهش داشته باشم و اینجا بنویسم درباره اش هرچند منابع فارسی خوب هم براش زیاده ولی من گاهی دوست دارم تفسیر خودم رو از یه موضوع بیان کنم  :S . O . L . I . D:سالید شامل پنج اصل اساسی در ساختار و طراحی یک برنامه شی گراست که باعث میشه علاوه بر قابلیت تست ساده کد بشدت انعطاف پذیر قابل توسعه و تمیز باشه هرکدوم از حروف انگلیسی که کلمه سالید رو تشکیل دادن حرف اول شروع اون اصلن یعنی شما اصلا نیازی نیست ترتیب و ترکیب خاصی رو یه جایی تو ذهنتون نگه دارید. این پنج اصل به شرح زیرن که البته به تفکیک و با مثال در ادامه درباره شون توضیح میدم :Single responsibility principleOpen–closed principleLiskov substitution principleInterface segregation principleDependency inversion principle اصل تک مسئولیتی:اصل تک مسئولیتی میگه که اگر شما قراره مقادیری رو جمع کنید یک تابع داشته باشید که فقط کارش جمع کردنه ! اگر قراره یک Json پارس شه یک فانکشن فقط مسئولیت پارس کردن داشته باشه فقط یک کار! همین. بدون اینکه هیچ اطلاعی داشته باشه از اینکه این داده ها از کجا اومده و خروجی قراره کجا بره ( یه جورایی در راستای انکپسولیشن کلاس هم هست ) شما نباید کد هوشمند بزنید قرار نیست تابع شما علاوه بر جمع کردن دوتا مقدار کنترل کنه که مقدار از یه حدی بیشتر یا کمتره قرار نیست بعد از جمع کردن نتیجه با چیزی مقایسه شه قرار نیست درون تابع چیزی رو کنترل کنید فرض کنید چنین کاری کردید چندمدل دیتا باید سمتش پاس داده شه تا شرایط مختلف توی یونیت تست مورد بررسی قرار بگیره؟ خیلی زیاد بازهم ممکنه پوشش صددرصدی برای عملکرد صحیح محسوب نشه. هرکدوم از این کارها باید تفکیک شه یک تابع برای مقایسه یک تابع برای اعتبار سنجی مقادیر ورودی و یک تابع برای جمع کردن اینجوری برای هر تابع  3-4 مدل ورودی توی یونیت تست احتمالا بتونه به شما اطمینان خاطر بیشتری بده که کدتون تا حد زیادی عملکرد مناسبی داره به عبارتی  هرچه تابعی که نوشتید باهوش تر باشه کنترل و تست کردنش سخت تره پس عملا با رعایت این قانون یک قدم به بهتر تست نوشتن نزدیکتر میشیم.یه نگاهی به شبه کد پایین بندازیدclass Customer
{
    public void Add()
    {
        try
        {
            // Database code goes here
        }
        catch (Exception ex)
        {
        Log.d(&amp;quotadd function exeption&amp;quot,ex.geterror.tostring());
                }
    }
} اگر دقت کنید میبینید فانکشن اضافه کردن مشتری علاوه بر انجام کار اصافه کردن مشتری کار لاگ انداختن رو هم انجام میده و این غلطه !زمان نوشتن بلاک های کدتون حتما اصل KISS رو بیادداشته باشید keep it simple, stupid  به هیچ وجه سعی نکنید همه کارها رو توی یک بلاک کد انجام بدید این کار باعث میشه زمان Debug  کردن به مشکل بخورید و از اون مهمتر تست نوشتن رو بشدت دشوار میکنه پس باز هم برای تاکید میگم هر کلاس و تایع دقیقا یک کار معین و مشخص تمام! علاوه بر اون با اینکار میتونید به reusability کدتون کمک کنید مثلا نیاز نیست هربار یک فرآیند رو جاهای مختلف تکرار کنید و اصطلاحا کپی کنید از طرفی اگر تو دیباگ مشکلی باشه میتونید فقط با یک تغییر در یک کلاس کل مشکل ( اینجا لاگ زدن) رو برطرف کنید حالا فرض کنید جاهای مختلف لاگ زدن رو کپی کرده باشید احتمال خیلی زیادی هست بالاخره یه جا از قلم بیافته و کدتون با باگ منتشر شهclass FileLogger
{
    public void Handle(string error)
    {
        Log.d(&amp;quotadd function exeption&amp;quot,ex.geterror.tostring());
    }
}
class Customer
{
    private FileLogger obj = new FileLogger();
    publicvirtual void Add()
    {
        try
        {
            // Database code goes here
        }
        catch (Exception ex)
        {
            obj.Handle(ex.ToString());
        }
    }
}اصل باز بسته :اسم عجیبی هست برای یک اصل طراحی شی گرا! خب فرض کنید قراره شما تابعی بنویسید که یک کد رو برای کاربر ایمیل کنه مدتی بعد تصمیم گرفته میشه که کاربر میتونه انتخاب کنه کد تایید اعتبارش به جای ایمیل براش SMS شه چه کار باید کرد؟ تجربه من میگه اکثرمواقع اصل اول و دوم باهم نقض میشه یعنی برنامه نویس میاد توی همون تابعی که قراره کد تایید اعتبار رو ایمیل کنه یه شرط درنظر میگیره که تحت شرایط یک تابع ارسال ایمیل صدا زده شه و تحت شرایط دو تایع ارسال SMS فراخوانی شه یعنی توی یک بلاک کد دو تا کار امکان انجام دارند! دوتا بلاک کدی که احتمالا بخش زیادی شون مشابه هست از طرفی شما تابعی رو که قبلا نوشتید دارید تغییر میدید به شکلی که یک تایپ به ورودی های اضافه میکنید و یک شرط مطمنید این تغییر فقط رو بخشی که باید اثر میذاره ؟ اگر بدون اطلاع دارید رو کد برنامه نویس دیگه ای کار میکنید این احتمال بشدت زیاده که یکی دو خط تغییر دو سه ساعت کار رو دستتون بذاره تا همه چیز رو مطابق شرایط فعلی تغییر بدید و هرچه شما تغییر ایجاد کنید باز هم جاهایی جدیدی هست که باید با شرایط جدید منطیق بشن درون یک چرخه بی نهایت یا سیاه چاله ای افتادید که اگر کد یک برنامه نویس دیگه باشه و پروژه نسبتا بزرگ یه ریفکتور خیلی زیبا براتون به ارمغان میاره چیکار باید کرد ؟اسم Open - closed  با یک جمله قابل تشریح هست : &quot;بلاک های کد (یا نهاد های نرم افزاری یا ماژولها یا کلاس ها و...) دربرابر اکستنشن و توسعه باز هستند و در برابر اصلاحات بسته&quot;. شما اجازه اصلاح تابع برای ارسال SMS  رو ندارید اما اجازه اضافه کردن تابعی برای ارسال SMS رو دارید ! و البته باید کدی که نوشته شده به شکلی باشه که &quot;اجازه توسعه بدهد و نیاز به تغییر دادن نداشته باشد&quot; یعنی هم باید زمان نوشتن کد اونها رو به شکل بسته بنویسیم هم زمان اضافه کردن قابلیت و تغییر اون ها رو بسته نگه داریم اگر کدی به ما اجازه بده که با ارث بری و... قابلیت به برنامه اضافه کنیم بسته است و اگر کدی این اجازه رو بده ما نده باز هستحس میکنم یکم پیچیده شد! بیاید یه جور دیگه به موضوع نگاه کنیم فرض کنید ما یه اینترفیس  authentication code داریم این اینترفیس کلا کارش جابجایی یک رشته هست که باید برای کاربر ارسال شه (چیزی که فانکشن درون اینترفیس انجام میده گرفتن کد اعتبار سنجی از یک کلاس و دادنش به کلاس دیگه هست همین !)خب حالا ما یک کلاس ارسال کد داریم که فقط ایمیل میفرسته میایم و با تغییر دادنش و اضافه کردن if یا switch بررسی میکنیم که کد برای کاربر ایمیل شه یا SMS و بعدش هم رخ عقاب میگیریم که به به تسک داون شد :| برای اینکار باید اینترفیس تغییر کنه و کلاسهای پیاده سازی کننده اش هم تغییر کنند اینجوری ما یک قطعه کد که اجازه توسعه میده ولی بسته است رو داریم باز میکنیم و این غلطه خب این کار به وضوح اصل دوم رو نقض میکنه و اصل اول رو زیر پا له میکنه ! چون هم تو کلاس تغییر ایجاد کردیم هم اینکه یک بلاک کد هوشمند داریم که تصمیم میگیره از چه طریق کد ارسال کنه!  چیکار کنیم؟ما یک کلاس جدید بوجود میاریم برای ارسال کد با SMS و باز هم اینترفیس توش Implement میشه و کد ارسال SMS درونش نوشته میشه اینجوری دوتا کلاس داریم توی کد قبل تغییری ایجاد نکردیم (که یک کد بسته بوده) بلکه قابلیت های تعیین شده رو گسترش دادیم (و بازش نکردیم) این به معنای واقعی کلمه رعایت اصل اول و دومه ! و اگر احیانا به بخش هایی از کلاس ارسال ایمیل نیاز داریم میتونیم از همون کلاس ارسال ایمیل اکستندش کنیم تا توابعی که از کلاس ایمیل نیاز داریم رو اینجا بتونیم داشته باشیم و توش تغییر ایجاد کنیم و باهاش SMS ارسال کنیم بدون اینکه ساختار ورژن قبلی کد رو با خطر ناپایداری و اون چرخه بی پایان که بالاتر گفتم مواجه کنیم چرا اینترفیس؟ بعدا میگم ولی تا همینجا توضیحات کافی هستمثال سوم ساده ترین مثال هست رو با کد توضیح میدم فرض کنید نیاز هست بسته به نوع زبان انتخابی کاربر در یک مرحله ما بهش پیغام خطا نشون بدیم class ٍError {
 public say(lang) {
 if (lang == &#039;pr&#039;) {
 return &#039;خطا&#039;; 
 } else if (lang == &#039;en&#039;) {
 return &#039;Error&#039;; 
 }  }}
Error obj = new Error;
console.log(obj.say(&#039;pr&#039;));تو قطعه کد بالا یک کد کاملا باز رو می بینید این ساختار برای اضافه کردن زبان سوم به هیچ عنوان راهی جز باز کردن کلاس نمیده پس عملا قابلیت توسعه رو از ما صلب کرده حالا چطوری باید نوشته شه ؟ به شکل زیر؟class ٍError { 
 public say(lang) 
}
public class persian {  
....
 return &#039;خطا&#039;;  
 } 
public class English{ 
.....
return &#039;Error&#039;; 
}
  Error obj = new Error; 
console.log(obj.say(persian))نکته : پیشرفت خوبیه برای اینکه اصل دوم نقض نشده ولی من باز هم میگم نه چرا؟ چون من میخوام توی تمام زبان ها حتما یک تعریف مشخص برای خطا ارسال بشه از طرفی اونقدر حرفه ای نیست که ما کلاسهایی شبیه هم داشته باشیم که خروجی های یکسانی ازشون میگیریم ولی ساختار و قالبی نداشته باشن که تضمین کنه خروجی به شکلی که من میخوام ارسال بشه از طرفی هر تغییر تو کلاسهایpersian یا english یا تغییر پیاده سازی زبانهای جدید میتونه روی Error اثر گذار باشه در حالی که Error یه کلاس سطح بالا و بالادستی هست این رو نگه دارد برای اصل پنجم به این موضوع برمیگردیم و حسابی بهش رسیدگی میکنیماصل لیسکوف: این اصل خیلی ساده تر و سر راست تره اگر شما کلاسی داشته باشید که از یک کلاس دیگه ارث بری کرده باشه (extend) شده باشه باید بتونید هرجا از کلاس والد استفاده کردید کلاس فرزند رو جایگزین کنید به عبارتی وقتی کلاسی رو می نویسید باید حداقل ویژگی ها رو شامل بشه و ویژگی هایی که ممکنه گاهی وجود نداشته باشن رو ازش حذف کنید و درکلاس های extend شده اش قرار بدیدفرض کنید ما کلاس A رو داریم که شامل یک فانکشن edit هست در جاهای مختلف ازش استفاده میکنیم و میخوایم حالا کلاسی بسازیم که editable نباشه و اسمش رو بذاریم B تفاوت اینه که کلاس اول قابل تغییر و ادیت و کلاس دوم غیرقابل تغییر و ادیت هست! و کلاس دوم یعنی  B از کلاس اول یعنی A ارث بری میکنه (Extend) شده وقتی کلاس B  رو در برنامه جایگزین A کنید وقتی نیاز به فراخوانی فانکشن Edit باشه یه مشکل بزرگ داریم اونم اینه که تو کلاس B هیچ فانکشن editی وجود نداره و کاربر با EXception روبرو میشه ! راه حل چیه؟ اینکه از اول توی کلاس A ادیت نداشته باشیم بلکه فقط ویژگی هایی رو در کلاس A داشته باشیم که بی کم و کاست در تمام کلاسهای فرزندش تکرار بشن و وقتی به چیزی شبیه edit نیاز بود یک کلاس جدید با این ویژگی ایجاد کنیم که از A ارث بری میکنه مثال زیر رو ببینید:public class A {
// this is Parent class
void read()
void getinstance()}public class c extends A{
// editable One
void edit()
}public class B{
// not editable one
....
}A a=new A()   
a.read()را میتوان به اشکال زیر نوشت بدون اینکه مشکلی بوجود بیایدb.read()c.read()اصل تفکیک اینترفیس ها :این اصل از ساده ترین اصول این لیست هست که میگه اگر شما یک interface رو در یک کلاس implements کردید لزوما باید تمامی فانکشن های تعریف شده در interface در این کلاس پیاده سازی داشته باشند این اصل ساده میگه که اگر شما اینترفیسی دارید که توی چند کلاس اون رو پیاده سازی میکنید و توی هر کلاس فقط بعضی از فانکشن ها دارای کد و پیاده سازی اند شما مشکلی به نام fat interface دارید و به عبارتی ساختاری در کلاس شما وجود داره که به اون نیاز ندارید به عنوان مثال اگر یک اینترفیس داشته باشیم که شامل 4 فانکشن show-edit-save-read باشه تمام کلاس ها پیاده کننده باید از هر 4 فانکشن استفاده کنند اگر فقط یک کلاس نیاز به edit نداشته باشه باید edit  در اینترفیس دیگری قرار بگیره و کلاس هایی که بهش نیاز دارند هر دو اینترفیس رو پیاده سازی کنند در ساده ترین تعریف اگر فانکشن F رو در اینترفیس A دارید که بعضی کلاسهای پیاده کننده اینترفیس بهش نیاز ندارند و بدنه اون خالی میمونه باید F رو به اینترفیس B منتقل کنید  هرجا نیاز به پیاده سازی F بود هر دو اینترفیس A و ‌B رو پیاده سازی کنید و هرجا نیاز به F نبود فقط A رو پیاده سازی کنید همین!وارونگی وابستگی :این شاید پیچیده ترین اصل این 5 تا باشه پس باید یکم با دقت بیشتری بررسی شه در اصل دوم من یک راه حل ارائه دادم و گفتم این حداقل نیاز ها رو برطرف میکنه ولی پیاده سازی کاملا صحیحی نیست فقط حداقل اصل دوم رعایت میشه و راه حل دومی وجود داره که بهتره و در پایان مقاله درباره اش بحث میکنیم ! دلیل حداقلی بودنش وابستگی کلاس سطح بالاتر به  کلاس های سطح پایینه ! این یعنی چی؟ و راه حل بهتر چیه؟انتزاع: ما بخش های در برنامه داریم شامل abstract calsses و intrface که اینها به خودی خود اجرا نمیشن بلکه قالب یک کلاس قابل اجرا میشن یعنی میشه اونها رو به عنوان ساختار به یک کلاس معرفی و پیاده سازی کرد کاری به تفاوت این دو ندارم موضوع بیشتر انتزاع هست! در انتزاع  ما تصور میکنیم این قاعده و ساختار باید باشد فارغ از نوع پیاده سازی جزییات مثلا در اینترفیس مثال اصل دوم باید showError در تمامی کلاس های پیاده کننده وجود داشته باشد فارغ از نوع پیاده سازی جزییات هر کلاس ( در این مثال فارغ از نوع زبان)کلاس سطح بالا و پایین : در ساده ترین تعریف ممکن کلاس های سطح بالا تعیین کننده روال ها در برنامه اند اینکه داده از کجا بیاید به کجا برود نتیجه این کار به کجا فرستاده شود مثلا اگر نیاز به حذف یک رکورد از دیتا بیس باشد کلاسهای سطح بالا تصمیم میگیرند رکورد وارد شده به کجا برود نتیجه موفقیت آمیز یا عدم موفقیت آن پس از بازگشت به کجا ارسال شود ! در اندروید ViewModel ها مثال خیلی خوبی برای کلاس های سطح بالا هستند آنها مستقیما به دیتا بیس کوئری ارسال نمیکنند یا مستقیما یک Json دریافتی را parse نمیکنند بلکه تصمیم میگیرند چه بخش از json پارس شده که الان به شکل یک آبجکت است به کجا برود در مقابل کلاسهایی که کوئری میزنند دریافت و ارسال اطلاعات را انجام میدهند و.... همگی کلاسهای سطح پاییند که به نوعی پیاده کننده نیازهای کلاسهای سطح بالاترندحال اگر در یک کلاس سطح بالا نیاز باشد که از کلاس دیتا بیس فانکشن ذخیره یک داده صدا زده شود باید در کلاس سطح بالا یک آبجکت از کلاس سطح پایین ساخته شود این یعنی وابستگی کلاس سطح بالا به کلاس سطح پایین! و هر تغییر در کلاس سطح پایین نیاز به اعمال تغییر در کلاس سطح بالا دارد! اصل دقیقا بیانگر این است که این رابطه باید تغییر کند! در وارونگی وابستگی بیان میشود کلاس های سطح بالا نیاد به کلاسهای سطح پایین وابسته باشند بلکه باید به کلاسهای انتزاعی سطح پایین وابسته باشندحالا بیاید برگردیم به مثال آخر اصل دوم که گفتم به دلایلی این راه حل خوب نیست و تغییرات کلاس های پایین دستی مثل Persian میتونه باعث شه که شما برید و تو کلاس بالا دستی ٍError تغییرات اعمال کنید تو مثال زیر راه حل کامل و درستش رو میبینید که علاوه بر اصل دوم اصل پنجم هم توش رعایت شده کلاسهای زبانها با کمک یک لایه انتزاع یعنی LanguageInterface پیاده سازی شدن و کلاس Error به جای وابستگی به کلاسهای مختلف مثل persian و english به یک اینترفیس ( انتزاع ) وابسته است interface LanguageInterface { public String showError()}
 class ٍError {   public say(LanguageInterface lang)  } 
 public class persian implements LanguageInterface {    
public String showError(){ 
  return &#039;خطا&#039;;   
  }  } 
public class English implements LanguageInterface{   
public String showError(){   
 return &#039;Error&#039;;   
   }  } 
 Error obj = new Error;  console.log(obj.say(persian))خب همونطوری که مشخصه وقتی میخوای تو کلاس Error یک ارور نمایش بدم نیاز به تعریف ابجکت از کلاس پایین دستی نیست چرا؟ چون English و persian به شکل زیر تعریف میشن! اینجوری کلاس Error دیگه به Persian یا English وابسته نیست بلکه به LanguageInterface وابسته استLanguageInterface persian=new Persian()
LanguageInterface english=new English()نکته مهم : راه حل های متفاوتی برای پیاده سازی وارونگی وابستگی هست که یک مدلش رو دربالا دیدید ولی متدی هست که فکر کنم همه باهاش آشناییم به نام Dependency Injection اینجوری که شما تو یه لایه جداگانه آبجکت های کلاسهای سطح پایین رو ایجاد میکنید و آبجکت ها به شکل ورودی های از قبل ایجاد شده به کلاسهای سطح بالا تزریق میشن اینجوری نیازی هم به Interface به این شکل نداریم یکی از مهمترین کتابخونه های برای پیاده سازی این متد Dagger  هست که توی جاوا و اندروید حسابی به کار میاد!سخن پایانی:بالا گفتم که منابع فارسی زیادی برای توضیح این اصول وجود داره اصولی که برای برنامه نویسی شی گرا ضروری هستند و هر برنامه نویسی که با زبانهای شی گرا کار میکنه باید بتونه اینها رو تشخیص بده به کار ببنده و پیاده سازی کنه دلیل نوشتن این متن شرح و بسط موضوع از نگاه خودم بود قطعا ولی دلیل مهمترش اینه که خیلی وقتها برنامه نویسهایی میبینم که شاید بشدت آپدیتن میتونن به شما بگن ورژن آخر کتابخانه فلان دقیقا چنده و مثلا تو کنفرانس آخر Google IO چه چیزی معرفی شده و چیکار میکنه ولی وقتی سراغ اساسی ترین اصول توی کدشون بگردید ناامید میشید پس اصول خیلی مهمن:) امیدوارم براتون راهگشا باشه!از وقتی که برای  مطالعه گذاشتید متشکرم </description>
                <category>SAJAD noroozi</category>
                <author>SAJAD noroozi</author>
                <pubDate>Sat, 28 Nov 2020 01:02:03 +0330</pubDate>
            </item>
                    <item>
                <title>فی مصائب نشت حافظه در اندروید یا فرار از تله مموری لیک(بخش دوم)</title>
                <link>https://virgool.io/MobileLab/%D9%81%DB%8C-%D9%85%D8%B5%D8%A7%D8%A6%D8%A8-%D9%86%D8%B4%D8%AA-%D8%AD%D8%A7%D9%81%D8%B8%D9%87-%D8%AF%D8%B1-%D8%A7%D9%86%D8%AF%D8%B1%D9%88%DB%8C%D8%AF-%DB%8C%D8%A7-%D9%81%D8%B1%D8%A7%D8%B1-%D8%A7%D8%B2-%D8%AA%D9%84%D9%87-%D9%85%D9%85%D9%88%D8%B1%DB%8C-%D9%84%DB%8C%DA%A9%D8%A8%D8%AE%D8%B4-%D8%AF%D9%88%D9%85-tpvyhymwpxns</link>
                <description>همونطور که تو پست قبلی قولش رو داده بودم تو اولین پست درمورد مموری لیک صحبت کردم و گفتم چطوری بوجود میاد و چرا باید مراقبش باشیم و چطوری قابل تشخیص هست این رو هم گفتم که معمولا براساس خطاهای برنامه نویس اشیائی بوجود میاد که نمیشه با garbage collector از بینش برد و....  معمولا یه سری اشتباهات رایج هست که باعث میشه نشت حافظه بوجود بیاد و تو این بخش  این دسته از اشتباهات رایج و سناریو های معمول رو بررسی می کنیم اگر قسمت قبل رو نخوندین بهتون پیشنهاد میکنم حتما نگاهی بهش بندازید:فی مصائب نشت حافظه در اندروید یا مموری لیک چیست؟(بخش اول)broadcast receivers (دریافت کننده های سراسری):خب broadcast receiver جایی استفاده میشن که لازمه توی برنامه چک کنیم مثلا باطری خالیه یا صد در صد پره یا گوشی تازه بوت شده یا خیر و...سناریو:سناریو این هست که ما توی یک اکتیویتی یک broadcast receiver ایجاد کرده و رجیستر کردیم ولی یادمون رفته تو stop این broadcast receiver رو آن رجیستر یا غیرفعال کنیم این یک نمونه واضح از مموری لیک هست چون حتی زمانی که شما اکتیویتی رو ببندید باز هم اون رفرنس و اون فضای اشغال شده باقی خواهد ماند راه حل راه حل بسیار ساده است شما باید حتما توی  اکتیویتی broadcast receiver رو آن رجیستر کنید و کل این کار تو کمتر از یک خط  انجام میشه بطور کلی پیشنهاد میشه که broadcast receiver رو در   on resume و  On start رجیستر کنید و در on destroy  ان رجیستر Static Activity or View Referenceسناریو:فرض کنید نیاز هست که با یک edittext در اکتیویتی کار کنید اما بیاید و edittext  رو بنا به هر دلیل و منطقی که ممکن داشته باشید به صورت static تعریف کنید در این صورت GC توانایی برگردوندن حافظه رو از اون ویو نخواهد داشت و مشکل نشت حافظه بوجود میاد راه حل هرگز ویو اکتیویتی و کانتکست رو به صورت استاتیک تعریف نکنید هرگز چنین کاری نکنیدContextاگر بخوام به سادگی توضیح بدم دو نوع context در اندروید وجود داره یکی UI با حجم بیشتر وسربار بیشتر که برای کارهایی ازجمله inflate کردن استفاده میشه و دیگری non-Ui که سبک تر هست و برای کارهای دیگری که فرايند طولانی تر دارند یا ارتباطی به UI ندارن استفاده میشه بحث Context پیچیدگی های خاص خودشو داره و ترجیح میدم برای خارج نشدن از مسیر اصلی خیلی درگیرش نشیم سناریو :در نظر بگیرید که کلاسی داریم که کارش خوندن دیتا از حافظه هست یا کارش به گونه ای هست که باید از singleton Class استفاده کنید و دقیقا برای این کار به Context احتیاج داره ماهم از اونجایی که توی یک اکتیویتی داریم این فراخوانی  سینگلتون کلاس رو انجام میدیم با خیالت راحت getactivitycontext رو پاس میدیم نتیجه؟ نشت حافظه راه حل:هرجا که نیاز به استفاده از Context وجود داشت جز در مواردی که context مستقیما درگیر المان های UI هست باید از getapplicationcontext استفاده کنید دقت کنید که getcontext و getactivitycontext هردو از نوع UI هستند و در صورتی که به کلاس های سینگلتون یا کلاسهای درگیر هرنوع فرایند طولانی مدت ارسال بشن نشت حافطه ایجاد میکنن میشه برای جاهایی که حتما باید از UI context استفاده کرد context رو ارسال کرد و بلافاصله بعد از استفاده ازش مقدارش رو null کرد هرچند روش دوم توصیه نمیشه WEAK Referenceبدون شک سخت ترین قسمت این مقاله چه برای نوشتن چه برای درک و بکارگیری همین بخش هست بهتون پیشنهاد میکنم اگر با این نوشته نتونستید درک درستی از موضوع داشته باشید حتما به مقالات مرتبط با پرفرمنس در اندروید و رفرنس ها در جاوا مراجعه کنید چون همین جا می پذیرم احتمالا مطلب یکم سخت تر از موضوعات قبلی باشه بطور کلی 4 نوع از رفرنس در جاوا وجود داره strong -weak-soft-phantomزمانی که دارید یک شی از یک کلاس ایجاد میکنید و یا مقداری در constructor میگیرید شما یه ارتباط و یک نوع معرفی مبدا انجام میدید ! این معرفی مبدا رو بهش میگن رفرنس دهی که البته خیلی ها برای ساده تر شدن فقط نوع strong و weak رو در نظر میگیرن و به دوتای دیگه کار زیادی ندارن اینجا هم کل بحث ما پیرامون همین دو نوع رفرنس هست بهتره برای واضح شدن ادامه مطلب نگاهی به این دو سبک و نوع رفرنس دهی داشته باشیم رفرنس دهی قوی یا strong :این همون نوع رفرنس دهی و ایجاد شی ساده در جاوا هست و احتمالا همه به عنوان شکل استاندارد ایجاد شی میشناسنش میتونید به مثال پایین یه نگاهی بندازید تا متوجه بشید دقیقا از چه چیزی حرف میزنیم !MyObject object = new MyObject();خب این نوع ایجاد ابجکت برای ما شیئی رو بوجود میاره که GC توانایی از بین بردنش رو نداره و به اصطلاح strong reachable هست خب تا اینجا همه چیز عالیه ما هم دقیقا همینو میخوایم که شی ایجاد شده رو در بالاترین حد دسترسی نگه داریم اینکه مشکل کجا بوجود میاد رو بعد از بررسی weak reference توضیح میدم پس فعلا تا همینجا بشناسیدش :)رفرنس دهی ضعیف یا weak:این نوع رفرنس دهی تقریبا مشابه نمونه بالاست با این تفاوت که GC توانایی از بین بردنش رو داره و اجازه نمیده که درون حافظه باقی بمونه نمونه تعریفش هم به این شکل هست :private WeakReference&lt;MyObject&gt; object= new WeakReference&lt;&gt;(object);خب حالا ببینیم کجا ها باعث ایجاد مشکل میشه تقریبا تمامی موارد بعدی که درباره نشت حافظه درباره شون بحث میکنیم مستقیما به همین رفرنس دهی اشاره دارن پس اگر متوجه نشدید مفهوم چیه یا دوست دارید بیشتر درباره اش بخونید حتما یه سر به اینجا و اینجا بزنید مشکل زمانی ایجاد میشه که شما یک اکتیویتی یا المان ویو رو به یک کلاس داخلی دیگه پاس میدین و توی کلاس دوم المان مورد نظر مثلا edittext ما به صورت strong reference تعریف شده کار شما انجام میشه اما به نشت حافظه میخوریدتاکید اول :هرگز یک اکتیویتی یا ویو و المان های درونش رو به صورت strong reference در کلاس دیگه تعریف نکنید هرگز این کار رو نکنید چون مانع پس گرفتن حافظه از اون اکتیویتی بعد از پایان کارش میشید ! هرگز این کار رو نکنیدتاکید دوم : اگر یکی از این موارد زیر رو استفاده میکند به هیچ عنوان حتی به ذهنتون خطور هم نکنه که المان های UI مربوط به ویو و اکتیویتی درونشون به صورت  strong reference معرفی کنید هرگز به این چنین کاری فکر نکنید   در ادامه میتونید چندتا نمونه از اشتباهات رایج مربوط به رفرنس دهی المان های UI  رو مشاهده کنیدinner classesthreadsrunnabletimertaskHandlerasynctasks1 . AsyncTaskپیاده سازی غلط :public class AsyncTaskReferenceLeakActivity extends AppCompatActivity {

    private TextView textView;
    private BackgroundTask backgroundTask;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_first);

        /*
         * Executing AsyncTask here!
         * */
        backgroundTask = new BackgroundTask(textView);
        backgroundTask.execute();
    }

    /*
     * Couple of things we should NEVER do here:
     * Mistake number 1. NEVER reference a class inside the activity. If we definitely need to, we should set the class as static as static inner classes don’t hold
     *    any implicit reference to its parent activity class
     * Mistake number 2. We should always cancel the asyncTask when activity is destroyed. This is because the asyncTask will still be executing even if the activity
     *    is destroyed.
     * Mistake number 3. Never use a direct reference of a view from acitivty inside an asynctask.
     * */
 private class BackgroundTask extends AsyncTask&lt;Void, Void, String&gt; {    
        @Override
        protected String doInBackground(Void... voids) {

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return &amp;quotThe task is completed!&amp;quot
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            textView.setText(s);
        }
    }
}پیاده سازی صحیح :public class AsyncTaskReferenceLeakActivity extends AppCompatActivity {

    private TextView textView;
    private BackgroundTask backgroundTask;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_first);

        /*
         * Executing AsyncTask here!
         * */
        backgroundTask = new BackgroundTask(textView);
        backgroundTask.execute();
    }


    /*
     * Fix number 1
     * */
    private static class BackgroundTask extends AsyncTask&lt;Void, Void, String&gt; {

        private final WeakReference&lt;TextView&gt; messageViewReference;
        private BackgroundTask(TextView textView) {
            this.messageViewReference = new WeakReference&lt;&gt;(textView);
        }


        @Override
        protected String doInBackground(Void... voids) {

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return &amp;quotThe task is completed!&amp;quot
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
          /*
           * Fix number 3
           * */          
            TextView textView = messageViewReference.get();
            if(textView != null) {
                textView.setText(s);
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        /*
         * Fix number 2
         * */
        if(backgroundTask != null) {
            backgroundTask.cancel(true);
        }
    }
}2 . Threads پیاده سازی غلط public class ThreadReferenceLeakActivity extends AppCompatActivity {

    /*  
     * Mistake Number 1: Do not use static variables
     * */    
    private static LeakyThread thread;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_first);

        createThread();
        redirectToNewScreen();
    }


    private void createThread() {
        thread = new LeakyThread();
        thread.start();
    }

    private void redirectToNewScreen() {
        startActivity(new Intent(this, SecondActivity.class));
    }


    /*
     * Mistake Number 2: Non-static anonymous classes hold an 
     * implicit reference to their enclosing class.
     * */
    private class LeakyThread extends Thread {
        @Override
        public void run() {
            while (true) {
            }
        }
    }پیاده سازی صحیح :public class ThreadReferenceLeakActivity extends AppCompatActivity {

    /*
     * FIX I: make variable non static
     * */
    private LeakyThread leakyThread = new LeakyThread();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_first);

        createThread();
        redirectToNewScreen();
    }


    private void createThread() {
        leakyThread.start();
    }

    private void redirectToNewScreen() {
        startActivity(new Intent(this, SecondActivity.class));
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // FIX II: kill the thread
        leakyThread.interrupt();
    }


    /*
     * Fix III: Make thread static
     * */
    private static class LeakyThread extends Thread {
        @Override
        public void run() {
            while (!isInterrupted()) {
            }
        }
    }
}و البته میتونید مثال های بیشتر رو در این مقاله ببینید سعی من زمان نوشتن این دو پست باز کردن موضوع و بررسی بیشترش بود بخش های زیادی از این دو پست صرفا ترجمه مقالاتی بود که خوندم و تو خود متن و منابع لیک مقالات هست میتونید بهشون مراجعه کنید تلاشم هم اول ایجاد محتوای قابل درک و ساده به زبان فارسی بود و دوم بررسی دقیق تر و کنار هم چیدن پازل هایی که از جاهای مختلف تو اینترنت قابل دسترسی هستن در صورتی که سوالی مطرح بود یا احیانا ایرادی در نوشته دیدین ممنون میشم که تو کامنت ها یادآوری کنید مرسی از وقتی که گذاشتید منابع : https://android.jlelse.eu/9-ways-to-avoid-memory-leaks-in-android-b6d81648e35e  https://android.jlelse.eu/memory-leak-patterns-in-android-4741a7fcb570  https://blog.aritraroy.in/everything-you-need-to-know-about-memory-leaks-in-android-apps-655f191ca859  https://instabug.com/blog/how-to-fix-android-memory-leaks/ </description>
                <category>SAJAD noroozi</category>
                <author>SAJAD noroozi</author>
                <pubDate>Tue, 03 Sep 2019 19:19:49 +0430</pubDate>
            </item>
                    <item>
                <title>فی مصائب نشت حافظه در اندروید یا مموری لیک چیست؟(بخش اول)</title>
                <link>https://virgool.io/MobileLab/%D9%81%DB%8C-%D9%85%D8%B5%D8%A7%D8%A6%D8%A8-%D9%86%D8%B4%D8%AA-%D8%AD%D8%A7%D9%81%D8%B8%D9%87-%D8%AF%D8%B1-%D8%A7%D9%86%D8%AF%D8%B1%D9%88%DB%8C%D8%AF-%DB%8C%D8%A7-%D9%85%D9%85%D9%88%D8%B1%DB%8C-%D9%84%DB%8C%DA%A9-%DA%86%DB%8C%D8%B3%D8%AA%D8%A8%D8%AE%D8%B4-%D8%A7%D9%88%D9%84-s9b0knq5bemn</link>
                <description>نشت حافظه یا مموری لیک یکی از مهمترین مشکلاتی است که معمولا در برنامه نویسی اندروید باهاش دست و پنجه نرم میکنیم ولی خب قبل از اینکه بریم سراغش باید یه نگاهی به کل موضوع بندازیم بعد از اون برم سراغ جاهایی که معمولا نشت حافظه اتفاق میافته و چطوری میشه ازش جلوگیری کرد پس قبل از هرچیزی باید یه سری تعاریف درباره این مشکل داشته باشیم بعد کم کم بریم سراغ بقیه اش بخش اول این مقاله درباره همین موارد هست و اینکه چرا نشت حافطه بده و اصلا چرا اتفاق میافته .مموری لیک اونقدر موضوع کلیدی و مهمی در امر توسعه هست که میتونه مرز بین یه دولوپر خوب و یه دولوپر بد باشه و البته از مسائلی است که خیلی از توسعه دهنده ها باهاش درگیرن پس اگر باهاش درگیر شدین یا در کارتون باهاش برخورد داشتین اعتماد به نفستون رو از دست ندین این اتفاق ممکنه برای هر برنامه نویسی پیش بیاد مهم اینه چطوری مدیریت شه و مشکل رو حل کنید معمولا بحث پرفرمنس و کیفیت کار از اون مباحثی هست که خیلی بهش پرداخته نمیشه خیلی وقتها درست کار کردن اپ شما تنها چیزیه که ازتون میخوان پس بحث پرفرمنس به حاشیه میره موضوعی که واقعا میتونه باعث دردسر بشه و یکی از مهمترین بخش ها در تولید اپ همین بحث مدیریت اشیاء در حافظه استGarbage Collectorخوشبختانه جاوا از زبان هایی هست که مدیریت حافظه رو به خوبی انجام میده نه تنها اختصاص و عدم تخصیص حافظه رو انجام میده بلکه میتونه بدون زحمت خاصی اون منبعی رو که نیاز ندارید از برنامه تون پس بگیره شاید این سوال براتون پیش اومده که خب چرا ما باید درگیر مدیریت حافظه باشیم وقتی چیزی مثل Garbage Collector داریم اگر مشکلی تو مدیریت حافظه بوجود بیاد تقصیر ما نیست بلکه مقصر اصلی جاواست! خب بهتره یکم موضع رو باز تر کنم تا متوجه بشید چرا مموری لیک بوجود میاد و اینکه Garbage Collector دوستی هست که سعی داره خرابکاری های مارو تمیز کنه نه مقصر خرابکاری هایی که ما توی برنامه مون داریم Garbage Collector خب Garbage Collector میاد و نقطه ابتدایی تخصیص حافظه رو به عنوان نقطه اصلی یا root در نظر میگیره تمامی اشیائی که به طور مستقیم یا غیر مستقیم به این پایه ها متصلن رو طی میکنه و حافظه ای که بهش نیاز نباشه رو از اشیاء پس میگیره ولی مشکل از اونجایی شروع میشه که یه سری از اشیاء ساخته شده توسط GC طی نمیشن یا به عبارتی Garbage Collector اونها رو دیدار نمیکنه پس ما به محض اجرای GC یه درخت از حافظه داریم که از نقطه root و سرشاخه شروع میشه یک ملاقات کننده داریم که از تمام گره های مرتبط تا پایین ترین برگ های درخت پیش میره ولی تعدادی از گره های اصطلاحا مرده وجود داره که ملاقات کننده نمیتونه اون ها رو ملاقات کنه و همین موضوع باعث میشه که ما توی برنامه مون آشغال جا بذاریم تقریبا شبیه کاری که خیلیا تو جنگل و دریا و جاهای دیگه میکنن و نتیجه چیزی شبیه تصویر پایین میشهخب برای مطالعه بیشتر درباره GCدر جاوا  اینکه چه زمانی اجرا میشه و....میتونید به اینجا و اینجا مراجعه کنید مفهوم نشت حافظهخب حالا که یه دید کلی درباره مدیریت حافظه در جاوا داریم شاید بتونیم ساده ترین تعریف از نشت حافظه رو ارائه بدیم&quot;نشت حافظه زمانی اتفاق می افتاد که ما یک شئ را پس از آنکه به هدف ایجادش دست پیدا کردیم همچنان نگهداری کنیم&quot;فرض کنید که هدف یک بطری پلاستیکی آب معدنی حمل آب مورد نیاز شما در طول پیاده روی باشه بعد از اینکه آب بطری خالی شد و شما از پیاده روی برگشتین به هدف بوجود اومدن اون بطری دست پیدا کردید و دیگه بهش نیاز ندارید ولی اگر اونو توی اتاقتون نگهدارید و هرروز یک بطری جدید بهش اضافه کنید چی؟ این دقیقا همون اتفاقی هست که اگر مراقب نشت حافظه نباشیم توی اپلیکیشنمون میافته :)اما قسمت خوب داستان اینه که نشت حافظه همیشه نمیتونه یه مصیبت بزرگ باشه بلکه با توجه به حجمی که توی حافظه ایجاد میکنه میتونه یه نگرانی بزرگ یا فقط یه اتفاق خیلی کوچیک و بی آزار باشه شما فرض کنید یک شی 9 کیلوبایت حافظه رو اشغال میکنه و توسط مدیرحافظه از بین نمیره تا اینجا چیز آزازدهنده ای نیست ولی اگر اون شی 500 کیلوبایت رو بگیره و درون حلقه ای ایجاد بشه که 600 بار میچرخه چی؟ هنوزم میشه بهش اهمیت نداد؟ شاید باورش سخت باشه ولی توی فریم ورک خود اندروید هم گاهی از این نشت حافظه های خیلی کوچولو وجود داره که تاثیر زیادی روی کل عملکرد ندارن و میشه در کمال آرامش ازشون رد شد چون گاهی تغییر ساختار و رفع مشکل هزینه ای به مراتب بیشتر داره تا مثلا یک نشت 15 کیلوبایتی !اما باز هم تاکید میکنم نشت حافظه میتونه شما رو به معنای واقعی کلمه به زانو دربیاره و کار کردن روی پروژه براتون شبیه کار کردن تو جهنم بشه پس باید خیلی مراقبش باشید چون هیچکس نمیخواد با اپلیکیشن پر از لگ کند کار کنه که هر لحظه ممکنه کرش کنه خواه ناخواه این موضوع میتونه باعث ریزش شدید کاربرهاتون بشه زمانی که اپلیکیشن شما مموری لیک یا نشت حافظه داشته باشه وقتی کاربر ازش استفاده میکنه مرتب هیپ حافظه رو پر میکنه و از جایی که GC توانایی خالی کردن هیپ حافظه اپ رو نداره نهایتا به جایی میرسیم که فضایی برای اختصاص دهی وجود نداره و فاجعه اتفاق میافته اپ شما کرش میکنه و از کار میافته از طرفی GC برای پردازش توان زیادی از سی پی یو میگیره همین موضوع میتونه اپ شما رو کند کنه پس هرچه کمتر به GC نیاز داشته باشید و هرچه کمتر اجرا شه توان کمتری از پردازشگر صرف میشه و به همین سادگی امکان ایجاد لگ در اپ شما کاهش پیدا میکنه حالا این در شرایط استفاده از GC های کوچک هست اگر heap نتونه فضای خالی ایجاد کنه مرتب GC های بزرگتر با نیاز پردازشی بالاتری اجرا میشه و این به وضوح میتونه اپ شما رو کند و لگی کنه و اساسا تمام تجربه کاربری شما رو تحت تاثیر قرار بده فکر کنم تا اینجا به خوبی مشخص شده که چرا ما باید حتما فکری به حال نشت حافظه بکنیم و چرا همین موضوع میتونه مرز بین توسعه دهنده خوب و بد باشه نحوه تشخیص نشت حافظه در اندروید از جایی که ممکنه نشت حافظه بصورت غیرعمد اتفاق بیافته پس نمیشه لزوما از درون کد تشخیصش داد و معمولا توی تست های رفتاری یا مانیتورینگ اپلیکیشن در حالت اجرا میشه متوجه نشت حافظه شد هرچند تعدادی از موقعیت ها وجود داره که امکان مموری لیک درشون بالاست و میشه با کنترل و دقت در نوشتن چنین بلاک هایی از کد احتمال یه مموری لیک ویران کننده رو کم تر کرد . اما نحوه تشخیص :Android Studio Profilerابزار مانیتورینگ اندروید استودیو که در زمان اجرای برنامه میتونید علاوه بر مانیتورینگ حافظه مقدار استفاده از CPU و GPU و حتی ارتباط با شبکه رو روی نمودار ببینید میتونید استفاده از حافظه و پر و خالی شدن حافظه رو تو بخش های مختلف برنامه بررسی کنید و میتونه ابزار خوبی باشه برای تشخیص پر و خالی شدن حافظه خصوصا زمانی که اپ رو به حالت بکراند ببرید و مقدار مصرف حافظه و خالی شدن حافظه رو ببینید ۲. Leak Canaryخب اینم از ابداعات حاصل از تنبلی مهندسان کامپیوتر هست تقریبا هرچیزی که برای پیدا کردن نشت حافظه نیاز دارید درون این کتابخونه هست در کنار اپ شما اجرا میشه هرجا نیاز باشه از حافظه DUMP میگیره و جاهایی که پتانسیل نشت دارن رو به صورت نوتیفیکیشن براتون ارسال میکنه و از همه مهمتر محل نشت رو trace میکنه تا بهتون کمک کنه محل اصلی نشت رو پیدا و اصلاح کنید بهتون پیشنهاد میکنم حتما ازش استفاده کنید و یه جای اختصاصی برای تست کردن زمان کد نوشتن براش در نظر بگیرید خب برای اینکه این نوشته خیلی طولانی می شد تصمیم گرفتم جاهایی که بیشتر نشت اتفاق میافته و نحوه مدیریت کردن و جلوگیری کردن ازش رو تو بخش دوم بنویسم چون اگر قرار بود همه چیز تو یه پست باشه طولانی بودنش یکم آزار دهنده میشد تو روزهای آینده درباره اینکه چطوری میشه از مموری لیک فرار کرد و کجا ها معمولا اتفاق میافته خواهم نوشتمرسی از وقتی که به خوندن اختصاص دادید ممنون میشه اگر انتقادی بود کامنت بذارید بخش دوم مقاله مموری لیک در اندروید &lt;br/&gt;</description>
                <category>SAJAD noroozi</category>
                <author>SAJAD noroozi</author>
                <pubDate>Fri, 30 Aug 2019 21:18:39 +0430</pubDate>
            </item>
                    <item>
                <title>بلعیدن شیرینی دانمارکی یا راهکاری برای قورت دادن استوانه ها</title>
                <link>https://virgool.io/@sjd.noroozi91/%D8%A8%D9%84%D8%B9%DB%8C%D8%AF%D9%86-%D8%B4%DB%8C%D8%B1%DB%8C%D9%86%DB%8C-%D8%AF%D8%A7%D9%86%D9%85%D8%A7%D8%B1%DA%A9%DB%8C-%DB%8C%D8%A7-%D8%B1%D8%A7%D9%87%DA%A9%D8%A7%D8%B1%DB%8C-%D8%A8%D8%B1%D8%A7%DB%8C-%D9%82%D9%88%D8%B1%D8%AA-%D8%AF%D8%A7%D8%AF%D9%86-%D8%A7%D8%B3%D8%AA%D9%88%D8%A7%D9%86%D9%87-%D9%87%D8%A7-mcftjpolptjs</link>
                <description>چرا و چگونگی استفاده از realm اونقدر واضحه که من میخوام باز هم دربارش بگم این دوست عزیز دانمارکی دقیقا مثل شیرینی دانمارکی خوشمزه دوست داشتنی و طبیعتا شیرینیه چیزی که اینجا میخونید راهکار ساده و سریع برای استفاده از پایگاه داده ریل ام هست ساده سریع و به همون شدت آسون برای رهایی از کوئری زدن های نامانوس در SQLITE  به دامان ریل ام چنگ بزنید و متفرق نشوید! :)قصه از کجا شروع شد...قصه از اونجایی شروع شد که من همیشه از sql فراری بودم هیچوقتم دوستش نداشتم :|  اکثر پروژه هایی که انجام دادم و کد هایی که تو این چند سال نوشته بودم عملا کلاینت های اندرویدی بودن که بود و نبودشون به سرور و دیتای ارسالی از بکند گره خورده بود ولی یه جایی تصمیم گرفتم قورباغه رو قورت بدم و بگردم ببینم چجوری میتونم  کار با sqlite  رو بدون دردخونریزی تجربه کنم خب کلی ORM خوب وجود داره که بدون نیاز به نوشتن query دنیا رو قشنگتر میکنن منم داشتم بینشون میچرخیدم که به دوست نازنینی برخوردم که جذابیتش منو تحت تاثیر قرار داد و اون دوست گرامی چیزی نبود جز Realmریل ام (realm)چیست؟ریل ام یک ORM برای استفاده از SQLITE نیستبلکه دقیقا یک جایگزین زیبا و جذاب برای sqlite هست که و به نوعی میشه بهش گفت اولین پایگاه داده شی گرا برای موبایل. ریل ام از هسته c++ استفاده میکنه و یک پایگاه داده مبتنی بر table در اختیار کاربر قرار میده خب برای اینکه بهتر بشه با sqlite مقایسه اش کرد باید یه جمع بندی کلی داشته باشیمبرتری های نسبت به SQLITE :سرعت بالاتر (تا ده برابر سریعتر )استفاده ساده تربا اشیا (objects) بهتر کار میکنهبا داده های پویا و روی هوا (on the fly) بهتر کار میکنهپشتیبانی قوینقاط ضعف نسبت به SQLITE :قابلیت import نداردهمچنان در حال توسعه محتوای آموزشی کمتری درباره اش منتشر شدهنمیتوان در طول thread به اشیا دسترسی داشتقابلیت های مهم :پشتیبانی از nullپشتیبانی از نقشهقابلیت migrate آساناعلان تغییر یک داده خاصقابلیت استفاده از کلید های اصلی (primary key)مرکبطبق آماری که خود توسعه دهنده های realm دادن حدودا 100 هزار توسعه دهنده در حال حاضر از realm استفاده میکنن که خب نشون میده میتونه جایگزین خوب و مناسبی برای SQLITE تو بحث موبایل ( بطور مشخص منظور من اندروید هست قابلیت استفاده در IOS هم داره) هستچیزی که در ادامه نوشته شده صرفا یک توضیح ساده و آموزش CRUD در REALM هست نحوه استفاده از قابلیت های دیگه مثل notification و... رو میتونید تو سایت اصلی پیدا کنیداستفاده از REALMاضافه کردن به پروژه:کافیه این چند خط زیر رو در build.gradle  پروژه اضافه کنیدbuildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath &amp;quotio.realm:realm-gradle-plugin:5.8.0&amp;quot
    }
}بالای build.gradle اپلیکیشن این یک خط رو اضافه کنید:apply plugin: &#039;realm-android&#039;خب حالا کافیه ابزار دور زدن تحریم رو روشن کنید و صبر کنید gradle سینک شهحالا توی اکتیوی extend شده از اپلیکیشن یا MainActivity تون realm رو باید initialize کنید اونم به سادگیRealm.init(this);تو مرحله بعد باید دیتا بیس رو بسازیم قطعا وقتی دیتا بیس میسازیم و فانکشن های crud مینویسیم باید برای ایجاد دیتا بیس از singleton استفاده کنید و خب بدیهیه ولی گفتم تذکر بدم تا مبادا هربار که شی جدید ساخته میشه یه دیتا بیس با همون نام ساخته شه چون اگر این کار کنید قطعا به در و دیوار برخورد میکنید :) پس یک بار initialize و یک بار ایجاد دیتا بیس و به تعداد مختلف crud . ساخت پایگاه داده:Realm DBname = Realm.getDefaultInstance();ایجاد مدل داده :قبل از هرکار دیگه باید object  درست کنیم من اینجا فرض میکنم قراره یه تعداد کتاب ذخیره کنیم پس اینجوری میشه public class Book extends RealmObject {
@PrimaryKey
private int id;
private String title;
private String description;
private String author;
// Standard getters &amp; setters generated by your IDE…
و برای هرکدوم getter و setter تولید میکنیم البته ما که تولید نمیکنیم android studio این کارو میکنه نوشتن داده در پایگاه:تا اینجای کار تقریبا همه چیز محیاست تا بتونیم دیتا ذخیره کنیم اپدیت کنیم بخونیم و پاک کنیم قدم اول باید دیتا بنویسیم : DBname.beginTransaction();
‌Book book = DBname.createObject(Book.class);
book.setId(&amp;quot1325&amp;quot);
book.settitle(&amp;quotrealmbook&amp;quot);
book.setauthor(&amp;quotsajad&amp;quot);
book.setdescription(&amp;quotits about Realm DB&amp;quot);
DBname.commitTransaction();خواندن داده های ذخیره شده:به همین سادگی ما یه شی کتاب به پایگاه داده مون اضافه کردیم بریم سراغ خوندن داده ها از پایگاه داده مون://Read all data
RealmResults&lt;‌Book&gt; results = DBname.where(Book.class).findAll();
for(Book book : results){
 System.out.println(book.gettitle() + &amp;quot &amp;quot + book.getauthor());
}
//Read specific data
RealmResults&lt;Book&gt; results = DBname.where(Book.class).equalTo(&amp;quotid&amp;quot, 1235).findAll(); به روز کردن داده ها:آپدیت کردن و به روز کردن داده ها در realm:RealmResults&lt;‌Book&gt; results = DBname.where(Book.class).equalTo(&amp;quotid&amp;quot, 20).findAll();
DBname.beginTransaction();
for(Book book : results){
Book.settitle(&amp;quotnew Realm book&amp;quot);
}
DBname.commitTransaction();پاک کردن داده ها از پایگاه:پاک کردن داده های در realm با کدهای زیر انجام میشه:RealmResults&lt;‌Book&gt; results = Dbname.where(Book.class).findAll(); 
DBname.beginTransaction(); 
// remove single match
results.deleteFirstFromRealm();
results.deleteLastFromRealm(); 
// remove a single object
Book book = results.get(5);
book.deleteFromRealm();
 // Delete all matches
 results.deleteAllFromRealm();
   DBname.commitTransaction();فقط یک نکته باقی مونده اگر دقت کرده باشید اعمال تغییرات رو دیتا بیس مستلزم استفاده از دو عبارت .beginTransaction() و .commitTransaction() هست در آخر هم باید بگم realm قابلیت های جذاب زیادی داره که میشه ازش استفاده کرد تا بهترین نتیجه رو بتونیم بگیریم علاوه بر اون سرویس کلود برای اپلیکیشن ارائه میده که البته ما جز دور افتاده از بقیه دنیا محسوب میشیم :)امیدوارم مفید بوده باشه توضیحات و قطعا درصورت انتقاد و یادآوری مشکلاتی که احیانا از چشم من دور مونده بنده رو شاد میکنیدمنابع:وبسایت برنامه نویس دیوانهوبسایت اصلی Realmداکیومنت اصلی realmآموزش در androidHiveآپدیت: یکی از بزرگترین مشکلات من در استفاده از realm بالابردن حجم برنامه به شکل قابل توجهی (حدود 5 مگابایت) بود که باعث شد طی یک عملیات سریع برم سمت RoomDB که هم سرعت خوبی داره هم ساده و سبک هست </description>
                <category>SAJAD noroozi</category>
                <author>SAJAD noroozi</author>
                <pubDate>Thu, 24 Jan 2019 02:44:58 +0330</pubDate>
            </item>
                    <item>
                <title>بتمن ،اندروید ،گوگل و دیگران</title>
                <link>https://virgool.io/coderlife/basicknowledgeinandroidevelopment-okiuljtgvtbg</link>
                <description>بت دروید بتمن دنیای اندروید هاهمه چیز دقیقا از جایی شروع شد که دو روز قبل تا نیمه شب داشتم کد میزدم و خیلی اتفاقی تو گیت یکی از کد های دوسال قبلم رو دیدم از خدا که پنهون نیست از شما چه پنهون که حسابی به خودم توهین کردم که آخه مرد نا حسابی اینی که تو به عنوان کد به خورد این و اون دادی اسمش اصلا کد نیست که بیشتر شبیه کاغذ آبی طراحی هیولای اسپاگتی پرنده است !خوب پس اومدم یه نیم نگاهی به کد های جدیدم کردم که ببینم چی شد و چیکار کردم و چه تجربه هایی داشتم که خروجیش یه کد قابل خوندن تر قابل فهم تر و قابل تست تر شده و همونطور ک درحال خوندن بودم روانه ی رختخواب گران مایه شدم و 5-6 تا توییت درباره اش نوشتم که این پایین هست :) بعد گفتم خب چرا به آدمهایی که جای سه سال قبل من هستن نگم چی رو از کجا خوندم که بهتر بتونن راه رو پیدا کنن نتیجه کار شد این پست ویرگول و اینکه چطوری میشه با کمک اندروید و گوگل در راه بتمن شدن قدم برداشت. من سعی کردم تا جایی که میشه مفاهیم کلی تر که باعث دید بهتری به کل فرآیند تولید اپلیکیشن میشه رو مد نظر قرار بدم قطعا اینکه شما بدونید فرگمنت با اکتیویتی چه فرقی داره رو میتونید تو هرکتاب آموزش اندروید یا کلاسی پیدا کنید ولی خب اینکه بهتره کدوم معماری رو استفاده کنید کجا از اکتیویتی استفاده شه و کجا از فرگمنت رو خب خیلی جاها ازش غافل میشن چه تو کتابها چه تو کلاسها این سبک دانش چیزی هست که خود برنامه نویس باید پیگیرش باشه و یاد بگیره و گاهی سردرگم میشه که من الان چی باید یاد بگیرم برای بهتر شدن و چه چیزی نیاز دارم من تمرکزم رو گذاشتم رو اون بحث امیدوارم به کارتون بیاد,توصیه به استفاده درست از هرچیز :)دسته بندی درست تو کد نویسیمعماری تو جاوادستورالعمل های لازم برای نوشتن کد تمیز و قابل تستهمونقدر که مهمه بدونید تو جاوا چیکار میکنید تقریبا یک چهارمش باید بدونید تو گریدل دارید چیکار میکنید :)تو این مقاله سعی میکنم به ساده ترین شکل ممکن درباره چیزایی که به ذهنم میرسه توضیح بدم و تا حد ممکن منبع فارسی معرفی کنم ولی اگر زبانتون حداقل درحد خوندن یکی دوتا مقاله تخصصی جوابگو نیست حتما حتما حتما حتما یه فکری به حالش بکنید:) از اون گذشته ممکنه خیلی از چیزایی که من به واسطه کم تجربگی تجربه کردم رو شما تجربه نکنید من رشته ام تو دانشگاه ای تی بود ولی شبکه هیچوقت راضیم نکرد و باز برگشتم سمت کد پس ممکنه یه سری از چیزایی که میگم به عنوان یه مهندس نرم افزار بدونید و به کار ببرید یا تو دانشگاه و کلاس و.. درباره اش خونده باشید و درکش کرده باشید پیشاپیش به بزرگی خودتون ببخشید اگر چیز تکراری دیدین :) جاوا و شی گرایی:به عنوان کسی که هرگز کلاس جاوا نرفت هرگز قبل از اندروید جاوا نزد و کل مفهوم شی گرایی رو تو زبانی به نام C++ درک کرد به شما پیشنهاد میکنم اگر خود جیمز گاسلینگ و مدیران ارشد سان مایکرو سیستمز اومدن گفتن داداش نیازی به دانش اولیه جاوا نداری و برو سراغ اندروید شما به نیابت از من میتونی با پشت دست بزنی تو دهنشون :))) اول اینکه شما حتما حتما نیاز داری که دانش اولیه درباره جاوا داشته باشی اینکه چطوری کار میکنه تفاوت JDK و JRE رو بدونید، بدونید مفهوم super و this چیه ،برای این کار من یه کورس بشدت خوب دیدم تو فرانش که لینکش این پایین هست کامل نیست ولی اگر دارید کد اندروید میزنید و تو مفاهیم شی گرایی خیلی خوب نیستید و این موضوع اذیتتون میکنه حتما این دوره رو ببینید که حسابی گره از کارتون باز  میکنه :)و البته یه کتاب جمع و جور جاوا که خیلی دوسش دارم و واقعا کتاب خوبیه لینک آمازونشو براتون میذارم با یکم تلاش احتمالا بتونید PDF اش پیدا کنید ولی نمونه فارسی کتاب جاوا نخوندم و نمیدونم کیفیتشون در چه حده پس هر کتابی که باهاش راحتید و مباحث اولیه و پایه رو به خوبی توضیح میده خوبه دوره مفهوم شی گرایی در جاوا برای برنامه نویسان اندرویدEffective Java۲.معماری در اندروید:معماری یک نرم افزار و الگو های معماری در نرم افزار یکی از چیزهایی هست که خیلی از توسعه دهنده های تازه کار اندروید کلا یادشون میره همچین چیزی وجود داره و کد باید دارای یه ساختار مشخص باشه اینکه معماری چقدر میتونه موثر باشه تو تمیزی کد و اینکه بدونید دقیقا دارید چیکار میکنید رو کار ندارم بذارید ساده ترین شکل ممکنش رو بگم یه سری آدم سالهاست دارن کار نرم افزاری میکنن اونا دیدن اگر ساختار مشخصی برای کد وجود داشته باشه زندگی زیباتر میشه در نتیجه تصمیم گرفتن این ساختار ها رو ایجاد کنند تو زبان های مختلف درباره اشون مقاله بنویسن و اینکه بگن چطوری میشه یه ساختار بوجود آورد اینکه چرا معماری استفاده میشه یه بحثه که خیلی واردش نمیشم و البته از لینک های زیر میتونید برای درکش استفاده کنید. اینجا خود گوگل بحث معماری تو اندروید رو باز یه سری نمونه کد داره  و... این شما رو میبره به ویدیو های مربوط به معماری در جلسات برنامه نویسان اندروید تهران یا همون logcat  که اجتماع خیلی دوست داشتنی رو به وجود آوردن :)Guide to app architectureAndroid Architecture Patterns : MV( C | P | VM )Building Modern apps using the Android Architecture GuidelinesConsidering architecture for Android app3.الگو های طراحیدیزاین پترن زمانی به وجود اومد که یه سری مشکل تکراری برای برنامه نویس ها پیش اومد :| خب تقریبا جوابها همیشه تکراری بود موارد استفاده متفاوت بود :)) خب بهتر بگم اینجوری بود که قابلیت هایی نیاز بود به برنامه اضافه شه که ممکن بود هرکاری بکنن و عملکردشون مهم نبود مهم نحوه پیاده سازی اونا در حالتی کاملا تر و تمیز مرتب و شیک بود اینگونه بود که در دهه نود میلادی یه سری دوستان گرامی که بعد ها چون اسماشون زیاد میشد به gang of four معروف شدن اومدن یه کتاب نوشتن و تعدادی روش برای این سبک مشکلات در ساختار شی گرایی فارغ از زبان برنامه نویسی ایجاد کردن هنوز هم بهترین کتاب در این رابطه همون کتاب معرفشون (اسمش طولانی بود این لینک ویکی پدیای کتابه) هست هرچند بر این تعداد الگو های افزوده شد بعضی هاش کاربردی تره بعضیاش نه و... ولی خب در مجموع خیلی سخت نیست یادگیریشون و خیلی هم کاربردی هست متاسفانه فقط یه جا پیدا کردم که تعداد زیادی از این الگو ها رو به زبان فارسی توضیح بده که اونم زبان پیش فرضش رو C# انتخاب کرده بود که خب از لحاظ تئوری میشه ازش استفاده کرد یکم باهوش و با دقت باشید میتونید عین اون کد ها رو تو جاوا پیاده سازی کنید ( به کسی نگید ولی بیل گیتس و رفقا سی شارپ رو از رو دست جاوا تقلب کردن :)))) )Design Patterns: Elements of Reusable Object-Oriented SoftwareDesign patterns (in farsi)- tosinso WebSite۴.S.O.L.I.Dشاعر میگه من بنده آن دمم که مدیر گوید تست برای نرم افزارت بنویس و من نتوانم ! بذارید من یکم خوش خیال باشم فکر کنم شما دقیقا به توصیه هام گوش دادید و رفتین یاد گرفتین دقیقا کد تمیز با معماری خوب نوشتید  و دیزاین پترن استفاده کردین آیا کافی است؟ متاسفم نه :| خب بذارید اینجوری بگم عزیزانی که این پایین لیست شدن جز نکات کلیدی و شب امتحانی تو کد تمیز و قابل تست نوشتن هستن:) ولی خب قرار نیست اینجا توضیح خاصی درباره شون بدم چون هم انگلیسی هم فارسی کسانی که سابقه شون خیلی بیشتر و قوی تره درباره شون حسابی تر و تمیز صحبت کردن فقط بگم رعایت این ها باعث میشه که بتونید خیلی ساده و سریعتر برای کدتون تست بنویسید و ماژولاریتی کدتون هم زیاد میشه البته از وقتی من بیشتر بهشون توجه میکنم پوستمم شفاف تر شده :)S: Single Responsibility O: Open / Closed L: Liskov Substitution I: Interface Segregation D: Dependency Inversionویدیو جلسات LOGCAT که خب طبیعتا فارسی هستS.O.L.I.D: The First 5 Principles of Object Oriented Design۵.REST-JSONخب این دیگه هیچ ربطی به اندروید نداره :| البته دروغ چرا ربط داره ولی نه اونقدر که قبلی ها ربط داشتن خب اینجوری بگم که این روزها هرچی اپ تولید میشه یه جوری یه راه دررو برای ارتباط با اینترنت دارن بدین ترتیب باید راهی باشه تا اپلیکیشن بتونه تو اینترنت پبام بفرسته یا دریافت کنه مثلا قراره شما یه سری داده از یه سایتی مثل توییتر بگیرید یا اصلا چرا توییتر شما یه وبسایت دارید و میخواید برای وبسایتتون اپلیکیشن بسازید و سرویس هاتون رو در قالب اپ هم ارائه بدین راه حل یه زبان مشترک هست که اپلیکیشن اندرویدتون بتونه با وب سرویستون صحبت کنه اینجاست که پای REST و JSON وسط میاد و معمولا هرجا بخواید استخدام بشیدیکی از شرایط آشنایی با کتابخانه هایی مثل volly و Retrofit هست که دقیقا برای همین کار طراحی شدن دوتا آموزش ساده درباره این عزیزان این پایین لینک میکنم سخت نیست ولی بشدت کاربردیه درضمن JSON رو صرفا بابت پرکاربرد تر بودن آوردم بغل rest وگرنه کاملا درجریانم لزوما نیازی نیست که برای ارتباط rest از json استفاده شه :)REST APIJSON۶.SQL-DBخب تقریبا داریم تموم میشیم این شخصا تجربه خودم نبوده من قبل از اینکه یاد بگیریم اسم اندروید رو هم بنویسم با ایشون کارهای ژانگولر میکردم :)) (حالا انگار میشه باش چیکار کرد نهایتا دوتا کوئری زدم بابا ) خب sql شاید هم نباشه ولی من دوست داشتم اینجا درباره اش بنویسم ایشون خیلی کاربردیه زیادی کاربردیه شما میتونی بدون دونستن چیز خاصی از ایشون و صرفا کپی کردن کد از اینترنت یا استفاده از ORM دیتا ذخیره کنی یا پاک کنی و ... ولی خب اگر بخوام صادقانه بگم هرگز نمیشه بدون ادویه و پیاز مرغ درست کرد(گرسنم بود که این مثال رو زدم) اگر مستقیما از sqlite استفاده کنید که خب قطعا نیازتون میشه و اگر از sqlite استفاده نکنید دونستن ساختار شما رو ده پله جلو میندازه ساختار درست پیاده کردن توی پایگاه داده میتونه خیلی به بالا رفتن کارایی و سرعت اپلیکیشنتون اضافه کنه پس من گزینه 6 ام رو اختصاص دادم به sql که اگر بلد نیستید حتما حتما حتما حداقل مفاهیم پایه اش رو بخونید لینک های مفید مرتبط رو پایین میبینید البته منابع فارسی هم زیاد هست میتونید استفاده کنید ولی صرفا من اینا رو پیدا کردم دوست داشتمAndroid SQLite EssentialsSQL Cookbook (Cookbooks (O&amp;#x27;Reilly))۷.GIT-Github-Gitlabو یا هر سرویس دیگه ای :) گیت یکی از بهترین چیزهایی که تو زندگی میشه باهاش سر و کله زد مثل لینوکس گیت یک سامانه است که به شما اجازه میده بتونید بدون مشکل خاصی از هر مرحله فرآیند اپلیکیشنتون بک اپ داشته باشید و یا اینکه بتونید کدهاتون رو به اشتراک بذارید و اپلیکیشن متن باز منتشر کنید و از اون مهمتر که شاید بهترین مزیتش باشه اینه که شما میتونید اپ های گروهی تولید کنید و بدون اینکه مشکل خاصی بوجود بیاد چندین نفر روی یک پروژه کار کنند و نتیجه هم کم نظیر شه در عین حال گیتهاب و گیت لب دو سرویس مبتنی بر گیت هستن که  برای دولوپر های تازه کار تفاوت خاصی با بهشت ندارن پر از کد ها و لایبرری های ازاد که میشه ازشون استفاده کرد کدهاشون خوند و یاد گرفت واقعا اگر فکر میکند بدون گیت میشه برنامه نویس بود تقاضای تجدید نظر دارم:)آموزش مقدماتی کار با گیت گیت هاب و گیتلبGit-pro BookVersion Control with Git: Powerful tools and techniques for collaborative software developmentکلام آخر:اول ببخشید اگر شوخیام خیلی بی مزه بود :)) سعی کردم ساده و راحت بنویسم و البته روان اگر خطایی داشت بر من ببخشید دوم اینکه این ۷ موضوع مفاهیم خیلی پایه ای هستن که دونستنشون امتیاز نیست بلکه الزام هست برای کدنویس خوب بودن مفاهیم خیلی جزئی تری هست از لایبرری های خاص تا فلان تکنولوژی ترند روز ولی خب همونطور که گفتم من مخاطبم صرفا خودم در زمستان 94 بود جایی که بلد بودم چیزی بنویسم که کار کنه ولی چیزی که خوب باشه چی؟ اونو نمیدونستم و سعی کردم بفهمم اما این فهمیدن هزینه داشت فرصت های زیادی از دست دادم بابت ندونستن یه سری مفاهیم زمان زیادی از دستم پرید درک یه سری مفاهیم بابت ندونستن بعضی مفاهیم پایه ای تر برام خیلی سخت تر بود ولی خب فهمیدم باید بخونم  بخونم و بیشتر بخونم تا مسیر برای بهتر شدن و قدم بعد واضح تر شه امیدوارم این نوشته بتونه کمک کنه مسیر واضح تر شه :)و البته اینکه آدم هایی با سابقه و توانایی بیشتر از من قطعا خیلی خیلی زیاد هست و من بشدت دوست دارم درباره مواردی که نوشتم و درست و غلط و صحیح یا خطا بودن نوشته ام نظر بدن پیشاپیش ممنونم </description>
                <category>SAJAD noroozi</category>
                <author>SAJAD noroozi</author>
                <pubDate>Mon, 01 Oct 2018 19:27:46 +0330</pubDate>
            </item>
            </channel>
</rss>