قبل از استفاده از وب ورکر، بهتر هست مرورگر را بررسی کنیم که آیا از این قابلیت پشتیبانی میکند یا خیر؟ روش بررسی کردن این قابلیت، شیوههای مختلفی دارد که به تعدادی از آنها اشاره میکنیم:
typeof(Worker) !== "undefined"
<script src="/js/modernizr-1.5.min.js"></script> Modernizr.webworkers
نحوه پشتیبانی وب ورکرها در مروگرهای مختلف به شرح زیر است:
برای ایجاد یک وب ورکر ابتدا لازم است تا کدهای پردازشی را داخل یک فایل js جداگانه بنویسیم. در این مثال ما قصد داریم که شمارندهای را بنویسیم:
var i=0; function timedCount() { i=i+1; postMessage(i); setTimeout("timedCount()", 500); } timedCount();
سپس در فایل HTML به شکل زیر وب ورکر را مورد استفاده قرار میدهیم. در سازنده Worker، ما آدرس فایل js را وارد میکنیم و برای توقف آن نیز از متد terminate استفاده میکنیم:
<!DOCTYPE html> <html> <head> <script> var worker; function Start() { worker=new Worker("webwroker-even-numbers.js"); worker.onmessage=(event)=> { document.getElementById("output").value=event.data; } } function Stop() { worker.terminate(); } </script> <meta charset="utf-8"> <title></title> </head> <body> <input type="text" id="output"/> <button onclick="Start();">Start Worker</button> <button onclick="Stop();">Stop Worker</button> </body> </html>
worker.onerror = function (event) { console.log(event.message, event); };
همچنین برای ورکر هم میتوانید پیامی را ارسال کنید، برای همین کد زیر را به کد ورکر اضافه میکنیم:
self.onmessage=(event)=>{ i=event.data; };
worker.onmessage=(event)=> { document.getElementById("output").value=event.data; if(event.data==8) worker.postMessage(100); }
روشهای ارسال پیام
به این نوع ارسال پیام، Structure Cloning گویند و با استفاده از این شیوه، امکان ارسال نوعهای مختلفی امکان پذیر شده است؛ مثل فایلها، Blobها، آرایهها و کلاسها و ... ولی باید دقت داشته باشید که این ارسال پیامها به صورت کپی بوده و آدرسی ارجاع داده نمیشود و باید مدنظر داشته باشید که ارسال یک فایل، به فرض پنجاه مگابایتی، به خوبی قابل تشخیص است. طبق نظر گوگل، از حجم 32 مگابایت به بعد، این گفته به خوبی مشهود بوده و زمانبر میشود. به همین علت فناوری با نام Transferable Objects ایجاد شده است که "کپی صفر" Zero-Copy را پیاده سازی میکند و باعث بهبود عملگر کپی میشود:
worker.postMessage(arrayBuffer, [arrayBuffer]);
var ab = new ArrayBuffer(1); worker.postMessage(ab, [ab]); if (ab.byteLength) { alert('Transferables are not supported in your browser!'); } else { // Transferables are supported. }
worker.postMessage({data: ab1, moreData: ab2}, [ab1, ab2]);
نمودار زیر مقایسهای بین Structure Cloning و Transferable Objects است که توسط گوگل منتشر شده است:
RTT=Round Trip Time
نمودار
بالا برای یک فایل 32 مگابایتی است که زمان رفت به ورکر و پاسخ (برگشت از ورکر)
را اندازه گرفتهاند. در ستونهای اول، این موضوع برای فایرفاکس به روش
Structure Cloning به مدت 302 میلی ثانیه زمان برد که همین موضوع برای
Transferables حدود 6.6 میلی ثانیه زمان برد.
آقای اریک بایدلمن در بخش مهندسی کروم گوگل میگوید: همین سرعت به ما در انتقال تکسچرها و مشها در WebGL کمک میکند.
استفاده از اسکریپت خارجی
در صورتیکه قصد دارید از یک اسکرپیت خارجی، در ورکر استفاده کنید، تابع importScripts برای اینکار ایجاد شده است:
importScripts('script1.js'); importScripts('script2.js');
importScripts('script1.js', 'script2.js');
Inline Worker
اگر بخواهید در همان صفحه اصلی یک ورکر را ایجاد کنید و فایل جاوا اسکریپتی خارجی نداشته باشید، میتوانید از inline worker استفاده کنید. در این روش باید یک نوع blob را ایجاد کنید:
var blob = new Blob([ "onmessage = function(e) { postMessage('msg from worker'); }"]); // یک آدرس همانند آدرس ارجاع به فایل درست میکند var blobURL = window.URL.createObjectURL(blob); var worker = new Worker(blobURL); worker.onmessage = function(e) { // e.data... }; worker.postMessage(); // ورکر آغاز میشود
blob:http://localhost/c745ef73-ece9-46da-8f66-ebes574789b1
window.URL.revokeObjectURL(blobURL);
chrome://blob-internals
این مطلب به عنوان اولین بخش از این سری مطالب منتشر میشود.
هدف این نوشته بررسی جزییات برنامه نویسی در رابطه با کلاس و شیء نیست. بلکه دریافتن چگونگی شکل گرفتن ایده شیء گرایی و علت مفید بودن آن است.
مشاهده مفاهیم شیء گرایی در پیرامون خود
حتماً در دنیای برنامه نویسی شیء گرا بارها با کلمات کلاس و شیء روبرو شده اید. درک صحیح از این مفاهیم بسیار مهم و البته بسیار ساده است. کار را با یک مثال شروع میکنیم. به تصویر زیر نگاه کنید.در سمت راست بخشی از نقشه یک ساختمان و در سمت چپ ساختمان ساخته شده بر اساس این نقشه را میبینید. ساختمان همان شیء است. و نقشه ساختمان کلاس آن است چراکه امکان ایجاد اشیائی که تحت عنوان ساختمان طبقه بندی (کلاس بندی) میشوند را فراهم میکند. به همین سادگی. کلاسها طرح اولیه، نقشه یا قالبی هستند که جزییات یک شی را توصیف میکنند.
حتماً با من موافق هستید اگر بگویم:
- در نقشه ساختمان نمیتوانید زندگی کنید اما در خود ساختمان میتوانید.
- از روی یک نقشه میتوان به تعداد دلخواه ساختمان ساخت.
- هنگامی که در یک ساختمان زندگی میکنید نیازی نیست تا دقیقاً بدانید چگونه ساخته شده و مثلاً سیم کشی یا لوله کشیهای آن چگونه است! تنها کافیست بدانید برای روشن شدن لامپ باید کلید آن را بزنید.
- ساختمان دارای ویژگی هایی مانند متراژ، ضخامت دیوار، تعداد پنجره و ابعاد هر یک و ... است که در هنگام ساخت و بر اساس اطلاعات موجود در نقشه تعیین شده اند.
- ساختمان دارای کارکرد هایی است. مانند بالا و پایین رفتن آسانسور و یا باز و بسته شدن درب پارکینگ. هر یک از این کارکردها نیز بر اساس اطلاعات موجود در نقشه پیاده سازی و ساخته شده اند.
- ساختمان تمام اجزای لازم برای اینکه از آن بتوانیم استفاده کنیم و به عبارتی در آن بتوانیم زندگی کنیم را در خود دارد.
سوال: کلاس یا نقشه ایجاد گاو چیست؟ اگر از من بپرسید خواهم گفت طرح اولیه گاو هم ممکن است وجود داشته باشد البته در اختیار خداوند و با سطح دسترسی ملکوت!
اتومبیل، تلویزیون و ... همگی مثال هایی از اشیاء پیرامون ما در دنیای واقعی هستند که حتماً میتوانید کلاس یا نقشه ایجاد آنها را نیز بدست آورید و یا ویژگیها و کارکردهای آنها را برشمارید.
مفاهیم شیء گرایی در مهندسی نرم افزار
مفاهیمی که تاکنون در مورد دنیای واقعی مرور کردیم همان چیزی است که در دنیای برنامه نویسی ـ به عقیده من دنیای واقعیتر از دنیای واقعی ـ با آن سر و کار داریم. علت این امر آن است که اصولاً ایده روش برنامه نویسی شیء گرا با مشاهده محیط پیرامون ما به وجود آمده است.برای نوشتن برنامه جهت حل یک مسئله بزرگ باید بتوان آن مسئله را به بخشهای کوچکتری تقسیم نمود. در این رابطه مفهوم شیء و کلاس با همان کیفیتی که در محیط پیرامون ما وجود دارد به صورت مناسبی امکان تقسیم یه مسئله بزرگ به بخشهای کوچکتر را فراهم میکند. و سبب میشود هماهنگی و تقارن و تناظر خاصی بین اشیاء برنامه و دنیای واقعی بوجود آید که یکی از مزایای اصلی روش شیء گراست.
از آنجا که در یک برنامه اصولاً همه چیز و همه مفاهیم در قالب کدها و دستورات برنامه معنا دارد، کلاس و شیء نیز چیزی بیش از قطعاتی کد نیستند. قطعه کد هایی که بسته بندی شده اند تا تمام کار مربوط به هدفی که برای آنها در نظر گرفته شده است را انجام دهند.
همان طور که در هر زبان برنامه نویسی دستوراتی برای کارهای مختلف مانند تعریف یک متغیر یا ایجاد یک حلقه و ... در نظر گرفته شده است، در زبانهای برنامه نویسی شیء گرا نیز دستوراتی وجود دارد تا بتوان قطعه کدی را بر اساس مفهوم کلاس بسته بندی کرد.
به طور مثال قطعه کد زیر را در زبان برنامه نویسی سی شارپ در نظر بگیرید.
class Player { public string Name; public int Age; public void Walk() { // کدهای مربوط به پیاده سازی راه رفتن } public void Run() { // کدهای مربوط به پیاده سازی دویدن } }
این کلاس به چه دردی میخورد؟ کجا میتوانیم از این کلاس استفاده کنیم؟
پاسخ این است که این کلاس ممکن است برای ما هیچ سودی نداشته باشد و هیچ کجا نتوانیم از آن استفاده کنیم. اما بیایید فرض کنیم برنامه نویسی هستیم که قصد داریم یک بازی فوتبال بنویسیم. به جای آنکه قطعات کد مجزایی برای هر یک از بازیکنان و کنترل رفتار و ویژگیهای آنان بنویسیم با اندکی تفکر به این نکته پی میبریم که همه بازیکنان مشترکات بسیاری دارند و به عبارتی در یک گروه یا کلاس قابل دسته بندی هستند. پس سعی میکنیم نقشه یا قالبی برای بازیکنها ایجاد کنیم که دربردارنده ویژگیها و رفتارهای آنها باشد.
همان طور که در نقشه ساختمان نمیتوانیم زندگی کنیم این کلاس هم هنوز آماده انجام کارهای واقعی نیست. چراکه برخی مقادیر هنوز برای آن تنظیم نشده است. مانند نام بازیکن و سن و ....
و همان طور که برای سکونت لازم است ابتدا یک ساختمان از روی نقشه ساختمان بسازیم برای استفاده واقعی از کلاس یاد شده نیز باید از روی آن شیء بسازیم. به این فرآیند وهله سازی یا نمونه سازی نیز میگویند. یک زبان برنامه نویسی شیء گرا دستوراتی را برای وهله سازی نیز در نظر گرفته است. در C# کلمه کلیدی new این وظیفه را به عهده دارد.
Player objPlayer = new Player(); objPlayer.Name = “Ali Karimi”; objPlayer.Age = 30; objPlayer.Run();
تمام آنچه که بازیکن برای انجام امور مربوط به خود نیاز دارد در کلاس بازیکن کپسوله میشود. بدیهی است در یک برنامه واقعی ویژگیها و رفتارهای بسیار بیشتری باید برای کلاس بازیکن در نظر گرفته شود. مانند پاس دادن، شوت زدن و غیره.
به این ترتیب ما برای هر برنامه میتوانیم مسئله اصلی را به تعدادی مسئله کوچکتر تقسیم کنیم و وظیفه حل هر یک از مسائل کوچک را به یک شیء واگذار کنیم. و بر اساس اشیاء تشخیص داده شده کلاسهای مربوطه را بنویسیم. برنامه نویسی شیء گرا سبب میشود تا مسئله توسط تعدادی شیء که دارای نمونههای متناظری در دنیای واقعی هستند حل شود که این امر زیبایی و خوانایی و قابلیت نگهداری و توسعه برنامه را بهبود میدهد.
احتمالاً تاکنون متوجه شده اید که برای نگهداری ویژگیهای اشیاء از متغیرها و برای پیاده سازی رفتارها یا کارکردهای اشیاء از توابع استفاده میکنیم.
با توجه به این که هدف این مطلب بررسی مفهوم شیء گرائی بود و نه جزییات برنامه نویسی، بنابراین بیان برخی مفاهیم در این رابطه را که بیشتر در مهندسی نرم افزار معنا دارند تا در دنیای واقعی در مطالب بعدی بررسی میکنیم.
تلاشهای بسیاری توسط توسعه گران صورت پذیرفته است تا فرایند ایجاد وب سرویس WCF در بستر HTTP آسان شود. امروزه وب سرویس هایی که از قالب REST استفاده میکنند مطرح هستند.
ASP.NET Web API از مفاهیم موجود در ASP.NET MVC مانند Controllerها استفاده میکند و بر مبنای آنها ساخته شده است. بدین شکل، توسعه گر میتواند با دانش موجود خود به سادگی وب سرویسهای مورد نظر را ایجاد کند. Web API، پروتوکل SOAP را به کتابهای تاریخی! سپرده است تا از آن به عنوان روشی برای تعامل بین سیستمها یاد شود. امروزه به دلیل فراگیری پروتوکل HTTP، بیشتر محیطهای برنامه نویسی و سیستم ها، از مبانی اولیهی پروتوکل HTTP مانند اَفعال آن پشتیبانی میکنند.
حال قصد داریم تا وب سرویسی را که در قسمت اول با WCF ایجاد کردیم، این بار با استفاده از Web API ایجاد کنیم. به تفاوت این دو دقت کنید.
using System.Web.Http; namespace MvcApplication1.Controllers { public class ValuesController : ApiController { // GET api/values/5 public string Get(int id) { return string.Format("You entered: {0}", id); } } }
نحوهی برگشت یک مقدار از متدها در Web API، مانند WCF است. میتوانید خروجی متد Get را با اجرای پروژهی قبل در Visual Studio و تست آن با یک مرورگر ملاحظه کنید. دقت داشته باشید که یکی از اصولی که Web API به آن معتقد است این است که وب سرویسها میتوانند ساده باشند. در Web API، تست و دیباگ وب سرویسها بسیار راحت است. با مرورگر Internet Explorer به آدرس http://localhost:{port}/api/values/3 بروید. پیش از آن، برنامهی Fiddler را اجرا کنید. شکل ذیل، نتیجه را نشان میدهد.
در اینجا نتیجه، عبارت "You entered: 3" است که به صورت یک متن ساده برگشت داده شده است.
ایجاد یک پروژهی Web API
در Visual Studio، مسیر ذیل را طی کنید.
File> New> Project> Installed Templates> Visual C#> Web> ASP.NET MVC 4 Web Application
نام پروژه را HelloWebAPI بگذارید و بر روی دکمهی OK کلیک کنید (شکل ذیل)در فرمی که باز میشود، گزینهی Web API را انتخاب و بر روی دکمهی OK کلیک کنید (شکل ذیل). البته دقت داشته باشید که ما همیشه مجبور به استفاده از قالب Web API برای ایجاد پروژههای خود نیستیم. میتوان در هر نوع پروژه ای از Web API استفاده کرد.
اضافه کردن مدل
مدل، شی ای است که نمایانگر دادهها در برنامه است. Web API میتواند به طور خودکار، مدل را به فرمت JSON، XML یا فرمت دلخواهی که خود میتوانید برای آن ایجاد کنید تبدیل و سپس دادههای تبدیل شده را در بدنهی پاسخ HTTP به Client ارسال کند. تا زمانی که Client بتواند فرمت دریافتی را بخواند، میتواند از آن استفاده کند. بیشتر Clientها میتوانند فرمت JSON یا XML را پردازش کنند. به علاوه، Client میتواند نوع فرمت درخواستی از Server را با تنظیم مقدار هدر Accept در درخواست ارسالی تعیین کند. اجازه بدهید کار خود را با ایجاد یک مدل ساده که نمایانگر یک محصول است آغاز کنیم.
بر روی پوشهی Models کلیک راست کرده و از منوی Add، گزینهی Class را انتخاب کنید.
نام کلاس را Product گذاشته و کدهای ذیل را در آن بنویسید.
namespace HelloWebAPI.Models { public class Product { public int Id { get; set; } public string Name { get; set; } public string Category { get; set; } public decimal Price { get; set; } } }
مدل ما، چهار Property دارد که در کدهای قبل ملاحظه میکنید.
اضافه کردن Controller
در پروژه ای که با استفاده از قالب پیش فرض Web API ایجاد میشود، دو Controller نیز به طور خودکار در پروژهی Controller قرار میگیرند:
- HomeController: یک Controller معمول ASP.NET MVC است که ارتباطی با Web API ندارد.
- ValuesController: یک Controller مختص Web API است که به عنوان یک مثال در پروژه قرار داده میشود.
توجه: Controllerها در Web API بسیار شبیه به Controllerها در ASP.NET MVC هستند، با این تفاوت که به جای کلاس Controller، از کلاس ApiController ارث میبرند و بزرگترین تفاوتی که در نگاه اول در متدهای این نوع کلاسها به چشم میخورد این است که به جای برگشت Viewها، داده برگشت میدهند.
کلاس ValuesController را حذف و یک Controller به پروژه اضافه کنید. بدین منظور، بر روی پوشهی Controllers، کلیک راست کرده و از منوی Add، گزینهی Controller را انتخاب کنید.
توجه: در ASP.NET MVC 4 میتوانید بر روی هر پوشهی دلخواه در پروژه کلیک راست کرده و از منوی Add، گزینهی Controller را انتخاب کنید. پیشتر فقط با کلیک راست بر روی پوشهی Controller، این گزینه در دسترس بود. حال میتوان کلاسهای مرتبط با Controllerهای معمول را در یک پوشه و Controllerهای مربوط به قابلیت Web API را در پوشهی دیگری قرار داد.
نام Controller را ProductsController بگذارید، از قسمت Template، گزینهی Empty API Controller را انتخاب و بر روی دکمهی OK کلیک کنید (شکل ذیل).
فایلی با نام ProductsController.cs در پوشهی Controllers قرار میگیرد. آن را باز کنید و کدهای ذیل را در آن قرار دهید.
namespace HelloWebAPI.Controllers { using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Web.Http; using HelloWebAPI.Models; public class ProductsController : ApiController { Product[] products = new Product[] { new Product { Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1.39M }, new Product { Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M }, new Product { Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M } }; public IEnumerable<Product> GetAllProducts() { return products; } public Product GetProductById(int id) { var product = products.FirstOrDefault((p) => p.Id == id); if (product == null) { var resp = new HttpResponseMessage(HttpStatusCode.NotFound); throw new HttpResponseException(resp); } return product; } public IEnumerable<Product> GetProductsByCategory(string category) { return products.Where( (p) => string.Equals(p.Category, category, StringComparison.OrdinalIgnoreCase)); } } }
برای ساده نگهداشتن مثال، لیستی از محصولات را در یک آرایه قرار داده ایم اما واضح است که در یک پروژهی واقعی، این لیست از پایگاه داده بازیابی میشود. در مورد کلاسهای HttpResponseMessage و HttpResponseException بعداً توضیح میدهیم.
در کدهای Controller قبل، سه متد تعریف شده اند:
- متد GetAllProducts که کل محصولات را در قالب نوع <IEnumerable<Product برگشت میدهد.
- متد GetProductById که یک محصول را با استفاده از مشخصهی آن (خصیصهی Id) برگشت میدهد.
- متد GetProductsByCategory که تمامی محصولات موجود در یک دستهی خاص را برگشت میدهد.
تمام شد! حال شما یک وب سرویس با استفاده از Web API ایجاد کرده اید. هر یک از متدهای قبل در Controller، به یک آدرس به شرح ذیل تناظر دارند.
GetAllProducts به api/products/
GetProductById به api/products/id/
GetProductsByCategory به api/products/?category=category/
در آدرسهای قبل، id و category، مقادیری هستند که همراه با آدرس وارد میشوند و در پارامترهای متناظر خود در متدهای مربوطه قرار میگیرند. یک Client میتواند هر یک از متدها را با ارسال یک درخواست از نوع GET اجرا کند.
در قسمت بعد، کار خود را با تست پروژه و نحوهی تعامل jQuery با آن ادامه میدهیم.
- اصل Open Closed چیست؟ | www.dotnetdev.info
- ترجمه کتاب اصول برنامهنویسی به فارسی | blog.afsharm.com
- قیمت گذاری نرم افزار- به دست آوردن قیمت تمام شده | weblog.radmanitd.com
- نمودار سازمانی | www.saaedco.com
- وب فارسی از الگوریتم ضعیف گوگل و سایتهای تبلیغاتی رنج می برد | shirazi.blogfa.com
- FREE: 5 Professional WPF Themes | www.mindscapehq.com
- JQuery Price Format Plugin | jquerypriceformat.com