日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

如何提高程序员的生产率 (2)

發布時間:2023/12/20 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何提高程序员的生产率 (2) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

版權聲明:本文由韓偉原創文章,轉載請注明出處:?
文章原文鏈接:https://www.qcloud.com/community/article/252

來源:騰云閣?https://www.qcloud.com/community

?

接上篇?如何提高程序員的生產率 (1)

三. 開發過程

溝通

軟件通常都需要經過很多人和很多次的溝通才能生產出來,但是溝通本身又往往會影響軟件的開發速度。這是一段很矛盾的關系。好的溝通方法能降低開發中因為信息不透明導致的開發資源浪費,而又盡量減少溝通所占用的精力。

1. 需求溝通
在任何一個軟件產品中,如何應對需求的變更,都是至關重要的。需求一直是軟件工作得以成功或者失敗的最重要因素。軟件開發中很多技術和方法都是圍繞著需求來設計的。

需求的溝通是需求工作的第一個環節。首先溝通的對象必須是經過挑選的,以免添加不必要的需求混亂。最佳的需求溝通是和用戶或者用戶代表。但是他們往往他們缺乏必要的計算機知識。而程序員卻很少有豐富的需求領域的知識。這個鴻溝需要雙方共同去彌補,最重要的做法是,不要光靠口說。

程序員應該認真研究需求領域的知識,仔細查看涉及的單據、原型產品、現有工作流程等,而且必須用筆記錄下來,之后再去整理問題,逐條咨詢用戶。在仔細了解情況之前,不宜開始設計整體程序結構。

當你有一定了解之后,程序員就可以動手開發一個快速的原型,如果沒有足夠資源,一組界面圖也是很好的。以程序的外觀來幫助用戶來協助設計,是最有力的需求溝通方式之一。不斷的在用戶的幫助下完善這些界面圖,標識上那些可能需要的數據和流程,然后完善,然后再繼續找用戶確認。這個過程在前期可能會相當枯燥,因為那些溝通用的原型也許一點都不會給后續的開發帶來重用。但是能明確需求,卻是對開發最大幫組。

2. 需求評審
在需求基本有一個思路之后,需要開始準備需求評審。首先說說評審的材料,一般會是《用例圖》,《領域建模的模型》,用例規約,一些《非功能需求點列表》,甚至軟件的一些經過用戶確認的使用流程和使用界面。

評審的過程其實遠沒有溝通的過程重要。這個環節主要是給大家一個明確的開端:現在我們開始做系統設計了。作為在一些公司內部,需求評審是否得到通過還是產品是否能正式開始立項的一個流程。

對于評審,很多時候會認為是,提交評審者來寫報告,然后向一堆專家或者上級來介紹,最后他們提出問題,幸運的話就蓋章認可。但我認為評審不應該是這樣的。因為如果上級和專家沒有參與項目需求的溝通,他們對項目的了解是片面的,靠一些文檔和口頭介紹,一定會以“挑毛病”的姿態出現。而項目本身是否真的可行,卻不負擔真正的責任。

因此我認為需求評審應該是項目發起者,也就是有權拍板是不是做這個項目的人,來主持這個評審會議,所有的材料由他宣講,疑問由他回答。而其他的與會者包括專家團和可能的開發團隊,紛紛向他提出問題,以確認真正的可行性。最后主持者在搜集了眾多意見后,篩選出有意義的意見,改善需求評審的材料,最后拍板是否完成需求評審。這種流程,無疑會要求公司的權力下放,而事實上,如果不是下放,又或者不是老板親自主持,很多項目最后就輸在了起跑線上。

3. 合作溝通
程序員的溝通講求的是效率,準確是最重要的要素,如果無法表達“準確”,那就只是在創作,而非溝通。對于需要高度注意力的工作——開發軟件來說,群體創作的效率實在不夠高。因此提高溝通的“準確”程度是至關重要的效率因數。

開發中的溝通有很多種,其中最重要的一種是需求溝通。特別是作為技術人員,和策劃、美術的溝通最多。這里需要重視的就是,和非技術人員溝通,快速原型:如假的界面圖或者手畫稿,填寫了假數據的表格等等,是很重要的溝通手段。很多時候我都會要求把這些溝通過程中的手畫稿掃描保留下來作為設計文檔的一部分。

另外一種溝通是程序員之間的。我一直認為程序員之間最好的溝通就是“不用溝通”。客戶端和服務端之間調整協議,最好的方法是直接兩個IDE聯調。關于工作任務的接口,最好是定義出接口代碼,并且有單元測試針對接口代碼做處理。當然拉,對于這些接口的設計,還是需要當面溝通的。

最后要說說會議。我認為溝通不應該打斷開發。不管是5分鐘還是1個小時,會議都是一種打斷。而很多會議需要開前準備很多東西,大家試圖用這種方法減少會議的時間,但實際上卻占用了同樣多的時間。我們應該關注如何減少會議,以及減少會議對開發的打斷。在午餐的時候開會,我認為是一個比較好的方式,這種打斷是天然的,不會產生額外的打斷。而且與會者通常不會睡著。午餐時的討論氣氛也會比較好,比起一本正經的會議要活躍的多。

4. 測試溝通
程序員和測試人員之間的溝通一定是密切與頻繁的,雖然我們有JIRA、BugZilla之類的BUG跟蹤系統,但是往往很多問題還是要通過口頭的溝通來解決,我認為和測試人員的溝通關鍵是要分出優先級,對于“可重現”的BUG應該優先溝通,因為可以很快解決。而那些偶現的問題,可能溝通中一大半都會是猜測,其實可以先放后,這不表示那些問題不重要,而是應該在確定能解決的問題都先解決掉,這些時間內測試人員也可以努力把偶現變成必現。

測試溝通的內容中,對于“名詞”一定要明確,因為我們會有很多個環境,必須要讓每個概念有個清晰的表達方法。我們經常會在“測試”這個詞上犯糊涂,比如“測試版”到底是哪個版本,“測試網”又是哪個網?甚至“測試機”是個PC還是個手機?這些都必須明確下來。比如用alpha網,beta網就清晰的多。

設計

1. 設計意見搜集
負責設計方案的人必須負責搜集設計意見。我不贊成方案由下屬設計,意見由下屬向上級搜集。我認為方案應該由上級負責,而意見向下屬爭取。如果有一個上級并不負責設計方案,那么他也不應該有權力去“評審”這個方案。這樣做看起來風險很大,因為我們很多的上級并不負責具體的“設計”工作,但是對比起上級提供一些不知道該怎么辦的“指示”,而非要加到方案中去的情況,可能危害要少的多。

一般來說我們認為上級會比下屬的經驗更豐富,如果“無權”評審方案,就必須換一種工作方式:要不自己來做設計,要不采用建議的方式說服下屬——這樣做的好處是能讓上級對自己的概念講解的更清晰、更細致。否則不足以說服下屬。

2. 設計評審
設計評審的形式往往是一個結論是yes or no的會議。但是實際上要用好這個溝通工具,卻不能怎么簡單。首先,方案的評審提交者應該是最后決定者,當然應該在一個機制的監督下決定。這個決定就是,對于與會者提出的問題,包括提交者提出的問題,都要有明確的答案。

與會者可能會與提交者就一些問題有分歧,但提交者會有最終決定權。這個機制聽起來很荒謬,好像自己指定法律自己又可以修改。但是,實際的開發上,如果方案和執行者并不統一,最后執行者還是會有辦法“規避”一些決策。這里也涉及一個重要的問題,就是要把權力給有能力承擔他的人。不能想著只是讓某些自己還不放心的人去做方案,然后試圖在評審的時候“把關”了事。

最后把關固然比不把關要好,但是把關要避免成為扯皮或者陽奉陰違,就必須要權事統一。真正的把技術的知識灌輸到底,這樣會耗費指導者較多的精力,因為需要在提交評審前更多的溝通。當然了,雖然方案又提交者決策,但是,作為業績考核和技能評定,上級還是可以針對這些設計方案來給出專業評判意見。對于非常頑固者,實際上也有一個“秋后算賬”的“威懾”。

設計方案,也是開發者的一個重要輸出,代表了開發者的技術水平和工作績效。

對于設計方案的組成部分,下面架構設計章節會有更多的討論。

測試

1. 單元測試
單元測試的好處是讓你在設計代碼之前,就要考慮別人如何去使用你的代碼。代碼的可讀性是建立在讀者的前提上的,如果強迫第一個讀者和使用者就是作者本人,那么在設計API和接口部分,就會考慮更少的耦合。因為強耦合會讓單元測試非常難寫。IDE和單元測試結合是一個很好的實踐,雖然并不能節省多少輸入的代碼量,但起碼會給與一個正式的環境。

每個細節組成部分的正確性測試,會增強你重構代碼的信心。對于單元測試,我認為最少應該覆蓋所有正確的路徑,以及重點防御的錯誤路徑。對于覆蓋了這些重點關注的地方之后,放開手重構代碼就很方便了。雖然很多語言能通過編譯就已經消滅了很多的BUG,但是起碼還是要運行一下。而單元測試可以分區域的運行完成的代碼,避免的整個系統一起運行,突然爆發一長隊的錯誤,讓DEBUG工作無從入手。

單元測試應該是代碼的一部分,和源代碼一起存放。自動構建時也應該進行檢查輸出結果。通常提交代碼的時候都會自動運行單元測試,但是當版本樹有分支合并的時候,單元測試尤為重要,而最重要的是在分支上建立的單元測試,這些測試會大大加強系統的穩定性,因為檢驗了“合并”功能產生的代碼——這些代碼是最容易出錯的。

2. 系統測試
系統測試的自動化程度決定了其重要性。系統測試一定要先辦法找到測試的“切入點”,如對WEB系統測試,使用HTTP請求列表作為測試發起事件。對于WINDOWS測試,則使用窗口消息。對于服務器,使用協議包。一定要想辦法把手工操作“記錄”成可編程控制的操作。第二個重點就是要有辦法用程序鑒別測試目標的輸出,這里可能會用到正則表達式,詞法分析,圖形辨認等,但是如果一個好的系統設計,在考慮到測試時候,應該設計出盡量簡單的測試輸出點數據。如一些結構化網絡數據,或者客戶端數據中的模型數據等。

系統測試的環境自動化部署是關鍵,其中測試數據還原也很重要。一般系統測試需要反復執行——每次發版本都要。而測試結果很多和數據結果有關,因此一定要有辦法把系統的數據(數據庫內容)還原成每次測試的初始狀態。這個在建立系統測試的環境的時候就應該考慮,并且做成每次測試執行前都自動還原數據,否則最后的“斷言”測試很可能會失敗。

3. 壓力測試
我們必須要做壓力測試。因為我們要提供有限服務。服務器或者客戶端都應該對系統的最大能力值有一個設定,然后通過壓力測試獲得最可靠的數據,用以設定這個值。這樣能保證程序在合理環境下正常運行。
壓力測試可以通過搜集、復制產生數據。比如服務器可以記錄網絡請求包,然后按會話記錄成一個個隊列,最后通過并發一起回訪,就可以模擬多人同時的情況。如果還不夠壓力,可以復制隊列,然后修改一些互斥數據(如用戶ID),產生更大的并發壓力。這種測試往往能很真實的反應情況,缺點是必須要搜集一定的用戶操作。但是我覺得公司一般的QA的操作就是很好的復制源。

壓力測試如果用自己構建的壓力數據,需要注意的事項:密度、順序、覆蓋率。有時候需要自己構造壓力數據,我認為最少應該有幾個可輸入的調控相:每秒并發發起多少請求,每個請求的間隔時間;每個請求的順序是否按預定順序排列好(因為有的操作是需要先后次序的),請求包是否覆蓋了系統的所有處理邏輯,而覆蓋的密度比例是否和真實的環境大體類似。如各種協議格式的包,是否按外網的比例來產生。

壓力測試必須要注意專用環境:帶寬、磁盤、硬件、測試數據還原。高速的局域網,最好和辦公網分開,否則會影響工作。磁盤要清空足夠大,否則可能會讓日志把磁盤填滿。要用專用的測試硬件,以免造成別的工作數據的破壞——同時也提供了性能指標的硬件基準,這個尤其重要。壓測的數據包數量巨大,一定會產生巨大的持久性數據,為了可以重復操作,這些數據一定要能自動還原。同時也是保證自動化重復壓力測試的需要。

編寫

1. 需求分析
KISS:保持簡單。需求之所以復雜,是因為人的思想難以界定,充滿了是和否的中間地帶。所以第一原則是:只承認確定是的需求。未來的需求暫時不考慮,在第一批需求完成后,真實的第二批需求就會確定下來。人類不可能未卜先知,所以不要妄想一開始就能準確的預測需求,只需要把確定的需求理解清楚,就打下了基礎。以學習的心態去了解需求,不要被固定的合同束縛,才真正能跨過需求的第一關。軟件領域最大的、永恒的挑戰,正是需求變更!

面向對象分析:尋求領域概念。計算機把世界抽象為0和1的序列,這種方式也影響了程序員。但是世界是復雜而多變的。固定的數據建模已經被證明了無法很好的應對需求變更,所以真正的方法應該是去先認識世界,對于業務領域中的概念做學習和界定,然后用面向對象的方法去框起來。這樣“對象”和現實世界與0、1之間,就搭起了一個人類可以理解的橋梁。因此我們的需求應該從領域模型出發,使用業務領域的名詞作為系統中對象的名詞,盡量用對象去“描述”這個領域中的概念,而不是急著去完成一個個概念供使用者交互的“流程”。

需求分析有很多工具,如領域建模。UML中的用例圖和用例規約。針對非功能需求的“場景-決策”表格。還有著名的魯棒圖,可以轉變成UML的模塊圖。這些都是值得學習的需求分析工具。而且不會太花費時間。

2. 代碼風格
這個方面《編寫可讀性代碼的藝術(ARC)》里面說的已經很詳細。只需要認真的按照里面所說的去做就可以了。

另外有一些慣例,我覺得明確一點的好:

  • 關于英文縮寫命名,為了簡單,一般只取前三個非元音字母為好,而且單詞長度超過5個字母的才縮寫。
  • 對于C++這類兼容過程式的語言,如果是過程式的變量或函數,應該采用下劃線連接小寫單詞,如arg_num, get_file_name(),如果是和類與對象相關的,包括屬性、方法,就采用JAVA風格的命名,如argNum,?getFileName()。

3. 代碼重用
理論上代碼重用這是個大話題,不應該放在這么小的位置來說。但是實際上軟件開發很多地方都涉及重用。所以這里只提一些我認為最重要的:能下載到的代碼絕不開發。——事實上很多程序員都以重新發明輪子為榮,并且都認為別人的輪子不好用,比如鄙視STL的C程序員比比皆是。我認為老板給你的工資很多時候并不包括重新發明輪子,不管你覺得怎樣,學會使用已有的輪子都是一個程序的義務。否則等于浪費老板的投資,對于自己來說雖然好像技術長進了,但是整個項目都被你脫了后腿。與其你自己去寫STL,不如去認真讀一讀STL源碼,掌握它的內容,然后教更多的程序員去用他。否則我懷疑最后你只能去寫匯編了,那就隨便你了。

代碼重用往往和機器性能有一定沖突,但是在我看來,很少項目因為性能差那么一點點而掛掉。但是因為代碼開發效率太低,跟不上項目需求變化而掛掉的項目多的多。所以那些只以性能作為技術水平標桿的程序員,某些時候是項目的毒瘤!

4. 設計范式
過程式:C語言
結構化編程當中,最重要的設計方法是:自頂而下,逐步細化。無論你是否在寫過程式范式的代碼,這個方法都應該遵守,否則一定會出現劃分粒度不一,難以重用的代碼塊。大部分的巨大函數體都是忽略這個原則造成的。

一般來說C語言會要求對一個內存進行操作,并且反應執行結果在其之上。所以通常都會有一個類似g_Env之類的全局變量,用來存放多個過程需要的數據。為了避免多個函數需要反復的通過不同的輸入參數和返回值來“串接”調用,通常都會設計成一起去修改 g_Env變量。

同時也會有一個g_Cfg的全局變量充當配置文件。面向過程的代碼則很少使用全局變量作為“操作臺”來處理數據,因為都被封裝到對象里面了。

C語言的回調模式一般通過函數指針來實現,這個幾乎是做框架代碼的最好用的方法。而面向對象則采用多態來取代函數指針,會更安全一些。

對于函數的返回值,一般來說不會用來真正的“返回”某些數據,而是返回的是處理的結果是否正常\異常。而處理結果的數據往往通過輸入參數(指針)來得到,這個是和面向對象代碼很大的區別。面向對象的語言一般支持異常,取代了返回值的“錯誤報告”功能,而返回值則真正是一個處理的結果。這樣減少了輸入參數,會讓API更容易使用,符合理解習慣,也更不容易出錯。

總體來說,注意抽象好函數的層次,使用統一的,盡量少一點的全局變量,使用函數指針實現回調,使用返回值作為函數的錯誤報告,使用輸入參數,就是過程式C語言的主要特點。

OO:設計模式
對于封裝、多態、繼承的玩法,最后演變成GOF23種設計模式。說到底都是為了實現幾個主要的原則,其中最關鍵的就是“開閉原則”。這方面的書籍也是汗牛充棟,特別需要關注的是《重構:改善既有代碼的設計》。

面向對象編程方式是現在最利用適應需求變化的一種技術。包括泛型這種靜態化的對象技術。所以無論什么原因,都應該掌握一定的這方面知識。

面向對象設計范式的核心點是去描述現實世界的概念,而非用算法和數據去模擬這個世界的運行。因為關注點在概念這種名詞特征上,所以可以先初略后精致的逐步細化設計,正好符合需求變化的特征。

動態模式:JS/PHP/PYTHON……
動態類型語言以其極致快速的開發效率,容易掌握的語法而聞名。其中最能提高效率的是動態數據類型。減少了大量的聲明、定義和局限的代碼。甚至減少了大量的數據結構的使用。如PHP里面所有的數組都是哈希表,而JS/PYTHON里面的Object就是哈希表。實際上AS3.0也是有類似的特性。更好的利用這些語法糖和數據類型是提高開發效率的關鍵。所以我也反對在這類語言里面自己重新包裝一套類似C語言的數據結構或者容器類庫,實在是沒必要。

動態類型語言另外一個特點是腳本化解釋運行,不需要維護堆棧,也不需要考慮編譯的定義。甚至還有交互式終端一行行的去命令式運行代碼。把盡量多的業務邏輯的處理細節“過程”用動態類型語言(腳本)來執行,是提高開發效率的重要手段。如果你比較一下用C語言編寫CGI和PHP比較一下,你就知道效率相差有多少了。

特定領域:SQL/SHELL
SQL這類語言和一般的語言有比較大的設計差別,他更多的設計為“表示”而非“命令,所以需要另外一種思考方式。而這類語言因為和領域結合很緊,所以是強大的領域工具,包括SHELL和AWK這種腳本語言,具備別的語言非常費勁才能實現的功能。在這些領域,盡量使用這些語言會有事半功倍的功效。

SQL中的函數和存儲過程,是強大的工具,有時候整個統計系統都可以直接在數據庫里面運行。而很多運維的系統工具,用shell來實現則會簡單高效,因為需要操作的功能是操作系統本身。

函數式:強大的數學表達力
Lisp,schema,erlang這些函數式語言,采用鏈表來描述一切,只需要棧而無需堆,用遞歸代替循環,這些都很符合多核并行運行的要求,而且還能很方便的中斷和恢復程序運行。在業務需求變化較少的,而計算任務比較多的場景,是一種非常強悍的編程工具。對此我了解不是很多,但是很希望有機會能用函數式語言做一個東西看看。

構建-集成-部署-測試

版本管理-構建腳本-自動構建-構建包管理:
所有的源代碼都必須進入版本管理;所有的構建、部署、測試腳本也需要進入版本管理,所有的一切都應該進入版本管理。一個構建系統的運行,應該是可以完全從版本管理服務器上重建一切的。

Hudson是一個很好的自動構建服務器,但是構建腳本你還是需要自己去寫。確保你的腳本可以從零開始構建,并且在所有你可能碰到的平臺上正常構建,如32位和64位系統。

構建出來的軟件包,應該讓hudson這類系統自動發布給所有相關的人,而且可以很方便的通過網絡獲取到,如HTTP或者SVN。并且需要保留多個歷史版本以備回滾。

部署腳本-部署環境-自動部署
部署腳本往往是用動態語言寫成,還會帶有數據庫操作等復雜的內容,因此必須也納入版本管理。部署環境應該是足夠安全而且和生產環境有足夠快速的網絡連接的。有了這些保障,才最后有自動部署的可能性。最好就是有一個部署服務器是和生產環境和辦公網絡,都屬于內網(局域網)連接的。簡單的自動部署工具必須要運維人員能掌握,并且取消開發人員的使用權限,避免開發人員直接修改線上服務產生的故障。

各類測試-自動測試-結果報告
代碼提交前應該運行完成單元測試,代碼在自動構建以及自動部署后,應該自動運行一定的系統測試腳本,結果放置到構建報告中。

一般來說,測試環境有幾種:開發環境、內測環境、外測環境、運營環境。

在開發環境應該是單元測試的運行環境。內測環境則應該是在自動部署后的其中一個環境,用以和產品人員溝通和驗證基本功能。外測環境應該和運營環境盡量一致,自動部署后,所有的測試失敗和人員手工測試缺陷,都應該視之為BUG進入跟蹤系統。而且外測環境應該是運維人員的工作范圍,不應該讓開發人員上去搗鼓。經過了這三層的測試環境,不管是代碼功能還是部署設置,應該都能自動化的在運營環境上可靠的運行了。

重構

兩頂帽子:加功能、改結構
關于重構有很多經典的書籍可以參考,比如《重構:改善既有代碼的設計》《重構與模式》。但其中很重要的一點,就是重構的時候禁止添加新的特性,因為會讓代碼在修改的時候陷入復雜的“連鎖”修改,從而讓重構困難增加。同時如果你修改了特性,也需要新的單元測試來保障重構的正確性,這些都是自己攪合自己的做法。而在增加特性的時候最好也不要重構,因為你在努力通過測試的時候,也是在整理和驗證需求。只有需求確定了,重構的目標才會清晰。

單元測試的重要性
重構的一個最大的困難,就是怕改的代碼太多,從而出現BUG。但是如果你有一個覆蓋率很高的單元測試集合,你就可以比較放心的去修改代碼,因為一旦出錯你立刻就能知道。當然有很多時候單元測試并非萬能,有些情況單元測試確實無法覆蓋,或者架設測試本身比較復雜。所以說重構還是一個比較高風險的動作。測試的工作本身是重構成功的最重要保障。

明確重構目標
很多時候重構起源于某些需求難以加入現有系統,但是如果只以這個作為重構目標,往往結果并非完全讓人滿意。實際上重構的目標應該是一個對于需求變更的總結以及前瞻。某些時候是以實現某種設計模式作為重構的目標。而選取的模式就是對于需求分析的結果。重構中目標的選取是至關重要的,這個需要對業務和技術有深入的理解,從另外一個角度看,重構目標和一開始的設計工作是同等的工作。所以說軟件開發的“架構設計”實際上是持續在進行的。

加班

加班的原因:學習、體力活
程序員的加班司空見慣,究其原因,有兩種,一種是不知道如何實現,另外一種是工作量大。

對于第一種情況,有些人會寫一堆代碼然后調試,發現不對又改。而我建議是應該把“不確定”的部分,設計一些代碼片段功能(單元),然后使用單元測試作為驗證,通過逐步掌握這些功能,最后形成可重用的代碼。這會是最節省時間的方法。

對于第二種情況,應該多考慮設計一些工具。比如使用一些腳本語言來代替一些數據的體力活,嘗試抽取可重用代碼來簡化邏輯。做這些可能一開始會比較費時間,但是長期來看,卻是可以節省下大量的加班時間。

實際每個程序員都知道生命寶貴,并不會有意的拖延工期,除非覺得這個工作實在是不值得去做。所以因為進度原因導致的強制加班,最后都會被“減班”還回來。損失比不加班還要大。《人件》里對于這個有詳細的論述,我也不去重復了。

如果是自愿性加班,本節會有用。如果是被迫性加班,實際上是無論如何不會增加整體的開發效率。所以如果真的要用加班這招,最重要的是變“被迫”為“自愿”。

如果作為團隊領導者,你看到整個團隊已經能在每天6小時內高效的工作,再強迫加班最后只能是降低開發速度。原因不再細速,可以參考《人件》。因此,如何讓團隊加班的方法,應該改成如何讓團隊不用加班的思考。改進開發工具,提高開發技術,加強團隊建設,這些都是有效的方法,唯一需要避免的就是如何“強迫”團隊加班。

避免加班的方法:思考設計、學習提高工作效率的方法、在上班時間內加班
根據我的經驗,如果一個程序員一天有6小時都高度注意力的做開發,實際上開發效率已經可以達到很高,而很多一天工作12小時的程序員,其高度注意力時間往往只有4個小時。所以不加班完全是可能的,除去別的因數,對于個人來說,避免自己玩死自己是最用的知識。在動手之前先仔細考慮清楚細節,可以避免后期邏輯BUG的折磨,這種BUG是最難調試的。而學習各種工具以及關注代碼在提高開發效率上的知識,則是另外一個重要的手段。因此再次吐槽那些不重視開發效率的程序員,你們輕視面向對象,輕視軟件工程知識,輕視那些對程序性能無關的知識,最后的苦果就是——一輩子加班!

程序員的狀態起伏

【設計-編碼-調試-總結】的循環
程序員在開發程序的過程中,往往會經歷以上幾個階段,在編碼階段是狀態的高峰,調試階段開始陷入痛苦,很多時候會跳過總結。整個循環完成后,則是疲憊不堪,注意力無法集中。因此我們可以注意幾個重要的環節,減輕這些壓力。

首先設計階段如果能盡快熱身,直接更專注的深入細節,則會避免無休止的修改方案,對于開發的指導也會更明確。而編碼環節采用更多的工具和技巧減少體力和腦力的消耗。如果設計階段和編碼階段的工作能關注代碼可讀性和結構,最后的調試往往也不會非常困難,然后為了獎勵一下自己,可以寫一點總結。

打破循環造成的心理影響
如果在每個階段中能盡量多的融入下一個階段的工作,同樣也可以起到降低壓力的作用。比如在設計階段就把很多重要的代碼命名工作做了,在編碼的時候就順手解決所有的語法錯誤,調試階段的測試用例就可以用來作為工作匯報的材料。

避免疲勞戰術的方案:縮小循環體
在開發的循環中,每個階段越長,最后的疲勞就會越大,而每個過程越短,則越容易被接受。所以盡量在設計階段劃分的細致一些,可以明顯的降低后續的工作壓力。縮小開發流程也是敏捷開發模式的重要觀點。這對需求分析、代碼結構、測試技巧都有很高的要求。重視這些知識,就會明顯的降低工作壓力。

四. 架構設計

邏輯架構

邏輯架構主要是為了明確需求而做的設計。針對需求以及需求變化作為架構目標。因此邏輯架構在架構設計中,是對于提高程序員生存率最至關重要的一個設計。采用合理的邏輯架構,將會大大降低需求變更對開發的延遲作用。邏輯架構最直接指導代碼中互相耦合的情況,仔細設計好耦合的規則,會讓后續開發事半功倍。

邏輯架構的經典模式有《POSA》中指出的幾種,其中以分層和微核模式最為常用。MVC和管道過濾器模式則在特定系統中是最優模式。后續基于分布系統的SoA等架構模式,則多是建立在分層的基礎上。分層模式可以按需求關注點來劃分層次,因此可以安排不同經驗水平的程序員分別承擔。微核模式則直接按具體功能劃分代碼,適合水平相差不大的團隊進行功能的并行開發,因為可以單獨測試。

不管何種邏輯架構,都是把功能-代碼劃分成多個不同的部分。這些部分通過一定的規則互相耦合。這提供了最好的工作量劃分依據,以及互相之間的接口定義。由于存在接口定義,將來人員流動的時候,也可以根據接口來理解代碼模塊的邏輯。良好的工作劃分,能極大的降低程序員之間的低效溝通,使得工作能被多個人同時推進,而工作能被同時推進,則是軟件項目能利用好人力資源最直接原因。

需要指出的是,很多使用非面向對象語言的項目,特別是C語言項目,非常蔑視進行邏輯架構設計,因為所謂結構化編程其實約束很少,而大家往往直接忽略掉。這是非常大的問題,導致一些復雜的“過程”最后完全無法維護。有很多項目到最后不管如何增加人手,都無法提高開發速度,就是因為實際那些代碼無法利用更多的人力,反而增加了更多的溝通成本,架構直接降低了開發效率——往進度落后的項目增加人手,只會讓進度更見落后。

運行架構

運行架構主要是為了解決運行時的質量需求,主要分為性能需求和可用性需求。系統的性能需求除了在代碼內部通過算法來提高,往往還要采用緩存和并行的方式來擴展。這就涉及到程序的運行時設計,如數據處理流,多進程間通訊,數據的多種格式轉化。對于可用性,實際上也是通過并行熱備的方法來實現,因此運行時的各種控制命令、地址、消息數據流也是運行架構需要考慮的。

運行架構一旦確定,等于大部分的“實現”代碼確定了下來,設計一個有足夠擴展性和可用性的運行架構,可以減少后期為了擴展性能或提供可用性做更多的代碼。而且也降低了系統在運行期對開發工作的干擾——正在運行系統出了問題,往往是在節假日或休息時間,都會迫使程序員回公司或者上線維護,極大的增加了開發人員的疲勞,同樣會影響項目的進度。因此一開始就考慮可用性和性能擴展問題,并且實際的用代碼去實現好,絕對是一個未雨綢繆的好方法。明智的項目經理會愿意在項目前期花多一些資源在這種“非功能性”方面的開發,從而得到一支士氣水平穩定的開發團隊。

通常運行架構需要至少設計一個可以水平擴展的接入層或邏輯層,以便通過增加服務器來提高性能擴展。因此也需要預先設計負載均衡的系統,如果是WEB系統,用DNS輪訓是最簡單方便的,如果是游戲類用戶間交互比較強的,設計一個“目錄服務器”用來提供客戶接入地址是最少需要做的。

可用性架構中,最少要為邏輯服務器和數據庫(持久層)服務器設計至少一個熱備服務器,在機器斷電或者機房斷網的情況下,可以經過程序自己的檢測機制,自動跳轉到備份服務器上處理。一般數據庫服務器mysql采用master-slave用來備用,而邏輯服務器則可以使用目錄服務器來指定備份服務器地址。當然了,如果目錄服務器也需要熱備的話,則需要另外一些代碼支持,如客戶端本身就會去多次嘗試不同的目錄服務器。

一般有“架構設計”的系統都會有運行架構的設計,所以我并不認為需要如何強調其必要性,反而需要強調的是,系統架構設計,遠遠不止是運行架構的設計。

開發架構

開發架構一般用于滿足開發時質量需求,和邏輯架構有密切的關系。開發架構定義了源代碼、二進制和發布包的文件、路徑、負責人的劃分和依賴關系。一個按照固定開發架構設計的系統,能方便的開發出持續集成的各種工具。

開發架構一般的主要呈現形式為SVN目錄構造方式,或者在makefile、IDE的項目設置文件中。一個軟件通常分成多個不同的“系統”或者“項目”。很多如Eclipse需要每個項目只存在一個執行入口main(),所以開發架構在這種情況下同時也收到運行時架構的進程設計限制。

一般來說功能相對獨立的代碼會成為一個“模塊”或者“系統”(項目),通過提供程序鏈接接口,如DLL,.a和.h文件,JAR文件,或者SWF文件來提供。這個粒度的劃分有多種標準,如按功能的,按開發者的。但是有一個通用的準則,就是如果已經設計的不同“模塊”中都有調用同一個或者類似的代碼塊。這塊代碼就有資格自己成為一個平行的“模塊”,以便日后修BUG可以單獨升級。

個人比較喜歡按業務功能的層次來劃分模塊,這樣有利于劃分任務,減少代碼互相影響,最重要的是比較容易讓人理解。但是就必須經常把工具類模塊協商抽取成為“公共模塊”。

部署架構

部署架構對于持續集成,降低程序員的運營期壓力,有至關重要的作用。一個好的部署架構可以提高性能和可用性。讓程序員可以按部就班的去解決問題。

運行時架構在軟件層面提供性能和可用性。而部署架構考慮的更多是硬件層面。比如網絡機房的分布,服務器硬件的搭配,監控和維護工具軟件的安裝。開發測試網絡和運營網絡的設置。關于安全性的配置。

幾個比較明確的經驗是:

  • 盡量靠近用戶部署機房
  • 所有機房間應該有一條專用的局域網鏈路,讓服務器間數據可以有專用線路可用。
  • 運營網絡的防火墻對于公網接口設置為只開啟服務端口,運營和維護端口全部放在局域網線路上。
  • 開發辦公網絡不能直接和服務器的局域網直接連接,降低個人PC被入侵造成的影響。所有運營網絡的服務器都必須限定有限IP的機器去連接遠程登錄,并且這些機器需要是LINUX的。
  • 對于服務器硬件按照磁盤IO密集型、網絡IO密集型、計算密集型、存儲空間大需求型、經濟節省型的分為5種型號,由業務技術人員仔細選擇。
  • 在測試、開發、管理等資源要求很小的服務器上,盡量采用虛擬機,最大化利用硬件,同時減少維護成本。
  • 對于日常服務器的維護和監控,建立報警和預警機制,如磁盤、帶寬、CPU、特定進程、監聽端口。
  • 對于機器和帶寬的部署,采用最少可用性保障的策略,就是最少有2份服務器以及2倍預計帶寬需求(或其他需求)。
  • 對于部署過程需要的腳本、配置文件、安裝包,必須要有自己獨立的SVN或者文件服務器管理。同時也需要建立“自動化”部署的工具。在這些工具完成之前,不應該正式對外運營。而部署工具本身應該在“外測”環境下經過詳細測試,才更新到正式運營網絡上。
  • 數據架構

    數據架構對于任何業務都有很重要的影響。對于用戶產生的數據,架構本身需要容易備份和恢復,數據就是財富,而數據架構是存放財富的方案。對于開發團隊產生的數據,則需要完善和方便的管理工具,便于修改和增加這些數據。

    數據架構本身還涉及性能、易用性等多個方面。一般來說分為使用關系型數據庫和不使用關系型數據庫兩種。但是不管那種,對于數據的備份(熱備)和恢復都是最首要應該考慮的問題。數據的結構過于復雜其實不利于備份和恢復。而很多時候大數據量又產生“分區”需求(分庫分表),這是分布數據存儲的課題。

    對于使用關系型數據的,一般需要依賴數據庫服務器自己的熱備功能和分區功能,或者自己去實現。然后使用ORM軟件來操作這些數據。所以關系型數據不宜做的過于復雜,太多的“外聯”表會讓整件事變得很復雜。
    如果不使用關系型數據庫,現在的NoSQL風潮提供了很多可選的方案,這些方案最大的特點就是對于結構復雜的數據有良好的擴展性,對于大數據量也有優秀的擴展功能——重要的是不用你自己去代碼實現。缺點則是可能無法保證“統一性”。比較實際的觀點是,盡量少使用關系型數據。雖然它的概念已經深入人心。

    每個模塊都可以做架構設計

    上面的幾個架構,基本包含了整個軟件架構應該涉及的方面。而我們往往比較重視一些“大項目”的架構設計,而比較忽視一些中小項目的架構設計。實際上大部分項目并非“大項目”,而大型項目本身也很可能劃分成更小一點的項目來外包,所以我們應該對于每個項目,都以架構設計的觀點去分析和設計,只是不需要陷入文檔的案牘之中就好了。

    一些好的架構設計,也可以在多個模塊和項目中共用。這種共用的好處非常多,一個是可以節省開發時間,另外也可以少走以前的彎路。最重要的是如果積累下這種設計的文檔和思想,可以讓整個團隊的開發效率都得到提高。

    五. 管理激勵

    明確目標

    目標管理是現代管理學的一個重要成果。明確團隊的目標,然后讓所有人都理解并認同這個目標,是管理中最重要的工作。只有每個人明確了目標,才可能發揮出他的主觀能動性。而且要有明確的目標,團隊成員之間才可能合作。否則成員之間可能會互相拆臺或者推卸責任。

    目標應該是整個團隊的目標,而不應該是只劃分到個人,因為這樣不利于團隊的整合,而會形成嚴重的個人主義。當然我們最常見的是團隊中對于目標不明確。

    目標應該包括以下內容,才稱得上明確。首先是項目要滿足的市場需求,這是項目的愿景。其次是項目怎樣才叫做的好的標準,一般是和競爭對手比較的結果。最后是項目目標和個人發展之間的關系。三層目標必須都讓每個人明確和認同,才能真正激發出團隊的動力來。

    市場需求如果大家不認可,就會覺得項目不值得做,這個時候就需要領導者來用數據和事實證明給大家看。

    項目優秀的標準,不可無限拔高或者虛無縹緲,明確的競爭對手數據是最好的標準,雖然這個信息通常很難獲得,但是這個是團隊中非常有凝聚力的信息。應該盡量的獲取,然后公布給團隊。

    每個人和項目成敗的關鍵,則是核心的激勵機制,雖然很多時候開始很難明確到金錢上的獎勵,但是應該起碼提供一個“最好情況下”的許諾。很多項目以收益分紅,或者過程評價來加工資作為明確的激勵。

    主要手段

    人在集體中能發揮的作用必然比單個人要大,這是人類作為群居動物的天性所決定的。如果你有一定的工作經驗,必定會體會過一個團結的團隊所發揮的良好作用。如何能構造起一個真正的高效的團隊,我認為最重要的方法是“溝通”。這種溝通必須是全方位的,包括團隊成員之間的私交,他們互相之間在工作能力、人品性格、興趣愛好方面的了解。在管理者和團隊之間,對于項目前景、公司狀況等一切和團隊切身利益相關的方面的信息,都必須有良好的溝通。如果程序員覺得你在隱瞞些東西,你一定就是在某些方面有所保留。這種猜忌會破壞團隊的形成。所以對于大量看起來是“保密”的信息上面,對團隊盡量多的公開,是能讓團隊得到主人翁感覺的重要手段。傳統管理方法中很多時候強調公司的信息保密,個人對于團隊的效忠。而這些在高科技開發企業中是行不通的,因為他們就掌握著公司的最大機密——產品開發。

    管理者除了對“人”做事,直接做事也必不可少,開發工作有很多方面是在做設計,所以開發工作本身并不是所謂的體力活,而是一些精巧的設計工作。除了自己參與開發工作,對于團隊其他部分的設計工作,特別是其中的重要決策,管理者也需要盡量多的參與。一方面這種參與可以培訓團隊成員,另外一方面能加強對于項目控制。在決策的過程中,通過廣泛的討論,也是團結團隊的一個手段。當然剛愎自用的處理方法就會產生反效果。

    因為程序開發本身是一種高度自律型的工作,所以管理者的“不做”比“做”更重要,而且應該提供不受干擾的環境。在程序員注意高度集中的情況下,工作效率是最高的。試圖不斷的“參與”開發而打斷程序員的工作,其實是在降低工作效率。好的管理者應該能讓程序員沉浸在開發工作當中,完全不去考慮什么進度報告,工作匯報之類的事情。

    因為程序員對于電腦的熟悉,所以經常會把一些別“專業”的行當混合起來交給程序去做。比如寫代碼的同事去處理數據庫,由或者讓程序員同事負責運維服務器和網絡……術業有專精,如果一個程序員專心的做數據庫的工作,他會比同時做其他幾個事情做的更好。更不用說讓程序員去夾網線搬箱子這些了。總體來說,提供資源支持,降低團隊的“非專業”精力消耗。

    人力分工

    按照專業領域分工;專業再細分分工;軟件開發團隊應該學習外科醫生的團隊,采用嚴格的分工合作,來降低混亂的溝通。每個人只負責自己的事情,會做的非常好。因此如果程序能很好的分成5個模塊,就使用5個程序員,然后為他們配上專業的秘書,數據庫管理員,測試人員,項目經理,運維人員,IT人員,以及其他的資源處理人員,比如美術資源處理專員。

    關注工作分切點的協議,因為人力分工是提高效率的重要手段,所以人員之間的切分點——協議或者流程,就是很關鍵的東西。客戶端和服務端程序員之間,通常就是直接的通訊協議,應該把通訊協議變成一種代碼,然后雙方都使用這種代碼。客戶端程序員和美術之間通常也應該使用某種基于軟件工具的格式文件,比如是UI編輯器的結果。處理WEB的團隊往往由美術提供圖片,然后由專人切圖變成HTML,而這個HTML文件就是很好的協議文件。有些數據錄入人員使用JSON格式的文件,或者是某種嚴格定義的EXCEL文件作為協議文件。

    很多團隊喜歡“廣播”方式的溝通,任何一個事情都讓所有人在一個QQ群里面看到,或者任何一個事情都抄送郵件給一堆人。實際上這種溝通只會浪費別人的時間,所以管理者應該降低溝通范圍,減少“噪音”。

    在《人件》中,提到了高效團隊的形式——膠凍團隊。也就是我們所說的非常團結而且互相信任的團隊。很多公司會以拓展訓練和部門活動的方式去推動形成團隊互信,這些都是有用的。但是在工作過程中,更重要的是讓信息共享來打破可能存在的隔膜,給與更大的自由發揮空間讓團隊成員有機會互動,組織團隊成員間一起討論和解決問題。讓團隊成員都感覺到受關注,并且提醒他們互相關注。多讓大家一起吃午飯。

    績效考核

    績效考核應該考核做了什么事,而不是做的怎么樣;這個和很多按“結果”管理的老板很不接受。但是如果你只是想把績效考核作為一個發獎金的機制的話,單獨使用獎金考核機制就可以了。績效考核應該是推動別人去做某件事的工具。對于已經明確的方法或者子目標,通過這種細化的方式去指導下屬工作。因為是需要事后算賬的,而且是量化的,所以下屬會對這個事情很認真,同時那些不好量化的事情,管理者也很難執行績效考核。所以對于“去做某些事”,是績效考核最好的目標。

    通過考核結果提供正式的工作方法意見。績效考核本身有個反饋的過程,這個反饋的過程應該提供給下屬針對每個具體事情的建議。這種具體的,單獨的一對一的指導,會提高團隊的穩定性。而且也讓團隊成員獲得“受關注”的感覺。這種感覺是形成高效團隊的重要工具。

    考核不能代替目標,不能阻礙目標,而應該是一個溝通工具。績效考核通常會涉及大量的文檔工作,也會有很多量化的工作,但是這些工作,往往不能完全代表商業目標的完成情況。所以有些時候只是平白的增加了管理工作量。績效考核的設定首要需要考慮是不能阻礙團隊目標的實現。很多時候甚至難以覆蓋目標。所以績效考核應該是成為一種溝通的工具:定時、定量、定人的交換對于工作方法的意見。

    目標達成情況作為考核的客觀指標,但不應該是主要績效考核指標。最簡單的績效考核指標就是收入或者利潤率。但是這種簡單指標除了在動機上提高下屬的工作熱情外,并沒有從方法和經驗上幫助團隊成員。有效的考核是引導下屬安裝更有經驗的方法去實現目標。

    進度掌控

    通過測試來了解進度;一切軟件的開發,如果無法測試,就是無法了解的。沒有人回去通過讀代碼了解項目的進度。所以項目本身必須具備經常提供“可測試”的功能。一旦進入測試,項目完成的數量和質量都立刻一目了然了。
    用提高工作效率和提供資源的方法推進進度,而不是通過加班。加班是最有效的降低工作效率的方法。只有降低本身進度推進的損耗——內耗,改善工作方法——更好的工具和更多的知識,除此之外很難有別的加快進度的手段。但是,你也可以通過增加更多的資源,比如人力或者機器。如何把資源放在合理的地方,本身是一門學問,本文在上面很多節都有提到如何有效的使用資源——人力和金錢。

    慶祝每一個進度節點。團隊需要鼓勵,才能保持速度。慶祝本身又是凝聚團隊的一個契機,讓成員覺得在這群人中間能不斷取得成功,本身就會增加互相合作的意愿。如果無端端搞一些團建活動,會讓人覺得厭煩,但是慶祝進度節點,則大家都會認同,可能只是一起吃個飯,但是也是非常有效的一頓飯。

    確保公布進度的目標,并且爭取團隊支持。進度的目標必須能達成共識,“無理”的目標實際上不能成為目標,團隊從此也會陷入最差的狀況——沒有目標。所以進度目標本身需要讓所有人理解并且愿意去努力。通過共同的進度目標,來促進團隊中所有人的積極性——那些喜歡偷懶的家伙也會不好意思。

    在重視質量的情況下推進進度,并且為質量犧牲一定的進度。項目質量是團隊和個人為之“自豪”的重要因數。如果你想擁有具備榮譽感的團隊,就需要為此付出一定代價,可能犧牲一些時間,來獲得更好的產品質量,實際上這是個事半功倍的事情。因為產品質量在長期來看,還是能提供更好的效益的。進度壓力如果造成太多的粗制濫造,會讓后期的團隊越來越沒信心趕上進度。最后被迫推倒重來,或者陷入一個“長期的重構”工程中。這些都是缺乏遠見導致的問題。

    預算制訂

    放松固定資產的預算,盡早投入固定資產預算。項目初期成本中有很大量的固定資產投入。而這些預算看起來可以用更便宜但是質量更差的替代品來替換。但是從長期來看,人力成本才是最重要的大頭。而如果你的固定資產太少,也會難以招聘或者穩住最優秀的那批員工。優質的固定資產不但折舊率更低,而且能讓程序員發揮出更好的功效,直接節省那些高額的人力成本。
    收緊人力資源預算,重視10倍效率員工的作用。人員的溝通成本,是所有關于人員的成本中最高昂的。人越少,需要的溝通就越少。很多公司在發展期喜歡快速擴充團隊,希望能抓住機會盡快占領市場。但是請記住,一個母親懷一個孩子需要10個月,100個母親去懷一個孩子,同樣需要10個月。團隊和項目的進度并非靠人的數量增加就能加快的。而且更重要的,優秀員工的工作效率最大可以比一般員工的效率高10倍以上,你只需要給他們5倍的工資,就能節省下另外50%的工資,同時還有不止50%的固定資產投入和其他費用。少而精的團隊在更方面都比龐大良莠不齊的團隊更有效率。
    針對風險,不斷修改預算,項目進度越后期,預算越準確。軟件項目開發和拍電影一樣,具備很高的風險。不但成本難以預料,而且收益也要最后才能知道。因此對于預算來說,不斷的記錄和回顧預算執行情況,以及其效率,修改現行預算方案,才能真正適合開發的進度。那種一年都按年度預算去執行的死板方法,是無法適應快速變化的軟件開發項目的。

    風險防御

    留出過冬的口糧,定出必須籠絡的人員,盡早進入資金循環。軟件項目風險之高,難以用其他行業完全類比。就算最著名的公司如微軟、IBM也頻頻推出失敗的產品。因此在資金上留有盡量大的余地非常重要,很多項目經歷過瀕死體驗后,才能實現商業成功。軟件項目能繼續高效的開發下去,核心人員是至關重要的,讓他們擁有足夠的耐心和薪水,和項目繼續下去,才有收獲那天的希望。而降低風險的最好方法,則是盡快去接觸風險,盡快讓產品上市,讓產品開始嘗試賺錢,能讓開發方向盡快明確到最實際的內容上來。團隊內的爭論和疑惑也會因為實際的財務數字而消散,大家的目標會更清晰——賺錢。

    師徒制度預備人員流動。人員流動是不可避免的,就算你做到100分,還是會有別的原因導致程序員離職。因此除了在代碼上提倡可讀性和良好的結構,重視文檔和過程記錄,采用預備接替人員是很重要的手段。讓資深程序員和一個學徒程序員一起工作,能盡快提高學徒程序員的能力,同時也讓代碼能有多一個人熟悉。在師傅離職后,徒弟就可以升職到師傅的地位,也是一種良性的激勵。而徒弟對于這個代碼的感情,是別人所無法比擬的。

    盡早進入團隊和項目估值,尋找合適的買家。項目除了直接到用戶市場上去實現商業價值外,還應該看到,軟件項目因為他的結構性和擴展性,往往會在更大的范圍內具有價值。一些其他商業方向的公司或者投資人,可能會看重你的項目的擴展價值。而這些擴展價值需要一定時間來讓別人認識到,因此對于管理者,在清晰的掌握項目的全面價值的情況下,盡早的介紹給潛在的投資人和客戶,能讓項目擁有更廣闊的前景,從而降低其天然的風險。

    ?

    轉載于:https://www.cnblogs.com/purpleraintear/p/6160716.html

    總結

    以上是生活随笔為你收集整理的如何提高程序员的生产率 (2)的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 日韩精品中文字幕在线 | 五十路av | 性折磨bdsm欧美激情另类 | 国产黄色av网站 | www国产亚洲精品久久网站 | 日韩成人av片 | 大胸奶汁乳流奶水出来h | 在线91av | 亚洲视频a | 黄色网页免费在线观看 | 欧美色老头old∨ideo | 红桃视频一区二区三区免费 | 国产精品免费无遮挡无码永久视频 | 成人免费毛片糖心 | 免费吸乳羞羞网站视频 | 亚洲综合图 | 一本久久综合 | 麻豆国产精品一区 | 椎名由奈在线观看 | 亚洲第一男人天堂 | 亚洲午夜18毛片在线看 | 特大巨交吊性xxxx | 中文字幕高清在线免费播放 | 欧美性xxxx图片 | 欧美在线xxx| 超碰97观看| 国产 日韩 欧美在线 | 日批免费在线观看 | 在线观看久草 | 日韩第九页 | 国产精品美女www | 青青草官网 | 牛牛澡牛牛爽一区二区 | 日本三级久久 | 操碰人人| 成人高清免费观看 | 欧美在线观看一区二区三区 | 2025国产精品 | 午夜免费小视频 | 男人和女人插插 | 女生张开腿给男生桶 | 神马影院一区二区三区 | aaa大片十八岁禁止 中文字幕亚洲在线观看 | 欧美特黄一区二区三区 | 黄色网久久| 国产欧美精品 | 国内精品在线观看视频 | 在线免费观看一区 | 顶弄h校园1v1 | 久久精品国产露脸对白 | 亚洲国产中文字幕在线 | 九九热免费| 美女光屁屁露胸胸 | 少妇情理伦片丰满午夜在线观看 | 亚洲天堂手机 | 91老师国产黑色丝袜在线 | 91精品国自产 | 亚洲国产日韩欧美在线观看 | 黄色大片国产 | 公侵犯人妻一区二区 | 国产精品xxxx| 亚洲精品无amm毛片 国内一区二区三区 | 国产高清在线观看视频 | 亚洲欧美偷拍视频 | 特级毛片www | 97久久久久久久久久 | 日本美女黄色一级片 | 三上悠亚一区二区三区 | 天天做夜夜爱 | 日本一区不卡在线观看 | 日韩精品1区2区 | 在线草 | 精品人妻无码中文字幕18禁 | 91久久精品国产91久久性色tv | 精品人妻少妇嫩草av无码 | 色花av| 嫩草影院在线观看视频 | 日韩欧美的一区二区 | 粉嫩av | 中文字幕乱码亚洲无线三区 | 日韩欧美在线一区二区 | 精品亚洲一区二区三区四区五区 | 精品在线视频一区二区三区 | 日韩免费福利视频 | 手机免费av片 | 中国吞精videos露脸 | 九九热免费精品视频 | 91传媒视频在线观看 | 精品动漫一区二区三区在线观看 | 自拍偷拍专区 | 中国毛片在线 | 老熟女一区二区三区 | 欧美精品日韩在线观看 | 久久精品视屏 | www午夜| 久久伊人精品 | 中文字幕在线字幕中文 | 在线播放日韩av | 灌满闺乖女h高h调教尿h |