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

راهنمای سبک 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 داشته باشد و، در صورت لزوم، هر ماژول باید کامنتی در اولین خط داشته باشد که توضیح دهد آن ماژول چه چیزی ارائه می‌دهد.