<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          我見過最糟糕的代碼

          共 5625字,需瀏覽 12分鐘

           ·

          2021-04-24 02:09

          數(shù)學(xué)算法俱樂部

          日期 : 2021年04月21日       

          正文共 :3192

          來源 : infoQ


          在本文中,我將向你展示我見過的一些最糟糕的代碼,它們被稱為“魔鬼代碼”,會(huì)帶來很嚴(yán)重的后果。然而,我們發(fā)現(xiàn)通過一些好的實(shí)踐,你可以很容易規(guī)避它們。
          “魔鬼代碼”
          需要改進(jìn)的代碼與所謂的“魔鬼代碼”是不一樣的
          不管使用的是哪種語言,“魔鬼代碼”都很糟糕,因?yàn)樗鼤?huì)危及項(xiàng)目的穩(wěn)定性和可維護(hù)性。在職業(yè)生涯中,我見過很多“魔鬼代碼”。
          當(dāng)它堆積如山時(shí),你的項(xiàng)目很快就會(huì)變成“十八層地獄”的樣貌。如果你喜歡到處捅婁子,那么領(lǐng)導(dǎo)看你的眼光也會(huì)越來越不一樣。
          模棱兩可和前后矛盾
          很久以前,我在一個(gè)清晨醒來,被世界末日般的景象嚇了一跳。生產(chǎn)環(huán)境出現(xiàn)一個(gè)很大的錯(cuò)誤,所有系統(tǒng)票證莫名其妙地返回“null”。到處都亂成一團(tuán)。所有人都像無頭蒼蠅一樣到處亂跑。
          我跑到公司,沖向工作站,第一步是看 Kibana。但是,沒有日志,什么都沒有。為了查明原因,我決定追溯票證的創(chuàng)建路徑。因此,我必須深入研究系統(tǒng)從誕生到現(xiàn)在創(chuàng)建的那些內(nèi)部庫。經(jīng)過一番調(diào)查,我找到了問題來源之一的一堆文件。
          然后,我看到這樣的景象:
          // use id and expire to get ticketasync function get_ticket(i, expire) { return CheckisNotExp(expire).then(async function() { var t = await GetTicketModel(i) if (t) { return t } else { logger.error(JSON.stringify(t)) return null } }).catch(async function(e) { logger.error(JSON.stringify(e)) return null})}
          真有一個(gè)“i”變量嗎?這是一個(gè) id,對(duì)不對(duì)?它是整數(shù)還是 UUID?到底是什么到期了?是日期還是時(shí)間戳?為什么會(huì)有 camelCase、PascalCase 和 snake_case?帶有 promise 的異步注解和又一個(gè)異步注解?如果失敗,我們會(huì)返回 null?簡直是魔鬼啊!
          那時(shí),每隔 5 分鐘就有一半的公司同事向我發(fā) Skype 消息,索取 ETA 修復(fù)。
          不過,首先,有人需要知道這里究竟發(fā)生了什么。而我意識(shí)到,該為這個(gè)問題負(fù)責(zé)的不是一個(gè)人,而是三個(gè)人。很久以前,其中兩個(gè)人離開了公司,而第三個(gè)人今天早上還沒來公司。
          根據(jù) Git 的記錄,這三個(gè)人碰這個(gè)文件的時(shí)間各自差了很久。因此,他們留下了不一致的代碼、不同的樣式、不一樣的 ECMAScript 版本和不同的 promise 處理方式。
          不管怎樣,在這段代碼中,一切都是模棱兩可的,一切都是不一致的。這是一個(gè)絕佳的反面案例,你應(yīng)該盡一切可能避免這種情況。不用說,代碼審查并沒有覆蓋到這里。
          為了解決問題,我們必須快速重寫它,更改那些變量和函數(shù)的名稱,不能再出現(xiàn)歧異。而且,各處的 Async/Await 都要做成相同的方式。
          我還要確保自己不會(huì)漏掉任何錯(cuò)誤,結(jié)果再返回一個(gè) null。如果出現(xiàn)什么問題,這些錯(cuò)誤肯定要破壞函數(shù)。異常應(yīng)由上面的層來處理。
          // hotfix// @todo rewrite the ticket module entirelyasync function getTicket(ticketUuid, ticketExpirationTimestamp) { await validTicketExpiration(ticketUuid, ticketExpirationTimestamp) const ticket = await getTicketByUuid(ticketUuid)return ticket}
          最好的解決方案是重寫這個(gè)模塊的一部分。這里的票證驗(yàn)證邏輯很糟糕。但這并不是最要緊的事情。當(dāng)務(wù)之急是找出并修復(fù)錯(cuò)誤。
          在更新代碼后,真正的錯(cuò)誤開始浮出水面。前一天所做的一個(gè)配置更改改變了票證創(chuàng)建行為。返回到先前的配置則可以立即解決這個(gè)問題。接下來的一周時(shí)間里,有問題的模塊被完全重寫。
          肉醬意面
          很久以前,我正在做一個(gè)代碼干凈整齊的產(chǎn)品。作為優(yōu)質(zhì)產(chǎn)品,一切都在內(nèi)部做好了優(yōu)化。功能是用盡可能少的代碼開發(fā)的。代碼高度重視可讀性。由注重整潔代碼的工程師管理的代碼審查流程確保產(chǎn)品嚴(yán)格遵循所有最佳實(shí)踐。SOLID、DRY、KISS、YAGNI 和你可以想到的其他首字母縮寫詞,這里都能見得到。
          即使做到這個(gè)地步,這個(gè)產(chǎn)品的某個(gè)特殊部分也會(huì)間歇性地崩潰。在一個(gè)沖刺期間,我終于設(shè)法安排出時(shí)間來調(diào)查這件事。
          很快,我意識(shí)到問題不在于產(chǎn)品。那些錯(cuò)誤只有一個(gè)共同點(diǎn):一個(gè)依賴項(xiàng)。那是一個(gè)通過內(nèi)部工件處理的內(nèi)部依賴項(xiàng)。
          它由另一個(gè)團(tuán)隊(duì)管理,而且——令人驚訝的是——這段代碼不是免費(fèi)提供的。你必須先獲得許可才能看到它。因此,我請(qǐng)求了訪問權(quán)限來了解到底發(fā)生了什么事情。然后,我收到了一條 Slack 消息,問我為什么要訪問源碼。
          “你好!為什么你需要訪問這個(gè)存儲(chǔ)庫?”
          “這是什么意思?你知道我在這里工作嗎?等等,我在路上。”
          我突然出現(xiàn)在他面前后,終于拿到訪問該項(xiàng)目的權(quán)限。
          我在其中看到一個(gè)文件,大小為 300KB。300KB 的文本,竟然有那么大。它已經(jīng)有好幾年沒人碰過了。上次碰過它的那個(gè)人,我完全不認(rèn)識(shí)。簡直是最可怕的魔鬼。
          那是我一生中見過的規(guī)模最大的意大利面條代碼。篇幅所限,我并沒有把所有代碼都放在這里。下面的代碼只是一部分:
          // Thousands of lines of spaghetti codesif (global.Builder){ module.exports.buildPgs = function(pgs, options, limitNodes = 0) { var config = options.config || {}; var builded = []; pgs.each(function(pg) { var supported = pg.prop('tagName') == "INPUT" && pr.attr['name'] == "file" && options.pgs.rel.active == "" && global.FileReader; if (!supported || !pg.f || pg.f.length == 0) return; for (var i = 0; i < pg.f.length; i++) { builded.push({ file: pg.f[i], instanceConfig: _.extend({}, config) });
          if (isFunction(options.before)) { var returned = options.before(pg.f.path); if (typeof returned === 'object' && global.status.in_progress) { if (returned.action == "skip") { var needsSkip = (typeof global.status.in_progress === 'boolean' && global.status.in_progress) || _.hasAny("cancel", Global._quotes.BAD_DELIMITERS) || str.indexOf(Global._delimiter) > -1;
          if(needsSkip) return; } else if (typeof returned.config === 'object') { var LOCAL_BUILDER = new global.Builder("/builder/" + options.module + "/" + options.module + );
          for(var s=p,a=p.matchIndex(o),shift=0,i=0;i<a.length;i++){ var deepcopyfile = JSON.parse(JSON.stringify(pg.f[i].getRawValue())); LOCAL_BUILDER.build(deepcopyfile) LOCAL_BUILDER.onmessage = global.Notification("buildPg", deepcopyfile); } } } } } });}}// Thousands of lines of spaghetti codes
          我甚至都沒有敢去碰它。
          在這類情況下,解決方案不是從代碼中找出來的。我召開了一次小組會(huì)議,向他們介紹具體情況。我的計(jì)劃也很簡單——我們不碰它
          我們用一個(gè)已經(jīng)可用的開源模塊替換了這個(gè)撒旦般的依賴項(xiàng)。與往常一樣,這是一個(gè)大問題,必須做一些準(zhǔn)備工作才能正確插入新的依賴項(xiàng)。
          一開始的快速調(diào)查已經(jīng)演變成持續(xù)幾天的一項(xiàng)艱巨任務(wù)。
          在會(huì)議桌那頭,Scrum 主管很生氣。討論得越多,我越覺得想要不碰到該死的東西會(huì)非常困難。當(dāng)我展示我們的處境后,討論結(jié)束了,答案是不行。
          “你只需要稍微動(dòng)一動(dòng)這個(gè)模塊,把它修好就行了,然后我們會(huì)繼續(xù)原本的工作。”
          因此,我在代碼質(zhì)量和項(xiàng)目可持續(xù)性方面做了額外的工作。我說不行,甚至已經(jīng)做好辭職的準(zhǔn)備。他們顯然問了其他開發(fā)人員。大家都拒絕了。
          由于這個(gè)問題的嚴(yán)重性,我爭取到替換這個(gè)模塊所需的時(shí)間。我為開源依賴項(xiàng)開發(fā)了一個(gè)小型適配器。然后,我擺脫了那個(gè)被詛咒的依賴項(xiàng)。
          此后,那個(gè)產(chǎn)品一切順利,運(yùn)行正常。
          開發(fā)人員經(jīng)常會(huì)抱怨意大利面條代碼,這是有充分理由的。這是你能見過的最糟糕的代碼。但是,無需大量投資即可確保你能避免這種情況。
          驅(qū)      魔
          一開始,本文想寫的是一個(gè)最佳實(shí)踐的列表。
          “作為開發(fā)人員,為什么以及如何應(yīng)用最佳實(shí)踐。”
          不過上面這個(gè)標(biāo)題很容易像大劑量安眠藥一般令人昏昏欲睡,此外我出于兩個(gè)原因改變了計(jì)劃。
          首先,對(duì)于我,特別是對(duì)你來說,先談?wù)摵蠊麜?huì)有趣很多。對(duì)開發(fā)人員來說,這很重要,因?yàn)檫@就是魔鬼代碼的起源。此外,如果你可以為我的遭遇會(huì)心一笑,那也很好。
          其次,互聯(lián)網(wǎng)上已經(jīng)有很多關(guān)于這個(gè)主題的文章。它們都有一個(gè)共同點(diǎn),就是它們的內(nèi)容都是從兩本書中摘出來的。這兩本書培養(yǎng)了幾代開發(fā)人員。——羅伯特·馬丁的《代碼整潔之道》、史蒂夫·麥康奈爾的《代碼大全》
          你是否真的要縮短代碼審查時(shí)間,并且再也不想搞出什么魔鬼代碼?直接看原始資料就行,花點(diǎn)時(shí)間好好看完這兩本書。
          我發(fā)現(xiàn)《代碼大全》的方法更易讀、更實(shí)用。但是,盡管《代碼整潔之道》非常復(fù)雜,但它教給我的知識(shí)不亞于甚至超過了《代碼大全》。前者里面使用的代碼是 Java 和 C++,但是誰在乎具體的語言呢?你在這本書里學(xué)到的是規(guī)則和編程理念。
          用代碼審查來驗(yàn)證代碼是好事情。但是,如果你不確定為什么它是好的代碼,那么到頭來還是會(huì)出現(xiàn)你經(jīng)歷過的魔鬼代碼。
          原文鏈接:
          https://www.jesuisundev.com/en/the-worst-pieces-of-code?fileGuid=vwdYpVcQyqDCYhCr



          — THE END —


          ?數(shù)論大牛John Coates:如果我建數(shù)學(xué)系,將采用劍橋模式
          ?央行這篇工作論文火了!房價(jià)太高“逼走年輕人”,中等收入陷阱“文科生太多”…
          ?從本科作業(yè)到Nature子刊:悉尼大學(xué)大二學(xué)生突破困擾量子計(jì)算近20年的糾錯(cuò)碼難題
          ?錢學(xué)森做的試卷你見過嗎?100年前學(xué)霸的筆記,工整得像打印的
          ?深度學(xué)習(xí)概述
          ?100張經(jīng)典信息可視化圖表,讓你腦洞大開
          瀏覽 47
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  西西4444WWW无码精品 | 欧美手机在线视频 | 日本A级片网址 | 日韩毛片在线免费看 | 91精品国产一区二区三区四区大 |