2010/05/11

گاو و مرغ

صبح یک روز بهاری یک مرغ و یک گاو در مزرعه‌ای در کنار هم راه می‌رفتند. مرغ به گاو گفت بیا با هم یک رستوران راه بیندازیم. گاو گفت باشه ولی اسمشو چی بذاریم؟ مرغ گفت اسمشو بزاریم رستوران «کباب و نیمرو». گاو گفت: نه من موافق نیستم. چون من باید از جونم بگذارم تا کباب درست بشه ولی تو فقط ی تخم می‌زاری و همین.

بی‌مزه بود نه؟ این داستان در واقع برگردان یک جوک کلاسیک انگلیسی است به اسم The Chicken and the Pig. این جوک مبنای دسته‌بندی نقش افراد تیم در روش Scrum است. نقش‌های مهم، یعنی نقش‌هایی که مستقیماً در تولید محصول دخالت دارند مثل ScrumMaster جز نقش‌های «گاو» یا همان Pig محسوب می‌شوند و نقش‌هایی مثل «سهام داران» که نقش مستقیم کمتری در تولید محصول دارند جز نقش‌های «مرغ» یا همان Chicken محسوب می‌شوند.




2010/05/06

‫Agile و استفاده از آن

اگر بخواهیم Agile را خیلی ساده و بدون استفاده از لغات دقیق و فنی و مرزبندی‌های مربوطه تعریف کنیم، آن وقت Agile یعنی یک نوع روش تولید نرم‌افزار که در آن عمده توجه به انعطاف‌پذیری تیم تولید در پذیرش تغییرات مداوم نیازمندی‌های اولیه نرم‌افزار است. این انعطاف‌پذیری در اثر iterative و incremental بودن این روش به وجود آمده است.

Agile در مجموعه مفاهیم مهندسی نرم‌افزار، هم‌خانواده مفاهیمی مثل RUP و SSADM است با این توضیح که این سال‌ها هم‌زمان با پیشرفت بحث‌های شی‌گرایی، Agile هم حسابی رواج پیدا کرده و در خیلی از پروژه‌ها جای RUP را گرفته است. Agile در مقایسه با متودولوژی‌هایی مثل RUP که predictive هستند، با اصطلاح adaptive توصیف می‌شود. adaptive یعنی این که روش مورد نظر می‌تواند خودش را به راحتی با تغییرات نیازمندی‌های تطبیق دهد. درست به همین دلیل هم است که نمی‌توان روند پیشرفت پروژه‌های Agile را با دقت پیش‌بینی کرد. از سویی دیگر روش‌هایی مثل RUP انطباق‌پذیری کمتری دارند ولی در مقابل چون تغییرات کمی دارند به خوبی predictive (قابل پیش‌بینی) هستند. Agile فقط شامل Scrum و XP نمی‌شود بلکه هر روشی را که با مانیفست Agile مطابقت داشته باشد را می‌توان Agile نامید، از جمله روش‌هایی که توسط مایکروسافت و بقیه ارائه شده‌اند.

به نظر می‌رسد Agile (با تکیه بر Scrum/XP) با همه راحتی‌هایی که دارد، برای اجرا در شرکت‌های ایرانی دچار مشکلات خاصی هم بشود:
۱- Agile اشتباهاً زیادی لوکس به نظر می‌رسد. مدیران شرکت‌ها دید خیلی خوبی نسبت به تشریفات آن نداشته و فکر می‌کنند یک جور کار غیر ضروری است. مثلاً Standingها (جلسات سرپایی مرور) یکی از آن موارد است.
۲- Agile اشتباهاً بی‌نظم و بی‌برنامه به نظر می‌رسد، چون Agile یک روش Adaptive است و نمی‌توان طرح‌های کاملاً دقیقی از روند پیشرفت کار ارائه داد. این موضوع می‌تواند بهانه خوبی در دست مخالفان Agile باشد. خصوصاً آنها که عاشق Gantt chart هستند. این طور افراد با اعمال گانت چارت و عدم تغییر گانت چارت عملاً Agile را از یک روش iterative و incremental به یک روش آبشاری مثل SSADM تبدیل می‌کنند.
۳- Agile اشتباهاً غیر مستند به نظر می‌رسد. بله درست است که Agile نسبت به روش‌هایی مثل RUP مستندات کمتری تولید می‌کند ولی این به خاطر تمرکز بیشتر بر ارائه خود محصول است نه بی‌اهمیتی آن نسبت به documentation.‏
۴- پایبندی به Agile اشتباهاً سخت به نظر می‌رسد. در Scrum که یکی از رایج‌ترین روش‌های Agile است، همه افراد تیم ملزم به تطبیق خود با بازه زمانی ۲ تا ۴ هفته‌ای به نام sprint هستند. در هر sprint ممکن است اولویت کارها عوض شود و taskهایی که در sprintهای قبلی با جدیت دنبال می‌شد کنار گذاشته شوند. در جلسات مابین sprint احتیاج به حضور و تعامل جدی نماینده کارفرما (product owner) هست. این‌ها باعث می‌شود تا بعضی افراد فکر کنند اجرای Scrum خیلی سخت است. ولی خوشبختانه واقعیت این است که با تعهد به این وظایف محصولی بهتر در زمانی کمتر تولید خواهد شد.


--------------
منبع: مقالات و نوشته‌های مربوط به Agile و Scrum در ویکی‌پدیا و StackOverflow




2010/05/01

‫lazy loading در NHibernate

lazy loading از آن قابلیت‌های جالبی است که همه دوست دارند آن را در برنامه خود داشته باشند. با کمک lazy loading که تقریباً همه ORMها آن را پیاده‌سازی کرده‌اند می‌توان بازیافت اطلاعات از دیتابیس را تا حداکثر زمان ممکن به تعویق انداخت. مثلاً فرض کنید آبجکتی به اسم obj1 دارای یک property به نام obj2 است که obj2 کلاسی است که اطلاعات آن از دیتابیس load می‌شود. در حالت lazy loading وقتی که obj1 از دیتابیس load می‌شود، صرفاً اطلاعات خودش load می‌شود مگر آن که عبارتی به شکل object o1 = obj1.obj2 فراخوانی شود. تازه در این مرحله است که اطلاعات obj2 هم از دیتابیس فراخوانی می‌شود. به این مدل فراخوانی اطلاعات از دیتابیس lazy loading گفته می‌شود چون تا زمانی که واقعاً نیاز به اطلاعات obj2 نباشد، اطلاعات آن از دیتابیس فراخوانی نخواهد شد. lazy یعنی تنبل.

lazy loading در ORMهای مختلف به روش‌های مختلفی انجام می‌شود. مثلاً بعضی‌ها از روش Inheritance استفاده می‌کنند. به این معنی که کلاس Business Entity شما بایستی از یک کلاس مخصوص ارث‌بری کند. این کلاس مخصوص خودش دارای متودهایی برای انجام عملیات lazy loading است. بعضی ORMهای دیگر از روش interface استفاده می‌کنند. در این روش کلاس Business Entity شما باید interface خاصی را implement کند. اما روش NHibernate استفاده از design pattern جالبی به اسم proxy است. در این روش NHiberntae به هنگام شروع به کار و ساختن session، به ازای هر کدام از کلاس‌های Business Entity شما یک کلاس مخصوص می‌سازد و هر جا که برنامه شما نیاز به استفاده از آن کلاس پیدا کرد، NH آن کلاس proxy را تحویلش می‌دهد. این قضیه از دید برنامه مخفی است. یعنی برنامه فکر می‌کند همچنان در حال استفاده از کلاس خودش است. به این ترتیب NH این فرصت را پیدا می‌کند که درخواست‌های دسترسی به propertyهای مختلف یک object را به جای آن که مستقیماً به دیتابیس بفرستد به آن کلاس proxy بفرستد. آن کلاس proxy هم خودش ترتیب lazy loading را می‌دهد. برای آن که یک کلاس proxy بتواند به وظیفه‌اش عمل کند باید کلیه propertyها و methodهای کلاس مبدا به صورت virtual تعریف شده باشد تا proxy factory بتواند همه آنها را در کلاس proxy ارث برده شده، override کند. NH برای تولید proxy از کتابخانه‌های مستقلی مثل Castle Dynamic Proxy استفاده می‌کند.

lazy loading در NH در سه سطح عمل می‌کند: الف- در سطح object. یعنی تا زمانی که واقعاً نیاز به خواندن اطلاعات objectهای دیگری که به صورت property تعریف شده‌اند نباشد، اطلاعات آن از دیتابیس خوانده نخواهد شد. NH فعلا lazy loading در سطح propertyهای غیر آبجکتی را پشتیبانی نمی‌کند.  ۲- در سطح کلی collection: تا زمانی که نیاز به اطلاعات یکی از اعضای آن collection نباشد، اطلات آن از دیتابیس بازیافت نخواهد شد. در این روش همیشه کل collection با هم خوانده می‌شوند. ۳- در سطح اعضای collection: درست مشابه روش قبل است با این تفاوت که lazy loading در سطح تک تک اعضای collection انجام می‌شود. مثلا وقتی که به عنصر چهارم یک collection نیاز هست فقط query همین یک رکورد به دیتابیس ارسال می‌شود نه دیگر اعضای collection. این حالت lazy loading به طور پیش‌فرض به خاطر جلوگیری از کندی سرعت غیر فعال است.

تنها مشکلی که با lazy loading وجود دارد، مشکل آن با session است. در مورد مثال بالا اگر obj1 در حین فعال بودن یک session از دیتابیس فراخوانی شود و آن session بدون فراخوانی obj1.obj2 بسته شود و فراخوانی پس از بسته شدن session انجام شود، خطا رخ می‌دهد چون آن object دیگر detach شده است. غلبه بر این مشکل خیلی سخت نیست. فقط کافی‌ست Close شدن session تا حد امکان به تعویق انداخته شود، مثلا به آخرین خط متود یا try-catch منتقل شود. و اگر این امکان‌پذیر نبود قبل از بسته شدن session، آن property مورد دار به صورت الکی فراخوانی شود تا برنامه یک بار مجبور شود به دیتابیس مراجعه کرده و اطلاعات خود را به روز کند. مشکل sessionها بیشتر در برنامه‌های web مشکل‌ساز هستند چون برنامه‌نویس مجبور است با هر بار Postback برنامه، session را ببندد.