زمانیکه پروژهی شما وابستگیهای متعددی داشته باشد، احتمال برخوردن به یک چنین خطایی بسیار محتمل است:
کتابخانهی Newtonsoft.Json جزو پروژههایی است که مدام به روز رسانی و نگهداری میشود. در این بین ممکن است وابستگی A از نگارش 4.5 آن استفاده کند و وابستگی B بر اساس نگارش 4.7 آن کامپایل شده باشد و وابستگی جدیدی از نگارش 6 آن استفاده کند. در یک چنین حالتی زمانیکه پروژهی شما آخرین نگارش JSON.NET را به همراه داشته باشد، وابستگیهای A و B پیام یافت نشدن نگارشهای خاص کتابخانهی Newtonsoft.Json را صادر خواهند کرد و در این حالت، برنامه در همان ابتدای کار کرش میکند. برای رفع این مشکل میتوان به دات نت گفت که تمام درخواستهای مرتبط با JSON.NET را به اسمبلی خاصی هدایت و پردازش کن. به این قابلیت assembly redirects گفته میشود و به نحو ذیل در فایلهای کانفیگ برنامه (app.config یا web.config) قابل تعریف است:
به این ترتیب تمام اسمبلیهایی که بر اساس نگارش قدیمی JSON.NET کامپایل شدهاند، باور خواهند کرد که نگارش 6 آن، همان نگارشی است که باید با آن کار کنند.
به روز رسانی قسمت assembly redirects توسط NuGet
البته اگر بستهی جدیدی را توسط نیوگت نصب کنیم، این assembly redirects به صورت خودکار توسط آن اضافه خواهند شد اما ... گاهی ممکن است موارد قدیمی را به روز نکند یا موردی فراموش شوند یا حتی اگر اطلاعاتی را پیشتر از وب یافتهاید، دارای خطای تایپی باشند. برای یک چنین مواردی اگر با خطای Could not load file or assembly ابتدای بحث مواجه شدید، مراحل ذیل را طی کنید تا بتوانید قسمت assembly redirects را بازسازی کنید:
الف) به فایل config برنامه مراجعه کرده و کلا قسمت assemblyBinding آنرا حذف کنید.
ب) سپس دستور ذیل را در کنسول پاورشل نیوگت اجرا کنید:
این دستور به تمام پروژههای موجود در solution جاری مراجعه کرده و قسمت assemblyBinding آنها را بر اساس آخرین اطلاعات پروژهها و وابستگیهای آنها به روز میکند.
Could not load file or assembly Newtonsoft.Json or one of its dependencies. The system cannot find the file specified.
<?xml version="1.0" encoding="utf-8"?> <configuration> <!-- ... --> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" /> </dependentAssembly> </assemblyBinding> </runtime> </configuration>
به روز رسانی قسمت assembly redirects توسط NuGet
البته اگر بستهی جدیدی را توسط نیوگت نصب کنیم، این assembly redirects به صورت خودکار توسط آن اضافه خواهند شد اما ... گاهی ممکن است موارد قدیمی را به روز نکند یا موردی فراموش شوند یا حتی اگر اطلاعاتی را پیشتر از وب یافتهاید، دارای خطای تایپی باشند. برای یک چنین مواردی اگر با خطای Could not load file or assembly ابتدای بحث مواجه شدید، مراحل ذیل را طی کنید تا بتوانید قسمت assembly redirects را بازسازی کنید:
الف) به فایل config برنامه مراجعه کرده و کلا قسمت assemblyBinding آنرا حذف کنید.
ب) سپس دستور ذیل را در کنسول پاورشل نیوگت اجرا کنید:
PM> Get-Project -All | Add-BindingRedirect
تا قسمت سوم توانستیم Xamarin را نصب و پروژهی اولیه آن را بیلد کنیم. سپس کد مشترک بین سه پلتفرم را بر روی Windows اجرا و Edit & continue آن را هم تست کردیم که هم برای UI ای که با Xaml نوشته میشود و هم برای منطقی که با CSharp نوشته میشود، کار میکند.
همانطور که گفتیم، کد UI و Logic برای هر سه پلتفرم مشترک است؛ منتهی به علت امکانات دیباگ فوق العاده و سرعت بیشتر ویندوز، ابتدا آن را بر روی ویندوز تست کردیم و بعد برای تکمیل UI، آن را بر روی Android اجرا میکنیم. این بار میتوانید دو پروژه UWP و iOS را Unload کنید و سپس پروژه Android ای را در صورت Unload بودن Load کنید. (با راست کلیک نمودن روی پروژه). این کار باعث میشود Visual Studio بیهوده کند نشود؛ مخصوصا اگر سیستم شما ضعیف است.
ابتدا با موبایل یا تبلت اندرویدی شروع میکنیم. اگر چه Xamarin از نسخهی 4.0.3 اندروید به بالا را پشتیبانی میکند، ولی توصیه میکنم وقتتان را بر روی گوشیهای اندرویدی کمتر از 4.4 تلف نکنید. دستگاه را میتوانید، هم به صورت USB و هم به صورت Wifi استفاده کنید. ابتدا باید دستگاه اندرویدی خود را آمادهی برای دیباگ کنید. برای این منظور مقالههای فارسی و انگلیسی زیادی وجود دارند که میتوانید از آنها استفاده کنید. من عبارت "اندروید debug" را جستجو کردم و به این مقاله رسیدم. همچنین Android SDK شما باید USB debugging اش نصب شده باشد که البته حجم زیادی ندارد. برای بررسی این مورد ابتدا از وجود فولدر extras\google\usb\_driver درAndroid SDK خود مطمئن شوید. حال سؤال این است که ویژوال استودیو، Android SDK را کجا نصب کردهاست که خیلی ساده در این لینک توضیح داده شدهاست.
اگر فولدر extras\google\usb\_driver وجود نداشت، باید آن را نصب کنید که خیلی ساده توسط Android SDK Manager امکان پذیر است؛ ولی نه! امکان پذیر نیست!
دلیل: در Xamarin شما همیشه بر روی آخرین SDKها حرکت میکنید. این شامل Windows SDK 17134 و Android SDK 27 و iOS SDK 11 است. وقتی از نسخهی فعلی ویژوال استودیو، یعنی 15.8 به نسخهی بعدی ویژوال استودیو که الان Preview است بروید، یعنی 15.9، عملا به این معنا است که به Windows SDK 17763 و Android SDK 28 و iOS SDK 12 میروید. این بزرگترین مزیت Xamarin است و این یعنی شما همیشه به صد در صد امکانات هر پلتفرم در زبان CSharp دسترسی دارید و همیشه آخرین SDK هر سیستم عامل در اختیار شماست و اگر دوستی از طریق Swift توانست مثالی از ARKit 2.0 را در iOS 12 پیاده سازی کند، قطعا شما هم میتوانید. همچنین تیم Xamarin نه تنها این امکانات را بلکه Documentation لازم را نیز در اختیار شما قرار میدهد. چون در همین مثال، مستندات Apple به زبان Swift / Objective-C بوده و مستندات Xamarin به زبان CSharp.
حال اگر سری به فولدر Android SDK نصب شدهی توسط Visual Studio بزنید، مشاهده میکنید که خبری از Android SDK Manager نیست! به صورت رسمی، مدتی است که گوگل در نسخههای اخیر Android SDK، دیگر Android SDK Manager را ارائه نمیکند و همانطور که گفتم شما الان بر روی آخرین نسخهی Android SDK هستید. هر چند ترفندهایی وجود دارد که این Manager را باز میگردانند، ولی لزومی به انجام این کار در Xamarin نیست و شما میتوانید از Android SDK Manager ای که تیم Xamarin ارائه دادهاست، استفاده کنید. همین مسئله در مورد Android Virtual Device Manager که برای مدیریت Emulatorها بود نیز صدق میکند.
برای استفاده از این دو، ضمن استفاده از ابزارهای دور زدن تحریم، در ویژوال استودیو، در منوی Tools، به قسمت Android رفته و Android SDK Manager را باز کنید. Android Emulator Manager نیز جایگزین Android Virtual Device Manager ای است که قبلا توسط گوگل ارائه میشد. حال بعد از باز کردن Android SDK Manager ارائه شده توسط Xamarin، به برگهی Tools آن بروید و از قسمت extras مطمئن شوید که Google USB driver تیک خورده باشد.
حال پس از وصل کردن گوشی یا تبلت اندرویدی به سیستم توسط کابل USB و Set as startup project نمودن پروژهی XamApp.Android که در قسمت قبل آن را Clone کرده بودید، میتوانید پروژه را بر روی گوشی خود اجرا کنید. اگر نام گوشی خود را در کنار دکمهی سبز اجرای پروژه (F5) نمیبینید، بستن و باز کردن Visual Studio را امتحان کنید.
پروژه را که اجرا کنید، اولین بیلد کمی طول میکشد (اولین بار دو برنامه بر روی گوشی شما نصب میشوند که برای کار دیباگ در Xamarin لازم هستند) و اساسا بیلد یک پروژهی اندرویدی کند است. خوشبختانه به واسطه وجود Xaml edit and continue احتیاجی به Stop - Start کردن پروژه و بیلد کردن برای اعمال تغییرات UI نیست و به محض تغییر Xaml، میتوانید تاثیر آن را در گوشی خود ببینید. ولی برای هر تغییر CSharp باید Stop - Start و Build کنید که زمان بر است و به همین علت تست بر روی پروژه ویندوزی را برای پیاده سازی منطق برنامه پیشنهاد میکنیم. البته در نسخهی 15.9 ویژوال استودیو، سرعت بیلد تا 40% بهبود یافته است.
ممکن است شما گوشی اندرویدی یا تبلت نداشته باشید که بخواهید بر روی آن تست کنید و یا مثلا گوشی شما Android 7 هست و میخواهید بر روی Android 8 تست بگیرید. در این جا شما احتیاج به استفاده از Emulator را خواهید داشت.
توجه داشته باشید که Emulator شما ترجیحا نباید ARM باشد و بهتر است یا X86 یا X64 باشد، وگرنه ممکن است خیلی کند شود. همچنین بهتر است Google Play Services داشته باشد. همچنین ترجیحا دنبال گزینهی اجرا کردن Emulator نروید؛ اگر خود ویندوز شما درون یک Virtual Machine در حال اجراست.
ابتدا ضمن جستجو کردن "فعال سازی intel virtualization"، اقدام به فعال سازی این امکان در سیستم خود کنید. این آموزش را مناسب دیدم.
گزینههای مطرح: [Google Android Emulator] - [Genymotion] - [Microsoft Hyper-V Android Emulator] که فقط یکی از آنها را لازم دارید.
Google Android Emulator توسط خود Google ارائه میشود و دارای Google Play Services نیز هست. بر اساس این آموزش به صفحه Workloads در Visual Studio Installer بروید و از قسمت Xamarin دو مورد "Google Android Emulator API Level 27" و "Intel Hardware Accelerated Execution Manager (HAXM) global install" را نصب کنید. توجه داشته باشید که بدین منظور احتیاج به ابزارهای دور زدن تحریم دارید؛ زیرا نیاز به دسترسی به سرورهای گوگل هست. این Emulator آماده برای دیباگ هست و نیازی به اقدام خاصی نیست.
Genymotion حجم کمتری دارد و برای دانلود احتیاج به ابزارهای دور زدن تحریم را ندارد و اساسا نسبت به بقیه بر روی سیستمهای ضعیفتر، بهتر کار میکند. فقط Emulator ای که با آن میسازید، به صورت پیش فرض Google Play Services را ندارد که در آخرین نسخههای آن گزینه Open GApps به toolbar اضافه شده که Google Play Services را اضافه میکند. (از انجام هر گونه عملیات پیچیده بر اساس آموزشهایی که برای نسخههای قدیمیتر Genymotion هستند، پرهیز کنید). مطابق با ابتدای همین آموزش برای دستگاههای اندرویدی، Emulator خود را آماده برای دیباگ کنید.
Microsoft Hyper-V android emulators. مایکروسافت قبلا اقدام به ارائه یک Android Emulator کرده بود که برای نسخه 4 و 5 اندروید بودند و بزرگترین ضعف آنها عدم پشتیبانی از Google Play Services بود که ادامه داده نشدند. ولی سری جدید ارائه شده توسط مایکروسافت چنین مشکلی را ندارد. اگر CPU شما AMD بوده و روشهای قبلی برای شما کند هستند یا اساسا کار نمیکنند، یا در حال حاضر در حال استفاده از Docker for Windows هستید که از Hyper-V استفاده میکنید و قصد استفاده مجدد از منابع موجود را دارید، این نیز گزینه خوبی است که جزئیات آن را میتوانید در اینجا دنبال کنید. این Emulator آماده برای دیباگ هست و نیازی به اقدام خاصی نیست.
پس از اینکه Emulator خود را ساختید، آن را اجرا کنید. سپس برنامه را از درون ویژوال استدیو اجرا کنید. مطابق نسخه ویندوزی، دوباره یک دکمه دارید و یک Label، عدد بر روی Label، با هر بار کلیک کردن بر روی دکمه، افزایش مییابد.
سرعت اجرای این برنامه در Emulator یا گوشی شما برای دیباگ است و در حالت Release، سرعت چندین برابر بهتر خواهد شد و به هیچ وجه تستهای Performance را بر روی Debug mode انجام ندهید.
حال نوبت به پابلیش پروژه میرسد. در این قسمت باید توجه کنید که حجم Apk شما برای پروژهی XamApp مثال ما به 7 مگ میرسد که برای یک فرم ساده خیلی زیاد به نظر میرسد. ولی اگر شما بجای یک فرم ساده، صد فرم پیچیده نیز داشته باشید، باز هم این حجم به 8 مگ نخواهد رسید. حجم Apk خیلی متاثر از کدهای شما نیست، بلکه شامل موارد زیر است:
1- NET. که خود شامل CLR & BCL است. (BCL (Base Class Library مثل کلاسهای string - Stream - List - File و (CLR (Common language runtime که شامل موارد لازم برای اجرای کدها است. این پیاده سازی بر اساس NET Standard 2.0. بوده که عملا اجازه استفاده از تعداد خیلی زیادی از کتابخانههای موجود را میدهد، حتی Entity framework core! البته هر کتابخانه حجم DLLهای خودش را اضافه میکند.
2- Android Support libraries که به شما اجازه میدهد از تعداد زیادی (و البته نه همه) امکانات نسخههای جدید اندروید در پروژهتان استفاده کنید که بر روی نسخ قدیمیتر Android نیز کار کنند. همچنین با یکپارچگی با Google Play Services عملا خیلی از کارها سادهتر و با Performance بهتری انجام میشود، مانند گرفتن موقعیت کاربر جاری.
3- Xamarin essentials . اگر چه در CSharp شما به صد در صد امکانات هر سیستم عامل دسترسی دارید و میتوانید مثلا مقدار درصد شارژ باطری را بخوانید، ولی اینکار مستلزم نوشتن سه کد CSharp ای برای Android - iOS - Windows است که طبیعتا کار را سخت میکند. اما Xamarin Essentials به شما اجازه میدهد با یک کد CSharp واحد برای هر سه پلتفرم، با باطری، کلیپبورد، قطب نما و خیلی موارد دیگر کار کنید.
4- Xamarin.Forms. اگر Button و Label ای که در مثال برنامه داشتیم، با یکبار نوشتن بر روی هر سه پلتفرم دارند کار میکنند، در حالی که هر پلتفرم، Button مخصوص به خود را دارد؛ این را Xamarin Forms مدیریت میکند. علاوه بر این، Binding نیز به عهدهی Xamarin Forms است.
5- Prism - Autofac - Bit Framework: درک آنها نیاز به دنبال کردن آموزشهای این دوره را دارد؛ ولی به صورت کلی معماری پروژه شما بسیار کارآمد و حرفهای خواهد شد و به کدی با قابلیت نگهداری بالا خواهید رسید.
6- Rg Plugins Popup و Xamanimation نیز دو کتابخانهی UI بسیار کاربردی و جالب هستند که در طول این آموزش از آنها استفاده خواهد شد.
حجم 7 مگ برای این تعداد کتابخانه و امکان، خیلی زیاد نیست و شما عملا تعداد زیادی از پروژههای خود را میتوانید با همین حجم ببندید و اگر مثلا به پروژهی Humanizer خیلی علاقه داشته باشید (که در این صورت حق هم دارید!) میتوانید با اضافه شدن چند کیلوبایت (!) به پروژه آن را داشته باشید. اکثر کتابخانههای NET. ای سبک هستند. همچنین موقع قرار گرفتن در پروژه، فشرده سازی نیز میشوند و قسمتهای استفاده نشدهی آنها نیز توسط Linker حذف میشوند.
علاوه بر این، اجرای برنامه بر روی گوشیهای ضعیف و قدیمی کمی طول میکشد. این مربوط به اجرای برنامه است؛ نه باز شدن فرم مثال ما که دارای Button و Label بود و اگر مثال ما دو فرم داشته باشد (که در آموزشهای بعدی به آن میرسیم) میبینید که چرخش بین فرمها بسیار سریع است.
مواردی مهم در زمینهی بهبود عملکرد پروژههای Xamarin در Android
در ابتدا باید بدانید Apk شما شامل دو قسمت است؛ یکی کدهای CSharp ای شما که DotNet ای بوده و در کنار کدهای کتابخانههایی چون Json.NET بر روی DotNet اجرا میشوند. دیگری کتابخانهای است که مثلا با Java نوشته شده و بعد برای استفاده در CSharp بر روی آن یک Wrapper یا پوشاننده توسعه داده شدهاست. عموما توسعه دهندگان چنین پروژههایی، ابتدا پروژه را به Java مینویسند و بعد برای JavaScript - CSharp و ... Wrapper ارائه میدهند.
برای بهبود اینها ابزارهایی چون AOT-NDK-LLVM-ProGurad-Linker و ... وجود دارند که سعی میکنم به صورت ساده آنها را توضیح دهم.
وظیفه ProGurad این است که از قسمتی از پروژهی شما که بخاطر کتابخانههای Java ای، عملا DotNet ای نیست، کدهای اضافه و استفاده نشده را حذف کند.
ممکن است استفاده از ProGurad باعث شود کلاسی که داینامیک استفاده شده است، به اشتباه حذف شود. پروژه XamApp دارای یک ProGuard configuration file است که جلوی چنین اشتباهاتی را حتی الامکان میگیرد.
همچنین ProGurad که در داخل Android SDK قرار دارد، به Space در طول مسیر حساس است (!) و با توجه به اینکه مسیر پیش فرض Android SDK نصب شدهی توسط ویژوال استودیو دارای Space است (C:\Program Files (x86)\Android\android-sdk) شما در همان ابتدا دچار مشکل میشوید! برای حل این مشکل ابدا فولدر Android SDK را جا به جا نکنید؛ بلکه از امکانی در ویندوز به نام Junction folder یا فولدر جانشین استفاده کنید. بدین منظور دستور زیر را وارد کنید:
mklink /j C:\android-sdk "C:\Program Files (x86)\Android\android-sdk"
این مورد باعث میشود که مسیر C:\android-sdk نیز به همان مسیر پیش فرض اشاره کند و این دو مسیر در واقع یکی هستند. امیدوارم این امکان را با قابلیت Shortcut سازی در ویندوز اشتباه نگیرید! حال از منوی Tools > Options > Xamarin > Android Settings مسیر Android SDK را به C:\android-sdk تغییر دهید که فاقد Space است و ویژوال استودیو را ببندید و باز کنید.
NDK که در ادامه SDK برای Android قرار میگیرد، Native Development Kit است و باعث میشود هم DLLهای DotNet ای و هم Jarهای Java ای به فایلهای so تبدیل شوند. so همان DLL ویندوز است، البته برای Linux و همانطور که احتمالا میدانید، پایه Android بر روی Linux است. طبیعتا کامپایل شدن کدها به so، بر روی بهبود سرعت برنامه تاثیر گذار است.
Linker نیز مشابه با ProGuard کمک میکند، ولی اینبار حجم DLLهای DotNet ای مانند Json.NET را کم میکند. بالاخره شما از صد در صد کلاسهای یک DLL استفاده نمیکنید و موارد اضافی نیز باید حذف شوند. البته این وسط، امکان حذف اشتباه کلاسهایی که به صورت داینامیک فراخوانی شده باشند وجود دارد که LinkerConfig موجود در پروژه XamApp حتی الامکان جلوی این مشکل را میگیرد.
Release mode مثل هر پروژه CSharp ای دیگری، بهتر است پروژه در حالت Release mode پابلیش شود. در پروژه XamApp در حالت Release mode، موارد بالا یعنی Linker-NDK-ProGuard نیز درخواست میشوند.
جزئیات این موارد در مستندات Xamarin وجود دارد و در پایان این دوره یک Project Builder سورس باز نیز به شما ارائه میشود که ساختار اولیه پروژهها را بر اساس نیازهای شما و با بهترین تنظیمات ممکن میسازد.
در پروژه XamApp علاوه بر موارد فوق، دو مورد دیگر نیز آماده به استفاده هستند، ولی غیر فعال شده اند؛ AOT و LLVM. اگر به تازگی برنامه نویس شدهاید، موارد زیر ممکن است خیلی برایتان پیچیده باشند، از آنها عبور کنید و به عنوان "نحوه انجام دادن پابلیش" بروید.
کدهایهای DotNet ای به سه شکل میتوانند اجرا شوند:
JIT - AOT - Interpreter
یک برنامه DotNet ای برای اجرا میتواند از ترکیب اینها استفاده کند. حالت Interpreter که خیلی جدید معرفی شده و الآن موضوع بحث نیست؛ میماند JIT و AOT
کد CSharp در هنگام کامپایل به IL تبدیل و سپس در زمان اجرا توسط Just in time compiler به زبان ماشین تبدیل میشود. اگر قبلا پروژهی ASP.NET یا ASP.NET Core نوشته باشید، چنین رفتاری را در پشت صحنه خواهد داشت. خود JIT که در هر بار اجرای برنامه انجام میشود، عملا زمان بر هست. ولی کد زبان ماشین حاصل از آن خیلی Optimize شده برای دقیقا همان ماشین هست؛ با در نظر گرفتن خیلی فاکتورها. در پروژههای سمت سرور مثل ASP.NET که پروژه وقتی یک بار اجرا میشود، مثلا روی IIS، ممکن است صدها هزار دستور را اجرا کند، در طول چندین روز یا ماه، این عمل JIT خیلی مفید هست. البته همان سربار اولیهی JIT هم توسط چیزی به عنوان Tiered JIT میتواند کمتر شود.
اما در پروژهی موبایل که برنامه ممکن است بعد از باز شدن، مثلا ده دقیقه باز باشد و بعد بسته شود، انجام شدن JIT با هر بار باز شدن برنامه خیلی مفید به فایده نیست. بنا به برخی مسائل که واقعا سطح این آموزش را خیلی پیچیده میکند، نتیجه کار JIT قابلیت Cache شدن آن چنانی ندارد و عملا باید هر بار اجرا شود.
در پروژههای موبایل، گزینه دیگری بر روی میز هست به نام Ahead of time یا AOT که کار تبدیل IL به زبان ماشین را در زمان کامپایل و پابلیش پروژه انجام دهد. طبیعتا این باعث میشود سرعت برنامه موبایل در عمل خیلی بالاتر رود، چون سربار JIT در هر بار اجرای برنامه حذف میشود. همچنین روال AOT میتواند از LLVM یا Low level virtual machine استفاده کند که منجر به تبدیل شدن کد زبان ماشینی میشود که بر روی LLVM کار میکند. LLVM خودش یک Runtime با سرعت خیلی بالاست که بر روی تمامی سیستم عاملها کار میکند.
بر روی Android - iOS - Windows میشود از AOT استفاده کرد. در iOS و ویندوز، استفادهی از AOT منجر به افزایش سایز برنامه نمیشود، چون قبلا برنامه یک سری کد IL بوده که زمان اجرا توسط JIT به کد ماشین تبدیل میشده و الان بجای آن IL، یک سری کد زبان ماشین مبتنی بر LLVM هست. اما بر روی Android، پیاده سازی AOT ناقص هست و البته که با فعال کردناش، سرعت برنامه بسیار بیشتر میشود، ولی کماکان نیاز به JIT و IL هم برای برخی از سناریوها هست. این مورد یعنی اینکه فعال سازی AOT+LLVM بر روی اندروید تا مادامی که AOT در Android به صورت آزمایشی هست، باعث افزایش حجم Apk ما از 7 به 13 مگ میشود. البته این مورد در نسخههای بعدی رفع خواهد شد و رفتار Android مشابه با iOS-Windows خواهد بود؛ یعنی حجم نسبتا کم و سرعت خیلی بالا.
برای فعال سازی AOT+LLVM در csproj پروژه اندرویدی، دو مقدار AotAssemblies و EnableLLVM را از false به true تغییر دهید:
<AotAssemblies>true</AotAssemblies> <EnableLLVM>true</EnableLLVM>
با این تنظیمات، بیلد شما طولانیتر و در عوض سرعت اجرای برنامه بیشتر خواهد شد.
نحوه انجام دادن پابلیش
برای انجام دادن پابلیش، بر روی پروژه XamApp.Android در هنگامیکه بر روی Release mode هستید، راست کلیک کنید و Archive را بزنید. سپس فایل Archive شده را انتخاب و Distribute را بزنید که به شما Apk مناسب برای انتشار توسط خودتان یا Google Play میدهد.
نکات مهم:
1- فایل Apk حاصل از Archive را بدون Distribute کردن، در اختیار کسی قرار ندهید. فقط پیام Corrupt و خراب بودن فایل، حاصل کارتان خواهد بود!
2- اولین باری که Distribute میکنید، Wizard مربوطه کمک میکند تا یک فایل Certificate را برای Apk اتان بسازید. آن فایل را گم نکنید! در پابلیشهای بعدی دیگر نباید Certificate جدیدی بسازید؛ بلکه فایل قبلی را باید به آن معرفی کنید و فقط رمز آن Certificate را دوباره بزنید.
3- به برنامه آیکون بدهید. برای آن Splash Screen خوبی بگذارید. در هر بار پابلیش، ورژن برنامه را افزایش دهید. اینها همگی توضیحات اش بر روی بستر وب موجود است. سؤالی بود، همینجا هم میتوانید بپرسید.
فایلهای Apk این مثال را میتوانید از اینجا دانلود کنید.
در قسمت بعدی آموزش، دیباگ و پابلیش گرفتن پروژه بر روی iOS را خواهیم داشت که البته مقداری از مطالب اش با مطالب این آموزش مشترک هست. بعد دست به کد شده و آموزش CSharp و Xaml را خواهیم داشت تا پروژهای با کیفیت، کارآمد و عالی از هر جهت بنویسید.
همچنین تعدادی از نکات مربوط به Performance که مربوط به ظاهر برنامه و نحوه چیدمان صفحات و کنترلها هستند و بر روی Performance هر سه پلتفرم تاثیر گذار هستند (و نه فقط Android) نیز در ادامه بحث خواهند شد.
تفاوتی نمیکند در چه رشتهای یا حرفهای مشغول به کار هستید؛ تفاوتی نمیکند در چه زمینهای قصد دارید مطلبی را منتشر کنید. برای تهیه یک مطلب خوب و ماندگار، باید یک سری اصول کلی را در نوشتن رعایت کرد که در ادامه به مرور آنها خواهیم پرداخت.
1) مطلب شما نیاز به مقدمه دارد
نیاز به مقدمه داشتن به معنای نوشتن کلمه «مقدمه» در ابتدای یک متن نیست. به این معنا است که به خواننده بگوئید مشکل کجا بوده یا به چه دلیلی قصد دارید مطلب جاری را منتشر کنید. بنابراین جهت تهیه یک مطلب خوب، یک راست اصل مطلب را شروع نکنید. لازم است چند سطری در مورد علت انتشار آن توضیح دهید.
2) پیش از انتشار مطلب چندبار آنرا مطالعه کنید
یک مطلب خوب نیاز به جمله بندی مناسب، استفاده از نقطه، ویرگول و امثال آن دارد و بدون استفاده از آنها متن شما هرچقدر هم حرفهای باشد، خواندنش مشکل خواهد بود و جلوه مناسبی نخواهد داشت.
3) سعی کنید در عنوان مطلب خود از کلمات کلیدی استفاده کنید
استفاده از کلمات کلیدی در عنوان مطالب، جستجوی آنها را برای خواننده سادهتر کرده و همچنین کمک بزرگی است به موتورهای جستجو در یافتن نتایجی بهتر.
4) تکرار کلمات و جملات یکسان را در متن خود به حداقل برسانید
برای مثال مدام در متن خود جمله «همانطور که ملاحظه میکنید» را تکرار نکنید. استفاده از افعال تکراری و جملات تکراری در یک متن باید حداقل باشند. برای نمونه اگر جمله جاری به «میشود» ختم خواهد شد، جمله بعدی را به «میگردد» ختم کنید. اگر جملهای دارای کلمات «برای مثال» است، جمله بعدی بهتر است به همراه کلمات «برای نمونه» باشد.
5) از جملات طولانی استفاده نکنید
یک جمله باید حداکثر یک سطر یا یک سطر و نصفی طول داشته باشد و گرنه خواننده را به شدت در دنبال کردن آن به زحمت خواهید انداخت. جملات طولانی را به جملاتی کوتاهتر خرد کنید.
6) استفاده از علامت تعجب را به حداقل برسانید
اشخاصی که مدام از چندین علامت تعجب پشت سرهم استفاده میکنند یا مدام از علامت سؤال به همراه چندین علامت تعجب بهره میگیرند، حس مسخره کردن شخص مقابل و همچنین عدم تعادل روانی خود را القاء میکنند.
7) در متن خود از تصاویر استفاده کنید
انسان موجودی است بصری. قدرت یادگیری ما از طریق دیدن چند برابر زمانی است که از طریق شنیدن یا خواندن نسبت به فراگیری مطلبی اقدام میکنیم.
« ما ...
10 درصد چیزهایی را که میخوانیم
20 درصد چیزهایی را که میشنویم
30 درصد چیزهایی را که میبینیم
50 درصد چیزهایی را که میبینیم و میشنویم
70 درصد چیزهایی را که در موردشان بحث میکنیم
80 درصد چیزهایی را که تجربه میکنیم
95 درصد چیزهایی را که به دیگران میآموزیم
... یاد میگیریم
»
8) اگر در سایتی مطلب مینویسید، اهداف کلی آنرا حفظ کنید
اگر نام سایت شما برنامه نویسی است، خواننده به دنبال شعر، داستان و یا مطالب خیلی شخصی و خصوصی شما نمیگردد. سایتهای زیادی هستند که به این مقولهها میپردازند و خیلی زود سطح کاری خود را به این ترتیب به حداقل تنزل خواهید داد.
9) به صفحات داخلی سایت خود لینک دهید
در مطلب تهیه شده سعی کنید به مطالب مشابه داخلی سایت خود لینک دهید. احتمال کپی شدن مطالب شما بسیار زیاد است. به این ترتیب میتوانید خوانندهها را در لابلای متن خود به مرجع اصلی هدایت کنید.
10) دست به اختراع برچسبهای جدید، پراکنده و بیهوده نزنید
اگر گروه بندی مطالب یک سایت بر اساس برچسبها است و تاکنون برچسبهای متعددی تعریف شده است، بهتر است از همانها استفاده کنید تا اینکه دست به اختراع زده و یک برچسب کاملا جدید را ثبت کنید. برای مثال اگر مطلب شما در مورد Entity framework است و تا کنون 20 مطلب ذیل این گروه ثبت شده، اختراع برچسب جدید EF Code first نه تنها کمکی نخواهد کرد، بلکه خوانندهای را که به دنبال یافتن مطالب یک گروه خاص است، سر در گم میکند. یا اگر قصد دارید یک برچسب کاملا جدید را اضافه کنید، حتما از یک برچسب کلی موجود نیز استفاده کنید تا روابط بین مطالب حفظ شوند.
11) مطالب شما بهتر است یک قسمت نتیجه گیری نیز داشته باشد
بهتر است در پایان یک مطلب، خلاصه بحث، پیشنهادها یا حتی سؤالاتی را مطرح کنید تا بتوانید خواننده را تا حدودی وادار به عکس العمل نمائید.
12) تا حد امکان از منابع سایت خود استفاده کنید
اگر قرار است تصویری در متن قرار گیرد، اگر نیاز است فایلی در سایت مطرح شود، بهتر است این موارد در سایت جاری هاست شوند؛ تا اینکه تصویر یک سایت دیگر را مستقیما در سایت خود لینک کنیم.
13) معرفی منابع
نیازی نیست در یک سایت، همانند مقالات علمی، در انتهای مطلب لیست منابع را ذکر نمود. در اینجا میشود قسمتی از جملات را به منبع استفاده شده لینک کرد. به این ترتیب دقیقا مشخص میشود هر قسمت و هر جملهای از چه ماخذی استفاده کرده و پیگیری آن سادهتر میشود.
14) تصاویر ارائه شده را فشرده کنید
فرمت مناسب ارائه تصویر در یک سایت bmp نیست. بهترین فرمت برای سایتها png است؛ از لحاظ حفظ تعداد رنگ و همچنین کاهش حجم. به علاوه ابزارهای زیادی برای کاهش حجم فایلهای png با حداقل افت کیفیت وجود دارند.
15) در مورد کدهای خود توضیح دهید
این مورد خصوصا به سایتهای برنامه نویسی مرتبط میشود. اینکه چند سطر کد بدون توضیح را در یک مطلب قرار دادهاید، نه لطفی است و نه اهمیتی دارد! هزاران هزار سطر از این دست کدها در GitHub، CodPlex و sourceforge وجود دارند. فرق کار شما با آنها در چیست؟
باید یک قسمت «توضیحات» ذیل کدهای ارائه شده وجود داشته باشد. همان نکاتی را که حین تهیه کدها در ذهن داشتید باید بتوانید توضیح دهید و گرنه ... کار شما ارزشی نخواهد داشت.
16) مطالب تجربی شما باید قابلیت تولید مجدد داشته باشند
برای مثال امروز در حین کار به یک مطلب جدید برخوردهاید که قصد دارید آنرا به اشتراک بگذارید. ذکر این نکته جدید به تنهایی کافی نیست. باید ابتدا بتوانید ذهن خواننده را جهت رسیدن به وضعیتی که قرار داشتید، آماده کنید. اگر قصد دارید قطعه کدی را به اشتراک بگذارید، خواننده باید بتواند این قطعه از پازل را در کنار قطعات دیگری که برای او ترسیم خواهید کرد، جای دهد. یا حداقل بتواند قطعه کد شما را بدون خطا کامپایل کند.
17) یک راست به سراغ کدنویسی و اصل مطلب نروید
اگر قرار است در مورد یک فناوری جدید در طی چند جلسه بحث کنید، لازم است یک جلسه کامل در مورد «چرا به این فناوری نیاز داریم» توضیح دهید. بنابراین ذکر اینکه بدون مقدمه به سراغ کدنویسی میرویم، سؤالات بسیاری را به جا خواهند گذاشت مانند ... «مشکل روشهای قبلی چی هست؟» «مزیت این روش جدید در کجاست؟» و تا نتوانید این مسایل را شرح دهید، کار شما خریدار نخواهد داشت.
18) در زبان فارسی نیم فاصلهها را رعایت کنید
در نگارش زبان فارسی فرق است بین «آمده ام» و «آمدهام» و یا «می شود» را باید «میشود» نوشت. میشود اندکی وقت گذاشت و با مبحث نیم فاصله آشنا شد .
در کل کار کردن در یک محیط گروهی و چند نویسندهای، به مرور زمان تجربههایی را به همراه خواهند داشت که با به اشتراک گذاشتن آنها و یا طرح صریح آنها، میتوان از تکرار اشتباهات متداول جلوگیری کرد.
1) مطلب شما نیاز به مقدمه دارد
نیاز به مقدمه داشتن به معنای نوشتن کلمه «مقدمه» در ابتدای یک متن نیست. به این معنا است که به خواننده بگوئید مشکل کجا بوده یا به چه دلیلی قصد دارید مطلب جاری را منتشر کنید. بنابراین جهت تهیه یک مطلب خوب، یک راست اصل مطلب را شروع نکنید. لازم است چند سطری در مورد علت انتشار آن توضیح دهید.
2) پیش از انتشار مطلب چندبار آنرا مطالعه کنید
یک مطلب خوب نیاز به جمله بندی مناسب، استفاده از نقطه، ویرگول و امثال آن دارد و بدون استفاده از آنها متن شما هرچقدر هم حرفهای باشد، خواندنش مشکل خواهد بود و جلوه مناسبی نخواهد داشت.
3) سعی کنید در عنوان مطلب خود از کلمات کلیدی استفاده کنید
استفاده از کلمات کلیدی در عنوان مطالب، جستجوی آنها را برای خواننده سادهتر کرده و همچنین کمک بزرگی است به موتورهای جستجو در یافتن نتایجی بهتر.
4) تکرار کلمات و جملات یکسان را در متن خود به حداقل برسانید
برای مثال مدام در متن خود جمله «همانطور که ملاحظه میکنید» را تکرار نکنید. استفاده از افعال تکراری و جملات تکراری در یک متن باید حداقل باشند. برای نمونه اگر جمله جاری به «میشود» ختم خواهد شد، جمله بعدی را به «میگردد» ختم کنید. اگر جملهای دارای کلمات «برای مثال» است، جمله بعدی بهتر است به همراه کلمات «برای نمونه» باشد.
5) از جملات طولانی استفاده نکنید
یک جمله باید حداکثر یک سطر یا یک سطر و نصفی طول داشته باشد و گرنه خواننده را به شدت در دنبال کردن آن به زحمت خواهید انداخت. جملات طولانی را به جملاتی کوتاهتر خرد کنید.
6) استفاده از علامت تعجب را به حداقل برسانید
اشخاصی که مدام از چندین علامت تعجب پشت سرهم استفاده میکنند یا مدام از علامت سؤال به همراه چندین علامت تعجب بهره میگیرند، حس مسخره کردن شخص مقابل و همچنین عدم تعادل روانی خود را القاء میکنند.
7) در متن خود از تصاویر استفاده کنید
انسان موجودی است بصری. قدرت یادگیری ما از طریق دیدن چند برابر زمانی است که از طریق شنیدن یا خواندن نسبت به فراگیری مطلبی اقدام میکنیم.
« ما ...
10 درصد چیزهایی را که میخوانیم
20 درصد چیزهایی را که میشنویم
30 درصد چیزهایی را که میبینیم
50 درصد چیزهایی را که میبینیم و میشنویم
70 درصد چیزهایی را که در موردشان بحث میکنیم
80 درصد چیزهایی را که تجربه میکنیم
95 درصد چیزهایی را که به دیگران میآموزیم
... یاد میگیریم
»
8) اگر در سایتی مطلب مینویسید، اهداف کلی آنرا حفظ کنید
اگر نام سایت شما برنامه نویسی است، خواننده به دنبال شعر، داستان و یا مطالب خیلی شخصی و خصوصی شما نمیگردد. سایتهای زیادی هستند که به این مقولهها میپردازند و خیلی زود سطح کاری خود را به این ترتیب به حداقل تنزل خواهید داد.
9) به صفحات داخلی سایت خود لینک دهید
در مطلب تهیه شده سعی کنید به مطالب مشابه داخلی سایت خود لینک دهید. احتمال کپی شدن مطالب شما بسیار زیاد است. به این ترتیب میتوانید خوانندهها را در لابلای متن خود به مرجع اصلی هدایت کنید.
10) دست به اختراع برچسبهای جدید، پراکنده و بیهوده نزنید
اگر گروه بندی مطالب یک سایت بر اساس برچسبها است و تاکنون برچسبهای متعددی تعریف شده است، بهتر است از همانها استفاده کنید تا اینکه دست به اختراع زده و یک برچسب کاملا جدید را ثبت کنید. برای مثال اگر مطلب شما در مورد Entity framework است و تا کنون 20 مطلب ذیل این گروه ثبت شده، اختراع برچسب جدید EF Code first نه تنها کمکی نخواهد کرد، بلکه خوانندهای را که به دنبال یافتن مطالب یک گروه خاص است، سر در گم میکند. یا اگر قصد دارید یک برچسب کاملا جدید را اضافه کنید، حتما از یک برچسب کلی موجود نیز استفاده کنید تا روابط بین مطالب حفظ شوند.
11) مطالب شما بهتر است یک قسمت نتیجه گیری نیز داشته باشد
بهتر است در پایان یک مطلب، خلاصه بحث، پیشنهادها یا حتی سؤالاتی را مطرح کنید تا بتوانید خواننده را تا حدودی وادار به عکس العمل نمائید.
12) تا حد امکان از منابع سایت خود استفاده کنید
اگر قرار است تصویری در متن قرار گیرد، اگر نیاز است فایلی در سایت مطرح شود، بهتر است این موارد در سایت جاری هاست شوند؛ تا اینکه تصویر یک سایت دیگر را مستقیما در سایت خود لینک کنیم.
13) معرفی منابع
نیازی نیست در یک سایت، همانند مقالات علمی، در انتهای مطلب لیست منابع را ذکر نمود. در اینجا میشود قسمتی از جملات را به منبع استفاده شده لینک کرد. به این ترتیب دقیقا مشخص میشود هر قسمت و هر جملهای از چه ماخذی استفاده کرده و پیگیری آن سادهتر میشود.
14) تصاویر ارائه شده را فشرده کنید
فرمت مناسب ارائه تصویر در یک سایت bmp نیست. بهترین فرمت برای سایتها png است؛ از لحاظ حفظ تعداد رنگ و همچنین کاهش حجم. به علاوه ابزارهای زیادی برای کاهش حجم فایلهای png با حداقل افت کیفیت وجود دارند.
15) در مورد کدهای خود توضیح دهید
این مورد خصوصا به سایتهای برنامه نویسی مرتبط میشود. اینکه چند سطر کد بدون توضیح را در یک مطلب قرار دادهاید، نه لطفی است و نه اهمیتی دارد! هزاران هزار سطر از این دست کدها در GitHub، CodPlex و sourceforge وجود دارند. فرق کار شما با آنها در چیست؟
باید یک قسمت «توضیحات» ذیل کدهای ارائه شده وجود داشته باشد. همان نکاتی را که حین تهیه کدها در ذهن داشتید باید بتوانید توضیح دهید و گرنه ... کار شما ارزشی نخواهد داشت.
16) مطالب تجربی شما باید قابلیت تولید مجدد داشته باشند
برای مثال امروز در حین کار به یک مطلب جدید برخوردهاید که قصد دارید آنرا به اشتراک بگذارید. ذکر این نکته جدید به تنهایی کافی نیست. باید ابتدا بتوانید ذهن خواننده را جهت رسیدن به وضعیتی که قرار داشتید، آماده کنید. اگر قصد دارید قطعه کدی را به اشتراک بگذارید، خواننده باید بتواند این قطعه از پازل را در کنار قطعات دیگری که برای او ترسیم خواهید کرد، جای دهد. یا حداقل بتواند قطعه کد شما را بدون خطا کامپایل کند.
17) یک راست به سراغ کدنویسی و اصل مطلب نروید
اگر قرار است در مورد یک فناوری جدید در طی چند جلسه بحث کنید، لازم است یک جلسه کامل در مورد «چرا به این فناوری نیاز داریم» توضیح دهید. بنابراین ذکر اینکه بدون مقدمه به سراغ کدنویسی میرویم، سؤالات بسیاری را به جا خواهند گذاشت مانند ... «مشکل روشهای قبلی چی هست؟» «مزیت این روش جدید در کجاست؟» و تا نتوانید این مسایل را شرح دهید، کار شما خریدار نخواهد داشت.
18) در زبان فارسی نیم فاصلهها را رعایت کنید
در نگارش زبان فارسی فرق است بین «آمده ام» و «آمدهام» و یا «می شود» را باید «میشود» نوشت. میشود اندکی وقت گذاشت و با مبحث نیم فاصله آشنا شد .
در کل کار کردن در یک محیط گروهی و چند نویسندهای، به مرور زمان تجربههایی را به همراه خواهند داشت که با به اشتراک گذاشتن آنها و یا طرح صریح آنها، میتوان از تکرار اشتباهات متداول جلوگیری کرد.
نظرات مطالب
نحوه کار با ftp - بخش اول
ممنون از مطلب شما.
چند نکته جزئی در مورد کدهای تهیه شده:
- وجود این try/catch در اینجا هیچ هدفی رو برآورده نکرده. از قسمت throw ex هم توصیه میشود که استفاده نکنید. از thow خالی استفاده کنید تا stack trace پاک نشه. به علاوه زمانیکه مشغول به طراحی یک کتابخانه هستید تا حد ممکن از ذکر try/catch خودداری کنید. وظیفه بررسی این مسایل مرتبط است به لایههای بالاتر استفاده کننده و نه کتابخانه پایه.
- if ابتدای متد هم ضرورتی ندارد. اگر قرار است باشد، باید به استفاده کننده در طی یک استثناء اعلام شود که چرا فایل درخواستی او آپلود نشده. در کل استفاده از متد File.Exists به همراه صدور استثناء در صورت عدم وجود فایل، در اینجا مناسبتر است.
- نامگذاریهایی مانند obj_ftp مربوط به دوران C است. در سیشارپ روش دیگری رو باید استفاده کنید که در مطلب اصول نامگذاری در دات نت به تفصیل بررسی شده.
- بررسی صفر بودن readBytes بهتر است پیش از فراخوانی متد Write انجام شود.
- یک سری از اشیاء در دات نت پیاده سازی کننده IDispoable هستند. به این معنا که بهتر است از using برای استفاده از آنها کمک گرفته شود تا کامپایلر قسمت finally به همراه آزاد سازی منابع را به صورت خودکار اضافه کند. این نکته برای مواردی که در بین کار استثنایی رخ میدهد جهت آزاد سازی منابع لازم است. یعنی بهتر بود بجای try/catch از try/finally و یا using در مکانهای مناسب استفاده میشد.
- علت استفاده از شیء Application دراینجا چه چیزی بوده؟ AppSettings خوانده شده از وب کانفیگ برنامه و کل اطلاعات آن در آغاز به کار یک برنامه ASP.NET به صورت خودکار کش میشوند. به همین جهت است که اگر حتی یک نقطه در فایل وب کانفیگ تغییر کند برنامه ASP.NET ری استارت میشود (تا دوباره تنظیمات را بخواند). بنابراین مستقیما از همان امکانات ConfigurationManager بدون انتساب آن به شیء سراسری Application استفاده کنید. اینکار سرباری آنچنانی هم ندارد؛ چون از حافظه خوانده میشود و نه از فایل. هر بار فراخوانی ConfigurationManager.AppSettings به معنای مراجعه به فایل web.config نیست. فقط بار اول اینکار انجام میشود؛ تا زمانیکه این فایل تغییر کند یا برنامه ری استارت شود.
چند نکته جزئی در مورد کدهای تهیه شده:
- وجود این try/catch در اینجا هیچ هدفی رو برآورده نکرده. از قسمت throw ex هم توصیه میشود که استفاده نکنید. از thow خالی استفاده کنید تا stack trace پاک نشه. به علاوه زمانیکه مشغول به طراحی یک کتابخانه هستید تا حد ممکن از ذکر try/catch خودداری کنید. وظیفه بررسی این مسایل مرتبط است به لایههای بالاتر استفاده کننده و نه کتابخانه پایه.
- if ابتدای متد هم ضرورتی ندارد. اگر قرار است باشد، باید به استفاده کننده در طی یک استثناء اعلام شود که چرا فایل درخواستی او آپلود نشده. در کل استفاده از متد File.Exists به همراه صدور استثناء در صورت عدم وجود فایل، در اینجا مناسبتر است.
- نامگذاریهایی مانند obj_ftp مربوط به دوران C است. در سیشارپ روش دیگری رو باید استفاده کنید که در مطلب اصول نامگذاری در دات نت به تفصیل بررسی شده.
- بررسی صفر بودن readBytes بهتر است پیش از فراخوانی متد Write انجام شود.
- یک سری از اشیاء در دات نت پیاده سازی کننده IDispoable هستند. به این معنا که بهتر است از using برای استفاده از آنها کمک گرفته شود تا کامپایلر قسمت finally به همراه آزاد سازی منابع را به صورت خودکار اضافه کند. این نکته برای مواردی که در بین کار استثنایی رخ میدهد جهت آزاد سازی منابع لازم است. یعنی بهتر بود بجای try/catch از try/finally و یا using در مکانهای مناسب استفاده میشد.
- علت استفاده از شیء Application دراینجا چه چیزی بوده؟ AppSettings خوانده شده از وب کانفیگ برنامه و کل اطلاعات آن در آغاز به کار یک برنامه ASP.NET به صورت خودکار کش میشوند. به همین جهت است که اگر حتی یک نقطه در فایل وب کانفیگ تغییر کند برنامه ASP.NET ری استارت میشود (تا دوباره تنظیمات را بخواند). بنابراین مستقیما از همان امکانات ConfigurationManager بدون انتساب آن به شیء سراسری Application استفاده کنید. اینکار سرباری آنچنانی هم ندارد؛ چون از حافظه خوانده میشود و نه از فایل. هر بار فراخوانی ConfigurationManager.AppSettings به معنای مراجعه به فایل web.config نیست. فقط بار اول اینکار انجام میشود؛ تا زمانیکه این فایل تغییر کند یا برنامه ری استارت شود.
نظرات مطالب
ASP.NET MVC #10
- Steven Sanderson (عضو تیم ASP.NET MVC) از روش ActionName استفاده میکنه (نویسنده کتاب Pro ASP.NET MVC هم هست). بنابراین روش برگزیده رو میشه این حالت درنظر گرفت. در مورد FormCollection هم در انتهای بحث توضیح دادم. Scaffold هم جهت تولید View مورد استفاده قرار میگیره نه کنترلر و اکشن متدهای آن. البته در این حالت strongly typed ، نیاز به مدل خواهد داشت که خارج از بحث FormCollection است؛ چون loosely typed است و نمیشه Viewایی رو از یک FormCollection استخراج کرد.
- هدف من تکمیل بحث بود. آشنایی با انواع روشهای ممکن.
ضمن اینکه من چند سال قبل به کمک روش Request.Form که توضیح دادم، یک form generator برای ASP.NET Web forms نوشتم. زمانیکه کنترلهای وب فرمها به صورت پویا به صفحه اضافه بشن، دیگه eventها جهت دریافت مقادیر اونها معنا نخواهند داشت (با توجه به اینکه کل صفحه رو بخواهیم پویا تولید کنیم و برنامه چند صد فرم پویا داشته باشد). در اینجا از همین روش Request.Form برای دریافت مقادیر کنترلهای پویای اضافه شده به صفحه استفاده کردم.
- هدف من تکمیل بحث بود. آشنایی با انواع روشهای ممکن.
ضمن اینکه من چند سال قبل به کمک روش Request.Form که توضیح دادم، یک form generator برای ASP.NET Web forms نوشتم. زمانیکه کنترلهای وب فرمها به صورت پویا به صفحه اضافه بشن، دیگه eventها جهت دریافت مقادیر اونها معنا نخواهند داشت (با توجه به اینکه کل صفحه رو بخواهیم پویا تولید کنیم و برنامه چند صد فرم پویا داشته باشد). در اینجا از همین روش Request.Form برای دریافت مقادیر کنترلهای پویای اضافه شده به صفحه استفاده کردم.
نظرات اشتراکها
چرا از آنگولار به ری اکت + ری داکس سوئیچ کردم!
- فسلفه React مبتنی بر مخلوط کردن جاوا اسکریپت و HTML با هم هست در فایلهای JSX (نوشتن HTML با کدهای جاوا اسکریپت). به این صورت شما مزیتهای ذاتی HTML و CSS را یکجا از دست میدید؛ چون دیگه نمیتونید HTML جدا یا CSS جدای از جاوا اسکریپت را داشته باشین. در حالیکه در Angular این دو یا این سه (TypeScript، HTML و CSS) از هم جدا هستند که مزیت آن دسترسی به انواع ادیتورهایی هست که بدون اینکه برای Angular نوشته شده باشند، در همان بدو معرفی آن، با آن سازگار هستند که سادگی توسعه را به همراه داره. شاید تولید کامپوننتهای ساده React تولید شده با کدهای جاوا اسکریپتی ساده باشه، اما کمی که حجم آن بیشتر شد، کنترل و مدیریت این مخلوط، سختتر و سختتر میشه و به علاوه مخلوط کردن کدهای یک فریم ورک با HTML و CSS خیلی شبیه به PHP کلاسیک و یا ASP کلاسیک هست و این روزها کسی را پیدا نمیکنید که برای پروژههای واقعی حتی از PHP در حالت کلاسیک آن بدون یک فریم ورک جانبی استفاده کنه. در Angular از همان بدو امر مباحث طراحی ماژولها، کامپوننتها و جدا سازی کدها به صورت ذاتی طراحی شدهاند.
- مزیت کار کردن با TypeScript در مقایسه با ES6 خالص در React، امکان دسترسی به کامپایل آفلاین هست و مباحث پیشرفتهی کامپایلر مانند tree-shaking (حذف کدهای مرده) و AOT (a head of time compilation) که سبب میشن هم حجم نهایی کمتری تولید شود و هم پیش از اجرای برنامه در مرورگر و سپس یافتن باگهای احتمالی در زمان اجرا، پیش از موعد و توسط کامپایلر این باگها گزارش شوند. اگر قصد داشته باشید به یک چنین کیفیت و بررسی کدی در React برسید، باید تعداد آزمونهای واحد قابل توجهی را داشته باشین تا بتونید یافتن مشکلاتی را که کامپایلر TypeScript گوشزد میکند، شبیه سازی کنید. همچنین شما در TypeScript میتونید به تمام امکانات پیشرفتهی زبان جاوا اسکریپت (حتی پس از ES6) دسترسی داشته باشید، اما کد نهایی جاوا اسکریپتی تولید شدهی توسط آنرا برای ES5 که تمام مرورگرها از آن پشتیبانی میکنند، تولید کنید که این هم خودش یک مزیت مهم هست. بنابراین TypeScript فقط یک static type checker ساده نیست.
- اینکه Angular یک فریمورک هست به خودی خودش یک مزیت مهم هست نسبت به React که یک کتابخانه است و اجزای آن باید از منابع مختلفی تهیه شوند. فریم ورک یعنی به روز رسانیهای منظم تمام اجزای آن توسط خود تیم Angular و سازگاری کامل و یکدست هر جزء با نگارش فعلی یا همان آخرین نگارش موجود. اگر با دنیای وابستگیهای ثالث در یک پروژهی واقعی کار کرده باشید به خوبی میدونید که هر چقدر تعداد آنها کمتر باشند، نگهداری طولانی مدت آن پروژه آسانتر میشود؛ چون روزی ممکن است آن کتابخانهی ثالث دیگر توسعه پیدا نکند، یا منسوخ شود یا دیرتر از آخرین نگارش ارائه شده به روز رسانی شود. مزیت داشتن یک فریم ورک یکدست، درگیر نشدن با این مسایل است؛ خصوصا اینکه عموما کتابخانههای ثالث کیفیتشون در حد کتابخانهی اصلی نیست و اینکه مثلا خود تیم Angular ماژول روتر، اعتبارسنجی یا فرمهای اون رو توسعه میده، قطعا کیفیتشون از کتابخانههای ثالث دیگه بهتر هست.
- در مورد سرعت و کارآیی و حتی مصرف حافظه، مطابق یک benchmarck خیلی معتبر، وضعیت Angular اندکی بهتر از React است؛ هرچند در کل از این لحاظ به هم نزدیک هستند.
- این مباحث انحصاری شدن و اینها هم در مورد محصولات سورس باز، زیاد مفهومی ندارند و بیشتر یکسری شعار ایدئولوژیک هست توسط کسانیکه حتی تغییر رفتار این شرکتها را هم دنبال نمیکنند و منابع و ماخذی رو که مطالعه کردن مربوط به یک دهه قبل هست.
- مزیت کار کردن با TypeScript در مقایسه با ES6 خالص در React، امکان دسترسی به کامپایل آفلاین هست و مباحث پیشرفتهی کامپایلر مانند tree-shaking (حذف کدهای مرده) و AOT (a head of time compilation) که سبب میشن هم حجم نهایی کمتری تولید شود و هم پیش از اجرای برنامه در مرورگر و سپس یافتن باگهای احتمالی در زمان اجرا، پیش از موعد و توسط کامپایلر این باگها گزارش شوند. اگر قصد داشته باشید به یک چنین کیفیت و بررسی کدی در React برسید، باید تعداد آزمونهای واحد قابل توجهی را داشته باشین تا بتونید یافتن مشکلاتی را که کامپایلر TypeScript گوشزد میکند، شبیه سازی کنید. همچنین شما در TypeScript میتونید به تمام امکانات پیشرفتهی زبان جاوا اسکریپت (حتی پس از ES6) دسترسی داشته باشید، اما کد نهایی جاوا اسکریپتی تولید شدهی توسط آنرا برای ES5 که تمام مرورگرها از آن پشتیبانی میکنند، تولید کنید که این هم خودش یک مزیت مهم هست. بنابراین TypeScript فقط یک static type checker ساده نیست.
- اینکه Angular یک فریمورک هست به خودی خودش یک مزیت مهم هست نسبت به React که یک کتابخانه است و اجزای آن باید از منابع مختلفی تهیه شوند. فریم ورک یعنی به روز رسانیهای منظم تمام اجزای آن توسط خود تیم Angular و سازگاری کامل و یکدست هر جزء با نگارش فعلی یا همان آخرین نگارش موجود. اگر با دنیای وابستگیهای ثالث در یک پروژهی واقعی کار کرده باشید به خوبی میدونید که هر چقدر تعداد آنها کمتر باشند، نگهداری طولانی مدت آن پروژه آسانتر میشود؛ چون روزی ممکن است آن کتابخانهی ثالث دیگر توسعه پیدا نکند، یا منسوخ شود یا دیرتر از آخرین نگارش ارائه شده به روز رسانی شود. مزیت داشتن یک فریم ورک یکدست، درگیر نشدن با این مسایل است؛ خصوصا اینکه عموما کتابخانههای ثالث کیفیتشون در حد کتابخانهی اصلی نیست و اینکه مثلا خود تیم Angular ماژول روتر، اعتبارسنجی یا فرمهای اون رو توسعه میده، قطعا کیفیتشون از کتابخانههای ثالث دیگه بهتر هست.
- در مورد سرعت و کارآیی و حتی مصرف حافظه، مطابق یک benchmarck خیلی معتبر، وضعیت Angular اندکی بهتر از React است؛ هرچند در کل از این لحاظ به هم نزدیک هستند.
- این مباحث انحصاری شدن و اینها هم در مورد محصولات سورس باز، زیاد مفهومی ندارند و بیشتر یکسری شعار ایدئولوژیک هست توسط کسانیکه حتی تغییر رفتار این شرکتها را هم دنبال نمیکنند و منابع و ماخذی رو که مطالعه کردن مربوط به یک دهه قبل هست.
نظرات مطالب
EF Code First #1
سلام آقای نصیری
ممنون بخاطر مطالب مفیدتون. EF یک ORM قوی هست ولی بعضی مواردش هست که به نظر بنده نوعی در حد این ORM نیست.که دو موردش رو در اینجا ذکر میکنم :
1) در برنامه های چند لایه اگر لایه ها بصورت پروژه های جداگانه در نظر گرفته شده باشند باید Connection String رو در لایه UI ، BL و DAL قرار داد که به نظر من از لحاظ امنیتی درست نیست. این بهتره که در UI ما اصلا ندونیم COnnection String چی هست. البته این مورد با کد نویسی قابل حل هست ولی در کل مناسب نیست
2) من در کی از پروژه های گروهی به این مسئله برخوردم. ما در قسمت DAL فلدرهای مختلف داشتیم و هر کسی در فلدر قسمتی که کار میکرد میخواست یک دیتا مدل داشته باشه. این کار باعث میشد که به تعداد دیتا مدلها ما Connection String داشته باشیم و اگر میخواستیم از یک Connection String استفاده کنیم اسم کلاسی که تولید میشد برای همه یکسان میبود (اما در Name Space های مختلف) .
به نظر من EF از لحاظ Connection String یک مقدار ضعف داره.تا نظر دوستان چه باشه. ممنون و موفق باشید
ممنون بخاطر مطالب مفیدتون. EF یک ORM قوی هست ولی بعضی مواردش هست که به نظر بنده نوعی در حد این ORM نیست.که دو موردش رو در اینجا ذکر میکنم :
1) در برنامه های چند لایه اگر لایه ها بصورت پروژه های جداگانه در نظر گرفته شده باشند باید Connection String رو در لایه UI ، BL و DAL قرار داد که به نظر من از لحاظ امنیتی درست نیست. این بهتره که در UI ما اصلا ندونیم COnnection String چی هست. البته این مورد با کد نویسی قابل حل هست ولی در کل مناسب نیست
2) من در کی از پروژه های گروهی به این مسئله برخوردم. ما در قسمت DAL فلدرهای مختلف داشتیم و هر کسی در فلدر قسمتی که کار میکرد میخواست یک دیتا مدل داشته باشه. این کار باعث میشد که به تعداد دیتا مدلها ما Connection String داشته باشیم و اگر میخواستیم از یک Connection String استفاده کنیم اسم کلاسی که تولید میشد برای همه یکسان میبود (اما در Name Space های مختلف) .
به نظر من EF از لحاظ Connection String یک مقدار ضعف داره.تا نظر دوستان چه باشه. ممنون و موفق باشید
نظرات مطالب
EF Code First #7
- مشکل کلاس کانفیگ فوق در این است که از یک طرف InverseProperty تعریف کردید، از طرف دیگر در حالت تنظیمات Fluent، این مورد رعایت نشده. مثلا DriverAssistance باید به TransferencesForAssistance (مطابق InverseProperty تعریف شده) مرتبط میشد و الی آخر (الان همگی به یک مورد مرتبط شدن).
- در کل نیازی به کلاس کانفیگ فوق ندارید. حذفش کنید. EF میتونه روابط one-to-many رو بدون کانفیگ خاصی تشخیص بده. علت وجود قسمت هفتم، اعمال یک سری تنظیمات اضافهتر است نسبت به تنظیمات پیش فرض. مثلا اگر از نامهای پیش فرض خرسند نیستید، اینجا میتونید توسط Fluent API خیلی از این موارد رو سفارشی سازی کنید و تغییر بدید. البته شرطش هم این است که از ICollection برای معرفی موارد one-to-many استفاده کنید (که اینکار در کلاس Driver انجام شده، همچنین یک سر دیگر آن به صورت virtual در کلاس مقابل وجود دارد. به علاوه مطلب نحوه تعریف صحیح کلیدهای خارجی را هم اضافه کنید تا طراحی بهتری داشته باشید).
- در کل نیازی به کلاس کانفیگ فوق ندارید. حذفش کنید. EF میتونه روابط one-to-many رو بدون کانفیگ خاصی تشخیص بده. علت وجود قسمت هفتم، اعمال یک سری تنظیمات اضافهتر است نسبت به تنظیمات پیش فرض. مثلا اگر از نامهای پیش فرض خرسند نیستید، اینجا میتونید توسط Fluent API خیلی از این موارد رو سفارشی سازی کنید و تغییر بدید. البته شرطش هم این است که از ICollection برای معرفی موارد one-to-many استفاده کنید (که اینکار در کلاس Driver انجام شده، همچنین یک سر دیگر آن به صورت virtual در کلاس مقابل وجود دارد. به علاوه مطلب نحوه تعریف صحیح کلیدهای خارجی را هم اضافه کنید تا طراحی بهتری داشته باشید).
نظرات مطالب
ASP.NET MVC #11
در قسمت آخر مطلبتون یک ModelBinder سفارشی برای DateTime نوشته شده که روش خوب و مناسبی هست برای جلوگیری از تکرار کد اضافی. اما یک مشکلی که من دارم اینه این روش شما برای گرفتن اطلاعات از کلاینت درست عمل میکنه اما مشکل اینجاست اگر من بخوام این فیلد تاریخ رو به کاربر نشون بدم چه کاری باید انجام بدم؟یعنی من این فیلد رو از دیتابیس خوندم چطور میشه اونو به مقدار شمسی تبدیل کنم و به کاربر نشون بدم ! چون مقدار تاریخ شمسی برای یک DateTime قابل قبول نیست(راهی ک من برای حل مشکل داشتم این بود که یک فیلد String در viewmodelقرار میدادم و مقادیر اونو وقتی اطلاعات از سمت کاربر میومد به مقدار میلادی تبدیل میکردم و در فیلد مربوطه قرار میدادم و وقتی اطلاعات رو از دیتابیس لود میکردم مقدار فیلد تاریخ رو به شمسی تبدیل میکردم و در فیلد string میذاشتم.)