淺談專案程式碼規範

yandihuangdi發表於2021-06-13

程式碼規範,此話題略範。從何說起?各司企皆具規範,大同小異,也有自稱一派者,稀也。

官方規範

《PHP PSR 標準規範》是現有的標準規範,本人也是該規範的追隨者,求同存異,會加一些自己的習慣進去,此習慣主要來自於專案經驗。

如果你還沒有看過官方標準規範,建議你進去看下。

程式碼規範的優勢

齊心協力 意思是認識一致,共同努力。出自《墨子·尚賢》。

此成語充分的說明了程式碼規範的優勢。在閱讀程式碼的時候,閱讀者會因為程式碼中的註釋,規範命名,加速了非己所寫程式碼的理解。閱讀效率上來了,帶來了更好的開發效率,行話曰:程式碼是寫給人看的。此處的人,是你也是你的團隊成員。

推薦的程式碼規範

目前我自己形成了一套編寫習慣,略覺可揚,此習慣也是今年(2021)初具形態,故以示之,望與眾行內人士共論之。若有增進之處,望暢言,笑迎之。

子曰:三人行,必有我師焉。擇其善者而從之,其不善者而改之。

程式碼規範思路舉例

我將自己寫的 demo 展示如下:

app/Http/Controllers/Api/AuthController.php

    // 會員-登入
    public function login(Request $request)
    {
        $rules = [
            'username' => 'required|alpha_num|between:3,20',
            'password' => 'required|alpha_num|between:6,12',
        ];
        $messages = [];
        // 替換 傳參 為指定內容
        $customAttributes = [
            'username' => '使用者名稱',
            'password' => '密碼',
        ];
        $validator = Validator::make($request->all(), $rules, $messages, $customAttributes);
        if ($validator->fails())
        {
            return response()->json([
                'code'   => 403,
                'errors' => $validator->errors()->toArray()
            ], 403);
        }

        // users.username
        $username = $request->post('username');
        // users.password
        $password = $request->post('password');

        // 校驗使用者名稱是否存在
        if (User::where('username', $username)->exists() === false)
        {
            return response()->json([
                'code'   => 403,
                'errors' => ['username' => '會員不存在']
            ], 403);
        }
        $user = User::where('username', $username)->first();
        // 校驗使用者密碼
        if (User::generatePassword($password, $user->salt) != $user->password)
        {
            return response()->json([
                'code'   => 403,
                'errors' => ['password' => '密碼錯誤']
            ], 403);
        }

        $token  = UserToken::generateToken($user->id);
        $key    = UserToken::getTokenKey($token);
        // 60 * 60 * 24 * 30, 30 day
        $second = 2592000;

        DB::beginTransaction();
        try {
            // redis 寫入 token
            Redis::setEx($key, $second, $token);
            // token 寫入資料庫
            UserToken::setToken($user->id, $token);

            DB::commit();
        } catch (\Exception $e) {
            DB::rollBack();

            $context = [
                'function'  => __CLASS__.'->'.__FUNCTION__.'()',
                'line'      => __LINE__,
                'error'     => $e->getMessage()
            ];
            Log::channel('api-controller')->error('使用者登入', $context);

            return response()->json([
                'code'   => 403,
                'errors' => ['登入失敗']
            ], 403);
        }

        $data = [
            'token'     => $token,
            'username'  => $username,
        ];

        return response()->json([
            'code'      => 200,
            'data'      => $data,
            'message'   => 'success'
        ], 200);
    }// login() end

以上程式碼摘取於 api 控制器中,處理業務為 使用者-登入。
程式碼分為 四個片區:

  1. 輸入內容驗證區
  2. 業務邏輯區
  3. 業務處理區
  4. 業務處理返回區

每一個片區都有自己的工作內容,互相關聯,但互不干擾。如此而來,我們在讀程式碼的時候,就更加容易做區分了。

app/Models/User.php

    /**
     * 生成記錄
     *
     * @param string $username          users.username
     * @param string $password          users.password
     * @param string $payment_password  users.payment_password
     * @param string $phone             users.phone
     * @return int
     */
    public static function generateLog(string $username, string $password, string $payment_password = '', string $phone = ''): int
    {
        $salt = self::generateSalt(6);
        if (strlen($payment_password) > 0)
            $payment_password = self::generatePassword($payment_password, $salt);

        $insert = [
            'username'          => $username,
            'password'          => self::generatePassword($password, $salt),
            'payment_password'  => $payment_password,
            'phone'             => $phone,
            'salt'              => $salt,
            'is_lock'           => 'n',
            'is_frozen'         => 'n',
            'created_at'        => date('Y-m-d H:i:s'),
            'updated_at'        => date('Y-m-d H:i:s'),
        ];
        return self::insertGetId($insert);
    }// generateLog() end

模型方法,按照規範,應該是單一功能,如果是多功能,建議做拆分,提升維護性。

結語

寥寥數字,無法完全表明全意。總算是有個開始,將自己的經驗總結吐出出來。望多包涵。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章