‫آیا 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 درصد خیلی کمی از سرعت برنامه را کاهش می‌دهد، تغییرات زیادی را در روش کار می‌دهد و نیاز زیادی به آموزش و مطالعه دارد، اما در مجموع هزینه‌های تولید را کاهش می‌دهد، نگهداری کد را راحت‌تر می‌کند، تعداد باگ‌ها را کاهش می‌دهد و در نهایت هم منافع کارفرما و مدیریت را با خود به همراه دارد و هم رضایت برنامه‌نویسان را.

Dependency Injection

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

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

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

روند طراحی و توسعه نرم‌افزار طی ده سال گذشته حتی در همین ایران خودمان هم تغییرات زیادی داشته. آن زمان یعنی حدود سال ۷۹ شمسی مردم تازه از شر 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 است و … اما متاسفانه هنوز خیلی‌ها هستند که خود را از لذت و کارایی عصر جدید محروم کرده‌اند. به نظر من تنها عاملی که باعث می‌شود این طور افراد همچنان به استفاده از روش‌های قدیمی ادامه دهند عدم آگاهی نسبت به روش‌های جدید است. چون هیچ مدیر پروژه یا رییس شرکتی دوست ندارد کاری را که می‌شود در شش ماه انجام داد در هشت ماه انجام دهد و نهایتاً هم کدی را تحویل بگیرد که نگهداری و توسعه آن خیلی هم سخت باشد. به همین خاطر به این طور افراد توصیه می‌گردد اگر هم از روش‌های قدیمی خیلی هم راضی هستند اقلاً مطالعه‌ای در مورد روش‌های جدید و مزایای آن داشته باشند.