‫کار با 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 نترسید، امکانات خوبی دارد!

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

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

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

‫مشکل با EnableSEOPaging

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

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

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

نوروز ۱۳۹۰

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

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

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

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

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

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

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

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

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

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

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

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.

‫افزایش 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 اصلی هیچ فرقی ندارد.

‫محدودیت‌های 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 اضافه شود.

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.