مطالب
Roslyn #4
بررسی API کامپایل Roslyn

Compilation API، یک abstraction سطح بالا از فعالیت‌های کامپایل Roslyn است. برای مثال در اینجا می‌توان یک اسمبلی را از Syntax tree موجود، تولید کرد و یا جایگزین‌هایی را برای APIهای قدیمی CodeDOM و Reflection Emit ارائه داد. به علاوه این API امکان دسترسی به گزارشات خطاهای کامپایل را میسر می‌کند؛ به همراه دسترسی به اطلاعات Semantic analysis. در مورد تفاوت Syntax tree و Semantics در قسمت قبل بیشتر بحث شد.
با ارائه‌ی Roslyn، اینبار کامپایلرهای خط فرمان تولید شده مانند csc.exe، صرفا یک پوسته بر فراز Compilation API آن هستند. بنابراین دیگر نیازی به فراخوانی Process.Start بر روی فایل اجرایی csc.exe مانند یک سری کتابخانه‌های قدیمی نیست. در اینجا با کدنویسی، به تمام اجزاء و تنظیمات کامپایلر، دسترسی وجود دارد.


کامپایل پویای کد توسط Roslyn

برای کار با API کامپایل، سورس کد، به صورت یک رشته در اختیار کامپایلر قرار می‌گیرد؛ به همراه تنظیمات ارجاعاتی به اسمبلی‌هایی که نیاز دارد. سپس کار کامپایلر شروع خواهد شد و شامل مواردی است مانند تبدیل متن دریافتی به Syntax tree و همچنین تبدیل مواردی که اصطلاحا به آن‌ها Syntax sugars گفته می‌شود مانند خواص get و set دار به معادل‌های اصلی آن‌ها. در اینجا کار Semantic analysis هم انجام می‌شود و شامل تشخیص حوزه‌ی دید متغیرها، تشخیص overloadها و بررسی نوع‌های بکار رفته‌است. در نهایت کار تولید فایل باینری اسمبلی، از اطلاعات آنالیز شده صورت می‌گیرد. البته خروجی کامپایلر می‌تواند اسمبلی‌های exe یا dll، فایل XML مستندات اسمبلی و یا فایل‌های .netmudule و .winmdobj مخصوص WinRT هم باشد.
در ادامه، اولین مثال کار با Compilation API را مشاهده می‌کنید. پیشنیاز اجرای آن همان مواردی هستند که در قسمت قبل بحث شدند. یک برنامه‌ی کنسول ساده‌ی .NET 4.6 را آغاز کرده و سپس بسته‌ی نیوگت Microsoft.CodeAnalysis را در آن نصب کنید. در ادامه کدهای ذیل را به پروژه‌ی آماده شده اضافه کنید:
static void firstCompilation()
{
    var tree = CSharpSyntaxTree.ParseText("class Foo { void Bar(int x) {} }");
 
    var mscorlibReference = MetadataReference.CreateFromFile(typeof (object).Assembly.Location);
 
    var compilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);
 
    var comp = CSharpCompilation.Create("Demo")
                                .AddSyntaxTrees(tree)
                                .AddReferences(mscorlibReference)
                                .WithOptions(compilationOptions);
 
    var res = comp.Emit("Demo.dll");
 
    if (!res.Success)
    {
        foreach (var diagnostic in res.Diagnostics)
        {
            Console.WriteLine(diagnostic.GetMessage());
        }
    }
}
در اینجا نحوه‌ی کامپایل پویای یک قطعه کد متنی سی‌شارپ را به DLL معادل آن مشاهده می‌کنید. مرحله‌ی اول اینکار، تولید Syntax tree از رشته‌ی متنی دریافتی است. سپس متد CSharpCompilation.Create یک وهله از Compilation API مخصوص #C را آغاز می‌کند. این API به صورت Fluent طراحی شده‌است و می‌توان سایر قسمت‌های آن‌را به همراه یک دات پس از ذکر متد، به طول زنجیره‌ی فراخوانی، اضافه کرد. برای نمونه در این مثال، نحوه‌ی افزودن ارجاعی را به اسمبلی mscorlib که System.Object در آن قرار دارد و همچنین ذکر نوع خروجی DLL یا DynamicallyLinkedLibrary را ملاحظه می‌کنید. اگر این تنظیم ذکر نشود، خروجی پیش فرض از نوع .exe خواهد بود و اگر mscorlib را اضافه نکنیم، نوع int سورس کد ورودی، شناسایی نشده و برنامه کامپایل نمی‌شود.
متدهای تعریف شده توسط Compilation API به یک s جمع، ختم می‌شوند؛ به این معنا که در اینجا در صورت نیاز، چندین Syntax tree یا ارجاع را می‌توان تعریف کرد.
پس از وهله سازی Compilation API و تنظیم آن، اکنون با فراخوانی متد Emit، کار تولید فایل اسمبلی نهایی صورت می‌گیرد. در اینجا اگر خطایی وجود داشته باشد، استثنایی را دریافت نخواهید کرد. بلکه باید خاصیت Success نتیجه‌ی آن‌را بررسی کرده و درصورت موفقیت آمیز نبودن عملیات، خطاهای دریافتی را از مجموعه‌ی Diagnostics آن دریافت کرد. کلاس Diagnostic، شامل اطلاعاتی مانند محل سطر و ستون وقوع مشکل و یا پیام متناظر با آن است.


معرفی مقدمات Semantic analysis

Compilation API به اطلاعات Semantics نیز دسترسی دارد. برای مثال آیا Type A قابل تبدیل به Type B هست یا اصلا نیازی به تبدیل ندارد و به صورت مستقیم قابل انتساب هستند؟ برای درک بهتر این مفهوم نیاز است یک مثال را بررسی کنیم:
        static void semanticQuestions()
        {
            var tree = CSharpSyntaxTree.ParseText(@"
using System;
 
class Foo
{
    public static explicit operator DateTime(Foo f)
    {
        throw new NotImplementedException();
    }
 
    void Bar(int x)
    {
    }
}");
 
            var mscorlib = MetadataReference.CreateFromFile(typeof (object).Assembly.Location);
            var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary);
            var comp = CSharpCompilation.Create("Demo").AddSyntaxTrees(tree).AddReferences(mscorlib).WithOptions(options);
            // var res = comp.Emit("Demo.dll");
 
            // boxing
            var conv1 = comp.ClassifyConversion(
                comp.GetSpecialType(SpecialType.System_Int32),
                comp.GetSpecialType(SpecialType.System_Object)
                );
 
            // unboxing
            var conv2 = comp.ClassifyConversion(
                comp.GetSpecialType(SpecialType.System_Object),
                comp.GetSpecialType(SpecialType.System_Int32)
                );
 
            // explicit reference conversion
            var conv3 = comp.ClassifyConversion(
                comp.GetSpecialType(SpecialType.System_Object),
                comp.GetTypeByMetadataName("Foo")
                );
 
            // explicit user-supplied conversion
            var conv4 = comp.ClassifyConversion(
                comp.GetTypeByMetadataName("Foo"),
                comp.GetSpecialType(SpecialType.System_DateTime)
                );
        }
تا سطر CSharpCompilation.Create این مثال، مانند قبل است و تا اینجا به Compilation API دسترسی پیدا کرده‌ایم. پس از آن می‌خواهیم یک Semantic analysis مقدماتی را انجام دهیم. برای این منظور می‌توان از متد ClassifyConversion استفاده کرد. این متد یک نوع مبداء و یک نوع مقصد را دریافت می‌کند و بر اساس اطلاعاتی که از Compilation API بدست می‌آورد، می‌تواند مشخص کند که برای مثال آیا نوع کلاس Foo قابل تبدیل به DateTime هست یا خیر و اگر هست چه نوع تبدیلی را نیاز دارد؟


برای مثال نتیجه‌ی بررسی آخرین تبدیل انجام شده در تصویر فوق مشخص است. با توجه به تعریف public static explicit operator DateTime در سورس کد مورد آنالیز، این تبدیل explicit بوده و همچنین user defined. به علاوه متدی هم که این تبدیل را انجام می‌دهد، مشخص کرده‌است.
مطالب
یافتن تداخلات Collations در SQL Server

اگر دیتابیس خود را در طی چند سال از یک نگارش به نگارشی دیگر یا از یک سرور به سروری دیگر منتقل کرده باشید، به احتمال زیاد به مشکلات Collations هم برخورده‌اید. یکی از فیلدها Arabic_CI_AS است (بجا مانده از دوران قبل از SQL Server 2008) در یک جدول و در جدولی دیگر فیلدی تازه‌ای با Collation از نوع Persian_100_CI_AS تعریف شده است. Collations نحوه ذخیره سازی و مقایسه رشته‌ها را کنترل می‌کنند. زمانیکه یک جدول جدید را در SQL Server ایجاد می‌کنیم، اگر Collation فیلدها به صورت صریح ذکر نگردند، بر مبنای همان Collation پیش فرض دیتابیس تعریف خواهند شد.
بنابراین اگر پس از استفاده از SQL Server 2008 و تنظیم Collation پیش فرض دیتابیس به Persian_100_CI_AS ، به این موارد دقت نکنیم، دیر یا زود دچار مشکل خواهیم شد.
عملیات مرتب سازی با وجود تداخلات Collations مشکل ساز نمی‌شود (خطایی دریافت نمی‌کنید)، اما ممکن است الزاما صحیح عمل نکند. مشکل از آنجایی آغاز می‌شود که قصد داشته باشیم داده‌ها را مقایسه کنیم یا join ایی بین این دو جدول با فیلدهای ناهمگون از لحاظ Collation ایجاد نمائیم. در این حالت حتما خطاهای تداخل Collation را دریافت کرده و کوئری‌های ما اجرا نخواهند شد.
Cannot resolve collation conflict for equal to operation

یک راه حل این است که در حین join به صورت صریح collation هر دو فیلد ذکر شده را به صورت یکسان ذکر کنیم که بیشتر یک مرهم موقتی است تا راه حل اصولی. برای مثال:
SELECT ID
FROM ItemsTable
INNER JOIN AccountsTable
WHERE ItemsTable.Collation1Col COLLATE DATABASE_DEFAULT
= AccountsTable.Collation2Col COLLATE DATABASE_DEFAULT
راه دیگر این است که مشخص کنیم که Collation کدام فیلدها در دیتابیس با Collation پیش فرض دیتابیس تطابق ندارند. سپس بر اساس این لیست شروع به تغییر Collations نمائیم.
اسکریپت زیر تمام فیلدهای ناهمگون از لحاظ Collation دیتابیس جاری را برای شما لیست خواهد کرد:
DECLARE @defaultCollation NVARCHAR(1000)
SET @defaultCollation = CAST(
DATABASEPROPERTYEX(DB_NAME(), 'Collation') AS NVARCHAR(1000)
)

SELECT C.Table_Name,
Column_Name,
Collation_Name,
@defaultCollation DefaultCollation
FROM Information_Schema.Columns C
INNER JOIN Information_Schema.Tables T
ON C.Table_Name = T.Table_Name
WHERE T.Table_Type = 'Base Table'
AND RTRIM(LTRIM(Collation_Name)) <> RTRIM(LTRIM(@defaultCollation))
AND COLUMNPROPERTY(OBJECT_ID(C.Table_Name), Column_Name, 'IsComputed') = 0
ORDER BY
C.Table_Name,
C.Column_Name
برای مثال جهت تغییر Collation فیلد Serial از جدول tblArchive از نوع nvarchar با طول 200 به Persian_100_CI_AS می‌توان از دستور T-SQL زیر استفاده کرد:
ALTER TABLE [tblArchive] ALTER COLUMN [Serial] nvarchar(200) COLLATE Persian_100_CI_AS not null

نظرات اشتراک‌ها
کره‌جنوبی و ژاپن رکورددار بیشترین سرعت اینترنت در جهان
سرعت بیشتر؟! من از داتک اینترنت گرفتم. سه ماهه با 5 گیگ حجم اولیه. قبلا (تا یک ماه قبل) از ساعت 1 بامداد تا 7 صبح آن رایگان بود (در محاسبه حجم حساب نمی‌شد). الان یک ماه هست بدون اطلاع به کاربران، این ساعت شده از 2 بامداد تا 7 صبح. چون اطلاع نداشتم، مثل قبل از ساعت 1 بامداد هر شب دانلود می‌کردم. چند روز قبل دیدم که حجم 5 گیگ اولیه‌ام زودتر از موعد تمام شده! تبدیل این مساله به 2 بامداد، تقریبا زندگی من رو مختل کرده.
اشتراک‌ها
معرفی Gridify برای انجام عملیات Filtering ,Sorting ,Paging

یکی از دغدغه‌ها هنگام نوشتن یک API فیلتر کردن , سورت کردن یا دریافت اطلاعات به صورت صفحه ایست. چراکه به طور مثال برای اعمال فیلتر روی اطلاعات, ورودی ما یک رشته `string` است و تبدیل این رشته به یک query کار ساده ای نیست و نیاز دارد تا برای تک تک فیلد‌های لیست به صورت جداگدانه منطق ارتباطی آن نوشته شود. یا برای داشتن لیستی با قابلیت Paging نیاز داریم تا ابتدا تعداد کل رکورد‌ها را از دیتابیس دریافت کرده سپس بعد از محاسبه محدوده صفحه مورد نظر اطلاعات را برگردانیم.

با استفاده از Gridify میتوانیم به ساده‌ترین شکل این گونه عملیات را در برنامه‌های خود انجام دهیم و بسیاری از مشکلات  را با کمترین هزینه حل کنیم. (بخصوص زمانیکه از Web-API و SPA  استفاده میکنیم) 


معرفی Gridify برای انجام عملیات Filtering ,Sorting ,Paging
اشتراک‌ها
معرفی یکی از بهترین سایتهای کار گروهی

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

معرفی یکی از بهترین سایتهای کار گروهی
اشتراک‌ها
بازی ساز شویم یا میوه فروش؟ مسئله این است

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

بازی ساز شویم یا میوه فروش؟ مسئله این است
نظرات مطالب
روش اتصال دومین‌های ir. به یک DNS Server
با در نظر گرفتن طرح ابر ایران یا یا بهتر بگم همون اینترنت ملی سابق امکان اختلال در سرویس‌های خارجی وجود داره شما که همه چیز رو منتقل کردید به داخل شاید بهتر باشه از سرویس DNS داخلی استفاده کنید تا از مشکلات DNS احتمالی در آینده هم در امان باشیم. مشابه همین سرویس رو ابرآروان هم به صورت رایگان ارائه میده
در مورد قیمت‌های IR هم جالبه بدونید اگر از سایت‌های هاستینگ داخلی خرید کنید هزینه یکسال 5900 تومان و برای پنج سال 14600 تومان محاسبه می‌کنند. 
نظرات مطالب
رویه های ذخیره شده خوب یا بد؟!
از دیگر نکات مثبت استفاده از SP ها می‌توان به انعطاف بیشتر آنها در تغییرات روش و شیوه محاسبات در حین اجرای سیستم، اشاره کرد. به این معنا که در اتوماسیون‌های بزرگ، دائما روش‌های محاسبه بسته به خواسته مشتری و یا بخشنامه جدید در ارگان‌های دولتی در حال تغییر هستند و اگر منطق این محاسبات داخل کلاس‌های برنامه پیاده سازی شود، ما مجبوریم برای هر لحظه، ورژن جدیدی از برنامه و در حالتی بد‌تر ورژنی برای هر مشتری ایجاد کنیم. ولی با استفاده از Sp‌ها (فقط در همین موارد و نه کلیه کوئری ها) خیلی راحت و سریع می‌توان نیاز‌های مشتری را پاسخ داد.
نظرات مطالب
الگوی مشاهده‌گر Observer Pattern
یکی از مثال هایی که خودم چند روز پیش از این الگو در جاوا برای اندروید استفاده کردم این است که در بخشی از برنامه انتقال اطلاعاتی صورت میگرفت که شاید نیاز باشد هزاران آیتم در برنامه انتقال یابند که در این صورت بهتر بود که فعالیت توسط یک نوار پیشرفت نمایش داده شود و از آنجا که این انتقال برای آیتم‌ها در کلاسی جداگانه قرار داشت و در این حالت ممکن بود تکه کد نامربوط بین بخش رابط کاربری و منطق اضافه کند و وابستگی ایجاد کند از این الگو استفاده کردم. در این حالت هر وقت متد مورد نظر انتقالی انجام میداد کلاس پیشرفت را برای محاسبه درصد آگاه می‌ساخت.
نظرات مطالب
#Defensive Code in C - قسمت سوم
ایمن سازی کدها قبول؛
متد نهایی دو وظیفه رو انجام میدهد. یکی اعتبار سنجی داده‌ها و دومی محاسبه هدف نهایی در صورت ممکن.
یعنی باید تمام متدها بصورت درونی داده‌ها را خودشون اعتبار سنجی کنند؟
آیا اصل SRP رو نقض نکردیم؟
آیا اینچنین کد نوشتن‌ها باعث تکرار کد نمیشوند؟
نوشتن آزمون واحد برای متدهای چند مسولیتی به چه صورت خواهد بود؟
در پروژه واقعی با تعداد متدهای زیاد و لایه‌های متعدد به چه صورت باید رفتار کرد؟
نکته ای که قابل تأمل هست اینه که متد ما دو عدد از نوع رشته ای می‌گیرد و خروجی عددی تولید میکند. شاید با رفع این مشکل بشه کد تمیزتر و ایمن‌تری نوشت.