← SEARCHABLE ARCHIVE
Java · 2026-08-12

Java 從基礎到精通 — 第 10 講

使用層和測試創建可維護的應用程式

INTERACTIVE READING MODE →

該部落格上撰寫的文章是出於教學目的而創建的。 另外,文章中的資訊可能不正確,請謹慎。

隨著程式的發展,變化傳播的程度變得比類別的數量更重要。 讓我們透過劃分規則、儲存和螢幕邊界並使行為可測試來結束我們的 Java 系列。

責任層次

public final class OrderService {
    private final ItemRepository repository;

    public OrderService(ItemRepository repository) {
        this.repository = repository;
    }

    public OrderResult buy(int itemId, int gold) {
        Item item = repository.find(itemId)
            .orElseThrow(() -> new ItemNotFoundException(itemId));

        if (gold < item.getPrice()) {
            return OrderResult.notEnoughGold();
        }

        return OrderResult.success(item, gold - item.getPrice());
    }
}

本服務負責購買規則,並不直接了解資料庫或HTTP實作細節。 控制器或螢幕將輸入傳遞給服務並呈現結果。

將依賴關係置於外部

public interface ItemRepository {
    Optional<Item> find(int id);
}

ItemRepository repository = new FileItemRepository(path);
OrderService service = new OrderService(repository);

如果在建構函數之外選擇特定存儲,測試可以用記憶體實現替換它。 介面並不是每個類別的裝飾,而是放置在外部技術變化的邊界。

試運行

@Test
void purchaseKeepsRemainingGold() {
    ItemRepository repository = new MemoryItemRepository(
        new Item(10, "Potion", 30)
    );
    OrderService service = new OrderService(repository);

    OrderResult result = service.buy(10, 100);

    assertEquals(70, result.getRemainingGold());
}

此測試檢查外部可見的規則而不是內部方法呼叫順序。 即使您清理了實現,您也可以查看相同的合約是否適用於相同的輸入。

專案工具

Gradle 或 Maven 將編譯、測試、函式庫版本控制並打包成可重複的指令。 將建置檔案和測試放在儲存庫中,以便專案不僅僅在開發環境中運行。

一個好的 Java 結構並不是有很多層次結構的。 它是一種結構,其中改變狀態、外部資源和並發任務的生命週期的規則是明確的,並且可以在小單元中進行驗證。