2010/11/30

‫داستان بی‌سوادی ما - ۵: SQL Server Profiler‫

یکی از ابزارهایی که هم برای خطایابی خیلی استفاده می‌شود و هم برای پیدا کردن مشکلات سرعت Queryهای دیتابیسی، ابزار SQL Server Profiler است. من هم از این ابزار خیلی استفاده کرده و می‌کنم. اما مشکل من با این ابزار حجم زیاد log تولیدی آن است. گاهی اوقات برای دیدن یک Query خاص باید چند صد رکورد را بالا و پایین کنم تا به رکورد مورد نظرم برسم. هر چند که این مشکل خیلی آزار دهنده بود ولی چون چاره‌ی دیگری نداشتم مجبور بودم همچنان از Profiler استفاده کنم.

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

نمی‌دانم این بی‌سوادی ناقابل تا حالا چند صد ساعت وقتم را تلف کرده است. اما به هر حال نحوه‌ی فیلتر کردن اطلاعات بسیار ساده بوده و کافی بود تا از طریق برگه‌ی Event Selection، اطلاعات را بر حسب «نام کاربری» و… فیلتر کنم. برای کسب اطلاعات بیشتر به اصل مطلب در وبلاگ وحید مراجعه کنید.

این مطلب جزیی از سری نوشته‌های «داستان بی‌سوادی ما» است.




2010/11/28

پروژه‌های جاوایی در دات‌نت

تعدادی زیادی از پروژه‌های کد باز معروف ‭.Net‬ از روی پروژه‌های موفق Java ساخته شده‌اند. یکی از قشنگ‌ترین چیزهایی که در این تقلید رعایت شده، یکسان بودن API هر دو است. یعنی مثلاً اگر پروژه‌ی جاوایی JavaProjABC وجود داشته باشد که شامل سه کلاس C1 و C2 و C3 بوده و کلاس C2 شامل متودی به اسم m1 باشد که دو پارامتر string دریافت می‌کند، پروژه‌ی دات‌نتی آن که احتمالاً NProjABC یا ProjABC.Net نام دارد هم دقیقاً همین کلاس‌ها و همین متودها را دارد. علاوه بر این رفتار کلاس‌ها و متودها هم یکی است. مثلاً اگر متود m1 در پروژه‌ی جاوایی دو پارامتر دریافتی را در یک فایل متنی نوشته و زیر آن یک خط می‌کشد، متود m1 پروژه‌ی دات‌نتی هم دقیقاً همین کار را می‌کند.

خوبی این موضوع این است که کدهای نوشته شده برای استفاده از یک پروژه‌ی جاوایی یا دات‌نتی اصطلاحاً قابل حمل بوده و به راحتی قابل تبدیل به platform دیگر است. خوبی دیگر آن، یکی بودن شکل و شمایل configuration است. مثلاً کدهای مورد نیاز برای configuration پروژه‌ی جاوایی log4j بسیار شبیه به configuration نسخه‌ی دات‌نتی یعنی log4net است. خوبی دیگری هم هست که خیلی هم قابل استفاده است. وقتی که کار کردن با یکی را بلد باشید کار کردن با آن یکی را هم خود به خود یاد گرفته‌اید و اگر مثالی یا کتابی روی یکی از پروژه‌ها موجود باشد، در آن پروژه‌ی دیگر هم می‌توان از آن استفاده کرد.

این مورد آخر جدیداً خیلی برای من به درد بخور بود. یکی از APIهای پر استفاده‌ی جستجو در NHibernate عبارت است از ICriteria. من به مشکلی در استفاده از آن برخورده بودم که نمی‌دانستم چطور باید آن را حل کنم. در مورد NHibernate و ICriteria جستجو کردم و چیز خاصی پیدا نکردم. اما خوشبختانه چون NHibernate پورت پروژه‌ی معروف جاوایی Hibernate به دات‌نت است توانستم از روی یک سوال و جواب Hibernate جاوایی به جوابم برسم.




2010/11/27

Paging problem with Named SQL queries

Named SQL query in NHibernate is an easy way to apply paging through native SQL. SetFirstResult and SetMaxResults helps a lot here. But the problem is when query is get a bit complicated or for some other reasons that I don't know, paging does not works on pages after first page. In this case a wrong sql query is generated.

From given answers I didn't realized what's the root cause and if there is any solutions or not. But because I was in emergency I used my work-around for it.

My work-around is adding paging elements directly in the query and pass "first result" and "max results" to the query as parameters instead of using SetFirstResult and SetMaxResults. Consider following example:






  
    
     :firstResult 
ORDER BY query._sort_row

]]>

  




This code is inspired from script that NHibernate itself produces while correct paging. Parametrization "top" and "order" sections was not very easy. I got helped from here and here. Notice parametrized "order" is not necessary for paging. It was my own requirement.




2010/11/26

از رنجی که می‌بریم

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

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

یکی دیگر از مشکلات ما تخصصی بودن مشاغل در آمریکاست. در آنجا آنقدر کارهای متنوع گوناگونی وجود دارد هر کسی می‌تواند صرفاً در یک موضوع خاص تخصص پیدا کرده و هیچ وقت هم بیکار نماند. مثلاً آنجا یک نفر می‌تواند تمام عمرش را DBA باشد، طراح صفحات UI باشد، PHP کار باشد یا… در حالی که ما در ایران معمولاً مجبور هستیم تلفیقی از چند فناوری را به طور هم‌زمان به کار ببریم. اشکال این داستان آنجاست که برنامه‌نویس آمریکایی صرفاً یک موضوع خاص مثل Silverlight یا NHibernate را دنبال کرده و کاملاً در آن مهارت پیدا کرده و آن موضوع را بدون هیچ عیب و نقصی انجام می‌دهد. در حالی ما در ایران هیچ وقت چنین فرصتی را پیدا نکرده و همیشه از فناوری‌ها و روش‌ها به صورت دست و پا شکسته استفاده می‌کنیم.

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

از این دست موارد زیاد هستند و متاسفانه من راه حلی برای آن نمی‌شناسم. آیا دیگران هم وجود چنین مشکلاتی را حس می‌کنند؟ آیا کسی راه حلی دارد؟




2010/11/24

Partial Class

همیشه فکر می‌کردم امکان Partial Class در مورد کلاس‌هایی که خودم می‌نویسم چیز بی‌استفاده‌ای است. تا این که دیروز شرایطی پیش آمد که فقط Partial Class می‌توانست به من کمک کند.

من یک کلاس حجیم، بیش از ۷۰۰ خط داشتم که کار کردن با آن سخت شده بود. خصوصاً این که چند نفر به طور هم‌زمان روی آن کار می‌کردند و همیشه احتمال بروز conflict موقع check-in وجود داشت. علاوه بر این عملکرد متودهای آن را می‌شد به ۲ یا ۳ بخش مستقل تقسیم‌بندی کرد و بهتر بود هر کدام را در جای مستقلی نگه می‌داشتم. بنابراین فکر کردم که تقسیم این کلاس به دو یا چند کلاس دیگر خیلی بهتر است.

این کلاس از نوع Generic است و بیشتر اعضایش از نوع static تعریف شده‌اند. اول کار این طور به نظرم رسید که از Extension Method استفاده کرده و بخش‌های دوم و سوم را به یک کلاس static دیگر برده و عملکرد آنها را از طریق Extension Method مورد استفاده قرار دهم. با این که Extension Methodها با کلاس‌های Generic مشکلی نداشتند، اما چون می‌خواستم از داخل Extension Methodها، متودهای کلاس اصلی را که از نوع static هم بودن را صدا بزنم دچار خطای زیر می‌شدم:

Member 'SomeMethod()' cannot be accessed with an instance reference; qualify it with a type name instead

علت خطا همان طور که مشخص است این است که من اجازه ندارم از داخل Extension Methodها، متودهای static را صدا بزنم. ظاهراً دلیل آن این است که با Extension Methodها مشابه متودهای غیر static برخورد می‌شود و فراخوانی متودهای static از داخل آنها ممنوع است.

در اینجا بود که استفاده از Partial Classها به دردم خورد: کلاس مورد نظرم را به چند بخش کوتاه‌تر که از لحاظ عملکرد به هم شبیه بودند تقسیم کردم. این طوری اقلاً حجم فایل کلاس کوتاه‌تر شده و کار تیمی با آن راحت‌تر شد. به مثال MSDN دقت کنید:

public partial class Employee
  {
    public void DoWork()
    {
    }
  }

  public partial class Employee
  {
    public void GoToLunch()
    {
    }
  }




2010/11/22

‫‫‫‫داستان بی‌سوادی ما - ۴: Visual Studio Debugging

یکی از جاهایی که کار می‌کردم دو تا Solution خیلی بزرگ داشتیم. اولی که ۶۴ تا پروژه‌ی ویژوال استودیو بود که همگی تبدیل به dll می‌شدند و دومی که یک پروژه‌ی وب حجیم بود با چیزی بالای ۶۰۰ صفحه aspx. بعضی وقت‌ها که ایرادی پیش می‌آمد مجبور می‌شدم Solution اول را روی کامپیوتر خودم Build کنم، dllهایش را به Solution دوم اضافه کنم، Solution دوم را در حالت Debug بالا بیاورم، آن صفحه‌ای را که مشکل را داشت را باز کنم، روی آن خطی که dllهای Solution اول را صدا می‌زد Break Point بگذارم و هر وقت که اجرای برنامه به آن خط می‌رسید آنقدر F11 می‌زدم و از کلاس‌ها و متودهای مختلف رد می‌شدم تا به آنجایی که تازه می‌خواستم وجود یا عدم وجود ایراد را بررسی کنم برسم. این پروسه خودش در بهترین حالت ۲۰ دقیقه طول می‌کشید تازه بعضی وقت‌ها علت خطا را پیدا کرده و درست می‌کردم و می‌خواستم دوباره آن را امتحان کنم، این خودش یعنی ۲۰ دقیقه‌ی دیگر. حالا خودتان حساب کنید بعضی روزها که می‌افتادیم روی دنده‌ی Debug، چقدر باید وقتمان تلف می‌شد.

چند بار سعی کرده بودم این پروسه را با فراخوانی dllها در یک برنامه‌ی ویندوزی آزمایشی، حذف موقتی بعضی صفحات کم استفاده‌ی Solution دوم، استفاده از Unit Test، استفاده از logging و… کوتاه‌تر و بهینه‌تر کنم اما چندان موفق نبودم. چون به هر صورت بعضی چیزها را فقط در خود پروژه‌ی وب می‌توانستم Debug کنم. متاسفانه این بعضی چیزها خیلی کم تعداد نبودند و همیشه روی اعصاب من و بقیه راه می‌رفتند تا آنجا که بعضی وقت‌ها درخواست‌های Debug یک بخش را کلاً بی‌خیال شده و آن بخش را مجدداً بازنویسی می‌کردم یا این که ایرادهایی را که می‌دانستم قطعاً وجود دارند را مدام پشت گوش می‌انداختم چون واقعاً اعصاب و وقت دیباگ همچون پروژه‌ی حجیمی را نداشتم.

البته تا اینجای کار فقط یک حالت مشکل را شنیدید. حالت دیگر آن وقتی است که امکان استفاده از Break Point را ندارید و اصلاً نمی‌توانید Debug کنید. مثل وقتی که یک عملیاتی از قبیل Data Binding یا به روز رسانی اطلاعات از طریق کدهای Markup یا Declarative صفحات aspx انجام می‌شود.

این مشکلات چند سال است که گریبان‌گیر من است و من دیگر وجود آن را قبول کرده بودم تا این چند وقت پیش با یک ور رفتن کوچولو با StackOverflow فهمیدم که چقدر تا حالا وقتم بیهوده تلف می‌شده است. چون می‌توانستم به راحتی آب خوردن از گزینه Attach to Process ویژوال استودیو برای این کار استفاده کنم بدون آن که این همه وقتم تلف شود.

روش کار بدین صورت است که اول آن Solution وبی را باز می‌کنید و بدون حالت Debug به اجرا در می‌آورید. بعد Solution حاوی dllها را باز کرده و مطمئن شوید که به غیر از فایل‌های dll، فایل‌های pdb را هم دارید. البته اگر ندارید نگران نباشید. این فایل‌ها با یک بار Build به طور خودکار ساخته می‌شوند. قدم بعدی انتخاب گزینه‌ی Attach to Process از منوی Debug ویژوال استودیویی است که Solution حاوی dllها در آن باز است. حالا از فهرست پیش رو، process مربوط به ASP.NET Web Development Server را که معمولاً اسمش با WebDev شروع می‌شود را انتخاب نمایید. در این لحظه ویژوال استودیو خود به خود به حالت Debug می‌رود. شما می‌توانید هر جا که خواستید Break Point بگذارید. اگر به آن صفحه‌ای که نهایتاً آن کد را اجرا می‌کند بروید، می‌بینید که ویژوال استودیوی حاوی dll در محل Break Point انتخابی شما آماده دریافت F10 و F11 است. به همین سادگی! این کار حتی در مورد کدهایی هم که به طور مستقیم از markup صدا زده می‌شوند نیز قابل انجام است.

به عنوان سورپریز این قضیه را داشته باشید که می‌توانید عین همین کار را بدون اجرا کردن پروژه‌ی وبی از طریق ویژوال استودیوی اول هم انجام دهید البته به شرطی که همان پروژه را در IIS کامپیوترتان داشته باشید. روش کار به این صورت است که در بخش Attach to Process به جای Web Development Server از process مربوط به IIS که اسمش در ویندوز دو هزار و هشت w3wp است استفاده کنید.

سورپریز دومی هم وجود دارد. می‌توانید به جای استفاده از IIS کامپیوتر خودتان از IIS دیگر کامپیوترها هم استفاده کنید. یعنی می‌توانید از طریق ویژوال استودیوی کامپیوتر خودتان Web Applicationهایی که در IIS یک کامپیوتر دیگر نصب هستند را Debug کنید. اسم این کار Remote Debugging است.




2010/11/21

‫داستان بی‌سوادی ما - ۳: ASP.NET Membership

یکی از امکانات ASP.NET مجموعه Membership و امکانات جانبی آن است. این مجموعه به برنامه‌های ASP.NET امکان تعریف کاربر، نقش و کنترل دسترسی بر اساس آنها را می‌دهد. برای این که بتوان از این امکانات استفاده کرد بایستی موارد مورد نیاز ASP.NET applications services در بانک اطلاعاتی مورد استفاده برنامه نصب گردد. این کار به طور معمول با کمک ابزار aspnet_regsql.exe انجام می‌شود.

بنده هم هر وقت که می‌خواستم یک بانک اطلاعاتی را برای یک برنامه ASP.NET آماده کنم از همین ابزار aspnet_regsql.exe استفاده می‌کردم. البته بعدها در این کار پیشرفت کرده و جای این اسکریپت‌ها را در ویندوز پیدا کرده بودم:

 C:\Windows\Microsoft.NET\Framework\v4.0.30319

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

حال نکته بی‌سوادی من اینجاست که به تازگی متوجه شدم که کل این کارها با فراخوانی یک متود ساده هم قابل انجام بود! به کد زیر توجه کنید:

SqlServices.Install("databaseName", SqlFeatures.All, "connectionString");

این کلاس با ارزش در فضای نام System.Web.Management قرار دارد. جهت کسب اطلاع بیشتر به این لینک مراجعه کنید.




توجه: این نوشته در قالب سری نوشته‌های «بی‌سوادی ما» می‌باشد.




2010/11/20

‫داستان بی‌سوادی ما - ۲


چند ماه پیش بعد از این که متوجه شده بودم ما در بحث Error Handling برنامه‌هایمان حسابی وقت تلف کرده‌ایم و می‌توانستیم آن کار را خیلی راحت‌تر، سریع‌تر و موثرتر انجام دهیم، حسابی از دست خودم و بقیه کسانی که می‌توانستند متوجه این امکانات بهتر شوند ولی نشده بودند شاکی شده بودم.

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

یکی از راه‌های جلوگیری از این احساس حماقت‌ها این است که در حوزه‌ی فناوری‌های مورد استفاده خود حسابی خبره شده و هیچ کتاب، خبر یا وبلاگی را از دست ندهیم. اما متاسفانه این راه اقلاً برای من امکان‌پذیر نیست. چون من مثل یک برنامه‌نویس آمریکایی نیستم که فقط در یک محدوده‌ی خاص فعالیت کنم. من به طور هم‌زمان باید با مجموعه‌ای قابل توجهی از فناوری‌های هر چند به طور سطحی کار کنم. از جمله: C#‎، ASP.NET، XML، XSLT، JavaScript، MS SQL Server، NHibernate، Castle ActiveRecord، Network Programming، WPF، TFS، SVN، ‌Build Automation، Agile، Scrum، Ajax، UML، Visual Studio، Unit Test، LINQ، Windows و…

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




2010/11/19

Access NHibernate.ISession from Castle ActiveRecord

If you are a Castle ActiveRecord user you may currently encountered situations that it is needed to do some specific operation that is possible just via NHibernate or even just need to direct access to NHibernate's ISession. For example if you want to use LINQ-to-NHibernate or run SQL query with Castle ActiveRecord, there is no way other than direct access to ISession.

To access NHibernate's ISession you must utilize ActiveRecordMediator.Execute() or ActiveRecordBase.Execute(). This method accepts a NHibernateDelegate delegate. Then through this delegate you have access to NHibernate's ISession. Consider following code that uses LINQ-to-NHibernate through Castle ActiveRecord:

[ActiveRecord(Lazy = true)]
public class Car: ActiveRecordBase
{
    public static List GetCars()
    {
        return (List)Execute(
            delegate(ISession session, object instance)
            {
                //here you have direct access to ISession

                var q = from car in session.Linq()
                        select car;

                return q.ToList();
            }, null);
    }
}
For more examples go to this, this and this link.




2010/11/18

BelongsTo and cascading

BelongsTo is a attribute in Castle ActiveRecord that is used to mark an association as many-to-one. For example consider following class diagram. There is an association between Student and Teacher named ArtStudent. This is a many-to-one association so you must add BelongsTo attribute to Student class as showed in following code snippet.



[ActiveRecord(Lazy = true)]
public class Teacher : ActiveRecordBase
{
    //other properties
}

[ActiveRecord(Lazy = true)]
public class Student : ActiveRecordBase
{
    [BelongsTo("ArtTeacher_ID", Cascade = CascadeEnum.None)]
    public virtual Teacher ArtTeacher { set; get; }

    //other properties
}

As this is an one-way association from Student only, Teacher does not know anything about student so it not necessary to add any association or property to Teacher.

Using Cascade field of BelongsTo attribute you can tell ActiveRecord what to do if any modifications occurs to Student. These modification can be SaveUpdate and/or Delete. Please take attention that means modifications just for Student not Teacher. For example if you have had set cascade mode to CascadeEnum.Delete, whenever the Student is deleted, its associated Teacher will be deleted too, but if a Teacher is deleted, no Student will be deleted.

More documentation about BelongsTo attribute:

1. BelongsToAttribute API Document (Trunk)
2.  BelongsToAttribute API Document (RC1)
3. BelongsToAttribute Class
4. BelongsToAttribute Members
5. CascadeEnum Enumeration




2010/11/14

استخدام برنامه‌نویس در موسسه پرشیا شبکه


شرکت (موسسه) ما در حال استخدام برنامه‌نویس جدید است. اصل آگهی شرکت به شرح ذیل می‌باشد:

«موسسه اطلاع‌رسانی مهندسی پزشکی پرشیا شبکه قصد دارد تعدادی برنامه‌نویس C#/ASP.NET که فارغ التحصیل مهندسی کامپیوتر – نرم‌افزار باشند را به طور تمام وقت استخدام نماید. تخصص‌های مورد نیاز عبارت‌اند از تسلط به C#/ASP.NET 3.5 و MS SQL Server و آشنایی با JavaScript و فناوری‌های Ajax. محل شرکت تهران – سعادت آباد است.»

بنده شش ماه است که در این موسسه کار می‌کنم و اینجا را توصیه می‌کنم به کسانی که دوست دارند با روش‌ها، ابزارها و فناوری‌های جدید کار کنند. از جمله Scrum، ORM، Continuous Integration و TDD. عمده‌ی برنامه‌های اینجا با ASP.NET نوشته می‌شوند. امید است که با حضور در اینجا هم خودتان «رشد» کنید و هم باعث «رشد» موسسه شوید. علاقه‌مندان رزومه‌شان را به آدرس info@persiabme.com ارسال کنند. ۲۳ آبان ۸۹




2010/11/12

‫چرا SVN بهتر از TFS است؟


دلایل خیلی زیادی برای این برتری وجود دارد. ولی فعلاً به این یکی بسنده کنید. فرایند پشتیبان‌گیری و برگرداندن پشتیبان‌ها (backup/restore) در svn خیلی ساده ولی در TFS خیلی پیچیده است.

برای پشتیبان‌گیری از مخزن SVN کافی است فولدر آن را در ویندوز کپی کرده و در جای مطمئنی نگه دارید. برای برگرداندن پشیبان هم کافی است فولدر پشتیبان را مجدداً در جای قبلی کپی کنید.

اما در TFS 2010 شما باید به کلی از کارهای admin ویندوز و  Sql Server مسلط باشید و برای انجام یک restore ناقابل مراحل زیادی را طی کنید. اگر باور نمی‌کنید نگاهی به لینک‌های زیر که همگی مربوط به فرایند backup/restore در TFS 2010 است نگاهی بیندازید.




2010/11/10

Tools for generating Castle ActiveRecord classes from database

I was searching for tools that generate Castle ActiveRecord domain classes from databases tables and here is my list of findings:

1. ActiveWriter:
Is a visual tools that you can draw your class diagrams with it. It has versions for VS 2005 and VS 2008 but I'm not sure about VS 2010.

2. My Generation:
A general and popular tool for generating any code from database tables. This template based tool generates code of NHiberante, EF, UI, Castle ActiveRecord and etc. Additional info: link.

3. Active-Record-Gen:
Generates ActiveRecord classes from database.

4. The Darkside:
Generates classes from database and from EDMX files. Additional info: link.

5. GeneratorStudio:
Generates code from database.

6. The AgilityForORMs Castle ActiveRecord code generator:
Generates code from database.




2010/11/08

Paging methods

ASP.NET GridView and other similar controls that support paging needs special methods that return only the requested slice of data and  the count of total data. As I'm a lover of NHibernate/Castle ActiveRecord I have gathered paging techniques in NHibernate HQL, LINQ-to-NHibernate and Castle ActiveRecord:


NHIbernate HQL:

public IList GetData(int page, int pageSize, ref long count)
{
    IList result = null;
    string query_string = "from my_class";
    IMultiQuery query = session.CreateMultiQuery()
        .Add(session.CreateQuery(query_string)
        .SetFirstResult((page - 1) * pageSize)
        .SetMaxResults(pageSize))
        .Add("select count(*) " + query_string);
    IList list = query.List();
    result = (IList)list[0];
    count = (long)((IList)list[1])[0];
    return result;
}

LINQ-to-NHibernate:
internal List GetData(int page, int pageSize)
{

    var q = from t in session.Linq()
            select t;

    return q
        .Skip((page - 1) * pageSize)
        .Take(pageSize)
        .ToList();
}

Castle ActiveRecord:
public static Company[] FindAll(int maximumRows, int startRowIndex, string sortExpression)
{
    Order[] orders;

    if (string.IsNullOrEmpty(sortExpression))
        orders = new Order[0];
    else
    {
        orders = new Order[1];
        const string DESC = " DESC";
        if (sortExpression.EndsWith(DESC))
            orders[0] = Order.Desc(sortExpression.Replace(DESC, string.Empty));
        else
            orders[0] = Order.Asc(sortExpression);
    }

    return SlicedFindAll(startRowIndex, maximumRows, orders);
}

public static int TotalCount()
{
    return Count();
}


For more info refer to this link, link, link and this link.




2010/11/06

تجاربی از اسکرام

همان طور که می‌دانید اسکرام یکی از متودولوژی‌های جدید توسعه نرم‌افزار از خانواده Agile است. این روش مزایای زیادی، اقلاً برای ما، دارد و روز به روز رواج بیشتری در دنیا پیدا می‌کند. ما هم در مدت اخیر تصمیم گرفتیم از این روش برای یکی دو تا از پروژه‌های جدید استفاده کرده و مزایا و معایبش را به طور عملی لمس کنیم. یکی از این پروژه‌ها، پروژه‌ی کوچکی با ASP.NET بود که تعداد افراد درگیر با آن چه در نقش برنامه‌نویس چه در نقش Product Owner کمتر از ۵ نفر بوده و انجام فاز اول آن چیزی حدود ۱۰ هفته طول کشید. انجام این پروژه با اسکرام برای من که اسکرام را با کتاب Scrum and XP from the Trenches یاد گرفته بودم نکات و تجاربی را با خود به همراه داشت که ذیلاً می‌آیند:


۱- قوانین اسکرام برای غربی‌های منظم نوشته شده نه کشورهایی مثل ما. در نتیجه نمی‌توان از مثلاً افرادی مثل Product Owner انتظار داشت همیشه فهرست PBIهایش را به طور کامل و منظم به همراه داشته باشد.

۲- Self Organized بود تیم در اسکرام خیلی مورد توجه قرار گرفته ولی عموماً ایرانی‌ها عادت دارند یک نفر همیشه کارهایشان را به آنها یادآوری کرده و یک نفر دیگر انجام آن کارها را مدام چک کند. ضعف این خصیصه در افراد برنامه‌نویس خیلی از کیفیت کار در اسکرام کم می‌کند.

۳- روی برنامه و اصول پیش رفتن در نظر خیلی افراد یک کار لوکس (قرتی‌بازی) به نظر می‌رسد. مثلاً شکستن یک PBI به چند Task و یادداشت آن در Task Board یکی از آن کارهاست.

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

۵- ایرانی‌ها به طور کلی عاشق Customize کردن هستند. مثلاً دوست دارند موتور پیکان را روی بدنه پژو بگذارند و به اسم پژو آر-دی به بازارا بفرستند. یا این که مدام در فکر بومی‌سازی علوم و فناوری خارجی بپردازند. متاسفانه اسکرام هم از این قاعده سرطانی مستثنی نیست و افراد عاشق دستکاری قوانین آن هستند. مثلا در اسکرام گفته شده طول اسپرینت‌ها باید یکسان باشد ولی ما هم اسپرینت‌های یک هفته‌ای داشتیم و هم اسپرینت‌های دو هفته‌ای.

۶- …


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




2010/11/04

‫Paging بدون DataSource


بیشتر کارهای کنترل‌های ASP.NET را هم می‌توان به صورت Declartive و هم در Codebehind انجام داد. یکی از این کارها عملیات Paging در GridView است. متاسفانه یک محدودیت ظریف در حالت غیر Declarative وجود دارد که کار را برای کسانی که همه کارهای کنترل‌هایشان را در Codebehind انجام می‌دهند سخت کرده است.

اگر GridView را به یک DataSource مثل ObjectDataSource وصل کنید، آن DataSource از دو متود خاص برای بازیافت بهینه اطلاعات استفاده می‌کند. یکی متودی که برای دریافت فقط یک صفحه از اطلاعات و نه همه آنها به کار می‌رود و دیگری متودی برای دریافت تعداد کل رکوردها. اگر از DataSource استفاده نکنید باید event مربوط به PageIndexChanging را در codebehind مورد استفاده قرار دهید. کد این قسمت مشابه کد زیر خواهد بود:

protected void grdList_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
grdList.PageIndex = e.NewPageIndex;
grdList.DataSource = GetData(grdList.PageSize, e.NewPageIndex);
grdList.DataBind();
}

اما چون بدون استفاده از DataSource راهی وجود ندارد که به GridView بگوییم تعداد کل رکوردها چندتاست، پس مکانیزم Pager کار نخواهد کرد. این همان محدودیت ظریف است که در مکانیزم Paging مربوط به GridView وجود دارد. این محدودیت در این لینک MSDN هم توضیح داده شده است. برای کسب اطلاع بیشتر می‌توانید به این لینک و این لینک هم مراجعه کنید.




2010/11/02

Create simple CodeActivity for TFS Build 2010

Sometimes that you need to customize TFS Build 2010, you need to create a custom CodeActivity. A CodeActivity is written in C# and you can do what you can't in TFS Build itself, there. The simplest way to create a custom CodeActivity, deploy and use it, is as follow:


1. Create a .Net 4.0 based Class Library project. CodeActivity exists in .Net framework 4.0 only.

2. Add a Code Activity to it by right click on the project, select Add New Item and navigating to Workflow tab.

3. Add a reference to "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\ReferenceAssemblies\v2.0\Microsoft.TeamFoundation.Build.Client.dll".

4. Add "[BuildActivity(HostEnvironmentOption.All)]" as your CodeActivity's class attribute.

5. Add desired arguments and codes.

6. Build the project.

7. Copy generated dll to "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PrivateAssemblies". If you don't do this, you will not be able to use Visual Studio to add your CodeActivity to any build process template.

8. Add generated dll to a specific location in TFS Source Control.

9. Open up your desired build process template.

10. Add generated dll to the toolbox by right clicking on empty space in General tab, select "Choose Items...", click Browse, navigate to "C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PrivateAssemblies" again and select your generated dll. After this you will see your CodeActivity there.

11. Drag Code Activity on the desired placed in process template.

12. Add any arguments that you want to be accessed via Build Definition to the template process and pass them to your CodeActivity's arguments. To add any arguments to a template process, open Arguments tab in the bottom-left corner of the screen and add them there.

13. Check-in template process. If you don't so, you will not see your added arguments in Process tab of build definitions.

14. Open Build Definition that uses this build process template. You will see any arguments that you have previously added to build process. You can set any value in them.


Note: Above addresses are based on a x64 installation.
Note: For more info refer to Jim's guide and Ewald's guide.