成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

使用 jsinspect 檢測(cè)前端代碼庫(kù)中的重復(fù)/近似代碼

ZoomQuiet / 837人閱讀

摘要:使用檢測(cè)前端代碼庫(kù)中的重復(fù)近似代碼從屬于筆者的前端入門(mén)與工程實(shí)踐,更多前端相關(guān)學(xué)習(xí)資料推薦閱讀前端每周清單第期學(xué)習(xí)資源,發(fā)布,六問(wèn)程序員如何成長(zhǎng)泛前端知識(shí)圖譜。利用對(duì)于或者代碼構(gòu)建語(yǔ)法樹(shù),根據(jù)不同的節(jié)點(diǎn)類(lèi)型,譬如等標(biāo)記相似結(jié)構(gòu)的代碼塊。

使用 jsinspect 檢測(cè)前端代碼庫(kù)中的重復(fù)/近似代碼 從屬于筆者的 Web 前端入門(mén)與工程實(shí)踐,更多前端相關(guān)學(xué)習(xí)資料推薦閱讀前端每周清單第6期:Angular 4.0學(xué)習(xí)資源,Egg.js 1.0發(fā)布,六問(wèn)CTO程序員如何成長(zhǎng)、泛前端知識(shí)圖譜(Web/iOS/Android/RN)。

在開(kāi)發(fā)的過(guò)程中我們往往會(huì)存在大量的復(fù)制粘貼代碼的行為,這一點(diǎn)在項(xiàng)目的開(kāi)發(fā)初期尤其顯著;而在項(xiàng)目逐步穩(wěn)定,功能需求逐步完善之后我們就需要考慮對(duì)代碼庫(kù)的優(yōu)化與重構(gòu),盡量編寫(xiě)清晰可維護(hù)的代碼。好的代碼往往是在合理范圍內(nèi)盡可能地避免重復(fù)代碼,遵循單一職責(zé)與 Single Source of Truth 等原則,本部分我們嘗試使用 jsinspect 對(duì)于代碼庫(kù)進(jìn)行自動(dòng)檢索,根據(jù)其反饋的重復(fù)或者近似的代碼片進(jìn)行合理的優(yōu)化。當(dāng)然,我們并不是單純地追求公共代碼地完全剝離化,過(guò)度的抽象反而會(huì)降低代碼的可讀性與可理解性。jsinspect 利用 babylon 對(duì)于 JavaScript 或者 JSX 代碼構(gòu)建 AST 語(yǔ)法樹(shù),根據(jù)不同的 AST 節(jié)點(diǎn)類(lèi)型,譬如 BlockStatement、VariableDeclaration、ObjectExpression 等標(biāo)記相似結(jié)構(gòu)的代碼塊。我們可以使用 npm 全局安裝 jsinspect 命令:

Usage: jsinspect [options] 


Detect copy-pasted and structurally similar JavaScript code
Example use: jsinspect -I -L -t 20 --ignore "test" ./path/to/src


Options:

  -h, --help                         output usage information
  -V, --version                      output the version number
  -t, --threshold            number of nodes (default: 30)
  -m, --min-instances        min instances for a match (default: 2)
  -c, --config                       path to config file (default: .jsinspectrc)
  -r, --reporter [default|json|pmd]  specify the reporter to use
  -I, --no-identifiers               do not match identifiers
  -L, --no-literals                  do not match literals
  -C, --no-color                     disable colors
  --ignore                  ignore paths matching a regex
  --truncate                 length to truncate lines (default: 100, off: 0)

我們也可以選擇在項(xiàng)目目錄下添加 .jsinspect 配置文件指明 jsinspect 運(yùn)行配置:

{
  "threshold":     30,
  "identifiers":   true,
  "literals":      true,
  "ignore":        "test|spec|mock",
  "reporter":      "json",
  "truncate":      100,
}

在配置完畢之后,我們可以使用 jsinspect -t 50 --ignore "test" ./path/to/src 來(lái)對(duì)于代碼庫(kù)進(jìn)行分析,以筆者找到的某個(gè)代碼庫(kù)為例,其檢測(cè)出了上百個(gè)重復(fù)的代碼片,其中典型的代表如下所示??梢钥吹皆谀硞€(gè)組件中重復(fù)編寫(xiě)了多次密碼輸入的元素,我們可以選擇將其封裝為函數(shù)式組件,將 label、hintText 等通用屬性包裹在內(nèi),從而減少代碼的重復(fù)率。

Match - 2 instances

./src/view/main/component/tabs/account/operation/login/forget_password.js:96,110
return 
{ this.setState({ userPwd: value }) }} />
./src/view/main/component/tabs/my/login/forget_password.js:111,125 return
{ this.setState({ userPwd: value }) }} />

筆者也對(duì)于 React 源碼進(jìn)行了簡(jiǎn)要分析,在 246 個(gè)文件中共發(fā)現(xiàn) 16 個(gè)近似代碼片,并且其中的大部分重復(fù)源于目前基于 Stack 的調(diào)和算法與基于 Fiber 重構(gòu)的調(diào)和算法之間的過(guò)渡時(shí)期帶來(lái)的重復(fù),譬如:

Match - 2 instances

./src/renderers/dom/fiber/wrappers/ReactDOMFiberTextarea.js:134,153
  var value = props.value;
  if (value != null) {
    // Cast `value` to a string to ensure the value is set correctly. While
    // browsers typically do this as necessary, jsdom doesn"t.
    var newValue = "" + value;

    // To avoid side effects (such as losing text selection), only set value if changed
    if (newValue !== node.value) {
      node.value = newValue;
    }
    if (props.defaultValue == null) {
      node.defaultValue = newValue;
    }
  }
  if (props.defaultValue != null) {
    node.defaultValue = props.defaultValue;
  }
},

postMountWrapper: function(element: Element, props: Object) {

./src/renderers/dom/stack/client/wrappers/ReactDOMTextarea.js:129,148
  var value = props.value;
  if (value != null) {
    // Cast `value` to a string to ensure the value is set correctly. While
    // browsers typically do this as necessary, jsdom doesn"t.
    var newValue = "" + value;

    // To avoid side effects (such as losing text selection), only set value if changed
    if (newValue !== node.value) {
      node.value = newValue;
    }
    if (props.defaultValue == null) {
      node.defaultValue = newValue;
    }
  }
  if (props.defaultValue != null) {
    node.defaultValue = props.defaultValue;
  }
},

postMountWrapper: function(inst) {

筆者認(rèn)為在新特性的開(kāi)發(fā)過(guò)程中我們不一定需要時(shí)刻地考慮代碼重構(gòu),而是應(yīng)該相對(duì)獨(dú)立地開(kāi)發(fā)新功能。最后我們?cè)俸?jiǎn)單地討論下 jsinspect 的工作原理,這樣我們可以在項(xiàng)目需要時(shí)自定義類(lèi)似的工具以進(jìn)行特殊代碼的匹配或者提取。jsinspect 的核心工作流可以反映在 inspector.js 文件中:

... 
this._filePaths.forEach((filePath) => {
  var src = fs.readFileSync(filePath, {encoding: "utf8"});
  this._fileContents[filePath] = src.split("
");
  var syntaxTree = parse(src, filePath);
  this._traversals[filePath] = nodeUtils.getDFSTraversal(syntaxTree);
  this._walk(syntaxTree, (nodes) => this._insert(nodes));
});

this._analyze();
...

上述流程還是較為清晰的,jsinspect 會(huì)遍歷所有的有效源碼文件,提取其源碼內(nèi)容然后通過(guò) babylon 轉(zhuǎn)化為 AST 語(yǔ)法樹(shù),某個(gè)文件的語(yǔ)法樹(shù)格式如下:

Node {
  type: "Program",
  start: 0,
  end: 31,
  loc:
   SourceLocation {
     start: Position { line: 1, column: 0 },
     end: Position { line: 2, column: 15 },
     filename: "./__test__/a.js" },
  sourceType: "script",
  body:
   [ Node {
       type: "ExpressionStatement",
       start: 0,
       end: 15,
       loc: [Object],
       expression: [Object] },
     Node {
       type: "ExpressionStatement",
       start: 16,
       end: 31,
       loc: [Object],
       expression: [Object] } ],
  directives: [] }
{ "./__test__/a.js": [ "console.log(a);", "console.log(b);" ] }

其后我們通過(guò)深度優(yōu)先遍歷算法在 AST 語(yǔ)法樹(shù)上構(gòu)建所有節(jié)點(diǎn)的數(shù)組,然后遍歷整個(gè)數(shù)組構(gòu)建待比較對(duì)象。這里我們?cè)谶\(yùn)行時(shí)輸入的 -t 參數(shù)就是用來(lái)指定分割的原子比較對(duì)象的維度,當(dāng)我們將該參數(shù)指定為 2 時(shí),經(jīng)過(guò)遍歷構(gòu)建階段形成的內(nèi)部映射數(shù)組 _map 結(jié)構(gòu)如下:

{ "uj3VAExwF5Avx0SGBDFu8beU+Lk=": [ [ [Object], [Object] ], [ [Object], [Object] ] ],
  "eMqg1hUXEFYNbKkbsd2QWECLiYU=": [ [ [Object], [Object] ], [ [Object], [Object] ] ],
  "gvSCaZfmhte6tfnpfmnTeH+eylw=": [ [ [Object], [Object] ], [ [Object], [Object] ] ],
  "eHqT9EuPomhWLlo9nwU0DWOkcXk=": [ [ [Object], [Object] ], [ [Object], [Object] ] ] }

如果有大規(guī)模代碼數(shù)據(jù)的話我們可能形成很多有重疊的實(shí)例,這里使用了 _omitOverlappingInstances 函數(shù)來(lái)進(jìn)行去重;譬如如果某個(gè)實(shí)例包含節(jié)點(diǎn) abcd,另一個(gè)實(shí)例包含節(jié)點(diǎn)組 bcde,那么會(huì)選擇將后者從數(shù)組中移除。另一個(gè)優(yōu)化加速的方法就是在每次比較結(jié)束之后移除已經(jīng)匹配到的代碼片:

_prune(nodeArrays) {
  for (let i = 0; i < nodeArrays.length; i++) {
    let nodes = nodeArrays[i];
    for (let j = 0; j < nodes.length; j++) {
      this._removeNode(nodes[j]);
    }
  }
}

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/82229.html

相關(guān)文章

  • JavaScript權(quán)威指南筆記(上)-語(yǔ)言核心

    摘要:二進(jìn)制浮點(diǎn)數(shù)和四舍五入錯(cuò)誤在使用實(shí)數(shù)時(shí),常常只是真實(shí)值的一個(gè)近似表示。作用域分類(lèi)全局函數(shù),塊級(jí)作用域鏈變量對(duì)象用于存儲(chǔ)執(zhí)行上下文中的變量函數(shù)聲明函數(shù)參數(shù)變量初始化階段瀏覽器截圖瀏覽器截圖代碼執(zhí)行階段類(lèi)和模塊 詞法結(jié)構(gòu) 字符集 使用Unicode編寫(xiě) ES3 Unicode2.1+ ES5 Unicode3+ 區(qū)分大小寫(xiě) 注釋 // 注釋 /* 注釋 */ 標(biāo)識(shí)符和保留字 必須以字...

    skinner 評(píng)論0 收藏0
  • 咋做長(zhǎng)文本去重

    摘要:新問(wèn)題拋出有沒(méi)有一種簽名算法,如果文本非常相似,簽名值也非常相似呢二文本相似性的簽名算法上文提出的問(wèn)題,可以用局部敏感哈希解決,局部敏感哈希是一類(lèi)文本越相似,哈希值越相似的算法,有興趣的同學(xué)自行百度,這里分享一下的思路。 緣起:(1)原創(chuàng)不易,互聯(lián)網(wǎng)抄襲成風(fēng),很多原創(chuàng)內(nèi)容在網(wǎng)上被抄來(lái)抄去,改來(lái)改去(2)百度的網(wǎng)頁(yè)庫(kù)非常大,爬蟲(chóng)如何判斷一個(gè)新網(wǎng)頁(yè)是否與網(wǎng)頁(yè)庫(kù)中已有的網(wǎng)頁(yè)重復(fù)呢?這是本文要...

    coordinate35 評(píng)論0 收藏0
  • 算法分析 - Algorithms, Part I, week 1 ANALYSIS OF ALGO

    摘要:實(shí)際上這個(gè)情形中存在冪定律實(shí)際上絕大多數(shù)的計(jì)算機(jī)算法的運(yùn)行時(shí)間滿(mǎn)足冪定律?;谘芯康弥?,原則上我們能夠獲得算法,程序或者操作的性能的精確數(shù)學(xué)模型。 前言 上一篇:并查集下一篇:棧和隊(duì)列 在算法性能上我們常常面臨的挑戰(zhàn)是我們的程序能否求解實(shí)際中的大型輸入:--為什么程序運(yùn)行的慢?--為什么程序耗盡了內(nèi)存? 沒(méi)有理解算法的性能特征會(huì)導(dǎo)致客戶(hù)端的性能很差,為了避免這種情況的出線,需要具備算法...

    Leo_chen 評(píng)論0 收藏0
  • JavaScript 工作原理之三-內(nèi)存管理及如何處理 4 類(lèi)常見(jiàn)的內(nèi)存泄漏問(wèn)題(譯)

    摘要:這是因?yàn)槲覀冊(cè)L問(wèn)了數(shù)組中不存在的數(shù)組元素它超過(guò)了最后一個(gè)實(shí)際分配到內(nèi)存的數(shù)組元素字節(jié),并且有可能會(huì)讀取或者覆寫(xiě)的位。包含個(gè)元素的新數(shù)組由和數(shù)組元素所組成中的內(nèi)存使用中使用分配的內(nèi)存主要指的是內(nèi)存讀寫(xiě)。 原文請(qǐng)查閱這里,本文有進(jìn)行刪減,文后增了些經(jīng)驗(yàn)總結(jié)。 本系列持續(xù)更新中,Github 地址請(qǐng)查閱這里。 這是 JavaScript 工作原理的第三章。 我們將會(huì)討論日常使用中另一個(gè)被開(kāi)發(fā)...

    weknow619 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<