مطالب
زیباتر کد بنویسیم

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


1- سعی کنید میزان تو در تو بودن کدهای خود را محدود کنید.
لطفا به مثال زیر دقت نمائید:

void SetA()
{
if(a == b)
{
foreach(C c in cs)
{
if(c == d)
{
a = c;
}
}
}
}

توصیه شده است فقط یک سطح تو در تو بودن را در یک تابع لحاظ کنید. تابع فوق 4 سطح تو رفتگی را نمایش می‌دهد (برای رسیدن به a=c باید چهار بار از tab استفاده کنید). برای کاهش این تعداد سطح می‌توان به صورت زیر عمل کرد:

void SetA()
{
if(a != b)
return;

foreach(C c in cs)
a = GetValueOfA(c);
}

TypeOfA GetValueOfA(C c)
{
if(c == d)
return c;

return a;
}

خواناتر نشد؟!

افزونه‌های CodeRush و refactor pro مجموعه‌ی DevExpress از لحاظ مباحث refactoring در ویژوال استودیو حرف اول را می‌زنند. فقط کافی است برای مثال قطعه کد if داخلی را انتخاب کنید، بلافاصله سه نقطه زیر آن ظاهر شده و با کلیک بر روی آن امکان استخراج یک تابع از آن‌را برای شما به سرعت فراهم خواهد کرد.



مثالی دیگر:

if (foo) {
if (bar) {
// do something
}
}

به صورت زیر هم قابل نوشتن است (جهت کاهش میزان nesting):

if (foo && bar) {
// do something
}

افزونه‌ی Resharper امکان merge خودکار این نوع if ها را به همراه دارد.



و یا یک مثال دیگر:
میزان تو در تو بودن این تابع جاوا اسکریپتی را ملاحظه نمائید:

function findShape(flags, point, attribute, list) {
if(!findShapePoints(flags, point, attribute)) {
if(!doFindShapePoints(flags, point, attribute)) {
if(!findInShape(flags, point, attribute)) {
if(!findFromGuide(flags,point) {
if(list.count() > 0 && flags == 1) {
doSomething();
}
}
}
}
}
}

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

function findShape(flags, point, attribute, list) {
if(findShapePoints(flags, point, attribute)) {
return;
}

if(doFindShapePoints(flags, point, attribute)) {
return;
}

if(findInShape(flags, point, attribute)) {
return;
}

if(findFromGuide(flags,point) {
return;
}

if (!(list.count() > 0 && flags == 1)) {
return;
}

doSomething();
}

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

void UpdateBankAccountTransactionListWithYesterdaysTransactions()
//or?
void UpdateTransactions()

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

//function thisReallyHandyFunction() {
// someMagic();
// someMoreMagic();
// magicNumber = evenMoreMagic();
// return magicNumber;
//}

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

از کامنت‌های نوع زیر پرهیز کنید که بیشتر سبب رژه رفتن روی اعصاب خواننده می‌شود تا کمک به او! (خواننده را بی‌سواد فرض نکنید)

// Get the student's id
thisId = student.getId();

کامنت زیر بی معنی است!

// TODO: This is too bad. FIX IT!

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


4- عدم استفاده از عبارات شرطی بی‌مورد هنگام بازگشت دادن یک مقدار bool:
مثال زیر را درنظر بگیرید:

if (foo>bar) {
return true;
} else {
return false;
}

آن‌را به صورت زیر هم می‌توان نوشت:

return foo>bar;

5- استفاده از متغیرهای بی مورد:
برای مثال:

Something something = new Something(foo);
return something;

که می‌شود آ‌ن را به صورت زیر هم نوشت:

return new Something(foo);

البته یکی از خاصیت‌های استفاده از افزونه‌ی Resharper ویژوال استودیو، گوشزد کردن و اصلاح خودکار موارد 4 و 5 است.



6- در نگارش‌های جدید دات نت فریم ورک استفاده از ArrayList منسوخ شده است. بجای آن بهتر است از لیست‌های جنریک استفاده شود. کدی که در آن از ArrayList استفاده می‌شود طعم دات نت فریم ورک 1 را می‌دهد!

7- لطفا بین خطوط فاصله ایجاد کنید. ایجاد فواصل مجانی است!

دو تابع جاوا اسکریپتی زیر را (که در حقیقت یک تابع هستند) در نظر بگیرید:

function getSomeAngle() {
// Some code here then
radAngle1 = Math.atan(slope(center, point1));
radAngle2 = Math.atan(slope(center, point2));
firstAngle = getStartAngle(radAngle1, point1, center);
secondAngle = getStartAngle(radAngle2, point2, center);
radAngle1 = degreesToRadians(firstAngle);
radAngle2 = degreesToRadians(secondAngle);
baseRadius = distance(point, center);
radius = baseRadius + (lines * y);
p1["x"] = roundValue(radius * Math.cos(radAngle1) + center["x"]);
p1["y"] = roundValue(radius * Math.sin(radAngle1) + center["y"]);
pt2["x"] = roundValue(radius * Math.cos(radAngle2) + center["y"]);
pt2["y"] = roundValue(radius * Math.sin(radAngle2) + center["y");
// Now some more code
}

function getSomeAngle() {
// Some code here then
radAngle1 = Math.atan(slope(center, point1));
radAngle2 = Math.atan(slope(center, point2));

firstAngle = getStartAngle(radAngle1, point1, center);
secondAngle = getStartAngle(radAngle2, point2, center);

radAngle1 = degreesToRadians(firstAngle);
radAngle2 = degreesToRadians(secondAngle);

baseRadius = distance(point, center);
radius = baseRadius + (lines * y);

p1["x"] = roundValue(radius * Math.cos(radAngle1) + center["x"]);
p1["y"] = roundValue(radius * Math.sin(radAngle1) + center["y"]);

pt2["x"] = roundValue(radius * Math.cos(radAngle2) + center["y"]);
pt2["y"] = roundValue(radius * Math.sin(radAngle2) + center["y");
// Now some more code

}

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

8- توابع خود را کوتاه کنید.
یک تابع نباید بیشتر از 50 سطر باشد (البته در این مورد بین علما اختلاف هست!). اگر بیشتر شد بدون شک نیاز به refactoring داشته و باید به چند قسمت تقسیم شود تا خوانایی کد افزایش یابد.
به صورت خلاصه یک تابع فقط باید یک کار را انجام دهد و باید بتوان عملکرد آن‌را در طی یک جمله توضیح داد.

9- از اعداد جادویی در کدهای خود استفاده نکنید!
کد زیر هیچ معنایی ندارد!

if(mode == 3){ ... }
else if(mode == 4) { ... }

بجای این اعداد بی مفهوم باید از enum استفاده کرد:

if(mode == MyEnum.ShowAllUsers) { ... }
else if(mode == MyEnum.ShowOnlyActiveUsers) { ... }

10- توابع شما نباید تعداد پارامتر زیادی داشته باشند
اگر نیاز به تعداد زیادی پارامتر ورودی وجود داشت (بیش از 6 مورد) از struct و یا کلاس جهت معرفی آن‌ها استفاده کنید.

اشتراک‌ها
اعمال فیلترهای اینستاگرام بر روی تصاویر تحت وب
 Many love using Instagram and the filters that come with the app, to make their photos more interesting and beautiful. So far though, the use of these filters are restricted to use inside the app. What if you want to use Instagram filters on web images, outside of the app, like photos you want to put up in your personal blog or website ?
اعمال فیلترهای اینستاگرام بر روی تصاویر تحت وب
مطالب
توصیه‌هایی در مورد overloading متدها

مطلب زیر چکیده‌ای است از کتاب Framework Design Guidelines در مورد سربارگذاری توابع

الف) از یک نوع خروجی استفاده کنید

مثال زیر را در نظر بگیرید:

public User[] GetGroupMembers(int groupId)
public List<User> GetGroupMembers(string groupName)

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

ب) نام‌های آرگومان‌های توابع سربارگذاری شده شما باید یکسان باشند

در مثال زیر، از اولین آرگومان جهت دریافت شناسه‌ی یک گروه استفاده می‌شود:

public List<User> GetGroupMembers(int groupId)
public List<User> GetGroupMembers(int id, int pageIndex, int pageSize)

اما همانطور که ملاحظه می‌کنید در یکی از groupId استفاده شده و در دیگری از نام id . این روش مزموم است! از آن پرهیز کنید! (هر دو یا باید groupId باشند و یا id . این هماهنگی و یکسان بودن باید در توابع سربارگذاری شده‌ی شما حفظ شود)

ج) ترتیب آرگومان‌ها را در توابع سربارگذاری شده حفظ و رعایت نمائید

لطفا به مثال زیر دقت کنید:

public List<User> GetGroupMembers(int groupId)
public List<User> GetGroupMembers(int pageIndex, int pageSize, int groupId)

در اینجا شناسه‌ی گروه یکبار به عنوان آرگومان اول معرفی شده و بار دیگر به عنوان آرگومان سوم. این کار نیز مزموم است، زیرا برنامه نویس‌ها از روی عادت به اولین آرگومان توابع سربارگذاری شده‌ی شما، همان شناسه‌ی گروه را ارسال خواهند کرد و این مورد سبب بروز باگ‌هایی خواهد شد که ردیابی آن مشکل است. بنابراین اگر شناسه‌ی گروه به عنوان اولین آرگومان معرفی شده، در تمامی overload های این تابع نیز اولین آرگومان باید همان شناسه‌ی گروه باشد.

د) از call forwarding استفاده کنید

جهت توضیح بهتر call forwarding به مثال زیر دقت نمائید:
public List<User> GetGroupMembers(int groupId)
{
return GetGroupMembers(groupId, 0, 10);
}

public List<User> GetGroupMembers(int groupId, int pageIndex, int pageSize)
{
return GetGroupMembers(groupId, pageIndex, pageSize, SortOrder.Ascending);
}

public List<User> GetGroupMembers(int groupId, int pageIndex, int pageSize, SortOrder sortOrder)
{
var query = new GroupQuery();
query.GroupID = groupId;
query.PageIndex = pageIndex;
query.PageSize = pageSize;
query.SortOrder = sortOrder;

return GetGroupMembers(query);
}

public List<User> GetGroupMembers(GroupQuery groupQuery)
{
// Actual implementation to get group members goes here
}

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

ه) زیاده‌ روی نکنید!

آخرین موردی که توصیه شده این است که در تهیه توابع سربارگذاری شده زیاده روی نکنید. در این نوع موارد باید قانون 80/20 را در نظر گرفت. 2 تا 3 تابع سربارگذاری شده ارائه دهید که 80 درصد کار را انجام می‌دهند و سپس یک تابع سربارگذاری شده‌ی دیگر ارائه دهید که 20 درصد باقیمانده را پوشش دهد.


پ.ن.
در سی شارپ 4 ، با معرفی optional parameters ، شاید کمتر به سربارگذاری نیاز باشد.

مطالب
املای صحیح فناوری‌های مرتبط با مایکروسافت

به نظر شما .net درست است یا .Net یا ... ؟
Asp.net چطور؟ آیا ASP.Net درست است یا Asp.net یا ... ؟!
Direct X درست است یا Direct-X یا ... ؟
Linq درست است یا linq یا ...؟

پاسخ: هیچکدام!
املای تمامی موارد ذکر شده نادرست است. جدولی را یکی از کارکنان مایکروسافت در این زمینه تهیه کرده است که در آدرس ذیل می‌توانید مشاهده نمائید:




مطالب
ایجاد رنگ و روی سفارشی برای ادیتور Visual Studio

برنامه‌ی آنلاینی جهت تولید یک theme سفارشی جدید برای ویژوال استودیو ایجاد شده است که در آدرس زیر قابل استفاده است:


ابتدا تنظیمات رنگ خود را انتخاب کنید، سپس بر روی دکمه refresh کلیک نمائید تا نمونه‌ای از نتیجه‌ی کار را بتوان مشاهده کرد و سپس بر روی دکمه create کلیک کنید.


و برای استفاده از فایل تولید شده از طریق منوی tools گزینه‌ی Import and Export Settings اقدام کنید.


مطالب
بررسی علت CPU Usage بالای برنامه در حال اجرا

فرض کنید به یک سرور مراجعه کرده‌اید و شکایت از CPU Usage مربوط به پروسه w3wp.exe یا همان IIS Worker Process است که بالای 90 درصد می‌باشد. بر روی این سرور هم هیچ چیز دیگری نصب نیست و مطابق مقررات موجود، قرار هم نیست که برنامه‌ای نصب شود. اکنون سؤال این است که چطور تشخیص می‌دهید، کدام قسمت یکی از برنامه‌ها‌ی دات نتی در حال اجرا (در اینجا یکی از برنامه‌های ASP.NET هاست شده)، سبب بروز این مشکل شده است؟ کدام ترد بیشترین زمان CPU را به خود اختصاص داده است؟ چطور باید خطایابی کرد؟
اولین کاری که در این موارد توصیه می‌شود مراجعه به برنامه‌ی معروف process explorer و بررسی برگه‌ی threads آن است. در اینجا حتی می‌توان call stacks مرتبط با یک ترد را هم مشاهده کرد. اما ... این برگه در مورد پروسه‌ها و تردهای دات نتی، اطلاعات چندانی را در اختیار ما قرار نمی‌دهد.
خوشبختانه امکان دیباگ پروسه‌های دات نتی در حال اجرا توسط کتابخانه‌ی MdbgCore.dll پیش بینی شده است. این فایل را در یکی از مسیر‌های ذیل می‌توانید پیدا کنید:
C:\Program Files\Microsoft SDKs\Windows\vXYZ\bin\MdbgCore.dll
C:\Program Files\Microsoft SDKs\Windows\vXYZ\bin\NETFX 4.0 Tools\MdbgCore.dll

در ادامه می‌خواهیم توسط امکانات این کتابخانه، به stack trace تردهای در حال اجرای یک برنامه دات نتی دسترسی پیدا کرده و سپس نام متدهای مرتبط را نمایش دهیم:
using System;
using System.Collections;
using System.Diagnostics;
using Microsoft.Samples.Debugging.MdbgEngine;

namespace CpuAnalyzer
{
class Program
{
static void Main(string[] args)
{
var engine = new MDbgEngine();

var processesByName = Process.GetProcessesByName("MyApp");
if (processesByName.Length == 0)
throw new InvalidOperationException("specified process not found.");
var processId = processesByName[0].Id;

var process = engine.Attach(processId);
process.Go().WaitOne();

foreach (MDbgThread thread in (IEnumerable)process.Threads)
{
foreach (MDbgFrame frame in thread.Frames)
{
if (frame == null || frame.Function == null) continue;
Console.WriteLine(frame.Function.FullName);
}
}

process.Detach().WaitOne();
}
}
}
در اینجا در ابتدا نیاز است تا pid یا process-id مرتبط با برنامه در حال اجرا یافت شود. سپس از این pid جهت اتصال (engine.Attach) به پروسه مورد نظر استفاده خواهیم کرد. در ادامه کلیه تردهای این پروسه در حال دیباگ لیست شده و سپس MDbgFrameهای این ترد بررسی می‌شوند و نام متدهای مرتبط در کنسول نمایش داده خواهند شد.
خوب در مرحله بعد شاید بد نباشد که این متدها را بر اساس CPU usage آن‌ها مرتب کنیم. به این ترتیب بهتر می‌توان تشخیص داد که کدام متد مشکل ساز بوده است. برای این منظور باید به API ویندوز و تابع GetThreadTimes مراجعه کرد و اولین پارامتر ورودی آن، همان thread.CorThread.Handle اولین حلقه مثال فوق می‌باشد. هر کدام که جمع KernelTime + UserTime بیشتری داشت، همان است که مشکل درست کرده است.
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool GetThreadTimes(IntPtr handle, out long creation, out long exit, out long kernel, out long user);
این مورد را به عنوان تمرین بررسی کرده و ادامه دهید! همچنین بهتر است جهت دستیابی به اطلاعاتی معتبر، اولین حلقه برنامه فوق، حداقل 10 بار اجرا شود تا اطلاعات آماری بهتری را بتوان ارائه داد. البته در این حالت نکته‌ی زیر باید رعایت شود:
for (int i = 0; i < 10; i++)
{
foreach (MDbgThread thread in (IEnumerable)process.Threads)
{
//...
}
process.Go();
Thread.Sleep(1000);
process.AsyncStop().WaitOne();
}

در کل این مثال جای کار زیاد دارد. برای مثال طراحی یک رابط کاربری برای آن و نمایش جزئیات بیشتر. به همین منظور حداقل سه پروژه مشابه را می‌توان نام برد:

مطالب
چگونه یک ایمیل مفید خودکار را طراحی کنیم؟

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

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

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

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

4) ایمیل شما باید حاوی لینکی جهت باز کردن برنامه‌ی تحت وب مرتبط نیز باشد.
کاری ارجاع شده است؟ بهتر است لینک پویایی را جهت هدایت کاربر به صفحه‌ی مرتبط رسیدگی به همان کار ارجاعی ارسال کنید. به این صورت زحمت او را کمتر کرده و یک مرحله گزارش گیری را حذف خواهید کرد. یا حداقل یک محل مراجعه‌ی کلی بعدی را به این صورت می‌توان ارائه داد.

5) از بکارگیری قسمت from ایی مانند DoNotReply@Site.Com خودداری کنید.
کاربر دریافت کننده‌ی ایمیل باید بداند که در صورت وجود مشکل باید به کجا مراجعه کند؟ چه کسی این ایمیل را ارسال کرده؟
هرچند برنامه به صورت خودکار تمام قسمت‌های این ایمیل ارسالی را تهیه می‌کند اما اگر خبرنامه‌ی تنظیم شده‌ای نیست، حتما شخص ارسال کننده‌ای دارد. یا حداقل یک ایمیل عمومی را برای این مورد تنظیم کنید (ایمیلی که وجود خارجی داشته و هر از چندگاهی بررسی می‌شود).

6) رنگ زمینه و اندازه‌ی قلم مناسبی را انتخاب کنید.
دقیقا برای هر کدام از موارد ذکر شده چندین بار مشکل داشته‌ام! عموما کسانی که ایمیل‌ها را دریافت می‌کنند سن و سال دار هستند. بنابراین انتخاب فونت tahoma با اندازه‌ی 8 یا pt 7 سبب توبیخ زود هنگام شما خواهد شد!
همچنین هر چه ساده‌تر بهتر. دقیقا مشکلات از زمانی آغاز می‌شوند که طرحی را انتخاب کنید یا رنگی را برای زمینه بکار ببرید. اینجا است که هر روز یک سلیقه‌ی تحمیلی را باید پذیرا باشید.

7) دقیقا مشخص کنید که ایمیل دریافتی آیا رونوشت‌ است یا خیر!
همان مبحث ارجاع کار را در نظر بگیرید. پس از اینکه سیستم راه اندازی شد، مدیر یکی از قسمت‌ها چند روز بعد این درخواست را "حتما" ارسال خواهد کرد: رونوشت تمام کارهای ارجاعی به کلیه پرسنل بخش و همچنین ریز اقدامات آن‌ها باید برای بنده نیز ارسال شود.
در اینجا تنها افزودن قسمت CC به ایمیل‌های خودکار کفایت نمی‌کند. حتما به صورت درشت در بالای ایمیل، قبل از شروع بدنه ذکر کنید که ایمیل دریافتی یک رونوشت است. در غیر اینصورت باید پاسخگوی علت دریافت ایمیل‌هایی باشید که به درخواست خودشان CC شده است!

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

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


خوب! حالا به نظر شما این ایمیل خودکار ارسالی سایت IDevCenter که اخیرا اضافه شده است چه نمره‌ای را کسب می‌کند؟



- تاریخ شمسی در انتهای ایمیل ندارد.
- عنوان‌ها ثابت هستند.
- هیچ جزئیاتی ارائه نشده است.
- لینک مرتبط دارد.
- قسمت from مناسبی دارد.
- ساده است؛ خوب است! فقط اندازه قلم آن بهتر است یک شماره بزرگتر شود.
- بحث رونوشت اینجا مورد ندارد.
- بحث لاگ ... شخصی است.
- امکان تنظیم دریافت ایمیل پیش بینی شده است.
نمره از 7 : 3.5

مطالب
هزینه استفاده از دات نت فریم ورک چقدر است؟

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

سؤال: هزینه استفاده از دات نت فریم ورک چقدر است؟
پاسخ: رایگان است! از زمان ارائه ویندوز سرور 2003 به بعد، دات نت فریم ورک به عنوان یکی از کامپوننت‌های اصلی ویندوز عرضه می‌شود و هر شخصی که مجوز اصلی استفاده از ویندوز را خریده باشد، به صورت خودکار مجوز استفاده از دات نت فریم ورک را هم خواهد داشت و نیازی نیست بابت آن هزینه‌ی خاصی را متقبل شود. برای مثال ویندوز سرور 2003 ، دات نت 1.1 سرخود است و ویندوز 7 و ویندوز سرور 2008 ، دات نت سه و نیم سرخود هستند.

سؤال: آیا برای توسعه‌ی دات نت حتما نیاز است تا ویژوال استودیوی چند هزار دلاری را خرید؟!
پاسخ: خیر! ویژوال استودیو، نسخه‌های مختلفی دارد و حتما نیازی نیست تا از نسخه‌ی ultimate آن استفاده کنید. برای مثال نسخه‌ی Express آن که توسط خود مایکروسافت ارائه شده، رایگان است (+). مهم‌ترین تفاوت آن با نسخه‌ی ultimate در این است که افزونه پذیر نیست و این مورد شاید برای خیلی‌ها اصلا اهمیتی نداشته باشد چون عموما افزونه‌های بد نوشته شده، باعث ناپایداری IDE می‌شوند یا مثلا نسخه‌ی ultimate به همراه MSTests جهت انجام ساده‌تر unit testing‌ ارائه شده که در نسخه‌ی Express وجود ندارد، این هم مهم نیست چون فریم ورک‌های سورس باز آزمون واحد دیگری مانند Nunit ، MBUnit و غیره هم وجود دارند که اصلا نیازی به هیچ IDE‌ خاصی جهت کار ندارند و مسایلی از این دست. یا برای سورس کنترل می‌شود از SVN ، Git ، مرکوریال و غیره هم همیشه استفاده کرد. این‌ها هم مستقل هستند از نوع IDE مورد استفاده.

همچنین یک گروه مستقل، IDE دیگری را به نام SharpDevelop تهیه کر‌ده‌اند که بسیار با کیفیت بوده و از همه مهم‌تر سورس باز است و رایگان. خیلی‌ها از کنترل‌های این IDE در پروژه‌های خودشون استفاده می‌کنند (مثل syntax highlighting همراه آن و غیره)

در کنار تمام این‌ها، هیچ وقت دقت کرده‌اید که در پوشه دات نت نصب شده در ویندوز چه چیزهایی یافت می‌شوند؟! مثلا به آدرس C:\Windows\Microsoft.NET\Framework\v4.0.30319 مراجعه کنید. فایل csc.exe همان کامپایلر خط فرمان سی شارپ است. کاری هم که IDE ها انجام می دهند این است که لیست فایل‌های شما رو به صورت آرگومان به این برنامه ارسال می‌کنند. این اتوماسیون به صورت دستی هم میسر است. IDE شما می‌شود مثلا برنامه رایگان notepad++ ایی که syntax highlighting تمام زبان‌های دات نتی را پشتیبانی می‌کند. ساده‌ترین سیستم build شما یک فایل bat خواهد بود که csc.exe را مدیریت می‌کند.

علاوه بر تمام این‌ها، MonoDevelop را هم اضافه کنید. این IDE ، نسخه‌ی ویندوزی هم دارد.

سؤال: من شنیدم دات نت فقط با SQL Server کار می‌کنه. این هم که گرونه؟!
پاسخ: خیر! نسخه‌ی رایگان SQL server به نام SQL Server express هم موجود است و در نسخه‌ی 2008 R2 آن محدودیت حجم بانک اطلاعاتی آن به 10 گیگ رسیده که برای اکثر کارها تا چند سال کافی است (+).
ضمنا قبلا در مورد لیست بانک‌های اطلاعاتی قابل استفاده توسط دات نت فریم ورک مطلب نوشتم و در سایت موجود است. بنابراین دات نت اصلا به SQL Server محدود نیست (+).

سؤال: دات نت سورس بسته است! نه این اصلا خوب نیست؛ آینده نداره!
پاسخ: خیر. سورس کامل دات نت فریم ورک تحت مجوز‌های MS-PL و MS-RSL چندسالی هست که منتشر شده و این مجوز (MS-PL) جزو مجوزهای معتبر و پذیرفته شده سورس باز است (+).
لینک دریافت

خبر مرتبط

ضمنا کارهای سورس باز مایکروسافت به این یک قلم ختم نمی‌شود. برای مثال به سایت CodePlex مراجعه کنید تا سورس کامل ASP.NET MVC نگارش 3 را دریافت کنید(+)، همینطور مجموعه کنترل‌های WPF و Silverlight و غیره‌ای که تهیه‌ کرده‌اند (+) و بسیاری موارد دیگر.

سؤال: دات نت که فقط روی ویندوز اجرا میشه. نه؛ این خوب نیست!
پاسخ: خیر! پروژه‌ای سابقا تحت عنوان Mono وجود دارد/داشت (+) که توسط شرکت ناول اداره می‌شد و کار آن انتقال دات نت به لینوکس و سایر سکوهای کاری بود. پس از فروخته شدن ناول، این پروژه به ظاهر متوقف شد، اما تیم اصلی آن تحت نام دیگری به نام زاماریان (+) دوباره شروع به کار کرده و جالب اینجا است که تا دات نت 4 را هم تحت لینوکس پشتیبانی می‌کند(+). جهت اطلاع ASP.NET رو به صورت کامل می‌تونید تحت لینوکس اجرا کنید (+). همچنین سایر موارد پشتیبانی شده رو.


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


در کنار تمام این مباحث، بحث «هزینه یادگیری و آموزش» را هم اضافه کنید. شاید یکی بیاد بگه CPP فلان، اون یکی بهمان! ولی این سؤالات هم برای من نوعی که تیم گوگل کروم نوشته شده با CPP رو مدیریت نمی‌کنم (و به قول اونطرف آبی‌ها یک Average Joe هستم!) مهم هستند:
- چندتا کتاب فارسی آموزشی خوب در این زمینه در کشور موجود است. من یادم میاد اولین کتاب VC منتشر شده در کشور پس از 450 صفحه به شما یاد می‌داد چطور با MFC دکمه به صفحه اضافه کنید، چطور منو درست کنید و همین! این شد برنامه نویسی CPP!
- چند عدد انجمن رفع اشکال فعال را که تاریخ آخرین به روز رسانی و پرسش و پاسخ آن‌ها مثلا دیروز بوده را در مورد زبان xyz می‌توان یافت؟
- اگر به مشکل برخوردم، کسی هست به داد من برسه؟ چه زمانی؟! مثلا هفته بعد یا تا آخر امروز؟
- چندتا وبلاگ فعال در این زمینه موجود است؟ آیا هستند کسانی که در این زمینه‌ها فعالانه مطلب منتشر کنند؟ اطلاع رسانی کنند؟
- اگر کارمند برنامه نویس شرکتی امروز قهر کرد، مدیر بخش توسعه تا چه زمانی می‌تونه یک نفر رو جایگزین اون کنه؟ مثلا تا آخر ماه یا تا آخر سال؟! اون هم با چه کیفیتی؟ با چه دستمزدی؟
و اینجا است که وضعیت دات نت در ایران بسیار مطلوب‌تر از موارد مشابه به نظر می‌رسد. از نظر تعداد کتاب فارسی مهیا، تعداد انجمن، تعداد وبلاگ فعال و غیره.

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

مطلب امروز به کنترل شخصی مرتبط است. به درد همه می‌خوره! :)
چگونه ارسال ایمیلی را که ممکن است 5 دقیقه بعد از ارسال آن به شدت پشیمان شویم، کنترل کنیم؟!

برای به تاخیر انداختن تمامی ایمیل‌های ارسالی از طریق آوت لوک می‌توان به صورت زیر عمل کرد:

به منوی tools‌ گزینه rules and alerts مراجعه کنید.


در صفحه باز شده بر روی دکمه new rule کلیک کنید.
در پنجره بعدی گزینه Check messages after sending را انتخاب کرده و بر روی دکمه next کلیک کنید.


در صفحه بعد تنها بر روی گزینه next کلیک کنید (تا تنظیمات ما بر روی تمامی ایمیل‌های ارسالی اعمال شود).
سپس بر روی دکمه yes پیغام باز شده کلیک نمائید.
تنظیمات اصلی مطلب جاری مربوط به این صفحه است. در اینجا گزینه defer delivery by a number of minutes را تیک بزنید.




سپس بر روی لینک a number of کلیک کنید تا صفحه وارد کردن میزان زمان به تاخیر انداختن ارسال را بتوان وارد کرد. پس از وارد کردن یک عدد دلخواه و کلیک بر روی دکمه ok ، بر روی دکمه next کلیک نمائید.
در صفحه بعد نیز بر روی دکمه next کلیک کنید. (البته در اینجا می‌توان مشخص کرد که برای مثال اگر عنوان ویژه‌ای بکار برده شد یا به گروه خاصی ایمیل ارسال گردید، این محدودیت برداشته شود)
و در آخرین صفحه، نامی دلخواه را وارد کرده و بر روی دکمه‌ی خاتمه کلیک نمائید.
در صفحه‌ی اصلی rules & alerts نیز بر روی دکمه apply کلیک کنید، تا تنظیمات اعمال گردد.

از این پس هر ایمیل ارسالی شما مدتی در outbox معطل شده و سپس ارسال می‌گردد.
هنوز تا 5 دقیقه دیگر فرصت هست! با مراجعه به outbox می‌توان ایمیل مورد نظر را در صورت منصرف شدن حذف یا ویرایش کرد. (بنابر تجربه 3 دقیقه کافی است!)

مطلب ارسالی فوق برای آوت لوک 2007 تنظیم شد. اگر آوت لوک شما 2003 است لطفا به آدرس زیر مراجعه کرده و قسمت Delay delivery of all messages را مطالعه نمائید.



مطالب
مقایسه مجوزهای سورس باز

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

نام مجوز آیا به کار مشتق شده از پروژه اصلی، می‌توانم نامی دیگر بدهم؟ آیا باید حتما کار مشتق شده سورس باز باقی بماند؟ آیا می‌توانم برای کار مشتق شده مجوزی جدید انتخاب کنم؟ آیا می‌توانم کار مشتق شده را بفروشم و کسب درآمد کنم؟

Apache License 2.0
بله خیر بله بله

Common Development and Distribution License (CDDL)
بله خیر بله (به مجوزهای سازگار دیگری از همین دست) بله

GNU General Public License 2.0 (GPLv2)
بله، اما حتما باید لیست تغییرات انجام شده نسبت به پروژه اصلی را نیز
ارائه بدهید.
بله بله (به مجوزهای سازگار دیگری از همین دست یا توافق با نویسنده اصلی) بله

GNU Library General Public License (LGPL)
بله بله، اما امکان استفاده از کتابخانه‌های کامپایل شده یک پروژه سورس باز
تحت این مجوز در یک پروژه سورس بسته نیز وجود دارد.
بله (به مجوزهای سازگار دیگری از همین دست) بله

Microsoft Public License (Ms-PL)
بله، اما نمی‌توانید از علامت تجاری خود استفاده کنید. خیر خیر بله

Microsoft Reciprocal License (Ms-RL)
بله، اما نمی‌توانید از علامت تجاری خود استفاده کنید. بله خیر بله

Mozilla Public License 1.1 (MPL)
بله خیر خیر بله

BSD License
بله خیر بله بله

MIT License
بله خیر بله بله



همچنین لازم به ذکر است که
مجوزهای کار اصلی و کار مشتق شده هر دو باید ذکر شوند.
پسندیده است که از نویسندگان کار اصلی، نامبرده شده و قدردانی گردد.
هیچکدام از این مجوزها مسؤولیتی را در قبال کار انجام شده نمی‌پذیرند!

جهت مطالعه بیشتر:
http://khason.net/blog/open-source-licenses-comparison-table/
http://developer.kde.org/documentation/licensing/licenses_summary.html
http://en.wikipedia.org/wiki/Comparison_of_free_software_licences