最佳實踐(3):Windows應用開發

Nikkko發表於2015-04-06

這是Futurice公司的Windows 8.x 和 Windows Phone 8.x 應用開發者的經驗教訓。通過參考這些指南能夠避免重複造輪子。如果你對iOS或者Android開發感興趣,一定也要去看一下他們的《iOS開發最佳實踐》和《安卓開發最佳實踐》。

歡迎反饋,但是在這之前請先閱讀這個指南


C# 開發一般都用 Visual Studio

使用Visual Studio Pro或更好的版本

Visual Studio實際上是用來開發Windows應用的IDE。免費的精簡版本對於入門來說不錯,但是缺少一些重要的特性,比如支援額外的擴充套件。專業版本能通過一次安裝提供所有不同專案型別的支援、額外開發特性、支援擴充套件、和一些支援團隊合作的特性。特惠版主要新增了一些優於普通單元測試的內建測試支援,而旗艦版新增了增強的除錯、架構和程式碼分析工具。

使用Productivity Power工具(2013)

來自微軟的一個免費 VS 開發擴充套件。它缺少一些同類產品——比如JustCode或者ReSharper——擁有的特性。不過這似乎不會使IDE的效率變低。

使用NuGet

Nuget是微軟的一個包管理工具。在新的Visual Studio中預裝了一個叫NuGet Package Manager的擴充套件。注意:當不需要在解決方案中包含原始碼時,請把它作為外部引用。

使用Package Restore

根據NuGet的文件:

自從NuGet2.7開始,當Build開始時,NuGet 的Visual Studio擴充套件整合進了Visual Studio 的Build事件和修復失去的包的過程中。

這種包修復方法有若干優點:

  • 不需要專門為你的工程或解決方案去啟用它。Visual Studio 在你的工程在被構建之前就會自動下載缺失的包,並且團隊成員不需要了解NuGet Package Restore的詳細情況。
  • 在你的專案或解決方案中不需要額外的目錄或檔案。
  • Visual Studio 呼叫 MSBuild 之前前,會恢復(缺失的)包。這可以讓通過目標/屬性檔案匯入的擴充套件 MSBuild 的包在 MSBuild 啟動之前恢復,以確保成功構建(build)。
  • 與用Visual Studio建立的ASP.NET 網站專案相容。

如果你點選了Visual Studio中的”Enable NuGet Package Restore”按鈕後你會使用舊的包修復工具。如果是這樣,你應該遷移至:NuGet docwith pictures.

將程式碼分成小段的方法,以提升堆疊跟蹤和堆疊呼叫檢視的效能

為了可重用性,程式碼通常被分割成小段的方法塊。然而即使不打算重用它們,也應該將方法拆分。方法名記載了程式碼包含的內容。當除錯時這給予你更多關於呼叫堆疊資訊,和更好的異常的堆疊跟蹤資訊。堆疊跟蹤更多應用到釋出版的程式中,在那裡面程式碼行的資訊已經丟失了。

在跟蹤的時候使用caller information屬性

當為任意的引數新增CallerMemberName、CallerFilePath 或者 CallerLineNumber屬性的時候,這個引數的相關資訊將被設定成呼叫者的檔案路徑、行號和成員名。這些值將在編譯時被設定進方法呼叫中,不會影響執行效率,也不會被混淆的程式碼所影響。

來自MSDN的例子:

你的HTTP應用使用HTTPClient

在各種各樣的可用的HTTP API中,HttpClient是一個新的支援 非同步/等待 和自動請求解壓的API。通過 非同步/等待的方式來使用它來保持程式碼的簡潔易讀。

瞭解計時器

這裡有為了不同目的的不同的計時器。比如WinRT的DispatcherTimer(定時器),WP Silverlight 的DispatcherTimer ThreadPoolTimer。另外還有Observable.Timer,Task.Delay。最後但不是最重要的Thread.Sleep

返回一個IEnumerable的時候,用yield

而不是寫一些像下面這樣的東西:

而是要這樣寫:

如果沒有yield返回被呼叫,它會自動返回一些空的IEnumreable。當你想獲取一個IEnumreable的時候這樣做會避免一些空引用異常。當且僅當可能的迭代器需要的時候,這個yield方法才會執行。比如,下面的語句僅僅建立了一個Galaxy例項,避免了一些不必要的執行過程。

LINQ查詢顯式轉換成集合,以避免不必要的重複運算

可能首先需要了解的關於LINQ的事是,每次訪問查詢結果的時候,它建立的查詢都會被執行。有時候你的確想要這樣。然而,你經常僅僅想要執行這個查詢一次,多次訪問被查詢的結果。為了避免不必要的重複計算以及查詢結果變化帶來的錯誤,請使用ToArray、ToList等擴充套件方法來執行查詢並將結果儲存到集合中。

所以不要這樣做:

而要這樣做:

不要被IObservable超時蠱惑(這個IObservable資源,IObservable firstTimeout, Func> timeoutDurationSelector

現在,這是一個介面,所以不同的實現呈現的結果也不一樣。以下的應用都至少是相對於在System.Reactive.Linq.Observable中的實現而言的.

很容易想到應該這樣做:

然而,這樣很容易就超時了.所以正確的使用方法是:

所以,當傳遞的IObservable完成時會發生超時,而不是在傳遞的TimeSpan的持續時間過了以後超時.

Windows App 開發

不要給你的自定義控制元件的名字硬編碼

當編寫自定義或使用者控制元件的時候,不要給控制元件的名字屬性設定一個固定的值.在XAML中這意味著為根節點設定x:Name屬性。

每一個在PresentationFrameworkCollection中的從屬物件必須有一個獨特的名字,並且如果最終在同一個PresentationFrameworkCollection中新增了兩個有同樣名字的控制元件,你會遇到這樣的情況:

當你不硬編碼的時候,框架(framework)會為每一個例項生成一個專屬的名字。

當將屬於一個依賴物件的多個依賴屬性繫結到一起時要格外小心

將會有兩個可能的意外情況:

順序問題

案例:12

捆綁到DataContext改變了預設的捆綁資源

比如,以下的XAML在MyAdViewModel中而不是在MyPageViewModel尋找AdVisiblity。改變捆綁的順序沒有任何影響。(但是會首先在MyPageViewModel中尋找,然後在MyAdViewModel中尋找)。

會發生這種事情是因為”{Binding PropertyName}”是以下的簡寫:

“{Binding Path=DataContext.PropertyName, Source={RelativeSource Self}”

事實上它將 DataContext中的自己的屬性,和在這個物件中的PropertyName屬性繫結在了一起。當DataContext沒有設定時,它會自動從父類繼承。

使用CallerMemberName屬性或者一個LINQ表示式來幫助通知屬性的改變

很多的MVVM框架已經在檢視模型中提醒屬性的改變。不過不要用其中的任何一種,你應該為自己建立一個基礎檢視模型類。但是應當注意建立一個LINQ表示式所造成的效能開銷。

比如:

如果你在ViewModels中使用Rx,也請使用ReactiveProperties ReactiveCommands

如果你還沒有用過能方便地從XAML中繫結互動程式碼的庫的話,去搜尋一下ReactiveProperty 和 ReactiveCommand 幫助類。或者直接在面選用一個由Tomasz Polanski建立的 reactive工具庫。

相關文章