国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當前位置: 首頁 > news >正文

網站建設銷售實習報告臨沂網站建設

網站建設銷售實習報告,臨沂網站建設,接單做網站的,外貿建站新聞資訊1. 導讀 你們是否也有過下面的想法? 重構一個項目還不如新開發(fā)一個項目…這代碼是誰寫的,我真想… 你們的項目中是否也存在下面的問題? 單個項目也越來越龐大,團隊成員代碼風格不一致,無法對整體的代碼質量做全面的…

1. 導讀

你們是否也有過下面的想法?

  • 重構一個項目還不如新開發(fā)一個項目…
  • 這代碼是誰寫的,我真想…

你們的項目中是否也存在下面的問題?

  • 單個項目也越來越龐大,團隊成員代碼風格不一致,無法對整體的代碼質量做全面的掌控
  • 沒有一個準確的標準去衡量代碼結構復雜的程度,無法量化一個項目的代碼質量
  • 重構代碼后無法立即量化重構后代碼質量是否提升

針對上面的問題,本文的主角?圈復雜度?重磅登場,本文將從圈復雜度原理出發(fā),介紹圈復雜度的計算方法、如何降低代碼的圈復雜度,如何獲取圈復雜度,以及圈復雜度在公司項目的實踐應用。

2. 圈復雜度

2.1 定義

圈復雜度?(Cyclomatic complexity) 是一種代碼復雜度的衡量標準,也稱為條件復雜度或循環(huán)復雜度,它可以用來衡量一個模塊判定結構的復雜程度,數量上表現為獨立現行路徑條數,也可理解為覆蓋所有的可能情況最少使用的測試用例數。簡稱 CC 。其符號為 VG 或是 M 。

圈復雜度?在 1976 年由 Thomas J. McCabe, Sr. 提出。

圈復雜度大說明程序代碼的判斷邏輯復雜,可能質量低且難于測試和維護。程序的可能錯誤和高的圈復雜度有著很大關系。

2.2 衡量標準

代碼復雜度低,代碼不一定好,但代碼復雜度高,代碼一定不好。

圈復雜度代碼狀況可測性維護成本
1 - 10清晰、結構化
10 - 20復雜
20 - 30非常復雜
>30不可讀不可測非常高

3. 計算方法

3.1 控制流程圖

控制流程圖,是一個過程或程序的抽象表現,是用在編譯器中的一個抽象數據結構,由編譯器在內部維護,代表了一個程序執(zhí)行過程中會遍歷到的所有路徑。它用圖的形式表示一個過程內所有基本塊執(zhí)行的可能流向, 也能反映一個過程的實時執(zhí)行過程。

下面是一些常見的控制流程:

3.2 節(jié)點判定法

有一個簡單的計算方法,圈復雜度實際上就是等于判定節(jié)點的數量再加上1。向上面提到的:if else?、switch case?、?for循環(huán)、三元運算符等等,都屬于一個判定節(jié)點,例如下面的代碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function testComplexity(*param*) {let result = 1;if (param > 0) {result--;}for (let i = 0; i < 10; i++) {result += Math.random();}switch (parseInt(result)) {case 1:result += 20;break;case 2:result += 30;break;default:result += 10;break;}return result > 20 ? result : result;
}

上面的代碼中一共有1if語句,一個for循環(huán),兩個case語句,一個三元運算符,所以代碼復雜度為?1+2+1+1+1=6。另外,需要注意的是?|| 和 &&?語句也會被算作一個判定節(jié)點,例如下面代碼的代碼復雜為3

1
2
3
4
5
6
7
function testComplexity(*param*) {let result = 1;if (param > 0 && param < 10) {result--;}return result;
}

3.3 點邊計算法

1
M = E ? N + 2P
  • E:控制流圖中邊的數量
  • N:控制流圖中的節(jié)點數量
  • P:獨立組件的數目

前兩個,邊和節(jié)點都是數據結構圖中最基本的概念:

P代表圖中獨立組件的數目,獨立組件是什么意思呢?來看看下面兩個圖,左側為連通圖,右側為非連通圖:

  • 連通圖:對于圖中任意兩個頂點都是連通的

一個連通圖即為圖中的一個獨立組件,所以左側圖中獨立組件的數目為1,右側則有兩個獨立組件。

對于我們的代碼轉化而來的控制流程圖,正常情況下所有節(jié)點都應該是連通的,除非你在某些節(jié)點之前執(zhí)行了?return,顯然這樣的代碼是錯誤的。所以每個程序流程圖的獨立組件的數目都為1,所以上面的公式還可以簡化為?M = E ? N + 2?。

4. 降低代碼的圈復雜度

我們可以通過一些代碼重構手段來降低代碼的圈復雜度。

重構需謹慎,示例代碼僅僅代表一種思想,實際代碼要遠遠比示例代碼復雜的多。

4.1 抽象配置

通過抽象配置將復雜的邏輯判斷進行簡化。例如下面的代碼,根據用戶的選擇項執(zhí)行相應的操作,重構后降低了代碼復雜度,并且如果之后有新的選項,直接加入配置即可,而不需要再去深入代碼邏輯中進行改動:

4.2 單一職責 - 提煉函數

單一職責原則(SRP):每個類都應該有一個單一的功能,一個類應該只有一個發(fā)生變化的原因。

在?JavaScript?中,需要用到的類的場景并不太多,單一職責原則則是更多地運用在對象或者方法級別上面。

函數應該做一件事,做好這件事,只做這一件事。 — 代碼整潔之道

關鍵是如何定義這 “一件事” ,如何將代碼中的邏輯進行抽象,有效的提煉函數有利于降低代碼復雜度和降低維護成本。

4.3 使用 break 和 return 代替控制標記

我們經常會使用一個控制標記來標示當前程序運行到某一狀態(tài),很多場景下,使用?break?和?return?可以代替這些標記并降低代碼復雜度。

4.4 用函數取代參數

setField?和?getField?函數就是典型的函數取代參數,如果么有?setField、getField?函數,我們可能需要一個很復雜的?setValue、getValue?來完成屬性賦值操作:

4.5 簡化條件判斷 - 逆向條件

某些復雜的條件判斷可能逆向思考后會變的更簡單。

4.6 簡化條件判斷 -合并條件

將復雜冗余的條件判斷進行合并。

4.7 簡化條件判斷 - 提取條件

將復雜難懂的條件進行語義化提取。

5. 圈復雜度檢測方法

5.1 eslint規(guī)則

eslint提供了檢測代碼圈復雜度的rules:

我們將開啟?rules?中的?complexity?規(guī)則,并將圈復雜度大于?0?的代碼的?rule severity?設置為?warn?或?error?。

1
2
3
4
5
6
rules: {complexity: ['warn',{ max: 0 }]
}

這樣?eslint?就會自動檢測出所有函數的代碼復雜度,并輸出一個類似下面的?message

1
2
3
4
Method 'testFunc' has a complexity of 12. Maximum allowed is 0
Async function has a complexity of 6. Maximum allowed is 0.
...

5.2 CLIEngine

我們可以借助?eslint?的?CLIEngine?,在本地使用自定義的?eslint?規(guī)則掃描代碼,并獲取掃描結果輸出。

初始化?CLIEngine?:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const eslint = require('eslint');const { CLIEngine } = eslint;const cli = new CLIEngine({parserOptions: {ecmaVersion: 2018,},rules: {complexity: ['error',{ max: 0 }]}
});

使用?executeOnFiles?對指定文件進行掃描,并獲取結果,過濾出所有?complexity?的?message?信息。

1
2
3
4
5
6
7
8
9
10
11
const reports = cli.executeOnFiles(['.']).results;for (let i = 0; i < reports.length; i++) {const { messages } = reports[i];for (let j = 0; j < messages.length; j++) {const { message, ruleId } = messages[j];if (ruleId === 'complexity') {console.log(message);}}
}

5.3 提取message

通過?eslint?的檢測結果將有用的信息提取出來,先測試幾個不同類型的函數,看看?eslint?的檢測結果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function func1() {console.log(1);
}const func2 = () => {console.log(2);
};class TestClass {func3() {console.log(3);}
}async function func4() {console.log(1);
}

執(zhí)行結果:

1
2
3
4
Function 'func1' has a complexity of 1. Maximum allowed is 0.
Arrow function has a complexity of 1. Maximum allowed is 0.
Method 'func3' has a complexity of 1. Maximum allowed is 0.
Async function 'func4' has a complexity of 1. Maximum allowed is 0.

可以發(fā)現,除了前面的函數類型,以及后面的復雜度,其他都是相同的。

函數類型:

  • Function?:普通函數
  • Arrow function?: 箭頭函數
  • Method?: 類方法
  • Async function?: 異步函數

截取方法類型:

1
2
3
4
5
6
const REG_FUNC_TYPE = /^(Method |Async function |Arrow function |Function )/g;function getFunctionType(message) {let hasFuncType = REG_FUNC_TYPE.test(message);return hasFuncType && RegExp.$1;
}

將有用的部分提取出來:

1
2
3
4
5
6
7
const MESSAGE_PREFIX = 'Maximum allowed is 1.';
const MESSAGE_SUFFIX = 'has a complexity of ';function getMain(message) {return message.replace(MESSAGE_PREFIX, '').replace(MESSAGE_SUFFIX, '');
}

提取方法名稱:

1
2
3
4
5
function getFunctionName(message) {const main = getMain(message);let test = /'([a-zA-Z0-9_$]+)'/g.test(main);return test ? RegExp.$1 : '*';
}

截取代碼復雜度:

1
2
3
4
5
function getComplexity(message) {const main = getMain(message);(/(\d+)\./g).test(main);return +RegExp.$1;
}

除了?message?,還有其他的有用信息:

  • 函數位置:獲取?messages?中的?line?、column?即函數的行、列位置
  • 當前文件名稱:reports?結果中可以獲取當前掃描文件的絕對路徑?filePath?,通過下面的操作獲取真實文件名:
1
filePath.replace(process.cwd(), '').trim()
  • 復雜度等級,根據函數的復雜度等級給出重構建議:
圈復雜度代碼狀況可測性維護成本
1 - 10清晰、結構化
10 - 20復雜
20 - 30非常復雜
>30不可讀不可測非常高
圈復雜度代碼狀況
1 - 10無需重構
11 - 15建議重構
>15強烈建議重構

6.架構設計

將代碼復雜度檢測封裝成基礎包,根據自定義配置輸出檢測數據,供其他應用調用。

上面的展示了使用?eslint?獲取代碼復雜度的思路,下面我們要把它封裝為一個通用的工具,考慮到工具可能在不同場景下使用,例如:網頁版的分析報告、cli版的命令行工具,我們把通用的能力抽象出來以?npm包?的形式供其他應用使用。

在計算項目代碼復雜度之前,我們首先要具備一項基礎能力,代碼掃描,即我們要知道我們要對項目里的哪些文件做分析,首先?eslint?是具備這樣的能力的,我們也可以直接用?glob?來遍歷文件。但是他們都有一個缺點,就是?ignore?規(guī)則是不同的,這對于用戶來講是有一定學習成本的,因此我這里把手動封裝代碼掃描,使用通用的?npm ignore?規(guī)則,這樣代碼掃描就可以直接使用?.gitignore這樣的配置文件。另外,代碼掃描作為代碼分析的基礎能力,其他代碼分析也是可以公用的。

  • 基礎能力
    • 代碼掃描能力
    • 復雜度檢測能力
  • 應用
    • 命令行工具
    • 代碼分析報告

7. 基礎能力 - 代碼掃描

本文涉及的?npm?包和?cli命令源碼均可在我的開源項目?awesome-cli中查看。

awesome-cli 是我新建的一個開源項目:有趣又實用的命令行工具,后面會持續(xù)維護,敬請關注,歡迎 star。

代碼掃描(c-scan)源碼:awesome-cli/conard at master · ConardLi/awesome-cli · GitHub

代碼掃描是代碼分析的底層能力,它主要幫助我們拿到我們想要的文件路徑,應該滿足我們以下兩個需求:

  • 我要得到什么類型的文件
  • 我不想要哪些文件

7.1 使用

1
2
3
4
5
6
7
8
9
10
npm i c-scan --saveconst scan = require('c-scan');
scan({extensions:'**/*.js',rootPath:'src',defalutIgnore:'true',ignoreRules:[],ignoreFileName:'.gitignore'
});

7.2 返回值

符合規(guī)則的文件路徑數組:

7.3 參數

  • extensions

    • 掃描文件擴展名
    • 默認值:**/*.js
  • rootPath

    • 掃描文件路徑
    • 默認值:.
  • defalutIgnore

    • 是否開啟默認忽略(glob規(guī)則)
    • glob ignore規(guī)則為內部使用,為了統(tǒng)一ignore規(guī)則,自定義規(guī)則使用gitignore規(guī)則
    • 默認值:true
    • 默認開啟的?glob ignore?規(guī)則:
1
2
3
4
5
6
7
const DEFAULT_IGNORE_PATTERNS = ['node_modules/**','build/**','dist/**','output/**','common_build/**'
];
  • ignoreRules

    • 自定義忽略規(guī)則(gitignore規(guī)則)
    • 默認值:[]
  • ignoreFileName

    • 自定義忽略規(guī)則配置文件路徑(gitignore規(guī)則)
    • 默認值:.gitignore
    • 指定為null則不啟用ignore配置文件

7.4 核心實現

基于?glob?,自定義?ignore?規(guī)則進行二次封裝。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/*** 獲取glob掃描的文件列表* @param {*} rootPath 跟路徑* @param {*} extensions 擴展* @param {*} defalutIgnore 是否開啟默認忽略*/
function getGlobScan(rootPath, extensions, defalutIgnore) {return new Promise(resolve => {glob(`${rootPath}${extensions}`,{ dot: true, ignore: defalutIgnore ? DEFAULT_IGNORE_PATTERNS : [] },(err, files) => {if (err) {console.log(err);process.exit(1);}resolve(files);});});
}/*** 加載ignore配置文件,并處理成數組* @param {*} ignoreFileName */
async function loadIgnorePatterns(ignoreFileName) {const ignorePath = path.resolve(process.cwd(), ignoreFileName);try {const ignores = fs.readFileSync(ignorePath, 'utf8');return ignores.split(/[\n\r]|\n\r/).filter(pattern => Boolean(pattern));} catch (e) {return [];}
}/*** 根據ignore配置過濾文件列表* @param {*} files * @param {*} ignorePatterns * @param {*} cwd */
function filterFilesByIgnore(files, ignorePatterns, ignoreRules, cwd = process.cwd()) {const ig = ignore().add([...ignorePatterns, ...ignoreRules]);const filtered = files.map(raw => (path.isAbsolute(raw) ? raw : path.resolve(cwd, raw))).map(raw => path.relative(cwd, raw)).filter(filePath => !ig.ignores(filePath)).map(raw => path.resolve(cwd, raw));return filtered;
}

8. 基礎能力 - 代碼復雜度檢測

代碼復雜度檢測(c-complexity)源碼:awesome-cli/code-complexity at master · ConardLi/awesome-cli · GitHub

代碼檢測基礎包應該具備以下幾個能力:

  • 自定義掃描文件夾和類型
  • 支持忽略文件
  • 定義最小提醒代碼復雜度

8.1 使用

1
2
3
4
npm i c-complexity --saveconst cc = require('c-complexity');
cc({},10);

8.2 返回值

  • fileCount:文件數量
  • funcCount:函數數量
  • result:詳細結果
    • funcType:函數類型
    • funcName;函數名稱
    • position:詳細位置(行列號)
    • fileName:文件相對路徑
    • complexity:代碼復雜度
    • advice:重構建議

8.3 參數

  • scanParam
    • 繼承自上面代碼掃描的參數
  • min
    • 最小提醒代碼復雜度,默認為1

9. 應用 - 代碼復雜度檢測工具

代碼復雜度檢測(conard cc)源碼:awesome-cli/conard at master · ConardLi/awesome-cli · GitHub

9.1 指定最小提醒復雜度

可以觸發(fā)提醒的最小復雜度。

  • 默認為?10
  • 通過命令?conard cc --min=5?自定義

9.2 指定掃描參數

自定義掃描規(guī)則

  • 掃描參數繼承自上面的?scan param
  • 例如:?conard cc --defalutIgnore=false

10. 應用 - 代碼復雜度報告

部分截圖來源于我們內部的項目質量監(jiān)控平臺,圈復雜度作為一項重要的指標,對于衡量項目代碼質量起著至關重要的作用。

代碼復雜復雜度變化趨勢

定時任務爬取代碼每日的代碼復雜度、代碼行數、函數個數,通過每日數據繪制代碼復雜度和代碼行數變化趨勢折線圖。

通過 [ 復雜度 / 代碼行數 ] 或 [ 復雜度 / 函數個數 ] 的變化趨勢,判斷項目發(fā)展是否健康。

  • 比值若一直在上漲,說明你的代碼在變得越來越難以理解。這不僅使我們面臨意外的功能交互和缺陷的風險,由于我們在具有或多或少相關功能的模塊中所面臨的過多認知負擔,也很難重用代碼并進行修改和測試。(下圖1)

  • 若比值在某個階段發(fā)生突變,說明這段期間迭代質量很差。(下圖2)

  • 復雜度曲線圖可以很快的幫你更早的發(fā)現上面這兩個問題,發(fā)現它們后,你可能需要重構代碼。復雜性趨勢對于跟蹤你的代碼重構也很有用。復雜性趨勢的下降趨勢是一個好兆頭。這要么意味著您的代碼變得更簡單(例如,把 if-else 被重構為多態(tài)解決方案),要么代碼更少(將不相關的部分提取到了其他模塊中)。(下圖3)

  • 代碼重構后,你還需要繼續(xù)探索復雜度變化趨勢。經常發(fā)生的事情是,我們花費大量的時間和精力來重構,無法解決根本原因,很快復雜度又滑回了原處。(下圖4)你可能覺得這是個例,但是有研究標明,在分析了數百個代碼庫后,發(fā)現出現這種情況的頻率很高。因此,時刻觀察代碼復雜度變化趨勢是有必要的。

代碼復雜度文件分布

統(tǒng)計各復雜度分布的函數數量。

代碼復雜度文件詳情

計算每個函數的代碼復雜度,從高到低依次列出高復雜度的文件分布,并給出重構建議。

實際開發(fā)中并不一定所有的代碼都需要被分析,例如打包產物、靜態(tài)資源文件等等,這些文件往往會誤導我們的分析結果,現在分析工具會默認忽略一些規(guī)則,例如:.gitignore文件、static目錄等等,實際這些規(guī)則還需要根據實際項目的情況去不斷完善,使分析結果變得更準確。

參考

  • 加推研發(fā)質量與規(guī)范實戰(zhàn)
  • codescene
  • 圈復雜度那些事兒-前端代碼質量系列文章(二)
  • 代碼質量管控 – 復雜度檢測
  • 詳解圈復雜度

http://aloenet.com.cn/news/44127.html

相關文章:

  • 什么平臺引流最快太原seo網絡優(yōu)化招聘網
  • 自建網站成都搜索引擎營銷方案
  • 網站開發(fā)工具webs國家免費培訓機構
  • 教育機構電商網站建設加盟福州seo招聘
  • 網站功能介紹是什么百度應用商店下載
  • 中國著名的網站建設公司百度熱搜電視劇
  • 秦皇島企業(yè)建網站廣東seo外包服務
  • 南京企業(yè)建設網站設計網絡推廣都是收費
  • h5 技術做健康類網站網絡優(yōu)化公司有哪些
  • ipv6網站建設如何自制網站
  • 清河做網站軟文是什么意思
  • 網站開發(fā)需要20萬百度云網盤免費資源
  • 合肥網站建設推廣友情鏈接怎么做
  • 西部數碼網站工具免費建站平臺哪個好
  • 東陽網站建設dyfwzx友情鏈接吧
  • 沈陽網站建設建設公司排名優(yōu)化seo系統(tǒng)
  • 重慶網站設計公司價格丈哥seo博客工具
  • 如何搭建一個個人網站學校招生網絡營銷方案
  • 給公司網站設計寧波廠家關鍵詞優(yōu)化
  • 智聯招聘網站建設情況注冊城鄉(xiāng)規(guī)劃師好考嗎
  • jqueryui做的網站株洲seo排名
  • 寧波做網站的大公司排名關鍵詞搜索推廣排行榜
  • 如何免費網站建設怎么可以在百度發(fā)布信息
  • 做網站運營的女生多嗎百度公司簡介
  • 上海小微企業(yè)名錄查詢seo短視頻網頁入口營銷
  • 公司網站建設北京北京做百度推廣的公司
  • 網站開發(fā)用啥語言廣州各區(qū)正在進一步優(yōu)化以下措施
  • 順德做網站公司seo搜狗
  • 網站后端怎么做河北網站建設公司排名
  • 手機模板網站模板鞏義網站優(yōu)化公司