資深架構師的經驗分享——軟體專案開發和決策

認真期待發表於2018-05-12

這篇文章是關於什麼的

參與專案決策的人必須意識到他們的決定對專案的成功和成本以及時間和金錢的影響。

對於我20多年的軟體開發經驗和10多年的諮詢工作,我作為架構師或開發人員參與了許多專案 - 其中大多數成功,有些失敗,但每個專案(無論成功與否)都涉及好的和不好的決策由各種人製作。

本文的目的是通過提倡根據我的經驗做出的決定以及避免錯誤的決策來為專案成功奠定基礎。

總的來說,我擁有C ++,Java,C#和JavaScript的經驗,但在過去的10年中,我一直主要致力於C#桌面應用程式。儘管如此,這裡提出的許多想法都具有一般性。當我討論一個C#桌面應用程式時,我明確地陳述它。

軟體開發始終存在一個“政治元件” - 本文不涉及這一點。本文的目的是提供建議,以最大限度地提高客戶滿意度,同時最大限度地減少支出。

專案開發主要指南

在這裡,我介紹了軟體開發的兩個主要準則,這將在文章中進一步詳細描述。

  1. 在軟體開發主題上有很多書籍,文章和更多的廣告垃圾。用一粒鹽吧!如果你讀的東西與常識衝突 - 選擇常識。

  2. 在公司,專案或個人層面,需求的傳播(特別是API需求)應該從使用它的人(客戶)流向構建它的人,而不是相反。通過客戶端,我也指同一專案中使用其他人構建的軟體的開發人員。這個非常重要的規則常常被忽視,不利於專案的成功。

在專案的開始

在一個專案的開始階段就要做出一些重要的決定。理論上,在專案開始時做出的錯誤決策可以稍後糾正。然而,錯誤的決定浪費的金錢或時間越多,後來糾正的可能性越小,因為糾正它們會引發能力問題。

選擇一種語言

資深架構師的經驗分享——軟體專案開發和決策

對於一門語言,我強烈建議不要使用C ++(除非你正在構建一些非常高效能的演算法,因為它的編譯時間很慢,因此一秒鐘的分裂至關重要)。每個軟體開發(如果正確完成)都涉及很多原型設計,並重新啟動應用程式或為應用程式執行測試。程式碼更改後的每次新執行都涉及編譯。C ++模板的構建方式是在編譯時必須生成程式碼,這樣C ++通常編譯起來非常慢。編譯速度緩慢將導致原型設計速度緩慢,開發速度相應緩慢。沒有模板,C ++沒有現代強型別語言那麼強大。

而且,Java和C#擁有許多內建於該語言的標準庫,而C ++則依賴於第三方庫。

最佳團隊規模

資深架構師的經驗分享——軟體專案開發和決策

在我的經驗中,較小的團隊可以更快地生成更好的軟 例如,對於桌面三層專案,我會推薦一個3人團隊 - 每個層級一個人+一個建築師+ 1-3個裁員。

我最成功的專案正是由3-7名成員組成的團隊。我參與過的最不成功的專案之一是擁有20多名成員的團隊,幾年內無法實現幾個月內小型專案將實現的目標。

Scrum或不Scrum

資深架構師的經驗分享——軟體專案開發和決策

毫無疑問 - 對Scrum來說!敏捷/ Scrum可能並不完美,但它比替代品更好。然而,Scrum的某些方面並不有效(我認為它們不應該成為過程的一部分,儘管大多數敏捷教科書都會提到它們)。以下是scrum的正面和負面特徵列表。我的建議是:避免使用負面特徵。

Scrum的積極

  1. 通常,在專案開始時,客戶本身可能不清楚他們需要什麼。它需要很多迭代(包括客戶和開發人員的錯誤)讓客戶弄清楚需要構建什麼,以及開發人員如何構建它。Scrum的迭代方法最適合這種正規化。

  2. 在scrum之下,開發人員可以估計自己需要多長時間才能實現某個功能 - 他們通常可以做得比管理人員好得多。

  3. 每日更新對經理和開發人員都有益。雙方都可以更好地瞭解專案的位置。此外,對於開發者來說,這是一個與他人分享他們一直在努力工作的機會,以便了解他人正在做什麼,並且一般來說,在程式設計時可以鍛鍊大腦的非程式設計部分部分休息一下。

  4. Scrum會議結束後,包括演示和計劃在內,也會因日常會議的原因而受益,但規模較大。

Scrum的負面影響

  1. 一些Scrum版本倡導只跟蹤整個團隊的表現 - 不考慮個人開發者的貢獻。雖然團隊績效非常重要,但認識個人努力仍然很重要。

  2. 在Scrum結束時召開了會議,人們捶胸說出了什麼問題 - 越多越好。我從來沒有看到從他們身上出現任何好東西。發生問題時,應由開發人員解決。更嚴重的問題應該升級到建築師/經理,有時候應該改變專案程式。

對等程式設計

資深架構師的經驗分享——軟體專案開發和決策

除非是短期的,並且由兩個願意合作伙伴完全自願地分享知識,否則永遠不會看到任何好的同伴節目。

我練習非常積極,快速,以結果為導向的程式設計 - 觀看別人的節目讓我想睡覺。我認識的每個人都被迫做同儕程式設計,分享我對它的看法。

選擇軟體包和第三方元件

你應該非常小心選擇3 次黨庫-你應該懷疑華而不實的演示和廣告。選擇一個3 次方包(無論是開源還是需要付出的東西),只有當以下條件之一是true

  1. 這是一個眾所周知的產品 - 如MS Visual Studio,Oracle DB,MS SQL Server,Telerik或DevExpress控制元件 - 擁有數千種證詞

  2. 您的開發人員將直接使用該軟體,並在合理的時間內對該軟體進行試驗,至少兩週,並且使用起來非常舒適。

請記住,您為軟體包支付的金額越多 - 之後將更換或更換副本越困難,因為您花錢的人會希望確保這筆錢不會被浪費。

請記住,偉大的公司仍然可以有糟糕的產品。我多年前就有一個團隊對Oracle的Stellent軟體產生了負面影響 - 他們花費了大約25萬美元!對於甲骨文而言,他們當時剛剛購買了Stellent,因此它完全是在Oracle之外開發的。

此外,還記得那花了一個月研究3 個在一開始方元件可以從字面上拯救你年後。

第三方組成部分的一些具體建議

本部分針對MS桌面系統。

UI控制元件的包

對於WPF前端,我推薦以下軟體包:

  1. Telerik - 用WPF概念構建而成,易於修改和學習。

  2. DevExpress - 不需要 WPF(在我看來),所以定製起來不那麼容易,但仍然靈活而且速度很快。它具有Telerik沒有的一些控制元件,包括允許使用者在執行時組裝WPF檢視和地理地圖控制元件的設計器控制元件。

我對Xceed瞭解不多,但從我聽到的情況來看,它的使用也相當不錯。

我會警告反對Syncfusion - 至少幾年前,它建立與WPF意識形態相反。

我會推薦反對Infragistics - 它具有最開箱即用的功能,但根據我的經驗,這很難定製,而在WPF中,定製是遊戲的名稱!

所有上述WPF軟體包在製圖時都會遇到效能問題。我與之合作的WPF Chart軟體包,我強烈建議使用SciChart。

無論您選擇何種軟體包 - 選擇包含下載原始碼許可權的許可證。每當我使用Telerik或DevExpress時,我都必須研究他們的程式碼,以便能夠產生我的客戶所期望的效果。

IoC容器

大多數體面的規模專案都應該包含控制的倒置,以便為專案構建擴充套件點或便於交換實際測試實現的實現(例如,當涉及到對後端測試前端功能時)。

大多數情況下,我使用的MEF2有點複雜,但總是適合專案的目的。

我聽到很多Ninject的正面評論(儘管我自己從未使用過)。

我正在開發Roxy IoC容器。它仍在進行中,特別是在IoC方面,所以我現在不能推薦它。希望我能在幾周內推薦它。

測試框架

不管怎樣,Xunit是我所知道的最好的測試框架,我極力推薦它。這是免費的。它允許使用各種基於屬性的輸入來執行相同的測試。在其他框架中,您必須為每個輸入組合編寫單獨的程式碼。

中間層

在MS宇宙中,我會建議使用MVC控制器或WebApi或WCF構建自定義中間層。我也喜歡在中間層使用ADO Entity Framework。

WCF比ASP中間層解決方案更復雜,更強大。通常,ASP中間層對於此目的來說已經足夠了,但對於更復雜的需求,比如使用TCP連線而不是HTTP,WCF很棒。

後端

對於體面大小的專案,我建議使用Oracle或MS SQL Server。根據我的經驗,最多不使用SQL資料庫作為快取機制與SQL資料庫一起使用,或者用於某些特殊操作,例如全域性搜尋。

專案工具

我使用了許多工具,下面是我推薦的工具:

對於原始碼控制,我推薦Git和Subversion; 都工作得很好,都是免費的 - 我的首選是Git。

作為需求/錯誤跟蹤系統,我推薦Atlassian Jira或Rally。兩者都是高度可配置,經過充分測試的解決方案。

為了構建,釋出和持續整合,我推薦Atlassian Bamboo。

請注意,當使用者數少於10時,Atlassian軟體非常便宜。對於這樣的團隊,每個產品的平均費率為每月10美元。

進步vs保守派

團隊中總有人渴望並願意學習新軟體和新軟體包(我就是其中之一),以及那些想要堅持熟悉的老軟體和舊軟體包的人。

以下是這些方法合理的一些例子。

進步是正確的

  1. 很久以前,由於縮短了編譯時間和原生包,從C ++切換到Java極大地提高了專案的生產力。

  2. 切換到WPF和C#絕對是一個偉大的決定 - WPF是最好的基於Windows的桌面開發包,而C#現在比Java更強大,並且不斷改進。

  3. 人們採用反應式擴充套件的速度很慢,但它絕對是一個很好的軟體包,可以用來構建過去非常複雜的事情。

  4. Roslyn是一款出色的C#編譯器,我相信它最終將使人們能夠實現自己的語言特性,同時提供完整的IDE支援。

當保守派是對的

在過去的10年中,微軟釋出了許多失敗的軟體包。(這教會我小心)。

  1. 我對Silverlight仍然非常痛苦。我認為這是一個偉大的web開發包。我敢打賭Silverlight(儘管我明白它是微軟的一種慈善行為,因為它破壞了自己的平臺),我輸了。

  2. Windows RT,曾經被MS積極推廣的多個Windows Phone平臺失敗。(我已經更聰明瞭,從一開始我就感覺不太好)

關於預測包裹何時失敗或成功的一些想法

恐怕以100%確定性來預測幾乎是不可能的。

WPF是一個很好的包,我從第一眼就愛上了它的概念(之前我有過很多類似的想法)。

Silverlight也是由MS完全維護的一個很好的軟體包,當MS決定他們不再需要時,它基本上已經死亡。

Windows RT是一個翻版,我覺得它從一開始就會成為一個翻版,因為他們偏離了.NET並試圖進入本地。

我猜的經驗法則是:

  1. 當MS釋出一款優秀的產品並在其背後放置一些肌肉時 - 產品就會蓬勃發展。

  2. 當MS釋出一款優秀的產品並停產時 - 產品就會死亡。

  3. 即使MS肌肉也無法挽救糟糕的產品。

我想在本小節中對有關新的MS軟體包的一些預測加以限制。

基於我掌握的有限資訊,我相信Xamarin擁有光榮的未來 - 它有望成為智慧手機和平板電腦程式設計的主要手段之一。

恐怕UWP不會飛,因為它只適用於Windows 10和Windows 10產品。您將無法在Windows 8或Windows 7上執行它,更不用說Linux或Mac。為什麼使用它,如果它只是WPF和WPF在任何Windows平臺上執行的蒼白陰影?

我以前錯了,我可能又錯了 - 時間會顯示。

在專案開始前或開始時進行原型設計

儘管Agile具有迭代性,事實上客戶可能只是對最終產品應該在一開始就應該有一個模糊的概念,但專案設計師在開始時至少想出了一個小原型是一個好習慣專案。

這樣的原型應該結合一些UI,中間層和資料庫功能以及基本的測試專案。應用程式的所有部分應該可操作並相互通訊,並且應該執行測試。

根據我的經驗,我建議在原型上花費2周到1個月的時間。只有在建築師要求的情況下,建築師才能在別人的幫助下親自完成。

該專案的其餘部分將涉及擴大原始原型。

除了作為參考的初始參考點之外,這樣的原型還可以讓管理人員和團隊確信他們做出的決定以及他們使用的第三方元件將實際達到最終目標。

3層架構

這是標準的3層體系結構模式:

資深架構師的經驗分享——軟體專案開發和決策

在圖中 - 雙面黑色箭頭表示從UI客戶端到中間層以及從中間層到資料庫的請求 - 響應連線。

單側紅色箭頭表示從實時饋送到中間層和客戶(訂閱它)的“熱”(實時)連線。此外,它還顯示一旦收到實時資料,它可能會記錄到資料庫中(從中間層到資料庫的紅色箭頭)。

中間層可以有快取記憶體,單個客戶端快取記憶體可以提高速度。通常,您快取您知道在特定時間段內不會更改的資料。當時間間隔過去後,您將資料強制從快取中移出或標記為“過時”,以便在下一次請求後重新整理資料。

重要說明:根據我的經驗,最好的中間層是沒有任何業務邏輯的層。業務邏輯應該駐留在資料庫和UI中。中間層應該是資料庫基本功能中高度可配置的通用閘道器,並且不應在每次擴充套件業務邏輯時都進行修改。我用C#和Java在我的生活中多次構建了這樣的中間層。

也許第二個最好的中間層是在新增新的業務邏輯時僅需要較小的和標準化的修改的層。我也曾多次與這樣的中間層合作過。

執行專案

客戶端 - 伺服器API要求傳播原則

多層開發的主要原則是客戶端應該比他實現它的API有更多的發言權(API應該由客戶端驅動)。

正如軟體的客戶(或客戶端代理,如產品經理)對最終產品的外觀應該有更多的說法,UI開發人員也應該對他從中間層使用的API有更大的發言權,後端。

我想清楚2點:

  1. 我並不是說UI開發人員完全確定了API。應該在請求者和實現者之間的討論中明確API - 有些事情可能不可能或很難實現。

  2. 伺服器的實現仍然取決於伺服器開發人員 - 我只談論客戶需要的公共API。

資深架構師的經驗分享——軟體專案開發和決策

UI開發人員和後端/中間層開發人員之間的關係應該與終端使用者和UI開發人員之間的關係完全相同

這個原則通常不被遵循。實際上,人們從後端和中間層開始開發,然後UI必須圍繞所有由此產生的API問題進行論述。

想象一下,UI開發人員會來到終端使用者,並告訴他們,即使他沒有與他們進行任何諮詢,他所建的東西也能滿足他們的需求。聽起來相當荒謬,但是UI開發人員不得不經常處理類似的情況,當後端開發人員告訴他們現在他們擁有他們所需要的所有東西,即使他們沒有與UI開發人員進行任何諮詢。

我的經驗一次又一次地證實了這個原則 - 需求,APIs甚至開發都應該從使用API的部分傳播到實現它的部分。這不僅適用於客戶端 - 伺服器部門,也適用於您自己編寫重要軟體的情況。你需要從軟體的目的開始,然後填寫'空格'。否則,如果你從'空白'開始,你可能會發現他們不太適合這個目的。

測試驅動開發的普及是對這種正規化的另一種證實。

建立API

在傳統的'瀑布'哲學中,建築師試圖在專案的一開始就建立很多介面,以便開發人員能夠為他們程式設計。從我的角度來看,這不是最好的方法 - 它把馬車放在了馬匹的前面。

在開始時應該建立很少的介面,並且架構師應該隨時準備修改它們,如果發現它們不符合目的。

應該在需要時建立介面 - 例如,只要有方法或類需要處理滿足某個介面但實現可能會有所不同的物件時。不要過於努力地預見,你需要一個介面 - 首先(當只需要一個實現時)程式設計到一個類,但是當出現這樣的需求時,準備將它改變為一個介面。

這在個人層面和建築師層面都是如此。敏捷的迭代特效能夠適應API修改。

建築師的角色

這將我帶入軟體架構師的角色。

團隊中的一位開發人員可以承擔建築師的角色(特別是在專案大小合理的情況下)。

這是軟體架構師應該承擔的任務:

  1. 概述釋出過程 - 將產品移至使用者或使用者代理。

  2. 隨時關注產品開發進度和產品需求變化。

  3. 在開始階段 - 如上所述構建產品的非常稀疏的骨架(原型)(包括初始測試專案)。

  4. 解決各種開發人員之間的軟體問題。

  5. 找出程式碼共同點並將它們分解成可供各種開發人員在各個地方使用的通用API。

最後一點也應該由各個開發人員為他們自己的程式碼實施,或者如果開發人員在多個開發人員領域中看到程式碼的共同性,他應該將其引入共同考慮範圍,並讓架構師決定是否需要分解通用性。

一般來說,程式碼中的共同點應該不斷重構,無論是由開發人員還是架構師。

有些人認為他們需要提前找出並排除所有共同點。這不太可能。沒有人能夠做到這一點,就像沒有人能夠在專案開始時建立所有介面一樣。沒有理由花大量時間在一開始就考慮個人或架構師層面的共同點。在整個程式碼開發過程中,您將能夠找到要重構的程式碼。

我對建築師的建議是在整個多層架構中考慮資料形狀。在關聯式資料庫中 - 資料通常放置在規範化的表格中。也有一些記錄可能通過實時提要進行傳播。該級別沒有層次結構。然而,在UI方面,大多數記錄需要一些層次結構,以使用者想要的形狀顯示給使用者。我打算寫另一篇專門討論資料形狀和資料形狀轉換的文章。

建立一個團隊

根據我的經驗,工作場所以外的非工作相關活動是建立人與人之間信任並讓人感覺自己是團隊的好方法。以下是一些可行的活動:

  1. 清道夫狩獵

  2. 去一家餐館或喝一杯

  3. 足球比賽

  4. 保齡球

人的問題

以下是我在整個專案中觀察到的一些與人相關的問題

  1. 良好的領導能力和政治技能不足以執行一個專案。事實上,我看到專案失敗了,因為他們是由具有良好領導才能和政治技能的人領導的,但沒有任何軟體開發意識或有一些軟體開發意識,但不敢用它來反駁上司。

  2. 在會議上充滿自信地發言的人不一定知道軟體細節。重要的決定決不應該在一次會議上進行 - 只有在徹底的書面討論之後。

當沒有線索的人試圖接管某個領域的編碼或專案領導時,我觀察到了所謂的“庸醫”問題。他們可能具有良好的領導能力和演講技巧,其中一些甚至可能擁有技術技能,但在不同的領域。不應允許這些人在他們不知道的領域做出決定。

檢查一個人是否是某個領域的專家的一種方法是讓他建立一個概念驗證原型。如果他不能建立一個小概念證明,他不應該被允許接管這個專案。

我曾與一位表示製作原型的人合作需要太多時間,並且每個人都只是跟隨他的領導或者整個專案都將崩潰。這種“全部或全部”的方法肯定是一種尷尬的跡象 - 應該始終可以建立一個小概念證明。這個人不得不離開這個專案,沒有他,專案就成功了。

面試候選人

我在職業生涯中進行了許多面試,這裡有幾點我想分享一下:

  1. 切中要害 - 如果你想聘請Angular專家,不要問他關於WPF或SQL的許多問題。

  2. 例如,測試概念並不是細節,例如,測試人們對關聯式資料庫概念的理解總是很好的,但是(除非你專門僱用SQL專家),你不必在MS SQL Server中測試他對臨時表的瞭解。

  3. 有時候,記憶力好的人可以通過心靈學習很多資訊,然後用它來進行面試。這就是為什麼讓人們真正進入並進行簡單的編碼考試非常重要。這種方式總是可以看出該人是否擁有知識,或者在幾天之前他就簡單地擠滿了所有東西。

編寫,執行和測試要求

這個要求應該在開發者和訂購需求的人之間進行確定 - 它可能是終端使用者,也可能是團隊中的建築師或其他開發人員。由於開發人員的屁股已經上線,開發人員應該經常仔細閱讀這個要求,確保在開始工作之前不要留下任何碎片。

要求(或Jiras)通常應該考慮到單一功能。該功能可能是使用者功能,或者可能是終端使用者永遠不會看到的功能,例如某些重構; 無論哪種方式,大多數情況下,一個要求應該有一個功能。

一旦建立了需求,就不應該新增新的功能請求。它應該作為從請求者到質量保證的路線圖。如果事實證明開發人員實施了這項要求,但是要求是錯誤的或者不完整 - 這是請求者的錯,並且應該開啟一個新的Jira來覆蓋剩餘的。但是,如果開發人員沒有滿足這個要求 - 這是開發人員的錯,而且需要重新開放並重新分配給同一開發人員完成。

當涉及到UI開發時,也有一些小的,易於實現的需求(我稱之為'UI煩惱'),儘管它們可以接觸完全不同的功能,但它們都可以使用到單個Jira。你可以為他們開啟特殊的'尼特'吉拉,在'單一功能'的條件是沒有必要的。

​針對上面的技術我特意整理了一下,有很多技術不是靠幾句話能講清楚,所以乾脆找朋友錄製了一些視訊,很多問題其實答案很簡單,但是背後的思考和邏輯不簡單,要做到知其然還要知其所以然。如果想學習Java工程化、高效能及分散式、深入淺出。微服務、Spring,MyBatis,Netty原始碼分析的朋友可以加我的Java進階群:744642380,群裡有阿里大牛直播講解技術,以及Java大型網際網路技術的視訊免費分享給大家。

結論

在本文中,我以建築師和開發人員的長期經驗為基礎,提出了啟動和執行多層專案的建議。

我相信遵循這些建議可以大大降低專案成本的時間和金錢,並提高產品的價值。


相關文章