如何建立良好的軟體?軟體不僅僅是編寫程式碼而更是開發知識! - csc.gov.sg

banq發表於2019-08-20

軟體具有使用傳統管理技術難以構建的特性; 有效的發展需要一種不同的、更具探索性和反覆性的方法。

為什麼糟糕的軟體會發生在好人身上
糟糕的軟體是世界上為數不多的用金錢無法解決的事情之一。數十億美元的航空公司的航班搜尋應用程式通常不如學生群體構建的那些程式。在面臨共享租車服務的威脅同時,全世界成熟的計程車公司其實都已經有了糟糕的預訂應用程式。痛苦的企業IT系統通常是具有大量預算的專案,這些專案是在多年的時間內建立起來的。不管軟體壞的原因是什麼,似乎並不缺乏資金。

令人驚訝的是,不良軟體的根本原因與特定的工程選擇關係不大,而更多地與如何管理開發專案有關。最糟糕的軟體專案通常以非常特殊的方式進行:
專案所有者開始想要構建特定的解決方案,並且從未明確地確定他們試圖解決的問題。然後,他們收集了大量利益相關者的一長串要求。然後將此列表交給相應大型的外部開發團隊,他們從頭開始構建這個高度定製的軟體。一旦滿足所有要求,每個人都會在系統啟動並宣佈專案完成時慶祝。

不良軟體的根本原因與特定的工程選擇關係不大,而更多地與如何管理開發專案有關。

但是,儘管系統在技術上符合規範,但在將其置於實際使用者手中時會發現嚴重問題。它緩慢,令人困惑,並充滿了微妙的錯誤,使得使用它是一種挫敗。不幸的是,到目前為止,外部開發團隊已被解僱,並且沒有剩餘資源來進行必要的修復。當一個新專案可以在幾年後啟動時,所有關於導致這些問題的原因的知識已經離開了組織並且迴圈再次開始。

正確的編碼語言,系統架構或介面設計將因專案而異。但是,軟體特有的特徵導致傳統管理實踐失敗,同時允許小型創業公司以低廉的預算取得成功:

  • 重用好的軟體很容易; 它是讓你快速建立美好事物的原因; 
  • 軟體的限制不在於構建它的資源量,而在於它在崩潰之前可以獲得的複雜程度; 和
  • 軟體的主要價值是不是生成的程式碼,而是誰生產它的人積累的知識。


瞭解這些特徵可能無法保證良好的結果,但它確實有助於澄清為什麼這麼多專案會產生不良後果。此外,這些導致一些核心運營原則可以大大提高成功的機會:
  1. 儘可能簡單地開始;
  2. 尋找問題並進行迭代; 和
  3. 聘用你可以最好的工程師。

雖然有許多更微妙的因素需要考慮,但這些原則構成了一個基礎,可以讓您開始構建優秀的軟體。

重用軟體可以讓您快速構建好東西
軟體易於複製。在機械級別,程式碼行可以逐字地複製並貼上到另一臺計算機上。更一般地說,網際網路上有很多關於如何使用線上提供的現成程式碼模組構建不同型別系統的教程。現代軟體幾乎從未從頭開發。即使是最具創新性的應用程式也是使用已經組合和修改的現有軟體構建的,以實現新的結果。
可重用程式碼模組的最大來源是開源社群。開源軟體是一種軟體,其中程式碼可以自由釋出,供任何人檢視和使用。開源社群的許多最大貢獻者都是巨型科技公司。如果你想像Facebook那樣使用最先進的行星可擴充套件資料庫,只需下載他們在2008年開源的Cassandra程式碼。如果你想親自試用Google的尖端機器學習,請下載TensorFlow系統於2015年釋出。使用開原始碼不僅可以使您的應用程式開發更快,而且可以讓您訪問比您自己開發的任何技術都複雜得多的技術。對於最流行的開原始碼,它更加安全,因為有更多人關注並修復漏洞。這就是數字技術取得如此迅速進步的原因:即使是最新的工程師也可以利用我們專業提供的最先進的工具。
雲服務的出現進一步提高了可重用性,只需訂閱費即可充分利用甚至專有系統。需要一個簡單的網站?只需使用Squarespace或Wix等網站構建服務,只需點選幾下即可配置一個。一個資料庫?從Amazon Web Services或Microsoft Azure訂閱虛擬版。雲服務允許開發人員從專業化中受益; 服務提供商處理所有訂戶使用的可靠,高質量軟體的設定,維護和持續開發。這允許軟體開發人員停止在解決問題上浪費時間,而是專注於提供實際價值。
如果所有時間花在重建現有技術上,就無法取得技術進步。軟體工程是關於構建自動化系統,而自動化的第一件事就是日常的軟體工程工作。關鍵是要了解要重用的系統是什麼,如何根據您的獨特需求定製它們,以及修復沿途發現的新問題。

軟體工程是關於構建自動化系統,而自動化的第一件事就是日常的軟體工程工作。

軟體受到複雜性的限制
(banq注:該文沒有意識到 重用導致複雜性,因為一個軟體要考慮重用,相當於多個職責都要考慮,抽象其中共用職責,萬一抽象得不適當,導致使用起來非常複雜,不如各自開發各自得,解耦高於重用,才能降低複雜性,集中在一起重用才會導致複雜,重用導致忽視上下文,變得難以學習和熟練應用,那麼多開源軟體,真正適合你的應用場景的很少。)

一個軟體的有用性通常受其複雜性的限制,而不是建立它所投入的資源量。
IT系統通常充滿了功能,但仍然受到使用者的討厭,因為它們變得多麼混亂。相比之下,排名靠前的移動應用程式往往因其簡單性和直觀性而受到稱讚。學習使用軟體很難。除此之外,新功能實際上會讓使用者感覺更糟糕,因為累積的複雜性開始變得勢不可擋。例如,在擔任Apple的媒體生態系統中心近20年後,iTunes今年分為三個不同的應用程式(用於音樂,播客和電視節目),因為它的功能對於一個應用程式而言變得過於複雜。從可用性的角度來看,限制不是可以實現多少功能,而是適合簡單直觀介面的功能。

即使忽略了可用性,一旦專案變得過於複雜,工程進度就會停滯不前。新增到應用程式的每個新程式碼行都有可能與其他每一行進行互動。應用程式的程式碼庫越大,每當構建新功能時引入的錯誤就越多。最終,從新錯誤中建立的工作速率取消了功能開發所完成的工作速率。這被稱為“技術債務”,是專業軟體開發的主要挑戰。這就是為什麼許多大型IT系統存在多年未解決的問題的原因。為專案增加更多的工程師只會增加混亂:隨著程式碼庫從自身的重量中剔除,它們開始更快地執行。

構建良好的軟體涉及交替擴充套件和降低複雜性的迴圈。

在這種情況下,前進的唯一方法是退後一步,使程式碼庫合理化並簡化。可以重新設計系統架構以限制意外的互動。即使已經構建了非關鍵功能,也可以將其刪除。可以部署自動化工具來檢查錯誤和編寫錯誤的程式碼。比爾蓋茲曾經說過“透過程式碼行測量程式設計進度就像測量飛機建造進度”。人類思維只能處理有限的複雜性,因此軟體系統的複雜程度取決於複雜性預算的使用效率。
構建良好的軟體涉及交替擴充套件和降低複雜性的迴圈。隨著新功能的發展,無序自然會在系統中積累。當這種混亂開始引起問題時,暫停進展以花時間清理。這個兩步過程是必要的,因為沒有柏拉圖式的良好工程:它取決於您的需求和您遇到的實際問題。即使是簡單的使用者介面(如Google的搜尋欄)也會在表面下包含大量複雜性,而這些複雜性無法在單次迭代中完善。挑戰在於管理這個迴圈,讓它變得混亂到足以取得有意義的進展,但不要讓它變得如此複雜以至於變得勢不可擋。

沒有柏拉圖式的好工程:它取決於您的需求和您遇到的實際問題。​​​​​​​

軟體是關於發展知識而不是編寫程式碼​​​​​​​
在軟體開發中,大多數想法都很糟糕; 這不是任何人的錯。只是可能的想法的數量是如此之大,以至於任何特定的想法可能都不會起作用,即使它是非常謹慎和聰明地選擇的。要取得進步,你需要從一堆糟糕的想法開始,拋棄最壞的想法,並發展最有希望的想法。Apple是一個富有遠見的設計典範,它在登陸最終產品之前會經歷數十個原型。最終產品可能看似簡單; 這是一個錯綜複雜的知識,為什麼選擇這個特定的解決方案而不是它的替代方案,使它變得更好。
即使在產品構建之後,這種知識仍然很重要。如果一個新團隊接管了一個不熟悉的軟體程式碼,該軟體很快就會開始降級。作業系統將更新,業務需求將發生變化,並且將發現需要修復的安全問題。處理這些微妙的錯誤通常比首先構建軟體更難,因為它需要對系統的體系結構和設計原則有深入的瞭解。
在短期內,一個不熟悉的開發團隊可以透過權宜之計修復來解決這些問題。但隨著時間的推移,由於附加程式碼的臨時性質,新錯誤會累積起來。由於不匹配的設計範例,使用者介面變得混亂,並且整體上系統複雜性增加。軟體不應被視為靜態產品,而應視為開發團隊集體理解的生動體現。

軟體不應被視為靜態產品,而應視為開發團隊集體理解的生動體現。

這就是為什麼依靠外部供應商進行核心軟體開發很困難的原因。您可能會獲得一個正在執行的系統及其程式碼,但是有關它如何構建以及所做出的設計選擇的寶貴知識會讓您的組織失去興趣。這也是為什麼將系統交給新供應商進行“維護”的原因常常會導致問題。即使系統記錄得很好,每次新團隊接管時都會丟失一些知識。多年來,該系統成為許多不同作者的程式碼拼湊而成。繼續跑步變得越來越難; 最終,沒有人真正理解它是如何運作的。
為了使您的軟體能夠長期保持良好執行,讓您的員工與外部幫助一起學習以保留組織中的關鍵工程知識非常重要。

良好軟體開發的3個原則​​​​​​​

1.儘可能簡單地開始
對於特定領域而言,成為“一站式商店”的專案往往註定失敗。推理似乎足夠明智:有什麼更好的方法來確保您的應用程式解決人們的問題,而不是讓它儘可能多地解決?畢竟,這適用於超市等實體店。不同之處在於,雖然在設定實體店後新增新商品相對容易,但是具有兩倍功能的應用程式的構建難度是其兩倍,並且難以使用。
構建優秀的軟體需要關注:從可以解決問題的最簡單的解決方案開始。一個精心設計但簡單化的應用程式從來沒有新增必要功能的問題。但是,一個很難做很多事情的大型IT系統通常無法簡化和修復。即使是成功的“全部”應用程式,如微信,Grab和Facebook,也開始使用非常具體的功能,並且只有在確保了自己的位置後才能進行擴充套件。軟體專案很少失敗,因為它們太小; 他們失敗是因為他們太大了。

軟體專案不會因為它們太小而失敗,; 他們失敗是因為他們太大了。

遺憾的是,在實踐中保持專案的重點非常困難:只收集所有利益相關者的要求已經建立了大量的功能。
管理這種膨脹的一種方法是使用優先順序列表。仍然需要收集所有要求,但每個要求都根據它們是絕對關鍵功能,高附加值還是非常有用而進行標記。這樣可以建立一個低得多的緊張計劃流程,因為不再需要明確排除功能。然後,利益相關者可以更加明智地討論哪些特徵是最重要的,而不必擔心專案遺漏的問題。這種方法也明確了具有更多特徵的權衡。想要提高功能優先順序的利益相關者還必須考慮他們願意優先考慮哪些功能。團隊可以從最關鍵的目標開始,在時間和資源允許的情況下沿著列表工作。

我們對所有最成功的應用程式採用了類似的流程。Form.gov.sg最初是一個手動Outlook宏,花了我們六個小時為我們的第一個使用者設定,但今天已經處理了大約一百萬個公開提交。Data.gov.sg最初是一個開源專案的直接副本,並且已經發展到每月超過300,000次訪問。Parking.sg有大量的200個可能的功能列表,我們從來沒有開始構建,但今天仍有超過110萬使用者。這些系統雖然簡單但不是因為它而受到好評。

2.尋找問題並重復
事實上,現代軟體是如此複雜,變化如此之快,以至於沒有多少計劃可以消除所有缺點。就像寫一篇好文章一樣,尷尬的早期草稿對於瞭解最終論文應該是什麼是必要的。要構建優秀的軟體,您需要首先構建不良軟體,然後積極尋找問題以改進您的解決方案。
這開始於簡單的事情,就像與你想要幫助的實際人交談一樣簡單。目標是瞭解您想要解決的根本問題,並避免僅根據先入為主的偏見跳轉到解決方案。當我們第一次開始使用Parking.sg時,我們的假設是執法人員發現必須繼續對紙質優惠券進行心理計算令人沮喪。然而,在與經驗豐富的官員度過了一個下午之後,我們發現,對於專業人士來說,進行這些計算實際上非常簡單。這一次談話為我們節省了數月的潛在浪費,讓我們將我們的專案重點放在幫助司機上。
謹防偽裝成問題陳述的官僚目標。“駕駛員在處理停車券時感到沮喪”是一個問題。“作為我們部門家庭數字化計劃的一部分,我們需要為司機構建應用程式”不是。“使用者對在政府網站上查詢資訊的難度感到惱火”是一個問題。“作為數字政府藍圖的一部分,我們需要重建我們的網站以符合新的設計服務標準”不是。如果我們的最終目標是讓公民的生活更美好,我們需要明確承認使他們的生活更加糟糕的事情。
透過明確的問題陳述,您可以透過實驗測試不同解決方案的可行性,這些解決方案在理論上難以確定。與聊天機器人交談可能並不比瀏覽網站更容易,使用者可能不想在他們的手機上安裝另一個應用程式,無論它對國家有多麼安全。使用軟體,顯而易見的解決方案通常具有致命的缺陷,直到它們投入使用才會出現。目標尚未構建最終產品,而是首先儘可能快速且廉價地識別這些問題。用於測試介面設計的非功能性模型。半功能模型嘗試不同的功能。匆忙編寫的原型程式碼可以幫助更快地獲得反饋。在此階段建立的任何東西都應視為一次性的。
透過對正確解決方案的充分理解,您可以開始構建實際產品。您停止探索新想法並縮小範圍,以確定您的特定實現的問題。從少數測試人員開始,他們將很快發現需要修復的明顯錯誤。隨著問題的解決,您可以越來越多地向更大的池開放,他們會發現更多深奧的問題。
大多數人只提供一次反饋。如果你首先向大量觀眾釋出,每個人都會給你相同的明顯反饋,你將無處可去。即使是最好的工程師構建的最好的產品創意也會出現重大問題。目的是反覆改進輸出,打磨粗糙的邊緣,直到出現好的產品。
即使在完成所有這些迭代之後,在釋出之後,產品問題也是最重要的。只有0.1%的時間發生的問題可能在測試期間不會被注意到。但是,一旦你有一百萬使用者,每天問題都沒有得到解決,你需要處理的是一千個憤怒的人。您需要先解決新移動裝置,網路中斷或安全攻擊造成的問題,然後才能對使用者造成重大損害。透過Parking.sg,我們構建了一系列輔助系統,可以不斷檢查主系統是否存在付款差異,重複停車會話和應用程式崩潰。隨著時間的推移建立一個“免疫系統”可以讓你避免不堪重負,因為新的問題不可避免地會出現。
總的來說,方法是使用這些不同的反饋迴路來有效地識別問題。小的反饋迴路可以快速輕鬆地進行修正,但卻錯過了更廣泛的問題。大型反饋迴圈可以解決更廣泛的問 您希望同時使用兩者,儘可能使用緊密迴圈解析,同時仍具有寬迴圈以捕獲意外錯誤。構建軟體不是為了避免失敗; 它是在戰略上儘快失敗,以獲得建立良好事物所需的資訊。

3.僱用最好的工程師
擁有良好工程學的關鍵是擁有優秀的工程師。谷歌,Facebook,亞馬遜,Netflix和微軟都擁有令人眼花繚亂的全球最大技術系統,然而,他們有一些最有選擇性的採訪流程,同時仍在激烈地競爭招募最強大的候選人。有一個原因是,即使是應屆畢業生的工資也隨著這些公司的增長而大幅上升,並不是因為他們喜歡放棄金錢。
史蒂夫賈伯斯和馬克祖克伯都表示,最優秀的工程師的工作效率至少是普通工程師的10倍。這不是因為優秀的工程師編寫程式碼的速度要快10倍。這是因為他們做出了更好的決定,節省了10倍的工作量。
優秀的工程師可以更好地掌握他們可以重複使用的現有軟體,從而最大限度地減少他們必須從頭開始構建的系統部分。他們可以更好地掌握工程工具,自動完成自己工作的大部分日常工作。自動化還意味著釋放人類以解決意外錯誤,最好的工程師在這方面做得更好。優秀的工程師自己設計的系統更健壯,更容易被他人理解。這具有乘數效應,讓他們的同事更快更可靠地建立他們的工作。總的來說,優秀的工程師是如此有效,不是因為他們產生了更多的程式碼,而是因為他們做出的決定可以避免你從不知道的工作中解脫出來。
這也意味著最優秀的工程師團隊通常可以比普通工程師的大型團隊更快地構建。他們充分利用可用的開原始碼和複雜的雲服務,並將平凡的任務解除安裝到自動化測試和其他工具上,這樣他們就可以專注於創造性解決問題的工作。他們透過確定關鍵功能的優先順序並減少不重要的工作,快速測試使用者的不同想法。這是經典著作“ 神話人月 ” 的核心論點1:總的來說,增加更多的軟體工程師不會讓專案變得更快,只會讓它變大。

構建軟體不是為了避免失敗; 它是在戰略上儘快失敗,以獲得建立良好事物所需的資訊。

與普通工程師的大型團隊相比,規模較小的優秀工程師團隊也將建立更少的錯誤和安全問題。與撰寫論文類似,作者越多,編碼風格,假設和怪癖就越多,在最終的複合材料產品中進行協調,從而為可能出現的問題提供更大的表面積。相比之下,由較小的優秀工程師團隊構建的系統將更加簡潔,連貫,並且更好地被其建立者理解。沒有簡單性就無法獲得安全性,簡單性很少是大規模協作的結果。
工程工作越協作,工程師就越需要。工程師程式碼中的問題不僅影響他的工作,也影響他的同事的工作。在大型專案中,糟糕的工程師最終會為彼此創造更多的工作,因為錯誤和糟糕的設計選擇會產生大量問題。大型專案需要建立在可靠的程式碼模組上,並採用有效的設計,並且具有非常明確的假設。您的工程師越好,系統在自身重量崩潰之前就越大。這就是為什麼最成功的科技公司儘管規模龐大但堅持要求最好的人才。系統複雜性的硬限制不是工程工作量,而是質量。

結論
良好的軟體開發始於清楚地瞭解您想要解決的問題。這使您可以測試許多可能的解決方案,並採用一種好的方法。透過重用正確的開原始碼和雲服務,加速開發,允許立即訪問已建立的軟體系統和複雜的新技術。開發週期在探索和整合之間交替,快速而混亂地進行新的想法,然後集中和簡化以保持複雜性的可管理性。隨著專案的進展,它將逐漸受到更多人群的測試,以消除日益罕見的問題。啟動是指真正的工作需要一個優秀的開發團隊:應該構建多層自動化系統來快速處理問題並防止對實際使用者造成傷害。


HN評論:
1. 軟體不僅僅是編寫程式碼而更是開發知識,管理層在團隊之間傳遞任務,從不關注知識和知識轉移,我遇到了更多問題。令人驚訝的是,作為一名軟體工程師,在18年多的時間裡,我已經看過很多次了。團隊將運作良好,然後該機構試圖改變。通常他們會試圖透過在研發上投入資金來開闢“創新”,基本上是為了增長而增加體積。然後你有很多團隊,溝通變得非常具有挑戰性,所以他們就會發展出某種“任務管理”層。管理層從不瞭解誰實際上知道了什麼,只是跟蹤他們擁有多少“理論頻寬”以及建立功能的願望清單。然後crapware真正開始流動。然後我感到無聊,繼續前進到下一個地方。

2. “更喜歡工作程式碼而非綜合文件”並不意味著“不做文件”。
文件是必不可少的 如何工作是一件重要的事情。理想情況下,它應該在版本控制中並從程式碼生成,因為它不太可能過時。它仍有問題(當程式碼和文件不一致時你會怎麼做?哪個是正確的?)
我用戰略DDD修復它 - 我至少開發了一種“普遍存在的語言”(或UL):我會讓其他人與我一起制定明確的術語,並確保在使用者故事中始終如一地使用它並在程式碼庫中。這是賭注。

然後,我會在我正在工作的環境中發生事件並開始開發高階文件。
即使在這一點上,系統之間的關係也會出現,你可以圍繞事物繪製圓圈並命名它們(域,上下文),並且UL會更好一些。此時,您可以開始考慮使用UL以及域和上下文的語言來描述您的一些服務。

到那時,人們應該開始點選這樣可以讓生活變得更輕鬆 - 混淆更少,現在你們都在共同努力,以便對設計有一個共同的理解,DDD的重點在於設計和程式碼的匹配

 

相關文章