مطالب
معرفی سرویس‌های ارائه شده توسط شرکت‌های گوگل، آمازون و مایکروسافت در قالب رایانش ابری - قسمت اول

رایانش ابری مفهوم نسبتا جدیدی در عرصه‌ی فناوری اطلاعات است و در حال گسترش می­‌باشد. به طور خلاصه رایانش ابری به همه چیز اعم از برنامه کاربردی( Application )، سکو ی ( Platform ) توسعه نرم افزار، سخت افزار و زیرساخت، به عنوان سرویس نگاه می‌کند. زیرساخت های موجود در مراکز داده( Data Center ) به انضمام  نرم‌افزارهایی که در آن قرار دارند، مجموعه‌ه­ایی را تشکیل می­‌دهند که ابر نامیده می­‌شود. به عبارت ساده­‌تر رایانش ابری یعنی استفاده­ اشتراکی از برنامه­‌ها و منابع یک محیط شبکه­‌ای برای انجام یک کار، بدون این که مالکیت، مدیریت منابع شبکه و سخت­ افزار و برنامه­‌ها، برای استفاده کننده مهم باشد. در رایانش ابری منابع کامپیوترها، برای انجام یک کار استفاده می‌شوند و داده­‌های مربوط به پردازش، در هیچ کدام از کامپیوترهای شخصی ذخیره نمی­‌شوند، بلکه در جای دیگری در داخل همان منابع شبکه، ذخیره می­‌شوند تا در زمان و مکان دیگری قابل دسترسی باشند.

بر همین اساس شرکت های پیشرو در زمینه فناوری اطلاعات به ارائه سرویس هایی تحت عنوان خدمات رایانش ابری پرداخته اند و هدف از این سری مطالب ارائه شده، شرح مختصری بر سرویس‌های ارائه شده می باشد. در قسمت اول به معرفی سرویسهای شرکت گوگل پرداخته می شود و در قسمت‌های بعدی، سرویس‌های  شرکت‌های مایکروسافت و آمازون معرفی می‌گردد.

 سرویس­‌های رایانش ابری گوگل، در زیر دو چتر قرار دارند. گروه اول شامل مجموعه گسترده­ای از برنامه­‌های محبوب گوگل مانند Google Doc ،   Google Health ، Google Mail ، Google Earth هستند که با کلیک بر روی گزینه More و Even More که در بالای صفحه اصلی گوگل قرار دارند، می­توان به آن­ها دسترسی پیدا کرد.

دومین محصول مبتنی بر ابر گوگل، ابزار توسعه PaaS گوگل است. این سکو در سال 2008 برای توسعه برنامه‌­های تحت وب، با استفاده از زیرساخت گوگل به نام موتور Google App  معرفی شد. هدف از آن قادر ساختن توسعه دهندگان برای ساخت و استقرار برنامه­‌های وب بدون نگرانی از زیرساختی است که برنامه بر رویش اجرا می­شود. برنامه­‌های این موتور، با زبان­های سطح بالا به ویژه جاوا و پایتون و در چارچوب GAE نوشته می­‌شوند. گوگل به منظور گسترش این نوع برنامه­‌ها یک سطح رایگان مشخص از سرویس را ارائه می­دهد و زمانی که برنامه از سطح مشخصی از بار پردازشی، ذخیره­‌سازی و پهنای باند شبکه فراتر رفت، آنگاه شارژها بر مبنای میزان استفاده محاسبه می­شود.

برنامه­‌های GAE را باید به گونه­‌ای نوشت که با زیرساخت گوگل وفق یابند. این مسئله، باعث محدودیت برنامه­‌های قابل اجرا در GAE  می­گردد و علاوه بر آن، انتقال برنامه‌­ها به سکوی GAE و یا انتقال از این سکو به سایر سکو­های موجود دشوار می­شود.

از میان سرویس های ابری رایگان ارائه شده از سوی گوگل، به معرفی سرویس آنالیز گوگل بسنده کرده و تمرکز اصلی بر روی سکوی توسعه نرم‌افزاری این شرکت ( GAE ) می‌باشد.


Google Analytics

به اختصار GA نامیده می­شود و یک ابزار آماری است که تعداد و انواع بازدیدکنندگان وب­‌سایت و نحوه استفاده از وب­‌سایت را اندازه­‌گیری می­کند. این محصول بر روی بسته تحلیلی Urchin 5 که گوگل در سال 2006 آن را خریداری نمود، ساخته شده است. این سرویس رایگان عرضه می­شود و فرآیند تحلیل را با استفاده از یک قطعه کد جاوا اسکریپت به نام Google Analytics Tracking Code با پیاده‌سازی در تگ صفحه وب انجام می­‌شود.

این کد با اولین بارگذاری صفحه در سیستم­ کاربران، به جمع آوری اطلاعات مورد نیاز پرداخته و برای پردازش به سرورهای GA باز پس می­فرستد. این کد با کمک Cookie مرورگر اطلاعات مورد نیاز را جمع آوری می­نماید.

سرویس Google Analytics


آشنایی با Google App Engine

GAE یک سکو به عنوان سرویس می­باشد و مبتنی بر ابر گوگل است و بر روی زیر ساخت­ گوگل مستقر شده است. 

این سرویس توسعه دهندگان را قادر می­سازد تا برنامه‌­های وب ایجاد کرده و بر روی سرور­های گوگل مستقر سازند و گوگل مدیریت زیرساخت را بر عهده گیرد و اعمالی مانند نظارت، برطرف کردن اشکالات احتمالی، خوشه بندی، مدیریت وهله‌سازی ماشین‌های مجازی و غیره را انجام دهد. برای اجرای یک برنامه در GAE ابتدا باید استانداردهای سکوی گوگل رعایت شود. این استانداردها دامنه برنامه­‌هایی که قابل اجرا می­باشند را بسیار محدود می‌­نماید و قابلیت حمل آن­ها را کاهش می­دهد.

محدودیت­‌هایی که این سکو ایجاد می­‌کند، با خود مزایایی را به همراه می­‌آورد که در زیر به آن­ها اشاره می­گردد:

  • وب سرویس­های پویا بر مبنای استانداردهای رایج
  • توسعه خودکار و توازن بار بین ماشین‌های وهله‌سازی شده که مورد استفاده وب سرویس است.
  • اعتبارسنجی با استفاده از API موجود در گوگل.
  • فضای ذخیره سازی ماندگار با قابلیت جستجو، مرتب سازی و مدیریت تراکنش.
  • صف کاری و زمان بندی کاری
  • محیط توسعه سمت مشتری( توسعه دهندگان ) برای شبیه سازی GAE در سیستم محلی.
  • پشتیبانی از محیط اجرا جاوا و پایتون.

هنگامی که یک برنامه در GAE مستقر گردید، با استفاده از نام دامنه دلخواه یا با استفاده از آدرس تجاری Google Apps قابل دستیابی است. موتور Google Apps در حال حاضر برنامه­‌هایی که در جاوا و پایتون نوشته شده است را پشتیبانی می­کند و علاوه بر آن از زبان­های ماشین مجازی جاوا و چندین چارچوب تحت وب پایتون که WSGI و CGI را پشتیبانی می­کنند نیز با محیط GAE سازگاری دارند.

برنامه­‌هایی که در GAE اجرا می­شوند از سیستم عامل مستقل هستند یا به گفته گوگل بر روی   Sand Box  اجرا می­شوند. این ویژگی GAE را قادر می­سازد، سیستم را بهینه کند تا تقاضاهای وب، با بار ترافیکی فعلی منطبق شوند. همچنین برنامه­‌ها را قادر می­سازد با امنیت بالاتری کار کنند، زیرا تنها می­توانند به کامپیوترهایی متصل شوند که آدرس‌های مشخصی دارند و سرویس­ها را با استفاده از پروتکل Http و یا Https از پورت­های شناخته شده پاسخ دهند. از طرف دیگر برنامه‌­ها نیز به این میزان محدود شده که تنها فایل­ها را بخوانند. آن‌ها حق نوشتن فایل به صورت مستقیم بر روی سیستم­ها را ندارند و برای دستیابی به داده، باید از ذخیره داده در Cache یا سرویس ماندگار دیگری استفاده نمایند.

GAE یک سیستم انبار داده توزیع شده دارد که از پرس و جوها و تراکنش­ها پشتیبانی می­نماید. این انبار داده غیر رابطه­‌ای است، اما اشیاء داده یا موجودیت­‌هایی که خصوصیات لازم را دارند، ذخیره می­‌نماید. به همین علت در پرس و جوها می­توان از فیلتر نوع موجودیت بهره برد و آن­ها را به ترتیب خصوصیات مرتب نمود.

در نهایت توجه به مدل قیمت‌گذاری گوگل قابل توجه است. گوگل برای تشویق توسعه دهندگان در نوشتن برنامه با استفاده از GAE ، استقرار و توسعه برنامه را تا میزان مشخصی از منابع رایگان کرده است و با عبور از مقدار رایگان باید هزینه را به ازای مصرف پرداخت نمود. بر اساس جدول ارائه شده در سایت شرکت گوگل به ازای تجاوز از میزان مصرف رایگان، سیستم هزینه گذاری بر اساس تعرفه‌های زیر، اقدام به محاسبه حق شارژ می‌نماید و بدیهی است برای آگاهی از آخرین تعرفه‌ها و کسب اطلاعات بیشتر، مراجعه به  صفحه سایت شرکت گوگل  توصیه می‌شود:

  • مبلغ به ازای هر یک ساعت استفاده از CPU معادل 0.08 دلار
  • داده ذخیره شده به ازای هر گیگابایت در ماه معادل 0.18 دلار
  • پهنای باند خروجی به ازای هر گیگابایت معادل 0.12 دلار
  • پهنای باند ورودی رایگان
  • هزینه دریافت هر ایمیل معادل 0.0001 دلار 

به منظور ذخیره اطلاعات در منبع داده پایدار، از API استفاده می­گردد که به ازای تعداد تراکنش­هایی که تبادل می­گردد، هزینه پرداخت می­شود. از آنجایی که بنا به تعداد تبادلات و نوع حافظه پایداری که استفاده می­گردد، هزینه متغیر است، خواننده محترم برای رویت لیست مذکور به منبع ذکر شده، ارجاع داده می­شود.


  منبع سهمیه 
سهمیه پیش فرض رایگان به ازای هر برنامه   
  مصرف  CPU 
  28 ساعت به ازای هر برنامه در روز 
  منبع ذخیره پایدار داده 
1 گیگابایت به ازای هر برنامه در ماه
  پهنای باند ورودی 
  1 گیگابایت به ازای هر برنامه در روز 
  پهنای باند خروجی 
  1 گیگابایت به ازای هر برنامه در روز 
  تراکنش با منبع داده  Datastore 
  50 هزار تراکنش برای خواندن و نوشتن به ازای هر برنامه در ماه 
  تراکنش با منبع داده  Blobstore 
  5 گیگابایت به ازای هر برنامه در روز 
  ایمیل دریافتی 
  100 دریافت به ازای هر برنامه در روز 

مطالب
سخنان بزرگان!

اشکال زدایی (debug) یک کد چندین مرتبه از نوشتن آن سخت‌تر است. بنابراین اگر کد اولیه خود را بسیار هوشمندانه بنویسید، جهت اشکال زدایی آن به اندازه‌ی کافی باهوش نخواهید بود! (Brian Kernighan)

تنها دو نوع زبان برنامه نویسی وجود دارد: آنهایی که برنامه نویس‌ها از آن شکایت دارند و آن‌هایی که اصلا مورد استفاده قرار نمی‌گیرند! (Bjarne Stroustrup)

هر کسی می‌تواند کدی بنویسد که یک کامپیوتر آن‌را درک کند. یک برنامه نویس خوب کدی را می‌نویسد که برای سایر همکارانش قابل درک باشد. (Martin Fowler)

اندازه‌گیری درصد پیشرفت یک پروژه برنامه نویسی با شمارش تعداد سطرهای کدهای آن همانند اندازه گیری درصد پیشرفت ساخت یک هواپیما از طریق وزن کردن آن است! (Bill Gates)

برنامه نویسی سطح پایین (Low-level) روح برنامه نویس‌ها را جلا می‌بخشد! (John Carmack, ID software)

بزرگی واقعی با اندازه گیری مقدار آزادی که به دیگران عطا می‌کنید، سنجیده می‌شود و نه به اینکه چگونه دیگران را وادار می‌کنید تا آنچه را که مد نظر شما است اجرا کنند. (Larry Wall)

هیچگاه از gets و sprintf استفاده نکنید، در غیر اینصورت شیاطین به زودی به سراغ شما خواهند آمد! (FreeBSD Secure Programming Guidelines)

صحبت کردن ساده است. کدت رو نشون بده! (Linus Torvalds)

علوم رایانه هیچگاه شخصی را تبدیل به یک برنامه نویس خوب نمی‌کنند همانطور که مطالعه در مورد رنگ‌ها و قلم‌ها شما را تبدیل به یک نقاش خوب نمی‌کند. (Eric Raymond)

برنامه نویسی مانند س.ک.س است. یک اشتباه و سپس تحمل کردن و پشتیبانی آن تا آخر عمر! (Michael Sinz)

هیچ برنامه‌ای تا زمانیکه آخرین یوزر آن بمیرد به پایان نخواهد رسید! (از یک گروه پشتیبانی نرم افزار ناشناس!)

برنامه نویس‌های C هرگز نخواهند مرد. آن‌ها فقط تبدیل به void خواهند شد. (ناشناس)

پایان دنیای یونیکس 2 به توان 32 ثانیه پس از اول ژانویه 1970 است! (ناشناس)

زمانی‌ که کد می‌نویسید فرض کنید شخصی که قرار است در آینده از کدهای شما نگهداری کند یک دیوانه‌ی زنجیری است که آدرس خانه‌ی شما را می‌داند! (Rick Osborne)

سادگی یک برنامه یکی از شرایط قابل اطمینان بودن آن است. (Edsger Dijkstra)

یونیکس سیستم عامل ساده‌ای است، اما شما باید فرد باهوشی باشید تا بتوانید این سادگی را درک کنید! (Dennis Ritchie)

اگر به کامپایلر دروغ بگوئید او بعدا انتقام خواهد گرفت! (Henry Spencere)

پرل تنها زبان برنامه نویسی است که پیش و پس از رمزنگاری RSA به یک شکل به نظر می‌رسد! (Keith Bostic)

تنها دو صنعت هستند که به مصرف کنندگان خود "کاربر" می‌گویند: صنعت کامپیوتر و تجارت مواد مخدر! (ناشناس)

مطالب
آناتومی یک گزارش خطای خوب
به مشکلی در برنامه‌ای برخورده‌اید؟ کتابخانه‌ای کار نمی‌کند؟ خطایی را دریافت کرده‌اید؟ برنامه کامپایل نمی‌شود؟ برنامه آنطور که مدنظر شما است رفتار نمی‌کند؟ برای طرح این مسایل، صرف عنوان کردن «برنامه کار نمی‌کنه» یا «خطا می‌ده» منزلت خودتان را تا حد یک کاربر عادی تازه کار تنزل داده‌اید. در ادامه ساختار یک گزارش خطای خوب را بررسی خواهیم کرد، تا شما را سریعتر به مقصودتان برساند و همچنین کار پیگیری برنامه نویس یا برنامه نویس‌های مسئول را نیز مقداری ساده‌تر کند.


کارهای لازم پیش از طرح سؤال
- سعی کنید انجمن‌های مرتبط را یکبار بررسی و جستجو کنید.
- عین خطای دریافتی را در گوگل جستجو کنید. اگر از برنامه‌ها یا کتابخانه‌های معروف و متداول استفاده می‌کنید، یکی از مزیت‌های مهم کار با آن‌ها، «تنها نبودن» است! یقین داشته باشید خطایی را که دریافت کرده‌اید پیشتر توسط ده‌ها نفر دیگر در سایت‌های مختلف مطرح شده‌اند و بالاخره با بررسی آن‌ها می‌توان به پاسخ رسید.
- شاید راهنمای برنامه در این مورد خاص مطلبی را عنوان کرده است.

و ... به صورت خلاصه باید بتوانید به این سؤال پاسخ دهید: «خودت چکار کردی؟». حداقل نشان دهید که فرد حاضر و آماده طلبی نیستید و پیشتر یک حداقل تقلایی را انجام داده‌اید.


کجا باید سؤال پرسید؟
- اگر به انجمنی برای طرح سؤال خود مراجعه کرده‌اید، حتما زیر شاخه صحیحی را انتخاب کنید تا سؤال شما بسته نشود یا کلا حذف نگردد. برای مثال سؤال ASP.NET را در بخش سی‌شارپ نپرسید یا برعکس یا اگر سایتی مقاله‌ای را منتشر کرده، ذیل آن در مورد نحوه بک آپ گرفتن از اکانت توئیتر خود سؤال نپرسید!
- اگر پاسخی را دریافت کردید، ادامه بحث را ذیل همان مطلب پیگیری کنید و مجددا مطلب جدیدی را ایجاد نکنید.
- اگر تا نیم ساعت بعد جوابی را دریافت نکردید، کل بخش‌های یک سایت را با ارسال پیام خود اسپم نکنید. یکبار ارسال یک سؤال کافی است. اکثر این سایت‌ها حالت یک «چت آفلاین» را دارند. به این معنا که ابتدا پیغام خود را می‌گذارید، اگر مدتی بعد (ممکن است چند ساعت بعد) شخصی آن‌را مشاهده کرد و قادر به پاسخ دهی بود، به شما کمک خواهد کرد. بنابراین اگر سریعا به جواب نرسیدید، نه کل سایت را اسپم کنید و نه ... شروع به رفتارهای ناشایست کنید. اینکار با فریاد کشیدن وسط یک جمع تفاوتی ندارد. اشخاص مرتبط همواره آنلاین نیستند؛ ضمنا ممکن است واقعا پاسخی برای یک سؤال نداشته باشند. منصف باشید.
- از ایمیل‌های خصوصی افراد یا قسمت پیام‌های خصوصی سایت‌ها برای ارسال سؤالات شخصی استفاده نکنید. ایمیل خصوصی، مخصوص کارهای شخصی است. قسمت پیام‌های خصوصی یک سایت عموما مخصوص رسیدگی به مشکلات کاربری است. این تصور را نداشته باشید که اشخاص مشاور شخصی رایگان پروژه‌های تجاری شما هستند.
- بهترین محل برای پرسیدن سؤالات مرتبط با یک پروژه خاص، mailing list یا انجمن گفتگو و یا issue tracker آن پروژه است. وقت خودتان را با ارسال خطاهای یک پروژه خاص، در یک انجمن عمومی و همه منظوره تلف نکنید. کمی جستجو کنید که سایت اصلی پروژه کجا است. بعد دقت کنید آیا جایی برای پرسش و پاسخ دارد یا خیر. اکثر پروژه‌های خوب، مکانی را جهت جمع آوری بازخوردهای پروژه خود، اختصاص می‌دهند.


چطور باید سؤال پرسید؟
سؤال فنی خوب پرسیدن هم یک هنر است؛ که تعدادی از مشخصه‌های مهم آن‌را در ذیل مرور خواهیم کرد:
- عنوان مناسبی را برای سؤال خود انتخاب کنید. «لطفا کمک کنید» یا «من مشکل دارم» یا «مشکل در پروژه»، عموما واکنش‌های تندی را به همراه دارند؛ و تا حد ارسال اسپم در یک سایت بی‌کیفیت تلقی می‌شوند. ضمن اینکه انتخاب عنوان‌های مناسب، جستجوهای بعدی را در سایت ساده می‌کنند و کمک بزرگی خواهند بود به افراد بعدی.
- محیطی را که خطا در آن رخ داده است، توضیح دهید. ذکر IIS تنها کافی نیست. کدام نگارش آن؟ در کدام ویندوز؟
برای مثال شماره نگارش کتابخانه یا نرم افزار مورد استفاده را ذکر کنید. شاید خطایی که گرفته‌اید در نگارش بعدی آن برطرف شده است.
ذکر شماره نگارش VS.NET یا شماره نگارش دات نت مورد استفاده، سیستم عامل و کلا توصیف محیط بروز خطا، عموما بسیار مفید هستند.
- حتما کل خطای دریافت شده را ارسال کنید. اگر در یک برنامه C خطایی حاصل شود، احتمالا شکلی مانند Error 0xABCD را دارد. اما استثناءهای دات نت به همراه stack trace و حتی شماره سطر خطای حاصل نیز هستند. همین مساله می‌تواند به خطایابی نهایی بسیار کمک کند.
- سؤال خود را طوری مطرح کنید که شخص مقابل بتواند آن‌را در کمترین زمان ممکن «باز تولید» کند. برای مثال ذکر خطای دریافتی بسیار خوب است. اگر داده‌ای که سبب بروز این خطا شده است را هم ارسال کنید، مفید‌تر خواهد بود؛ یا اگر دستور پاور شل خاصی در کنسول نیوگت خطا می‌دهد، صرفا عنوان نکنید که جواب نگرفته‌اید. چه دستوری را اجرا کرده‌اید؟ چه خطایی را دریافت کرده‌اید؟ ساختار پروژه شما چیست؟ آیا شخص مقابل می‌تواند بر اساس اطلاعاتی که ارائه دادید یک آزمایش شخصی را تدارک ببیند؟ آیا می‌تواند آن‌را با توضیحات شما مجددا تولید کند؟
زمان باز تولید خطا را هم مدنظر داشته باشید. برای مثال اگر بتوانید قطعه کدی را ارائه دهید که در کمترین زمان ممکن، صرفا با کپی و پیست آن در VS.NET قابل کامپایل باشد، بسیاری علاقمند به پاسخگویی به شما خواهند شد. در غیراینصورت آنچنان انتظار نداشته باشید که شخص پاسخ دهنده وقت زیادی را برای رسیدگی به جزئیات سؤال شما صرف کند؛ یا مدتی مشغول به تهیه یک مثال جدید بر مبنای توضیحات شما شود.
حجم کدهای ارسالی شما نیز در اینجا مهم هستند. کل پروژه خود را ارسال نکنید! سعی کنید یک مثال کوچک را که بتواند سریعا خطای مدنظر شما را بازتولید کند، ارسال کنید و نه بیشتر. همچنین کدهایی که برای اجرا نیاز به GUI نداشته باشند نیز در این حالت اولویت دارند.
و به صورت خلاصه، خودتان را بجای پاسخ دهنده قرار دهید. آیا با چند جمله‌ای که ارائه داده‌اید، می‌توان انتظار پاسخی را داشت یا خیر.
- ایمیل شخصی خود را در انتهای پیام ارسال نکنید. کسی اهمیتی نمی‌دهد! اگر سؤال شما پاسخی داشته باشد، همانجا دریافت خواهید کرد و نه در میل باکس شخصی.
- املاء و انشای متنی را که ارسال می‌کنید، یکبار بررسی کنید. اگر برای شما اهمیتی ندارد که چه کلمات و جمله بندی را باید بکار برد، برای شخص مقابل هم آنچنان اهمیتی نخواهد داشت که زیاد وقت صرف کند.
- از بکار بردن smileyهای بیش از حد یا قرار دادن تعداد علامت تعجب‌های بیش از حد خودداری کنید. این موارد عموما به مسخره کردن شخص مقابل تفسیر می‌شوند.
- در بدو امر فریاد نکشید که «باگ» پیدا کرده‌اید؛ خصوصا اگر به mailing list اختصاصی یک پروژه پیامی را ارسال می‌کنید. چون اگر مشکل شما واقعا باگ نباشد، بیشتر یک توهین تلقی خواهد شد و در دفعات بعدی پاسخ دادن به شما به صورت ضمنی مؤثر خواهند بود؛ یا جواب نمی‌گیرید و یا جدی گرفته نخواهید شد.  
- هدف از کاری را که مشغول به انجام آن بود‌ه‌اید را نیز ذکر کنید. ذکر خطای دریافتی بسیار مفید است اما اگر بتوانید یک دید کلی را نسبت به کاری که مشغول به آن بوده‌اید، ایجاد کنید، شاید پاسخ بهتری را دریافت کنید. برای مثال جهت رسیدن به هدف و مقصود شما بهتر است از روش دیگری استفاده کنید.
- پس از اینکه پیامی را دریافت کردید، یک حداقل واکنشی را ارسال کنید. مثلا خوب بود؛ کمک کرد و یا مفید نبود. همین واکنش‌ها در آینده به کمک نتایج جستجوهای انجام شده خواهند آمد و اشخاص بعدی حداقل خواهند دانست که پاسخ داده شده صحیح بوده است یا خیر.

و همیشه بخاطر داشته باشید: تمام خدماتی که سایت‌های عمومی به شما ارائه می‌دهند «یک لطف» است و حقی را برای شما ایجاد نمی‌کنند. این اشخاص از شما پول نمی‌گیرند تا به سؤالات شما پاسخ دهند یا تبدیل به مشاور خصوصی رایگان شما شوند. می‌توانید محیط را برای این اشخاص، با اندکی احترام، ملایمت و انصاف، دلپذیرتر کنید.
نظرات اشتراک‌ها
روش دیگری برای تمیزسازی HTML و مقابله با XSS
ValidHtmlTags = new Dictionary<string, List<string>> {
{ "div", new List<string> { "dir", "align", "style" } }
//...
هر موردی رو که لازم هست خودتون اضافه کنید (این اصلاح در آخرین کامنت مطلب یاد شده پیوست شده).
مطالب
وب‌پارت اسلاید متحرک در شیرپوینت 2010
در خلال تعدادی از پروژه‌هایی که در زمینه توسعه شیرپوینت 2010 درگیر بودم، یکی از وب‌پارت‌هایی که اکثر مشتریان درخواست می‌کردند وب پارت اسلاید متحرک بود. به نظر من داشتن این وب‌پارت ظاهرا خیلی برای مشتریان مهم بنظر می‌رسید، بهمین سبب در زیر به پیاده‌سازی آن اشاره می‌کنم.

ساخت لیست سفارشی

ابتدا یک لیست سفارشی بنام ContentSlides ایجاد می‌کنیم و  ستونی از نوع Rich HTML به آن اضافه می‌کنیم.

ایجاد یک پروژه شیرپوینتی از نوع Visual Web Part

سپس یک پروژه شیرپوینت از نوع Visual Web Part در سایتی که لیست فوق در آن قرار دارد می‌سازیم.





در این مرحله نامگذاری‌های پیش‌فرض ویژوال استودیو که برای ویژوال وب‌پارت در نظر گرفته را به نام مناسب تغییر می‌دهیم.



افزودن پلاگین AnythingSlider

ابتدا پلاگین AnythingSlider را از این آدرس دریافت نمایید. سپس فایلهای anythingslider.css, anythingslider-ie.css, jquery.min.js, jquery.anythingslider.js  و "default.png " را به ویژوال وب‌پارت اضافه می‌کنیم. برای اضافه کردن فایلهای این پلاگین، ابتدا فولدر "Layouts" به پروژه اضافه می‌نماییم و سپس فایلهای این پلاگین در این فولدر قرار می‌دهیم.

سپس در خط 129 و 155 و 181 فایل anythingslider.css

background: url("../images/default.png") no-repeat; 
را به
background: url(“default.png") no-repeat;
تغییر دهید و شکل پروژه به صورت زیر خواهد شد.

در ادامه، بر روی "ContentSliderVisualWebPartUserControl.ascx" دابل کلیک کنید و کد زیر را به آن اضافه می‌کنیم.

<SharePoint:CssRegistration ID="AnythingSliderCssRegistration" runat="server" 
Name="/_layouts/ContentSliderWebPart/anythingslider.css"></SharePoint:CssRegistration>
<SharePoint:CssRegistration ID="AnythingSliderCssRegistrationIE7" runat="server" 
Name="/_layouts/ContentSliderWebPart/anythingslider.css" ConditionalExpression="lte IE 7"></SharePoint:CssRegistration>

<SharePoint:ScriptLink ID="JqueryScriptLink" runat="server" 
Name="/_layouts/ContentSliderWebPart/jquery.min.js"></SharePoint:ScriptLink>
<SharePoint:ScriptLink ID="AnythingSliderScriptLink" runat="server" 
Name="/_layouts/ContentSliderWebPart/jquery.anythingslider.js"></SharePoint:ScriptLink>

توجه کنید در کد بالا ما از کنترل‌های "SharePointCssRegistration" و "SharePointScriptLink" برای اضافه نمودن فایلهای Css و JavaScript مورد نیاز و هم چنین از خصیصه "ConditionalExpression" برای اضافه کردن فایل "anythingslider-ie.css" برای مرورگر اینترنت اکسپلورر 7 به بالا استفاده کردیم.

ایجاد کوئری برای لیست سفارشی

برای ایجاد کوئری از کتابخانه jQuery بنام SPService که از این آدرس قابل دریافت است، استفاده می‌کنیم. فایل "jquery.SPServices.min.js" موجود در این کتابخانه را همانند سایر فایل‌های اضافه شده در قسمت قبل را به پروژه اضافه می‌کنیم.

برای استفاده از کتابخانه، کد زیر را در user control قسمت فبلی و در ادامه کدهای قبلی وارد می‌کنیم.

<SharePoint:ScriptLink ID="SPServicesScriptLink" runat="server" 
Name="/_layouts/ContentSliderWebPart/jquery.SPServices.min.js"></SharePoint:ScriptLink>

و برای ایجاد کوئری کد زیر در user control وارد می‌کنیم.

<script language="javascript" type="text/javascript">

$(document).ready(function () {
$().SPServices({
operation: "GetListItems",
async: false,
listName: "ContentSlides",
CAMLViewFields: "<ViewFields<FieldRef Name='SlidesContent' /></ViewFields>",
completefunc: function (xData, Status) {
$(xData.responseXML).SPFilterNode("z:row").each(function () {
var liHtml = "<li>" + $(this).attr("ows_SlidesContent") + "</li>";
$("#slider").append(liHtml);
});
}
});

/*-- Initialize AnythingSlider plugin --*/
    $('#slider').anythingSlider();

});
</script>

<ul id="slider" />

وظیفه این کد انجام کوئری بر روی لیست "ContentSlides" و ایجاد ساختار یک لیست جهت نمایش اسلایدها می‌باشد که آیتم‌های این لیست مقادیر ستون
"Slides Content" می‌باشد، شناسه این لیست "Slider" است.

توجه کنید: ما می‌توانیم CAML Queryهای پیشرفته‌ای برای اعمال فیلتر مناسب و چیدمان اسلایدها استفاده کنیم.

در ادامه، برای مقدار دهی اولیه به پلاگین بوسیله فراخوانی تابع

 $('#slider').anythingSlider();

انجام می‌شود.

در پایان براحتی با Deploy نمودن Solution، امکان استفاده از وب پارت مهیاست.

برای دریافت کد این پروژه از این آدرس استفاده کنید.

مطالب
چرا توسعه چابک (Agile Development)؟

خیلی از ما با کابوس پروژه ای که هیچ تجربه ای در انجام آن نداریم روبرو شده ایم. نبودن تجربه موثر منجر به خطاهای تکراری و غیر قابل پیش بینی شده و تلاش و وقت ما را به هدر می­دهد. مشتریان از کیفیت پایین، هزینه بالا و تحویل دیر هنگام محصول ناراضی هستند و توسعه دهندگان از اضافه کارهای بیشتر که منجر به نرم افزار ضعیت­تر می­گردد، ناخشنود.

همین که با شکستی مواجه می­شویم از تکرار چنین پروژه هایی اجتناب می­کنیم. ترس ما باعث می­شود تا فرآیندی بسازیم که فعالیت­های ما را محدود نموده و ایجاد آرتیفکت­ها[۱] را الزامی کند. در پروژه­ جدید از  چیزهایی که در پروژه‌های قبلی به خوبی کار کرده­اند، استفاده می­کنیم. انتظار ما این است که آنها برای پروژه جدید نیز به همان خوبی کار کند.

اما پروژه‌­ها آنقدر ساده نیستند که تعدادی محدودیت و آرتیفکت­ ما را از خطاها ایمن سازند. با بروز خطاهای جدید ما آنها را شناسایی و رفع می­کنیم. برای اینکه در آینده با این خطاها روبرو نشویم آنها را در محدودیت­ها و آرتیفکت­های جدیدی قرار می­دهیم. بعد از انجام پروژه‌های زیاد با فرآیندهای حجیم و پر زحمتی روبرو هستیم که توانایی تیم را کم کرده و باعث کاهش کیفیت تولید می­شوند.

فرآیندهای بزرگ و حجیم می­تواند مشکلات زیادی را ایجاد کند. متاسفانه این مشکلات باعث می­شود که خیلی از افراد فکر کنند که علت مشکلات، نبود فرآیندهای کافی است. بنابراین فرآیندها را حجیم­تر و پیچیده­تر می­کنند. این مسئله منجر به تورم فرآیندها می­گردد که در محدوده سال ۲۰۰۰ گریبان بسیاری از شرکت­های نرم افزاری را گرفت.

اتحاد چابک

در وضعیتی که تیم­های نرم افزاری در بسیاری از شرکت­ها خود را در مردابی از فرآیندهای زیاد شونده می­دیدند، تعدادی از خبره‌­های این صنعت که خود را اتحاد چابک[۲] نامیدند در اویل سال ۲۰۰۱ یکدیگر را ملاقات کرده و ارزش هایی را معرفی کردند تا تیم­های نرم افزاری سریعتر نرم افزار را توسعه داده و زودتر به تغییرات پاسخ دهند. چند ماه بعد، این گروه ارزش­هایی تعریف شده را تحت مانیفست اتحاد چابک در سایت http://agilemanifesto.org منتشر کردند.

مانیفست اتحاد چابک

ما با توسعه نرم افزار و کمک به دیگران در انجام آن، در حال کشف راه‌های بهتری برای توسعه نرم افزار هستیم. از این کار به ارزش‌های زیر می­رسیم :

۱- افراد و تعاملات بالاتر از فرآیندها و ابزارها

۲- نرم افزار کار کننده بالاتر از  مستندات جامع

۳- مشارکت مشتری بالاتر از قرارداد کاری

۴- پاسخگویی به تغییرات بالاتر از پیروی از یک برنامه

با آنکه موارد سمت چپ ارزشمند هستند ولی ما برای موارد سمت راست ارزش بیشتری قائل هستیم.

افراد و تعاملات بالاتر از فرآیندها و ابزارها

افراد مهمترین نقش را در پیروزی یک پروژه دارند. یک فرآیند عالی بدون نیروی مناسب منجر به شکست می­گردد و بر عکس افراد قوی تحت فرآیند ضعیت ناکارآمد خواهند بود.

یک نیروی قوی لازم نیست که برنامه نویسی عالی باشد، بلکه کافیست که یک برنامه نویسی معمولی با قابلیت همکاری مناسب با سایر اعضای تیم باشد. کار کردن با دیگران، تعامل درست و سازنده با سایر اعضای تیم خیلی مهمتر از این که یک برنامه نویس با هوش باشد. برنامه نویسان معمولی که تعامل درستی با یکدیگر دارند به مراتب موفقتر هستند از تعداد برنامه نویسی عالی که قدرت تعامل مناسب با یکدیگر را ندارند.

در انتخاب ابزارها آنقدر وقت نگذارید که کار اصلی و تیم را فراموش کنید. به عنوان مثال می­توانید در شروع به جای بانک اطلاعاتی از فایل استفاده کنید، به جای ابزار کنترل کد گرانقیمت از برنامه رایگان کد باز استفاده کنید. باید به هیچ ابزاری عادت نکنید و صرفا به آنها به عنوان امکانی جهت تسهیل فرآیندها نگاه کنید.

نرم افزار کار کننده بالاتر از  مستندات جامع

نرم افزار بدون مستندات، فاجعه است. کد برنامه ابزار مناسبی برای تشریح سیستم نرم افزاری نیست. تیم باید مستندات قابل فهم مشتری بسازد تا ابعاد سیستم از تجزیه تحلیل تا طراحی و پیاده سازی آن را تشریح نماید.

با این حال، مستندات زیاد از مستندات کم بدتر است. ساخت مستندات زیاد نیاز به وقت زیادی دارد و وقت بیشتری را می‌گیرد تا آن را با کد برنامه به روز نمایید. اگر آنها با یکدیگر به روز نباشند باعث درک اشتباه از سیستم می‌شوند.

بهتر است که همیشه مستندات کم حجمی از منطق و ساختار برنامه داشته باشید و آن را به روز نماید. البته آنها باید کوتاه و برجسته باشند. کوتاه به این معنی که ۱۰ تا ۲۰ صفحه بیشتر نباشد و برجسته به این معنی که طراحی کلی و ساختار سطح بالای سیستم را بیان نماید.

اگر فقط مستندات کوتاه از ساختار و منطق سیستم داشته باشیم چگونه می‌توانیم اعضای جدید تیم را آموزش دهیم؟ پاسخ کار نزدیک شدن به آنها است. ما دانش خود را با نشستن در کنار آنها و کمک کردن به آنها انتقال می­دهیم. ما آنها را بخشی از تیم می­کنیم و با تعامل نزدیک و رو در رو به آنها آموزش می­دهیم.

مشارکت مشتری بالاتر از قرارداد کاری

نرم افزار نمی­تواند مثل یک جنس سفارش داده شود. شما نمی‌توانید یک توصیف از نرم افزاری که می‌خواهید را بنویسید و آنگاه فردی آن را بسازد و در یک زمان معین با قیمت مشخص به شما تحویل دهد. بارها و بارها این شیوه با شکست مواجه شده است.

این قابل تصور است که مدیران شرکت به اعضای تیم توسعه بگویند که نیازهای آنها چیست، سپس اعضای تیم بروند و بعد از مدتی برگردند و یک سیستمی که نیازهای آنها را برآورده می‌کند، بسازند. اما این تعامل به کیفیت پایین نرم افزار و در نهایت شکست آن می‌انجامد. پروژه‌های موفق بر اساس دریافت بازخورد مشتری در بازه‌های زمانی کوتاه و مداوم است. به جای وابستگی به قرارداد یا دستور کار، مشتری به طور تنگاتنگ با تیم توسعه کار کرده و مرتبا اعمال نظر می­کند.

قراردادی که مشخص کننده نیازمندیها، زمانبندی و قیمت پروژه است، اساسا نقص دارد. بهترین قرارداد این است که تیم توسعه و مشتری با یکدیگر کار کنند.

پاسخگویی به تغییرات بالاتر از پیروی از یک برنامه

توانایی پاسخ به تغییرات اغلب تعیین کننده موفقیت یا شکست یک پروژه نرم افزاری است. وقتی که طرحی را می­ریزیم باید مطمئن شویم که به اندازه کافی انعطاف پذیر است و آمادگی پذیرش تغییرات در سطح بیزنس و تکنولوژی را دارد.

مسیر یک پروژه نرم افزاری نمی­تواند برای بازه زمانی طولانی برنامه ریزی شود. اولا احتمالا محیط تغییر می­کند و باعث تغییر در نیازمندی‌ها می­شود. ثانیا همین که سیستم شروع به کار کند مشتریان نیازمندی­های خود را تغییر می‌دهند. بنابراین اگر بدانیم که نیازها چیست و مطمئن شویم که تغییر نمی­کنند، قادر به برآورد مناسب خواهیم بود، که این شرایط بعید است.

یک استراتژی خوب برای برنامه ریزی این است که یک برنامه ریزی دقیق برای یک هفته بعد داشته باشیم و یک برنامه ریزی کلی برای سه ماه بعد.

اصول چابک

۱- بالاترین اولویت ما عبارت است از راضی کردن مشتری با تحویل سریع و مداوم نرم افزار با ارزش. تحویل نرم افزار با کارکردهای کم در زود هنگام بسیار مهم است چون هم مشتری چشم اندازی از محصول نهایی خواهد داشت و هم مسیر کمتر به بیراهه می‌رود.

۲- خوش آمدگویی به تغییرات حتی در انتهای توسعه. اعضای تیم چابک، تغییرات را چیز خوبی می‌بینند زیرا تغییرات به این معنی است که تیم بیشتر یاد گرفته است که چه چیزی مشتری را راضی می‌کند.

۳- تحویل نرم افزار قابل استفاده از چند هفته تا چند ماه با تقدم بر تحویل در دوره زمانی کوتاهتر. ما مجموعه از مستندات و طرحها را به مشتری نمی‌دهیم.

۴- افراد مسلط به بیزنس و توسعه دهندگان باید روزانه با یکدیگر روی پروژه کار کنند. یک پروژه نرم افزاری نیاز به هدایت مداوم دارد.

۵- ساخت پروژه را بر توان افراد با انگیزه بگذارید و به آنها محیط و ابزار را داده و اعتماد کنید.  مهمترین فاکتور موفقیت افراد هستند، هر چیز دیگر مانند فرآیند، محیط و مدیریت  فاکتورهای بعدی محسوب می­شوند که اگر تاثیر بدی روی افراد می­گذارند، باید تغییر کنند.

۶- بهترین و موثر‌ترین روش کسب اطلاعات در تیم توسعه، ارتباط چهره به چهره است. در تیم چابک افراد با یکدیگر صحبت می‌کنند. نامه نگاری و مستند سازی فقط زمانی که نیاز است باید صورت گیرد.

۷- نرم افزار کار کننده معیار اصلی پیشرفت است. پروژه‌های چابک با نرم افزاری که در حال حاضر نیازهای مشتری را پاسخ می‌دهد، سنجیده می‌شوند. میزان مستندات، حجم کدهای زیر ساخت و هر چیز دیگری غیره از نرم افزار کار کننده معیار پیشرفت نرم افزار نیستند.

۸- فرآیندهای چابک توسعه با آهنگ ثابت را ترویج می‌دهد. حامیان، توسعه دهندگان و کاربران باید یک آهنگ توسعه ثابت را حفظ کنند که بیشتر شبیه به دو  ماراتون است یا دوی ۱۰۰ متر. آنها با سرعتی کار می‌کنند که بالاترین کیفیت را ارائه دهند.

۹- توجه مداوم به برتری تکنیکی و طراحی خوب منجر به چابکی می­گردد. کیفیت بالاتر کلیدی برای سرعت بالا است. راه سریعتر رفتن این است که نرم افزار تا جایی که ممکن است پاک و قوی نگهداریم. بنابراین همه اعضای تیم چابک تلاش می­کنند که با کیفیت­ترین کار ممکن را انجام دهند. آنها هر آشفتگی را به محض ایجاد برطرف می‌کنند.

۱۰-  سادگی هنر بیشینه کردن مقدار کاری که لازم نیست انجام شود، است. تیم چابک همیشه ساده‌ترین مسیر که با هدف آنها سازگار است را در پیش می­گیرند. آنها وقت زیادی روی مشکلاتی که ممکن است فردا رخ دهد، نمی­گذارند.  آنها کار امروز را با کیفیت انجام داده و مطمئن می­شوند که تغییر آن در صورت بروز مشکلات در فردا، آسان خواهد بود.

۱۱-  بهترین معماری و طراحی از تیم‌های خود سازمان ده بیرون می‌آید. مدیران، مسئولیت‌ها را به یک فردی  خاصی در تیم نمی‌دهند بلکه بر عکس با تیم به صورت یک نیروی واحد برخورد می­کنند. خود تیم تصمیم می­گیرد که هر مسئولیت را چه کسی انجام دهد. تیم چابک با هم روی کل جنبه‌های پروژه کار می­کنند. یعنی یک فرد خاص مسئول معماری، برنامه نویسی، تست و غیره نیستند. تیم، مسئولیتها را به اشتراک گذاشته و هر فرد بر کل کار تاثیر دارد.

۱۲-  در بازهای زمانی مناسب تیم در می­یابد که چگونه می­تواند کاراتر باشد و رفتار خود را متناسب با آن تغییر دهد. تیم می­داند که محیط دائما در حال تغییر است، بنابراین خود را با محیط تغییر می­دهد تا چابک بماند.

ضرورت توسعه چابک

امروزه صنعت نرم افزار دارای سابقه بدی در تحویل به موقع و با کیفیت نرم افزار است. گزارشات بسیاری تایید می­کنند که بیش از ۸۰ درصد از پروژه‌های نرم افزاری با شکست مواجه می­شوند؛ در سال ۲۰۰۵ موسسه IEEE  برآورد زده است که بیش از ۶۰ بیلیون دلار صرف پروژه‌های نرم افزاری شکست خورده شده است. عجب فاجعه­ای؟

شش دلیل اصلی شکست پروژه‌های نرم افزاری

وقتی که از مدیران و کارکنان سوال می­شود که چرا پروژه‌های نرم افزاری با شکست مواجه می­شوند، آنها به موضوعات گسترده ای اشاره می­کنند. اما شش دلیل زیر بارها و بارها تکرار شده است که به عنوان دلایل اصلی شکست نرم افزار معرفی می­شوند:

۱- درگیر نشدن  مشتری

۲- عدم درک درست نیازمندها

۳- زمان بندی غیر واقعی

۴- عدم پذیریش و مدیریت تغییرات

۵- کمبود تست نرم افزار

۶- فرآیندهای غیر منعطف و باد دار

چگونه چابکی این مشکلات را رفع می­کند؟

با آنکه Agile برای هر مشکلی راه حل ندارد ولی برای مسائل فوق بدین صورت کمک می­کند:

مشتری پادشاه است!

برای رفع مشکل عدم همکاری کاربر نهایی یا مشتری، Agile مشتری را عضوی از تیم توسعه می­کند. به عنوان عضوی از تیم، مشتری با تیم توسعه کار می­کند تا مطمئن شود که نیازمندها به درستی برآورده می­شوند. مشتری همکاری می­کند در شناسایی نیازمندی­ها، تایید می­کند نتیجه نهایی را و حرف آخر را در اینکه کدام ویژگی به نرم افزار اضافه شود، حذف شود و یا تغییر کند، را می­زند.

نیازمندی‌ها به صورت تست­های پذیرش[۳] نوشته می­شوند

برای مقابله با مشکل عدم درک درست نیازمندی­ها، Agile تاکید دارد که نیازمندیهای کسب شده باید به صورت ویژگی­هایی تعریف شوند که بر اساس معیارهای مشخصی قابل پذیرش باشند. این معیارهای پذیرش برای نوشتن تست­های پذیرش به کار می­روند. به این ترتیب قبل از اینکه کدی نوشته شود، ابتدا تست پذیرش نوشته می­شود. این بدین معنی است که هر کسی باید اول فکر کند که چه می­خواهد، قبل از اینکه از کسی بخواهد آن را انجام دهد. این راهکار فرایند کسب نیازمندی­ها را از بنیاد تغییر می­دهد و به صورت چشم گیری کیفیت برآورد و زمان بندی را بهبود می­دهد.

زمانبندی با مذاکره بین تیم توسعه و سفارش دهنده تنظیم می­شود

برای حل مشکل زمان بندی غیر واقعی، Agile زمان بندی را به صورت یک فرآیند مشترک بین تیم توسعه و سفارش دهنده تعریف می­کند. در شروع هر نسخه از  نرم افزار، سفارش دهنده ویژگی‌های مورد انتظار را به تیم توسعه می­گوید. تیم توسعه تاریخ تحویل را بر اساس ویژگی­ها برآورد می­زد و در اختیار سفارش دهنده قرار می­دهد. این تعامل تا رسیدن به یک دیدگاه مشترک ادامه می­یابد.

هیچ چیزی روی سنگ حک نشده است، مگر تاریخ تحویل

برای رفع مشکل ضعف در مدیریت تغییرات، Agile اصرار دارد که هر کسی باید تغییرات را بپذیرد و نسبت به آنها واقع بین باشد. یک اصل مهم Agile  می­گوید که هر چیزی می­تواند تغییر کند مگر تاریخ تحویل! به عبارت دیگر همین که محصول به سمت تولید شدن حرکت می­کند، مشتری (در تیم محصول) می­تواند بر اساس اولویت­ها و ارزش­های خود ویژگی­های محصول را کم یا زیاد کرده و یا تغییر دهد. به هر حال او باید واقع بین باشد. اگر او یک ویژگی جدید اضافه کنید، باید تاریخ تحویل را تغییر دهد. به این ترتیب همیشه تاریخ تحویل رعایت می­گردد.

تست­ها قبل از کد نوشته می­شوند و کاملا خودکار هستند

برای رفع مشکل کمبود تست، Agile تاکید می­کند که ابتدا باید تست­ها نوشته شوند و همواره ارزیابی گردند. هر برنامه نویس باید اول تست­ را بنویسد، سپس کد لازم برای پاس شدن آن را. همین که کد تغییر می­کند باید تست­ها دوباره اجرا شوند. در این راهکار، هر برنامه نویس مسئول تست­های خود است تا درستی برنامه از ابتدا تضمین گردد.

مدیریت پروژه یک فعالیت جداگانه نیست

برای رفع مشکل فرآیندهای غیر منعطف و باددار، Agile مدیریت پروژه را درون فرآیند توسعه می­گنجاند. وظایف مدیریت پروژه بین اعضای تیم توسعه تقسیم می­شود. برای مثال هر ۷ نفر در تیم توسعه نرم افزار (متدلوژی اسکرام) زمان تحویل را با مذاکره تعیین می­کنند. همچنین کد برنامه به صورت خودکار اطلاعات وضعیت پروژه را تولید می­کند. به عنوان مثال  نمودار burndown ، تست­های انجام نشده، پاس شده و رد شده به صورت خودکار تولید می­شوند.

به کار گیری توسعه چابک

یکی از مشکلات توسعه چابک این است که شما اول باید به خوبی آن را درک کنید تا قادر به پیاده سازی درست آن باشید. این درک هم باید کلی باشد (مانند Scrum و XP) و هم جزئی (مانند TDD و جلسات روازنه). اما چگونه باید به این درک برسیم؟ کتاب­ها و مقالات انگلیسی زیادی برای یادگیری توسعه چابک و پیاده سازی آن در سازمان وجود دارند، ولی متاسفانه منابع فارسی کمی در این زمینه است. هدف این کتاب رفع این کمبود و آموزش عملی توسعه چابک و ابزارهای پیاده سازی آن است.

برای این یک توسعه دهنده چابک شوید، باید به مهارت­های فردی و تیمی چابک برسید. در ادامه این مهارت­ها معرفی می­شوند.

مهارت­های فردی

قبل از هر چیز شما باید یک برنامه نویس باشید و مقدمات برنامه نویسی مانند الگوریتم و فلوچارت، دستورات برنامه نویسی، کار با متغیرها، توابع و آرایه­‌ها را بلد باشید. پس از تسلط به مقدمات برنامه نویسی می­توانید مهارت­های برنامه نویسی چابک را فرا بگیرید که عبارتند از:

- برنامه نویسی شیءگرا

- توسعه تست محور

- الگوهای طراحی

در ادامه نحوه کسب این مهارت­ها بیان می­شوند.

برنامه نویسی شیءگرا

اساس طراحی چابک بر تفکر شیءگرا استوار است. بنابراین تسلط به مفاهیم و طراحی شیءگرا ضروری است. 

توسعه تست محور

مهمترین و انقلابی‌ترین سبک برنامه نویسی از دهه گذشته تا به امروز، توسعه یا برنامه نویسی تست محور است. این سبک بسیاری از ارزش‌های توسعه چابک را فراهم می­کند و یادگیری آن برای هر توسعه دهنده چابک ضروری است.

الگوهای طراحی

الگوهای طراحی راه حل­های انتزاعی سطح بالا هستند. این الگوها بهترین تکنیک­های[۴] طراحی نرم افزار هستند و بسیاری از مشکلاتی که در طراحی نرم افزار رخ می­دهند با استفاده از این الگوها قابل حل هستند.

مهارت­های تیمی

انجام پروژه نرم افزاری یک کار تیمی است. شما پس از یادگیری مهارت­های فردی باید خود را آماده حضور در تیم توسعه چابک کنید. برای این منظور باید با مهارت تیمی مانند آشنایی با گردشکار تولید نرم افزار، حضور موثر در جلسات، قبول مسئولیت­ها و غیره آشنا شوید.

اسکرام

تمامی مهارت­های تیمی توسعه چابک توسط اسکرام آموزش داده می­شوند. اسکرام فریم ورکی برای توسعه چابک است که با تعریف فرآیندها، نقش­ها و آرتیفکت­های مشخص به تیم­های نرم افزاری کمک می­کند تا چابک شوند.


[۱] Artifact : خروجی یک فرآیند  است. مثلا خروجی طراحی شیءگرا، نمودارهای UML است.

[۲] Agile Alliance

[3] Acceptance Tests

[4] Best Practice

--------------------------------

اطلاعات بیشتر در http://AgileDevelopment.ir

نظرات مطالب
ASP.NET MVC #17

سلام؛ ممنون بابت پاسختون. این طوری به forgeryToken نگاه نکرده بودم.

در صفحه برای Delete و ثبت اطلاعات و یا حتی فیلترکردن اطلاعات و هرجا که کاربر اطلاعاتی وارد می‌کند از AntiForgeryToken استفاده کردم و حذف و ورود اطلاعات و فیلتر کلا در یک صفحه اما هرکدام در تگ Form مجزایی ارسال و دریافت می‌شود و در هر تگ Form یک ForgeryToken گذاشتم.

برای اونها چه کار کنم؟ اصلا کار بنده درست بوده؟ من هرکجا کاربر اطلاعاتی وارد کرده از Token استفاده کردم ولی مشکل اینجاست که با توجه به طراحی کل اونها نیازه که در یک صفحه باشه.

می تونم یک AntiForgeryToken کلی داشته باشم و با جاوا اسکریپت اون و بخونم و به Form.Serilaise() اضافه کنم. اما می‌خواستم راه بهینه اون و بپرسم.

نظرات مطالب
متدی برای بررسی صحت کد ملی وارد شده
دوست گلم سلام
طبق فرمول‌های ارائه شده با بررسی کد ملی به طریق بالا که اگر اینترنت هم جستجو بزنین فرمول هاش ارائه شده این اعداد با روش بالا بررسی شده و در صورت عدم اعتبار کد ملی به شما خروجی میده. روشی که شما می‌خوای پیش بگیری اینه که باید برین و لیست کد تمام شهرستان‌های ایران بگیرین و توی برنامه به کار ببندین. که به نظرم روش جالبی نیست
مطالب
چرا TypeScript؟
زبان TypeScript به عنوان superset زبان JavaScript ارائه شده‌است و هدف آن، strong typing و ارائه‌ی قابلیت‌های پیشرفته‌ی زبان‌های شیءگرا، جهت نوشتن برنامه‌های کلاینت و سرور، با کمترین میزان خطاها است. زبان TypeScript چندسکویی و سورس باز است و در نهایت به نگارشی از JavaScript کامپایل می‌شود که با تمام مرورگرهای فعلی سازگاری دارد و یا در سمت سرور بدون مشکلی توسط NodeJS قابل درک است.
- TypeScript زبان توصیه شده‌ی توسعه‌ی برنامه‌های AngularJS 2 است و همچنین با سایر کتابخانه‌های معروف جاوا اسکریپتی مانند ReactJS و jQuery نیز سازگاری دارد. بنابراین اگر قصد دارید به AngularJS 2 مهاجرت کنید، اکنون فرصت خوبی است تا زبان TypeScript را نیز بیاموزید. همچنین WinJS نیز با TypeScript نوشته شده‌است.
- superset زبان JavaScript بودن به این معنا است که تمام کدهای جاوا اسکریپتی موجود، به عنوان کد معتبر TypeScript نیز شناخته می‌شوند و همین مساله مهاجرت به آن‌را ساده‌تر می‌کند. زبان‌های دیگری مانند Dart و یا CoffeeScript ، نسبت به JavaScript بسیار متفاوت به نظر می‌رسند؛ اما Syntax زبان TypeScript شباهت بسیار زیادی به جاوا اسکریپت و خصوصا ES 6 دارد. در اینجا تنها کافی است پسوند فایل‌های js را به ts تغییر دهید و از آن‌ها به عنوان کدهای معتبر TypeScript استفاده کنید.
- strong typing و معرفی نوع‌ها، کدهای نهایی نوشته شده را امن‌تر می‌کنند. به این ترتیب کامپایلر، پیش از اینکه کدهای شما در زمان اجرا به خطا بر بخورند، در زمان کامپایل، مشکلات موجود را گوشزد می‌کند. همچنین وجود نوع‌ها، سرعت توسعه را با بهبود ابزارهای مرتبط با برنامه نویسی، افزایش می‌دهند؛ از این جهت که مفهوم مهمی مانند Intellisense، با وجود نوع‌ها، پیشنهادهای بهتر و دقیق‌تری را ارائه می‌دهد. همچنین ابزارهای Refactoring نیز در صورت وجود نوع‌ها بهتر و دقیق‌تر عمل می‌کنند. این موارد مهم‌ترین دلایل طراحی TypeScript جهت توسعه و نگهداری برنامه‌های بزرگ نوشته شده‌ی با JavaScript هستند.
- Syntax زبان TypeScript به شدت الهام گرفته شده از زبان سی‌شارپ است. به همین جهت اگر با این زبان آشنایی دارید، درک مفاهیم TypeScript برایتان بسیار ساده خواهد بود.
- بهترین قسمت TypeScript، کامپایل شدن آن به ES 5 است (به این عملیات Transpile هم می‌گویند). در زبان TypeScript به تمام امکانات پیشرفته‌ی ES 6 مانند کلاس‌ها و ماژول‌ها دسترسی دارید، اما کد نهایی را که تولید می‌کند، می‌تواند ES 5 ایی باشد که هم اکنون تمام مرورگرهای عمده آن‌را پشتیبانی می‌کنند. با تنظیمات کامپایلر TypeScript، امکان تولید کدهای ES 3 تا ES 5 و همچنین ES 6 نیز وجود دارد. نمونه‌ی آنلاین این ترجمه را در TypeScript playground می‌توانید مشاهده کنید.
- TypeScript چندسکویی است. امکانات و کامپایلر این زبان، برای ویندوز، مک و لینوکس طراحی شده‌اند.
- TypeScript سورس باز است. طراحان اصلی آن، همان طراحان زبان سی‌شارپ در مایکروسافت هستند و هم اکنون این زبان به صورت سورس باز توسط این شرکت توسعه داده شده و در GitHub نگهداری می‌شود.


آماده سازی محیط‌های کار با TypeScript

برای کار با TypeScript، یک ادیتور متنی ساده، به همراه کامپایلر آن کفایت می‌کند. اما همانطور که عنوان شد، یکی از مهم‌ترین دلایل وجودی TypeScript، بهبود ابزارهای برنامه نویسی مرتبط با JavaScript است و اگر قرار باشد صرفا از یک ادیتور متنی ساده استفاده شود، فلسفه‌ی وجودی آن زیر سؤال می‌رود.

نصب TypeScript در ویژوال استودیو

در نگارش‌های جدید ویژوال استودیو، از VS 2013 Update 2 به بعد، قسمت ویژه‌ی TypeScript نیز قابل مشاهده‌است. البته این قسمت با به روز رسانی‌های TypeScript، نیاز به به روز رسانی دارد. به همین جهت به سایت رسمی آن مراجعه کرده و بسته‌های جدید مخصوص VS 2013 و یا 2015 آن‌را دریافت و نصب کنید.


همچنین افزونه‌ی Web Essentials نیز امکانات بیشتری را جهت کار با TypeScript به همراه دارد و امکان مشاهده‌ی خروجی جاوا اسکریپت تولیدی را در حین کار با فایل TypeScript فعلی میسر می‌کند. در سمت چپ صفحه TypeScript را خواهید نوشت و در سمت راست، خروجی JavaScript نهایی را بلافاصله مشاهده می‌کنید.


تصویر فوق مربوط به VS 2015 است. همچنین گزینه‌ی افزودن یک فایل و آیتم جدید نیز امکان افزودن فایل‌های TS را به همراه دارد.


نصب و تنظیم TypeScript در ویژوال استودیو کد

ویژوال استودیو کد، نگارش رایگان، سورس باز و چندسکویی ویژوال استودیو است که بر روی ویندوز، مک و لینوکس قابل اجرا است. ویژوال استودیو کد نیز به همراه پشتیبانی بسیار خوبی از TypeScript است، تا حدی که تمام ارائه‌های معرفی Anugular 2 توسط تیم مربوطه‌ی آن از گوگل، توسط ویژوال استودیو کد و یکپارچگی آن با TypeScript انجام شدند.


ویژوال استودیو کد بر مبنای فولدرها کار می‌کند و با گشودن یک پوشه در آن (با کلیک بر روی دکمه‌ی open folder آن)، امکان کار کردن با آن پوشه و فایل‌های موجود در آن را خواهیم یافت.
نکته‌ی مهم اینجا است که پس از نصب VS Code، برای فایل‌های با پسوند ts بلافاصله Intellisense مرتبط نیز مهیا است و نیاز به هیچگونه تنظیم اضافه‌تری ندارد. همچنین قابلیت‌های type safety این زبان نیز در این ادیتور به نحو واضحی مشخص هستند:


در ادامه ابتدا یک پوشه‌ی جدید خالی را ایجاد کنید و سپس این پوشه را در VS Code باز نمائید (از طریق منوی فایل، گزینه‌ی گشودن پوشه). سپس ماوس را بر روی نام این پوشه حرکت دهید:


همانطور که مشاهده می‌کنید، دکمه‌ی new file ظاهر می‌شود. در اینجا می‌توانید فایل جدیدی را به نام test.ts اضافه کنید.
در ادامه با فشردن دکمه‌های ctrl+shift+p، امکان انتخاب یک task runner را جهت کامپایل فایل‌های ts خواهیم داشت:


در اینجا ابتدا عبارت task< را وارد کنید و سپس از منوی باز شده، گزینه‌ی rub build task را انتخاب کنید:


پس از آن، در بالای صفحه مشاهده خواهید کرد که عنوان شده: «هنوز هیچ task runner ایی برای اینکار تنظیم نشده‌است»


برای این منظور بر روی دکمه‌ی configure task runner تصویر فوق که با رنگ آبی مشخص شده‌است، کلیک کنید. به این ترتیب یک فایل جدید به نام task.json ایجاد می‌شود که در پوشه‌ای به نام vscode. در ریشه‌ی پروژه (یا همان پوشه‌ی جاری) قرار می‌گیرد:


فایل task.json دارای تعاریفی است که کامپایلر TypeScript یا همان tsc را فعال می‌کند:
{
"version": "0.1.0",

// The command is tsc. Assumes that tsc has been installed using npm install -g typescript
"command": "tsc",

// The command is a shell script
"isShellCommand": true,

// Show the output window only if unrecognized errors occur.
"showOutput": "silent",

// args is the HelloWorld program to compile.
"args": ["HelloWorld.ts"],

// use the standard tsc problem matcher to find compile problems
// in the output.
"problemMatcher": "$tsc"
}
محتوای پیش فرض و ابتدایی این فایل را در قطعه کد فوق مشاهده می‌کنید. این فایل json را جهت تنظیمات کامپایلر TypeScript پروژه‌ی جاری، ویرایش خواهیم کرد. در این فایل دکمه‌ی ctrl+space را بفشارید. بلافاصله منوی تکمیل کننده‌ی این فایل ظاهر می‌شود. از ترکیب ctrl+space در قسمت‌های مختلف این فایل جهت دریافت توصیه‌های بیشتری نیز می‌توان استفاده کرد.
در اینجا قسمتی که نیاز به تنظیم دارد، خاصیت args است. مقادیر آن، پارامترهایی هستند که به کامپایلر typescript ارسال می‌شوند. برای نمونه آن‌را به صورت ذیل تغییر دهید:
"args": [
         "--target", "ES5",
         "--outdir", "js",
         "--sourceMap",
         "--watch",
         "test.ts"
    ],
پارامتر و سوئیچ target مشخص می‌کند که خروجی تولیدی باید با فرمت ES 5 باشد. همچنین فایل‌های js تولیدی را در پوشه‌ی js در ریشه‌ی پروژه یا پوشه‌ی جاری قرار دهد. پارامتر sourceMap مشخص می‌کند که علاوه بر فایل‌های js، فایل‌های map که بیانگر نگاشت بین فایل‌های ts و js هستند نیز تولید شوند. این فایل‌ها برای دیباگ برنامه بسیار مفید هستند. پارامتر watch، کلیه‌ی تغییرات پوشه‌ی جاری را تحت نظر قرار داده و به صورت خودکار کار کامپایل را انجام می‌دهد. در آخر نیز فایل و یا فایل‌های ts مدنظر ذکر می‌شوند.
برای اجرای کامپایلر، ابتدا از منوی view گزینه‌ی toggle output را انتخاب کنید تا بتوان خروجی نهایی کامپایلر را مشاهده کرد. سپس گزینه‌ی view->command pallet و اجرا tasks< را انتخاب کنید. در ادامه همانند مرحله‌ی قبل، یعنی گزینه‌ی run build task را اجرا کنید (که خلاصه‌ی این عملیات ctrl+shift+B است).

به این ترتیب پوشه‌ی js که در خاصیت args مشخص کردیم، تولید می‌شود:


البته این خطا هم در قسمت output نمایش داده می‌شود:
 error TS5023: Unknown option 'watch'
Use the '--help' flag to see options.

علت اینجا است که در تنظیمات فوق، خاصیت command به tsc تنظیم شده‌است و همانطور که در کامنت آن عنوان شده‌است، کامپایلر typescript را از طریق دستور npm install -g typescript دریافت می‌کند و نیازی به ذکر مسیر آن در اینجا نیست. بنابراین لازم است تا با npm و نصب typescript از طریق آن آشنا شد و به این ترتیب کامپایلر آن‌را به روز کرد تا دستور watch را شناسایی کند.


نصب TypeScript از طریق npm

همانطور که عنوان شد، TypeScript چندسکویی است و این مورد را از طریق npm یا NodeJS package manager انجام می‌دهد. برای این منظور به آدرس https://nodejs.org/en   مراجعه کرده و فایل نصاب آن‌را مخصوص سیستم عامل خود دریافت و سپس نصب کنید. Node.js یک runtime سمت سرور اجرای برنامه‌های جاوا اسکریپتی است. از آنجائیکه TypeScript در نهایت به JavaScript تبدیل می‌شود، استفاده از node.js انتخاب مناسبی جهت اجرا و توزیع آن در تمام سیستم عامل‌ها بوده‌است.
پس از نصب node.js، از package manager آن که npm نام دارد، جهت نصب TypeScript استفاده می‌شود. چون node.js به Path و مسیرهای اصلی ویندوز اضافه می‌شود، تنها کافی است دستور npm install -g typescript را در خط فرمان صادر کنید. در اینجا سوئیچ g به معنای global و دسترسی عمومی است.


همانطور که در این تصویر مشخص است، پس از صدور دستور نصب TypeScript، نگارش 1.8.9 آن نصب شده‌است. اما زمانیکه کامپایلر tsc را با پارامتر version اجرا می‌کنیم، شماره نگارش قدیمی 1.0.3.0 را نمایش می‌دهد. برای رفع این مشکل به مسیر C:\Program Files (x86)\Microsoft SDKs\TypeScript مراجعه کرده و پوشه‌ی 1.0 را به 1.0-old تغییر نام دهید.


اکنون اگر مجددا بررسی کنیم، نگارش صحیح قابل مشاهده است:


پس از این تغییرات اگر مجددا به VS Code باز گردیم و ctrl+shift+B را صادر کنیم (جهت اجرای مجدد task runner و اجرای tsc تنظیم شده) ، پیام ذیل مشاهده می‌شود:
 15:33:52 - Compilation complete. Watching for file changes.
به این معنا که اینبار پارامتر watch را شناسایی کرده‌است و دیگر از کامپایلر قدیمی tsc استفاده نمی‌کند. برای آزمایش آن، از منوی view گزینه‌ی split editor را انتخاب کنید و سپس در سمت چپ فایل test.ts و در سمت راست، فایل test.js کامپایل شده را باز کنید:


در اینجا چون پارامتر watch فعال شده‌است، هر تغییری که در فایل ts داده شود، بلافاصله کامپایل شده و در فایل js منعکس خواهد شد.


تنظیم VS Code جهت دیباگ کدهای TypeScript

در نوار ابزار کنار صفحه‌ی VS Code، بر روی دکمه‌ی دیباگ کلیک کنید:


سپس بر روی دکمه‌ی چرخ‌دنده‌ی موجود که کار انجام تنظیمات را توسط آن می‌توان ادامه داد، کلیک کنید. بلافاصله منویی ظاهر می‌شود که درخواست انتخاب محیط دیباگ را دارد:


در اینجا node.js را انتخاب کنید. با اینکار فایل جدیدی دیگری به نام launch.json به پوشه‌ی vscode. اضافه می‌شود. اگر به این فایل دقت کنید دو خاصیت name به نام‌های Launch و Attach در آن موجود هستند. این نام‌ها در یک دراپ داون، در کنار دکمه‌ی start دیباگ نیز ظاهر می‌شوند:


- در فایل launch.json، باید خاصیت "program": "${workspaceRoot}/app.js" را ویرایش کرد و app.js آن‌را به test.ts مثال جاری تغییر داد.
- سپس خاصیت "sourceMaps" آن نیز باید تغییر کرده و جهت استفاده‌ی از source mapهای تولیدی به true تنظیم شود.
- در آخر باید مسیر پوشه‌ی خروجی js را نیز تنظیم کرد: "outDir": "${workspaceRoot}/js"
همچنین باید دقت داشت چون externalConsole به false تنظیم شده‌است، خروجی این کنسول به output ویژوال استودیوکد منتقل می‌شود.

اکنون اگر بر روی دکمه‌ی سبز رنگ start کلیک کنید (دکمه‌ی F5)، امکان دیباگ سطر به سطر کد TypeScript را خواهید یافت:



فایل‌های نهایی json یاد شده‌ی در متن را از اینجا می‌توانید دریافت کنید:
 VSCodeTypeScript.zip
مطالب
React 16x - قسمت 7 - ترکیب کامپوننت‌ها - بخش 1 - ارسال داده‌ها، مدیریت رخ‌دادها
تا اینجا، تنها با یک تک کامپوننت کار کردیم؛ اما یک برنامه‌ی واقعی ترکیبی است از چندین کامپوننت که در نهایت درخت کامپوننت‌ها را در React تشکیل می‌دهند. به همین جهت در طی چند قسمت، نکات ترکیب کامپوننت‌ها را بررسی می‌کنیم.


ترکیب کامپوننت‌ها

در ادامه، همان برنامه‌ی تا قسمت 5 را که کار نمایش یک counter را انجام می‌دهد، تکمیل می‌کنیم. در این برنامه اگر به فایل index.js دقت کنید، کار رندر تک کامپوننت Counter را انجام می‌دهیم:
ReactDOM.render(<Counter />, document.getElementById("root"));
اما یک برنامه‌ی واقعی React، متشکل از درختی از کامپوننت‌ها است. به این ترتیب با ترکیب و در کنار هم قرار دادن کامپوننت‌های مختلف، می‌توان به UI ای کارآمد و پیچیده رسید.
برای نمایش این مفهوم، کامپوننت جدید src\components\counters.jsx را ایجاد می‌کنیم. قصد داریم در این کامپوننت، لیستی از کامپوننت‌های Counter را رندر کنیم. سپس در index.js، بجای رندر کامپوننت Counter، کامپوننت جدید Counters را رندر می‌کنیم. به این ترتیب درخت کامپوننت‌های برنامه، در سطح بالایی خودش از کامپوننت Counters شروع می‌شود و سپس فرزندان آن‌را کامپوننت‌های Counter تشکیل می‌دهند. به همین جهت فایل index.js را به صورت زیر ویرایش می‌کنیم تا به کامپوننت Counters اشاره کند:
import Counters from "./components/counters";

ReactDOM.render(<Counters />, document.getElementById("root"));
سپس به فایل جدید src\components\counters.jsx مراجعه کرده و با استفاده از قطعه کدهای کمکی imrc و cc که در قسمت‌های قبل با آن‌ها آشنا شدیم، ساختار بدنه‌ی کامپوننت جدید Counters را ایجاد می‌کنیم. اکنون در متد render آن، یک div را ایجاد کرده و داخل آن، چندین کامپوننت Counter را رندر می‌کنیم:
import React, { Component } from "react";

import Counter from "./counter";

class Counters extends Component {
  state = {};

  render() {
    return (
      <div>
        <Counter />
        <Counter />
        <Counter />
        <Counter />
      </div>
    );
  }
}

export default Counters;
در این حالت اگر به مرورگر مراجعه کنیم، مشاهده خواهیم کرد که هر کامپوننت، state خاص خودش را دارد و از سایر کامپوننت‌ها ایزوله است:


در مرحله‌ی بعد، بجای رندر و درج دستی این کامپوننت‌ها، آرایه‌ای از اشیاء counter را ایجاد کرده و سپس آن‌ها را توسط متد Array.map رندر می‌کنیم:
import React, { Component } from "react";
import Counter from "./counter";

class Counters extends Component {
  state = {
    counters: [
      { id: 1, value: 0 },
      { id: 2, value: 0 },
      { id: 3, value: 0 },
      { id: 4, value: 0 }
    ]
  };

  render() {
    return (
      <div>
        {this.state.counters.map(counter => (
          <Counter key={counter.id} />
        ))}
      </div>
    );
  }
}

export default Counters;
در اینجا یک خاصیت جدید را به شیء منتسب به خاصیت state به نام counters اضافه کرده‌ایم. این خاصیت حاوی آرایه‌ای از اشیاء counter است که هر کدام دارای یک id (که در قسمت key ذکر خواهد شد) و مقداری اولیه است. سپس آرایه‌ی this.state.counters را توسط متد map، رندر کرده‌ایم. تا اینجا پس از ذخیره‌ی فایل و بارگذاری مجدد برنامه، همان خروجی قبلی را مشاهده خواهیم کرد.


ارسال داده‌ها به کامپوننت‌ها

مشکل! مقدار value هر شیء شمارشگر تعریف شده، به کامپوننت‌های مرتبط رندر شده اعمال نشده‌است. برای مثال اگر value اولین شیء را به 4 تغییر دهیم، هنوز هم این کامپوننت با همان مقدار صفر شروع به کار می‌کند. برای رفع این مشکل، به همان روشی که ویژگی key کامپوننت Counter را مقدار دهی کردیم، می‌توان ویژگی‌های سفارشی دیگری را تعریف و مقدار دهی کرد:
  render() {
    return (
      <div>
        {this.state.counters.map(counter => (
          <Counter key={counter.id} value={counter.value} selected={true} />
        ))}
      </div>
    );
پس از تعریف ویژگی‌های دلخواه value و selected که یکی از آن‌ها به مقدار value شیء counter مرتبط متصل است، به خود کامپوننت Counter مراجعه کرده و سپس در ابتدای متد render آن، خاصیت props به ارث رسیده شده‌ی از کلاس پایه‌ی Component را جهت بررسی بیشتر لاگ می‌کنیم:
class Counter extends Component {
  state = {
    count: 0
  };

  render() {
    console.log("props", this.props);
    //...
پس از ذخیره‌ی فایل counter.jsx و بارگذاری مجدد برنامه، یک چنین خروجی در کنسول توسعه دهندگان مرورگر قابل مشاهده است:


خاصیت this.props، یک شیء ساده‌ی جاوا اسکریپتی است و شامل تمام ویژگی‌هایی می‌باشد که ما در کامپوننت Counters برای هر کدام از کامپوننت‌های Counter رندر شده‌ی توسط آن، تعریف کردیم. برای نمونه دو ویژگی جدید value و selected را که به تعاریف المان‌های Counter در کامپوننت Counters اضافه کردیم، در اینجا به همراه مقادیر منتسب به آن‌ها، قابل مشاهده هستند. البته در این خروجی، key را ملاحظه نمی‌کنید؛ چون هدف اصلی آن، معرفی یکتای المان‌ها در DOM مجازی React است.
بنابراین اکنون می‌توان به value تنظیم شده‌ی در کامپوننت Counters به صورت this.props.value در کامپوننت Counter دسترسی یافت و سپس از آن جهت مقدار دهی اولیه‌ی counter استفاده کرد.
class Counter extends Component {
  state = {
    count: this.props.value
  };
اکنون اگر تغییرات کامپوننت Counter را ذخیره کرده و به مرورگر مراجعه کنیم، در اولین بار نمایش برنامه و بدون اعمال هیچگونه تغییری، یک چنین خروجی حاصل می‌شود:


یک نکته: در اینجا selected={true} را داریم. اگر مقدار آن‌را حذف کنیم، یعنی selected تنها درج شود، مقدار آن، همان true دریافت خواهد شد.


تعریف فرزند برای المان‌های کامپوننت‌ها

ویژگی‌های اضافه شده‌ی به تعاریف المان‌های کامپوننت‌ها، توسط خاصیت this.props، به هر کدام از آن کامپوننت‌ها منتقل می‌شوند. این خاصیت props، یک خاصیت ویژه را به نام children، نیز دارا است و از آن برای دسترسی به المان‌های تعریف شده‌ی بین تگ‌های یک المان اصلی استفاده می‌شود:
  render() {
    return (
      <div>
        {this.state.counters.map(counter => (
          <Counter key={counter.id} value={counter.value} selected={true}>
            <h4>‍Counter #{counter.id}</h4>
          </Counter>
        ))}
      </div>
    );
  }
در اینجا بین تگ‌های ابتدا و انتهای تعریف المان Counter، یک محتوا نیز تعریف شده‌است. اکنون اگر به خروجی کنسول توسعه دهندگان مرورگر دقت کنیم، خاصیت جدید اضافه شده‌ی children را نیز می‌توان مشاهده کرد:


یک نمونه مثال واقعی این قابلیت، امکان تعریف محتوای دیالوگ باکس‌ها، توسط استفاده کنند‌ه‌ی از آن است.


روش دیباگ برنامه‌های React

افزونه‌ی مفید React developer tools را می‌توانید برای مرورگرهای کروم و فایرفاکس، دریافت و نصب کنید. برای نمونه پس از نصب آن در مرورگر کروم، یک برگه‌ی جدید به لیست برگه‌های کنسول توسعه دهندگان آن اضافه می‌شود:


همانطور که مشاهده کنید، درخت کامپوننت‌های برنامه را در برگه‌ی جدید Components، می‌توان مشاهده کرد. در اینجا با انتخاب هر کدام از فرزندان این درخت، مشخصات آن نیز مانند props و state، در کنار صفحه ظاهر می‌شوند. همچنین در بالای همین قسمت، 4 آیکن مشاهده‌ی سورس، مشاهده‌ی DOM و یا لاگ کردن جزئیات شیء کامپوننت انتخابی در کنسول هم درج شده‌اند:


که برای نمونه چنین خروجی را لاگ می‌کند:



بررسی تفاوت‌های خواص props و state

در کامپوننت Counter، از props برای مقدار دهی اولیه‌ی state استفاده می‌کنیم:
class Counter extends Component {
  state = {
    count: this.props.value
  };
اکنون این سؤال مطرح می‌شود که چه تفاوتی بین props و state وجود دارد؟
- props حاوی اطلاعاتی است که به یک کامپوننت ارسال می‌کنیم؛ اما state حاوی اطلاعاتی است که مختص به آن کامپوننت بوده و private است. یعنی سایر کامپوننت‌ها نمی‌توانند به state کامپوننت دیگری دسترسی پیدا کنند. برای مثال در کامپوننت Counters، تمام attributes سفارشی تنظیم شده‌ی بر روی تعاریف المان‌های کامپوننت Counter، جزئی از اطلاعات props خواهند بود. در اینجا نمی‌توان به state کامپوننت مدنظری دسترسی یافت و آن‌را مقدار دهی کرد. به همین ترتیب state کامپوننت Counters نیز در سایر کامپوننت‌ها قابل دسترسی نیست.
- همچنین باید درنظر داشت که props، در مقایسه با state، فقط خواندنی است. به عبارتی مقدار ورودی به یک کامپوننت را داخل آن کامپوننت نمی‌توان تغییر داد. برای مثال سعی کنید در داخل متد رویدادگردان کلیک موجود در کامپوننت Counter، مقدار this.props.value را به صفر تنظیم کنید. در این حالت با کلیک بر روی دکمه‌ی Increment، بلافاصله خطای readonly بودن خواص شیء منتسب به props را دریافت می‌کنیم. در اینجا اگر نیاز است این مقدار را داخل کامپوننت تغییر دهیم، باید ابتدا این مقدار را دریافت کرده و سپس آن‌را داخل state قرار دهیم. پس از آن امکان ویرایش اطلاعات منتسب به state، داخل یک کامپوننت وجود خواهد داشت.


صدور و مدیریت رخ‌دادها

در ادامه می‌خواهیم در کنار هر دکمه‌ی Increment کامپوننت شمارشگر، یک دکمه‌ی Delete هم قرار دهیم:


مشکل! اگر کد مدیریتی handleDelete را در کامپوننت Counter قرار دهیم، چگونه باید به لیست آرایه‌ی اشیاء counters والد آن، یعنی کامپوننت Counters که سبب رندر شدن کامپوننت‌های شمارشگر شده (state = { counters: [ ] })، دسترسی یافت و شیء‌ای را از آن حذف کرد؟ در React، کامپوننتی که state ای را تعریف می‌کند، باید کامپوننتی باشد که قرار است آن‌را تغییر دهد و اطلاعات state هر کامپوننت، صرفا متعلق به آن کامپوننت بوده و جزو اطلاعات خصوصی آن است. بنابراین مدیریت حذف و یا افزودن کامپوننت‌ها در لیست نمایش داده شده، باید جزو وظایف کامپوننت Counters باشد و نه Counter.
برای حل این مشکل، کامپوننت Counter تعریف شده (کامپوننت فرزند) باید سبب بروز رخ‌داد onDelete شود تا کامپوننت Counters (کامپوننت والد)، آن‌را توسط متد handleDelete مدیریت کند. بنابراین ابتدا به کامپوننت Counters (کامپوننت والد) مراجعه کرده و متد رویدادگردان handleDelete را به آن اضافه می‌کنیم:
  handleDelete = () => {
    console.log("handleDelete called.");
  };
سپس ارجاعی از این متد را به صورت خاصیتی از props به کامپوننت Counter (کامپوننت فرزند) ارسال خواهیم کرد؛ برای این منظور در کامپوننت Counters (کامپوننت والد)، ویژگی onDelete را به تعریف المان Counter اضافه کرده و آن‌را با ارجاعی به متدhandleDelete  مقدار دهی می‌کنیم:
<Counter
     key={counter.id}
     value={counter.value}
     selected={true}
     onDelete={this.handleDelete}
/>
پس از آن به کامپوننت Counter مراجعه کرده و دکمه‌ی جدید Delete را به صورت زیر در کنار دکمه‌ی Increment تعریف می‌کنیم:
<button
  onClick={this.props.onDelete}
  className="btn btn-danger btn-sm m-2"
>
  Delete
</button>
در اینجا onClick، به خاصیت onDelete شیء props ارسالی به کامپوننت متصل شده‌است.
اکنون اگر برنامه را ذخیره کرده و پس از بارگذاری مجدد برنامه در مرورگر بر روی دکمه‌ی Delete کلیک کنیم، پیام «handleDelete called» در کنسول توسعه دهندگان مرورگر لاگ می‌شود. به این ترتیب کامپوننت فرزند سبب بروز رخ‌دادی شده و والد آن، این رخ‌داد را مدیریت می‌کند.


به روز رسانی state

تا اینجا دکمه‌ی Delete فرزند، به متد handleDelete والد متصل شده‌است. مرحله‌ی بعد، پیاده سازی واقعی حذف یک المان از DOM مجازی و به روز رسانی state است. برای اینکار ابتدا به رخ‌دادگردان onClick، در کامپوننت شمارشگر، مراجعه کرده و id دریافتی را به سمت والد ارسال می‌کنیم:
onClick={() => this.props.onDelete(this.props.id)}
البته در سمت والد نیز باید این id را به صورت یک خاصیت جدید به props اضافه کنیم (تا this.props.id فوق کار کند)؛ چون ویژگی key، مختص DOM مجازی بوده و به props اضافه نمی‌شود:
<Counter
  key={counter.id}
  value={counter.value}
  selected={true}
  onDelete={this.handleDelete}
  id={counter.id}
/>
اکنون این id را در کامپوننت والد دریافت و به آن واکنش نشان می‌دهیم:
  handleDelete = counterId => {
    console.log("handleDelete called.", counterId);
    const counters = this.state.counters.filter(
      counter => counter.id !== counterId
    );
    this.setState({ counters }); // = this.setState({ counters: counters });
  };
همانطور که پیشتر نیز در این سری عنوان شده، در React، مقدار state را به صورت مستقیم تغییر نمی‌دهیم و اینکار باید از طریق متد setState آن صورت گیرد. به عبارت دیگر مستقیما خاصیت counters شیء منتسب به خاصیت state را تغییر نمی‌دهیم. ابتدا یک آرایه‌ی جدید از المان‌ها را تولید کرده و به متد setState ارسال می‌کنیم. سپس React، هم خاصیت counters و هم UI را بر این اساس به روز رسانی خواهد کرد. در اینجا، لیست جدید counters، بر اساس id دریافتی از کامپوننت فرزند، تولید شده و به متد this.setState ارسال می‌شود. در این حالت اگر برنامه را ذخیره کرده و پس از بارگذاری مجدد آن در مرورگر، بر روی دکمه‌ی Delete هر ردیف کلیک کنیم، آن ردیف از UI حذف خواهد شد.

البته پیاده سازی ما تا به اینجا بدون مشکل کار می‌کند، اما به ازای هر خاصیت counter، یک ویژگی جدید را به تعریف المان مرتبط اضافه کرده‌ایم که در طول زمان بیش از اندازه طولانی خواهد شد. برای رفع این مشکل، خود شیء counter را به صورت یک ویژگی جدید به کامپوننت مرتبط با آن ارسال می‌کنیم. به این ترتیب اگر در آینده خاصیتی را به این شیء اضافه کردیم، دیگر نیازی نیست تا آن‌را به صورت دستی و مجزا تعریف کنیم. به همین جهت ابتدا تعریف المان Counter را به صورت زیر خلاصه می‌کنیم که در آن ویژگی جدید counter، حاوی کل شیء counter است:
<Counter
  key={counter.id}
  counter={counter}
  onDelete={this.handleDelete}
/>
سپس در سمت کامپوننت فرزند شمارشگر، دو تغییر this.props.counter.value و this.props.counter.id باید صورت گیرند تا مقادیر شیء counter به درستی خوانده شوند.


کدهای کامل این قسمت را از اینجا می‌توانید دریافت کنید: sample-07.zip