FTP in .Net

Doing FTP in .Net is not as hard as you may imagine. There is a very simple way and a bit advanced way. Simple way is using System.Net.WebClient class    and its UploadFile method. Advanced way includes using System.Net.FtpWebRequest and System.Net.FtpWebResponse classes. Using them you can do ordinary FTP operations like ListDirectory, UploadFile, DeleteFile, etc. For an example see following code. More information is available from here.

public void DeleteFile(string remotePath)
    FtpWebRequest request = (FtpWebRequest)WebRequest.Create(remotePath);
    request.Credentials = new NetworkCredential("user name", "password");
    request.Method = WebRequestMethods.Ftp.DeleteFile;

    FtpWebResponse response = (FtpWebResponse)request.GetResponse();



‫تبدیل به استرینگ در C#‎

اگر شما هم تا حالا برای ساخت یک استرینگ از استرینگ و عدد در C#‎ از روشی مثل string str = "old" + (2+2).ToString()‎ استفاده می‌کردید، یعنی خودتان زحمت ToString()‎ را می‌کشیدید، دیگر این زحمت را نکشید. چون قانون String Concatenation در C#‎، شرح داده شده در بخش ۷.۸.۴ مشخصات زبانی C#‎، طوری است که اگر بخواهید یک عدد یا هر نوع داده‌ای دیگری مثل DateTime یا کلاس‌های ساخت دست خودتان را به یک استرینگ اضافه کنید، آن عدد یا نوع داده‌ای غیر استرینگ خود به خود به استرینگ تبدیل می‌شود، یعنی .ToString()‎ آن به طور خودکار فراخوانی می‌شود.

این موضوع را وسط یک رفتار عجیب C#‎ پیدا کردم. یک سری کد از قبل داشتم که در آنها یک رشته به یک متغیر از نوع استرینگ می‌چسبید. نوع آن متغیر را بعد از مدتی به یک کلاس ساخت خودم تبدیل کردم و انتظار داشتم کامپایلر C#‎ به آن خط گیر بدهد که نداد. به همین خاطر یک سوال در Stack Overflow پرسیدم و علت را فهمیدم.


How to add parameter to Build process parameters?

If you have added some new Activity or CodeActivity to your build process template but you don't want to edit template process each time you want modify properties of Activity or CodeActivity, you must add that parameter to "Build process parameters" list of your desired build definition. By doing this, there is no need to modify template process and check-in back it each time.

Jason has described this and has showed how you can do it by editing XAML file directly. But if you are searching for an easier way, follow these steps:

1. Open build process template.
2. Open Arguments tab at the bottom-left corner of the screen.
3. Add your parameters as "In" arguments.
4. Pass value of these arguments to properties of desired build/workflow activities.
5. Save and check-in template process.
6. Open up Build Definition that uses this template process.
7. Go to Process tab and navigate to Misc section. You will see your added arguments there, that are added as "Build process parameters".
8. Fill your values there to be used by TFS Build.


Custom workflow activity's problem with Visual Studio designer

After reading Jim Lamb's guide for creating a custom workflow activity for TFS Build 2010, I created a project to create my own custom workflow activity too, by following Jim's guides line by line. At the end, despite my correct custom activity, when I tried to use that in a typical template process by dragging it onto the workflow I just saw a deny symbol and couldn't put my activity on that workflow.

After so many verifications of my custom activity and so many googling, I decided to add my activity by editing XAML file directly in notepad. Unfortunately when loaded the workflow in the Visual Studio again, a red label with message "Activity could not be loaded because of errors in the XAML." was showing instead of my activity. So googled again and found Ewald Hofman's solution. Based on his guides I installed my assembly in GAC and the red error message label disappeared. I was having still 2 more problems. First, Jim's sample code was working with no problem, but my activity needed registration in GAC. Second, despite of disappearing red label, I was still unable to drag my activity to workflows, I was forced to edit XAML file directly.

After a whole challenging day, I realized that Jim's sample assembly exists in C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PrivateAssemblies previously! I don't know how Jim's ActivityPack has gone to that location but I know when I copied my custom activity's assembly to that location, my 2 problem solved too. So I could use Visual Studio designer to drag my custom workflow activity into any workflow or template process I want.


log4net: logging NHibernate and my own domain

I was used to use entlib for logging. But as I'm in favour of open source and because I am using NHibernate and Castle ActiveRecord in my applications, decided to use log4net instead. So found a good article about it, and enabled it for my application. But the problem was a very huge log file was producing because of verbose logs from NHibernate.

I've been heard that log4net uses hierarchical loggers but did not have a good understanding of it. I was thinking that using hierarchical loggers I can omit NHibernate's logs and instead show my application's logs. My bad assumption about hierarchical loggers was that they should be defined in app.config/web.config as nested. Obviously this assumption was wrong. Hierarchical logger in log4net means that you define a root and define all loggers inside it directly. Hierarchy then is understood of "name" attribute of "logger" node. This just acts a C# namespaces. For example you can have "NHibernate" and "NHibernate.SQL". The second one is a child of the first.

Following guides in this, this, this, this and this link helped me to build my own config that works greatly in my application:


















Customizing build process in TFS 2010

If you ever has need to customize build process in Team Foundation Build 2010, you may noticed that there is several ways to do it while each way is suitable for a specific range of requirements:

1. Running external tools like batch files or ftp.exe or MSBuild Community Tasks via InvokeProcess or via MSBuild Activity.

2. Invoke .Net classes and methods like System.IO.File.Delete() via InvokeMethod.

3. Creating your own custom workflow activity for TFS Build 2010.

For our specific need that is synchronizing a remote server via FTP, none of first 2 ways is suitable. In first way, running external programs, this is very hard to synchronize a whole remote directory and its sub-directories just via ftp.exe and a bunch of batch file commands like FOR. In addition, this may impose dependency to external tools in the server.

In the second way, running .Net classes and methods, we have to create our own ftp utility or use third party tools like ftp.exe or MSBuild Community Tasks. In addition this causes using intensive usage of TF Build activities that's not easy to copy to new Team Foundation builds in new projects.

Third and last way, creating your own activity is harder to implement but has many advantages over other ways including:

1. High flexibility because this is entirely written by yourself.

2. Maintaining is easier because all of your work is kept in a single Visual Studio project.

3. It is easier to deploy it in new team builds because it is simply just one single workflow activity.

4. It is easier to configure. You configure it via its arguments and variables. No need to modify template process itself.


Confusing problem with log4net

I'm using log4net for logging in my ASP.NET application. This web site is based on .Net framework 3.5 and is installed on IIS 7.5 and Windows Server 2008 R2 in a 64 bit machine. Logging was working greatly when I was running application from Visual Studio 2010's internal web server, but was not working at all when run from IIS.

First thing that I thought about was permission. So I grant full access to network service with the folder containing application: "c:\inetpub\wwwroot\myapp". But this didn't work and no log file generated. As I'm new to Windows Server 2008, I tried to grant full permission to all users that I knew: IUSR, local service, aspnet, IIS_IUSRS, Everyone, etc. But still nothing was working. A question in SO caused me to think this is because of trust level, so I set my application's trust level to full. But still nothing was working. Another question in serverfault.com caused me to think the problem root is that Windows Server 2008 is using a new user for IIS. So I tried to use icacls to add ApplicationPoolIdentity to permission list. After it, I tried to change Identity of DefaultAppPool to Network Service. But none of this two solutions solved my problem.

Some people have been recommending to enabling internal logging of log4net to detect original problem. And yes, this showed me what was the problem:

log4net: XmlConfigurator: config file [C:\inetpub\wwwroot\log4net.config] not found. Configuration unchanged.

After some investigations, root cause was detected. It was due to incorrect use of Server.MapPath. I was forgotten to add a tilde mark in beginning of log4net.config's path. When I used Server.MapPath as follow, all headaches have suddenly disappeared and my log file appeared and get working as I was desiring:

XmlConfigurator.Configure(new FileInfo(Server.MapPath("~/log4net.config")));
A wrong path has been causing log4net to search c:\inetpub\wwwroot for log4net.config not my application's path at c:\inetpub\wwwroot\myapp. All this nightmare was because of my own mistake not Windows, IIS or .Net!

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

دوستی می‌خواست چیزهایی راجع به نرم‌افزارهای آزاد، متن‌باز، تفاوت‌ها و دیگر مسائل بداند. این متن جوابی است به ایشان.

متن‌باز بودن نرم‌افزار به چه معنی است؟ تا آنجا که من می‌دانم هر نرم‌افزاری می‌تواند متن‌باز هم باشد. مثلاً یک نرم‌افزار پولی یا مجانی یا آزاد یا غیر آزاد می‌تواند متن‌باز هم باشد یا نباشد. دلیل این که همراه بیشتر نرم‌افزارهای پولی سورس آنها هم ارائه نمی‌شود آن است که سورس برنامه‌ها بسیار گرانقیمت‌تر از خود نرم‌افزارها هستند. مثلا ویندوز ایکس‌پی فرضاً ۱۰۰ دلار است ولی سورس کد آن ۱۰ میلیون دلار است.

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

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

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

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

روش رایج پول در آوردن از نرم‌افزارهای آزاد، پشتیبانی فنی و خدمات مشاوره است. مثلاً نرم‌افزار OTRS خودش آزاد، متن‌باز و مجانی است و هر کسی هر کار که دلش خواست می‌تواند با آن بکند. اما شرکت حامی آن خدمات hosting آن را به صورت پولی ارائه می‌کند، خدمات نصب و مشاوره و خدمات پشتیبانی آن را هم به صورت پولی ارائه می‌کند و پول خوبی از این راه به دست می‌آورد. البته راه‌های زیادی برای پول درآوردن از نرم‌افزارهای آزاد هست که بستگی به شرایط دارد.

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

جهت اطلاع بیشتر:
‫کپی‌لفت (Copyleft) چیست؟ 
‫چرا FOSS (و Open Source) برای ما خوب است؟‫حرکت به سمت FOSS
‫برنامه‌های من برای مهاجرت به FOSS 

ضمناً فکر می‌کنم سایت‌ها و انجمن‌های فارسی‌زبان زیادی باشند که روی این موضوعات کار می‌کنند.


Unlocking TFS Version Control items

We have a Visual Studio solution that uses some external assemblies coming from third parties. This solution resides in TFS 2010 version control. We have configured Team Foundation Build to do automatic builds of the solution. As you know you should put any external assemblies in TFS Version Control to do a proper build without any build breaks. So we did same. Whenever we want to update the assembly with a new one, we first check-out the item, copy newer assembly to local folder and then check-in it again.

An assembliy (.dll file) in TFS can not be checked-out by multiple users because it's a binary file and can't merged or compared. Just like files of type gif. We had a situation recently that a user checked-out one assembly without checking-in it again or undoing his change. As he went to vacation, that assembly remained locked in TFS version control and no one could check-out that assembly again. Me as TFS administrator was forced to unlock it. So googled for the solution and found Martin Woodward's work-around:

tf lock $/MyProject/MyPath/MyFile.cs /lock:none /workspacename:WorkSpaceName /server:my_server
Unfortunately this was not working for me because I got error:
Tf10152: the item xxx must remain locked because its file type prevents multiple check-outs.

I was very hopeless but another link showed me how to use "undo" to solve my problem. This time it worked nicely:
tf undo /workspace; /server:  item

For those unfamiliar with "tf", it is powerful command-line tool for TFS that can be run from a "Visual Studio Command Prompt" window.


Each TPC needs a separate Build Controller

If you are going to start using TFS 2010 please be aware that each TPC (Team Project Collection) needs a separate Build Controller.

For those who are intended to use TFS 2010 as their ALM engine, TFS 2010 can contain several TPCs. Each TPC can contain several Team Projects. Each Team Project is a regular space in TFS that contains Work Item Management, Source Control and Build automation. Build automation in each Team Project contains several Build Definitions that build project with several conditions. Each Build Definition is assigned to a Build Controller. A Build Controller is a build server that builds project using conditions defined in Build Definitions.

In other hands while defining a new Build Definition you must specify its Build Controller. Unfortunately with TFS 2010 you can not use Build Controller defined for say TPC number one for say TPC number two. Each TPC must have its own Build Controller.

Considering that a Build Controller is really a server, assigning a server to each TPC defined in TFS is not very applicable in most companies and teams. There is an article in MSDN blogs that shows a way to use a single Build Controller in several TPCs. As the article itself emphasis, this hack is not recommended for operational installations. Some people like us have been forced to use a single TPC for all Team projects. This work-around has many disadvantages like interfere of Team Projects, security issues, etc, but at least have solved the problem of need to several servers as Build Controllers.

See also:
My question in StackOverflow
Related content in TFS forum
Related content in GeeksWithBlogs
Jim Lamb's hack for the problem


برون‌سپاری خدمات تخصصی - بخش اول

همیشه یک ایده وسوسه کننده در ذهن من بوده برای تخصصی کار کردن. چون این ایده هنوز در ذهن خودم هم جا نیفتاده مجبورم بیشتر با مثال توضیح بدهم.

فرض کنید یک شرکت نرم‌افزاری با ۵ الی ۱۰ برنامه‌نویس وجود دارد که ۱- قصد کار کردن با یک تکنولوژی جدید مثل ASP.NET MVC یا NHibernate را دارد یا ۲- می‌خواهد از ابزاری مثل Git برای سورس کنترل استفاده کند یا ۳- قصد بهبود شبکه داخلی خودش را دارد و می‌خواهد مثلاً پهنای باند اینترنتی را به نحو مقتضی بین کامپیوترها تقسیم کند. یا این که ۴- جدیداً مشکلات حادی با MS SQL Server پیدا کرده و می‌خواهد مسائلی مثل حجم خیلی زیاد دیتابیس، collation و ایندکس‌گذاری را در آن حل کند یا ۵- شرکت در محیط مشتری‌هایش مشکلات زیادی با فونت و حروف عربی-فارسی دارد و می‌خواهد این مشکل را یک بار برای همیشه با اعمال استانداردهای مرتبط حل کند یا ۷- شرکت می‌خواهد مسائل مشترکی را مثل اتصال به دستگاه کارت‌خوان، پرینت بارکد، تولید دیسکت بیمه، اتصال به نرم‌افزارهای جانبی مثل اکسل، Word و…، پرینت روی چک بانک‌های مختلف، پیاده‌سازی پروتکل ECE و غیره را که بارها و بارها در شرکت‌های مختلف حل شده‌اند را حل کند یا این که ۸- شرکت حس می‌کند تیم برنامه‌نویسی‌اش در مسائلی مثل documentation یا test ضعف دارد و به نحوی می‌خواهد این مشکلات را کاهش دهد یا این که ۹- شرکت مشکل خاصی ندارد ولی می‌خواهد برای چند سال آینده‌ش برنامه‌ریزی کرده و سمت و سوی تکنولوژی‌های موجود را بداند.

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

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


‫آیا NHibernate انتخاب خوبی به عنوان یک ORM است؟

اگر در مورد لزوم استفاده از ORM به جواب مثبت رسیده‌اید، انتخاب یک ORM کار چندان  سختی نیست. در حال حاضر ORMهای تجاری و غیر تجاری زیادی وجود دارند از جمله ADO.NET Entity Framework، LLBLGen Pro، SubSonic و… برای دیدن فهرست آنها می‌توانید به این لینک مراجعه کنید.

NHibernate یک ORM کد باز است که از دنیای جاوا وارد دات‌نت شده است. کد باز بودن آن خود به خود مزایای زیادی ایجاد می‌کند. از جمله: جامعه استفاده کنندگان بیشتر، تنوع محصولات جانبی، عدم نیاز به کرک و قفل‌شکنی، عدم وابستگی به ‎.Net Framework و…

از آنجا که NHibernate بر اساس پروژه‌ی جاوایی Hibernate ایجاد شده از تمام تکنیک‌ها و منابع آموزشی آن می‌توان در NHibernate نیز استفاده کرد. NHibernate مدت‌هاست که چه در جاوا و چه در دات‌نت مورد استفاده است و منابع، نمونه کدها و پروژه‌های زیادی بر اساس آن به وجود آمده.

در مورد NHibernate پروژه‌های جانبی زیادی وجود دارد که کار کردن با آن را خیلی راحت‌تر ساخته است. مثلاً Fluent NHibernate به عنوان ابزاری که با کمک آن دیگر نیازی به استفاده از Xml Mappingهای NHibernate یعنی HBMها وجود ندارد. NHibernate Profiler ابزاری برای بازرسی و افزایش سرعت NHibernate. پروژه‌ی Castle ActiveRecord به عنوان ابزار راحت‌کننده‌ی کار با NHibernate و چندین پروژه‌ی مفید دیگر.

یکی از نگرانی‌های همیشگی در کار با ORMها Performance است. مسلماً هر ORMی مقدار کمی سرعت را کاهش می‌دهد. چون ORM یک لایه‌ی اضافی بر روی ADO.NET است. اما این موضوع در برابر دیگر مزایایی که استفاده از ORM به دست می‌دهد قابل اغماض است. البته این کاهش سرعت عمدتاً به علت عدم تنظیم صحیح ORM یا طراحی غلط Class Diagram است و می‌توان آن را تا اندازه‌ی زیادی از بین برد.

در این مورد که آیا NHibernate را می‌توان در پروژه‌های بزرگ به کار برد یا نه فکر نمی‌کنم در مورد پروژه‌هایی که داخل کشور به کار می‌روند مشکل خاصی ایجاد کند. تصور من این است که NHibernate خودش یک چیزی مثل ADO.NET است و می‌تواند بدون توجه به بزرگی یا کوچکی پروژه، یک Performance قابل قبول را از خودش به نمایش بگذارد.

ما در شرکت قبلی استفاده‌های خیلی خوبی از NHibernate کرده و از خیلی از مزایای آن بهره برده بودیم. اما متاسفانه در مقوله‌ی Performance مشکلاتی داشتیم که باز هم  عمدتاً مربوط به عدم استفاده صحیح ما از NHibernate بود. مطمئنم که با استفاده مناسب‌تر و داشتن دانش فنی عمیق‌تر از NHibernate می‌توانستیم مشکل Performance را هم از سر راه برداریم. با این وجود توصیه‌ام به کسانی که قصد استفاده از NHibernate را دارند این است که قبل از شروع حسابی مستندات آن را مطالعه کنند و یکی دو نمونه هم با آن بسازند. ضمناً در مورد طراحی Class Diagramهای دیتابیسی نهایت دقت را به عمل آورند در غیر این صورت حسابی به دردسر خواهند افتاد.

یکی از مشکلات موجود با NHibernate، راه‌اندازی اولیه آن است. منظور از راه‌اندازی اولیه، نوشتن Data Access Layer برنامه با استفاده از آن است. این کار علاوه بر این که وقت‌گیر و حوصله‌بر است، کار حساسی نیز هست. چون در صورت طراحی غلط مشکلات زیادی به وجود خواهد آمد. توصیه این است که برای رفع این مشکل از پروژه‌ی Castle ActiveRecord استفاده کنید. ActiveRecord تقریباً یک Data Access Layer کامل است که کار با NHibernate را به شدت راحت‌تر می‌کند. خصوصاً این که با Castle ActiveRecord مشابه Fluent NHibernate دیگر نیازی به Xml Mapping وجود ندارد. علاوه بر این چون Castle ActiveRecord بر اساس NHibernate نوشته شده تمام امکانات NHibernate را هم هنوز می‌توان با آن استفاده کرد. مثلاً می‌توان با NHibernate.ISession به طور مستقیم در Castle ActiveRecord کار کرد.

توجه: این مطلب در ادامه نوشته‌ی «آیا ORM برای ما مناسب است؟» نوشته شده است.

‫آیا ORM برای ما مناسب است؟

یکی از دوستان می‌خواهد بداند آیا استفاده از NHibernate در یک پروژه‌ی بزرگ با توجه به تجربه‌های قبلی آن، کار درستی است یا نه. این سوال را باید به دو قسمت تقسیم کرد. اول این که آیا استفاده از ORM به طور کلی کار درستی است یا نه. و دوم این که آیا استفاده از NHibernate به عنوان ORM کار درستی است یا نه. در این نوشته به سوال اول می‌پردازیم: آیا استفاده از ORM برای شرکت ما کار درستی است؟ سوال دوم در نوشته‌ی دیگری مورد بررسی قرار خواهد گرفت.

در دنیای Object Oriented Programming کار مستقیم با دیتابیس یک معضل حساب می‌شود. چون به خاطر ماهیت رابطه‌ای بودن آنها نمی‌شود با آنها مثل object برخورد کرد. به همین خاطر ORMها به وجود آمدند تا دیتابیس را زیر خودشان مخفی کرده و آن را به شیوه‌ی مناسب object oriented به لایه‌های بالاتر تحویل دهند.

برای استفاده کامل از امکانات ORM باید همه اصول Object Oriented Programming رعایت شود. یعنی تعریف کلاس‌ها، اینترفیس‌ها و روابط بین آنها باید مطابق اصول باشد. مثلاً اگر عادت به استفاده از متغیرهای عمومی دارید، اگر متودها را فقط به صورت استاتیک می‌نویسید، اگر متودهایی می‌نویسید که گاه به ۵۰۰ خط هم می‌رسند، اگر عادت به استفاده از مفاهیم سه‌گانه OOP ندارید، اگر نمی‌دانید Design Pattern چیست و… باید روش خود را تغییر دهید در غیر این صورت استفاده از ORM نه تنها هیچ مزیتی برای شما ندارد بلکه شما را حسابی هم به دردسر خواهد انداخت.

در بحث Documentation در ORM و دیتابیس، مهم‌ترین موضوعی که با آن برخورد می‌کنید این است که دیگر اجازه استفاده از ERD ندارید. بلکه به جای آن باید از UML Class Diagram استفاده کنید. چون ERD بر اساس ماهیت رابطه‌ای است ولی Class Diagram بر اساس ماهیت Object Oriented ساخته شده. اگر افراد گروه شما به ERD عادت دارند و نمی‌توانند یا نمی‌خواهند از Class Diagram استفاده کنند، این یعنی یک زنگ خطر. چون این افراد بعدها مشکلات زیادی را به وجود خواهند آورد.

تعامل با دیتابیس یکی از بنیادی‌ترین تغییراتی است که استفاده از ORM ایجاد می‌کند. ORMها این تفکر را تبلیغ می‌کنند که عملیات داده‌ای در سمت کد اتفاق بیفتند نه در داخل دیتابیس. این یعنی حداقل استفاده از امکانات داخلی دیتابیس. به عبارت دیگر اگر می‌خواهید از ORM استفاده کرده و از همه مزایای بهره‌مند شوید باید استفاده از Stored Procedureها، Viewها، Triggerها و… را بی‌خیال شوید. حال اگر در شرکتی هستید که همه Business برنامه را از طریق Stored Procedureها، Triggerها، Viewها و… اعمال می‌کنند، بدانید که استفاده از ORM در آنجا خیلی سخت بوده و مخالفان سرسخت زیادی خواهد داشت.

تجربه‌ای که ما در شرکت قبلی داشتیم در بعضی جاها با خودش شکست به همراه داشت. البته میزان موفقیت در استفاده از ORM از نظر شخص خودم حداقل ۷۵ درصد بود. متاسفانه علت آن بخش‌های ناموفق فقر دانش خودمان در استفاده از ORM بود. مهم‌ترین آن‌ها عبارتند از:

۱- چون نتوانسته بودیم ORM خودمان را به خوبی Config کنیم دچار مشکل Performance شده و مجبور شده بودیم بعضی جاها استثنا قائل شده و از Store Procedure استفاده کنیم.

۲- در صفحات ASP.NET برای Data Binding از ObjectDataSource استفاده نکرده بودیم در نتیجه مجبور شده بودیم بیشتر کارها از جمله Paging و… را از طریق code behind انجام دهیم. این موضوع باعث حجیم شدن و پیچیده شدن بیهوده‌ی code behind شده بود. علت عدم استفاده از ObjectDataSource نا آگاهی خودمان بود ولی به هر صورت اگر از به جای ORM از ADO.NET استفاده می‌کردیم کمتر دچار این مشکلات می‌شدیم.

۳- ما برای گزارش‌گیری از MS SQL Server Reporting Services استفاده می‌کردیم. گزارشات در این سیستم به دو نوع client و server تقسیم می‌شوند. ما بلد نبودیم یا شاید هم راهی وجود نداشت که خروجی‌های objectی مثل IList را به گزارشات سروری بفرستیم. در نتیجه آنجا هم مجبور شدیم برای تهیه گزارشات به صورت مستقیم از Sql استفاده کنیم.

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


‫Escrow چیست؟

یکی از اولین گام‌های فعالیت در سایت‌های تجارت الکترونیک مثل e-Bay و vWorker فهم مفاهیم و اصطلاحات مورد استفاده در آنهاست. یکی از مفاهیم خیلی مهم در سایت vWorker که از معروف‌ترین سایت‌های Freelance است، مفهوم Escrow است.

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

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

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

مرجع: مقاله «اسکرو» در ویکی‌پدیا