۶ مفهوم لازم انگولار برای تسلط بر معماری آن – به زبان ساده


در این مقاله با 6 مفهوم مهم انگولار آشنا خواهیم شد که هر توسعهدهنده انگولار برای تسلط یافتن بر این کتابخانه و طراحی اپلیکیشنهای با معماری مناسب باید بر آنها مسلط باشد. انگولار یکی از بزرگترین فریمورکهای جاوا اسکریپت محسوب میشود و قابلیتهای زیادی را به صورت آماده در اختیار ما قرار میدهد. از این رو برای کسب تسلط بر این فریمورک نیاز به یادگیری مفاهیم اندکی وجود دارد.
شش مفهوم خاص وجود دارند که هر توسعهدهنده انگولار باید به صورت عمیقی با آنها آشنا باشد تا بتواند به خوبی اپلیکیشنهای با معماری مناسب را بنویسد. این کار نیازمند بررسی سورس کد خود فریمورک انگولار نیست، گرچه این کار هم فواید زیادی دارد.
یک معماری برای هابهای کامپوننت کلود
هابهای کامپوننت کلود مانند Bit.dev به صورت گستردهای برای انتشار، مستندسازی و سازماندهی کامپوننتهای انگولار استفاده میشوند. ما از آنها برای بیشینهسازی استفاده مجدد از کد و ساختن اپلیکیشنهایی که مقیاسپذیری مناسبی دارند استفاده میکنیم.
چنان که در ادامه این راهنما خواهیم دید، یک معماری مناسب انگولار ما را مطمئن میسازد که کدبیس به ترتیبی ساخته شده است که امکان اشتراک و استفاده مجدد از کامپوننتها را به روشی آسان در میان ریپازیتوریهای مختلف فراهم میسازد.
معماری ماژول/کتابخانه
معماری ماژول انگولار تا حدودی منحصر به فرد است و احتمالاً درک آن از دید افراد مبتدی یکی از دشوارترین بخشها محسوب میشود. پیچیدهترین مفهوم در مورد معماری ماژول انگولار این است که ما از قبل از یک معماری ماژول دیگر بر مبنای آن استفاده میکنیم. بله ما در مورد ایمپورتهای ES صحبت میکنیم.
از آنجا که ماژولهای انگولار یک لایه اضافی روی گروهبندی منطقی اضافه میکند لازم است که آنها را تا حد امکان با همدیگر مرتبط نگهداری کنیم. اما از سوی دیگر دانستن شیوه جداسازی و افراز کارکردهای اپلیکیشن در ماژولهای خوشتعریف نیز یک جزء کلیدی از معماری اپلیکیشنهای انگولار به حساب میآید.
انواع مختلف ماژولهای انگولار
در این بخش با انواع مختلف ماژولهای انگولار آشنا میشویم.
- ماژول اعلانها/ویجت؛ برای نمونه ماژولی که مجموعهای از کامپوننتهای UI، دایرکتیوها و Pipe-ها را شامل میشود.
- ماژول سرویسها؛ برای نمونه HttpClientModule
- ماژول مسیریابی
- ماژول دامنه/قابلیت
- ماژول هسته/مشترک
کتابخانه یا ماژول
شاید برخی استدلال کنند که همین تمایز را میتوان در سطح کتابخانه نیز قائل شد. برای نمونه میتوانیم یک کتابخانه برای سرویسها، یک کتابخانه برای مسیر و از این دست داشته باشیم. اما این که بخواهید یک کتابخانه یا ماژول بنویسید به مقداری زیادی به نوع پروژه و این که از یک پروژه تک ریپازیتوری یا چند ریپازیتوری استفاده میکنید، بستگی دارد.
سؤالاتی که باید پیش از نوشتن یک ماژول پاسخ داد
پیش از نوشتن یک ماژول چند سؤال وجود دارد که باید از خود بپرسید.
- میخواهیم چه نوع ماژولی بنویسیم؟ اگر این نتوانید به سؤال پاسخ بدهید، باید با انواع مختلف ماژولهایی که در بخش قبل اشاره کردیم آشنا شوید.
- آیا این ماژول برای خود یک کتابخانه خواهد بود یا صرفاً یک ماژول است؟ پاسخ به این سؤال کمی دشوارتر است. اگر از یک پروژه تک ریپازیتوری استفاده میکنید، ساخت کتابخانه در بلند مدت گزینه مناسبتری خواهد بود.
جداسازی دغدغهها بین کامپوننتها، سرویسها و دایرکتیوها
جداسازی دغدغهها از لحاظ نظری ساده است، اما در عمل دشوارتر از آن چیزی است که به نظر میرسد. ما از روزهای Angular.js به خاطر داریم که باید کامپوننتها را سبک و سرویسها را سنگین بسازیم و از نظر بنیادی در نسخههای جدید تفاوت زیای در این خصوص ایجاد نشده است.
با این حال باید درک کرد که چه چیزی به کامپوننت تعلق دارد و چه چیزی به سرویس مربوط میشود و چرا دایرکتیوها چنین قابلیتهای کمتر توجهشدهای محسوب میشوند.
حالت (State)
چه دادهها در خارج از کامپوننت به اشتراک گذاشته شوند و مورد دسترسی قرار گیرند و چه لوکال و کپسولهسازیشده باشند، در هر صورت درک محل قرارگیری حالت حائز اهمیت بالایی است.
- اگر حالت بین کامپوننتها به اشتراک گذاشته میشود یا اگر لازم است که از سوی سرویسها مورد دسترسی قرار گیرد، در این صورت باید آن را در یک سرویس قرار دارد. در این وضعیت در عمل مهم نیست شما از چه ابزار مدیریت حالت استفاده میکنید، فقط کافی است درون یک سرویس قرار داشته باشد.
- اگر حالت (مانند یک فرم) به صورت لوکال است و تنها درون یک کامپوننت مورد استفاده قرار میگیرد، در این صورت آن را در یک کامپوننت ذخیره کنید.
دستکاری DOM
اغلب کارهای مرتبط با دستکاریِ DOM احتمالاً بهتر است درون دایرکتیوها انجام شوند. فرض کنید میخواهید یک کارکرد «کشیدن و رها کردن» (Drag and Drop) را به یکی از کامپوننتهای خود اضافه کنید. بدیهی است که به این منظور میتوانید یک کامپوننت ایجاد کرده و رویدادها از طریق آن متصل سازید، اما در این زمان دو چیز با هم مخلوط میشوند:
- شیوه نمایش ظاهری کامپوننتها
- شیوه رفتار قابلیت یک کامپوننت خاص.
دایرکتیوها مسئول قابلیت استفاده مجدد در انگولار هستند و به طور معمول عادت نداریم در پروژهها چنان که باید و شاید از آنها استفاده کنیم. دایرکتیوها میتوانند برای کاستن از مقدار زیادی از مسئولیتهای کامپوننتها مورد استفاده قرار گیرند.
تغییر تشخیص و رندرینگ
زمانی که بحث رندر مجدد UI را در نظر میگیریم، انگولار یک فریمورک کاملاً جادویی به نظر میآید. با این حال بهینهسازی آن برای رندر مجدد صرفاً در مواردی که مورد نیاز است بحث کاملاً متفاوتی محسوب میشود و نیاز به اندکی دانش و شهود عمیق دارد.
شما به عنوان یک معمار انگولار احتمالاً میدانید که تشخیص تغییر به روش OnPush موجب بهینهسازی عملکرد میشود. اما همه چیز همواره مطابق انتظار ما پیش نمیرود. این موضوع به خصوص در مواردی که از Observable-ها و از pipe ناهمگام درون قالبهای خود استفاده نمیکنید بیشتر به چشم میآید.
تسلط بر تشخیص تغییر
برای این که تسلط خوبی بر موضوع تشخیص تغییر پیدا کنید، باید کار را به روش زیر آغاز کنید:
- با همه دادههای خود طوری رفتار کنید که گویی تغییرناپذیر (immutable) هستند. در این زمینه استفاده از کتابخانههای مدیریت حالت نیرو گرفته از RX کمک زیادی میکنند.
- برای نمایش دادهها در قالبهایتان صرفاً (یا غالباً) از Observable-ها استفاده کنید. اگر از حالت لوکال استفاده میکنید از یک BehaviorSubject بهره بگیرید.
- تسلط یافتن بر مبحث تشخیص تغییر یک گام الزامی در مسیر ساخت اپلیکیشنهای با کارایی بالا محسوب میشود، چون شما نه تنها باید مطمئن شوید چه زمانی یک بهروزرسانی مورد نیاز است، بلکه باید این اطمینان را پیدا کنید که بهروزرسانیها صرفاً در موارد لازم اجرا شوند.
شکستن حدود سرعت انگولار
کاهش رندر مجدد یکی از رموز سریع و کارآمد ساختن اپلیکیشنها است. با این حال، برخی اوقات، ممکن است لازم باشد حدود سرعت اپلیکیشنهایی که شدیداً نیازمند کارایی بالا هستند مانند بازیها، بهروزرسانیهای با فراوانی بالا و لیستهای بزرگ و پیچیده را بشکنید. این کار به کمک حذف Zone و بهروزرسانی UI با کمک جدیدترین قابلیتهای Ivy ممکن شده است.
مسیریابی
مسیریابی نه تنها به ما امکان میدهد که SPA خود را در چندین صفحه مجازی سازماندهی کنیم، بلکه موجب میشود که به لطف قابلیتهای «بارگذاری کند» (lazy-loading) مسیریابی در انگولار، باندلهای اپلیکیشن را بسته به تقاضا بارگذاری کنیم.
اگر روی اپلیکیشن بزرگی کار میکنید و اندازه باندلها از 1 مگابایت تجاوز میکنند، احتمالاً دلیل اهمیت این موضوع را میدانید. در عمل هیچ کس نمیخواهد این حجم از دادهها را برای یافتن امکان تعامل با اپلیکیشن دانلود کند.
مسیریابی باید نه تنها برای افراز مسیرهای سطح فوقانی، بلکه برای عرضه بخشهای کوچکتر و عمیقتر UI نیز اجرا شود. بدین ترتیب میتوانید محتوای باندل را افراز کنید و همچنین بخشهای کوچکتر اپلیکیشن را که لازم نیست تا زمانی که کاربر آنها را درخواست کرده است، روی دستگاهش دانلود شوند، نیز جدا کنید.
مثال: یک کامپوننت زبانهدار
برای نمونه فرض کنید مشغول ساخت یک رابط کاربری زبانهدار (Tabbed) و هر زبانه از دیگری مستقل است. این یک موقعیت مناسب برای افراز هر زبانه در مسیر خاص خود و استفاده از بارگذاری کُند برای بارگذاری صرفاً محتوای زبانه انتخاب شده است.
نمونه دیگر Popup-ها و Modal-ها هستند. هیچ نیازی به بارگذاری آنها همراه با باندل اولیه وجود ندارد. اگر کاربر آنها را درخواست کند، یعنی در صورت نیاز میتوان آنها را بارگذاری کرد.
فرمها
اغلب اپلیکیشنهای CRUD اساساً از فرمهای مختلف تشکیل یافتهاند. در این موارد ممکن است وقت زیادی را صرف نوشتن فرمها بکنید و به همین جهت یادگیری Angular Forms نیز حائز اهمیت است.
اغلب فرمها احتمالاً باید با استفاده از ماژول ReactiveFormsModule نوشته شوند و از این رو از اتصال دوطرفه با ngModel رها میشویم، مگر این که یک کنترل ساده داشته باشید. درک API مربوط به Angular Forms کاملاً ساده است و کسب مهارت عموماً به مطالعه مستندات و یادگیری دامهای خاص آن مربوط است.
دام اصلی که در زمان کار با Angular Forms باید از آن آگاه باشید، این است که اساساً فاقد نوعبندی است. این موضوع احتمالاً آزاردهندهترین بخش آن است و جز این قابلیتی عالی محسوب میشود. بنابراین باید بسیار مراقب باشید تا مطمئن شوید که فرمها با انواع ساحتمان داده شما همخوانی دارند.
RxJS
آخرین نکته مهم که در مورد انگولار بررسی میکنیم RxJS که شهرت منفی زیادی کسب کرده است. میتوان گفت که یکی از قدرتمندترین قابلیتهای انگولار، یکپارچگی عمیق آن با Rx و برنامهنویسی واکنشی تابعی است. برای این که انگولار را عمیقاً یاد بگیرید و یک معماری عالی خلق نمایید، باید ابتدا Rx و یا دست کم عملگرهای مهمتر آن را بیاموزید. تبدیل شدن به یک توسعهدهنده ماهر انگولار بدون صرف ساعتها وقت برای درک Rx کاری دشوار به نظر میآید.
دست کم دو دلیل برای این که یادگیری Rx در زمان نوشتن اپلیکیشنهای انگولار مفید است، میتوان برشمرد؟ یکی افزایش کارایی و دیگری پردازش ناهمگام است. پردازش ناهمگام در اپلیکیشنهای مدرن که قابلیتهای تعاملی مختلف دارند به میزان زیادی دشوار است. از این رو باید Promise ،setTimeout و setInterval را فراموش کنید و شروع به انجام کارها به شیوه Rx نمایید.
دلیل مهم دیگر برای کسب مهارت در Rx بهینهسازی عملکرد است. بدیهی است که استفاده از pipe ناهمگام صرفاً یک شروع محسوب میشود و گاهی اوقات کافی نیست. کنترل رندرهای مجدد تنها از طریق pipeline کردن رویدادهای که نیاز به رندر مجدد دارند ممکن است. Rx طیفی از عملگرها ارائه میکند که به کش کردن و دستهبندی عملیات کمک میکند و از این رو موجب بهینهسازی عملکرد اپلیکیشن میشود.
سخن نهایی
در این مقاله به صورت اجمالی به بررسی برخی از نکات مهم برای یادگیری عمیق انگولار پرداختیم. اما موارد مورد نیاز برای یادگیری به این فهرست محدود نمیشود. در هر حال هرگز فراموش نکنید که برای کسب مهارت در هر موضوع مرتبط با وب باید ابتدا مبانی وب را یاد بگیرید که شامل جاوا اسکریپت، CSS، الگوهای طراحی، کد تمیز، ابزارهای توسعه وب و مواردی از این دست میشوند.
اگر این مطلب برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای JavaScript (جاوا اسکریپت)
- آموزش مقدماتی AngularJS برای ساخت اپلیکیشنهای تکصفحهای
- مجموعه آموزشهای برنامهنویسی
- پارامترهای URL در انگولار — به زبان ساده
- نوشتن قالب پیچیده برای انگولار — به زبان ساده
==