<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>

          再見,整潔代碼

          共 4585字,需瀏覽 10分鐘

           ·

          2021-10-30 17:16

          那是一個(gè)深夜。

          我的同事們剛剛提交了過去整整一周所寫的代碼。我們正在開發(fā)一個(gè)基于 Canvas 的圖形編輯器,他們負(fù)責(zé)實(shí)現(xiàn)各種“形狀”(比如:矩形、橢圓形)的縮放功能,縮放行為由拖拽“形狀”邊緣上的操作柄來實(shí)現(xiàn)。

          代碼運(yùn)行正常。

          但是代碼有些重復(fù)。每個(gè)“形狀”(如:矩形、橢圓形)各自擁有若干操作柄,從不同方向拖拽操作柄都會(huì)對(duì)“形狀”的位置和尺寸產(chǎn)生相應(yīng)的影響。如果用戶按住“Shift”鍵,我們還需要保持住“形狀”的寬高比不變。這里涉及到一些數(shù)學(xué)計(jì)算。

          代碼看起來是這樣的:

          let?Rectangle?=?{
          ??resizeTopLeft(position,?size,?preserveAspect,?dx,?dy)?{
          ????//?10?repetitive?lines?of?math
          ??},
          ??resizeTopRight(position,?size,?preserveAspect,?dx,?dy)?{
          ????//?10?repetitive?lines?of?math
          ??},
          ??resizeBottomLeft(position,?size,?preserveAspect,?dx,?dy)?{
          ????//?10?repetitive?lines?of?math
          ??},
          ??resizeBottomRight(position,?size,?preserveAspect,?dx,?dy)?{
          ????//?10?repetitive?lines?of?math
          ??},
          };

          let?Oval?=?{
          ??resizeLeft(position,?size,?preserveAspect,?dx,?dy)?{
          ????//?10?repetitive?lines?of?math
          ??},
          ??resizeRight(position,?size,?preserveAspect,?dx,?dy)?{
          ????//?10?repetitive?lines?of?math
          ??},
          ??resizeTop(position,?size,?preserveAspect,?dx,?dy)?{
          ????//?10?repetitive?lines?of?math
          ??},
          ??resizeBottom(position,?size,?preserveAspect,?dx,?dy)?{
          ????//?10?repetitive?lines?of?math
          ??},
          };

          let?Header?=?{
          ??resizeLeft(position,?size,?preserveAspect,?dx,?dy)?{
          ????//?10?repetitive?lines?of?math
          ??},
          ??resizeRight(position,?size,?preserveAspect,?dx,?dy)?{
          ????//?10?repetitive?lines?of?math
          ??},??
          }

          let?TextBlock?=?{
          ??resizeTopLeft(position,?size,?preserveAspect,?dx,?dy)?{
          ????//?10?repetitive?lines?of?math
          ??},
          ??resizeTopRight(position,?size,?preserveAspect,?dx,?dy)?{
          ????//?10?repetitive?lines?of?math
          ??},
          ??resizeBottomLeft(position,?size,?preserveAspect,?dx,?dy)?{
          ????//?10?repetitive?lines?of?math
          ??},
          ??resizeBottomRight(position,?size,?preserveAspect,?dx,?dy)?{
          ????//?10?repetitive?lines?of?math
          ??},
          };

          這種重復(fù)的數(shù)學(xué)計(jì)算邏輯,對(duì)我來說,真的難受。

          這不是“整潔”的代碼。

          多數(shù)的重復(fù)都在于“方向”上的相似,舉個(gè)例子,Oval.resizeLeft()?和?Header.resizeLeft()?就很類似。這是因?yàn)?,它們都是在處理拖拽左?cè)操作柄的問題。

          另一個(gè)原因在于“形狀”所擁有的方法上的相似,例如,Oval.resizeLeft()?和?Oval?上的其它方法是類似的。這是因?yàn)?,它們都是在處理“橢圓形”上的問題。更進(jìn)一步,Rectangle,?Header?以及?TextBlock?都有相似的地方,因?yàn)槲谋究蚨际恰熬匦巍薄?/span>

          我有個(gè)辦法。

          我們可以通過對(duì)代碼邏輯進(jìn)行分組,來實(shí)現(xiàn)“去除全部重復(fù)”的目的:

          let?Directions?=?{
          ??top(...)?{
          ????//?5?unique?lines?of?math
          ??},
          ??left(...)?{
          ????//?5?unique?lines?of?math
          ??},
          ??bottom(...)?{
          ????//?5?unique?lines?of?math
          ??},
          ??right(...)?{
          ????//?5?unique?lines?of?math
          ??},
          };

          let?Shapes?=?{
          ??Oval(...)?{
          ????//?5?unique?lines?of?math
          ??},
          ??Rectangle(...)?{
          ????//?5?unique?lines?of?math
          ??},
          }

          然后,像這樣來組合它們:

          let?{top,?bottom,?left,?right}?=?Directions;

          function?createHandle(directions)?{
          ??//?20?lines?of?code
          }

          let?fourCorners?=?[
          ??createHandle([top,?left]),
          ??createHandle([top,?right]),
          ??createHandle([bottom,?left]),
          ??createHandle([bottom,?right]),
          ];
          let?fourSides?=?[
          ??createHandle([top]),
          ??createHandle([left]),
          ??createHandle([right]),
          ??createHandle([bottom]),
          ];
          let?twoSides?=?[
          ??createHandle([left]),
          ??createHandle([right]),
          ];

          function?createBox(shape,?handles)?{
          ??//?20?lines?of?code
          }

          let?Rectangle?=?createBox(Shapes.Rectangle,?fourCorners);
          let?Oval?=?createBox(Shapes.Oval,?fourSides);
          let?Header?=?createBox(Shapes.Rectangle,?twoSides);
          let?TextBox?=?createBox(Shapes.Rectangle,?fourCorners);

          代碼量減少到 1 / 2,并且,重復(fù)代碼不復(fù)存在!這真是“整潔”啊。如果我們希望改變具體某個(gè)“方向”上的或“形狀”上的行為,只需要修改一處,而非多處。

          已經(jīng)很晚了(我很疲憊了),我提交我重構(gòu)后的代碼,然后就躺下了,并對(duì)自己“幫助同事整潔代碼”而感到心滿意足。

          第二天上午

          … 事情并非我想的那樣。

          我的上級(jí)單獨(dú)找到了我,委婉地要求我撤銷昨天的那些修改。我感到很不可思議,舊代碼那么差勁,而我的是多么“整潔”??!

          我那時(shí)只好謹(jǐn)遵照守;但是后來,歷經(jīng)數(shù)年,我才明白他們的要求是對(duì)的。

          那是一個(gè)職業(yè)階段

          對(duì)“整潔代碼”的沉迷、好于“消除重復(fù)代碼”,是我們大多數(shù)開發(fā)者都會(huì)經(jīng)歷的階段。當(dāng)我們對(duì)自己的代碼沒有信心,自我價(jià)值感和專業(yè)榮譽(yù)感往往會(huì)使我們與一些可測量的東西靠攏,一組嚴(yán)格的 lint 規(guī)則、一套命名規(guī)范、一種文件結(jié)構(gòu)、無重復(fù)性指標(biāo),等等。

          你不可能讓“重復(fù)代碼”自動(dòng)被消除,但是確實(shí)可以借助“實(shí)踐經(jīng)驗(yàn)”使它更可行。你往往可以看到,每次修改后的代碼量是變得更多或更少。結(jié)果就是,消除重復(fù)代碼看起來提高了代碼的某些客觀的可測量指標(biāo)。然而,糟糕的是,這擾亂了人們的自我認(rèn)知,他們會(huì)對(duì)自己說:“我是那種會(huì)寫出整潔代碼的人”,而這其實(shí)跟其它的自我欺騙行為沒什么兩樣。

          一旦學(xué)會(huì)了如何“抽象”,我們似乎就會(huì)更進(jìn)一步,每次看到重復(fù)的代碼,我們甚至能夠從“無”中發(fā)現(xiàn)可“抽象”的東西。編碼數(shù)年以后,我們已經(jīng)厲害得隨處都能看到重復(fù)的代碼,我們同時(shí)獲得了一項(xiàng)新的超能力:抽象。進(jìn)而,如果有人告訴我們“抽象是好的”,我們便對(duì)此更加篤信。于是我們開始去批判那些不崇尚”整潔代碼”的人。

          我現(xiàn)在明白,我的那次“重構(gòu)行為”確實(shí)是一場災(zāi)難(譯者:夸張了吧~),從兩個(gè)方面來說:

          • 首先,我沒有告訴代碼的作者。我在沒有他們參入的情況下,重寫并提交了代碼。即便,那確是一次對(duì)代碼的“改善”(我現(xiàn)在不以為然了),它也十分可怕。一個(gè)健康的工程團(tuán)隊(duì)需要不斷地“建立彼此的信任”。不經(jīng)討論而擅自重寫同事的代碼,是對(duì)高效協(xié)作能力的徹底否定。
          • 其次,一切都需要權(quán)衡。為了減少重復(fù),我的代碼難于應(yīng)付需求變更,而這并不值得。例如,我們后邊需要為不同“形狀”上的各個(gè)操作柄添加特殊的行為邏輯。為了應(yīng)付這些,我的“抽象”無疑使修改困難了數(shù)倍,反觀那原本“骯臟的”代碼,它則能夠輕松處理。

          我的意思是你應(yīng)該寫“臟”的代碼嗎?不,我建議你深入思考一下“整潔”與“骯臟”分別意指何物。你有對(duì)于批判、正確、美和優(yōu)雅的直覺嗎?你如何能確定地說你的這次工程成果達(dá)到了那些質(zhì)量指標(biāo)?它們?nèi)绾未_切地影響到代碼的產(chǎn)生與維護(hù)?

          我當(dāng)時(shí)確然對(duì)于這些問題沒有進(jìn)行過深入思考;我當(dāng)時(shí)考慮的是代碼“看起來”如何,而不是代碼該如何隨著不斷流動(dòng)的團(tuán)隊(duì)而演進(jìn)。

          寫代碼是一場旅行?;叵胍幌?,你編寫第一行代碼時(shí)的情形,到現(xiàn)在你所處的狀態(tài)。我相信,當(dāng)突然發(fā)現(xiàn)“抽取出一個(gè)函數(shù)”或“重構(gòu)一個(gè)類的定義”是如何使問題由復(fù)雜變得簡單的時(shí)候,你必定是開心的。一旦對(duì)自己的作品產(chǎn)生了自豪感,你就會(huì)熱切地去追求代碼的整潔。對(duì)此,你可以保持一段時(shí)間。

          但是不要止乎此,不要成為一個(gè)整潔代碼的狂熱分子。整潔代碼并不是目的,它只是讓我們從所面對(duì)系統(tǒng)的異常復(fù)雜性中解脫出來的方法。在你不是很明確一個(gè)改動(dòng)會(huì)如何影響到整個(gè)代碼庫時(shí),這信念可以作為一種安全防護(hù)機(jī)制。但是在未知的海洋里,你需要一個(gè)指南針。

          那就讓整潔代碼指引你吧,然后忘了它。

          轉(zhuǎn)自:https://overreacted.io/zh-hans/goodbye-clean-code/

          ——————END——————

          歡迎關(guān)注“Java引導(dǎo)者”,我們分享最有價(jià)值的Java的干貨文章,助力您成為有思想的Java開發(fā)工程師!

          瀏覽 34
          點(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>
                  我要看日本一级黄色片 | 日本处女学生妺一级片 | 蜜桃视频免费网站 | 成天免费无码婬片在线观看免费 | 永久免费一区二区 |