<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های سید عماد رضوی</title>
        <link>https://virgool.io/feed/@razavioo</link>
        <description>یک عدد برنامه نویس خوشحال هستم.</description>
        <language>fa</language>
        <pubDate>2026-06-10 12:53:23</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/26670/avatar/VQCNk3.jpg?height=120&amp;width=120</url>
            <title>سید عماد رضوی</title>
            <link>https://virgool.io/@razavioo</link>
        </image>

                    <item>
                <title>گذار آرام از Android و JVM به KMP: یک سفر سه ساله</title>
                <link>https://virgool.io/@razavioo/android-jvm-kmp-yuvrjqapbmf2</link>
                <description>در این مقاله سعی دارم مسیر پروژه‌ای را شرح دهم که بعد از سه سال گسترش دادیم و در نهایت به KMP تبدیل شد. یکی از دلایل من برای انتشار این مقاله نسبتا طولانی این است که اگر برنامه‌نویسی خود را در بخشی از این مسیر می‌بیند، بتواند برای ادامه مسیر پروژه خود به درک بهتری برسد. به جهت برخی ملاحظات ضروری، امکان ارائه مثال‌های واقعی (و تشریح کسب‌و‌کار پروژه) را ندارم. اما تلاش می‌کنم این موضوع مانعی برای شفافیت توضیحات فنی من نباشد. این نوشتار مبتنی بر تجربیات من است، ممکن است در نگارش بخش‌های کوچکی از آن دچار اشتباه شده باشم. امیدوارم با بازخورد سازنده خود، این متن را به سطح کیفی بالاتری برسانید.می ۲۰۱۹در ابتدای همکاری من، سه پروژه‌ی اندرویدی که از نظر معماری در شرایط مناسبی نبود، برای رفع نیازهای شرکت ساخته شده بود که همگی از نظر کسب‌و‌کاری اشتراکات زیادی داشتند (مثلا دیتابیس همگی تا حد زیادی شبیه به هم بود). اولین قدم من در هنگام ورود، استفاده از Build Variant ها بود. با این کار، باگ‌های زیادی به وجود آمد و منجر به تغییرات فایل زیادی شد ولی بالاخره هر سه پروژه به پایداری متوسطی رسید. توسعه گسترش پیدا کرد، ظاهر برنامه بهبود را بهبود دادیم. از Volley به Retrofit مهاجرت کردیم. در این زمان، هنوز پروژه ما DI (تزریق وابستگی) نداشت. تمام کلاس‌های سورس با جاوا نوشته شده بود. تمام ظاهر برنامه با XML پیاده سازی شده است. در برنامه هیچ تستی نوشته نشده است و برای برخی نیازهای بیزینسی، ماژول‌های Java ای ساخته بودیم. مثلا ماژول common که شامل Utility های کاربردی برنامه بود.فوریه ۲۰۲۰کمی پیش رفتیم. پروژه با پیاده‌سازی بخش‌های گسترده‌ای از کسب‌وکار جلو رفته بود. من اقدام به تبدیل پروژه به Single Activity کردم. به سراغ Fragment و Navigation Component رفتیم. کمی بعد، ما بخشی از Custom View های مربوط به پروژه را به یک ماژول جداگانه اندرویدی منتقل کردیم. هدف ما این بود که هر چه زودتر دیزاین سیستم طراحی شده را وارد پروژه کنیم. هدفی که تا زمان استقرار Jetpack Compose و جایگزینی آن با XML محقق نشد.می ۲۰۲۰اولین کدهای کاتلین به پروژه اضافه شد. از این زمان به تدریج فایل‌های جدید عمدتا با کاتلین زده می‌شد و فایل‌های قدیمی جاوا کم کم به کاتلین تبدیل می‌شد. گاهی باگ‌هایی در این تبدیل رخ می‌داد ولی از آن گریزی نداشتیم. مخصوصا به این دلیل که پروژه هنوز ساختار درستی از نظر معماری نداشت و تقریبا برای هیچ یک از بخش‌های پروژه تستی نوشته نشده بود.مارس ۲۰۲۱به ما خبر رسیده است که قرار است یک نسخه JVM از این پروژه برای سیستم‌عامل Linux داشته باشیم. با اضافه شدن آقای محمد سهرابی به پروژه، تمرکز بر روی بحث معماری پروژه افزایش پیدا می‌کند. بالاخره معماری پروژه به شکل فعلی آن یعنی Clean Architecture + MVVM + DI رسید. با تمرکز بیشتر بر روی جنبه‌های معماری پروژه، کم‌کم کلاس‌ها، پوشه‌ها و ماژول‌های قابل توجهی ساخته، تغییر کرده یا حذف شدند. تبدیل فایل‌های جاوا به کاتلین نیز سرعت گرفت. Kotlin Coroutines وارد ماجرا شد. همینطور Hilt Dependency Injection به پروژه اضافه شد.آگوست ۲۰۲۱پس از اینکه بخش‌هایی از پروژه اندرویدی به شکل Abstraction/Implementation پیاده‌سازی شد، زمان ساخت یک پروژه JVM فرا رسید. در این زمان ما پیاده‌سازی ارتباط با دیتابیس را در پروژه اندرویدی خود با Room انجام داده بودیم (که تا لحظه نگارش این متن، پشتیبانی از سایر پتلفرم‌ها ندارد) و برای JVM، کتابخانه Exposed را انتخاب کردیم. این کتابخانه از اندروید پشتیبانی نمی‌کرد. گزینه بهتر SQLDelight بود که پلتفرم‌های هدف ما را به خوبی پشتیبانی می‌کرد. ما در آن زمان به این موضوع واقف نبودیم. برای Dependency Injection در اندروید از Hilt استفاده می‌کردیم که در JVM پشتیبانی نمی‌شد. در JVM به سراغ Dagger رفتیم. برای ارتباط با سرور نیز به سراغ کتابخانه قدرتمند Ktor رفتیم چون Retrofit قابلیت استفاده در پلتفرمی غیر از اندروید نداشت. برای اینکه بتوانیم از ماژول‌های مشترک بین دو پروژه بهره ببریم، به سراغ Maven Publish و Gitlab Package Registry رفتیم. کمی جلوتر، مثلا ماژولی برای تمامی ارتباطات با سرور بر اساس Ktor شکل گرفت تا نیازی به نوشتن جداگانه هر بخش از این کدها نباشد. برای Logging به سراغ کتابخانه‌های ساخته شده بر پایه‌ی SLF4J رفتیم. در سمت JVM از Log4j بهره بردیم و در سمت اندروید، مهاجرت به Logback را شروع کردیم.دسامبر ۲۰۲۱یک نیروی مستعد به مجموعه اضافه کردیم. آقای مهدی بهمن‌پور با روحیه هنری و فهم خیلی خوب از برنامه‌نویسی، به ما این امید رو داد که در سمت ظاهر برنامه، می‌توانیم انتظار کارهای خیلی جذابی داشته باشیم. در این مدت ما بر روی دامنه برنامه تغییرات زیادی داشتیم و در سمت JVM، کتابخانه Picocli را برای بهبود رابط کاربری CLI مستقر کردیم. در بخش دیتابیس، با درک جدیدی که از کتابخانه‌ Exposed پیدا کردیم، در پیاده‌سازی‌های خود و نحوه نوشتن Query های خود، بهبودهایی داشتیم. مهدی در پیاده‌سازی بعضی بخش‌های مربوط به Gradle ابتکار عمل را در دست گرفت. مثلا ساخت یک اسکریپت برای مشخص ساختن ورژن Debug و Release در پروژه JVM یا تبدیل تمامی فایل‌های Groovy به Kotlin (فرمت kts).جولای ۲۰۲۲کم کم پروژه از نظر بیزینسی به ثبات می‌رسد و ما توانستیم زمان و تمرکز بیشتری برای تسک‌های فنی پیدا کنم. بالاخره اولین کدهای Jetpack Compose توسط مهدی به پروژه اضافه شد. بیزینس توسط محمد جلو رفت و سمت ظاهر توسط مهدی راهبری شد. من هم راهبری کلی پروژه را به عهده داشتم و سعی می‌کردم ایده تبدیل پروژه‌ها به KMP را همیشه در ذهن سایر نفرات تیمم زنده نگه دارم.نوامبر ۲۰۲۲پروژه را به Version Catalog منتقل کردیم. تغییری که کار ما برای سایر تغییرات در Gradle را راحت‌تر کرد.آوریل ۲۰۲۳در این زمان به این نتیجه رسیدیم که نوبت خداحافظی با کتابخانه قدرتمند Room و مهاجرت به SQLDelight در اندروید و JVM شده است. برای اینکه این تغییر با حداقل مشکل انجام شود، محمد سهرابی ماموریتی برای نوشتن تست در لایه دیتا (مخصوصا لایه Datasource) را شروع کرد. با پایان فرآیند تست‌نویسی او، خودش و من مشغول نوشتن فایل‌های sq و اجرای سایر تغییرات شدیم. پس از مدتی، به جهت تفاوت‌های Dagger با Hilt و نیز تفاوت Driver ‌های SQLDelight پیدا شد که نیاز به تغییراتی در نحوه اجرای تست‌ها و تغییر کدهایی در آن قسمت گشت. در مجموع این مهاجرت تکنولوژی به دلیل تفاوت پارادایم میان Room و SQLDelight، زمان قابل توجهی از ما گرفت. اما پس از آن، برای هر دو پروژه اندروید و JVM، یک ماژول مشترک برای ارتباط با دیتابیس برنامه داشتیم.ژوئن ۲۰۲۳مهدی بهمن‌پور مسئول پیگیری تسکی شد که ما در آن زمان به اشتباه به آن Feature Flag می‌گفتیم. هدف از این تسک آن بود که در لایه Business هر یک از سه Flavor ای که برای پروژه اندرویدی داشتیم، به جای آنکه بر اساس Flavor حالت مشخصی در نظر بگیریم، Feature های مشترکی را شناسایی کنیم که با تغییر هر یک از آن‌ها در جایی مشخص (مثلا یک فایل که در build.gradle به آن اشاره می‌شود)، بتوانیم ویژگی جدیدی را برای آن Flavor اعمال کنیم. برای این تغییر نیاز بود تا مهدی بخش‌های مختلف برنامه را از نظر امکانات جداسازی کند و برای هر یک از ترکیب حالاتی که ممکن بود پیش بیاید، پیاده‌سازی‌های مناسبی داشته باشد. این کار در نهایت به قابلیت کنترل بیشتر امکانات هر یک از Flavor‌ های برنامه اندرویدی انجامید. وجود یا عدم وجود هر یک از Feature های تعریف شده، به یک Use Case تبدیل شد. تمرکز بیزینس را از Flavor خارج کرد و به ما انعطاف بیشتری برای توسعه پروژه برای شرکت‌های متفاوت با شرایط بیزینسی جدیدی را داد.جولای ۲۰۲۳چهارمین Flavor به پروژه اندرویدی اضافه شد. قبل از آن، نیاز بود تا یک Feature تقسیم به دو Feature شود. به جهت پیاده‌سازی انجام شده پیشین، زمان اضافه شدن این Flavor و گرفتن خروجی مناسب آن بسیار کوتاه بود. کمی پیشتر با ناراحتی از محمد سهرابی خداحافظی کردیم و مدتی بعد با اضافه شدن آقای محسن عابدینی به ادامه مسیر قبلی خود امیدوار شدیم. مسیری که می‌توانیم از ظرفیت توجه بالای او به جزئیات، مطالعه مستندات به شکل دقیق و علاقه شدیدش به فهم جدیدترین توسعه‌هایی که در دنیای اندروید اتفاق می افتد، استفاده کنیم.مارس ۲۰۲۴به سراغ قدم نهایی رفتیم. در ابتدا تصور ما این بود که KSP با Build Flavor ها به درستی کار نمی‌کند و باید برای پیاده‌سازی چیزی جز آن، زمان قابل توجهی صرف کنیم. همینطور برداشت اشتباه دیگری داشتیم و آن این بود که اگر پروژه اندرویدی با Hilt پیاده‌سازی شده است، امکان استفاده از آن در ماژول مربوط به اندروید وجود ندارد و باید حتما به کتابخانه دیگری تبدیل شود. برای این منظور به سراغ Kotlin Inject رفتم و تبدیل پروژه JVM از Dagger به KI را انجام دادم. آقای عابدینی به سراغ پروژه اندرویدی رفت و آن تبدیل را پیگیری کرد. با این حال این تبدیل (که فعلا نیازی به انجامش نداشتیم)، به ما به مشترک‌سازی بخش بیشتری از پروژه‌ها در قسمت DI انجامید. همزمان ابتدا تمامی ماژول‌های Java/Kotlin و سپس تمامی Android Library ها به پروژه JVM منتقل شد.در نهایت ساختار پروژه KSP با اضافه شدن یک ماژول از نوع Kotlin Multiplatform به نام shared شکل گرفت و وابستگی به پروژه JVM داده شد. برای پروژه اندرویدی، وابستگی مخصوص پلتفرمی در ماژول shared تعریف نشد و پروژه اندرویدی صرفا به بخش common این ماژول وابسته شد. با اجرای پروژه در هر یک از دو پلتفرم، خیالمان راحت شد که بالاخره هر چند جزئی، یک پروژه KMP داریم که باید تلاش کنیم بهبودش بدهیم.نکات پایانی۱. از ابتدا اصلی‌ترین هدف فنی ما، ادغام تمامی پروژه‌ها بود. ولی بیشتر زمان ما صرف پیاده‌سازی نیازهای کسب‌وکار می‌شد. زمانی که شاید اگر کمی زودتر به این هدف فنی رسیده‌ بودیم، با اتلاف زمان کمتری مواجه می‌شدیم. با توجه به پایداری KMP، به نظرم بهترین زمان برای یکی کردن پروژه‌ها، همین الان باشد.۲. تیم پروژه Room در حال توسعه تسک‌هایی است تا بتواند به صورت یک کتابخانه KMP منتشر شود.۳. من، محمد سهرابی، مهدی بهمن‌پور و در نهایت محسن عابدینی را می‌توانید در لینکدین پیدا کنید.۴. من هر هفته برای روزهای پنجشنبه تعدادی جلسه رایگان نیم ساعته در ADPList تنظیم کرده‌ام که در صورت نیاز می‌توانید قرار جلسه‌ای تنظیم نمایید.</description>
                <category>سید عماد رضوی</category>
                <author>سید عماد رضوی</author>
                <pubDate>Thu, 11 Apr 2024 10:25:52 +0330</pubDate>
            </item>
                    <item>
                <title>روش ساده دانلود هر کتاب خارجی</title>
                <link>https://virgool.io/@razavioo/%D8%B1%D9%88%D8%B4-%D8%B3%D8%A7%D8%AF%D9%87-%D8%AF%D8%A7%D9%86%D9%84%D9%88%D8%AF-%D9%87%D8%B1-%DA%A9%D8%AA%D8%A7%D8%A8-%D8%AE%D8%A7%D8%B1%D8%AC%DB%8C-mpjoe0uakt8r</link>
                <description>پیدا کردن کتاب های خارجی سخته ؟ اگر یک روش ساده برای جستجوی کتاب ها توی گوگل باشه چطور ؟-inurl:htm -inurl:html intitle:&quot;index of&quot; +(&quot;/ebooks&quot;|&quot;/book&quot;) +(chm|pdf|zip) +&quot;BookName&quot;کافیه نوشته بالا رو توی گوگل بزنید و به جای BookName، اسم کتابی که می خواهید دانلود کنید رو وارد کنید.</description>
                <category>سید عماد رضوی</category>
                <author>سید عماد رضوی</author>
                <pubDate>Sun, 26 Apr 2020 10:36:02 +0430</pubDate>
            </item>
                    <item>
                <title>مراقب آپدیت کتابخانه RETROFIT خود باشید</title>
                <link>https://virgool.io/@razavioo/watchoutforretrofit-zxku3put0tj0</link>
                <description>دوستان عزیز می خواستم یک تجربه ای رو باهاتون در میون بذارم. چند هفته قبل برای یک برنامه عجله ای، داشتم لحظه های آخر، برنامه رو روی چند تا از گوشی های دوستان نصب می کردم که متوجه شدم که یکی از دستگاه‌ها خطای عجیبی میده. خطای من به OkHTTP ارتباط داشت که من ازش به عنوان کلاینت retrofit استفاده کرده بودم. این خطا توی نسخه های قبل از ورژن 5 اندروید مشاهده می شد. این کتابخانه به عنوان dependency به صورت کلی توی اون نسخه retrofit من اضافه شده بود. با یک مقدار مطالعه توی سایت‌ها متوجه شدم که OkHTTP به صورت کلی در نسخه های جدید تر خودش، به دلایل امنیتی پشتیبانی خودش رو از ورژن های پایین تر اندروید، یعنی قبل از اندروید 5، حذف کرده. بعد از کلی جستجوی دیگه، به یک صفحه راهنما توی یک سایت بر خوردم.مراقب آپدیت رتروفیت باشیدhttps://cashapp.github.io/2019-02-05/okhttp-3-13-requires-android-5پیشنهاد می کنم حتما مطالعه بکنید. خیلی اطلاعات خوبی داده که چرا این اتفاق افتاده و چرا پشتیبانی از بین رفته. و در نهایت با بررسی changelog کتابخونه retrofit متوجه شدم که آخرین نسخه ای که هنوز این مشکل رو نداره، نسخه 2.6.4 خواهد بود و بعد از اون، یا بایستی ورژن اندروید minimum رو روی اندروید 5 بذارید (API 21) یا اینکه جستجو کنید در مورد اینکه چطوری میشه با وجود نسخه های پایین تر اندروید، از امکانات نسخه جدید OkHTTP استفاده کرد. من هنوز راهکار مناسبی پیدا نکردم. شما پیشنهادی دارید؟</description>
                <category>سید عماد رضوی</category>
                <author>سید عماد رضوی</author>
                <pubDate>Sun, 01 Mar 2020 12:13:58 +0330</pubDate>
            </item>
                    <item>
                <title>آمار بازدید مطالب من در سال ۹۷</title>
                <link>https://virgool.io/@razavioo/%D8%A2%D9%85%D8%A7%D8%B1-%D8%A8%D8%A7%D8%B2%D8%AF%DB%8C%D8%AF-%D9%85%D8%B7%D8%A7%D9%84%D8%A8-%D9%85%D9%86-%D8%AF%D8%B1-%D8%B3%D8%A7%D9%84-%DB%B9%DB%B7-ondxc8f1unli</link>
                <description>من در سال گذشته، در مجموع ۱ مقاله در ویرگول منتشر کردم. در طول این سال مقالات من ۸ مرتبه لایک شدند و ۴ نظر نیز بر روی آن‌ها ارسال شد. با مطالعه این مقالات، ۳ نفر تصمیم گرفتند تا من را در ویرگول دنبال کنند تا از مقالات بعدی من باخبر شوند.مخاطبیندر طول این سال، مقالات من توسط ۱۵۸ نفر در ویرگول مطالعه شده است. مدت زمانی که این افراد در حال مطالعه‌ی آن‌ها بوده‌اند برابر با ۶,۶۸۹ ثانیه است. اگر فرض کنیم در حال حاضر جمعیت ایران ۸۰ میلیون نفر است، این یعنی من توانسته‌ام سرانه مطالعه کشورم ایران را ۰/۰۰۰۰۸۴ ثانیه افزایش دهم. شاید بتوانیم این عدد را به «اثر پروانه‌ای» تشبیه کنیم؛ چرا که هر کدام از نویسندگان در ویرگول توانسته‌ایم عددی کوچک را به سرانه مطالعه کشور اضافه کنیم اما مجموعِ تک تکِ این اعداد، یک عدد بزرگ شده است. من در کنار سایر کاربرانِ ویرگول توانستیم در سال ۹۷، سرانه مطالعه ایران را ۴/۱۲۲۳۴۳ ثانیه افزایش دهیم.می‌توانیم برای سال ۹۸، اتفاقات بزرگتری را رقم بزنیم.ویدیوی آمار مخاطبین من را ببینید: https://cdn.virgool.io/annual-report-97/cei56nljowrl-i7T0.mp4 </description>
                <category>سید عماد رضوی</category>
                <author>سید عماد رضوی</author>
                <pubDate>Thu, 28 Mar 2019 00:22:37 +0430</pubDate>
            </item>
                    <item>
                <title>آموزش مینی فریم ورک فلسک</title>
                <link>https://virgool.io/coderlife/flask-open-source-ebook-abec0qna5mnq</link>
                <description>از آنجایی که منابع آموزشی فریم ورک فلسک در وب فارسی چندان زیاد نیست، تصمیم گرفتم آموزش متنی سایت pluralsight رو ترجمه بکنم. پروژه ترجمه خود رو هم توی گیت لب به صورت آزاد قرار دادم تا اگه از دوستان کسی اشتباهی دید، خودش تغییرش بده تا من اصلاحش بکنم.کتاب آموزش فلسکدو پاراگراف اول کتاب رو در ادامه می تونید بخونید.فریم ورک برنامه تحت وب یا به بیان ساده تر، فریم ورک وب شامل مجموعه ای از کتابخانه ها و ماژول هایی ست که به یک توسعه دهنده برنامه تحت وب امکان می دهد که برنامه ها را بدون درگیری با جزئیات سطح پایین مانند پروتکل ها، مدیرت تردها بنویسد. فلسک، فریمورک توسعه برنامه های تحت وب برای زبان برنامه نویسی پایتون است. Ronacher Armin توسعه دهنده آن است که گروه علاقه مندان به پایتون با نام Pocco را نیز رهبری می کند. فلسک بر پایه ابزار WSGI Werkzeug و موتور نشانه گذاری Jinja٢ کار می کند که هر دو از پروژه های Ronacher هستند.برای دانلود کتاب به پروژه متن باز آموزش فلسک بروید و فایل PDF رو برای خواندن آموزش و یا فایل TEX را برای ویرایش فایل لاتکس پروژه دانلود فرمایید.</description>
                <category>سید عماد رضوی</category>
                <author>سید عماد رضوی</author>
                <pubDate>Fri, 04 Jan 2019 10:03:38 +0330</pubDate>
            </item>
            </channel>
</rss>