关于php:好孩子的编码习惯

5次阅读

共计 4915 个字符,预计需要花费 13 分钟才能阅读完成。

前言

我常常能听到一些对话
狗腿子 A: 哇 我刚刚去改 ** 我的项目的代码,看的我有点狐疑人生
狗腿子 B: 我当初我的项目的跟屎山一样
狗腿子 C: 我隔壁那哥们每天写代码都特地随性,我有点按耐不住我的刀
…..

明天跟大家聊聊一些 我眼中 好孩子的编码习惯,而不是代码格调习惯(psr-*),当然还是强烈建议大家代码格调跟psr-4 靠齐。

举荐一本《代码整洁之道》,这本书我曾经书都快翻烂了,墙裂举荐!!!

不适度的 if 嵌套判断

案例背景
有个函数须要判断用户是否参加流动

案例代码

    if (用户 == VIP) {if (用户的过期工夫 <= 1 个月内) {if (用户没加入过工作) {return true;}
        } else {return false;}
    } else {return true}
    

面对这种多条件的判断能够试着用 拦截法 逆向思维
拦截法 只有符合条件立马返回后果,不再嵌套的 if。能够了解成横向判断变成纵向判断。

舒适感
从上往下看 > 从左往右看

逆向思维 大家上学的时候都理解过,与其漫天去找合乎的条件还不如找不符合条件,这样的逻辑代码能够少很多。

    if (用户 != VIP) {return true;} 
    
    if (用户加入过工作) {return false;}
    
    if (用户的过期工夫 <= 1 个月内) {return true;}
    
    return false;
    

不适度的 try-catch 嵌套

我遇到过很多我的项目都适度嵌套 try-catch 导致最上层的 try-catch catch 了寂寞。

案例代码

function insertUser($data)
{
    try {userIsInValid();
    } catch (Exception $exception) {}}

function userIsInValid()
{
    try {// 逻辑判断} catch (Exception $exception) {return true;}
    return true;
    
}

这样的代码没有问题,然而如果假如 userIsInValid 真的产生代码级的谬误没法晓得那里出问题,尽管不会毁坏业务的健壮性。
可能有人说了在 Excetion 加个日志,然而如果嵌套的 try-catch 多了,排查日志也是一件很苦楚的事件。

1. 尽可能业务最上层包裹异样 除非网络 IO 申请函数。
2. 如果非要异样嵌套 须要定义每个异样的类型。
3. 尽可能依据特定的异样进行 catch 不倡议间接 catch Exception。
4. 异样和日志是个cp,还是不要遗记了。

<?php

function insertUser($data)
{
    try {userIsInValid();
    } catch (Exception $exception) {
        // 日志
        // 业务解决
    } catch (HttpException $httpException) {
       // 日志
       // 业务解决
    }
}

function userIsInValid()
{
    //
    return true;
}

不要用 if-else 做谬误类型判断

案例代码 (起源某个网民前段时间征询)

<?php

.....
if ($code === 'NOTENOUGH') {packApiData(400014, 'Company have no enough money to pay', [], '企业余额有余');
} elseif ($code === 'AMOUNT_LIMIT') {packApiData(400015, 'Amount limit', [], '金额超限或被微信风控拦挡');
} elseif ($code === 'OPENID_ERROR') {packApiData(400016, 'Appid and Openid does not match', [], 'Openid 格局谬误或不属于此公众号');
} elseif ($code === 'SEND_FAILED') {
    // 付款谬误, 要查单来看最终后果
    if ($orderInfo[1]['status'] == 'SUCCESS') {
        // 还是胜利给了,扣回余额
        
        packApiData(200, 'success', [$orderInfo[1]]);
    } else {packApiData(400017, 'Weixin pay failed', [], '微信领取付款失败');
    }
} elseif ($code === 'SYSTEMERROR') {packApiData(400018, 'Weixin pay server error', [], '微信领取服务器谬误');
} elseif ($code === 'NAME_MISMATCH') {packApiData(400019, 'Real name mismatch', [], '微信用户的真名校验失败');
} elseif ($code === 'FREQ_LIMIT') {packApiData(400020, 'Api request frequently', [], '微信领取接口调用过于频繁,请稍候再申请');
} elseif ($code === 'MONEY_LIMIT') {packApiData(400021, 'Company have reached total payment limit', [], '曾经达到今日付款总额下限');
} elseif ($code === 'V2_ACCOUNT_SIMPLE_BAN') {packApiData(400022, 'This payment account has no real name', [], '用户的微信领取账户未实名');
} elseif ($code === 'SENDNUM_LIMIT') {packApiData(400023, 'The number of times the user paid today exceeded the limit', [], '该用户今日收款次数超过限度');
}

这样的代码可能写起来特地难受,然而前期进行业务的减少改写和工夫的积淀,容易变成让人胆怯的屎山代码。

咱们用 mapping 错误码来调整下

function packApiDataByOrderError($code)
{
    $errorCodeMappins = [
        "NOTENOUGH" => [
            "code" => 400014,
            "wx_message" => "Company have no enough money to pay",
            "error_message" => "企业余额有余"
        ],

        "AMOUNT_LIMIT" => [
            "code" => 400015,
            "wx_message" => "Amount limit",
            "error_message" => "金额超限或被微信风控拦挡"
        ],

        .....
    ];

    if (array_key_exists($code, $errorCodeMappins)) {
        packApiData($errorCodeMappins[$code]['code'],
            $errorCodeMappins[$code]['wx_message'],
            [],
            $errorCodeMappins[$code]['error_message']
        );
    }

    packApiData(
        999999,
        "undefined message",
        [],
        "未知谬误"
    );
}

倡议 errorCodeMappins 不要放在函数内,能够放在类顶部或者专门枚举类。
通过 errorCode 能够防止调整主流程代码,可能保障主流程的代码比拟精简也能对不同的 code 进行谬误的定义

if ($code == "SEND_FAILED") {
    // 付款谬误, 要查单来看最终后果
    if ($orderInfo[1]['status'] == 'SUCCESS') {
        // 还是胜利给了,扣回余额
        PDOQuery($dbcon, 'UPDATE user SET money=money-? WHERE open_id=?', [$payAmount, $openId], [PDO::PARAM_INT, PDO::PARAM_STR]);
        packApiData(200, 'success', [$orderInfo[1]]);
    } else {packApiData(400017, 'Weixin pay failed', [], '微信领取付款失败');
    }
}

packApiDataByOrderError($code);

在适合的场景应用设计模式

上述可能只能针对错误码进行革新,如果万一咱们须要不同的谬误进行逻辑解决还怎么办。这时候能够思考用设计模式 (比方用以多态取代条件表达式)

设计模式 固好但不要适度应用,不然整个我的项目更难保护,你要深信将来的你队友不晓得是什么样的生物

$callbackCodeMappings = ["SEND_FAILED" => OrderSendFailed::class,];

if (array_key_exists($code, $callbackCodeMappings)) {$class = new $callbackCodeMappings[$code];
    $class->handle();}


interface OrderStateImp
{public function handle($context);
}

class OrderSendFailed implements  OrderStateImp
{public function handle($context)
    {}}

$callbackCodeMappings同样倡议配置专门枚举文件内。
给出得代码比拟毛糙,其实能够更加健壮性的做一些判断

激励用全局错误码来管制谬误

写接口的咱们对以下的 json 格局特地相熟

{
    "success": true,
    "error_code": 0,
    "message": "","results": []}

对以下的代码也曾经相熟

if (***) {$this->error(999,"****", []);
}

这样的后果的错误码容易反复没有对立治理,事实上惟一错误码应该有以下帮忙。
1. 前端能够依据错误码做逻辑解决
2. 依据错误码能间接疾速定位到错误代码

倡议

<?php

namespace App\ErrorCode;

class UserErrorCode
{
    const USER_DISABLE_ERROR = [
        "error_code" => 1050001,
        "message" => "用户已被停用"
    ];
}

$this->error(UserErrorCode::USER_DISABLE_ERROR);

错误码倡议

1- 2 位 – 我的项目码 | 3- 4 位 – 模块码 | 5- 7 位具体业务错误码

牢靠的命名标准

不牢靠的命名总会让人误导。
比方变量命名为 userArrayList 我认为是个数组列表变量, 事实上这个特么是个对象列表。

1. 做有意义的辨别
比方 singleUserItemuserItem 有啥区别
比方 getUserListgetUsers 有啥区别

2. 能够通过 搜寻翻译 能晓得的变量含意
不要把变量贴入 搜寻翻译 会呈现七七八八的货色
3. 如果真的不晓得该怎么翻试试用拼音把别硬凹了
比方之前做 百度 的一个接口对接
变量命名为 hundredDegree 而不是 baidu

其余的能够参照《代码简洁之道》

函数的繁多职责

最最最最初也是最重要的,代码的恶心大多数来源于函数的职责不清晰,有全都塞在一起的、东一块西一块的。
其实对于繁多职责有很多文章在形容,如何去测验或者去写符合标准的繁多职责。
画流程图
如果你能把业务的流程图画的特地清晰,那么你的函数的职责也就定下来了。

<?php

// 兑换逻辑
function doExchange()
{if (checkIsLock()) { }
    lock();
    if (!checkUserIsExchange()) { }
    costUserPoint();
    exchangeGoods();}
// 判断是否乐观锁
function checkIsLock(){}
// 上乐观锁
function lock(){}
// 判断用户是否能够兑换
function checkUserIsExchange(){}
// 扣除积分
function costUserPoint(){}
// 兑换商品
function exchangeGoods(){}

最初

上述为 洪光光 心中的好孩子的习惯,也有可能是你眼中坏孩子的习惯。如果你认为是坏孩子的习惯或者认为还有其余好孩子的习惯欢送评论 撕逼 探讨。
毕竟

正文完
 0