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

2018-06-16 18:28 更新

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

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

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

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

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

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

簡介

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

準(zhǔn)備

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

時(shí)間

項(xiàng)目開始前肯定要給出排期,那么接下來就說排期和時(shí)間管理的問題。

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

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

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

舉個(gè)例子:

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

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

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

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

合作

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

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

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

因?yàn)轫撁姹徊鸱殖闪四K,而我們的項(xiàng)目中支持模塊化開發(fā),所以兩個(gè)人合作起來還是挺容易的,每個(gè)人負(fù)責(zé)自己的模塊,互不干擾。

效率

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

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

技術(shù)

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

指導(dǎo)原則

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

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

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

技術(shù)棧

來說說我們這次的技術(shù)棧吧

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

架構(gòu)

架構(gòu)是個(gè)最大的問題,我們從下面四個(gè)方面來說說:

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

目錄

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

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

模版

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

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

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

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

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

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

樣式

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

我們將樣式精心分類,總共有以下三類:

  • 公用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è)能夠抽取成公共的顏色變量

再來說說組件樣式,一個(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ì)忽視嵌套問題,任意嵌套,我們規(guī)定嵌套不能超過三層。

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

.wgt-step-read .arrow // 嵌套
.wgt-step-read-arrow // 組合類名

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

再來說說我們樣式的指導(dǎo)原則:

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

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

  • px
  • rem

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

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

行為

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

邊界

邊界這塊在內(nèi)部分享中介紹了很多內(nè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)過了多年的沉淀,已經(jīng)沒有人能夠熟悉的知道他的方方面面,那么我們?nèi)绾卫砬宄?,?jīng)驗(yàn)的一些屬性、分類、邊界情況呢?

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

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

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

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

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

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

一條線的變遷

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

對(duì)你沒看錯(cuò),就是下面這條線,就是她?。?!

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

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

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

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

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

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

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

收益

最后來說說這次改版的收益吧。

可維護(hù)性

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

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

總結(jié)

這次改版讓我明白了一個(gè)道理,頁面中的任何元素都可能沒有,需要考慮到容錯(cuò)處理;設(shè)計(jì)不能一蹴而就,往往需要反復(fù)打磨,反復(fù)修改,或者推翻重來;憑空的設(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)

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

表揚(yáng)

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

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

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

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

本文的百度腦圖。

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

掃描二維碼

下載編程獅App

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

編程獅公眾號(hào)