پرش به مطلب اصلی

راهنمای سبک Pawn

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

همچنین ببینید:

اصطلاح‌شناسی​

دستور​

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

a = b + c;

این دستوری است متشکل از متغیری که نتیجه یک Expression به آن اختصاص داده می‌شود.

SetPlayerColor(playerid, 0xFF4700FF);

این دستوری است که به برنامه می‌گوید تابعی با برخی آرگومان‌ها فراخوانی کند.

x + 8

این دستور نیست چون نتیجه در هیچ جایی استفاده نمی‌شود، این فقط یک Expression است.

دستور مرکب​

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

{
new message[] = "hi!";
print(message);
}

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

if (a == b)
{
print("hello!");
}

این دستور مرکبی با شرط if است، معمولاً به عنوان "دستور if" شناخته می‌شود.

return Function1(), Function2(), Function3();

این دستور مرکب نیست، زنجیره‌ای از دستورها است که با کاما جدا شده‌اند. این شکل از زنجیره‌ای کردن دستورها عمل بدی تلقی می‌شود.

عبارت​

عبارت قطعه نحوی است که مقداری تولید می‌کند، دستور معتبر نیست مگر اینکه مقدار تولید شده به شکلی استفاده شود.

عبارات اغلب برای تشکیل دستورها ترکیب می‌شوند.

a + b

این عبارت ساده جمع است که دو مقدار می‌گیرد و عملگر جمع را روی آن‌ها اعمال می‌کند.

راهنماها​

آکولادها​

آکولادهای Allman ترجیح داده می‌شوند:

function()
{
//
}

اما اگر نمی‌توانید حافظه عضلانی را کنار بگذارید، آکولادهای K&R نیز Pawn معتبر هستند:

function() {
//
}

Switch ها​

Switch ها باید دو سطح تورفتگی استفاده کنند، یکی برای بلوک switch و دیگری برای هر دستور case یا دستور مرکب.

switch (variable)
{
case 0:
return 0;
case 1:
return 1;
case 2:
return 2;
default:
return -1;
}
switch (variable)
{
case 0:
{
// code...
return 0;
}
case 1:
{
// code...
return 1;
}
case 2:
{
// code...
return 2;
}
default:
{
// code...
return -1;
}
}

دستورات مرکب (بلوک‌ها)​

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

func()
{
singleLineExpr();
}
func()
{
if ()
{
singleLineExpr();
}
}
func()
{
if ()
{
singleLineExpr();
}
else if ()
{
//
}
else
{
//
}
}

نامگذاری​

توابع​

توابع باید با PascalCase نامگذاری شوند.

متغیرهای سراسری​

متغیرهای سراسری اعلان شده با new همیشه باید از PascalCase با پیشوند g_ استفاده کنند، پس g_VariableName، اما اگر با static اعلان شده‌اند همیشه باید از PascalCase با پیشوند s_ استفاده کنند، پس s_VariableName

سراسری‌های ثابت باید از SCREAMING_SNAKE_CASE استفاده کنند.

متغیرهای محلی​

متغیرهای محلی همیشه باید از camelCase استفاده کنند و هرگز نباید از نام‌های تک حرفی استفاده کنند، به جز:

  • i، j، k و غیره در حلقه‌های for
  • x، y، z و غیره در زمینه‌های ریاضی

شمارشگرها​

شمارشگرها، اگر نامگذاری شده‌اند، باید با E_ (تگ قوی) یا e_ (تگ ضعیف) شروع شوند

فیلدهای شمارشگر نیز باید SCREAMING_SNAKE_CASE باشند و از نام شمارشگر به عنوان پیشوند استفاده کنند.

static enum E_PLAYER_DATA {
E_PLAYER_CASH,
Float:E_PLAYER_HEALTH,
}

استفاده از تگ ضعیف

static enum e_PLAYER_DATA {
E_PLAYER_CASH,
Float:E_PLAYER_HEALTH,
}

فیلدهای شمارشگر بدون نام نیز باید SCREAMING_SNAKE_CASE باشند و از نام شمارشگر به عنوان پیشوند استفاده کنند.

static enum {
ENUMATOR_INTEGER,
Float:ENUMATOR_FLOAT,
}

شمارشگرها همیشه باید static اعلان شوند مگر خارج از ماژول استفاده شوند.

ماکروها و تعریف‌های پیش‌پردازنده​

ماکروها همیشه باید از SCREAMING_SNAKE_CASE استفاده کنند صرف نظر از کاربردشان.

تعریف‌های پیش‌پردازنده (تعریف‌های ثابت) نیز باید از SCREAMING_SNAKE_CASE استفاده کنند.

این کمک می‌کند بین متغیرها و ثابت‌ها و همچنین توابع و ماکروها تمایز قائل شد.

عموماً توصیه می‌شود از اختراع عناصر نحوی جدید خودداری شود تا از سردرگمی تازه‌کارها در مورد اینکه کدام کلمات جزء زبان هستند و کدام کلمات از کتابخانه‌ها هستند جلوگیری شود.

اما برخی کتابخانه‌های قدیمی این کار را می‌کنند و نمی‌توانند به دلیل سازگاری با گذشته تغییر کنند.

مستندسازی​

همیشه توابع صادراتی را با کامنت خط ساده در قالب // FunctionName does X, Y and Z and returns A مستند کنید که کلمه اول نام خود تابع است و به دنبال آن توضیح مختصری از کارش. نیازی نیست وقت را صرف توضیح هر پارامتر جداگانه کنید. برای مثال:

// LoadPlayerAccount is called to initiate the account load process. This
// function will trigger HTTP calls to get player data, it will display dialogs
// to the player and eventually, once the process has completed, the event
// `OnPlayerLogin` is emitted on success. On failure, the player is kicked.
stock Error:LoadPlayerAccount(playerid)
{
// code...
}

هر بسته باید README داشته باشد و، در صورت لزوم، هر ماژول باید کامنتی در اولین خط داشته باشد که توضیح دهد آن ماژول چه چیزی ارائه می‌دهد.