2011/03/30

‫کار با git


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

اگر شما هم می‌خواهید کار با git را خیلی سریع شروع کنید بهتر است یک فضای git در assembla.com (این سایت امکان ایجاد repo خصوصی را فراهم می‌کند) ایجاد کرده، Git Extensions یا msysgit را نصب و سپس بر اساس راهنمای git svn crash و instructions خود assembla.com کارتان را شروع کنید. مقداری از اطلاعات مفید:

* git و دستورات خط فرمانی آن خیلی شبیه به svn هستند. با این تفاوت که در git هر کسی برای خودش یک repo دارد و می‌تواند مدام با repoهای دیگر اعضای گروه push و pull کند.

* تعدادی از دستورات git عبارت هستند از git status، git commit -a، git add و git diff. به شباهت آنها با svn توجه کنید.

* شما در git هر وقت که کارتان تمام شد تغییرات را commit می‌کنید. هر وقت هم که خواستید این تغییرات را به repo دیگران بفرستید یا تغییرات repo افراد دیگر را دریافت کنید باید از عملیات pull و push استفاده کنید.

* مدل branch و tag در git کمی فرق کرده.

* git هم add-inهایی هم برای Visual Studio و هم برای Windows Explorer دارد.

* در git شماره versionها مثل svn یکی یکی بالا نمی‌رود بلکه به صورت عددی هگزا دسیمال مشابه Guid است.

* برای شروع کار با یک مخزن دیگر باید با استفاده از git clone یک نسخه از آن را در کامپیوتر خودتان دریافت کنید. این دستور مشابه svn checkout است.

* در git هم می‌توان یک repo را به طور قراردادی repo مرکزی فرض کرد و افراد را ملزم به push/pull با آن کرد.

* از اسم git نترسید، امکانات خوبی دارد!




2011/03/28

زندگی و فناوری

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

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




2011/03/26

‫مشکل با EnableSEOPaging

یکی از امکانات کنترل گرید تلریک یعنی RadGrid امکان SEO friendly بودن مکانیزم Paging آن می‌باشد. به این معنی که هر کدام از Pageهای گرید، URL مختص به خودشان را دارند. به عبارت دیگر با وارد کردن URL صفحه می‌توان به همان Page متناظر رسید. این امکان در کنترل استاندارد GridView وجود ندارد.

متاسفانه یکی از مشکلاتی که EnableSEOPaging ایجاد می‌کند پاک شدن دیگر کنترل‌های موجود در صفحه به هنگام رفت و آمد بین Pageهای مختلف گرید است. یعنی اگر از صفحه ۱ به صفحه ۲ بروید همه اطلاعات داخل دیگر کنترل‌های صفحه از بین می‌روند. البته این رفتار به نوعی منطقی است و از طبیعت آن ناشی می‌شود.

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




2011/03/20

نوروز ۱۳۹۰


فرا رسیدن نوروز ۱۳۹۰ را از طرف خودم و خانواده‌ام به همه دوستان، همکاران، خوانندگان این وبلاگ و تمامی اعضای خانواده آنها از جمله:

ناصر حاجلو، مسعود رمضانی، وحید نصیری، مجید آواژ (بهساد)، ایمان نعمتی (فراسان)، سید علا سبزپوش، علی اقدم، کاوه یزدی نژاد، سهیل رشیدی (iDevCenter)، هادی اسکندری، کیانوش آل شیخ، امید امیرلو، امیر مهرانی (The Coach)، علی واحد (رادمان)، شایان شلیله، حسین فکوری نژاد، محمد شمس، امیر قاضیات (AmirGT)، صالح سوزنچی، ؟ غفوری، حسین ملایی، حسین معصومی، احمد رضا خرمشکوه، حمید رضا محمدی (گزیر)، مهدی هاشمی نژاد، سالار خلیل زاده، اسد صفر زاده، مهدی عسگری (مجله برنامه‌نویس)، مسعود دانش پور، علیرضا فاتحی، مجید افرا، مهدی طلایی، مهدی نیکبخت، سعید مقیمی، کلیه همکاران در شرکت فعلی و شرکت‌های قبلی و بقیه

تبریک گفته و برای همگی سالی بهتر از سال پیش آرزو می‌کنم.




2011/03/18

شباهت برنامه‌نویسی و آشپزی در ایران

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

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




2011/03/16

‫مشکلات نوع داده DateTime در NHibernate

در NHibernate فیلدهایی که از نوع DateTime تعریف می‌شوند دارای مشکلاتی هستند. از جمله:

۱- اگر به جای DateTime?‎ (نوع nullable) از DateTime استفاده کنید، به خاطر این که SQL Server Min. DateTime با ‎.Net Min DateTime تفاوت دارد، آبجکت خود به خود dirty شده و احتمالاً یک update اضافه به سیستم تحمیل خواهد شد. ±


۲- DateTimeهایی که از طریق NHibernate ذخیره می‌شوند دقت پایین‌تری نسبت به SQL دارند. ±

۳- متفاوت بودن دقت NHibernate و SQL ممکن است باعث dirty شدن خود به خود آبجکت هم بشود. ±




2011/03/14

Entity auditing in CastleActiveRecord

In my Castle ActiveRecord based application I have a base class named ARSuperClass that all my domain entities except than EntityLogger inherit from it instead of inheriting from ActiveRecordBase. I have ModifyDate and CreateDate fields in ARSuperClass that must be updated each time an entity is created or updated. Additionally each creation/updating operations must be logged in EntityLogger too.


In first solution I overrode OnSave and OnUpdate then changed ModifyDate and CreateDate in them and also added a new record to EntityLogger. This solution was working but with each entity update, two updates were occurring. It was because with changing audit fields, the object went dirty again and so another update was needed.

In second solution I replaced OnSave with BeforeSave and replace OnUpdate with OnFlushDirty. This solved duplicate updates with entity creation but entity updates were still generating two updates.

In third solution I searched for something like BeforeUpdate but Castle ActiveRecord didn't have such a thing. So I used NHibernate's IPreUpdateEventListener and all my problems get solved.

For more info about how to use NHibernate event listener in Castle ActiveRecord go here.




2011/03/12

‫افزایش Performance در NHibernate با استفاده از اپراتورهای Projection

یکی از راه‌های توصیه شده برای افزایش Performance در Queryهای دیتابیس، پرهیز از استفاده‌های بی‌مورد از select * from some_table می‌باشد. راه حل توصیه شده استفاده از projection و برگرداندن صرفاً ستون‌های مورد نیاز از دیتابیس است. مثلاً باید از select col1, col2 from some_table استفاده شود.

در همین راستا LINQ-to-NHibernate هم پشتیبانی خوبی از اپراتورهای Projection در LINQ دارد. به نمونه زیر توجه کنید:
var query = from
                    entity in ActiveRecordLinq.AsQueryable()
                  where
                     entity.Prop1 == "123"
                  select
                      new SomeEntityDTO(Prop1, Prop2);

List list = query.ToList();
اسکریپت SQL تولید شده از query بالا فقط شامل Prop1 و Prop2 خواهد بود. توجه شود query بالا با استفاده Castle ActiveRecord نوشته شده ولی با LINQ-to-NHibernate اصلی هیچ فرقی ندارد.




2011/03/10

‫محدودیت‌های Castle ActiveRecord

Castle ActiveRecord یک کتابخانه مفید برای استفاده از NHibernate است. این کتابخانه هم کار mapping را مشابه Fluent NHibernate ساده می‌کند و هم کار مدیریت session و خیلی کارهای دیگر را خودش مدیریت می‌کند. به طوری که استفاده از NHibernate بسیار ساده‌تر شود. Castle ActiveRecord در واقع پیاده‌سازی Design Patternی به همین نام یعنی Active Record است. با این که Castle ActiveRecord کار با NHibernate را بسیار ساده‌تر کرده ولی به خاطر همین سادگی، محدودیت‌هایی هم نسبت به استفاده مستقیم از NHibernate دارد. از جمله:

۱- الگوی Active Rercord به طور کلی مورد انتقاد است. بعضی‌ها معتقدند الگوی Active Record ناکارآمد است و می‌توان به جای آن از الگوهای بهتری مثل Repository Pattern استفاده کرد. دقت کنید که الگوی پیش‌فرض Castle ActiveRecord همان Active Record است اما می‌توان با الگوهای دیگری از جمله Unit of Work هم با آن کار کرد.

۲- در فرایند Schema Update آن نمی‌توان اسکریپت‌های update را قبل از اجرا دید.

۳- Second Level Cache در بیشتر متودهای کلاس ActiveRecordBase امکان پذیر نیست، از جمله بیشتر overloadهای متود FindAll. برای فعال بودن Second Level Cache باید در Criteriaها از SetCachable(true)‎ استفاده شود.

۴- Second Level Cache ظاهراً در ActiveRecordLinq هم به همان دلیل قبلی غیر فعال است. در LINQ موجود در NHibernate چه در provider قدیمی چه در NH 3 راه حل‌هایی وجود دارد ولی ظاهراً نمی‌توان از آنها در Castle ActiveRecord استفاده کرد.



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




2011/03/09

Second Level Cache in Castle ActiveRecord

Second level cache is different than first level cache. It acts on session factory level not each individual session. In order to setup second level cache in a Castle ActiveRecord application consider following points:

1. Settings of second level cache in Castle ActiveRecord is basically as same as NHibernate.

2. In addition of web.config/app.config settings, caching must enabled in entities too.

3. Caching in collections and queries must be considered too.

4. Each operation must be wrapped in a transaction.

5. FindAll series of Castle ActiveRecord does not allow query caching. You must use your own custom build of Castle ActiveRecord.

6. For more info go here, here and here.




2011/03/08

طرح اهدا کامپیوتر

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

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

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




پ. ن.:
من شماره موبایل مدیر موسسه مهر گیتی را دیشب پیدا کردم. اگر کسی لازم داشت بگوید.




2011/03/06

پیغام خطای کشنده

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

به تازگی یکی از این پیغام خطاهای کشنده برای من اتفاق افتاد. زمانی که در حال فعال‌سازی Caching سطح دوم برای یک برنامه‌ی مبتنی بر Castle ActiveRecord بودم دچار خطای زیر شدم:

Unable to cast object of type 'NHibernate.Caches.SysCache.SysCacheProvider' to type 'NHibernate.Cache.ICacheProvider'.


NHibernate.Caches.SysCache نام اسمبلی است که قابلیت Second Level Cache را به NHibernate و Castle Active Record اضافه می‌کند. ظاهر امر نشان می‌داد که بین اسمبلی‌ها مورد استفاده ناهمخوانی نسخه‌ای وجود دارد. مثلا NHibernate من نسخه 2.1 است ولی SysCache مورد استفاده نسخه 3.0 است. به همین دلیل بارها و بارها نسخه‌های متفاوت NHibernate و Castle و SysCache را از SourceForge دریافت کردم ولی مشکل حل نشد. سعی کردم به جای SysCache از دیگر Cache Providerها استفاده کنم ولی آن هم نشد. در ادامه این سعی و تلاش‌ها چندین بار تنظیمات Caching مورد استفاده را در web.config و mappingها چک کردم، سورس‌های Castle و SysCache را خودم کامپایل کردم و حتی به فکر افتادم خودم یک Cache Provider ساده بنویسم اما مشکل حل نشد که نشد.

خلاصه این که در اوج ناامیدی بودم که در یکی از آن «لحظات طلایی» متوجه علت خطا شدم. چون تعداد Assemblyهای مورد استفاده در ارتباط با NHibernate و Castle زیاد بود، یکی از دوستان آنها را با هم merge کرده بود تا یک اسمبلی واحد تشکیل گردد. من هم اسمبلی NHibernate.Caches.SysCache را در کنار اسمبلی فوق‌الذکر گذاشته بودم و در تنظیم cache.provider_class نام اسمبلی NHibernate.Caches.SysCache را ذکر کرده بودم، در حالی که باید اسمبلی NHibernate.Caches.SysCache را با مجموعه قبلی merge (با استفاده از ilmerge.exe) کرده و در cache.provider_class نام اسمبلی حاصل از merge را ذکر می‌کردم!




2011/03/04

‫کتاب LINQ in Action


یکی از عادت‌های من در این وبلاگ نوشتن درباره‌ی کتاب‌هایی است که خوانده‌ام. یکی از کتاب‌هایی که مدت‌ها پیش خواندن آن را شروع کردم کتاب LINQ in Action است. این کتاب را برای تکمیل اطلاعاتم راجع به LINQ شروع کردم چون حس می‌کردم چیزهایی که راجع به LINQ از کتاب Pro C# 2008 and the .NET 3.5 Platform یاد گرفته بودم کافی نیست.

با توجه به این که هدف من از یادگیری LINQ صرفاً استفاده از LINQ-to-NHibernate بود، در نتیجه فقط ۵ فصل اول کتاب که راجع به مقدمات LINQ و Linq-to-Objects را مطالعه و بقیه فصول (۸ فصل) که راجع به LINQ-to-XML و LINQ-to-SQL بودند را بی‌خیال شدم. البته این کتاب کمی قدیمی است و در سال ۲۰۰۸ منتشر شده یعنی زمانی که LINQ-to-EF وجود نداشته است.

چیزی که من از خواندن همان ۵ فصل متوجه شدم این بود که یادگیری کامل LINQ بیشتر در کار عملی امکان پذیر است تا مطالعه صرف. از طرفی مطالب مربوط به LINQ به زعم من خیلی فرار هستند و اگر در در عمل و به طور مداوم استفاده نشوند خیلی زود فراموش می‌گردند.

نمی‌دانم از ۲۰۰۸ تا حالا کتاب بهتری برای LINQ منتشر شده یا نه ولی به هر صورت خواندن این کتاب را توصیه می‌کنم به کسانی که می‌خواهد LINQ به طور علمی و کاملاً دقیق بیاموزند.

پ.ن.: در این لینک هم چند کتاب دیگر برای LINQ معرفی شده.




2011/03/02

First level cache in Castle ActiveRecord

While I was trying to use first level cache in a Castle ActiveRecord based application I found some points that like to share:

1. First level cache is alive within a single session (NHibernate's ISession) only.

2. First level cache is enabled by default and can not be disabled.

3. If you don't use SessionScope properly you may have more than one session per ASP.NET web request. So you will not profit from first level cache. SessionScope is Castle ActiveRecord's way for NHibernate's ISession. Correct way to use SessionScopt in an ASP.NET web application is to use SessionScopeWebModule as a httpModule. More info could be found here.

4. First level cache can be used only by NHibernate Load and Get methods. So with Castle ActiveRecord you can only use Find and TryFind method. FindAll and other methods can not benefit from first level cache because they use ICriteria internally.


More info about NHibernate caching is available here.




2011/03/01

یاس فلسفی یک برنامه‌نویس

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

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

در شرکت (های) جدیدتر هر روز بیشتر از دیروز حس می‌کردیم که یک جای کار می‌لنگد. هر چقدر که روش انجام کارها را با اصول لاینفک مهندسی نرم‌افزار مقایسه می‌کردیم می‌دیدیم که اصول کجا و روش انجام ما کجا. هر روز بیشتر از روز قبل سعی می‌کردیم رییس شرکت را راضی کنیم که از روش‌های اصولی و تکنولوژی‌های روز استفاده کند اما رییس هم همیشه دلیل خاص خودش را داشت…

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



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