design

🪵 組件(Assembly)

在 .NET 中,「組件(Assembly)」是一個可以被執行或被載入的最小單位,通常就是一個 .dll(類別庫).exe(應用程式執行檔)

Dynamic Link Library(動態連結程式庫)。它是一個 二進位檔(binary file),副檔名是 .dll。
裡面存放的是「程式碼 + 資源」,但不能自己執行。要靠其他程式(例如 exe)來「載入」它,才能使用裡面的功能。簡單說,DLL 就像一本工具書,裡面有很多函式與類別,你可以引用它,但它不會自己動。

在 Windows 下,DLL/EXE 都遵循 PE(Portable Executable)格式。.NET 世界裡,DLL 裡面會多一層 IL(Intermediate Language,中間語言) 和 Metadata(中繼資料)。也就是說,.NET 的 DLL 並不是直接的 CPU 機器碼,而是「IL + Metadata」組合。

而 Visual Studio 的「Project」編譯出來之後,通常就是一個組件(Assembly)📦

例如像這樣

專案名稱(Project) 編譯後的組件(Assembly)
MyApp MyApp.exe
MyApp.Core MyApp.Core.dll
MyApp.Infrastructure MyApp.Infrastructure.dll

internal 的意思是:這個類別或成員只能在同一個組件(Assembly)裡被使用,外部組件無法直接存取。
換句話說,它就是「只給自己家人用的成員,不對外開放」。



p.s. binary file 指得是裡面的 0/1 沒有直接對應到文字,而是依照某種格式定義,給「程式」來解讀,它不是人類可以直接讀的文字,而是 給作業系統 / CLR 用的結構化資料。



🪵 internal 想解決的問題

這其實與「封裝(Encapsulation)」和「模組化(Modularity)」密切相關。本質上 internal 解決的是:「避免內部細節被外部依賴或誤用」。

  • 外部誤用:其他開發者可能把你只打算內部用的類別,拿來當正式 API。
  • 依賴綁死:別人對內部實作產生依賴,導致你無法隨意修改。改了可能會壞一堆外部程式,不改又會變成技術債。
  • 測試污染:你原本只打算給測試用的類別(例如 Mock、Stub),可能被誤以為是正式功能。

所以 internal 就像是在說:「這東西是內部細節,我不保證它的穩定性,也不打算提供給外部使用。」它為你劃出一個「自由調整的區域」,讓你能靈活修改內部設計,而不用擔心牽連外部使用者。



🪵 結語

internal 的存在並不是限制,而是一種保護。它讓設計者能清楚表達:「哪些東西是 API(保證穩定),哪些只是內部零件(隨時可能調整)」。當你合理運用 internal,就能保持專案的邏輯清晰、邊界明確,讓程式碼既有彈性又不失秩序。這是一種軟體設計者的自我約束,也是一種給使用者的承諾。

🪵 情境

Helper 或 Utility 類別

1
2
3
4
internal class PasswordHasher
{
public string Hash(string password) => ...
}

這類工具類別通常只是專案內部的實作細節。如果真的需要跨組件共用,就應該另外建立一個獨立的 Utility/Shared 專案,並把需要公開的工具類別設為 public。internal 強調了責任劃分:哪些是內部使用,哪些是跨專案共用。

大型專案結構的流程物件

假設你有一個大型專案結構如下:

  • MyApp.Domain(商業邏輯)
  • MyApp.Application(應用邏輯)
  • MyApp.Infrastructure(第三方套件實作)
  • MyApp.API(Web API)

你可能會在 Application 裡面有一些 handler 類別,只給內部 Command 用:

1
2
3
4
internal class CreateOrderFlowHandler
{
public void Execute(CreateOrderInput input) { ... }
}

測試專用 Stub 或 Mock class

有時候為了單元測試,你會做一些模擬類別或資料,這些不應該給正式程式使用:

1
2
3
4
internal class MockPaymentGateway : IPaymentGateway
{
public void Pay() => Console.WriteLine("Fake payment done.");
}

讓測試專案可以存取 internal

1
2
// AssemblyInfo.cs 加這一行
[assembly: InternalsVisibleTo("MyApp.Tests")]

Factory 或 Builder 的內部部件

1
2
3
4
internal class OrderItemValidator
{
public bool Validate(OrderItem item) { ... }
}

你用這個 Validator 來組成一個更大的處理流程,這個小部件 class 是內部結構之一。