如何重構(gòu)一個(gè)大型歷史項(xiàng)目——經(jīng)驗(yàn)詳情頁(yè)改版總結(jié)

2018-06-16 18:28 更新

挺長(zhǎng)時(shí)間沒(méi)寫(xiě)博客了,你以為我去玩了嗎?其實(shí)我是去做了一個(gè)大項(xiàng)目。

開(kāi)場(chǎng)之前先來(lái)個(gè)熱身吧,最近擼了一個(gè)小游戲《看你有多色》,源代碼在這里,歡迎大家交流。

項(xiàng)目做完后在內(nèi)部做了次分享,本文就是這次分享的文字版,警告:本文略長(zhǎng),建議備好咖啡,來(lái)一段愉快的閱讀之旅吧,我保證不會(huì)讓你失望的。

本文將會(huì)介紹如何重構(gòu)一個(gè)大型歷史項(xiàng)目的方方面面。

本文將會(huì)按照下面的目錄展開(kāi)分享,本文僅討論技術(shù)。

  • 簡(jiǎn)介
  • 準(zhǔn)備
  • 時(shí)間
  • 團(tuán)隊(duì)
  • 技術(shù)
  • 架構(gòu)
  • 邊界
  • 收益
  • 總結(jié)

簡(jiǎn)介

這次要改版的是經(jīng)驗(yàn)最重要的頁(yè)面之一——經(jīng)驗(yàn)wap詳情頁(yè),流量巨大,歷史悠久,就導(dǎo)致這必然是一個(gè)復(fù)雜的問(wèn)題。

準(zhǔn)備

項(xiàng)目上的準(zhǔn)備就是PM提供的MRD和設(shè)計(jì)師提供的PSD,前端的準(zhǔn)備基本是先熟悉舊版頁(yè)面的邏輯,我本人其實(shí)也不熟悉這個(gè)頁(yè)面。

時(shí)間

項(xiàng)目開(kāi)始前肯定要給出排期,那么接下來(lái)就說(shuō)排期和時(shí)間管理的問(wèn)題。

預(yù)估時(shí)間

前端項(xiàng)目的時(shí)間預(yù)估最準(zhǔn)確的就是從UE圖預(yù)估,拿到UE圖后將其拆分成各個(gè)組件,然后評(píng)估每個(gè)模塊的開(kāi)發(fā)時(shí)間,其實(shí)思想就是分治,將不可評(píng)估任務(wù)拆分成可評(píng)估任務(wù)。

這次的項(xiàng)目因?yàn)槭蔷湍K改版,還有一個(gè)維度就是看就模塊老代碼,這次老模塊是一個(gè)X,工作量未知,所以留了一些buffer,結(jié)果還真派上了用場(chǎng),在老代碼里跌倒了幾次。/(ㄒoㄒ)/~~

舉個(gè)例子:

  • 導(dǎo)航 2h
  • 頭部 3h
  • 尾部 4h
  • 。。。

風(fēng)險(xiǎn)

這次遇到可能影響進(jìn)度的風(fēng)險(xiǎn)點(diǎn)主要都是來(lái)自經(jīng)驗(yàn)的老代碼,歷史數(shù)據(jù)結(jié)構(gòu),各種邊界case。

有些東西,你不看老模塊的代碼是不可能知道的,所以還是要把老代碼全部看懂才行。

合作

本次兩個(gè)人一起開(kāi)發(fā),就涉及到如何合作的問(wèn)題,在開(kāi)始之前我制定了一些規(guī)則。

才學(xué)了語(yǔ)義化的提交信息,我準(zhǔn)備嘗試一下,我指定的規(guī)范在這里《我的提交信息規(guī)范》。

最后我們一共提交了100多個(gè)commit,基本上等同于100多個(gè)小功能,我提倡勤提交,這樣方便兩個(gè)人同步進(jìn)度。

因?yàn)轫?yè)面被拆分成了模塊,而我們的項(xiàng)目中支持模塊化開(kāi)發(fā),所以?xún)蓚€(gè)人合作起來(lái)還是挺容易的,每個(gè)人負(fù)責(zé)自己的模塊,互不干擾。

效率

根據(jù)人月神話(huà)來(lái)說(shuō),團(tuán)隊(duì)人越多可能效率越低,那么如何保證兩個(gè)人的效率和一個(gè)人時(shí)是一樣的呢?我們有如下利器來(lái)保證:

  • 模塊化開(kāi)發(fā)
  • 良好的基礎(chǔ)框架
  • 合理的項(xiàng)目(功能)拆分

技術(shù)

接下來(lái)說(shuō)說(shuō)我們這次改版的技術(shù)細(xì)節(jié)吧。

指導(dǎo)原則

技術(shù)上大體可以分為以下幾類(lèi):

  • 新技術(shù)
  • 陳舊技術(shù)
  • 成熟技術(shù)
  • 穩(wěn)定技術(shù)

對(duì)于新技術(shù)我們還是持敬畏的態(tài)度,這次的選型就是選擇成熟穩(wěn)定的技術(shù)。

技術(shù)棧

來(lái)說(shuō)說(shuō)我們這次的技術(shù)棧吧

  • fis-plus
  • sass
  • es6(新技術(shù))
  • promise(新技術(shù))
  • template
  • zepto,gmu

架構(gòu)

架構(gòu)是個(gè)最大的問(wèn)題,我們從下面四個(gè)方面來(lái)說(shuō)說(shuō):

  • 目錄
  • 結(jié)構(gòu)
  • 樣式
  • 行為

目錄

我們的目錄規(guī)范就是fisp的目錄規(guī)范,主要目錄如下:

  • page 模版文件
  • test 測(cè)試數(shù)據(jù)
  • widget 組成頁(yè)面的組件

模版

我們用的是smarty模版,對(duì)應(yīng)的就是結(jié)構(gòu)——HTML,比如我們的模版文件是index.tpl,其內(nèi)部有各個(gè)組件拼裝而成。

模版可以繼承,我們的業(yè)務(wù)模版都繼承通用模版,這樣的好處就是方便給所有頁(yè)面添加通用的一些東西。

還可以在父模版挖一些坑,在自模版填,這個(gè)功能叫做block。

舉個(gè)例子吧,比如如下圖我們?cè)诟改0嫱谝粋€(gè)title的坑,因?yàn)槊總€(gè)頁(yè)面的title可能都不一樣,在子頁(yè)面我們會(huì)向填坑

再來(lái)說(shuō)說(shuō)widget,一般的一個(gè)頁(yè)面會(huì)被拆分成一個(gè)個(gè)模塊(組件),然后又每個(gè)模塊去拼裝頁(yè)面。

舉個(gè)例子,下面左邊就是拆分完的頁(yè)面,右邊是偽代碼。

樣式

這次改版我們的樣式?jīng)Q定使用sass這個(gè)預(yù)處理器。

我們將樣式精心分類(lèi),總共有以下三類(lèi):

  • 公用css
  • 組件css
  • mixin

我們定義了兩個(gè)mixin:

@mixin clearfix() {
  &::after {
    content: "";
    display: table;
    clear: both;
  }
}

@mixin size($width, $height: $width) {
  width: $width;
  height: $height;
}

_variables.scss里面我們只定義了幾個(gè)能夠抽取成公共的顏色變量

再來(lái)說(shuō)說(shuō)組件樣式,一個(gè)典型的組件代碼大概如下:

@import "mixin";
@import "variables";

.wgt-step-read {
    background: $bg-color;
    a {
        color: $color-primary;
    }
    .arrow {
        @include size(5px, 9px);
    }
}

其編譯后的css如下所示

.wgt-step-read {background: #fff;}
.wgt-step-read a {color: #333;}
.wgt-step-read .arrow {width: 5px; height: 9px}

用了sass后我們可能會(huì)忽視嵌套問(wèn)題,任意嵌套,我們規(guī)定嵌套不能超過(guò)三層。

小貼士:這里介紹一個(gè)css選擇符的兩種邏輯,我推薦的其實(shí)是中庸思想,不走極端。

.wgt-step-read .arrow // 嵌套
.wgt-step-read-arrow // 組合類(lèi)名

.wgt-step-read ul p span // bad
.wgt-step-read .pv // 添加類(lèi)名,解決上面嵌套層級(jí)的問(wèn)題

再來(lái)說(shuō)說(shuō)我們樣式的指導(dǎo)原則:

  • wgt前綴(區(qū)分模塊和其他類(lèi))
  • 嵌套不要超過(guò)三層(添加類(lèi)名解決)
  • 合理使用類(lèi)名(語(yǔ)義)
  • 合理使用mixin(區(qū)分extend)
  • DRY

最后說(shuō)說(shuō)布局之爭(zhēng),項(xiàng)目開(kāi)始時(shí)我們有如下兩種布局可以選擇:

  • px
  • rem

最終我們選的還是傳統(tǒng)的px,因?yàn)槲覀優(yōu)槲覀兪侵R(shí)型頁(yè)面,頁(yè)面多為文字;其次px比rem更簡(jiǎn)單。

在我的邏輯看起來(lái)我用大屏是未來(lái)看到更多的文字,而不是更大的字體,如果我想看更大的字體我自己調(diào)整字體就好了。

行為

行為這里展開(kāi)講的地方不太多,因?yàn)榘凑漳K拆分以后,每個(gè)js都不太大,強(qiáng)調(diào)的一點(diǎn)就是不要再拼接字符串了,而是改用前端模版。

邊界

邊界這塊在內(nèi)部分享中介紹了很多內(nèi)容,這里絕大部分都不能展開(kāi)敘述,因?yàn)榭赡軙?huì)涉及到一些內(nèi)部的數(shù)據(jù);當(dāng)然我會(huì)將一些比較通用的知識(shí),不涉及經(jīng)驗(yàn)的具體細(xì)節(jié)。

起源

對(duì)于經(jīng)驗(yàn)而言,經(jīng)過(guò)了多年的沉淀,已經(jīng)沒(méi)有人能夠熟悉的知道他的方方面面,那么我們?nèi)绾卫砬宄?jīng)驗(yàn)的一些屬性、分類(lèi)、邊界情況呢?

答案就是追本溯源,而不是舍本逐末,我開(kāi)始的出發(fā)方向就錯(cuò)了,我一頭跳進(jìn)了某一個(gè)case中,還好后來(lái)及時(shí)修正了這種錯(cuò)誤的思想。

舉個(gè)例子,我們是如何追本溯源的呢?大概從以下一些方面:

  • 產(chǎn)生經(jīng)驗(yàn)的地方
  • 后端數(shù)據(jù)
  • 老代碼

最直觀的其實(shí)就是生產(chǎn)經(jīng)驗(yàn)的地方,也就是說(shuō)每個(gè)case都能在這里找到出處。

其次就是看模版數(shù)據(jù),再次就是看經(jīng)驗(yàn)的老代碼。

總而言之,經(jīng)驗(yàn)的復(fù)雜程度超乎我的想象。

一條線(xiàn)的變遷

有太多內(nèi)容都不能公開(kāi)給大家,想來(lái)想去就說(shuō)這個(gè)吧,還比較有意思。

對(duì)你沒(méi)看錯(cuò),就是下面這條線(xiàn),就是她?。?!

看看我是怎么實(shí)現(xiàn)的吧,如下圖,對(duì)你們看錯(cuò),separator-line就是這條線(xiàn)

不知道你會(huì)不會(huì)鄙視我,我選擇了一種不太優(yōu)雅的實(shí)現(xiàn)方式,為了裝飾性增加了多余的html。

不知道你會(huì)如何實(shí)現(xiàn)這條線(xiàn),來(lái)說(shuō)說(shuō)我的實(shí)現(xiàn)方式吧。

最開(kāi)始時(shí),我把它放在了tag-wp的bodder-bottom上,后來(lái)我發(fā)現(xiàn)tag-wp竟然可能不存在,o(╯□╰)o

我想那我就放在abstract-wp上吧,也許聰明的你猜到了解決,是的,這個(gè)元素也可能沒(méi)有。

最后我只能搞一個(gè)單獨(dú)元素出來(lái)了,o(╯□╰)o

這個(gè)問(wèn)題其實(shí)我們也可以換個(gè)思路,就峰回路轉(zhuǎn)了,我們可以不把這條線(xiàn)考慮成裝飾性元素,而是考慮成分割線(xiàn),是不是就好理解了呢,分割線(xiàn)就是該用一個(gè)元素來(lái)表示(hr),雖然我這里沒(méi)有用hr,但是內(nèi)心總是不那么忐忑了,誰(shuí)讓我是強(qiáng)迫癥呢,不寫(xiě)出優(yōu)雅的代碼我會(huì)吃不下,睡不著的。

收益

最后來(lái)說(shuō)說(shuō)這次改版的收益吧。

可維護(hù)性

舊的代碼,陳年失修,而且一直在打補(bǔ)丁,自我感覺(jué)改版后,可維護(hù)性上了一個(gè)量級(jí),這里就不能給大家貼代碼展示了。

不過(guò)有一個(gè)數(shù)據(jù)還是可以拿來(lái)展示一些的,其實(shí)新舊版都要處理同樣的邏輯的,同樣的邏輯舊版用了107行,而新版只用了73行。

總結(jié)

這次改版讓我明白了一個(gè)道理,頁(yè)面中的任何元素都可能沒(méi)有,需要考慮到容錯(cuò)處理;設(shè)計(jì)不能一蹴而就,往往需要反復(fù)打磨,反復(fù)修改,或者推翻重來(lái);憑空的設(shè)計(jì)完美卻不實(shí)用,好的設(shè)計(jì)必須結(jié)合產(chǎn)品內(nèi)容,項(xiàng)目細(xì)節(jié)。

優(yōu)點(diǎn)

這次改版我認(rèn)為在下面幾點(diǎn)上都是做的不錯(cuò)的地方:

  • 架構(gòu)
  • 新技術(shù)
  • 團(tuán)隊(duì)合作

缺點(diǎn)

如果說(shuō)優(yōu)缺點(diǎn)的話(huà),我認(rèn)為唯一的缺點(diǎn)就是時(shí)間的預(yù)估了,時(shí)間預(yù)估上的失誤還是很明顯的。如果時(shí)間不能準(zhǔn)確預(yù)估需要留好buffer。

表?yè)P(yáng)

我需要表?yè)P(yáng)我隊(duì)友的效率,開(kāi)發(fā)真的很快。比我快太多。

批評(píng)與自我批評(píng)

我要批評(píng)我隊(duì)友的效率,復(fù)制粘貼了太多老代碼,自己也沒(méi)看,而且代碼規(guī)范都沒(méi)遵守。

我也要批評(píng)我自己的效率,想得太多,做的太少,應(yīng)該提高自己的效率。

本文的百度腦圖。

以上內(nèi)容是否對(duì)您有幫助:
在線(xiàn)筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)