2010/08/28

‫ کار پروژه‌ای در سایت‌های Freelance

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

«جف اتوود» حدود دو سال پیش مطلبی انتقادی نسبت به این طور سایت‌ها نوشته. این نوشته خیلی جنجالی شده و کامنت‌های خیلی خیلی زیادی ذیل آن درج شده است. از آنجا که این کامنت‌ها از طرف افراد مختلفی درج شده است، به همین خاطر منبع بسیار بسیار خوبی است برای فهمیدن این که افراد استفاده کننده از این سایت‌ها خصوصاً rentacode.com که حالا به vworker.com تغییر نام یافته چه نظری راجع به آن دارند و چه تجاربی در آن داشته‌اند. با این که مطلب مربوط به دو سال پیش است ولی چون منبع دیگری سراغ نداشتم همه کامنت‌های آن را خواندم و سعی کردم خلاصه‌ای از نکات موجود در آن را استخراج کنم. این‌ها نظرات آن افراد است نه من:


۱- نظرات مثبت و منفی متضاد خیلی زیاد هست. بعضی‌ها معتقدند این سایت‌ها خیلی خوب و بعضی‌ها معتقدند خیلی بد هستند.

۲- این طور سایت‌ها بیشتر برای انجام پروژه‌های کوچکی که نیاز به پشتیبانی بعدی ندارند مناسب هستند.

۳- همیشه به این طور سایت‌ها به دید کار دوم و کار مکمل نگاه کنید نه کار اصلی.

۴- اول چند تا کار کوچک ولی موفق انجام دهید تا رزومه‌تان خوب شود.

۵- خیلی‌ها با چند مدت کار موفق توانسته‌اند مشتریان (Client) دائم برای خودشان دست و پا کنند و حتی توانسته‌اند کار Full Time در یک شرکت درست و حسابی پیدا کنند.

۶- هیچ وقت روی پروژه‌هایی که غیر واقعی هستند Bid (قیمت دادن به روش مناقصه‌ای) نکنید. مثل «نوشتن وب‌سایتی مثل facebook تنها با ۵۰۰ دلار!»

۷- پروژه‌هایی که spec (تعریف پروژه) نامناسبی دارند هیچ وقت به سرانجام نخواهند رسید.

۸- عمده خریداران آمریکایی و عمده فروشندگان هندی، اروپای شرقی، روسی و کشورهای کمتر ثروتمند دنیا هستند. به همین دلیل پروژه‌ها از یک طرف با قیمت‌های آمریکایی تا ساعتی ۱۰۰ دلار بالا می‌روند و از طرفی به خاطر برنامه‌نویسان ارزان قیمت هندی تا ساعتی ۴ دلار هم پایین می‌آیند.

۹- افرادی که در حوز‌ه‌های خیلی کوچکی مثل Add-in برای فایرفاکس یا برنامه‌نویسی VBA برای اکسل یا حتی CSS مهارت دارند در این طور سایت‌ها شانس بیشتری دارند. چون رقبای کمتری دارند.

۱۰ - خریداران خیلی به خوش قول بودن و مطمئن بودن فروشندگان اهمیت می‌دهند. اگر می‌خواهید در کار Freelance موفق باشید سعی کنید هیچ وقت اعتماد مشتریان را خدشه‌دار نکنید. خریداران زیادی به خاطر بی‌برنامگی فروشندگان متضرر شده‌اند بنابراین اگر کمی زرنگ باشید از این موضوع می‌توانید به نفع خودتان استفاده کنید.

۱۱- از رقابت در این فضای بین‌المللی نترسید. برنامه‌نویس‌های آمریکایی زیادی گرانقیمت هستند (ساعتی ۱۰۰ دلار) و برنامه‌نویسان هندی زیادی غیر قابل اعتماد.

۱۲- تعدادی از برنامه‌نویسان از این طور سایت‌ها دست می‌کشند نه به خاطر این که این سایت‌ها جاهای بدی هستند بلکه به این خاطر که راه‌های راحت‌تری برای جذب پروژه پیدا کرده‌اند.

۱۳- برای برنده شدن در یک مناقصه نیاز لازم نیست فقط قیمت را پایین بیاورید، بلکه باید همزمان نشان دهید که کیفیت کارتان بالاست.

۱۴- ارتباط بین شما و مشتری‌ها معمولاً از طریق ایمیل و Chat انجام می‌شود ولی آمادگی صحبت تلفنی با یک فرد انگلیسی زبان را داشته باشید.

۱۵- قبل از قیمت دادن برای پروژه تا می‌توانید از مشتری راجع به پروژه سوال کنید تا هیچ ابهامی باقی نماند.

۱۶- سایت معروف Digg از طریق همین سایت‌ها سفارش داده شده‌.

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




2010/08/24

سوختن هارد و سرور مجازی

درست یک روز بعد از این که چند نوسان برق در منزل مشاهده شد، هارد کامپیوترم جان به جان‌آفرین تسلیم کرد. حالا من مونده بودم و اطلاعاتی که از بین رفته بود و زجر نصب مجدد ویندوز، ویژوال استودیو، SQL Server، SVN، Jira و بقیه‌ی خورده ریزهای دیگر. البته مصیبت وارده از ناحیه اطلاعات از بین رفته و خرید مجدد هارد دیسک را هم فراموش نکنید. از آنجا که فعلاً از یک هارد موقتی استفاده می‌کنم و باید بعداً دوباره تمامی مراحل نصب را برای هارد جدید  هم تکرار کنم، باید دنبال راهی می‌گشتم تا زمان نصب مجدد را کاهش دهم. بعد از کلی دو دو تا چهار تا کردن تصمیم گرفتم از VM Ware برای ایجاد یک سرور مجازی استفاده کنم.

روشی که انجام دادم این است: نصب یک نسخه از ویندوز XP به صورت Virtual. از ویندوزهای جدیدتر استفاده نمی‌کنم چون ویندوز XP سریع‌تر نصب می‌شود و جای کمتری می‌گیرد. بلافاصله بعد از نصب، VM مربوطه را روی DVD می‌ریزم. چون ممکن است دفعات بعد هم به یک ویندوز تازه نیاز پیدا کنم. در این مرحله یک اشتباه کوچک انجام دادم و آن هم محدود کردن فضای مورد استفاده Virtual Machine به ۲۰ گیگ بود. چون فکر می‌کردم VM Ware کل آن فضا را در همان ابتدای کار اختصاص می‌دهد. البته بهتر است شما این فضا را خیلی بیشتر در نظر بگیرید چون اولاً نیازی به داشتن آن مقدار فضای خالی در همان لحظه وجود ندارد، ثانیاً بعد از ایجاد Virtual Machine دیگر نمی‌توان این فضا را تغییر داد. در مورد بقیه تنظیمات مثل شبکه، درایورها و بقیه نگران چیزی نباشید چون خود VM Ware پیش‌فرض‌های خوبی دارد و معمولاً مشکل خاصی در رابطه با شبکه وجود ندارد.

بعد از نصب ویندوز، باقی موارد مورد نیاز از جمله SQL Server را نصب می‌کنم. فقط باید دقت شود که به خاطر کوچک نگه داشتن حجم Virtual Machine هیچ اطلاعات اضافی مثل دیتابیس‌ها یا سورس کد را به Virtual Machine اضافه نکنید. بعد از این که همه چیز را خوب تست کردم کل Virtual Machine را روی DVD رایت می‌کنم. کپی یک نسخه از VM Ware و کلیه passwordها از جمله رمز ویندوز و SQL Server هم فراموش نشود. تا اینجا حجم Virtual Machine حدود ۴ گیگ شده که به راحتی می‌توان آن را روی یک DVD نگه داشت.

حالا دیگر می‌توانم با خیال راحت از این Virtual Machine به عنوان سرور استفاده کنم. از این به بعد هر وقت که هاردم بسوزد یا ویندوزم ایراد پیدا کند فقط مراحل نصب ویندوز و ویژوال استودیو را انجام خواهم داد، چون یک سرور را به صورت Virtual دارم. هم به صورت خام و بدون اطلاعات در DVD و هم به صورت عملیاتی. خوبی این روش این است که اولاً می‌توانم سرور را روی یک هارد مطمئن نگه‌داری کرده، در ویندوزهای مختلف آن را با استفاده از VM Ware اجرا کرده و با آن کار کنم، درست همانطور که از یک سرور واقعی در محل کار استفاده می‌شود. ثانیاً اگر دوباره فاجعه‌ای مثل سوختن هارد دیسک اتفاق بیفتد، با فرض داشتن backup اطلاعات، کافی است یک نسخه از سرور مجازی را که قبلاً روی DVD رایت کرده بودیم را روی هارد جدید کپی کرده، اطلاعات سورس، دیتابیس و… را restore تا کار در مدت زمان کمتری شروع شود.


امیدوارم هیچ وقت از این طور فجایع برای شما اتفاق نیفتد چون داغ از دستن دادن هارد خیلی سخت است!

به روز رسانی: مطابق نظرات دوستان که در بخش کامنت‌ها قابل مشاهده است، محدودیت حجم هارد مجازی را می‌توان به نحوی پشت سر گذاشت.




2010/08/22

‫چطور یک attribute ناقابل ده روز سرکارم گذاشت!

چند وقت پیش یک پروژه تستی کوچک NHibernateی ایجاد کردم برای ذخیره و بازیابی چند کلاس ساده. یک پروژه تست هم با استفاده NUnit درست کردم برای تست آن. در تست کردن به یک خطای آزار دهنده برخورد کرده بودم. طبق معمول از سر بی‌دقتی فقط آخر پیغام خطا را می‌خواندم که گفته بود don't flush the Session after an exception occurs. به همین خاطر به شدت به مدیریت session مربوط به NHibernate در متودهای [SetUp] و [TearDown] مشکوک شده بودم. خیلی آن را بالا و پایین کردم و کلی آن را با نمونه کدهای قبلی مقایسه کردم. آخرش متقاعد شدم یا ایراد از همان دو متود Setup و TearDown است یا به این خاطر است که این بار از روش جدیدی برای ایجاد پروژه‌ی اصلی استفاده کرده بودم.

 توی این هیری ویری هم هاردم سوخت و پروژه یک هفته خوابید. تا این که امشب بعد از کلی دقت به پیغام خطا فهمیدم که پیغام خطا با not-null property references a null or transient شروع می‌شود. البته جستجوی این خطا هم در اینترنت باز هم بیشتر مرا گمراه کرد. نمی‌دانم در «یک لحظه» چه اتفاقی افتاد که به mapping کلاس مربوطه شک کردم و نگاهی به آن انداختم. حدستان درست است، علت خطا در mapping نهفته بود. در تعریف همه propertyها یک attribute وجود داشت به اسم not-null که برابر true قرار داده شده بود. در واقع چیزی که برای من اتفاق افتاده بود خطا نبود. بلکه خود من از طریق آن attribute به NHibernate گفته بودم که آن property حق ندارد null باشد و NHibernate هم فقط داشت این موضوع را به من یادآوری می‌کرد چون من در بعضی جاهای تستم مقدار بعضی propertyها را اصلاً set نمی‌کردم.

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




2010/08/20

امتحان ورود کارشناسی ارشد

روز جمعه ۲۹ مرداد ۸۹ امتحان ورودی کارشناسی ارشد ناپیوسته مهندسی فن‌آوری اطلاعات دانشکده آموزش‌های الکترونیک دانشگاه شیراز در محل موسسه آیین زندگی حوالی آریاشهر برگزار شد. امتحان گرایش طراحی و تولید نرم‌افزار شامل سوالاتی از دروس زبان، ریاضی، برنامه‌سازی و مهندسی نرم‌افزار بود. صرف نظر از ایردات معمول امتحان، می‌توان ایراداتی را هم به سولات دو درس برنامه‌سازی پیشرفته و مهندسی نرم‌افزار وارد کرد.

۱- زبان برنامه‌نویسی مورد استفاده جاوا بود و آن‌هایی که مثل من به جای جاوا، سی‌شارپ بلد بودند خیلی متضرر شدند. البته این موضوع از قبل هم اعلام شده بود ولی اعلام قبلی آن فرق آنچنانی در اصل موضوع ایجاد نمی‌کرد.

۲- سوال ۳۳ کاملاً اشتباه بود. کد داده شده وارد حلقه بی‌نهایت می‌شد و البته هیچ کدام از خروجی‌های داده شده در گزینه‌های داده شده را تولید نمی‌کرد. به اصل سوال و گزینه‌های آن دقت کنید:
Public class test {
Public static void main(String[] args)
{
for (int j=1; j<=5; j++) {
for (int k=1; j<=j; k++)
System.out.print('*');
System.out.println();
}
}
}

گزینه اول
*****
 ****
  ***
   **
    *
گزینه دوم
*****
****
***
**
*
گزینه سوم
    *
   **
  ***
 ****
*****
گزینه چهارم
*
**
***
****
*****
البته اگر شرط حلقه دوم را با k<=j عوض کنیم مشکل حل شده و گزینه چهار صحیح خواهد بود.

۳- یک سوال سه بار تکرار شده بود! سوالات ۵۰ و ۵۴ کاملاً یکی بودند و سوال ۵۶ هم همان سوال ۵۰ و ۵۴ بود که فقط کمی متن آن عوض شده و جای دو تا از گزینه‌ها عوض شده بود. سوال عبارت بود از «کدام یک از موارد زیر در طراحی مورد بررسی قرار نمی‌گیرد.»

۴- در بعض از سوال‌ها از معادل‌های فارسی نامأنوسی استفاده بود که جواب دادن به سوالات را بی‌دلیل سخت می‌کرد. از جمله «واسط» به جای interface در سوال ۵۶، «تغییر دهنده» به معنی کلمات public و private که در ابتدای تعریف متودها و دیگر اعضای کلاس‌ها می‌آید.

۵- اشتباهات تایپی و گرامری هم که نایاب نبودند. مثلاً به گنگی سوال ۵۷ دقت کنید: «همبستگی (cohesion) یک نمایان کیفی است از میزان درجه این که یک ماژول ...» گزینه اول: بتواند به صورت فشرده‌تر نوشته شود. گزینه دوم…


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






2010/08/14

Saving time as UTC with NHibernate

In many applications that have world wide users, there is a need to dealing with UTC. In these applications, time is stored in UTC and then showed backed in local time to users. A good solution is not to bother developers to convert time to universal or local time every time manipulating time related data. Instead we could add a bit of code to setter getter of DateTime fields. Unfortunately this solution does not work in NHibernate and possibly other ORMs. Consider following code:

DateTime _myDate;

[Property]
public virtual DateTime MyDate
{
    set { _myDate = value;}
    get {return _myDate;}
}

In this code we can not add a ToLocalTime() or ToUniversalTime() to setter or getter. Because both NHibernate and the application use this same getter and setter. Real solution is to use a helper field. This way the helper field will not persist on database but real field persists on database. Real field mus not be accessible to developer because of confusion and possible unwanted changes. Consider final solution:

public virtual DateTime MyDate //helper field
{ 
    set { MyDateUtc = value.ToUniversalTime(); } 
    get { return MyDateUtc.ToLocalTime(); } 
}

[Property]
private DateTime MyDateUtc { set; get; } //real field

All codes are based on Castle Active Record.




2010/08/10

Dependency Injection

همیشه وقتی سورس نرم‌افزارهای Open Source را بررسی می‌کردم به یک چیز بی‌معنی برمی‌خوردم: استفاده بی‌مورد از interface. مثلاً کلاسی را پیدا می‌کردم که پیاده‌سازی یک اینترفیس خاص بود در حالی که خود آن اینترفیس هم فقط در همان یک جا مورد استفاده قرار گرفته بود. تا جایی که من می‌دانستم استفاده از interface وقتی خوب است که بخواهیم چندین و چند کلاس داشته باشیم که بخواهیم آن یک interface خاص را پیاده‌سازی کرده باشند. چند وقت پیش بالاخره به صرافت افتادم و در StackOverflow پرسیدم که چرا این روزها استفاده از interface این قدر باب شده است.

جواب خیلی واضح و قابل قبول بود. چون با استفاده از interfaceها می‌توان مفاهیمی مثل Dependency Injection و Decoupling را در نرم‌افزار پیاده‌سازی کرد. استفاده از این مفاهیم یعنی کلاس‌ها و دیگر بخش‌های برنامه را طوری بنویسیم که در حد ممکن از دیگر بخش‌ها بی‌خبر بوده و در نتیجه به آن وابستگی نداشته باشند. برنامه‌هایی که به این روش نوشته می‌شوند مدیریت و نگهداری راحت‌تری دارند و خواناتر هستند. علاوه بر این‌ها تکنیک‌های جدیدی که در TDD و Mocking استفاده می‌شوند در برنامه‌هایی که به روش Dependency Injection نوشته شده‌اند خیلی کاراتر و راحت‌تر عمل می‌کنند.




2010/08/05

‫Mocking و Rhino Mocks

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

مشکل من با Mocking از آنجا بود که نمی‌دانستم از کجا باید شروع کنم و چه چیزی را باید یاد بگیرم. من تمام وبلاگ/سایت نویسنده Rhino Mocks که تبدیل به استانداردی در دنیای Mocking شده را زیر و رو کردم، همینطور StackOverflow و گوگل را. اما ظاهراً خیلی از مطالبی که پیدا می‌کردم از جمله مطالب خود وبلاگ/سایت نویسنده آن یعنی Ayende Rahien از تاریخ گذشته و اصطلاحاً depricate شده بودند یا این که فهمیدن آنها خیلی سخت بود. هر کسی از هر روشی که خوشش آمده بود استفاده کرده بود و هیچ منبع درست و حسابی پیدا نمی‌شد. خوشبختانه با همه بالا و پایین‌ها متوجه شدم که دو روش کلی برای انجام Mocking با Rhino Mocks وجود دارد:


۱- روش کلاسیک یا Record-Replay: این روش قدیمی‌تر است و مبتنی بر انجام یک سری عملیات پشت سر هم، ضبط و سپس تکرار آنهاست. بیشتر منابعی که در اینترنت پیدا کرده بودم از این روش استفاده می‌کردند.

۲- روش AAA: این روش بعد از ورود lambda expressionها و extension methodها به C#‎ ابداع و مورد استفاده قرار گرفته است. بیشتر افراد معتقد هستند این روش خیلی راحت‌تر و خواناتر است. من هم این روش را برای ادامه کارم انتخاب کرده‌ام. یک مطلب بسیار خوب در مورد یادگیری این روش در اینجا آمده است.


برای استفاده از Mocking در تست‌ها باید آماده برداشتن یک قدم مهم بود: استفاده از مفاهیم Decoupling و Dependency Injection در سطح کد یا حداقل استفاده از کلاس‌های Virtual و غیر Static. چون Rhino Mock و بقیه ابزارها یا فقط از interfaceها یا از کلاس‌هایی که متودشان به صورت virtual تعریف شده باشد می‌توانند استفاده کنند. دلیل آن هم اصلاً غیر منطقی نیست. به یاد داشته باشید برای استفاده از Lazy Loading در NHibernate هم باید setterها و getterها به صورت Virtual تعریف می‌شد.


چند منبع:
۱-  مطلب اول و دوم وحید
۲- صفحه‌ی رسمی Rhino Mocks
۳- وبلاگ پدیدآورنده‌ی Rhino Mocks
۴- نوشته‌ی مارتین فولر درباره فرق Stub و Mock
۵- راهنمای خیلی خوبی برای شروع Mocking با استفاده از روش AAA
۶- صفحه‌ی ویکی‌پدیا درباره‌ی Mocking
۷- توضیحات پدیدآورنده‌ی Rhino Mocks درباره روش AAA