天天看點

記一次返工

作者:Grey

原文位址: 記一次返工

本周我經曆了參加工作以來,最大的一次返工,這一周都是茶飯不思的感覺,特此記錄一下,防止後續犯同樣的錯誤。

有一個Web系統X,使用者可以通過這個系統檢視自己的待辦資訊,并且可以用于待辦的審批,還有一個我們做的手機應用Y,Y系統需要支援檢視X系統的待辦資訊并完成審批操作。

剛拿到這個“粗粒度”需求的時候,我沒有進行足夠的需求分析,就開始“信心滿滿”梳理了一下自己的思路:

第一步:

X系統已有擷取待辦清單的接口,是以,擷取待辦清單這件事,我隻需要調用X系統接口并轉換成Y系統需要的資料結構即可。

第二步:

我當時的方案是通過X系統提供的一個後門URL(這個URL可以直接打開某條待辦的詳情)然後用爬蟲抓取待辦詳情,詳情的抓取最初考慮的是用js找一堆頁面元素的值,因為詳情内容比較多,且分布在多個iframe和tab頁面中,是以要模拟浏覽器跳轉到相應的iframe或者tab中抓取相應的詳情,這也為後續埋下了一個坑(因為要模拟浏覽器操作,切換頁面等操作會導緻抓取詳情時間會偏長,而Y系統擷取請求的時間隻有10s,超過10s的就會顯示資料加載失敗了)。

第三步:

待辦詳情中有附件資訊,我們無法通過抓取得到詳細的附件URL,是以需要在詳情頁面中,擷取相應的附件的ID,然後在X的伺服器中部署一個我寫的小程式,這個小程式可以通過附件ID查詢X系統資料庫擷取附件的實體位置,然後拿到附件資訊,并發請求到我們的文檔轉換系統中,可以将附件轉換成圖檔,轉換成圖檔最大地好處是可以在移動端很快速的預覽。

第四步:

第二步中的後門URL包含了審批資訊輸入框和審批按鈕, 我隻需要找到審批意見輸入框,用js腳本填入審批意見,找到審批按鈕,模拟浏覽器點選審批按鈕行為進行審批操作。稍微複雜一點地是要判斷點選審批按鈕以後,是否需要選擇下一步地審批人,這一步也好解決,通過抓取詳情頁面中下拉選人框中的内容,就可以把下一步需要選的審批人也抓取出來并告知Y系統下一步需要支援選人的操作。

梳理完以後自己的思路以後,當時我是這樣的感覺,

記一次返工

然後就“信心滿滿”進行開發了。。。

待辦詳情的抓取時間很不穩定,大概十次有6次會逾時(超過10s),我們有一個抓取的小程式,采用的是Phantom JS,我就用這個小程式進行詳情的抓取,邏輯大概是:

打開待辦URL,這個URL是後門URL,包含了使用者登入的操作,是以是必須打開的一個頁面。

等待頁面完全打開,我是通過判斷頁面中某個元素是否存在來判斷這個頁面是否完全打開了,即如果元素存在,證明頁面已經完全渲染完畢,如果不存在則一直等待頁面渲染。

然後開始抓取詳情,這裡需要切換一個iframe和打開兩個tab頁面,分别從裡面擷取需要的資料。但是這個過程太長了,因為1和2已經耗費了大約3s多的時間,後面的切換iframe和切換tab,都要等頁面完全渲染完畢才能抓取資訊,導緻時間經常會超過10s,如果增加逾時時間,體驗又會明顯變差,這顯然是不能接受的。

面對逾時問題,想到了另外一個解決方案,通過發ajax請求,直接擷取詳情資料,Chrome控制台下看了一下待辦詳情頁面請求,大部分入參都可以通過正則查找目前頁面來獲得,這便減少了兩次切換頁面的操作,但是有幾個參數沒辦法在目前頁面擷取,還是需要至少切換一個tab來擷取。

是以,解決辦法就變成了:

同上

然後開始抓取詳情,先在目前頁面擷取到能擷取到的所有需要發請求的入參值,然後用Js逐一發送請求擷取詳情。因為是逐一發ajax請求,要等待傳回值操作再發下一個請求,雖然比第一次嘗試速度有所提升,但是速度還是不穩定,還是會出現逾時現象。

第二次嘗試的瓶頸在于,串行發請求,速度還是有很大的限制,Js能否實作并發請求呢?說來慚愧,之前一直是做後端,用Java開發,連Js并發操作這件事,都不是特别清楚,是以就查了相關的資料,發現了Promise.all

将Ajax請求一個個封裝起來,諸如:

等若幹個這樣的方法,

然後通過Promise.all來并發執行這些請求:

用Promise.all重構完以後,我的心情是這樣的:

記一次返工

當我“戰戰兢兢”再一次嘗試擷取詳情的時候,速度是快了,但是,還是不穩定,還是會出現逾時的現象(10次大概有5次,這個頻率也是無法被接受的)。

我堅信用JavaScript做這件事還有其他優化的方向,限于技術能力,我當時能想到的用JavaScript來處理的方式就這麼多,而且截至時間馬上要到了,我沒有時間再去探索了,是以我用了自己相對熟悉的WebMagic很快地重構了一版,并發抓取詳情,發現,速度快了,而且也穩定很多了,10次可能最多2次逾時,後來仔細分析了一下逾時的原因,ajax請求發送過去以後,對方有一兩個請求傳回非常慢(30s以上),這件事我回報給自己的上司,當時是沒有解決方案,對方系統目前不可能做優化。

好吧,就到這裡吧,可以開始流程測試了!

我并沒有馬上送出測試人員進行測試,我想自己盡可能先走幾個流程,自己先測試整個流程是不是有問題,因為自己沒有用過X系統,是以找了相關的一位同僚幫助我建了一些測試的流程,我走了幾個測試流程,發現,還蠻順利的,流程性的bug基本沒有,詳情的抓取内容也正常,我當時就恨不得馬上就可以上線:

記一次返工

正當我“信心滿滿”地準備傳遞的時候,心裡還是不自覺地警惕了一下,要不再測一個流程?這一測,心都拔涼了,發現了一個大bug,

原來待辦詳情沒有那麼簡單,待辦詳情裡面有一個清單,我一直覺得這個清單是作為詳情顯示的,沒有什麼特别的地方,

可是後來我發現,這個清單裡面的每一項,都可以單獨進行審批!這就意味着,原先的思路就是錯的!

原先的思路是:

點選待辦->檢視詳情->審批

而正确的思路是:

點選待辦->檢視這個待辦中的條目資訊->點選條目資訊->檢視條目資訊->審批

此刻,我的心情是這樣的:

記一次返工

可是又有什麼辦法呢,硬着頭皮也要改!

上述bug帶來的問題不僅是架構的問題,還有性能,相當于每個條目都要切換一次頁面重新發送請求擷取詳情,

是以在待辦清單點選進入條目的時候,要準備好每個條目需要的ajax請求參數,這會增加條目擷取的時間,使用者打開條目目錄這件事,就要花去相當于之前看待辦詳情的時間,然後點選條目再看詳情這件事,也要花去同樣的時間,使用者體驗會極差,很大可能又會是逾時。

最後,各方溝通,我們決定直接通路X系統資料庫拿資料,因為是遺留系統,開發商已經不在了,運維人員也隻有代碼并做一些簡單的維護,我們決定直接看X系統的源碼來找到相應的邏輯,并用sql來查詢并擷取X系統的資料。

幸好,我們找到了大部分SQL語句,SQL的參數,之前在查找Ajax請求的時候,已經找到大部分了,是以我在附件抓取程式中将待辦和條目詳情擷取的邏輯轉換成直接從資料庫查詢資料。在此,感謝MyBatis-Spring-Boot-Starter,@Annotation的方式簡直比之前的XML方式提升了太多的開發效率,我幾乎可以原封不動拷貝原系統的SQL來進行查詢,用法如下:

這裡的

就相當于是X系統原封不動的拿來的SQL語句,資料結構也來不及設計了,就用<code>List&lt;Map&lt;String,Object&gt;&gt;</code>把!

改成從資料庫拿資料以後,沒有了逾時的問題了,重新測試了幾個流程,都正常了,終于可以舒一口氣了,但是心情卻很是複雜。

記一次返工

充分了解需求,應該在開發之前充分地了解需求,細化需求,由于需求了解不到位而返工開發的代價是巨大的。

在第三次嘗試中,有一個插曲,當時我面臨兩個方向的技術選擇,一個是使用自己相對不熟悉的JavaScript來做并發, 另一個是當時自己相對熟悉的Java中的爬蟲抓取工具WebMagic,也可以很好地實作并發操作。如果用WebMagic,或許并發和使用這塊,我會更加熟悉,之是以當時先選擇了JavaScript來做,是因為當時腦海中冒出了這樣的的想法:

自己的Js技術相對Java要弱一點,就要多鍛煉一下,是以就一直再探索用JavaScript可以有哪些優化的地方。畢竟自己的目标是希望可以做一個全棧工程師。

我似乎忘記了這是一個工作任務,完全把這個當成了自己學習和鍛煉的途徑,忽視了工作任務是有截至時間的。

這幾年,自己的學習方式大多是蜻蜓點水類型的,喜歡學習新技術,但是都不太深,後來,和一位老員工溝通了這件事,他告訴我一個很樸素的道理:

技術層出不窮,人的精力卻是有限的,語言隻是一種工具,重要的是程式設計思想。

繼續閱讀