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

داشتن آگاهی در مورد ساختارهای داده‌‌ها، الگوریتم‌ها و یا عملگرهای بیتی بسیار عالی است و یا تسلط بر نحوه‌ی کارکرد ابزارهایی مانند 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 و یا کلاس جهت معرفی آن‌ها استفاده کنید.

مطالب
لینک‌های هفته‌ی دوم اسفند

وبلاگ‌ها ، سایت‌ها و مقالات ایرانی (داخل و خارج از ایران)

امنیت

Visual Studio

ASP. Net

طراحی و توسعه وب

PHP

اس‌کیوال سرور

سی شارپ

VB

CPP

عمومی دات نت

مسایل اجتماعی و انسانی برنامه نویسی

متفرقه
مطالب دوره‌ها
شناسه ها و استفاده از Let
#F هم مانند سایر زبان‌های برنامه نویسی از یک سری Data Type به همراه عملگر و Converter پشتیبانی می‌کند که در ابتدا لازم است یک نگاه کلی به این موارد بیندازیم. به دلیل آشنایی اکثر دوستان به این موارد و به دلیل اینکه تکرار مکررات نشود از توضیح در این موارد خودداری خواهم کرد.(در صورت مبهم بودن می‌توانید از قسمت پرسش و پاسخ استفاد نمایید)
Basic Literal


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

Arithmetic Operators
(عملگر‌های محاسباتی)

Simple String (کار با نوع داده رشته ای)


بعد از بررسی موارد بالا حالا به معرفی شناسه‌ها می‌پردازم. شناسه‌ها در #F راهی هستند برای اینکه شما به مقادیر نام اختصاص دهید. برای اختصاص نام به مقادیر کافیست از کلمه کلیدی let به همراه یک نام  و علامت = و یک عبارت استفاده کنید. چیزی شبیه به تعریف متغیر در سایر زبان‌ها نظیر #C. دلیل اینکه در #F به جای واژه متغیر از شناسه استفاده می‌شود این است که شما می‌توانید به یک شناسه تابعی را نیز اختصاص دهید و مقدار شناسه‌ها دیگر قابل تغییر نیست. در #F کلمه متغیر یک واژه نادرست است چون زمانی که شما یه یک متغیر مقدار اختصاص می‌دهید، مقدار  اون متغیر دیگه قایل تغییر نیست. برای همین اکثر برنامه نویسان #F به جای استفاده از واژه متغیر از واژه مقدار یا شناسه استفاه می‌کنند. برای همین از واژه متغیر برای نام گذاری استفاده نمی‌شود. (البته در #F در بعضی مواقع ما شناسه‌ها رو دوباره تعریف می‌کنیم که چیزی شبیه به استفاده از متغیر هاست ولی با اندکی تفاوت. در این فصل تمرکز ما بر روی شناسه هایی است که مقدارشان تغییر نمی‌کند ولی در فصل برنامه نویسی دستوری به تفصیل در این باره توضیح داده شده است)
let x = 42
در بالا یک شناسه به نام x تعریف شد که مقدار 42 را دریافت کرد. در #F یک شناسه می‌تواند دارای یک مقدار معین باشد یا به یک تابع اشاره کند. این بدین معنی است #F معنی حقیقی برای تابع و پارامتر‌های آن ندارد و همه چیز رو به عنوان مقدار در نظر می‌گیرد.
let myAdd = fun x y -> x + y
کد بالا تعریف یک شناسه به نام myAdd است که به تابعی اشاره می‌کنه که دو پارامتر ورودی دارد و در بدنه آن مقدار پارامتر‌ها با هم جمع می‌شوند.(تعریف توابع به صورت مفصل بحث خواهد شد.) نکته جالب این است که تابع تعریف شده نام ندارد و #F دقیقا با توابع همون رفتاری رو داره که با شناسه‌ها دارد.
let raisePowerTwo x = x ** 2.0
در کد بالا شناسه ای تعریف شده است با نام raisePowerTwo که یک پارامتر ورودی داره به نام x و در بدنه آن (هرچیزی که بعد از = قرار گیرد) مقدار x رو به توان دو می‌کنه.

نام گذاری شناسه ها

برای نام گذاری شناسه‌ها نام انتخابی یا باید با Underscore شروع شود یا با حروف. بعد از آن می‌تونید از اعداد هم استفاده کنید.(نظیر سایر زبان‌های برنامه نویسی)
#F از unicode هم پشتیبانی می‌کنه یعنی می‌تونید متغیری به صورت زیر رو تعریف کنید.
let مسعود = ""
اگر احساس می‌کنید که قوانین نام گذاری در #F کمی محدود کننده است می‌تونید از علامت '' ''  استفاده کنید و در بین این علامت  هر کاراکتری که می‌خواهید رو قرار دهید و #F اونو به عنوان نام شناسه قبول خواهد کرد. برای نمونه
let ``more? `` = true
یا
let ``class`` = "style"
حتی امکان استفاده از کلمات کلیدی هم نظیر class به این روش وجود دارد.

محدوده تعریف شناسه ها
به دلیل اینکه در #F از {} به عنوان شروع و اتمام محدوده استفاده نمی‌شود دونستن و شناختن محدوده توابع بسیار مهم و ضروری است. چون اگر از شناسه ای که در یک محدوده در دسترس نباشد استفاده کنید با خطای کامپایلر متوقف خواهید شد.
همون بحث متغیر‌های محلی و سراسری (در سایر زبان ها) در این جا نیز صادق است یعنی در #F شناسه‌های سراسری و محلی خواهیم داشت. تمام شناسه ها، چه اون هایی که در توابع استفاده می‌شوند و چه اونهایی که به مقادیر اشاره می‌کنند محدودشون از نقطه ای که تعریف می‌شوند تا جایی که اتمام استفاده از اونهاست تعریف شده است. برای مثال اگر یک شناسه رو در بالای فایل تعریف کنید که یک مقدار دارد تا پایان SourceFile قابل استفاده است.( به دلیل نبود مفهوم کلاس از واژه sourceFile استفاده کردم). هم چنین شناسه هایی که در توابع تعریف می‌شوند فقط در همون توابع قابل استفاده هستند.
حالا سوال این است که با نبودن {} چگونه محدوده خود توابع مشخص میشود؟
در #F با استفاده از فضای خای یا space محدوده شناسه‌ها و توابع رو مشخص می‌کنیم.  برای روشن شدن مطلب به مثال زیر دقت کنید.
let test a b =
    let dif = b - a
    let mid = dif / 2
    mid + a

printfn "(test 5 11) = %i" (test 5 11)
printfn "(test 11 5) = %i" (test 11 5)
ابتدا اختلاف بین دو ورودی محاسبه می‌شود و در یک شناسه به نام dif قرار می‌گیرد. برای اینکه مشخص شود که این شناسه خود عضو یک تابع دیگر به نام test است از 4 فضای خالی استفاده شده است. در خط بعدی شناسه mid مقدار شناسه dif رو بر 2 تقسیم می‌کند. در انتها نیز مقدار mid با مقدار a جمع می‌شود و حاصل برگشت داده می‌شود.(انتهای بدنه تابع)
نکته مهم: به جای استفاده از فضای خالی(space) نمی‌تونید از TAB استفاده کنید.

LIGHTWEIGHT SYNTAX یا VERBOSE SYNTAX


در #F دو نوع سبک کد نویسی وجود دارد. یکی lightweight و دیگری Verbose. البته اکثر برنامه نویسان از سبک lightweight که به صورت پیش فرض در #F تعبیه شده است استفاده می‌کنند ولی آشنایی با سبک verbose نیز به عنوان برنامه نویس #F ضروری است. ما نیز به تبعیت از سایرین از سبک lightweight استفاده خواهیم کرد ولی یک فصل به عنوان مطالب تکمیلی اختصاص دادم که تفاوت این دو سبک را در طی چندین مثال بیان میکند.
همان طور که قبلا بیان شد #F بر اساس زبان OCaml پیاده سازی شده است. زبان OCaml مانند #F، یک زبان LIGHTWEIGHT SYNTAX نیست. LIGHTWEIGHT SYNTAX  بدین معنی است محدوده شناسه‌ها بر اساس فضای خالی بین اون‌ها مشخص می‌شود نه با ;. (البته استفاده از ; به صورت اختیاری است)
بازنویسی مثال بالا
let halfWay a b =
let dif = b - a in
let mid = dif / 2 in
mid + a
برای اینکه کامپایلر #F متوجه شود که قصد کدنویسی به سبک lightweight رو نداریم، باید در ابتدای هر فایل از دستور زیر استفاده کنیم.
#light "off"
مطالب دوره‌ها
معرفی پروژه F# Sample 101
در این پروژه که محیط آن را در تصویر زیر مشاهده می‌کنید مثال‌های متنوعی از زبان برنامه نویسی #F تعبیه شده است. از منوی سمت چپ گزینه‌ی مورد نظر خود را انتخاب کنید. کد مثال را می‌تونید در قسمت Code پروژه مشاهده کنید. با استفاده از گزینه Run Sample می‌تونید خروجی هر مثال را نیز بینید.


برای نمونه :

دریافت سورس کامل پروژه
نظرات اشتراک‌ها
آیا WPF مرده است؟!
بسته به اینکه شما مرده رو چی در نظر بگیرید مسئله فرق دارد. 
1- اینکه احتما نسخه بعدی وجود ندارد.(احتمالا)
2- جایگزینی بهتری برای آن وجود دارد(100% خیر){ولی احتمالا تا چند وقت دیگر می‌آید زیاد است. چون مایکروسافت قصد دارد تغییراتی را در برنامه‌های توسعه ای خود ایجاد کند که با یک کد برای همه پلت فرم‌ها کد نویسی شود. به نظر من برنامه ای شبیه ویندوز استو با امکانات کامل بزودی جایگزین خواهد شد که با توجه به تکنلوژی Xaml  برای wpf کار‌ها کار سویچ سخت نخواهد شد}
نظرات اشتراک‌ها
200 ویدیوی آموزشی jQuery
یک VPS ارزون بخر. بعد براش برنامه نویسی کن تا فایل‌های یوتیوب رو دریافت کنه و لینک مستقیم بهت بده. خیلی‌ها این دور و اطراف اینطوری کار می‌کنند (یا حتی برای خودشون ایجاد اشتغال کردن). الگوریتم تهیه لینک مستقیم از یوتیوب رو هم اگر خواستی مثلا می‌تونی به این اسکریپت و کدهاش مراجعه کنی؛ بگردی بازهم هست در همون سایت. نمونه‌های دات نتش هم هست در سایت کدپلکس.
اشتراک‌ها
بازی 2048 برای تلگرام

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

مهمترین نکته اینکه شما دو تا API تلگرام یکی SetScore  برای ثبت رکورد و دیگری GetHighScores را برای دریافت آخرین رکوردها را پیاده سازی کنید.

بازی 2048 برای تلگرام
اشتراک‌ها
جایگزینی بهتر برای احراز هویت و ایمن سازی اطلاعات حساس در وب

Web Authentication API (با نام مستعار WebAuthn) مشخصاتی است که توسط W3C و FIDO نوشته شده است به سرورها اجازه می‌دهد تا کاربران را با استفاده از رمزنگاری کلید عمومی (cryptography) به جای رمز عبور ثبت و احراز هویت کنند. 

کتابخانه fido2-net-lib جهت استفاده در دات نت

کتابخانه هایی جهت استفاده در زبان‌های برنامه نویسی دیگر

جایگزینی بهتر برای احراز هویت و ایمن سازی اطلاعات حساس در وب
اشتراک‌ها
language-agnostic به چه معناست؟
وقتی راه حل مساله ای language-agnostic  نامیده می‌شود، به این معناست که راه حل مستقل از ویژگی‌های زبانی می‌باشد. به عنوان مثال، الگوهای طراحی language-agnostic  هستند، زیرا در شیوه توصیف آنها پیاده سازی خاص مهم نیست چون آن را با کل یا زیر مجموعه ای از الگوها نشان میدهند(برخی از الگوهای طراحی را می‌توان بدون OOP اجرا کرد). UML یا BPMN یا  ERM یا حتی یک الگوریتم که به روش pseudo-code نوشته شده است language-agnostic میباشد. هر چیزی که مفهوم برنامه نویسی داشته باشد، اما در یک زبان خاص توصیف نشده باشد، می‌تواند language-agnostic نامیده شود.
language-agnostic به چه معناست؟
اشتراک‌ها
Retrofit در دات نت

یکی از محبوبترین کتابخانه‌ها در برنامه نویسی اندروید، retrofit است. این کتابخانه این امکان را به شما میدهد تنها با امضای یک متد در یک اینترفیس کلیه امکانات شامل دریافت اطلاعات از وب سرویس و همچنین serialization را داشته باشید و دیگر نیازی به نگرانی در مورد مسائل چون مدیریت تردها و سریالایز و ارسال درخواست و دریافت پاسخ و ... نداشته باشید و کار را سریعتر از گذشته پیش ببرید.

و همچنین این کتابخانه و هچنین بررسی آن توسطآقای هانسلمن

Retrofit در دات نت