故事的開篇 把時鐘撥回到9年前,那是2010年的10月份,李大胖入職了新公司,在公司本部呆了一個多月,就被髮往客戶單位進行駐場開發。 公司給客戶做的系統,需要不斷的二次開發和維護,所以直接去客戶單位比較利於工作的進行。 一個周五的下午,經理把我叫到辦公室,說到:“下周你就去客戶現場吧,我們有些同事在 ...
故事的開篇
把時鐘撥回到9年前,那是2010年的10月份,李大胖入職了新公司,在公司本部呆了一個多月,就被髮往客戶單位進行駐場開發。
公司給客戶做的系統,需要不斷的二次開發和維護,所以直接去客戶單位比較利於工作的進行。
一個周五的下午,經理把我叫到辦公室,說到:“下周你就去客戶現場吧,我們有些同事在那裡,那裡是有門禁的,需要有人接你才行”。
然後就把一個同事的手機號給了我,說到了就給他打電話,他會接你。就暫且把這位同事稱作“阿兵”吧。
此時剛剛畢業1年多點兒,不過好在客戶單位也不太遠。
什麼是甲方
周一的早上,我坐公交車來到了客戶單位。大門口雖有保全,不過可以隨意出入。我就進去來到了樞紐樓下麵,掏出手機撥打經理給我的號碼。
不一會下來一個人,就是阿兵,個頭不太高,大概1米7多一點兒,人很隨和。他帶著我刷了門禁,乘電梯來到了15樓。
周圍是一圈辦公室,中間是個很大的大廳。跟網吧似的,放著一排排的桌子、凳子和台式機。
裡面坐的大部分人都和我一樣,是別的公司的,來這裡為客戶服務的。我就坐到了阿兵的邊上,由於我剛來,用的還是客戶單位的電腦。
不一會阿兵說要帶我去見客戶,就是負責我們公司相關業務的那個對接人。估計公司已經提前告訴客戶了,今天要來一個新的開發。
我們來到了客戶的工位,也是這個大廳里,不過在另一個角落。客戶是個女的,30多歲,個子很矮。我們坐到她旁邊,聽她講著。
初到一個新環境,我習慣性地抬頭環顧四周,不料被客戶發現了,她直接懟了過來:“看什麼看,我是讓你來幹活的,還是瞎看的”。
我沒有吭聲,只是不敢再亂看了,心想客戶脾氣這麼暴。估計是她在講解,我沒有認真聽,她覺得是不尊重她吧。我當時是這樣認為的。
事後阿兵跟我說,人家是甲方,牛逼的很,我們只不過是給人家服務而已。以前我也只是知道在簽合同的時候有甲方乙方。
今天我算是領略了什麼是甲方,甲方就是爺。乙方TMD就是孫子,即使不是,也得給我裝成孫子。
事實證明我的理解沒錯,在接下來的日子里,我們一群1米7、8的血氣方剛的大老爺們被這個不到1米6的客戶無數次的批評,體無完膚,連頭都抬不起來。真的就像是灰太狼遇到了紅太郎,就差上平底鍋了。
PS:我沒有批判甲方的意思,只是我們運氣不好,遇到的客戶脾氣不太好而已。相信絕大多數甲方和乙方都成了好朋友,畢竟買賣不在友情在,抬頭不見低頭見。
客戶單位當時還是比較偏僻的,周圍沒有賣飯的,不過人家單位有食堂。中午阿兵請我在食堂吃了一頓飯,一般碼農都不善言談,也不太會跟別人客氣,所以當時我連一句謝謝都沒說。
在此我想對他說聲,“謝謝”,雖然已經遲到了9年。
找到原因了
沒有培訓,沒有文檔,阿兵大概給我講了講項目,又做了些必要的演示,然後我就開始自己慢慢熟悉、消化。
不久,來了一個需求,沒有需求文檔,是客戶口頭說的,說完就走了。阿兵就開始幹了。
如果沒有特別說明,就是一周時間開發完成並上線。因為周二、周四是例行上線日,我們項目組是周四上。
此後客戶沒再來找阿兵,阿兵也沒去找過客戶。
在周四的晚上,阿兵首先把新開發的需求打好包,然後停掉tomcat,把老的包備份出去,把新的包添加進來,然後啟動tomcat。接著自己測試一下,走一遍流程,發現沒有問題。最後給客戶發郵件,表明上線成功了。然後就回家了。
第二天剛上班不一會,客戶就氣衝衝的跑了過來,對著阿兵就吼:“你做的什麼東西呀,不是我要的啊,你要我說多少遍需求你才能明白呢”。
很顯然,阿兵沒有真正明白客戶想要的,做的東西不對。看來一場暴風驟雨是跑不掉了。
此後,這種戲碼經常性的不斷上演,我漸漸的似乎明白了。
我想沒有哪個人願意在一見面就給對方一頓痛批的。我想客戶在家裡也一定是一個賢妻良母、小鳥依人(這真的是我想的)。
為什麼她面對我們的時候就跟老虎似的。因為我們團隊在現場做的東西老是出問題(當然其它團隊也出問題),漸漸的就惡化了跟我們的關係。久而久之她對我們整個公司的所有團隊態度都不好。
於是就有了第一次見面時就給我來了個“下馬威”。
事實證明我想的是對的,因為後來我真的看到了客戶對我的微笑,這其實是很難得的。
我要改變嗎
醜媳婦兒早晚要見公婆。作為新手司機的我,終於要上路了。
客戶照例過來傳達一個口頭需求,然後就走了。感覺跟宣讀聖旨似的。然後我捋捋思緒,就開始做了。
在做的過程中,如果你仔細思考的話,會發現有很多問題。畢竟客戶都是做業務的,從業務到需求的轉化哪有那麼容易呀。
此時我該怎麼辦呢?也像阿兵那樣不考慮那麼多直接做嗎,還是選擇一個我認為最合理的方法去做呢?
不管選擇哪個,萬一最後做出來與客戶想要的又不一樣呢,豈不是又是一場暴風雨。這樣的話我和別人還有什麼區別呢?
思索再三,我不能這樣做。我要去找客戶問清楚,雖然是硬著頭皮去的。
來到客戶工位旁,“X老師,你好,你剛纔說的XX地方是不是可以這樣理解”,“是的,沒錯”,客戶說到。“那XX地方是不是可以那樣理解”,“不是那樣的,應該是這樣的”,客戶繼續說到。
就這樣一問一答,不一會功夫,我的所有疑問都解決了,道謝之後就回去繼續幹活。
其實我發現客戶並不是那麼難溝通,且溝通後做出來的東西,不管是好還是壞,至少和客戶的想法保持一致。
有時候開發時發現客戶的想法並不是最優解,我能想到更好的解決方案,此時就會去向客戶表明我的意見,有時客戶也會選擇聽我的。
慢慢地發現,客戶和我們團隊的關係緩和一些。客戶和我的關係一直都還可以,因為我從來了之後基本沒有犯過錯。
有時候需求並不是客戶直接提的,而是客戶的其它部門的同事提的,如果讓客戶再從中間倒一下嘴,不僅費時費力,而且容易出錯。此時我就說,你告訴我她在幾樓,工位是哪個,我直接去找她。
就這樣,我認識了一位14樓的姐姐,之所以叫姐姐是因為她人真的很好,後來在路上她看到我,特意降下車窗和我打招呼。
更大的挑戰
14樓的這位姐姐就稱她為“時姐”吧。起初去找時姐,是為了溝通和確認需求,這樣一來二去我們就漸漸地熟悉起來。
關係處的還不錯,因為我覺得她人很好,她覺得我也不錯。(此處省略一萬字)她的女兒都即將要上小學了。
有一次時姐把我叫下去,竟然不是談需求,而是告訴了我她的一個“大膽”的想法。
她有一項日常工作,就是把集團網站上的派給各個省的任務中和本省有關的任務都找出來,把這些網頁內容和其中的附件都倒騰到我們做的這個系統里,再派給和任務相關的科室主任去查閱,科室主任看到後,再派給具體員工去完成這個任務,這些任務通常還有最晚完成時間節點的限制。
一方面,這些工作就是複製/粘貼網頁內容,下載/上傳附件,非常機械無聊。二來呢,好多任務具有時效性,不能一天看一次,必須時時地刷刷集團網站,看有沒有新的任務。
目前這個工作都是她手動完成的,有時她需要提前下班去接孩子,就必須委托給其他人做這個事情,因為萬一漏掉緊急任務,整個人都會不好的。
她跟我說,這個事情能不能做成自動的?我明白她的意思,然後就說,我回去先試試吧,應該可以的。
這裡涉及到兩個技術問題:
一是要定時刷集團網站,找到指定頁面,獲取頁面內容,下載其中的附件。
二是想辦法把這些網頁內容和下載的附件,弄到我們的系統里。
先談談第二個問題,此時我對系統已經比較熟悉了,而且很早就知道一個工具叫做HttpWatch。在平時的開發測試中,都會使用這個工具查看當我在頁面上點了按鈕後,瀏覽器往伺服器端發送的數據到底是什麼樣子的。
因為經常看,所以對這個比較熟悉。當沒有附件時,預設使用application/x-www-form-urlencoded編碼body,表單欄位都是以key/value對的形式發送的。
當有附件時,必須以multipart/form-data編碼body,此時表單欄位和附件都是以分割線和回車換行來一部分一部分分開的。每部分都有欄位的類型、名字和具體內容,如果是文件的話,就是文件的內容。當然,沒有附件時,也可以使用這種方式。
後來上網搜索發現Apache HttpComponents可以以編程的方式發送http請求。我的初步想法就是拼湊模擬法。
瀏覽器往伺服器端發送什麼樣的數據,我使用代碼發送一模一樣的數據,理論上即使伺服器端認出來不是瀏覽器發送的,但因數據格式一樣,也能夠正常解析執行。
於是我使用代碼拼湊出來HttpWatch里看到的body格式的內容,並把它們寫入二進位文件里。然後使用HttpComponents設置好相同的Headers,並把這個二進位文件作為實體往伺服器端POST。
套用岳雲鵬的一句臺詞,我的天呢(再配上賤萌的表情),竟然成功了。
然後再來談談第一個問題。如何定時刷集團網站,複製網頁內容和下載附件。說來還真是巧合,接著往下看就知道了。
我們公司既有Java項目也有.NET項目。在客戶這邊有一種小項目叫業務探測。因為客戶有很多重要系統,要保證它們可用,在不可用時要及時發現並處理。
當時的做法就是定時刷頁面,模擬人工登陸,在失敗時發出告警。這個模擬就是用.NET做的,因為.NET是以控制項打天下的,在它的toolbox中就有瀏覽器控制項,把它拖到WinForm上,簡直跟瀏覽器差不多。
而且還可以使用C#代碼操作它,比如導航到某個頁面啦,獲取頁面元素啦,往輸入框里填值了,點擊某個按鈕了,非常之好用。
為什麼我會對這個這麼熟悉呢?因為我一開始就是學.NET的,只是現在是寫Java的,不過在不忙時,也用.NET搞過幾把業務探測。
這就給了我一個很明確的方向,在Java的世界中也一定有瀏覽器組件,而且可以使用Java語言來操作這個組件。可見多學點知識還是有好處的吧。
在網上一番搜索,終於找到了我想要的東西,它裡面有一個測試用的demo,是一個Swing寫的WinForm界面的瀏覽器,我大喜,直接用它了。
然後就使用Java代碼操作瀏覽器組件進行頁面導航,有一個問題是這個導航是非同步的,因網速不同,所以頁面完全載入好所花費的時間也不一樣。
理論上在頁面載入好後應該有一個回調,來告知頁面已經OK了,可以去裡面尋找html元素了,可惜我沒找到這個回調。
當時就採取了一個笨方法,就是每次導航後等待5秒。然後就認為頁面已經OK了,可以進行下一步了。
定位到頁面元素後,直接使用innerHTML獲取網頁內容。定位到附件標簽後,獲取下載鏈接,再使用HttpComponents下載附件。
至此,所有的技術點都已經搞定了,然後就整體整合起來,也是OK的。有點小興奮。
這一切都是在工作不忙時弄的,前前後後大概花了不到2個月。
然後就去找時姐,因為還有2個業務問題需要確定:
一是怎麼判斷任務和本省有關
二是怎麼判斷這個任務該派給哪個科室的領導
我跟時姐說,程式只能機械的模擬,它什麼都不懂。
時姐說任務里有時會帶省份名稱,但有時不帶。為了保證不漏掉內容,那就不判斷了,全部任務都弄下來。第一個問題解決了。
第二個問題就更簡單了,程式無論如何都不可能理解網頁里的內容的,更不可能知道派給誰。時姐說那就每個科室都派一遍。
跟時姐這樣的人溝通就是爽快,寧可錯殺一千,絕不放過一個。這也是一種解決方案呀。
至此,業務問題也全部OK了。接下來就是部署了。
這是一個以個人名義做得東西,而且只能部署到windows系統上,就找了一個空閑的機器部署上了。
雖然是以個人名義免費給客戶做的,但是如果真的出了問題,還是要承擔部分責任的。因為甲方雖然在我們面前很牛逼,但是在集團面前她們也是被考核對象,哈哈。
通過網上搜索,我把這個Java桌面程式打包成了一個exe文件,然後配置到windows的定時任務里。
程式會在早上上班後開始運行,每小時執行一次,在晚上下班後自動退出。如果中途程式無故退出時,定時任務會把它再起起來。
為了更保險起見,還會把每次執行結果自動發郵件給時姐和我。
後來這個程式運行了很長一段時間,從來沒出過問題。
當時之所以答應時姐,是因為一方面技術理論上可行,二是它能把一個人解放出來,去從事更有意義的事情。
也許搞編程的都有一種情懷吧,能讓電腦乾的重覆無聊的工作,決不讓人乾。
這下可火了,時姐每次見到客戶都一個勁的誇我,我終於看到了客戶對我的微笑了。
客戶仿佛對我們這個公司的印象都變好了。
終究被認可
後來隨著項目組的調整,客戶對原來的組長不太滿意,正好他也不想幹了,於是客戶就像我們公司推薦讓我當開發組長。
客戶組團對我就行了面談,其中一個人說到,如何提高軟體質量,即上線時不要老出問題。她說需要一個專門的測試人員進行測試。因為我們那時沒有測試人員,都是開發自己測自己的。
我當時說,一個工廠生產出來的產品好壞,不取決於質檢部門,而是由生產車間決定的。(不過後來還是招了個測試)
一個項目一開始測出來的bug越多,測了幾輪後沒有bug了,並不是說明bug被測完了,而是剩下很多陰性的bug不容被測出來了而已。
就好比一個大池塘,第一網撈出來的魚越多,說明池塘里的魚越多,隨著你的捕撈,魚只會變少,但不會沒有,除非把水抽乾。
就這樣,不管是鬼使神差的,還是命中註定的,我成了開發組長。
除此之外,我還收到了甲方給我頒發的優秀服務合作標兵證書和1000元購物卡,還有我們公司給我的優秀員工證書和1000元現金。
證書我就不曬了吧。當然卡和錢當時就被我媳婦兒弄跑了。
那麼,我能當好這個開發組長嗎,請關註後續講解。
如果覺得好看,請點個贊吧,或留下你的精彩評論。
(完)
更多精彩故事請關註“編程新說”
用獨特的視角說技術