前言
本次實(shí)踐是對一個(gè)現(xiàn)有的app的項(xiàng)目的后臺進(jìn)行代碼規(guī)范国旷,通過對比來實(shí)現(xiàn)bad code 到 good code 的一次實(shí)踐
目的是提高代碼的可讀性
關(guān)于規(guī)范
- 高效編碼 - 避免了過多的選擇造成的『決策時(shí)間』浪費(fèi)盲链;
- 風(fēng)格統(tǒng)一 - 最大程度統(tǒng)一了開發(fā)團(tuán)隊(duì)成員代碼書寫風(fēng)格和思路拜秧,代碼閱讀起來如出一轍爆雹;
- 減少錯(cuò)誤 - 減小初級工程師的犯錯(cuò)幾率挠说。
開發(fā)哲學(xué)
DRY –「Don’t Repeat Yourself」不寫重復(fù)的邏輯代碼近速;
約定俗成 - 「Convention Over Configuration」扭屁,優(yōu)先選擇框架提倡的做法,不過度配置嘉冒;
KISS - 「Keep it Simple, Stupid」提倡簡單易讀的代碼曹货,不寫高深、晦澀難懂的代碼讳推,不過度設(shè)計(jì)顶籽;
主廚精選 - 讓有經(jīng)驗(yàn)的人來為你選擇方案,不獨(dú)創(chuàng)方案银觅;
官方提倡 - 優(yōu)先選擇官方推崇的方案
感受
在一個(gè)項(xiàng)目中如果出現(xiàn)風(fēng)格不統(tǒng)一的寫法蜕衡,即使幾種寫法你都能明白,也是規(guī)則允許的寫法,即便是單人開發(fā)的項(xiàng)目慨仿,你在閱讀過程中久脯,也會因?yàn)檫@個(gè)原因出現(xiàn)短暫的停頓或者在寫代碼時(shí)會出現(xiàn)一個(gè)小的決策選擇,所以風(fēng)格的統(tǒng)一是非常重要的镰吆,尤其是多人開發(fā)的項(xiàng)目中帘撰,更應(yīng)該注意開發(fā)規(guī)范。
與其無休止的爭論哪種選項(xiàng)最好万皿,還不如只知道 一種選項(xiàng)摧找。這 一種選項(xiàng) 能覆蓋大部分的用例,且兼?zhèn)溟_發(fā)效率牢硅、程序執(zhí)行效率蹬耘、擴(kuò)展性、安全性等最佳實(shí)踐减余,當(dāng)再次遇到此類需求時(shí)综苔,毫不猶豫地使用這 一種選項(xiàng) 直接了當(dāng)?shù)亟鉀Q問題。
決策已提前做好位岔,沒必要浪費(fèi)時(shí)間多次決策如筛,節(jié)省時(shí)間,提高效率抒抬。
開發(fā)規(guī)范一旦統(tǒng)一杨刨,所有團(tuán)隊(duì)成員嚴(yán)格遵守,你會發(fā)現(xiàn)擦剑,你的隊(duì)友寫的代碼就如你自己寫的一樣妖胀,編碼愉悅感提高了,整個(gè)項(xiàng)目代碼閱讀起來更加流暢惠勒,工作效率自然也會因此提高做粤,同時(shí)代碼的健壯性也得到了保障。
環(huán)境說明
一般情況下捉撮,一個(gè)項(xiàng)目 應(yīng)該 有以下三個(gè)基本的項(xiàng)目環(huán)境:
Local - 開發(fā)環(huán)境
Staging - 線上測試環(huán)境
Production - 線上生產(chǎn)環(huán)境
關(guān)于多人開發(fā)
多人開發(fā),我們應(yīng)該保證各自計(jì)算機(jī)系統(tǒng)的統(tǒng)一妇垢,開發(fā)環(huán)境的統(tǒng)一巾遭,編碼工具的統(tǒng)一,只有各方面都是統(tǒng)一的闯估,才有利于形成工作流和使用經(jīng)驗(yàn)的傳承
代碼風(fēng)格規(guī)范
代碼風(fēng)格 必須 嚴(yán)格遵循 PSR-2 規(guī)范灼舍。
1.行文規(guī)范
- 問題分析
- 沒必要的注釋
- 沒對齊的 ->
- 沒有使用更簡潔的代碼
- bad code
//地址列表
public function fetchList(Request $request)
{
$data = DB::table('goldcat_address')
->whereNull('deleted_at')
->where([
'user_id' => $request->user_id,
])->get();
return success($data);
}
- good code
public function fetchList(Request $request)
{
$data = DB::table('goldcat_address')
->whereNull('deleted_at')
->where('user_id', $request->user_id)
->get();
return success($data);
}
2.重復(fù)的代碼片段,變量涨薪,以及沒必要的else
修改前 代碼字?jǐn)?shù)統(tǒng)計(jì)2545 97行
<?php
/*
* @Author: your name
* @Date: 2021-06-29 13:45:05
* @LastEditTime: 2021-07-07 10:16:08
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: \goldcat\app\Http\Controllers\Address\AddressController.php
*/
namespace App\Http\Controllers\Address;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class AddressController extends Controller
{
//地址列表
public function fetchList(Request $request)
{
$data = DB::table('goldcat_address')
->whereNull('deleted_at')
->where([
'user_id' => $request->user_id,
])->get();
return success($data);
}
//添加地址
public function add(Request $request)
{
$data = $request->all();
if ($request->default == 1) {
DB::table('goldcat_address')->where([
'user_id' => $request->header('uid'),
])->update([
'default' => 0,
]);
}
$id = DB::table('goldcat_address')->insertGetId($data);
return $this->fetchOne($id);
}
public function fetchOne($id)
{
$data = DB::table('goldcat_address')->find($id);
return success($data);
}
//更新
public function update(Request $request)
{
$data = DB::table('goldcat_address')->find($request->id);
if (isset($data->user_id) && $request->header('uid') == $data->user_id) {
$addressData = $request->all();
if ($request->default == 1) {
DB::table('goldcat_address')->where([
'user_id' => $request->header('uid'),
])->update([
'default' => 0,
]);
}
unset($addressData['user_id']);
unset($addressData['id']);
DB::table('goldcat_address')->where([
'id' => $request->id,
])
->update($addressData);
return $this->fetchOne($request->id);
} else {
return fail('授權(quán)失敗');
}
}
//刪除地址
public function del(Request $request)
{
DB::table('goldcat_address')
->where([
'id' => $request->id,
])
->update([
'deleted_at' => date('Y-m-d H:i:s'),
]);
return success('刪除成功');
}
}
修改后 代碼字?jǐn)?shù)統(tǒng)計(jì)2157 80行
<?php
namespace App\Http\Controllers\Address;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
class AddressController extends Controller
{
public function add(Request $request)
{
$data = $request->all();
if (1 == $request->default) {
DB::table('goldcat_address')
->where('user_id', $request->header('uid'))
->update(['default' => 0]);
}
$id = DB::table('goldcat_address')->insertGetId($data);
return $this->fetchOne($id);
}
public function update(Request $request)
{
$addressId = $request->id;
$authorId = DB::table('goldcat_address')
->where('id', $addressId)
->value('user_id');
if ($authorId && $request->header('uid') == $authorId) {
$addressData = $request->all();
if ($request->default == 1) {
DB::table('goldcat_address')
->where('user_id', $authorId)
->update(['default' => 0]);
}
unset($addressData['user_id']);
unset($addressData['id']);
DB::table('goldcat_address')
->where('id', $addressId)
->update($addressData);
return $this->fetchOne($addressId);
}
return fail('授權(quán)失敗');
}
public function fetchOne($id)
{
$data = DB::table('goldcat_address')->find($id);
return success($data);
}
public function fetchList(Request $request)
{
$data = DB::table('goldcat_address')
->whereNull('deleted_at')
->where('user_id', $request->user_id)
->get();
return success($data);
}
public function del(Request $request)
{
DB::table('goldcat_address')
->where('id', $request->id)
->update(['deleted_at' => date('Y-m-d H:i:s')]);
return success('刪除成功');
}
}
數(shù)據(jù)查詢時(shí)的一些格式規(guī)范
- 注意WHERE條件為1個(gè)和多個(gè)時(shí)的格式統(tǒng)一
- 使用新函數(shù)updateOrInsert 來代替先驗(yàn)證是否存在骑素,再根據(jù)結(jié)果進(jìn)行新增或者更新的操作,以使代碼閱讀起來邏輯性更強(qiáng)
//銀行卡的添加
public function cardAdd(Request $request)
{
//查看該用戶的銀行卡數(shù)量是否超過3張刚夺,超過則不能繼續(xù)添加
$count = DB::table('goldcat_bank_card')
->where([
'uid' => $request->header('uid'),
'status' => 1,
])
->count();
if ($count >= 3) {
return fail('最多只能添加三張銀行卡');
}
$card = $request->card;
//對銀行卡號進(jìn)行校驗(yàn),得到基本信息
$info = BankCard::info($card);
$validated = $info['validated'];
if (!$validated) {
return fail('卡號有誤');
}
//查看該銀行卡是否已經(jīng)存在
$realName = DB::table('goldcat_user_certification')
->where([
'uid' => $request->header('uid'),
'status' => 1,
])
->value('name');
$idCard = DB::table('goldcat_user_certification')
->where([
'uid' => $request->header('uid'),
'status' => 1,
])
->value('identity_card_number');
$exists = DB::table('goldcat_bank_card')->where([
'card' => $card,
'status' => 1,
])
->exists();
if ($exists) {
return fail('該銀行卡已被綁定');
}
//對銀行卡進(jìn)行真實(shí)性檢驗(yàn):正式服調(diào)用實(shí)名信息献丑,是否與申請人的姓名與身份證號一致
$check = $this->juheCheck($card, $realName, $idCard);
if (!$check) {
return fail('認(rèn)證信息不匹配末捣,銀行卡無效');
}
$name = $info['bankName'];
$cardTypeName = $info['cardTypeName'];
$bank = $info['bank'];
$exists = DB::table('goldcat_bank_card')->where([
'card' => $card,
])
->exists();
if ($exists) {
DB::table('goldcat_bank_card')
->where([
'card' => $card,
])
->update([
'uid' => $request->header('uid'),
'card' => $card, //卡號
'type' => $cardTypeName, //卡片類型
'bank' => $bank,
'name' => $name, //銀行名稱
'status' => 1,
]);
} else {
DB::table('goldcat_bank_card')
->insert([
'uid' => $request->header('uid'),
'card' => $card, //卡號
'type' => $cardTypeName, //卡片類型
'bank' => $bank,
'name' => $name, //銀行名稱
'status' => 1,
]);
}
return success('添加成功');
}
修改之后的
//銀行卡的添加
public function cardAdd(Request $request)
{
$card = $request->card;
//查看該用戶的銀行卡數(shù)量是否超過3張,超過則不能繼續(xù)添加
$count = DB::table('goldcat_bank_card')->where([
['uid', '=', $request->header('uid')],
['status', '=', 1],
])->count();
if ($count > 2) {
return fail('最多只能添加三張銀行卡');
}
//對銀行卡號進(jìn)行校驗(yàn),得到基本信息
$info = BankCard::info($card);
if (!isset($info['validated']) || !$info['validated']) {
return fail('卡號有誤');
}
//查看該銀行卡是否已經(jīng)存在
$exists = DB::table('goldcat_bank_card')->where([
['status', '=', 1],
['card', '=', $card],
])->exists();
if ($exists) {
return fail('該銀行卡已被綁定');
}
//對銀行卡進(jìn)行真實(shí)性檢驗(yàn):正式服調(diào)用實(shí)名信息创橄,是否與申請人的姓名與身份證號一致
$userInfo = DB::table('goldcat_user_certification')->where([
['uid', '=', $request->header('uid')],
['status', '=', 1],
])->select('name'.'identity_card_number')->first();
if (!$userInfo) {
return fail('請先完成實(shí)名認(rèn)證');
}
$check = $this->juheCheck($card, $userInfo->name, $userInfo->identity_card_number);
if (!$check) {
return fail('認(rèn)證信息不匹配箩做,銀行卡無效');
}
$bank = $info['bank'];
$name = $info['bankName'];
$cardTypeName = $info['cardTypeName'];
DB::table('goldcat_bank_card')->updateOrInsert([
'card' => $card, //卡號
'uid' => $request->header('uid'),
'type' => $cardTypeName, //卡片類型
'bank' => $bank,
'name' => $name, //銀行名稱
'status' => 1,
]);
return success('添加成功');
}
一段有問題的代碼
//根據(jù)銀行卡號返回銀行卡的銀行信息(銀行卡位數(shù)為16.17.19)
//預(yù)顯示 輸入第六位時(shí)就開始嘗試解析
public function backInfo(Request $request)
{
$card = $request->card;
//對于一個(gè)六位數(shù)至十位數(shù)的數(shù)字,對其進(jìn)行后補(bǔ)零操作妥畏,使其分別變成三個(gè)數(shù)字邦邦,分別是16位,17位醉蚁,19位
$cardLen = strlen($card);
$zeroNum = 16 - $cardLen;
$zero = '';
for ($i = 0; $i < $zeroNum; ++$i) {
$zero .= '0';
}
$card = $card.$zero;
for ($i = 17; $i < 20; ++$i) {
$card .= '0';
$info = BankCard::info($card);
$validated = $info['validated'];
if ($validated) {
return success([
'backName' => $info['bankName'],
'cardTypeName' => $info['cardTypeName'],
]);
}
}
}
問題分析
1.錯(cuò)誤時(shí)會沒有返回值
2.邏輯有點(diǎn)混亂燃辖,讓人有些看不到
3.對于大于16位的數(shù)字無法處理
4.漏掉了對16位的數(shù)字的驗(yàn)證修復(fù)后的代碼
//根據(jù)銀行卡號返回銀行卡的銀行信息(銀行卡位數(shù)為16.17.18 19)
//預(yù)顯示 輸入第六位時(shí)就開始嘗試解析
public function backInfo(Request $request)
{
$card = $request->card;
//對于一個(gè)小于20位的數(shù)字,補(bǔ)0使其位數(shù)逐漸增大网棍,在此過程中匹配信息
for ($i = strlen($card); $i < 20; ++$i) {
$info = BankCard::info($card);
if ($card > 15) {
$validated = $info['validated'];
if ($validated) {
return success([
'backName' => $info['bankName'],
'cardTypeName' => $info['cardTypeName'],
]);
}
}
$card .= '0';
}
return fail('無法自動(dòng)判斷');
}
一段丑陋的代碼會使人失去閱讀的欲望
public function rewardRead(Request $request)
{
$popreward20 = DB::table('goldcat_message')
->where(
[
'uid' => $request->header('uid'),
'status' => 0,
'type' => 4,
'user_type' => 1,
]
)
->value('type');
//注冊獎(jiǎng)勵(lì)20的彈窗
if ($popreward20) {
DB::table('goldcat_message')
->where(
[
'uid' => $request->header('uid'),
'type' => 4,
]
)
->update(
[
'status' => 1,
]
);
return success(
[
'img' => 'pop-reward-20.png',
]
);
}
//認(rèn)證獎(jiǎng)勵(lì)30彈窗
$popreward30 = DB::table('goldcat_message')
->where(
[
'uid' => $request->header('uid'),
'status' => 0,
'type' => 5,
'user_type' => 1,
]
)
->value('type');
if ($popreward30) {
DB::table('goldcat_message')
->where(
[
'uid' => $request->header('uid'),
'type' => 5,
]
)
->update([
'status' => 1,
]
);
return success(
[
'img' => 'pop-reward-30.png',
]
);
}
return fail('無需彈窗提醒');
}
修復(fù)后
//認(rèn)證成功獎(jiǎng)勵(lì)到賬彈窗提示
public function rewardRead(Request $request)
{
$popreward20 = DB::table('goldcat_message')->where([
'uid' => $request->header('uid'),
'status' => 0,
'type' => 4,
'user_type' => 1,
])->value('type');
//注冊獎(jiǎng)勵(lì)20的彈窗
if ($popreward20) {
DB::table('goldcat_message')->where([
'uid' => $request->header('uid'),
'type' => 4,
])->update(['status' => 1]);
return success(['img' => 'pop-reward-20.png']);
}
//認(rèn)證獎(jiǎng)勵(lì)30彈窗
$popreward30 = DB::table('goldcat_message')->where([
'uid' => $request->header('uid'),
'status' => 0,
'type' => 5,
'user_type' => 1,
])->value('type');
if ($popreward30) {
DB::table('goldcat_message')->where([
'uid' => $request->header('uid'),
'type' => 5,
])->update(['status' => 1]);
return success(['img' => 'pop-reward-30.png']);
}
return fail('無需彈窗提醒');
}
- 問題 閱讀代碼發(fā)現(xiàn)是要找出type為4或者為5的黔龟,并返回對應(yīng)的圖片和修改所返回的記錄的狀態(tài)為1
//認(rèn)證成功獎(jiǎng)勵(lì)到賬彈窗提示
public function rewardRead(Request $request)
{
$uid = 7; //$request->header('uid')
$res = DB::table('goldcat_message')->where([
'uid' => $uid,
'status' => 0,
'user_type' => 1,
])->where(function ($query) {
$query->where('type', '=', 4)
->orWhere('type', '=', 5);
})->select('id', 'type')->get();
$res = $res->toArray();
if (!$res) {
return fail('無需彈窗提醒');
}
$type = $res[0]->type;
DB::table('goldcat_message')->where([
'uid' => $uid,
'type' => $type,
])->update(['status' => 1]);
//注冊獎(jiǎng)勵(lì)20或3認(rèn)證獎(jiǎng)勵(lì)30的彈窗
return $type == 4 ? success(['img' => 'pop-reward-20.png']) : success(['img' => 'pop-reward-30.png']);
}
代碼由68行變?yōu)榱?6行,代碼數(shù)也由2081變?yōu)榱?40确沸,縮減了約60%捌锭,讀起來也更加的邏輯清晰了。