.NET 連結庫必須找出現有使用者穩定性與未來創新之間的平衡。 程式庫作者傾向於重構和反思代碼,直到程式碼完美無缺,但中斷現有的使用者會產生負面影響,尤其是對於低階程式庫來說。
項目類型和重大變更
.NET 社群如何使用函式庫會影響重大變更對終端使用者開發人員的影響。
低層和中層連結庫 ,例如串行化程式、HTML 剖析器、資料庫對象關係型對應程式或 Web 架構,受到重大變更的影響最大。
終端使用者開發人員會使用元件封裝來建置應用程式,並且其他程式庫將之作為 NuGet 套件的相依性。 例如,您要建置應用程式,並使用開放原始碼用戶端來呼叫 Web 服務。 用戶端使用的依賴的重大更新不是您可以修正的。 這是需要變更的開放原始碼用戶端,而且您無法控制它。 您必須尋找相容的連結庫版本,或將修正程式提交至用戶端連結庫,並等候新版本。 最壞的情況是,如果您想要使用兩個函式庫,而這兩個函式庫各自依賴於同一第三方函式庫的不同且互不相容的版本。
像是 UI 控制元件套件的高階程式庫對重大變更較不敏感。
高階函式庫會在終端使用者應用程式中直接參考。 如果發生重大變更,開發人員可以選擇更新為最新版本,或修改其應用程式以使用重大變更。
✔️ 想想您的函式庫將如何使用。 重大變更會對使用它的應用程式和連結庫產生什麼影響?
✔️ 避免在開發低階 .NET 函式庫時發生重大變更。
✔️ 請考慮將庫的大幅重寫發佈為新的 NuGet 套件。
中斷性變更的類型
重大變更屬於不同的類別,而且不會同樣有影響。
原始檔中斷性變更
來源中斷性變更不會影響程序執行,但會在下次重新編譯應用程式時造成編譯錯誤。 例如,新的多載方法可能會使先前明確的方法呼叫變得模棱兩可,或重新命名的參數會導致使用具名參數的呼叫者出錯。
public class Task
{
// Adding a type called Task could conflict with System.Threading.Tasks.Task at compilation
}
當開發人員重新編譯應用程式時,源碼中斷性變更才會造成危害,因此這是最不具干擾性的中斷性變更。 開發人員可以輕鬆地修復自己的損壞原始程式碼。
行為中斷性變更
行為改變是最常見的破壞性變更類型:幾乎任何行為改變都可能導致使用者的邏輯錯誤。 程式庫的變更,例如方法簽章、拋出的例外或輸入或輸出資料格式,都可能會對您的程式庫使用者造成負面影響。 如果用戶依賴先前錯誤的行為,即使是 Bug 修正也可以被視為中斷性變更。
新增功能和改善不良行為是件好事,但不小心,它可能會讓現有的使用者很難升級。 協助開發人員處理行為中斷性變更的其中一種方法,就是將其隱藏在設定後方。 設定可讓開發人員更新至最新版的程式庫,同時選擇接受或拒絕可能造成相容性問題的更動。 此策略可讓開發人員保持最新狀態,同時讓其耗用程式代碼隨著時間進行調整。
例如,ASP.NET Core MVC 具有 相容性版本 的概念,可修改 在 上 MvcOptions啟用和停用的功能。
✔️ 如果新功能會影響現有的使用者,請考慮預設將新功能關閉,並讓開發人員選擇使用設定加入功能。
如需 .NET API 中行為中斷性變更的詳細資訊,請參閱 .NET 行為變更相容性。
二進位中斷性變更
當您變更連結庫的公用 API 時,會發生二進位重大變更,因此針對舊版連結庫編譯的元件將無法再呼叫 API。 例如,藉由新增參數來變更方法的參數列表,會導致針對舊版程式庫編譯的組件拋出MissingMethodException。
二進位中斷變更也可以中斷 整個元件。 使用 AssemblyName 重新命名元件將會變更元件的身分識別,如同新增、移除或變更元件的強式命名密鑰一樣。 組件身份的變更將會中斷所有使用它的已編譯代碼。
❌ 請勿變更元件名稱。
❌ 請勿新增、移除或變更強式命名金鑰。
✔️ 請考慮使用抽象基類,而不是介面。
將任何項目新增至介面將導致實作該介面的現有類型出現問題。 抽象基類可讓您新增預設虛擬實作。
✔️ 請考慮將 ObsoleteAttribute 放在您想要移除的類型和成員上。 屬性應該有更新程序代碼的指示,不再使用過時的 API。
使用 ObsoleteAttribute 呼叫型別和方法的程式代碼會產生建置警告,其中包含提供給 屬性的訊息。 警告會讓使用過時 API 介面的人員有時間進行遷移,以便在過時的 API 被移除時,大多數人已經不再使用它。
public class Document
{
[Obsolete("LoadDocument(string) is obsolete. Use LoadDocument(Uri) instead.")]
public static Document LoadDocument(string uri)
{
return LoadDocument(new Uri(uri));
}
public static Document LoadDocument(Uri uri)
{
// Load the document
}
}
✔️ 請考慮在低層和中層函式庫中無限期地保留具有 ObsoleteAttribute 的類型和方法。
拿掉 API 是二進位重大變更。 如果維護過時的類型和方法成本較低,而且不會為您的程式庫新增大量技術債務,請考慮保留它們。 不移除類型和方法有助於避免上述最壞的情況。
如需有關 .NET API 變更哪些項目中斷二進位相容性的詳細資訊,請參閱 .NET 公用合約相容性。