關(guān)于重構(gòu)遺留代碼的函數(shù)式處理
????之前的文章中對(duì)于java函數(shù)式編碼做了一些了解,對(duì)于函數(shù)式的流式處理相信各位看官已經(jīng)有些了解,下面讓我們來(lái)淺談一下關(guān)于使用函數(shù)式處理對(duì)臃腫代碼進(jìn)行重構(gòu)的一些分析過(guò)程,預(yù)估這篇帖子文字為主,約消耗3-5分鐘時(shí)間,希望這篇帖子對(duì)各位看官在研發(fā)過(guò)程中能啟到拋磚引玉的作用。
關(guān)于未函數(shù)式處理的代碼存在的問(wèn)題
在java函數(shù)式編程出現(xiàn)之前的時(shí)代,代碼的編寫(xiě)思路大致為:
??? 1.我要code達(dá)到這么業(yè)務(wù)目的;
??? 2.為了達(dá)到業(yè)務(wù)目的,我需要做一些腳手架處理;
基于這兩個(gè)方面,我們開(kāi)始了開(kāi)發(fā)任務(wù),往往在編寫(xiě)過(guò)程中,隨著時(shí)間線的拉長(zhǎng)和開(kāi)發(fā)任務(wù)的緊迫性,到最后我們的項(xiàng)目代碼,往往會(huì)成為項(xiàng)目中的業(yè)務(wù)邏輯與公共處理方法,甚至架構(gòu)層的處理代碼,混為一團(tuán)。成為"一團(tuán)"狀態(tài)的代碼,我們沒(méi)有辦法評(píng)估它的合理性,因?yàn)楫吘顾鉀Q了業(yè)務(wù)問(wèn)題,做到了價(jià)值交付,但是這種項(xiàng)目幾乎不會(huì)給人帶來(lái)愉快的維護(hù)與迭代體驗(yàn),那么它的問(wèn)題出在哪里?
????首先,混亂的結(jié)構(gòu),讓我們?cè)谧鲰?xiàng)目重構(gòu)時(shí)會(huì)頻繁的做業(yè)務(wù)與過(guò)程分離的抽提處理,過(guò)程總對(duì)于源代碼的邏輯步驟會(huì)發(fā)生較大變動(dòng),需要對(duì)原業(yè)務(wù)流程了解十分細(xì)致的人來(lái)協(xié)助,但是往往這個(gè)人處于離職狀態(tài);
????其次,即使我們選擇惰性處理,源代碼保持不動(dòng),我們?cè)诨A(chǔ)之上分層提煉,做部分的重構(gòu)工作,對(duì)于后續(xù)代碼編寫(xiě)的人會(huì)越寫(xiě)越差異,甚至人格越發(fā)分裂,項(xiàng)目的結(jié)構(gòu)越發(fā)混亂,項(xiàng)目服務(wù)間的耦合程度也會(huì)遞增;
????最后,正經(jīng)人誰(shuí)想寫(xiě)這種結(jié)構(gòu)的代碼啊,你想嗎?我反正不想 :)
如何解決業(yè)務(wù)+過(guò)程混合的問(wèn)題?
????讓我們通過(guò)一段code demo來(lái)分析一下,場(chǎng)景是要求在一組專(zhuān)輯中,找出其中所有長(zhǎng)度大于1分鐘的曲目名稱(chēng),較為多見(jiàn)的編寫(xiě)方式:
public Set<String> find(List<Album> albums) {
????Set<String> trackNames = new HashSet<>();
????for(Album album: albums) {
????????for(Track track: album.getTracks()){
????????????if(track.getLen() > 60)?
????????????????trackNames.add(track.getName());
????????}
????}
}
閱讀這段代碼,第一眼我們較難理解它的編寫(xiě)目的,而且處理的邏輯過(guò)程都是硬性編寫(xiě),讀起來(lái)有一些晦澀。讓我們來(lái)看另一種處理寫(xiě)法:
public Set<String> find(List<Album> albums) {
????return albums.stream()
????????????????.flatMap(album-> album.getTracks())
????????????????.filter(track->track.getLen() >60).map(track-> trac.getName())
????????????????.collect(toSet());
}
閱讀這段代碼,可以很直觀的了解我們的業(yè)務(wù)處理步驟,原本業(yè)務(wù)間需要的邏輯處理已經(jīng)被"節(jié)省"掉。就想我們之前介紹函數(shù)式編程時(shí)有聊到,最安全的代碼是編寫(xiě)之后沒(méi)有副作用,這也正是流風(fēng)格代碼的優(yōu)勢(shì)。
與流風(fēng)格代碼的鏈?zhǔn)秸{(diào)用相比較,傳統(tǒng)的代碼風(fēng)格存在的問(wèn)題有:
????·代碼可讀性差,樣板代碼重復(fù)而且較多的重復(fù),將真正業(yè)務(wù)邏輯隱藏;
????·效率差,每一步都要對(duì)流及早求值,產(chǎn)生較多中間集合,浪費(fèi)存儲(chǔ);
????·難以自動(dòng)并行化處理;
????使用不會(huì)產(chǎn)生副作用的函數(shù)式代碼幾乎不會(huì)產(chǎn)生副作用,沒(méi)有副作用的函數(shù)不會(huì)改變程序或者外界的狀態(tài),也就是安全的代碼,建議新接觸的小伙伴采用參考建造者模式進(jìn)行code,以適應(yīng)習(xí)慣流式編程風(fēng)格。
結(jié)語(yǔ)
????今天的分享就寫(xiě)到這里,我是雷記,專(zhuān)注并樂(lè)于分享編程相關(guān)的興趣點(diǎn)與看法,如果你有好的想法和問(wèn)題,歡迎加入我們的討論組一起研討,祝各位國(guó)慶愉快:)
