2010/07/31

‫کمی درباره‌ی Mock و Stub

هم Mock و هم Stub در unit testهایی استفاده می‌شوند که شخص نمی‌تواند یا نمی‌خواهد از بعضی objectهای مورد نیاز استفاده نماید. مثلاً قرار است متود ارسال ایمیل به امور فروش در صورت کاهش موجودی برخی کالاها تست شود. فرض کنید موقع تست امکان ارسال ایمیل به علت قطعی اینترنت وجود ندارد. در این حالت آبجکت مربوط به ارسال ایمیل به نوعی شبیه‌سازی می‌شود. این کار باعث می‌شود تست مورد نظر روی خود عملیات کاهش موجودی و ارسال ایمیل تمرکز کند و کاری به مشکلات مربوط به ارسال ایمیل نداشته باشد. به غیر از ارسال ایمیل حالات دیگری هم وجود دارند که در آن استفاده از object مورد نظر امکان‌پذیر نیست. مثلاً خواندن اطلاعات از یک device وقتی که خود device را نداریم، محاسبه حقوق بر اساس اطلاعات کارمندان یک شرکت وقتی که اطلاعات هیچ کدام از کارمندان را نداریم و بسیاری حالات دیگر. خود شبیه‌سازی هم صرفاً محدود به Mock و Stub نمی‌شود. مثلاً می‌توان از الگوهایی مثل Object Mother هم استفاده کرد.

Mock با استفاده از برنامه‌های کمکی که به اسم Isolation Framework یا Mocking Framework معروف هستند انجام می‌شود. Rhino Mocks معروف‌ترین و پراستفاده‌ترین Mock Framework در دات‌نت است. در روش Mock ما آن آبجکتی را که قرار است شبیه‌سازی شود را معرفی می‌کنیم و سپس انتظاراتمان را از آن بیان می‌کنیم. مثلاً فرض کنید آبجکتی به اسم FaxReceiver دارید که یکی از متودهایش وظیفه دارد به شما بگوید از تاریخ آخرین عوض کردن کاغذ دستگاه فاکس، چند عدد فاکس دریافت کرده است. متود مورد تست شما از این آبجکت استفاده می‌کند و هر وقت که تعداد فاکس‌های دریافتی بیش از هزار عدد شد به اپراتور دستگاه پیغام دهد که موقع عوض کردن کاغذ دستگاه فرا رسیده است. با روش‌های معمولی تست نمی‌توان این متود را تست کرد مگر این که هزار عدد فاکس دریافت کنید. در اینجاست که از روش‌های شبیه‌سازی مثل Mock استفاده می‌شود. برای این کار آبجکت FaxReceiver به Mock Framework معرفی شده و به او می‌گوییم هر وقت متود تعداد فاکس‌های دریافتی فراخوانی شد از او «انتظار» داریم مقدار هزار را برگرداند.

مثال بالا را می‌توان با Stub هم انجام داد. با این تفاوت که در مورد Stub هیچ Framework یا Library وجود ندارد و شما مجبور هستید همه یا بخشی از آبجکت/متود مورد نظر را خودتان بنویسید. مثلا متودی بنویسید که به جای مراجعه واقعی به دستگاه فاکس و خواندن تعداد فاکس‌های دریافتی از آن، همیشه عدد هزار را برگرداند. با این که کار با Stub خیلی سخت‌تر از کار با Mock است ولی بعضی حالات وجود دارند که فقط با Stub می‌شود آنها را پیاده‌سازی کرد. مثلاً وقتی که نگهداشتن State برای ما مهم باشد. به عنوان مثال فرض کنید در تست دیگری بخواهیم بدانیم چند بار متود فراخوانی تعداد فاکس‌های دریافتی فراخوانی شده است. انجام این کار با Mocking امکان‌پذیر نیست و باید از روش Stub استفاده شود.

منابع:
Mocks Aren't Stubs
Mock object
آشنايي با mocking frameworks (چارچوب‌هاي تقليد) - قسمت اول
آشنايي با mocking frameworks - قسمت دوم




2010/07/24

‫سوء تفاهم با WF

WF یا همان Window Workflow Foundation فناوری جدیدی است که مایکروسافت از نسخه 3.0 به دات‌نت اضافه کرده و در نسخه 4.0 حسابی به آن رسیده است. ظاهراً این فناوری برای مایکروسافت خیلی با ارزش است چون سعی دارد این فناوری را مدام توسعه داده و از آن در جاهای مختلف استفاده کند. مثلاً مایکروسافت در TFS 2010 در کنار MSBuild از یک لایه اضافی برای راحت‌تر کردن و توسعه امکانات Team Build استفاده کرده که در این لایه از WF 4.0 استفاده شده.

از اولین باری که اسم Windows Workflow را شنیدم فکر می‌کردم قرار است از این تکنولوژی برای راحت‌تر کردن پیاده‌سازی Workflowهای معمول سازمان‌ها استفاده شود. حتی در شرکت قبلی این نقشه را داشتم که از WF برای پیاده‌سازی Workflow در شرکت مشتری استفاده کنم. اما زهی خیال باطل. چون به تازگی به خاطر نیازی که در Team Build 2010 به Workflow پیدا کردم متوجه شدم WF برای آن کار مناسب نبوده است. برای درک بهتر موضوع می‌توان Workflowها را به دو نوع اداری و برنامه‌ای تقسیم کرد:

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

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

Windows Workflow Foundation یا WF برای پشتیبانی از Workflow برنامه‌ای ایجاد شده است. WF کمک می‌کند که هر کدام از تکه‌های خیلی بزرگ نرم‌افزار به یک Activity تبدیل شود. این تکه‌ها بعداً در قالب یک Workflow با هم ارتباط پیدا می‌کنند. نهایتاً این Workflow در جایی host شده و توسط WF Runtime شروع به اجرا می‌کند. WF مدعیست به برنامه‌نویسان امکان می‌دهد تا بخش‌ها مختلف Workflow به طور موازی و در کامپیوترهای مختلف به اجرا درآورند. در واقع شعار WF نوشتن برنامه‌های بزرگی است که به راحتی برنامه‌های کوچک قابل توسعه و نگهداری هستند.

اما چرا نمی‌توان یک Workflow اداری را با کمک WF پیاده سازی کرد؟ چون به نظز من یک Workflow اداری اولاً تشکیل شده از قطعاتی از اطلاعات نه قطعاتی از نرم‌افزار، ثانیاً نباید از کاربر اداری توقع داشت برای تعریف Workflow از ویژوال استودیو و XAML استفاده کند، ثالثاً استفاده از WF نیاز به Build مجدد نرم‌افزار دارد که این امکان در محیط کاربر اداری فراهم نیست، رابعاً WF ابزار بیش از حد بزرگی برای انجام این کار است. انجام این کار با WF مثل این است که برای بلند کردن یک دوچرخه معمولی از یک جرثقیل چند ده تنی استفاده شود.




2010/07/23

نیازهای نیروی انسانی

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

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

بازی را از خودم شروع می‌کنم:

نیازهای من به عنوان یک نیروی انسانی برنامه‌نویس:

۱ - کارفرما همیشه این سوال را از خودش بپرسد که چرا من به جای یک مجموعه دولتی با شرایط خیلی بهتر، یک محیط کار خصوصی را انتخاب کرده‌ام.
۲ - داشتن اطلاعات کافی راجع به برنامه‌های جاری و آتی شرکت، محصولات شرکت و…
۳ - استفاده از فناوری‌ها روز، روش‌های جدید و اصول کاری درست و توجه به نیاز دائمی به آموزش و یادگیری .
۴ - عدم اضافه کار اجباری: من هم روابط اجتماعی دارم و کارهای دیگری دارم که باید به آنها برسم.
۵ - تمدید به موقع قرارداد و داشتن اطلاعات کافی و به موقع نسبت به نیازمندی یا عدم نیاز شرکت به من در دوره‌های بعدی.


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




Versioning assemblies with Team Build 2010

It was a while that I was searching a way increasing version number of a .Net assembly by each build. In the beginning there were very ambiguity for myself that I tried to solve one by one:

1. When to increase assemblies version? Each time that developer builds the project on his (her) machine? Or each time that a build occurs in Team Build? Very soon I realized that is better to use Team Build because version number in each development machine may increase separately. Additionally Team Build maintains a database of all previous build for future uses.

2. By using Team Build based solutions I was unable to use patterns such as "1.0.*" for AssemblyVersion. I was forced to modify/generate AssemblyInfo.cs or some files like VersionInfo.cs. The question was if Team Build or something like MSBuild would change AssemblyInfo.cs, how can I see version information? There are two ways: get latest version, check-out AssemblyInfo.cs/VersionInfo.cs, modify, check-in and cause build based on them or get latest version, modify AssemblyInfo.cs/VersionInfo.cs without check-out/check-in, cause build based on them. Jimb Lamb says it's a best practice to not check-in/check-out any changes during a build. I chose Jim's approach.

3. Should I use MSBuild or Team Build? Use MSBuild's tasks or Team Build's process templates and activities? The answer was dependent on how I want generate build numbers. As I wanted to use Team Build's build number in versioning and I wanted to access the history of a each assembly version, I chose Team Build because MSBuild's tasks are not able to save history of builds in a database.

4. How can I use Team Build 2010 to do the versioning for me? By using TfsSdk: ActivityPack. There is an activity named "UpdateVersionInfo" in the pack. You should put in the bottom of "Overall Build Process\Run On Agent\Initialize Workspace" activity just after "Get Workspace" activity. Don't forget to add arguments FileSpec, RegularExpression and VersionInfo with proper default values. Use "$(BuildDefinitionName)_$(Year:yyyy).$(Month).$(DayOfMonth)$(Rev:.r)" as build definition's Build Number Format as "UpdateVersionInfo" needs those extra periods. For more info refer to Jim Lamb's blog post describing it thoroughly.

Also see this blog posts and StackOverflow's questions: link, link, link, link, link, link, link.




2010/07/15

استفاده از مفاهیم جدید تولید نرم‌افزار

روند طراحی و توسعه نرم‌افزار طی ده سال گذشته حتی در همین ایران خودمان هم تغییرات زیادی داشته. آن زمان یعنی حدود سال ۷۹ شمسی مردم تازه از شر FoxPro خلاص شده و به دیتابیس‌های مدرن‌تری مثل Access، MS SQL Server و Oracle رو آورده بودند. برنامه‌نویسی در عصر ویندوز راحت‌تر و منظم‌تر شده بود. تا قبل از آن عموماً کسی لذت Foreign Key و Delete/Update Cascade را کشف نکرده بود. طی این ده سال استفاده از Database Driver و ADO رواج زیادی پیدا کرد. در این دوره آنها که منظم‌تر بودند از نمودارهای ERD برای بیان ساختار دیتابیس، نرمال‌سازی، کلاس‌های مجزا برای دسترسی به دیتابیس (معماری سه لایه) و… استفاده می‌کردند.

اما اکنون آن دوران به سر آمده و ما خیلی وقت است که وارده دوران Domain Driven Design یا همان DDD شده‌ایم. در عصر DDD هیچکس مستقیماً به دیتابیس وصل نمی‌شود بلکه از ORM‌ استفاده می‌کند. روابط بین entityها به جای ERD با UML Class Diagram تعریف می‌شود و معماری‌های چندلایه‌ای با استفاده از DDD خیلی راحت‌تر شده و…

حال سوال این است که آیا لازم است ما هم صرفاً به خاطر همراهی با زمان یه سمت Domain Driven Design و Object Oriented برویم یا این که واقعاً نفعی برای ما و شرکت‌مان در آن وجود دارد؟ جواب این سوال هر دو است. چون اولاً وقتی که همه دنیا به این سبک جدید رو آورده‌اند خیلی سخت است که ما همان روش‌ها و ابزارهای قدیمی را نگه داریم و خلاف جریان آب شنا کنیم. ثانیاً عصر جدید امکانات بسیار خوبی را با خود به همراه آورده است و نباید آن را به این سادگی از دست بدهیم.

عصر جدید یعنی دنیای Domain Driven Design و Object Oriented که با استفاده از ORMها و UML محقق می‌شود به شما کمک می‌کند که:
‫۱- کد شما قابلیت نگهداری بالایی داشته باشد.
‫۲- پیدا کردن و برطرف کردن باگ‌ها راحت‌تر باشد.
‫۳- اگر طراحی درست انجام شده باشد، برنامه‌نویسی راحت‌تر خواهد بود.
‫۴- مزایای معرفی شده در Object Oriented به طور ملموسی در دسترس قرار خواهد گرفت. مفاهیمی مثل Inheritance باعث می‌شود حجم کد کاهش یابد.
‫۵- کدهای DDD خیلی منظم‌تر از کدهای تولید شده در دوران قبل هستند.
‫۶- تولید نرم‌افزارهای DDD هم‌خوانی بسیار بیشتری با متودولوژی‌های جدید اسکرام، XP و… دارد.
‫۷- …


در بین شرکت‌ها و تیم‌های نرم‌افزاری ایرانی تعداد قابل توجهی به روش‌های عصر جدید رو آورده‌اند. یعنی از ORM استفاده می‌کنند، کل کار را به صورت Object Oriented جلو می‌برند، Documentation آنها بر اساس UML است و … اما متاسفانه هنوز خیلی‌ها هستند که خود را از لذت و کارایی عصر جدید محروم کرده‌اند. به نظر من تنها عاملی که باعث می‌شود این طور افراد همچنان به استفاده از روش‌های قدیمی ادامه دهند عدم آگاهی نسبت به روش‌های جدید است. چون هیچ مدیر پروژه یا رییس شرکتی دوست ندارد کاری را که می‌شود در شش ماه انجام داد در هشت ماه انجام دهد و نهایتاً هم کدی را تحویل بگیرد که نگهداری و توسعه آن خیلی هم سخت باشد. به همین خاطر به این طور افراد توصیه می‌گردد اگر هم از روش‌های قدیمی خیلی هم راضی هستند اقلاً مطالعه‌ای در مورد روش‌های جدید و مزایای آن داشته باشند.




2010/07/11

‫ALM چیست؟

ALM یا Application Lofecycle Management به طور اختصار یعنی مدیریت فرایند تولید نرم‌افزار با استفاده از ابزارهای کار تیمی مثل Source Control، Issue Tracking، Build Automation و… در واقع با کمک ALM کلیه امور مربوط به توسعه نرم‌افزار در یک تیم تولید نرم‌افزار به طور یکپارچه مدیریت و هدایت می‌شود. در اینجا منظور از امور تیم مواردی مثل زیر است:

۱- Source Control Management
‫۲- Issue/Bug/Feature Management
‫۳- Build Automation
‫۴- Architecure/Design (UML)‎
‫۵- Test: Unit Test - Acceptance Test - Load Test - ...
‫۶- Release Management
‫۷- Deploy Management
‫۸- Project Management
‫۹- …


عکس زیر روابط این اجزا را به خوبی نمایش می‌دهد:



هر تیمی که همه این امور را داشته باشد و بتواند آنها را با کمک ابزارهای مناسبی مدیریت کند یعنی ALM دارد. ابزارهای ALM می‌توانند کاملاً یکپارچه باشند. مثلاً Visual Studio Team System که ابزار ALM مایکروسافت است، شامل عمده ابزارهای مورد نیاز مثل Source Control، Work Item Management، Buid Automation، Test و… است. ابزارهای ALM می‌توانند از جاهای مختلفی آمده ولی باز هم یکپارچه باشند. مثل وقتی که از ابزارهای SVN برای Source Control، از NAnt برای Build، از Jira برای Issue Tracking و… استفاده شود.

ALM اصطلاحی است که این روزها بیشتر از روزهای قبل مورد استفاده قرار می‌گیرد. مثلاً مایکروسافت که در نسخه‌های ۲۰۰۵ و ۲۰۰۸ ویژوال استودیو از اصطلاح Team System استفاده می‌کرد، تصمیم گرفته در نسخه ۲۰۱۰ ویژوال استودیو به جای Team System از همین واژه Application Lifecycle Management استفاده نماید.


منابع:
ویکی‌پدیا
کتاب ALM with VS 2010




2010/07/05

How to restart an ASP.NET web application

One of the problems that I encounter so often is need to refresh an ASP.NET website. Many times we make some changes in website's data and need the website act on these new data. But unfortunately this does not take effect, because ASP.NET worker process is not going to read data from beginning.

One of examples that I recently encountered was a custom Sitemap provider. This provider read data from database and builds Sitemap based on it. But because of avoiding dead lock and avoiding building Sitemap with each request, the provider uses a `lock` and checks if the Sitemap tree has been built before, and if yes it just returns a cached version of it. So even data is changed, Sitemap will not informed about changes until an `IISREST`. IISRESET is not a good idea because you have not access to it in remote hosts. And IISRESET is a very expensive operations. It shut downs all websites.

Best way to force refreshing an ASP.NET website is to restart it internally. Peter Bromberg in an article describes some ways for restarting an ASP.NET website. Here is one of those ways that I used in my application happily:

public static void RestartWebSite()
{
    System.Web.HttpRuntime.UnloadAppDomain();
    
    //Loading a page after unloading is necessary
    //due to start the application again.
    HttpContext.Current.Response.Redirect("~/Default.aspx");
}