اشتراکها
مطالب
ASP.NET MVC #1
چرا ASP.NET MVC ؟
با وجود فریم ورک پختهای به نام ASP.NET web forms، اولین سؤالی که حین سوئیچ به ASP.NET MVC مطرح میشود این است: «برای چی؟». بنابراین تا به این سؤال پاسخ داده نشود، هر نوع بحث فنی در این مورد بی فایده است.
مزایای ASP.NET MVC نسبت به ASP.NET web forms
1) سادگی نوشتن آزمونهای واحد
مهمترین دلیل استفاده از ASP.NET MVC صرفنظر از تمام دلایل دیگر، بحث طراحی ویژه آن جهت ساده سازی تهیه آزمونهای واحد است. مشکل اصلی نوشتن آزمونهای واحد برای برنامههای ASP.NET web forms، درگیر شدن مستقیم با تمام جزئیات طول عمر یک صفحه است. به علاوه فایلهای code behind هر چند به ظاهر کدهای منطق یک صفحه را از کدهای HTML مانند آن جدا میکنند اما در عمل حاوی ارجاعات مستقیمی به تک تک عناصر بصری موجود در صفحه هستند (حس غلط جدا سازی کدها از اجزای یک فرم). اگر قرار باشد برای این وب فرمها و صفحات، آزمون واحد بنویسیم باید علاوه بر شبیه سازی چرخه طول عمر صفحه و همچنین رخدادهای رسیده، کار وهله سازی تک تک عناصر بصری را نیز عهده دار شویم. اینجا است که ASP.NET web forms گزینهی مطلوبی برای این منظور نخواهد بود و اگر نوشتن آزمون واحد برای آن غیرممکن نباشد، به همین دلایل آنچنان مرسوم هم نیست.
البته شاید بپرسید که این مساله چه اهمیتی دارد؟ امکان نوشتن سادهتر آزمونهای واحد مساوی است با امکان سادهتر اعمال تغییرات به یک پروژه بزرگ. تغییرات در پروژههای بزرگی که آزمون واحد ندارند واقعا مشکل است. یک قسمت را تغییر میدهید، 10 قسمت دیگر به هم میریزند. اینجا است که مدام باید به کارفرما گفت: «نه!»، «نمیشه!» یا به عبارتی «نمیتونم پروژه رو جمع کنم!» چون نمیتونم سریع برآورد کنم که این تغییرات کدام قسمتها را تحت تاثیر قرار میدهند، کجا به هم ریخت. من باید خودم سریع بتونم مشخص کنم با این تغییر جدید چه قسمتهایی به هم ریخته تا اینکه دو روز بعد زنگ بزنند: «باز جایی رو تغییر دادی، یکجای دیگر کار نمیکنه!»
2) دستیابی به کنترل بیشتر بر روی اجزای فریم ورک
در طراحی ASP.NET MVC همهجا interface ها قابل مشاهد هستند. همین مساله به معنای افزونه پذیری اکثر قطعات تشکیل دهنده ASP.NET MVC است؛ برخلاف ASP.NET web forms. برای مثال تابحال چندین view engine، routing engine و غیره توسط برنامه نویسهای مستقل برای ASP.NET MVC طراحی شدهاند که هیچکدام با ASP.NET web forms میسر نیست. برای مثال از view engine پیش فرض آن خوشتان نمیآید؟ عوضش کنید! سیستم اعتبار سنجی توکار آنرا دوست ندارید؟ آنرا با یک نمونه بهتر تعویض کنید و الی آخر ...
به علاوه طراحی بر اساس interface ها یک مزیت دیگر را هم به همراه دارد و آن هم ساده سازی mocking (تقلید) آنها است جهت ساده سازی نوشتن آزمونهای واحد.
3) سرعت بیشتر اجرا
ASP.NET MVC یک سری از قابلیتهای ذاتی ASP.NET web forms را مانند ViewState حذف کرده است. اگر وب را جستجو کنید، برنامه نویسهای ASP.NET web forms مدام از این مساله شکایت دارند و راه حلهای مختلفی را جهت حذف یا فشرده سازی آن ارائه میدهند. ViewState در ابتدای امر جهت شبیه سازی محیط دسکتاپ در وب درنظر گرفته شده بود و مهاجرت سادهتر برنامه نویسهای VB6 به وب، اما واقعیت این است که اگر یک برنامه نویس ASP.NET web forms به اندازه آن توجهی نداشته باشد، ممکن است حجم آن در یک صفحه پیچیده تا 500 کیلوبایت یا بیشتر هم برسد. همین مساله بر روی سرعت دریافت و اجرا تاثیر گذار خواهد بود.
4) کنترلهای ASP.NET web forms آنچنان آش دهنسوزی هم نیستند!
خوب، ViewState حذف شده، بنابراین اکثر کنترلهای ASP.NET web forms هم کاربرد آنچنانی در ASP.NET MVC نخواهند داشت؛ اما واقعیت این است که اکثر اوقات اگر شروع به سفارشی سازی یک کنترل توکار ASP.NET web forms کنید تا مطابق نیازهای کاری شما رفتار کند، پس از مدتی به یک کنترل کاملا از نو بازنویسی شده خواهید رسید! بنابراین در ابتدای امر تا 80 درصد کار اینطور به نظر میرسد که به عجب سرعت بالایی در توسعه دست یافتهایم، اما هنگامیکه قرار است این 20 درصد پایانی را پر کنیم، به این نتیجه خواهیم رسید که این کنترلها با این وضع ابتدایی که دارند قابل استفاده نیستند و نیاز به دستکاری قابل ملاحظهای دارند تا نیازهای واقعی کاری را برآورده کنند.
5) کنترل کامل بر روی HTML نهایی تولیدی
اگر علاقمند به کار با jQuery باشید، مدام نیاز خواهید تا با ID کنترلها و عناصر صفحه کار کنید. پیشتر ASP.NET web forms این ID را یک طرفه و به صورت مقدار منحصربفردی تولید میکرد که جهت کار با فریم ورکهای جاوا اسکریپتی عموما مشکل ساز بود. البته ASP.NET web forms در نگارشهای جدید خود مشکل عدم امکان مقدار دهی ClientId سفارشی را برای کنترلهای وب خود برطرف کرده است و این مورد را میتوان دستی هم تنظیم کرد ولی در کل باز هم آنچنان کنترلی رو خروجی HTML نهایی کنترلهای تولیدی نیست مگر اینکه مانند مورد چهارم یاد شده یک کنترل را از صفر بازنویسی کنید!
همچنین اگر باز هم بیشتر با jQuery و ASP.NET web forms کار کرده باشید میدانید که jQuery آنچنان سنخیتی با ViewState و Postback وب فرمها ندارد و همین مساله عموما مشکلزا است. علاوه بر آن اخیرا مایکروسافت توسعه ASP.NET Ajax خود را تقریبا در حالت تعلیق و واگذار شده به شرکتهای ثالث درآورده است و توصیه آنها استفاده از jQuery Ajax است. اینجا است که مدل ASP.NET MVC سازگاری کاملی را با jQuery Ajax دارد هم از لحاظ نبود ViewState و هم از جنبهی کنترل کامل بر روی markup نهایی تولیدی.
یا برای مثال خروجی پیش فرض یک GridView، جدول HTML ایی است که این روزها همهجا علیه آن صحبت میشود. البته یک سری آداپتور CSS friendly برای اکثر این کنترلها موجود است و ... باز هم دستکاری بیش از حد کنترلهای پیش فرض جهت رسیدن به خروجی دلخواه. تمام اینها را در ASP.NET MVC میشود با معادلهای بسیار باکیفیت افزونههای jQuery جایگزین کرد و از همه مهمتر چون ViewState و مفاهیمی مانند PostBack حذف شده، استفاده از این افزونهها مشکل ساز نخواهد بود.
6) استفاده از امکانات جدید زبانهای دات نتی
طراحی اصلی ASP.NET web forms مربوط است به دوران دات نت یک؛ زمانیکه نه Generics وجود داشت، نه LINQ و نه آنچنان مباحث TDD یا استفاده از ORMs متداول بود. برای مثال شاید ایجاد یک strongly typed web form الان کمی دور از ذهن به نظر برسد، زمانیکه اصل آن بر مبنای بکارگیری گسترده datatable و dataset بوده است (با توجه به امکانات زبانهای دات نتی در آن دوران). بنابراین اگر علاقمند هستید که این امکانات جدید را بکاربگیرید، ASP.NET MVC برای استفاده از آنها طراحی شده است!
7) از ASP.NET web forms سادهتر است
طراحی ASP.NET MVC بر اساس ایده Convention over configuration است. به این معنا که اجزای آن بر اساس یک سری قرار داد در کنار هم مشغول به کار هستند. مشخص است View باید کجا باشد، نام کنترلرها چگونه باید تعیین شوند و قرار داد مرتبط به آن چیست، مدل باید کجا قرار گیرد، قرار داد پردازش آدرسهای صفحات سایت به چه نحوی است و الی آخر. خلاصه در بدو امر با یک فریم ورک حساب شده که شما را در مورد نحوه استفاده صحیح از آن راهنمایی میکند، مواجه هستید.
به همین ترتیب هر پروژه MVC دیگری را هم که مشاهده کنید، سریع میتوانید تشخیص دهد قراردادهای بکارگرفته شده در آن چیست. بنابراین اگر قرار است ASP.NET را امروز شروع کنید و هیچ سابقهای هم از وب فرمها ندارید، یک راست با ASP.NET MVC شروع کنید.
8) محدود به پیاده سازی مایکروسافت نیست
پیاده سازیهای مستقلی هم از ASP.NET MVC توسط اشخاص و گروههای خارج از مایکروسافت وجود دارد: ^، ^، ^، ^ و ...
و در پایان یکی دیگر از دلایل سوئیچ به ASP.NET MVC ، «یاد گرفتن یک چیز جدید است» یا به عبارتی فرا گرفتن یک روش دیگر برای حل مسایل، هیچگاه ضرری را به همراه نخواهد داشت که هیچ، بلکه باعث بازتر شدن میدان دید نیز خواهد گردید.
یک دیدگاه دیگر
ASP.NET MVC برای شما مناسب نخواهد بود اگر ...
1) با پلیمرفیزم مشکل دارید.
ASP.NET MVC پر است از interfaces، abstract classes، virtual methods و امثال آن. بنابراین اگر تازه کار هستید، ابتدا باید مفاهیم شیءگرایی را تکمیل کنید.
2) اگر نمیتوانید فریم ورک خودتون رو بر پایه ASP.NET MVC بنا کنید!
ASP.NET MVC برخلاف وب فرمها به همراه آنچنان تعداد بالایی کنترل و افزونه از پیش مهیا شده نیست. در بدو امر شما فقط یک سری url helper، html helper و ajax helper ساده را خواهید دید؛ این نقطه ضعف ASP.NET MVC نیست. عمدا به این نحو طراحی شده است. همانطور که عنوان شد اکثر اجزای این فریم ورک قابل تعویض است. بنابراین دست شما را باز گذاشته است تا با پیاده سازی این اینترفیسها، امکانات جدیدی را خلق کنید. البته پس از این چندین و چند سال که از ارائه آن میگذرد، به اندازه کافی افزونه برای ASP.NET MVC طراحی شده است که به هیچ عنوان احساس کمبود نکنید یا اینکه نیازی هم نداشته باشید تا آنچنان فریم ورک خاصی را بر پایه ASP.NET MVC تهیه کنید. برای مثال پروژه MvcContrib موجود است یا شرکت telerik یک مجموعه سورس باز کامل مخصوص ASP.NET MVC را ارائه داده است و الی آخر.
3) اگر نمیتوانید از کتابخانههای سورس باز استفاده کنید.
همانطور که عنوان شد ASP.NET MVC به همراه کوهی از کنترلها ارائه نشده است. اکثر افزونههای آن سورس باز هستند و کار با آنها هم دنیای خاص خودش را دارد. چگونه باید کتابخانههای مناسب را پیدا کرد، کجا سؤال پرسید، کجا باگ گزارش داد، چگونه مشارکت کرد و غیره. خلاصه منتظر یک بسته شکیل حاضر و آماده نباید بود. خود ASP.NET MVC هم تحت مجوز MSPL به صورت سورس باز در دسترس است.
و یک نکته تکمیلی
مایکروسافت مدتی است شروع کرده به پرورش و زمزمه ایده «یک ASP.NET واحد». به عبارتی قصد دارند در یکی دو نگارش بعد، این دو (وب فرم و MVC) را یکی کنند. هم اکنون اگر مطالب وبلاگها را مطالعه کنید زیرساخت آن به نام ASP.NET Web API آماده شده است و در مرحله بتا است. نکته جالب اینجا است که این Web API امکان تعریف یکپارچه و مستقیم کنترلرهای MVC را در وب فرمها میسر میکند. ولی باز هم نام آن Controller است یعنی جزئی از ASP.NET MVC و کسی میتواند از آن استفاده کند که با MVC مشکلی نداشته باشد. بنابراین یادگیری MVC هیچ ضرری نخواهد داشت و جای دوری نخواهد رفت!
در این قسمت قصد داریم ساختار مقدماتی مثال این سری را که لیستی از تصاویر آپلود شدهی توسط کاربران مختلف را نمایش میدهد، بدون افزودن مباحث امنیتی و سطوح دسترسی کاربران وارد شدهی به سیستم، تشکیل دهیم. در قسمتهای بعدی، به تدریج آنرا با قابلیتهای مختلف IdentityServer 4x یکپارچه خواهیم کرد. در اینجا فرض بر این است که حداقل SDK نگارش 2.1.401 را پیشتر نصب کردهاید.
بررسی ساختار WebAPI مقدماتی مثال این سری
این پروژهی مقدماتی که هنوز قسمتهای اعتبارسنجی به آن اضافه نشدهاند، از دو قسمت WebApi و MvcClient تشکیل میشود.
کار قسمت WebApi، ارائهی یک Restful-API برای کار با گالری تصاویر است. برای اجرای آن وارد پوشهی src\WebApi\ImageGallery.WebApi.WebApp شده و ابتدا فایل restore.bat و سپس dotnet_run.bat را اجرا کنید.
در این حالت برنامه بر روی پورت 7001 در دسترس خواهد بود:
این پورت نیز در فایل Properties\launchSettings.json تنظیم شدهاست تا با پورت کلاینت MVC تهیه شده، تداخل نکند.
کار این سرویس، ارائهی ImagesController است که توسط آن میتوان لیستی از تصاویر موجود، اطلاعات یک تصویر و همچنین کار ثبت، ویرایش و حذف تصاویر را انجام داد.
در این Solution، رکوردهای تصاویری که در بانک اطلاعاتی ذخیره میشوند، یک چنین ساختاری را دارند:
همانطور که ملاحظه میکنید در اینجا OwnerId نیز در نظر گرفته شدهاست تا بتوان پس از اعمال مباحث اعتبارسنجی، تصاویر را از کاربری خاص دریافت و همچنین صرفا تصاویر متعلق به او را به آن کاربر خاص نمایش داد.
در این قسمت توسط کلاس ImageConfiguration کار مقدار دهی اولیهی بانک اطلاعاتی به کمک متد HasData مربوط به EF Core 2.1 صورت گرفتهاست و به این ترتیب میتوان برنامه را برای نمایش مقدماتی جاری، بدون داشتن سیستم اعتبارسنجی و مفاهیم کاربران، نمایش داد.
این قسمت از Solution، به نحو زیر تشکیل شدهاست:
- ImageGallery.WebApi.DataLayer
در اینجا کار تشکیل DbContext برنامه و همچنین مقدار دهی اولیهی بانک اطلاعاتی و تنظیمات Migrations قرار گرفتهاند.
- ImageGallery.WebApi.DomainClasses
در این پروژه کلاسهای موجودیتهای متناظر با جداول بانک اطلاعاتی قرار میگیرند.
- ImageGallery.WebApi.Mappings
این پروژه کار تهیه نگاشتهای AutoMapper برنامه را انجام میدهد؛ نگاشتهایی بین Models و DomainClasses که در ImagesController از آنها استفاده میشود.
- ImageGallery.WebApi.Models
در این پروژه همان DTO's پروژه قرار گرفتهاند. جهت رعایت مسایل امنیتی نباید کلاس موجودیت Image فوق را مستقیما در معرض دید API عمومی قرار داد. به همین جهت تعدادی Model در اینجا تعریف شدهاند که هم برای ثبت، ویرایش و حذف اطلاعات بکار میروند و هم جهت گزارشگیری از رکوردهای موجود جدول تصاویر.
- ImageGallery.WebApi.Services
در این پروژه کار با DbContext انجام شده و توسط آن اطلاعات تصاویر به بانک اطلاعاتی اضافه شده و یا واکشی میشوند.
- ImageGallery.WebApi.WebApp
این پروژه، همان پروژهی اصلی است که سایر قسمتهای یاد شده را در کنار هم قرار داده و به صورت یک Restful-API ارائه میدهد.
بررسی ساختار MvcClient مقدماتی مثال این سری
پس از اجرای WebAPI و آماده بودن آن جهت استفاده، اکنون یک کلاینت ASP.NET Core MVC را جهت کار با امکانات ImagesController آن، تدارک دیدهایم.
برای اجرای آن وارد پوشهی src\MvcClient\ImageGallery.MvcClient.WebApp شده و ابتدا فایل restore.bat و سپس dotnet_run.bat را اجرا کنید.
در این حالت برنامه بر روی پورت 5001 در دسترس خواهد بود:
این پورت نیز در فایل Properties\launchSettings.json تنظیم شدهاست.
در اینجا نمایی از اجرای این برنامه را مشاهده میکنید که لیستی از تصاویر را توسط GalleryController، از سرویس ImagesController مربوط به WebAPI، دریافت کرده و سپس نمایش میدهد. در این لیست تصاویر تمام کاربران با هم نمایش داده شدهاند و هنوز امکان فیلتر کردن آنها بر اساس کاربران وارد شدهی به سیستم را نداریم که در قسمتهای بعدی آنها را تکمیل خواهیم کرد.
این قسمت از Solution به نحو زیر تشکیل شدهاست:
- ImageGallery.MvcClient.Services
در اینجا یک Typed HTTP Client مخصوص NET Core 2.1. را تهیه کردهایم. این سرویس جهت دسترسی به آدرس https://localhost:7001 که WebAPI برنامه در آن قرار دارد، تشکیل شدهاست. روش ثبت مخصوص آنرا نیز در فایل آغازین پروژهی MvcClient.WebApp توسط متد services.AddHttpClient ملاحظه میکنید.
- ImageGallery.MvcClient.ViewModels
مدلهای متناظر با ساختار Viewهای Razor برنامهی وب، در اینجا قرار میگیرند.
- ImageGallery.MvcClient.WebApp
این پروژه، همان پروژهی اصلی است که سایر قسمتهای یاد شده را در کنار هم قرار داده و به صورت یک برنامهی MVC قابل مرور در مرورگر، ارائه میدهد.
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید.
برای اجرای آن ابتدا باید پروژهی WebApi.WebApp را اجرا کنید و سپس پروژهی MvcClient.WebApp.
بررسی ساختار WebAPI مقدماتی مثال این سری
این پروژهی مقدماتی که هنوز قسمتهای اعتبارسنجی به آن اضافه نشدهاند، از دو قسمت WebApi و MvcClient تشکیل میشود.
کار قسمت WebApi، ارائهی یک Restful-API برای کار با گالری تصاویر است. برای اجرای آن وارد پوشهی src\WebApi\ImageGallery.WebApi.WebApp شده و ابتدا فایل restore.bat و سپس dotnet_run.bat را اجرا کنید.
در این حالت برنامه بر روی پورت 7001 در دسترس خواهد بود:
این پورت نیز در فایل Properties\launchSettings.json تنظیم شدهاست تا با پورت کلاینت MVC تهیه شده، تداخل نکند.
کار این سرویس، ارائهی ImagesController است که توسط آن میتوان لیستی از تصاویر موجود، اطلاعات یک تصویر و همچنین کار ثبت، ویرایش و حذف تصاویر را انجام داد.
در این Solution، رکوردهای تصاویری که در بانک اطلاعاتی ذخیره میشوند، یک چنین ساختاری را دارند:
using System; using System.ComponentModel.DataAnnotations; namespace ImageGallery.WebApi.DomainClasses { public class Image { [Key] public Guid Id { get; set; } [Required] [MaxLength(150)] public string Title { get; set; } [Required] [MaxLength(200)] public string FileName { get; set; } [Required] [MaxLength(50)] public string OwnerId { get; set; } } }
در این قسمت توسط کلاس ImageConfiguration کار مقدار دهی اولیهی بانک اطلاعاتی به کمک متد HasData مربوط به EF Core 2.1 صورت گرفتهاست و به این ترتیب میتوان برنامه را برای نمایش مقدماتی جاری، بدون داشتن سیستم اعتبارسنجی و مفاهیم کاربران، نمایش داد.
این قسمت از Solution، به نحو زیر تشکیل شدهاست:
- ImageGallery.WebApi.DataLayer
در اینجا کار تشکیل DbContext برنامه و همچنین مقدار دهی اولیهی بانک اطلاعاتی و تنظیمات Migrations قرار گرفتهاند.
- ImageGallery.WebApi.DomainClasses
در این پروژه کلاسهای موجودیتهای متناظر با جداول بانک اطلاعاتی قرار میگیرند.
- ImageGallery.WebApi.Mappings
این پروژه کار تهیه نگاشتهای AutoMapper برنامه را انجام میدهد؛ نگاشتهایی بین Models و DomainClasses که در ImagesController از آنها استفاده میشود.
- ImageGallery.WebApi.Models
در این پروژه همان DTO's پروژه قرار گرفتهاند. جهت رعایت مسایل امنیتی نباید کلاس موجودیت Image فوق را مستقیما در معرض دید API عمومی قرار داد. به همین جهت تعدادی Model در اینجا تعریف شدهاند که هم برای ثبت، ویرایش و حذف اطلاعات بکار میروند و هم جهت گزارشگیری از رکوردهای موجود جدول تصاویر.
- ImageGallery.WebApi.Services
در این پروژه کار با DbContext انجام شده و توسط آن اطلاعات تصاویر به بانک اطلاعاتی اضافه شده و یا واکشی میشوند.
- ImageGallery.WebApi.WebApp
این پروژه، همان پروژهی اصلی است که سایر قسمتهای یاد شده را در کنار هم قرار داده و به صورت یک Restful-API ارائه میدهد.
بررسی ساختار MvcClient مقدماتی مثال این سری
پس از اجرای WebAPI و آماده بودن آن جهت استفاده، اکنون یک کلاینت ASP.NET Core MVC را جهت کار با امکانات ImagesController آن، تدارک دیدهایم.
برای اجرای آن وارد پوشهی src\MvcClient\ImageGallery.MvcClient.WebApp شده و ابتدا فایل restore.bat و سپس dotnet_run.bat را اجرا کنید.
در این حالت برنامه بر روی پورت 5001 در دسترس خواهد بود:
این پورت نیز در فایل Properties\launchSettings.json تنظیم شدهاست.
در اینجا نمایی از اجرای این برنامه را مشاهده میکنید که لیستی از تصاویر را توسط GalleryController، از سرویس ImagesController مربوط به WebAPI، دریافت کرده و سپس نمایش میدهد. در این لیست تصاویر تمام کاربران با هم نمایش داده شدهاند و هنوز امکان فیلتر کردن آنها بر اساس کاربران وارد شدهی به سیستم را نداریم که در قسمتهای بعدی آنها را تکمیل خواهیم کرد.
این قسمت از Solution به نحو زیر تشکیل شدهاست:
- ImageGallery.MvcClient.Services
در اینجا یک Typed HTTP Client مخصوص NET Core 2.1. را تهیه کردهایم. این سرویس جهت دسترسی به آدرس https://localhost:7001 که WebAPI برنامه در آن قرار دارد، تشکیل شدهاست. روش ثبت مخصوص آنرا نیز در فایل آغازین پروژهی MvcClient.WebApp توسط متد services.AddHttpClient ملاحظه میکنید.
- ImageGallery.MvcClient.ViewModels
مدلهای متناظر با ساختار Viewهای Razor برنامهی وب، در اینجا قرار میگیرند.
- ImageGallery.MvcClient.WebApp
این پروژه، همان پروژهی اصلی است که سایر قسمتهای یاد شده را در کنار هم قرار داده و به صورت یک برنامهی MVC قابل مرور در مرورگر، ارائه میدهد.
کدهای کامل این قسمت را از اینجا میتوانید دریافت کنید.
برای اجرای آن ابتدا باید پروژهی WebApi.WebApp را اجرا کنید و سپس پروژهی MvcClient.WebApp.
مطالب
AngularJS #3
در این مقاله مفاهیم انقیاد داده (Data Binding)، تزریق وابستگی (Dependency Injection)،هدایت گرها (Directives) و سرویسها را بررسی خواهیم کرد و از مقالهی آینده، به بررسی ویژگیها و امکانات AngularJS در قالب مثال خواهیم پرداخت.
انقیاد داده (Data Binding)
سناریو هایی وجود دارد که در آنها باید اطلاعات قسمتی از صفحه به صورت نامتقارن (Asynchronous) با دادههای دریافتی جدید به روز رسانی شود. روش معمول برای انجام چنین کاری؛ دریافت دادهها از سرور است که عموما به فرم HTML میباشند و جایگزینی آن با بخشی از صفحه که قرار است به روز رسانی شود، اما حالتی را در نظر بگیرید که با داده هایی از جنس JSON طرف هستید و اطلاعات صفحه را با این دادهها باید به روز رسانی کنید. معمولا برای حل چنین مشکلی مجبور به نوشتن مقدار زیادی کد هستید تا بتوانید به خوبی اطلاعات View را به روز رسانی کنید. حتما با خودتان فکر کرده اید که قطعا راهی وجود دارد تا بدون نوشتن کدی، قسمتی از View را به Model متناظر خود نگاشت کرده و این دو به صورت بلادرنگ از تغییرات یکدیگر آگاه شوند. این عمل عموما به مفهوم انقیاد داده شناخته میشود و Angular هم به خوبی از انقیاد داده دوطرفه پشتیبانی میکند.
برای مشاهده این ویژگی در Angular، مثال مقالهی قبل را به کدهای زیر تغییر دهید تا پیغام به صورت پویا توسط کاربر وارد شود:
<!DOCTYPE html> <html ng-app> <head> <title>Sample2</title> </head> <body> <div> <input type="text" ng-model="greeting.text" /> <p>{{greeting.text}}, World!</p> </div> <script src="../Scripts/angular.js"></script> </body> </html>
بدون نیاز به حتی یک خط کد نویسی! با مشخص کردن input به عنوان Model از طریق ng-model، خاصیت greeting.text که در داخل {{ }} مشخص شده را به متن داخل textbox مقید (bind) کردیم. نتیجه میگیریم که جفت آکلود {{ }} برای اعمال Data Binding استفاده میشود.
حال یک دکمه نیز بر روی فرم قرار میدهیم که با کلیک کردن بر روی آن، متن داخل textbox را نمایش دهد.
<!DOCTYPE html> <html ng-app> <head> <title>Sample2</title> </head> <body> <div ng-controller="GreetingController"> <input type="text" ng-model="greeting.text" /> <p>{{greeting.text}}, World!</p> <button ng-click="showData()">Show</button> </div> <script src="../Scripts/angular.js"></script> <script> var GreetingController = function ($scope, $window) { $scope.greeting = { text: "Hello" }; $scope.showData = function () { $window.alert($scope.greeting.text); }; }; </script> </body> </html>
به کمک ng-click، تابع showData به هنگام کلیک شدن، فراخوانی میشود. window$ نیز به عنوان پارامتر کلاس GreetingController مشخص شده است. window$ نیز یکی از سرویسهای پیش فرض تعریف شده توسط Angular است و ما در اینجا در سازندهی کلاس آن را به عنوان وابستگی درخواست کرده ایم تا توسط سیستم تزریق وابستگی توکار، نمونهی مناسب آن در اختیار ما بگذارد. window$ نیز تقریبا معادل شی window است و یکی از دلایل استفاده از آن سادهتر شدن نوشتن آزمونهای واحداست.
حال متنی را داخل textbox نوشته و دکمهی show را فشار دهید. متن نوشته شده را به صورت یک popup مشاهده خواهید کرد.
همچنین شی scope$ نیز نمونهی مناسب آن توسط سیستم تزریق وابستگی Angular، در اختیار Controller قرار میگیرد و نمونهی در اختیار قرارگرفته، برای ارتباط با View Model و سیستم انقیاد داده استفاده میشود.
معمولا انقیاد داده در الگوی طراحی (ModelView-ViewModel(MVVM مطرح است و به این دلیل که این الگوی طراحی به خوبی با الگوی طراحی MVC سازگار است، این امکان در Angular گنجانده شده است.
تزریق وابستگی (Dependency Injection)
تا به این جای کار قطعن بارها و بارها اسم آن را خوانده اید. در مثال فوق، پارامتری با نام scope$ را برای سازندهی کنترلر خود در نظر گرفتیم و ما بدون انجام هیچ کاری نمونهی مناسب آن را که برای انجام اعمال انقیاد داده با viewmodel استفاده میشود را دریافت کردیم. به عنوان مثال، window$ را نیز در سازندهی کلاس کنترلر خود به عنوان یک وابستگی تعریف کردیم و تزریق نمونهی مناسب آن توسط سیستم تزریق وابستگی توکار Angular صورت میگرفت.
اگر با IOC Containerها در زبانی مثل #C کار کرده باشید، قطعا با IOC Container فراهم شده توسط Angular هم مشکلی نخواهید داشت.
اما یک مشکل! در زبانی مثل #C که همهی متغیرهای دارای نوع هستند، IOC Container با استفاده از Reflection، نوع پارامترهای درخواستی توسط سازندهی کلاس را بررسی کرده و با توجه به اطلاعاتی که ما از قبل در دسترس آن قرار داده بودیم، نمونهی مناسب آن را در اختیار در خواست کننده میگذارد.
اما در زبان جاوا اسکریپت که متغیرها دارای نوع نیستند، این کار به چه شکل انجام میگیرد؟
Angular برای این کار از نام پارامترها استفاده میکند. برای مثال Angular از نام پارامتر scope$ میفهمد که باید چه نمونه ای را به کلاس تزریق کند. پس نام پارامترها در سیستم تزریق وابستگی Angular نقش مهمی را ایفا میکنند.
اما در زبان جاوا اسکریپت، به طور پیش فرض امکانی برای به دست آوردن نام پارامترهای یک تابع وجود ندارد؛ پس Angular چگونه نام پارامترها را به دست میآورد؟ جواب در سورس کد Angular و در تابعی به نام annotate نهفته است که اساس کار این تابع استفاده از چهار عبارت با قاعده (Regular Expression) زیر است.
var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m; var FN_ARG_SPLIT = /,/; var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/; var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
تابع annotate تابعی را به عنوان پارامتر دریافت میکند و سپس با فراخواندن متد toString آن، کدهای آن تابع را به شکل یک رشته در میآورد. حال کدهای تابع را که اکنون به شکل یک رشته در دسترس است را با استفاده از عبارات با قاعدهی فوق پردازش میکند تا نام پارامترها را به دست آورد. در ابتدا کامنتهای موجود در تابع را حذف میکند، سپس نام پارامترها را استخراج میکند و با استفاده از "," آنها را جدا میکند و در نهایت نام پارامترها را در یک آرایه باز میگرداند.
استفاده از تزریق وابستگی، امکان نوشتن کدهایی با قابلیت استفاده مجدد و نوشتن سادهتر آزمونهای واحد را فراهم میکند. به خصوص کدهایی که با سرور ارتباط برقرار میکنند را میتوان به یک سرویس انتقال داد و از طریق تزریق وابستگی، از آن در کنترلر استفاده کرد. سپس در آزمونهای واحد میتوان قسمت ارتباط با سرور را با یک نمونه فرضی جایگزین کرد تا برای تست، احتیاجی به راه اندازی یک وب سرور واقعی و یا مرورگر نباشد.
Directives
یکی از مزیتهای Angular این است که قالبها را میتوان با HTML نوشت و این را باید مدیون موتور قدرتمند تبدیل گر DOM بدانیم که در آن گنجانده شده است و به شما این امکان را میدهد تا گرامر HTML را گسترش دهید.
تا به این جای کار با attributeهای زیادی در قالب HTML روبرو شدید که متعلق به HTML نیست. به طور مثال: جفت آکولادها که برای انقیاد داده به کار برده میشود، ng-app که برای مشخص کردن بخشی که باید توسط Angular کامپایل شود، ng-controller که برای مشخص کردن این که کدام بخش از View متعلق به کدام Controller است و ... تمامی Directiveهای پیش فرض Angular هستند.
با استفاده از Directiveها میتوانید عناصر و خاصیتها و حتی رویدادهای سفارشی برای HTML بنویسید؛ اما واقعا چه احتیاجی به تعریف عنصر سفارشی و توسعه گرامر HTML وجود دارد؟
HTML یک زبان طراحی است که در ابتدا برای تولید اسناد ایستا به وجود آمد و هیچ وقت هدفش تولید وب سایتهای امروزی که کاملا پویا هستند نبود. این امر تا جایی پیش رفته است که HTML را از یک زبان طراحی تبدیل به یک زبان برنامه نویسی کرده است و احتیاج به چنین زبانی کاملا مشهود است. به همین دلیل جامعهی وب مفهومی را به نام Web Components مطرح کرده است. Web Components به شما امکان تعریف عناصر HTML سفارشی را میدهد. برای مثال شما یک تگ سفارشی به نام datepicker مینویسید که دارای رفتار و ویژگیهای خاص خود است و به راحتی عناصر HTML رابا استفاده از آن توسعه میدهید. مطمئنا آیندهی وب این گونه است، اما هنوز خیلی از مرورگرها از این ویژگی پشتیبانی نمیکنند.
یکی دیگر از معادلهای Web Componentهای امروز را میتوان ویجتهای jQuery UI دانست. اگر بخواهم تعریفی از ویجت ارائه دهم به این گونه است که یک ویجت؛ کدهای HTML، CSS و javascript مرتبط به هم را کپسوله کرده است. مهمترین مزیت ویجت ها، قابلیت استفادهی مجدد آنهاست، به این دلیل که تمام منطق مورد نیاز را در خود کپسوله کرده است؛ برای مثال ویجت datepicker که به راحتی در برنامههای مختلف بدون احتیاج به نوشتن کدی قابل استفاده است.
خب، متاسفانه Web Componentها هنوز در دنیای وب امروزی رایج نشده اند و ویجتها هم آنچنان قدرت Web Componentها را ندارند. خب Angular با استفاده از امکان تعریف Directiveهای سفارشی به صورت cross-browser امکان تعریف عناصر سفارشیه همانند web Componentها را به شما میدهد. حتی به عقیدهی عده ای Directiveها بسیار قدرتمندتر از Web Components عمل میکنند و راحتی کار با آنها بیشتر است.
با استفاده از Directiveها میتوانید عنصر HTML سفارشی مثل </ datepicker>، خاصیت سفارشی مثل ng-controller، رویداد سفارشی مثل ng-click را تعریف کنید و یا حتی حالت و اتفاقات رخ داده در برنامه را زیر نظر بگیرید.
و این یکی از دلایلی است که میگویند Angular دارای ویژگی forward-thinking است.
البته Directiveها یکی از قدرتمندترین امکانات فریم ورک AngularJS است و در آینده به صورت مفصل بر روی آن بحث خواهد شد.
سرویسها در AngularJS
حتما این جمله را در هنگام نوشتن برنامهها با الگوی طراحی MVC بارها و بارها شنیده اید که در Controllerها نباید منطق تجاری و پیچیده ای را پیاده سازی کرد و باید به قسمتهای دیگری به نام سرویسها منتقل شوند و سپس در سازندهی کلاس کنترلر به عنوان پارامتر تعریف شوند تا توسط Angular نمونهی مناسب آن به کنترلر تزریق شود. Controllerها نباید پیاده کنندهی هیچ منطق تجاری و یا اصطلاحا business برنامه باشد و باید از لایهی سرویس استفاده کنند و تنها وظیفهی کنترلر باید مشخص کردن انقیاد داده و حالت برنامه باشد.
دلیل استفاده از سرویسها در کنترلر ها، نوشتن سادهتر آزمونهای واحد و استفادهی مجدد از سرویسها در قسمتهای مختلف پروژه و یا حتی پروژههای دیگر است.
معمولا اعمال مرتبط در ارتباط با سرور را در سرویسها پیاده سازی میکنند تا بتوان در موقع نوشتن آزمونهای واحد یک نمونهی فرضی را خودمان ساخته و آن را به عنوان وابستگی به کنترلری که در حال تست آن هستیم تزریق کنیم، در غیر این صورت احتیاج به راه اندازی یک وب سرور واقعی برای نوشتن آزمونهای واحد و در نتیجه کند شدن انجام آزمون را در بر دارد. قابلیت استفادهی مجدد سرویس هم به این معناست که منطق پیاده سازی شده در آن نباید ربطی به رابط کاربری و ... داشته باشد. برای مثال یک سرویس به نام userService باید دارای متد هایی مثل دریافت لیست کاربران، افزودن کاربر و ... باشد و بدیهی است که از این سرویسها میشود در قسمتهای مختلف برنامه استفاده کرد. همچنین سرویسها در Angular به صورت Singleton در اختیار کنترلرها قرار میگیرند و این بدین معناست که یک نمونه از هر سرویس ایجاد شده و به بخشهای مختلف برنامه تزریق میشود.
مفاهیم پایه ای AngularJs به پایان رسید. در مقاله بعدی یک مثال تقریبا کامل را نوشته و با اجزای مختلف Angular بیشتر آشنا میشویم.
با تشکر از مهدی محزونی برای بازبینی مطلب
نظرات مطالب
ASP.NET MVC #18
سلام ،سال نو مبارک ممنون از پاسخ شما.
من از vs 2013 update1 و win 8.1 استفاده میکنم و برنامه رو با .NetFrameWork 4.5.1 تست کردم.یعنی شما میفرمایید که اگه این بستهی ارتقاع رو نصب کنم مشکل حل میشه؟ (مشکل صدا زدن RoleProvider)
اگر هم تو سیستم لوکال خودم حل شه! به سیستم عامل Host که دسترسی ندارم .بخوام اونم به روز کنم.
من در دات نت 4 که با وب فرم کار میکردم همیشه از RoleProvider سفارشی استفاده میکردم و مشکلی نداشت.با مطالعه مقاله شما علاقه مند شدم تا از این به بعد برنامه هامو با MVC توسعه بدم. ولی چون آموزش شما با MVC4 هست و الان که MVC5 عرضه شده سوالات زیادی ذهنم رو مشغول کرده یکی اینکه آیا احتمال داره طی این زمان که از انتشار این مقاله میگذره روشها عوض شده و یا روش بهتری برای MVC ارائه شده باشه؟
بازم ممنون از زحمتتتون.
من از vs 2013 update1 و win 8.1 استفاده میکنم و برنامه رو با .NetFrameWork 4.5.1 تست کردم.یعنی شما میفرمایید که اگه این بستهی ارتقاع رو نصب کنم مشکل حل میشه؟ (مشکل صدا زدن RoleProvider)
اگر هم تو سیستم لوکال خودم حل شه! به سیستم عامل Host که دسترسی ندارم .بخوام اونم به روز کنم.
من در دات نت 4 که با وب فرم کار میکردم همیشه از RoleProvider سفارشی استفاده میکردم و مشکلی نداشت.با مطالعه مقاله شما علاقه مند شدم تا از این به بعد برنامه هامو با MVC توسعه بدم. ولی چون آموزش شما با MVC4 هست و الان که MVC5 عرضه شده سوالات زیادی ذهنم رو مشغول کرده یکی اینکه آیا احتمال داره طی این زمان که از انتشار این مقاله میگذره روشها عوض شده و یا روش بهتری برای MVC ارائه شده باشه؟
بازم ممنون از زحمتتتون.
بد نیست لیست تعدادی از بانکهای اطلاعاتی مهم قابل استفاده در دات نت به همراه درایورهای ADO.NET آنها را با هم مرور نمائیم.
بانکهای اطلاعاتی قابل استفاده در دات نت فریم ورک | ||||||
ردیف | بانک اطلاعاتی | سایت مرجع | درایور ADO.NET | امکان استفاده از LINQ | مجوز استفاده | توضیحات |
1 | SQL Server 2000/2005/2008/2008 R2 | + | توکار (به صورت پیش فرض در دات نت فریم ورک موجود است) | بلی . به کمک LINQ to SQL ، Entity Framework ، NHibernate و بسیاری از ORM های دیگر | رایگان - تجاری | نسخههای Express آن رایگان است. |
2 | Microsoft SQL Azure | + | بلی : + | بلی. به کمک LINQ to SQL و Entity Framework | تجاری | |
3 | SQL Server Compact | + | بلی : + | بلی. به کمک LINQ to SQL و Entity Framework | رایگان | |
4 | Advantage Database Server | + | قابل دریافت از سایت اصلی: + | بلی. به کمک Entity framework و Telerik OpenAccess ORM | تجاری | |
5 | SQL Anywhere | + | قابل دریافت از سایت اصلی: + | بلی. به کمک Entity framework و Telerik OpenAccess ORM | رایگان - تجاری | Web Edition آن رایگان است. |
6 | MySQL | + | قابل دریافت از سایت اصلی : + | بلی . به کمک NHibernate ، LightSpeed ، DbLinq و تعدادی دیگر از ORM's | رایگان - تجاری | |
7 | Oracle | + | پشتیبانی توکار آن به زودی حذف خواهد شد اما از سایت اصلی قابل دریافت است : + | بلی . به کمک NHibernate ، LightSpeed ، DbLinq و تعدادی دیگر از ORM's | رایگان - تجاری | نسخهی Express آن رایگان است. |
8 | Access | + | توکار | بلی. به کمک ALinq ، NHibernate و یا LINQ to DataSets | تجاری | اگر از دات نت فریم ورک سه و نیم، سرویس پک یک استفاده کنید، امکان استفاده از LINQ to SQL جهت کار با بانکهای اطلاعاتی اکسس نیز مهیا است: + |
9 | SQLite | + | مهیا به صورت سورس باز : + | بلی. درایور ADO.NET آن پشتیبانی از Entity Framework را نیز اضافه میکند. همچنین NHibernate ، ALinq و سایر ORM's را باید به این لیست اضافه کرد. | رایگان | |
10 | Firebird | + | قابل دریافت از سایت اصلی: + | بلی. توسط ALinq ، NHibernate و موارد دیگر. | رایگان | |
11 | PostgreSQL | + | قابل دریافت از سایت اصلی: + | بلی. توسط NHibernate ، DBLinq و موارد دیگر | رایگان | |
12 | DB2 UDB | + | قابل دریافت از سایت اصلی: + | بلی. توسط NHibernate | تجاری | |
13 | ScimoreDB | + | قابل دریافت از سایت اصلی: + | محدود. توسط LINQ to DataSets | رایگان | |
14 | MongoDB | + | معرفی شده در سایت اصلی : + | بلی. درایور ADO.NET معرفی شده به همراه پروایدر LINQ نیز میباشد. | رایگان | |
15 | CouchDB | + | معرفی شده در سایت اصلی : + | محدود | رایگان | |
16 | VistaDB | + | اساسا برای دات نت نوشته شده است. | بلی. به کمک Entity framework | تجاری |
نظرات مطالب
نمونه سوالات مصاحبه استخدامی
کتاب اصول برنامه نویسی (Foundation of Programming) که به فارسی هم ترجمه شده هم منبع خوبی برای شروع میتونه باشه.
نظرات مطالب
معرفی برنامهی Subtitle Tools
سلام
بنده برنامه شما رو با ذکر کامل منبع و اسم حضرت عالی در یک فروم معرفی کردم.
پست بلافاصله ناپدید شد خودتان در جریان هستید؟
بنده برنامه شما رو با ذکر کامل منبع و اسم حضرت عالی در یک فروم معرفی کردم.
پست بلافاصله ناپدید شد خودتان در جریان هستید؟
نظرات مطالب
Contact me
سلام جناب نصیری
آیا امکانش هست با ذکر منبع و اسم شما از مقالاتتون در سایتهای دیگر استفاده کنم؟
(سایت برنامه نویس و سایت خودم)
آیا امکانش هست با ذکر منبع و اسم شما از مقالاتتون در سایتهای دیگر استفاده کنم؟
(سایت برنامه نویس و سایت خودم)
مطالب
دنیای چابک-قسمت اول
داخل وبلاگها و وب سایتهای فارسی زبان(مربوط به برنامه نویسی) که جستجو میکنیم شاهد کلمه ای هستیم که تازه به چشممان میخورد:Agile(چابک). البته لازم به ذکر است این کلمه چیز جدیدی نیست و سابقه ای در حدود 10 سال دارد(February 2001 ).که جمعی از برنامه نویسان بیانیه ای را تحت عنوان چابک (Agile ) تهیه کردند که متن آن به شرح زیر است:
ما با توسعه نرم افزار و کمک به دیگران در انجام آن . در حال کشف راههای بهتری برای توسعه نرم افزار هستیم. از این طریق باید دست یابیم به ارزش :
- افراد و تعاملات بالاتر از فرآیندها و ابزارها
- نرم افزار کارکننده بالاتر از مستندات جامع
- مشارکت مشتری در انجام کار بالاتر از قرارداد کار
- پاسخگویی به تغییرات بالاتر از پیروی یک طرح
با وجود اینکه موارد سمت چپ نیز ارزشمند هستند ولی ما برای موارد سمت راست ارزش بیشتری قائل هستیم .
که این بیانیه بر پایه 12 اصل(Agile principles)
- بالاترین اولویت ما جلب رضایت مشتری با تحویل زود و مداوم نرم افزاری ارزشمند میباشد
- استقبال از تغییر نیازمندی ها، حتی در اواخر فرآیند توسعه. فرآیندهای چابک، تغییر را در جهت مزیتِ رقابتی مشتری مهار میکنند
- تحویل زود به زود نرمافزار قابل استفاده دو، سه هفته یک بار تا دو ، سه ماه یک بار با ترجیح بر فاصلههای زمانی کوتاهتر
- ذی نفعان کسب و کار و توسعه دهندهها میبایست به صورت روزانه در طول پروژه با هم کار کنند
- پروژهها را بر دوش افراد با انگیزه بنا کنید. فضای لازم رابه آنها بدهید و از نیازهای آنها پشتیبانی کنید وبه آنها اعتماد کنید تا کارها را انجام دهند
- کارآمدترین و موثرترین روش انتقال اطلاعات به تیم توسعه و تبادل آن در میان اعضای تیم ، گفتگوی چهره به چهره است
- نرم افزار قابل استفاده اصلیترین معیار سنجش پیشرفت است
- فرآیندهای چابک توسعه پایدار را ترویج میدهندحامیان مالی , توسعه دهندگان و کاربران باید بتوانند سرعت پیشرفت ثابتی را برای مدت نامحدودی حفظ کنند
- توجه مداوم به برتری فنی و طراحی خوب باعث افزایش چابکی میشود
- سادگی -- هنر به حداکثر رساندن مقدار کار انجام نشده -- ضروری است
- بهترین معماریها , نیاز مندیها و طراحیها از تیمهای خود سازمانده پدید آور میشود
- در فواصل منظم , تیم برچگونگی موثرتر شدن تامل وتفکر مینماید و سپس تیم رفتار خود را بر اساس بازتاب این تفکر تنظیم و هم سو مینماید
متاسفانه در ایران حالا یا به علت سواد کم و یا به هر علتی از این بیانیه برداشتهایی متفاوت و غلط عده ای اونو به بازی تشبیه کردن و عده ای هم با اون کار میکنن ولی هیچکدوم از اصلهای اونو رعایت نمیکنن و بعد که پروژه شکست خورد میگن:متدولوژی خوب نبود و ... .
وقتی کتاب Agile Principles, Patterns, and Practices in C# رو مطالعه میکنید به این نتیجه میرسید که بیشترین چیزی که تاکید داره روی ارتباطات هستش.
قصد دارم در قالب چند پست به شما این اصول رو معرفی کنم.