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

مرحله جذب:

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

مرحله انتخاب:

این مرحله برای گزینش افراد است که همگان از  آن به عنوان مرحله مصاحبه یاد می‌کنند که مورد بحث ما نیست.

مواردی که در آگهی استخدام شرکت دلفین رعایت شده بود:

»ذکر نام شرکت

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

»ذکر آدرس و شماره تماس:

دلیل اصلی برای ذکر آدرس شرکت صرفا برای بررسی وضعیت رفت و آمد از نظر شرایط ترافیک شهری و بعد مسافت یا حتی شرایط رفت و آمد با خودروی شخصی است که برای بیشتر متقاضیان مهم است. در آگهی بالا نیز این مورد رعایت شده بود.

» ذکر شرایط استخدام

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

»ذکر شرایط تخصصی متقاضیان کار:

در بخش به صورت کامل شرایط تخصصی و مهارتی افراد مورد بررسی قرار گرفته بود. در یک نگاه خوب به نظر می‌رسید ولی اگر با دقت به این بخش نگاه کنید متوجه خواهید شد به دلیل عدم نگارش صحیح موارد مورد نیاز، کمتر کسی دارای این همه توانایی است آن هم به صورت تسلط کامل. استفاده از واژه تسلط کامل باید با احتیاط انجام شود. برای مثال تسلط کامل بر VB.NET , C#.NET Windows Application . بهتر بود از یا استفاده می‌شد. به این صورت " تسلط بر VB.NET یا C#.NET  در Windows Application"

» ذکر اولویت ها

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

»ذکر آدرس وب سایت شرکت:

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

مواردی که در آگهی استخدام شرکت دلفین رعایت نشده بود:

»عدم توازن بین عنوان آگهی با محتوای آن :

در عنوان آگهی ذکر شده بود "برنامه نویس تحت وب" در حالی که در شرایط تخصصی، موردی به عنوان تسلط کامل بر برنامه نویس تحت ویندوز ذکر شده  آن هم با دو زبان Vb.Net و C#.Net

آیا منظور از تسلط کامل بر مدیریت بانک اطلاعاتی SqlServer همان DBA است؟ اگر پاسخ مثبت است در این صورت چند نفر واجد شرایط را می‌توان پیدا کرد که هم در سطح DBA باشند و هم در سطح یک برنامه نویس سطح بالا؟ اگر پاسخ منفی است بهتر بود از واژه داشتن تجربه در زمینه مدیریت بانک اطلاعاتی یا حتی آشنایی با مدیریت بانک‌های اطلاعاتی استفاده می‌شد.

مورد دیگری که تا حدودی باعث سردرگمی می‌شد این است که نیاز به تسلط کامل به Asp.Net Web Form و هم چنین به Asp.Net MVC است. چرا هردو، آن هم در سطح تسلط کامل؟

در بخش اولویت‌ها موردی ذکر شد با عنوان آشنایی با کامپوننت‌های برنامه نویسی نظیر DevExpress و Telerik  و Kendo. آیا منظور آشنایی با تمام این موارد بوده است یا فقط یکی از آن ها؟

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

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

مطالب
نحوه‌ی استفاده از کتابخانه‌ی OpenSSL در ویندوز

سؤالی شده به این مضمون : "یه الگوریتم دارم که بر طبق اون باید اعداد تصادفی خیلی بزرگ تولید کنم، اونها رو جمع و ضرب کنم. اینکه چطوری باید از dll یا lib استفاده کنم رو بلد نیستم. از VS2008 استفاده میکنم..."

سؤال در مورد زبان CPP است. کتابخانه‌ی استاندارد انجام اینگونه عملیات برای زبان‌های C و CPP ، کتابخانه‌ی OpenSSL است. البته شاید الان 100 کتابخانه دیگر را هم لیست کنید، اما کسانی که با مباحث رمزنگاری اطلاعات مدتی کار کرده باشند، بعید است سر و کارشان به این کتابخانه نیفتاده باشد و یک استاندارد در این زمینه به شمار می‌رود؛ همچنین به دلیل سورس باز بودن در اکثر سکوهای کاری موجود نیز قابل استفاده است. بنابراین فراگیری نحوه‌ی کار کردن با آن یک مزیت به شمار می‌رود. قسمتی از این کتابخانه‌ی معظم مرتبط است به کار با اعداد بزرگ. این مورد را هم جهت استفاده در الگوریتم RSA نیاز دارد.
برای استفاده از آن در ویندوز ابتدا باید OpenSSL را کامپایل کنید. کار پر دردسری است. به همین جهت یک سایت فقط به این موضوع اختصاص یافته و هربار آخرین نسخه‌ی OpenSSL را برای ویندوز کامپایل می‌کند و در اختیار علاقمندان قرار می‌دهد : +
در حال حاضر یا باید Win32 OpenSSL v1.0.0a و یا Win64 OpenSSL v1.0.0a را دریافت کنید (برنامه‌ی شما اگر 64 بیتی کامپایل شود، dll های 32 بیتی را نمی‌تواند بارگذاری کند و برعکس).

روش استفاده از کتابخانه‌ی OpenSSL در ویژوال CPP :

الف) ابتدا فایل‌های کامپایل شده‌ی فوق را دریافت و نصب کنید. اکنون برای مثال یک پوشه‌ی OpenSSL-Win32 در کامپیوتر شما با محتویات این کتابخانه باید ایجاد شده باشد(اگر نسخه‌ی 32 بیتی را دریافت کرده‌اید).
سپس به پوشه‌ی OpenSSL-Win32\lib\VC آن مراجعه کنید. در اینجا فایل‌های کتابخانه‌ای جهت استفاده در ویژوال CPP قرار گرفته‌اند. اگر از محتویات پوشه OpenSSL-Win32\lib\VC\static استفاده کنید، نیازی به توزیع فایل‌های DLL این کتابخانه نخواهید داشت و اگر از کتابخانه‌های OpenSSL-Win32\lib\VC استفاده کنید، فایل‌های dll را نیز حتما باید به همراه برنامه‌ی خود توزیع نمائید.
سه نوع فایل در آن وجود دارند. ختم شده به MD ، MT و MDd که معانی آن‌ها در مورد چند ریسمانی بودن یا خیر است (برگرفته شده از فایل faq.txt دریافتی):

Single Threaded /ML - MS VC++ often defaults to this for the release version of a new project.
Debug Single Threaded /MLd - MS VC++ often defaults to this for the debug version of a new project.
Multithreaded /MT
Debug Multithreaded /MTd
Multithreaded DLL /MD - OpenSSL defaults to this.
Debug Multithreaded DLL /MDd

ب) جهت سهولت کار، پوشه‌ی OpenSSL قرار گرفته در مسیر OpenSSL-Win32\include را در آدرس زیر کپی نمائید:
C:\Program Files\Microsoft Visual Studio 10.0\VC\include
به این صورت حین استفاده از این کتابخانه نیازی به مشخص سازی محل قرارگیری فایل‌های include نخواهد بود.

ج) اکنون یک پروژه‌ی جدید Visual C++\Win32\Win32 console application را در VS.NET آغاز کنید؛ برای مثال به نام OpenSSLTest .

د) سپس به منوی پروژه، گزینه‌ی خواص پروژه مراجعه کرده و مطابق تصاویر زیر، این فایل‌های کتابخانه‌ای را معرفی کنید (انتخاب MD یا MT یا MDd بر اساس runtime library انتخاب شده است که در تصاویر مشخص گردیده):









ه) اکنون یک مثال ساده در مورد ضرب دو عدد بزرگ به صورت زیر می‌تواند باشد:

#include "stdafx.h"
#include <openssl/bn.h>
#include <string.h>


void RotateBytes(unsigned char *in, int n)
{
unsigned char *e=in+n-1;
do {
unsigned char temp=*in;
*in++=*e;
*e-- =temp;
} while(in<e);
}

int _tmain(int argc, _TCHAR* argv[])
{
//دو عدد بزرگ جهت آزمایش
unsigned char testP[] = {0xD1,0x31,0x85,0x4D,0x00,0xD6,0x31,0x97,0x3A,0xFC,0xD2,0x27,0x02,0xEF,0xC2,0xA7};
unsigned char testA[] = {0xC7,0x1B,0x25,0x72,0x03,0xCB,0x72,0x03,0xCF,0x23,0x27,0x2D,0x00,0xD6,0x31,0x98};

//تبدیل آرایه‌های فوق به فرمت اعداد بزرگ
BIGNUM *a = BN_new();
//it should be in "big-endian" form
RotateBytes(testA, 16);
BN_bin2bn(testA, 16, a);

BIGNUM *p = BN_new();
//it should be in "big-endian" form
RotateBytes(testP, 16);
BN_bin2bn(testP, 16, p);


//ضرب این دو عدد در هم
BIGNUM *result = BN_new();
BN_CTX *ctx = BN_CTX_new();

BN_mul(result, a, p, ctx);

//نمایش نتیجه
//حاصل از چند بایت تشکیل شده؟
int num = BN_num_bytes(result);
if(num>0)
{
unsigned char *tmpdata;
if((tmpdata=(unsigned char *)malloc(num)))
memset(tmpdata, 0, num);

//تبدیل عدد با فرمت اعداد بزرگ به آرایه‌ای از بایت‌ها
BN_bn2bin(result, tmpdata);
RotateBytes(tmpdata, num);

for(int i=0; i<num; i++)
{
if(i%16==0) printf("\n");
printf("%02X ",tmpdata[i]);
}

if(tmpdata) free(tmpdata);
}


//آزاد سازی منابع
BN_free(a);
BN_free(p);
BN_CTX_free(ctx);

return 0;
}


در مورد شرح توابع کتابخانه OpenSSL به اینجا مراجع کنید : +
علت استفاده از تابع RotateBytes ، تغییر endian ورودی است.

مطالب
آشنایی با CLR: قسمت یازدهم
انتشار نوع‌ها  (Types) به یک ماژول
در این قسمت به نحوه‌ی تبدیل سورس به یک فایل قابل انتشار می‌پردازیم. کد زیر را به عنوان مثال در نظر بگیرید:
public sealed class Program {
  public static void Main() {
    System.Console.WriteLine("Hi");
  }
}
این کد یک ارجاع به نام کنسول دارد که این ارجاع، داخل فایلی به نام mscorlib.dll قرار دارد. پس برنامه‌ی ما نوعی را دارد، که آن نوع توسط شرکت دیگری پیاده سازی شده است. برای ساخت برنامه‌ی کد بالا، کدها را داخل فایلی با نام program.cs قرار داده و با دستور زیر در خط فرمان آن را کامپایل می‌کنیم:
csc.exe /out:Program.exe /t:exe /r:MSCorLib.dll Program.cs
کد بالا با سوئیچ اول می‌گوید که فایلی را با نام program.exe درست کن و با سوئیچ دوم می‌گوید که این برنامه از نوع کنسول هست.
موقعیکه کامپایلر فایل سورس را مورد بررسی قرار می‌دهد، متوجه متد writerline می‌گردد؛ ولی از آنجاکه این نوع توسط شما ایجاد نشده است و یک نوع خارجی است، شما باید یک مجموعه از ارجاعات را به کمپایلر داده تا آن نوع را در آن‌ها بیابد. ارائه این ارجاعات به کامپایلر توسط سوئیچ r/ که در خط بالا استفاده شده است، صورت می‌گیرد.


mscorlib یک فایل سورس است که شامل همه‌ی نوع‌ها، از قبیل int,string,byte و خیلی از نوع‌های دیگر می‌شود. از آنجائیکه استفاده‌ی از این نوع‌ها به طور مکرر توسط برنامه نویس‌ها صورت می‌گیرد، کمپایلر به طور خودکار این کتابخانه را به لیست ارجاعات اضافه می‌کند. به بیان دیگر خط بالا به شکل زیر هم قابل اجراست:
csc.exe /out:Program.exe /t:exe Program.cs

به علاوه از آنجایی که بقیه‌ی سوئیچ‌ها هم مقدار پیش فرضی را دارند، خط زیر هم معادل خطوط بالاست:
csc.exe Program.cs

اگر به هر دلیلی دوست ندارید که سمت mscorlib ارجاعی صورت بگیرید، می‌توانید از دستور زیر استفاده کنید:
/nostdlib

مایکروسافت موقعی از این سوئیچ بالا استفاده کرده است که خواسته است خود mscorlib را بسازد. با اضافه کردن این سوئیچ، کد مثال که حاوی شیء یا نوع کنسول است به خطا برخواهد خورد چون تعریف آن در mscorlib صورت گرفته و شما با سوئیچ بالا دسترسی به آن را ممنوع اعلام کرد‌ه‌اید و از آنجاکه این نوع تعریف نشده، برنامه ازکامپایل بازخواهد ماند.
csc.exe /out:Program.exe /t:exe /nostdlib Program.cs

بیایید نگاه دقیقتری به فایل program.exe ساخته شده بیندازیم؛ دقیقا این فایل چه نوع فایلی است؟ برای بسیاری از مبتدیان، این یک فایل اجرایی است که در هر دو ماشین 32 و 64 بیتی قابل اجراست. ویندوز از سه نوع برنامه پشتیبانی می‌کند: CUI یا برنامه‌های تحت کنسول، برنامه‌هایی با رابط گرافیکی GUI و برنامه‌های مخصوص windows store که سوئیچ‌های آن به شرح زیر است:
//CUI
/t:exe

//GUI
/t:winexe

//Winsows store App
/t:appcontainerexe

قبل از اینکه بحث را در مورد سوئیچ‌ها به پایان برسانیم، اجازه دهید در مورد فایل‌های پاسخگو یا response file صحبت کنیم. یک فایل پاسخگو، فایلی است که شامل مجموعه‌ای از سوئیچ‌های خط فرمان می‌شود. موقعی‌که csc.exe اجرا می‌شود، به فایل پاسخگویی که شما به آن معرفی کرده‌اید مراجعه کرده و فرمان را با سوئیچ‌های داخل آن اجرا می‌کند. معرفی یک فایل پاسخگو به کامپایلر توسط علامت @ و سپس نام فایل صورت می‌گیرد و در این فایل هر خط، شامل یک سوئیچ است. مثلا فایل پاسخگوی response.rsp شامل سوئیچ‌های زیر است:
/out:MyProject.exe
/target:winexe

و برای در نظر گرفتن این سوئیچ‌ها فایل پاسخگو را به کامپایلر معرفی می‌کنیم:
csc.exe @MyProject.rsp CodeFile1.cs CodeFile2.cs

این فایل خیلی کار شما را راحت می‌کند و نمی‌گذارد در هر بار کامپایل، مرتب سوئیچ‌های آن را وارد کنید و کیفیت کار را بالا می‌برد. همچنین می‌توانید چندین فایل پاسخگو داشته باشید و هر کدام شامل سوئیچ‌های مختلفی تا اگر خواستید تنظیمات کامپایل را تغییر دهید، به راحتی تنها نام فایل پاسخگو را تغییر دهید. همچنین کامپایلر سی شارپ از چندین فایل پاسخگو هم پشتیبانی می‌کند و می‌توانید هر تعداد فایل پاسخگویی را به آن معرفی کنید. در صورتیکه فایل را با نام csc.rsp نامگذاری کرده باشید، نیازی به معرفی آن نیست چرا که کامپایلر در صورت وجود، آن را به طور خودکار خواهد خواند و به این فایل global response file یا فایل پاسخگوی عمومی گویند.
در صورتیکه چندین فایل پاسخگو که به آن فایل‌های محلی local می‌گویند، معرفی کنید که دستورات آن‌ها(سوئیچ) با دستورات داخل csc.rsp مقدار متفاوتی داشته باشند، فایل‌های محلی الویت بالاتری نسبت به فایل global داشته و تنظمیات آن‌ها روی فایل global رونوشت می‌گردند.

موقعی‌که شما دات نت فریمورک را نصب می‌کنید، فایل csc.rsp را با تنظیمات پیش فرض در مسیر زیر نصب می‌کند:
%SystemRoot%\
Microsoft.NET\Framework(64)\vX.X.X

حروف x نمایانگر نسخه‌ی دات نت فریمورکی هست که شما نصب کرده‌اید. آخرین ورژن از این فایل در زمان نگارش کتاب، شامل سوئیچ‌های زیر بوده است.
# This file contains command­line options that the C#
# command line compiler (CSC) will process as part
# of every compilation, unless the "/noconfig" option
# is specified.
# Reference the common Framework libraries
/r:Accessibility.dll
/r:Microsoft.CSharp.dll
/r:System.Configuration.dll
/r:System.Configuration.Install.dll
/r:System.Core.dll
/r:System.Data.dll
/r:System.Data.DataSetExtensions.dll
/r:System.Data.Linq.dll
/r:System.Data.OracleClient.dll
/r:System.Deployment.dll
/r:System.Design.dll
/r:System.DirectoryServices.dll
/r:System.dll
/r:System.Drawing.Design.dll
/r:System.Drawing.dll
/r:System.EnterpriseServices.dll
/r:System.Management.dll
/r:System.Messaging.dll
/r:System.Runtime.Remoting.dll
/r:System.Runtime.Serialization.dll
/r:System.Runtime.Serialization.Formatters.Soap.dll
/r:System.Security.dll
/r:System.ServiceModel.dll
/r:System.ServiceModel.Web.dll
/r:System.ServiceProcess.dll
/r:System.Transactions.dll
/r:System.Web.dll
/r:System.Web.Extensions.Design.dll
/r:System.Web.Extensions.dll
/r:System.Web.Mobile.dll
/r:System.Web.RegularExpressions.dll
/r:System.Web.Services.dll
/r:System.Windows.Forms.Dll
/r:System.Workflow.Activities.dll
/r:System.Workflow.ComponentModel.dll
/r:System.Workflow.Runtime.dll
/r:System.Xml.dll
/r:System.Xml.Linq.dll

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

نکته: در صورتی که قصد ارجاعی را دارید، می‌توانید آدرس مستقیم اسمبلی را هم ذکر کنید. ولی اگر تنها به نام اسمبلی اکتفا کنید، مسیرهای زیر جهت یافتن اسمبلی بررسی خواهند شد:
  • دایرکتوری برنامه
  • دایرکتوری که شامل فایل csc.exe می‌شود. که خود فایل mscorlib از همانجا خوانده می‌شود و مسیر آن شبیه مسیر زیر است:
%SystemRoot%\Microsoft.NET\Framework\v4.0.#####

  • هر دایرکتوری که توسط سوئیچ lib/ مشخص شده باشد.
  • هر دایرکتوری که توسط متغیر محلی lib مشخص شده باشد.
استفاده از سوئیچ noconfig/ هم باعث می‌شود که فایل‌های پاسخگوی از هر نوعی، چه عمومی و چه محلی، مورد استفاده قرار نگیرند. همچنین شما مجاز هستید که فایل csc.rsp را هم تغییر دهید؛ ولی این نکته را فراموش نکنید، در صورتی که برنامه‌ی شما به سیستمی دیگر منتقل شود، تنظیمات این فایل در آنجا متفاوت خواهد بود و بهتر هست یک فایل محلی را که همراه خودش هست استفاده کنید.
در قسمت بعدی نگاه دیگری بر متادیتا خواهیم داشت.
نظرات مطالب
دات نت 4 و کلاس Lazy
کتاب مفیدی برای شروع کار و یا یادگیری برای بکار بردن C#4 بنظرتون میاد:
Addison-Wesley Essential C# 4.0 (978 Pages)
Wrox Professional C# 4 and .NET 4 (1852 Pages)
OReilly C# 4.0 in a Nutshell 4th Edition Feb 2010 (1056 Pages)
Sams C# 4.0 How To Feb 2010 (669 Pges)
Effective C# 50 Specific Ways to Improve Your C# Second Edition (342 Pges)
مطالب
Functional Programming یا برنامه نویسی تابعی - قسمت اول
 آشنایی

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


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


برنامه نویسی شیء گرا در خون برنامه نویس‌های سی شارپ جاری است؛ ما معمولا ساعت‌ها درباره اینکه چگونه میتوانیم با استفاده از ارث بری و ترتیب پیاده کلاس‌ها، یک هدف خاص برسیم، بر روی کپسوله سازی تمرکز میکنیم و انتزاع (Abstraction) و چند ریختی ( Polymorphism ) را برای تغییر وضعیت برنامه استفاده میکنیم. در این مدل همیشه احتمال این وجود دارد که چند ترد به صورت همزمان به یک ناحیه از حافظه دسترسی داشته باشند و تغییری در آن به وجود بیاورند و باعث به وجود آمدن شرایط Race Condition شوند. البته همگی به خوبی میدانیم که میتوانیم یک برنامه‌ی کاملا Thread-Safe هم داشته باشیم که به خوبی مباحث همزمانی و همروندی را مدیریت کند؛ اما یک مساله اساسی در مورد کارآیی باقی می‌ماند. گرچه Parallelism به ما کمک میکند که کارآیی برنامه خود را افزایش دهیم، اما refactor کردن کد‌های موجود، به حالت موازی، کاری سخت و پردردسر خواهد بود.


راهکار چیست؟

برنامه نویسی تابعی، یک الگوی برنامه نویسی است که از یک ایده قدیمی (قبل از اولین کامپیوتر‌ها !) برگرفته شده‌است؛ زمانیکه دو ریاضیدان، یک تئوری به نام  lambda calculus را معرفی کردند، که یک چارچوب محاسباتی می‌باشد؛ عملیاتی ریاضی را انجام می‌دهد و نتیجه را محاسبه میکند، بدون اینکه تغییری را در وضعیت داده‌ها و وضعیت، به وجود بیاورد. با این کار، فهمیدن کد‌ها آسانتر خواهد بود و اثرات جانبی را کمتر خواهد کرد، همچین نوشتن تست‌ها ساده‌تر خواهند شد.


زبان‌های تابعی

جالب است اگر زبان‌های برنامه نویسی را که از برنامه نویسی تابعی پشتیبانی میکنند، بررسی کنیم، مانند Lisp , Clojure, Erlang, Haskel، هر کدام از این زبان‌ها جنبه‌های مختلفی از برنامه نویسی تابعی را پوشش میدهند. #F یک عضو از خانواده ML می‌باشد که بر روی دات نت فریمورک در سال 2002 پیاده سازی شده. ولی جالب است بدانید بیشتر زبان‌های همه کاره مانند #C به اندازه کافی انعطاف پذیر هستند تا بتوان الگوهای مختلفی را توسط آن‌ها پیاده کرد. از آنجایی که اکثرا ما از #C برای توسعه نرم افزارهایمان استفاده میکنیم، ترکیب ایده‌های برنامه نویسی تابعی میتواند راهکار جالبی برای حل مشکلات ما باشد.


مفاهیم پایه ای

قبلا درباره توابع ریاضی صحت کردیم. در زبان‌های برنامه نویسی هم ایده همان است؛ ورودی‌های مشخص و خروجی مورد انتظار، بدون تغییری در حالت برنامه. به این مفاهیم شفافیت و صداقت توابع میگوییم که در ادامه با آن بیشتر آشنا میشویم. به این نکته توجه داشته باشید که منظور از تابع در #C فقط Method نیست؛ Func , Action , Delegate هم نوعی تابع هستند.


شفافیت توابع (Referential Transparency)

به طور ساده با نگاه کردن به ورودی‌های تابع و نام آن‌ها باید بتوانیم کاری را که انجام میدهد، حدس بزنیم. یعنی یک تابع باید بر اساس ورودی‌های آن کاری را انجام دهد و نباید یک پارامتر Global آن را تحت تاثیر قرار دهد. پارامتر‌های Global میتوانند یک Property در سطح یک کلاس باشند، یا یک شیء که وضعیت آن تحت کنترل تابع نیست؛ مانند شی DateTime. به مثال زیر توجه کنید:
public int CalculateElapsedDays(DateTime from)
{
   DateTime now = DateTime.Now;
   return (now - from).Days;
}
این تابع شفاف نیست. چرا؟ چون امروز، یک خروجی را میدهد و فردا یک خروجی دیگر را! به بیان دیگر وابسته به یک شیء سراسری DateTime.Now است.
آیا میتوانید این تابع را شفاف کنیم؟ بله!
چطور؟ به سادگی! با تغییر پارامتر‌های ورودی:
 public static int CalculateElapsedDays(DateTime from, DateTime now) => (now - from).Days;
در مثال بالا، ما وابستگی به یک شیء سراسری را از بین بردیم.


صداقت توابع (Function Honesty)

صداقت یک تابع یعنی یک تابع باید همه اطلاعات مربوط به ورودی‌ها و خروجی‌ها را پوشش دهد. به این مثال دقت کنید:
public int Divide(int numerator, int denominator)
{
   return numerator / denominator;
}
آیا این تابع شفاف است؟ بله.
آیا این همه مواردی را که از آن انتظار داریم پوشش میدهد؟ احتمالا خیر!

اگر دو عدد صحیح را به این تابع بفرستیم، احتمالا مشکلی پیش نخواهد آمد. اما همانطور که حدس میزنید اگر پارامتر دوم 0 باشد چه اتفاقی خواهد افتاد؟
var result = Divide(1,0);
قطعا خطای Divide By Zero را خواهیم گرفت. امضای این تابع به ما اطلاعاتی درباره خطاهای احتمالی نمی‌دهد.

چگونه مشکل را حل کنیم؟ تایپ ورودی را به شکل زیر تغییر دهیم:
public static int Divide(int numerator, NonZeroInt denominator)
{
   return numerator / denominator.Value;
}
NonZeroInt یک نوع ورودی اختصاصی است که خودمان طراحی کرده‌ایم که تمام مقادیر را به جز صفر، قبول میکند.

به طور کلی تمرین زیادی لازم داریم تا بتوانیم با این مفاهیم به طور عمیق آشنا شویم. در این مقاله قصد دارم جنبه‌های ابتدایی برنامه نویسی تابعی مانند  Functions as first class values ، High Order Functions و Pure Functions را مورد بررسی قرار دهم.

Functions as first-class values

ترجمه فارسی این کلمه ما را از معنی اصلی آن خیلی دور می‌کند؛ احتمالا یک ترجمه ساد‌ه‌ی آم میتواند «تابع، ارزش اولیه کلاس» باشد!
وقتی توابع first-class values باشند، یعنی می‌توانند به عنوان ورودی سایر توابع استفاده شوند، می‌توانند به یک متغیر انتساب داده شوند، دقیقا مثل یک مقدار. برای مثال:
Func<int, bool> isMod2 = x => x % 2 == 0;
var list = Enumerable.Range(1, 10);
var evenNumbers = list.Where(isMod2);
در این مثال، تابع، First-class value می‌باشد؛ چون شما می‌توانید آن را به یک متغیر نسبت دهید و به عنوان ورودی به تابع بعدی بدهید. در مدل برنامه نویسی تابعی، تلقی شدن توابع به عنوان مقدار، ضروری است. چون به ما امکان تعریف توابع High-Order را میدهد.


High-Order Functions (HOF)

توابع مرتبه بالا! یک یا چند تابع را به عنوان ورودی می‌گیرند و یک تابع را به عنوان نتیجه بر میگرداند. در مثال بالا Extension Method ، Where یک تابع High-Order می‌باشد.
پیاده سازی Where احتمالا به شکل زیر می‌باشد:
public static IEnumerable<T> Where<T>(this IEnumerable<T> ts, Func<T, bool> predicate)
{
   foreach (T t in ts)
      if (predicate(t))
         yield return t;
}
1. وظیفه چرخیدن روی آیتم‌های لیست، مربوط به Where می‌باشد.
2. ملاک تشخیص اینکه چه آیتم‌هایی در لیست باید وجود داشته باشند، به عهده متدی می‌باشد که آن را فراخوانی میکند.

در این مثال، تابع Where، تابع ورودی را به ازای هر المان، در لیست فراخوانی میکند. این تابع می‌تواند طوری طراحی شود که تابع ورودی را به صورت شرطی اعمال کند. آزمایش این حالت به عهده شما می‌باشد. اما به صورت کلی انتظار می‌رود که قدرت توابع High-Order را درک کرده باشید.


Pure Functions

توابع خالص در واقع توابع ریاضی هستند که دو مفهوم ابتدایی که قبلا درباره آن‌ها صحبت کردیم را دنبال می‌کنند؛ شفافیت و صداقت توابع. توابع خالص نباید هیچوقت اثر جانبی (side effect) ای داشته باشند. این یعنی نباید یک global state را تغییر دهند و یا از آن‌ها به عنوان پارامتر ورودی استفاده کنند. توابع خالص به راحتی قابل تست شدن هستند. چون به ازای یک ورودی، یک خروجی ثابت را بر میگردانند. ترتیب محاسبات اهمیتی ندارد! این‌ها بازیگران اصلی یک برنامه تابعی می‌باشد که می‌توانند برای اجرای موازی، محاسبه متاخر ( Lazy Evaluation ) و کش کردن ( memoization ) استفاده شوند.

در ادامه این سری مقالات، به پیاده سازی‌ها و الگوهای رایج برنامه نویسی تابعی با #C بیشتر خواهیم پرداخت.
مطالب
مبانی TypeScript؛ تنظیمات TypeScript در ویژوال استودیو
تا اینجا «نحوه‌ی نصب و راه اندازی TypeScript را در VSCode» به همراه «تنظیمات کامپایلر TypeScript» و «دریافت فایل‌های d.ts. را توسط بسته‌های NodeJS» بررسی کردیم. در ادامه قصد داریم این تنظیمات را به نگارش کامل VS.NET نیز اعمال کنیم.


به روز رسانی وابستگی‌های VS.NET

برای دریافت آخرین نگارش TypeScript نیاز است افزونه‌های آن‌را از سایت رسمی زبان TypeScript دریافت و نصب کرد:


به علاوه نصب افزونه‌ی Web Essentials نیز جهت تکمیل امکانات کار با TypeScript مانند امکان مشاهده‌ی خروجی جاوا اسکریپت تولیدی، در حین کار با فایل TypeScript فعلی توصیه می‌شود. همچنین TSLint را نیز نصب می‌کند.


افزودن فایل تنظیمات tslint

افزونه‌ی Web Essentials که Web Analyzer نیز اکنون جزئی از آن است، به همراه TSLint هم هست که کار آن ارائه راهنماهایی جهت تولید کدهای با کیفیت TypeScript است. گزینه‌های آن‌را در منوی Tools -> Options می‌توانید مشاهده کنید:


برای بازنویسی تنظیمات آن (در صورت نیاز) فایل جدیدی را به نام tslint.json به ریشه‌ی پروژه (کنار فایل web.config) اضافه کنید. فایل پیش فرض آن چنین شکلی را دارد:
settings-defaults/tslint.json
و یک نمونه‌ی اصلاح شده‌ی آن به صورت ذیل است که می‌تواند به ریشه‌ی پروژه کپی شود:
tslint.json


تنظیمات کامپایلر TypeScript در VS.NET

هرچند قالب افزودن یک پروژه‌ی جدید TypeScript نیز به همراه نصب بسته‌های TypeScript به لیست پروژه‌های موجود اضافه می‌شود، اما عموما نیاز است تا فایل‌های ts. را به یک پروژه‌ی وب موجود اضافه کرد. بنابراین، یک پوشه‌ی جدید را به برای مثال به نام TypeScript ایجاد کرده و بر روی آن کلیک راست کنید. سپس گزینه‌ی Add->new item را انتخاب کرده و در اینجا TypeScript را جستجو کنید:


پس از اضافه شدن اولین فایل ts. به پروژه، دیالوگ زیر نیز ظاهر خواهد شد:


در اینجا جستجوی فایل‌های d.ts. را پیشنهاد می‌دهد. فعلا بر روی No کلیک کنید. این‌کار را در ادامه انجام خواهیم داد.
پس از افزودن اولین فایل ts. به پروژه، اگر به خواص پروژه‌ی جاری مراجعه کنید، برگه‌ی جدید تنظیمات کامپایلر TypeScript را مشاهده خواهید کرد:


با این تنظیمات در مطلب «تنظیمات کامپایلر TypeScript» پیشتر آشنا شده‌اید. برای مثال فرمت خروجی جاوا اسکریپت آن ES 5 باشد و یا در اینجا نوع‌های any که به صورت صریح any تعریف نشده‌اند، ممنوع شده‌است (تیک پیش فرض آن‌را بردارید). نوع ماژول‌های تولیدی نیز به commonjs تنظیم شده‌است.
همچنین در اینجا می‌توانید گزینه‌ی redirect JavaScript output to directory را هم مثلا به پوشه‌ی Scripts واقع در ریشه‌ی پروژه تنظیم کنید تا فایل‌های js. نهایی را در آن‌جا قرار دهد.

پس از این تنظیمات اولیه، به منوی tools->options مراجعه کرده و گزینه‌ی کامپایل فایل‌های ts. ایی را که به solution explorer اضافه نشده‌اند، نیز فعال کنید:


اعمال این تنظیمات نیاز به یکبار بستن و گشودن مجدد پروژه را دارد.


فعال سازی کامپایل خودکار فایل‌های ts. پس از ذخیره‌ی آن‌ها

پس از اعمال تغییرات فوق، اگر فایل ts. ایی را تغییر داده و ذخیره کردید و بلافاصله خروجی js. آن‌را مشاهده نکردید (این فایل‌ها در پوشه‌ی TypeScriptOutDir تنظیمات ذیل ذخیره می‌شوند و برای مشاهده‌ی آن‌ها باید گزینه‌ی show all files را در solution explorer فعال کنید)، فایل csproj پروژه‌ی جاری را در یک ادیتور متنی باز کرده و مداخل تنظیمات تنظیم شده‌ی در قسمت قبل را پیدا کنید. در اینجا نیاز است مدخل جدید TypeScriptCompileOnSaveEnabled را به صورت دستی اضافه کنید:
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
  <TypeScriptModuleKind>commonjs</TypeScriptModuleKind>
 <TypeScriptCompileOnSaveEnabled>True</TypeScriptCompileOnSaveEnabled>
  <TypeScriptOutDir>.\Scripts</TypeScriptOutDir>
  <TypeScriptNoImplicitAny>True</TypeScriptNoImplicitAny>  
  <TypeScriptTarget>ES5</TypeScriptTarget>  
  <TypeScriptRemoveComments>false</TypeScriptRemoveComments>
  <TypeScriptOutFile></TypeScriptOutFile>
  <TypeScriptGeneratesDeclarations>false</TypeScriptGeneratesDeclarations>
  <TypeScriptSourceMap>true</TypeScriptSourceMap>
  <TypeScriptMapRoot></TypeScriptMapRoot>
  <TypeScriptSourceRoot></TypeScriptSourceRoot>
  <TypeScriptNoEmitOnError>true</TypeScriptNoEmitOnError>  
</PropertyGroup>
پس از این تغییرات بدیهی است یکبار باید پروژه را بسته و مجددا بارگذاری نمائید.


رفع مشکل عدم کامپایل پروژه

زمانیکه افزونه‌های TypeScript را نصب کنید و تنظیمات فوق را اعمال نمائید، در دو حالت ذخیره‌ی یک فایل ts و یا کامپایل کل پروژه، فایل‌های js تولید خواهند شد. اما ممکن است نگارش نصب شده‌ی بر روی سیستم شما ناقص باشد و چنین خطایی را در حین کامپایل پروژه دریافت کنید:
 Your project file uses a different version of the TypeScript compiler and tools than is currently installed on this machine.  
No compiler was found at C:\Program Files (x86)\Microsoft SDKs\TypeScript\1.8\tsc.exe.
You may be able to fix this problem by changing the <TypeScriptToolsVersion> element in your project file.
اگر این خطا را دریافت کردید، سریع‌ترین راه رفع آن به صورت زیر است:
الف) ابتدا به تمام مسیرهای ذیل (در صورت وجود) مراجعه کرده و پوشه‌ی TypeScript را تغییر نام دهید (یا کلا آن‌را حذف کنید):
 C:\Program Files (x86)\Microsoft SDKs
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v12.0\
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v14.0\
ب) سپس نصاب افزونه‌ی TypeScript را مجددا اجرا کنید. اینبار گزینه‌ی repair ظاهر می‌شود. با ترمیم صورت گرفته، مشکل فوق برطرف خواهد شد. این گزینه‌ی repair را در کنترل‌پنل و قسمت add/remove programs هم می‌توانید پیدا کنید (اگر فایل نصاب افزونه را حذف کرده‌اید).


اصلاح شماره نگارش کامپایلر TypeScript خط فرمان ویژوال استودیو

در فایل C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools\VsDevCmd.bat که مربوط به خط فرمان VS.NET است، شماره نگارش TypeScript به 1.5 تنظیم شده‌است که نیاز به اصلاح دستی دارد؛ برای مثال تنظیم آن به نگارش 1.8 به صورت زیر است:
 @rem Add path to TypeScript Compiler
@if exist "%ProgramFiles%\Microsoft SDKs\TypeScript\1.8" set PATH=%ProgramFiles%\Microsoft SDKs\TypeScript\1.8;%PATH%
@if exist "%ProgramFiles(x86)%\Microsoft SDKs\TypeScript\1.8" set PATH=%ProgramFiles(x86)%\Microsoft SDKs\TypeScript\1.8;%PATH%
اگر از VS 2013 استفاده می‌کنید، چنین تنظیمی در فایل C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Tools\VsDevCmd.bat آن نیز وجود دارد که به نگارش 1 تنظیم شده‌است و این مورد هم باید اصلاح شود (تنظیمات آن دقیقا مانند تنظیم فوق است).


تداخل ReSharper با شماره نگارش TypeScript نصب شده

برای نمونه اگر بخواهیم از decorators استفاده کنیم، یک چنین خطایی نمایش داده می‌شود:


هرچند در ابتدای بحث، آخرین نگارش TypeScript برای دریافت معرفی شده‌است، اما پس از نصب آن، ممکن است هنوز خطای استفاده از نگارش قدیمی 1.4 را مشاهده کنید. علت آن به نصب بودن ReSharper بر می‌گردد:
به منوی ReSharper و سپس گزینه‌ی Options آن مراجعه کنید.
 ReSharper -> Options -> Code Editing -> TypeScript -> Inspections -> Typescript language level

در اینجا می‌توان نگارش TypeScript مورد استفاده را تغییر داد. این شماره‌ها، نگارش‌هایی هستند که ReSharper از آن‌ها پشتیبانی می‌کند و نه شماره‌ای که نصب شده‌است.

و یا حتی می‌توان به صورت کامل فایل‌های ts را از کنترل ReSharper خارج کرد:
 Tools -> Options -> ReSharper Options -> Code Inspection -> Settings -> File Masks to Skip -> add *.ts
این مورد زمانی مفید خواهد بود که شماره نگارش فعلی TypeScript، از شماره نگارش پشتیبانی شده‌ی توسط ReSharper بالاتر باشد. در این حالت ممکن است syntaxهای جدید زبان TypeScript را ReSharper به صورت خطا اعلام کند که اشتباه است. بنابراین باید به ReSharper اعلام کرد که از این فایل‌ها صرفنظر کند. برای نمونه در زمان نگارش این مطلب، جهت کار با decorators، حتما نیاز است ReSharper را جهت حذف بررسی فایل‌های ts تنظیم کرد و گرنه ذیل کدهای مرتبط، خطوط قرمز نمایش خطا را مشاهده خواهید کرد که با توجه به کامپایلر جدید موجود، بی‌مورد است.


افزودن فایل tsconfig.json به پروژه

همانطور که در مطلب «تنظیمات کامپایلر TypeScript» نیز مطالعه کردید، روش دیگری نیز برای ذکر تنظیمات ویژه‌ی کامپایلر، خصوصا مواردی که در برگه‌ی خواص پروژه هنوز اضافه نشده‌اند، با استفاده از افزودن فایل ویژه‌ی tsconfig.json وجود دارد.
پشتیبانی کاملی از فایل‌های tsconfig.json در پروژه‌های VS 2015 با ASP.Core 1.0 وجود دارد و حتی گزینه‌ای در منوی add->new item برای آن درنظر گرفته شده‌است.
اگر گزینه‌ی فوق را در لیست موارد add->new item پیدا نمی‌کنید (تحت عنوان TypeScript JSON Configuration File)، مهم نیست. تنها کافی است فایل جدیدی را به نام tsconfig.json به ریشه‌ی پوشه‌ی فایل‌های ts خود اضافه کنید؛ با این محتوا:
 {
    "compilerOptions": {
         "target": "es5",
         "outDir": "../Scripts",
         "module": "commonjs",
         "sourceMap": true,
         //"watch": true, // JsErrorScriptException (0x30001)
         //"compileOnSave": true, // https://github.com/Microsoft/TypeScript/issues/7362#issuecomment-196586037
         "experimentalDecorators": true,
         "emitDecoratorMetadata": true
    }
}
حتی اگر از VS 2013 هم استفاده می‌کنید، این فایل توسط کامپایلر tsc شناسایی شده و استفاده می‌شود. برای آزمایش آن، گزینه‌ای غیرمتعارف را به گزینه‌های موجود اضافه کرده و سپس پروژه را کامپایل کنید. بلافاصله خطایی را در لیست خطاهای کامپایل پروژه دریافت خواهید کرد.
در اینجا نیازی به استفاده از گزینه‌ی watch نیست و ممکن است سبب بروز خطای JsErrorScriptException (0x30001) شود. قرار است این مشکل در نگارش‌های بعدی افزونه‌ی TypeScript مخصوص VS.NET برطرف شود.


افزودن فایل‌های d.ts. از طریق نیوگت

به ازای هر کتابخانه‌ی جاوا اسکریپتی معروف، یک بسته‌ی نیوگت تعاریف نوع‌های TypeScript آن هم وجود دارد.
یک مثال: فرض کنید می‌خواهیم فایل d.ts. کتابخانه‌ی jQuery را اضافه کنیم. برای این منظور jquery.typescript را در بین بسته‌های نیوگت موجود، جستجو کنید:


برای سایر کتابخانه‌ها نیز به همین صورت است. نام کتابخانه را به همراه typescript جستجو کنید.
اشتراک‌ها
تبدیل کدهای Java به #C

When C# started back in 2001, Java and C# were similar languages. But in the last 20 years, C# has quickly evolved in its unique way.  

تبدیل کدهای Java به #C
اشتراک‌ها
ReSharper 2023.2 منتشر شد

ReSharper 2023.2: More C#, C++ 20, And C++ 23 Features, the Ability To Create And Navigate Through Unit Tests, Predictive Debugger Mode, And More 

ReSharper 2023.2 منتشر شد