做者:Greyjavascript
時間:2018-05-12html
原文地址: http://www.cnblogs.com/greyzeng/p/9029530.htmljava
本週我經歷了參加工做以來,最大的一次返工,這一週都是茶飯不思的感受,特此記錄一下,防止後續犯一樣的錯誤。git
有一個Web系統X,用戶能夠經過這個系統查看本身的待辦信息,而且能夠用於待辦的審批,還有一個咱們作的手機應用Y,Y系統須要支持查看X系統的待辦信息並完成審批操做。es6
剛拿到這個「粗粒度」需求的時候,我沒有進行足夠的需求分析,就開始「信心滿滿」梳理了一下本身的思路:github
第一步:web
X系統已有獲取待辦列表的接口,因此,獲取待辦列表這件事,我只須要調用X系統接口並轉換成Y系統須要的數據結構便可。ajax
第二步:spring
我當時的方案是經過X系統提供的一個後門URL(這個URL能夠直接打開某條待辦的詳情)而後用爬蟲抓取待辦詳情,詳情的抓取最初考慮的是用js找一堆頁面元素的值,由於詳情內容比較多,且分佈在多個iframe和tab頁面中,因此要模擬瀏覽器跳轉到相應的iframe或者tab中抓取相應的詳情,這也爲後續埋下了一個坑(由於要模擬瀏覽器操做,切換頁面等操做會致使抓取詳情時間會偏長,而Y系統獲取請求的時間只有10s,超過10s的就會顯示數據加載失敗了)。sql
第三步:
待辦詳情中有附件信息,咱們沒法經過抓取獲得詳細的附件URL,因此須要在詳情頁面中,獲取相應的附件的ID,而後在X的服務器中部署一個我寫的小程序,這個小程序能夠經過附件ID查詢X系統數據庫獲取附件的物理位置,而後拿到附件信息,併發請求到咱們的文檔轉換系統中,能夠將附件轉換成圖片,轉換成圖片最大地好處是能夠在移動端很快速的預覽。
第四步:
第二步中的後門URL包含了審批信息輸入框和審批按鈕, 我只須要找到審批意見輸入框,用js腳本填入審批意見,找到審批按鈕,模擬瀏覽器點擊審批按鈕行爲進行審批操做。稍微複雜一點地是要判斷點擊審批按鈕之後,是否須要選擇下一步地審批人,這一步也好解決,經過抓取詳情頁面中下拉選人框中的內容,就能夠把下一步須要選的審批人也抓取出來並告知Y系統下一步須要支持選人的操做。
梳理完之後本身的思路之後,當時我是這樣的感受,
而後就「信心滿滿」進行開發了。。。
待辦詳情的抓取時間很不穩定,大概十次有6次會超時(超過10s),咱們有一個抓取的小程序,採用的是Phantom JS,我就用這個小程序進行詳情的抓取,邏輯大概是:
面對超時問題,想到了另一個解決方案,經過發ajax請求,直接獲取詳情數據,Chrome控制檯下看了一下待辦詳情頁面請求,大部分入參均可以經過正則查找當前頁面來得到,這便減小了兩次切換頁面的操做,可是有幾個參數沒辦法在當前頁面獲取,仍是須要至少切換一個tab來獲取。
因此,解決辦法就變成了:
第二次嘗試的瓶頸在於,串行發請求,速度仍是有很大的限制,Js可否實現併發請求呢?說來慚愧,以前一直是作後端,用Java開發,連Js併發操做這件事,都不是特別清楚,因此就查了相關的資料,發現了Promise.all
將Ajax請求一個個封裝起來,諸如:
runAsync1()
runAsync2()
runAsync3()
等若干個這樣的方法,
而後經過Promise.all來併發執行這些請求:
Promise .all([runAsync1(), runAsync2(), runAsync3()]) .then(function(results){ console.log(results); });
用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來進行查詢,用法以下:
@Mapper public interface MyMapper { @Select("select x as y from xxx where xx=#{p}") List<Map<String,Object>> findByState(@Param("p") String p); }
這裏的
select x as y from xxx where xx=#{p}
就至關因而X系統原封不動的拿來的SQL語句,數據結構也來不及設計了,就用List<Map<String,Object>>
把!
改爲從數據庫拿數據之後,沒有了超時的問題了,從新測試了幾個流程,都正常了,終於能夠舒一口氣了,可是心情卻非常複雜。
充分理解需求,應該在開發以前充分地理解需求,細化需求,因爲需求理解不到位而返工開發的代價是巨大的。
在第三次嘗試中,有一個插曲,當時我面臨兩個方向的技術選擇,一個是使用本身相對不熟悉的JavaScript來作併發, 另外一個是當時本身相對熟悉的Java中的爬蟲抓取工具WebMagic,也能夠很好地實現併發操做。若是用WebMagic,或許併發和使用這塊,我會更加熟悉,之因此當時先選擇了JavaScript來作,是由於當時腦海中冒出了這樣的的想法:
本身的Js技術相對Java要弱一點,就要多鍛鍊一下,因此就一直再探索用JavaScript能夠有哪些優化的地方。畢竟本身的目標是但願能夠作一個全棧工程師。
我彷佛忘記了這是一個工做任務,徹底把這個當成了本身學習和鍛鍊的途徑,忽視了工做任務是有截至時間的。
這幾年,本身的學習方式大可能是走馬觀花類型的,喜歡學習新技術,可是都不太深,後來,和一位老員工溝通了這件事,他告訴我一個很樸素的道理:
技術層出不窮,人的精力倒是有限的,語言只是一種工具,重要的是編程思想。