【軟工】個人部落格作業
項目 | 内容 |
---|---|
課程:北航2020春軟體工程 | 部落格園班級部落格 |
作業:閱讀《建構之法》, 回答關于軟體和軟工的問題 | 個人部落格作業 |
個人課程目标 | 系統學習軟體工程,訓練軟體開發能力 |
這個作業在哪個具體方面幫助我實作目标 | 閱讀教材,對軟體、軟體工程、軟體産業有整體認識 |
看完《建構之法》後仍然不懂的問題
1. 軟體的“生命周期”?
原書第一章中寫道:
軟體團隊要從需求分析開始,……,展開後續工作,如設計(軟體架構)、實作(資料結構和算法)、測試,到最後釋出軟體。……,修複各種各樣的問題,這叫軟體維護,或者服務營運。這一系列過程就是軟體的生命周期。
看起來軟體生命周期的定義應該為一個序列,包含需求分析、軟體設計、實作、測試、運作和維護等。
然而在第五章關于流程等部分又提到了瀑布模型、瀑布模型的各種變體、統一流程(RUP)等。在瀑布模型中,各步驟是可以進行回溯的;在RUP中,需求分析、設計、實作、測試、部署工作流又滲透到了初始、細化、構造、傳遞四階段中。
這看起來有些沖突——我們當然可以概略地說軟體的生命過程中包含了需求分析、設計、實作、測試、部署這些階段,但将其按第一章講成是一個線性過程、或按RUP來說各個步驟在時間上有并行重疊,似乎都不是定數。
是以我認為對軟體的生命周期的定義是不确定的。首先無論是按哪種模型,似乎這些步驟都不是一個重複的Cycle。其次具體的軟體流程是按照需求和産品特點不斷調整的,沒有一個固定的、通用的流程。
我認為應當将軟體的“生命周期”粗略地定義為RUP的四階段——初始階段、細化階段、構造階段和傳遞階段。在每個階段裡的具體步驟是不定的。例如按照第一章講述的類似“序列”的流程中,四個階段内部的工作流是單向串聯的;按照瀑布模型來看,工作流是雙向串聯的;按照RUP來看,工作流是并行的但參與程度不同。
綜上,我認為軟體的生命周期是不固定的,且不能被稱為“周期”。如果偏要給定一個整體的流程,我認為按照RUP四階段的粗劃分比較合理。
2. Personal Software Process 與單元測試
在原書第二章介紹個人開發流程(PSP)時寫道,Development由以下部分組成:
分析需求、生成設計文檔、設計複審、代碼規範、具體設計、具體編碼、代碼複審、測試
這裡的測試我想是包含了單元測試和回歸測試。就回歸測試而言,将其寫到流程的最後是有道理的——編碼完成後進行測試,測試未通過的進行修複,修複後需要進行回歸測試以保證其他部分沒有退化。但我對單元測試的最早出現位置有質疑。我認為單元測試不僅在編碼完成後進行,而且應該伴随着具體編碼甚至具體設計時就應該開展。
書裡又寫道:
在寫技術子產品的規格說明書的時候,要越詳細越好,最好各項要求都可以表示為一個單元測試用例。……單元測試必須由最熟悉代碼的人(程式的作者)來寫。
這裡我們知道,單元測試的測試用例可以依照規格文檔來構造。那麼其實在完成最初的架構和子產品設計、在具體編碼之前,大部分單元測試的目标對象和測試用例就已經可以得出。我認為,應當在規格設計後先寫好單元測試用例和子產品接口,每個子產品具體編碼完成後盡可能早的進行單元測試,而不應該等到全部編碼完成、複審後再測試。到那時候,就算是程式的作者可能也記不得具體子產品的情況了。
而對結對程式設計而言,熟悉程式的人有兩個了,就可以在Driver寫代碼的同時,Navigator對着設計文檔和Driver寫的代碼設計測試用例、幫跑單元測試,同樣也是在編碼的同時,這樣效率更高且與函數/類規格更貼切,在寫代碼時發現的特殊處理需要測試也可以加在已有的測試上。
3. 代碼設計規範中的參數檢查、assert和規格
書中第四章介紹代碼規範時提到,
在Debug版本中,所有的參數都要驗證其正确性。在正式版本中,對從外部(使用者或别的子產品)傳遞過來的參數,要驗證其正确性。
如何驗證正确性?那就要用assert。當你覺得某事肯定如何時,就可以用斷言。……
“所有的參數都要驗證其正确性”是一件難以實作的工作。最基本的,對于Python這種動态類型語言,甚至需要驗證參數的類型!雖然Python在版本更新中引入了類型說明注釋:
def add(x:int, y:int) -> int:
return x+y
但是這僅僅是一個注釋,程式在運作時不會進行任何檢查。難道我們需要對這些參數一個個地
isinstance()
?
而參數的正确性也是難以規定的。考慮如下的對圖進行操作的函數(假定節點用整數編号代指):
def functionAboutGraph(nodeList, edgeList):
pass
所謂參數的正确性恐怕有如下幾個層級:
-
和nodeList
都是List。前者的元素是edgeList
,後者是int
。(int, int)
- 在
中出現的所有邊的頂點,都應屬于edgeList
nodeList
- 無重點、無重邊等其他可能由函數規格說明書制定的規則。
- ……
首先,這些驗證若全部使用assert進行驗證,可能比函數功能本身更費時(計算上的)和費心(程式員角度)。
其次,如何定義正确?正确性的驗證應當到什麼層次?哪些應當嵌在代碼裡做運作時檢查(萬無一失的),哪些應當放在單元測試裡進行測試(抽樣檢查的)?
這些問題我沒有答案。不過我有時會使用assert檢查一些“顯然的”(如何定義顯然?)正确性要求,比如
somePtr != nullptr; // NullPointer?
if (myContainer.count(element) && myContainer[element] == 123); // Existence?
4. NABCD模型
在競争環境下,NABCD模型中,NAC對産品是否成功的影響似乎過小,BD對産品的影響似乎過大:
我們要在競争性的環境中實踐軟體工程,那就要做實用并且創新的項目。……大家可以參考NABCD模型。
N:需求,你的創意滿足了使用者的什麼需求?
A:做法,看看你有什麼獨特的招數,不光是技術上的,也可以是商業模式上的。
B:好處,會帶來什麼好處?要花費什麼才能得到好處?得到的好處超過遷移成本?
C:競争,使用者需求 vs 我們産品 vs 别人産品
D:推廣,如何把産品交到使用者手中?
以我使用過的兩個軟體産品舉例。
- Grammarly:英文寫作助手,能提供拼寫與文法、流暢性、是否吸引人、達意程度、易讀性、詞彙選擇等方面的評分、分析和建議。這款産品的優勝之處在于,它高度滿足了使用者的爽點(超過了需求的範疇,可以稱為Benefits)。使用者隻需要輸入一段文字就可以在幾秒鐘内得到詞和短語級别的各方面的修改建議。無腦的使用者隻需要點選每項警告,點選應用建議的寫法,就可以目睹着自己的分數chuachua地上漲。另一個方面,Grammarly在YouTube大量投入了品質相當高的廣告,且直接點選就可以使用,非常簡單,在推廣(我認為原詞Delivery更達意,不是推廣好而是易得)上做到了很高的水準。
- 微信:我認為這款産品的成功原因在于Delivery,但不是由于微信本身,而是由于自己與騰訊全家桶的數十款軟體高度綁定,微信正在野心勃勃地發展為“下一代網際網路的入口”,微信成為了一個“産品矩陣“中的領頭羊。微信本身沒有滿足使用者的許多需求,也沒有什麼特殊的招數,現在更缺少競品。如果剝離騰訊系的其他app,微信恐怕難以敵過挑剔的使用者和追趕的競品。
在需求大家都能基本滿足、做法的先進性使用者難以直接感覺、産品趨同化的現在,是否滿足使用者不計成本也要用到的爽點和優秀的營銷與推廣仿佛決定了一款軟體的前途(而不是品質)。這說明NABCD模型是否過時?且NABCD的核心變成了B與D後,是否不再是一個軟體工程概念而變成了一個營銷與商業發展概念?
5. 團隊的創新能力
創新的迷思之七:成功的團隊更能創新?
很多成功的企業進入了“創新者的困境”。當成功的企業步入中年,它們當年發迹的市場成熟了,當年賴以成功的創新技術成了主流的成熟技術,又叫“維持性的技術”,在成熟的市場和維持性的技術環境中,技術的創新并不是影響企業成敗的主要因素……那些沒有成功包袱的小公司反而能把颠覆性的創新帶到市場,挑戰成熟企業的霸主地位。
關于這個Myth的論述我本人非常贊同。就以百度和位元組跳動為例,百度在當年也是靠硬實力和創新技術起家的,等到搜尋業務成為霸主後,就漸漸缺少産品上的創新動力,而是将其他的産品依賴搜尋業務的流量和使用者,靠吃老本帶起來其他的産品。而位元組跳動作為新興企業,在創業之初沒有成功的包袱,專注于以推薦系統為基礎的新鮮内容流式App,取得了蓬勃的發展。
然而作為熱愛創新的從業者,是應該加入百度式的穩定卻缺乏創新漸漸老去的企業,還是應該加入位元組跳動式的不斷創新正在高速發展的新興企業?我曾聽說不少應屆生更願意去應聘位元組跳動,但大多是因為更現代的産品和管理模式,即公司本身的“新”,而并不一定是因為公司的“創新”。那我不禁想問,對程式員的職業價值自我實作而言,企業是否創新(不是個人是否創新)是否是一個重要的因素?
“軟體”與“軟體工程”
- “軟體”這一詞彙是由 John Tukey在他1958年的論文《具體數學教學》中最早提到的。參考:維基百科
In 2000, Fred Shapiro, a librarian at the Yale Law School, published a letter revealing that Tukey's 1958 paper "The Teaching of Concrete Mathematics" contained the earliest known usage of the term "software" found in a search of JSTOR's electronic archives, predating the OED's citation by two years.
- “軟體工程”這一詞彙是由 Margaret Hamilton 作為MIT的某實驗室的軟體工程部主管,在為阿波羅飛船設計導航系統時發明的。參考:IEEE Computer Society
Indeed, Margaret Hamilton, renowned mathematician and computer science pioneer, is credited with having coined the term software engineering while developing the guidance and navigation system for the Apollo spacecraft as head of the Software Engineering Division of the MIT Instrumentation Laboratory.
軟體工程發展過程中有趣的冷知識和故事
參考:維基百科
Windows XP中自帶的三維彈球遊戲其實不是由微軟開發,而是由Maxis與Cinematronics開發和發行,但被微軟引入自家作業系統。在微軟版遊戲中,原廠商的名稱被通過更換顔色而有意隐藏起來,并且閹割了回放功能、遊戲音樂和更高的分辨率。
其實三維彈球遊戲中不止有Windows遊戲中看到的一張球台,而是共有3張“彈珠台”,分别名為“太空軍校生”(最出名的那一款)、“Skulduggery”以及“Dragon's Keep”。
當時絕大部分的同類型的電腦遊戲都是采用二維畫面渲染。而Full Tilt! Pinball則是采用三維預渲染繪圖技術,來“構造”三張不同的“彈珠台”,有别于其它模式類似的電腦遊戲,在同類遊戲中尚屬首次。
源程式版本管理軟體和項目管理軟體
- Microsoft TFS (Azure DevOps Server) 參考:Wikipedia 參考:部落格
- 優點:不僅支援版本控制,還支援項目管理,包括靈活開發和瀑布模型開發,覆寫了整個軟體生命周期
- 缺點:較為複雜,能應用起來的團隊、公司的數量少,大多隻用了極小一部分功能
- Git 參考:Wikipedia
- 優點:支援分布式開發,高效處理大型工程,支援非線性開發
- 缺點:初學者難以學習,三階段的概念複雜且易混淆
- GitHub 參考:Wikipedia 參考:部落格
- 優點:基于git,不僅支援git的各項功能,還擁有對文檔、issue、wikis、個人首頁、Gist等的支援,成為了一個交流的平台
- 缺點:可能不是捕捉創意過程和記錄創意點子的最佳工具;非常适用于代碼跟蹤,但是卻不是最好的設計跟蹤工具
- Bugzilla 參考:Wikipedia
- 優點:輕量化,高速高效,開源,容易在各種資料庫、工具和作業系統下使用
- 缺點:隻能支援缺陷追蹤和測試
- Trac 參考:維基百科
- 優點:有網頁界面,能把bug資料庫、版本控制系統和wiki結合起來,支援Git、Mercurial等多種版本控制系統
- 缺點:功能較為簡單
- Mercurial 參考:維基百科 參考:知乎
- 優點:高性能、可擴充性、分散性、完全分布式合作開發、能同時高效地處理純文字和二進制檔案,以及分支和合并功能,以此同時保持系統的簡潔性
- 缺點:功能比git簡陋,沒有命名空間,一旦和很多個版本庫交流容易導緻混淆
Wikipedia 通過統計Alexa Rank來對源代碼管理軟體進行排名。對于表格中沒有的軟體,我們也可以通過找到其官網,查詢Alexa指數來進行相對排序。

選擇兩個源程式/項目管理軟體進行實踐
Git
(圖中commit有本人賬戶資訊)
git作為最常用的源程式版本控制軟體,被内嵌到了Visual Studio, VS Code, Intellij系列, Apple XCode等IDE中。
且能通過IDE的圖形化界面直覺地看到commit和branch的變化,且能友善地進行檔案比較等操作,比起控制台git對使用者更友好。
GitHub
(圖中右上角為本人帳戶)
GitHub不僅作為一個git的網頁版平台,更支援issue、pr等功能。
以issues為例,使用者可以将産品的bug和使用中的疑問釋出到issues上,對開發者進行直接的回報。
此外,開發者還可以直接從使用者口中聽到對産品的要求、建議、疑問等,能将GitHub作為一個産品釋出頁,更直接地了解使用者的需求,以改進自己的産品。參與讨論的使用者還可以訂閱issue文章以擷取最新資訊。