重構(gòu)之重與敏捷之輕---身份證號(hào)重構(gòu)回顧
尋找重構(gòu)的案例
重構(gòu)的案例不好選取,我們自己實(shí)際的項(xiàng)目當(dāng)然有不少重構(gòu)的情況,卻不適合作為文章闡述出來。并不是因?yàn)楸C艿目剂?而是業(yè)務(wù)本身的內(nèi)容太復(fù)雜。當(dāng)然,這個(gè)復(fù)雜是相對的,對短短一篇文章來說,那怕是最小一部分的業(yè)務(wù)邏輯拿出來,也顯容量不夠。而且,過多的闡述業(yè)務(wù)邏輯,導(dǎo)致喧賓奪主,掩蓋了重構(gòu)的注意力。所以,要選取一個(gè)大家都熟悉的東西,身份證號(hào)恰恰中了我第一個(gè)要求。
即然是重構(gòu),必然要有個(gè)原始的版本,而且,要完成了實(shí)際的功能。開源中國的代碼分享也剛好為我提供了一個(gè)資源庫。代碼分享這個(gè)平臺(tái),真是太理想了,代碼規(guī)模不大不小,每一個(gè)分享又有一個(gè)明確的目標(biāo)功能。
看起來,確實(shí)是個(gè)金礦??墒请S著深入的搜索查看,能進(jìn)入我目標(biāo)范圍的卻是寥寥無幾。大部分代碼只是粘合劑,把外部庫的調(diào)用綜合起來,完成一個(gè)任務(wù)而已。還有些代碼,方法體太大,而代碼卻是簡單重復(fù),似乎重構(gòu)的必要,卻未能展現(xiàn)出重構(gòu)該有的不同側(cè)面,而且也有前面所提到的毛病,是粘合劑代碼塊。
(本文版權(quán)屬于? 2012 - 2013 予沁安)
而當(dāng)我看到身份證這三個(gè)字,才眼睛一亮,看似簡單的身份征號(hào)包括了太多內(nèi)容:
- 它是一個(gè)典型業(yè)務(wù)域的Value Object(不要與C#語法概念的Value Object混淆),我們自己的系統(tǒng)中,剛好也有做一個(gè)身份證號(hào)值對象的想法。之前我們已經(jīng)作一個(gè)月份對象(YearMonth),非常好用,但是,因?yàn)楣δ芏啻a量大,不適合作短篇。
- 它沒有對外部庫的依賴。不是說,我只能對這種獨(dú)立的代碼重構(gòu),而是限于篇幅和重點(diǎn)突出的考慮。
- 它的業(yè)務(wù)邏輯很大眾化,誰沒有身份證呢?
- 分享代碼已經(jīng)把足夠的業(yè)務(wù)邏輯包含進(jìn)起,我所做的就是保持這個(gè)不變?nèi)性谥貥?gòu)上。再完美不過的重構(gòu)案例了。
敏捷的方式重構(gòu)和作文
讓子彈飛
定下了目標(biāo),當(dāng)開始做的時(shí)候,滿腦子都是想法。原代碼是Java,要改成C#; getXX可以用屬性方式,更為簡捷;既然是Value Object,似乎用Struct比用Class更合適;作為Value,它應(yīng)該是個(gè)不變類(Immutable),因此不應(yīng)該動(dòng)態(tài)解析,在構(gòu)造器中解析,更為恰當(dāng); Validation的實(shí)現(xiàn)也不太合適……
是的,像我這樣資深的敏捷實(shí)踐者
,在第一時(shí)間仍有這種沖動(dòng),太多想法馬上實(shí)現(xiàn)的沖動(dòng)。這其實(shí)是人的一種天性,沒關(guān)系,我就讓思維的子彈先飛一會(huì)兒。
子彈亂飛之后的寂靜,我想到的第一件事情就是補(bǔ)測試。說到測試,我用MSpec曾屢屢想為MSpec做個(gè)入門介紹,卻一直未能成文,而直接使用MSpec的博文我卻已經(jīng)寫了不少, 大家就在實(shí)際用例中學(xué)習(xí)Machine.Specification吧。
說是補(bǔ)測試,其實(shí)從Java到C#的編澤錯(cuò)誤修改已經(jīng)開始了不少改動(dòng)。測試這一塊是原代碼完全缺失,補(bǔ)上這個(gè),可以說是重構(gòu)的一部分。
迭代一:
準(zhǔn)備工作做了不少,到最后,真正測試只寫了一個(gè)GetAddress()。而這成為了我的第一天。第一個(gè)測試成為我第一天的目標(biāo),圍繞這個(gè)目標(biāo),我放棄一切與此無關(guān)的工作,特別是之前子彈亂飛的內(nèi)容。
迭代二:
第二天,要做的事情一下子非常明確,按部就班的把其它的功能測試一一補(bǔ)全:生日,性別等等。幾乎不太用腦子,有時(shí)候,事情就是這樣,有波濤洶涌,有風(fēng)平浪靜,唯有測試是船舵。
從測試的條數(shù)來看,第二天進(jìn)展很快。寫出來的內(nèi)容也顯豐富。
迭代三:
第三天的進(jìn)展就順利多了。把各個(gè)功能測試一一補(bǔ)全通過,如生日,性別和驗(yàn)證。其中有個(gè)小插曲,驗(yàn)證邏輯提煉成獨(dú)立的類??偨Y(jié)起來沒有什么好說的,重構(gòu)本身卻有看頭。
迭代四:
到了第四天,才真正開始做我想要做的事情,整理邏輯,清理代碼。再加上代碼覆蓋工具DotCover的幫助,VS的復(fù)雜度分析,從另一個(gè)側(cè)面對重構(gòu)效果加以驗(yàn)證。其實(shí)應(yīng)該在重構(gòu)之前也分析一下代碼,兩相比較一下,效果會(huì)好很多。
從此,xx和xx過上了幸福的生活......
我的博文算是結(jié)束了,可是作為代碼的改進(jìn),其實(shí)并沒有結(jié)束,甚至我最開始的想法,有一部分都還沒有完成,如struct。我還丟掉了一部分業(yè)務(wù),如15位號(hào)碼轉(zhuǎn)換18位。這是作為重構(gòu)的展示已經(jīng)足夠。最重要的是,我已經(jīng)創(chuàng)立了一個(gè)健壯的<測試-實(shí)現(xiàn)>對,這個(gè)基礎(chǔ)上你可以繼續(xù)完善。
代碼本身的技術(shù)含量并不多,但重構(gòu)的流程,任務(wù)細(xì)分,小步前進(jìn)的理念,卻表達(dá)的非常充分。作為體驗(yàn),如果你能按照我走過的流程,再踏踏實(shí)實(shí)走一遍,會(huì)有完全不同的感覺。敏捷是實(shí)踐,重構(gòu)是實(shí)踐,唯有實(shí)踐才能體驗(yàn)實(shí)踐。
皓月碧空,漫野如洗,行往卓越的路上

浙公網(wǎng)安備 33010602011771號(hào)