احسان رضایی

یک توسعه دهنده

رعایت اصول و سبک کدنویسی

در PHP , برنامه نویسی , / تاریخ ارسال 04-12-1395 / 2 نظر / آخرین ویرایش 15-07-1403

سبک کدنویسی که در فریمورک و extension های رسمی استفاده میشه دارای اصول، قواعد و قانون های خودش هست. پس اگر تصمیم دارید چیزی به هسته اضافه کنید باید این قواعد رو در نظر بگیرید حتی در غیر این صورت هم رعایت این موارد خالی از لطف نیست و توصیه میکنم این کارُ انجام بدین. در حالی که میتونید راحت باشید، شما مجبور به رعایت این سبک در application خودتون نیستید...

نگاه کلی

به طور کلی ما از سبک PSR-2 استفاده میکنیم و هر چیزی که در این سبک وجود داره اینجا هم هست.

- در فایل ها باید از برچسب های php?> و =?> استفاده شود.

- در پایان هر فایل باید یک خط جدید(newline) داشته باشید.

- encoding فایل برای کد های php باید UTF-8 without BOM باشد.

-  به جای tab از 4 فضای خالی(space) استفاده کنید.

- نام کلاس ها باید به صورت StudlyCaps تعریف شوند.

- ثابت های داخل کلاس تماما باید با حروف بزرگ و گاهی با جداکننده "_" تعریف شوند.

- نام متد ها و پراپرتی ها باید به صورت camelCase تعریف شوند.

- پراپرتی های خصوصی(private) باید با "_" شروع شوند.

- همیشه از elseif جای else if استفاده کنید.

 

فایل ها

- در فایل ها باید از برچسب های php?> و =?> استفاده کرد نه از ?> .

- در انتهای فایل های php نباید از تگ <? استفاده کنید.

- در انتهای هر خط نباید space وجود داشته باشد

- پسوند فایل هایی که شامل کد php هستند باید php. باشد.

- encoding فایل برای کد های php باید UTF-8 without BOM باشد.

کلاس ها

- نام کلاس ها باید به صورت CamelCase تعریف شوند.

- آکولاد باز باید در خط بعدی، زیر نام کلاس نوشته شود.

- تمام کلاس ها باید بلاک مستندات مطابق استاندارد PHPDoc داشته باشند.

- برای تمام کد های داخل کلاس باید با 4 space فاصله ایجاد کنید.

 - فقط یک کلاس داخل هر فایل php باید موجود باشد.

- تمام کلاس ها باید namespaced داشته باشند.

- نام کلاس باید معال نام فایل و namespace باید مطابق مسیر آن باشد.

/** * Documentation */
class MyClass extends \yii\Object implements MyInterface
{    
    // code
}

ثابت ها

- ثابت های داخل کلاس تماما باید با حروف بزرگ و گاهی با جداکننده "_" تعریف شوند.

<?php
class Foo
{    
    const VERSION = '1.0';
    const DATE_APPROVED = '2012-06-01';
}

پراپرتی ها

- از کلید واژه های public، protected و private استفاده کنید.

- پراپرتی های public و protected باید در بالای کلاس و قبل از متد ها تعریف شوند. private هم همینطور اما ممکن هست کاهی قبل از متدی که با آن مرتبط هست آورده شود.

- ترتیب تعریف پراپرتی ها باید به صورت اول public، دوم protected و سپس private باشد! هیچ قانون سختی برای رعایت این مورد نیست...

- برای خوانایی بهتر میتونید از خط خالی بین گروه های public، protected و private استفاده کنید.

- متغییر های private باید مثل varName_$ باشند.

- اعضای عمومی داخل کلاس باید به صورت camelCase تعریف شوند.(حرف اول کوچک، با CamelCase فرق میکنه).

- بهتره از نام هایی مثل i$ و j$ استفاده نکنید.

<?php
class Foo
{
    public $publicProp1;
    public $publicProp2;

    protected $protectedProp;

    private $_privateProp;

    public function someMethod()
    {
        // ...
    }
}

متد ها

- توابع و متد ها باید camelCase باشند.

- نام باید هدف رو نشون بده.

- از کلید واژه های public، protected و private استفاده کنید.

- آکولاد باز باید در خط بعدی یعنی زیر نام متد قرار بگیره.

/** * Documentation */
class Foo{
    /**
     * Documentation
     */
    public function bar()
    {
        // code
        return $value;
    }
}

- برای متد ها باید مستندات بنویسید(PHPDoc).

- در PHPDoc نوع param@, var@, property@ و return@ باید مشخص شود(bool, int, string, array یا null).

- برای تایپ آرایه در PHPDoc از []ClassName استفاده کنید.

- خط اول PHPDoc باید هدف یک متد رو شرح بده.

- اگر متد ها چیزی رو بررسی میکنن مثل isActive بخش PHPDoc رو باید با عبارت Checks whether شروع کنید.

- return@ در PHPDoc  یاید دقیقا مشخص کنه چی بازگردانده میشود.

<?php
/** * Checks whether the IP is in subnet range * * @param string $ip an IPv4 or IPv6 address * @param int $cidr the CIDR lendth * @param string $range subnet in CIDR format e.g. `10.0.0.0/8` or `2001:af::/64` * @return bool whether the IP is in subnet range */
private function inRange($ip, $cidr, $range)
{
    // ... 
}

انواع

- تمام انواع و مقادیر باید با حروف کوچک نوشته شوند مثل true, false, null و array.

- تغییر نوع یک متغییر خیلی بده، به این مثال توجه کنید:

    public function save(Transaction $transaction, $argument2 = 100)
    {
        $transaction = new Connection; // bad
        $argument2 = 200; // good
    }

- اگر رشته ی شما شامل متغییر های دیگه این نیست از تک کوتیشن جای دابل کوتیشن استفاده کنید.

$str = 'Like this.';

- دو روش زیر مناسب برای جایگزینی هستند:

$str1 = "Hello $username!";
$str2 = "Hello {$username}!";

- برای الحاق قبل و بعد کاراکتر dot فاصله بذارید

$name = 'Yii' . ' Framework';

- و اگر رشته ی شما بلند بود میتونید اینطور عمل کنید:

$sql = "SELECT *"
    . "FROM `post` "
    . "WHERE `id` = 121 ";

- برای تعریف آرایه ها از نحوه ی کوتاه اون یعنی [] استفاده کنید.

- از ایندکس منفی در آرایه ها استفاده نکنید.

- روش های زیر قابل قبول و مناسب هستند:

        $arr = [3, 14, 15, 'Yii', 'Framework'];
        $arr = [3, 14, 15, 92, 6, $test, 'Yii', 'Framework',];
        $config = ['name' => 'Yii', 'options' => ['usePHP' => true],];

دستورات کنترلی

- در دستورات کنترلی قبل و بعد پرانتز space بذارید.

- آکولاد باز در همان خط دستور قرار میگیرد.

- آکولاد بسته در خط جدید.

- برای دستورات یک خطی همیشه از پرانتز استفاده کنید.

        if ($event === null) {
            return new Event();
        }
        if ($event instanceof CoolEvent) {
            return $event->instance();
        }
        return null; // the following is NOT allowed:if (!$model && null === $event)    throw new Exception('test');

- بعد از return از else استفاده نکنید

        $result = $this->getResult();
        if (empty($result)) {
            return true;
        } else {    // process result}
        }

- اینطور بهتره:

        $result = $this->getResult();
        if (empty($result)) {
            return true;
        }// process result

- از فرمت زیر برای switch استفاده کنید

        switch ($this->phpType) {
            case 'string':
                $a = (string)$value;
                break;
            case 'integer':
            case 'int':
                $a = (int)$value;
                break;
            case 'boolean':
                $a = (bool)$value;
                break;
            default:
                $a = null;
        }

- روش مناسب صدا زدن توابع همراه با پارامتر ها هم اینطور صحیحه

        doIt(2, 3);
        doIt(['a' => 'b']);
        doIt('a', ['a' => 'b', 'c' => 'd',]);

- در توابع بی نام بین function/use فضای خالی(space) بذارید.

// good
        $n = 100;
        $sum = array_reduce($numbers, function ($r, $x) use ($n) {
            $this->doMagic();
            $r += $x * $n;
            return $r;
        });
// bad
        $n = 100;
        $mul = array_reduce($numbers, function ($r, $x)use ($n) {
            $this->doMagic();
            $r *= $x * $n;
            return $r;
        });

مستند نویسی 

- phpDoc رو بخونید و موارد اونُ رعایت کنید.

- کد بدون مستندات مجاز نیست.

- تمام کلاس ها باید شامل بلاک مستندات در ابتدای فایل باشند.

- نیازی به نوشتن return@ ندارید اگر متد شما اگر چیزی را برنمیگرداند.

- به مثال های زیر توجه کنید:

1) فایل

<?php
/** * @link http://www.yiiframework.com/ * @copyright Copyright (c) 2008 Yii Software LLC * @license http://www.yiiframework.com/license/ */

2) کلاس

/** * Component is the base class that provides the *property*, *event* and *behavior* features. * * @include @yii/docs/base-Component.md * * @author Qiang Xue <[email protected]> * @since 2.0 */
class Component extends \yii\base\Object

3) متد یا تابع

/** * Returns the list of attached event handlers for an event. * You may manipulate the returned [[Vector]] object by adding or removing handlers. * For example, * * ``` * $component->getEventHandlers($eventName)->insertAt(0, $eventHandler); * ``` * * @param string $name the event name * @return Vector list of attached event handlers for the event * @throws Exception if the event is not defined */
public function getEventHandlers($name)
{
    if (!isset($this->_e[$name])) {
        $this->_e[$name] = new Vector;
    }
    $this->ensureBehaviors();
    return $this->_e[$name];
}

- از // برای کامنت گذاری استفاده کنید نه از #.

- در خطوطی که کامنت گذاشتین نباید کد بنویسید، یعنی اون خط برای اون کامنت باید باشه.

قوانین بیشتر

- تا جایی که میتونید از تابع empty به جای === استفاده کنید.

- اگر شرایط تو در تویی در کد شما وجود نداره return زود هنگام یا ساده تر بگم return وسط متد مشکلی نخواهد داشت.

- همیشه از static جای self به جز موارد زیر استفاده کنید:

1) دسترسی به ثابت ها باید با self انجام بشه.

2) دسترسی به پراپرتی های خصوصی باید با self انجام بشه.

3) مجاز به استفاده از self برای صدا زدن توابع در مواقعی مثل فراخوانی بازگشتی هستید.

نام گذاری namespace ها

- از حرف کوچک استفاده کنید.

- از فرم جمع اسم ها برای نشان دادن یک شی استفاده کنید مثل validators.

- از فرم منفرد اسم ها برای قابلیت ها و امکانات استفاده کنید مثل web.

- بهتره فضای نام تک کلمه ای باشه در غیر این صورت از camelCase استفاده کنید.

پیشنهاد

کتاب‌ها

کتاب الگوهای طراحی به بیان ساده(design patterns / دیزاین پترن)

در مهندسی نرم افزار، design patterns(الگوهای طراحی) راه حل‌های قابل استفاده برای مشکلاتی هستند که معمولاً در طراحی نرم‌افزار اتفاق می افتند.

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

کتاب refactoring / ریفکتورینگ

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

در کتاب Refactoring اثر Martin Fowler نوشته شده: refactoring تکنیک مرتب/منظم سازی برای تجدید ساختار کد موجود است. تغییر ساختار داخلی کد بدون تغییر رفتار خارجی آن.

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

ارسال نظر

علی محمد شیرازی در تاریخ 1396/05/18 - 23:24 نوشته
سلام.چقدر قشنگ و خلاصه توضیح دادید.ترسم ریخت.بعضی چیزا برام سنگینه که فکر کنم به خاطر عدم تسلط من به php است.اگر یک آموزش پروژه محور داشته باشیم خیلی خوبه و این که چه سایتهایی با yii ساخته شده.ممنون از آموزش رایگان .
پاسخ احسان:

خواهش میکنم. داخل گیت هاب میتونید پروزه های زیادی رو پیدا کنید. همچنین در انجمن yii بعضی از دوستان پروژه های خودشونُ معرفی کردن.

علی در تاریخ 1398/04/18 - 16:52 نوشته
سلام و عرض خسته نباشید واقعا لذت بردم ممنونم خیلی خوب توضیح داده شده و من جایی ندیدم این سبک رو مطرح کنه
پاسخ احسان:

سلام علی جان. خوشحالم که تونستی ازش استفاده کنی و برات مفید بود. موفق باشی.