設計指引範本
Prompt 目標
指導 AI 進行軟體設計,建立符合設計原則、易於維護且可擴展的軟體設計。
角色設定
你是一位資深軟體設計師,具備豐富的軟體設計經驗,熟悉設計模式、SOLID 原則和軟體工程最佳實務。
任務描述
請協助我完成 {專案名稱} 的軟體設計工作。
專案設計背景
- 專案名稱: {填入專案名稱}
- 設計範圍: {填入設計範圍,如:核心模組、特定功能}
- 技術棧: {填入使用的技術棧}
- 設計約束: {填入設計限制和約束}
- 品質要求: {填入品質屬性要求}
設計要求
請按照以下結構進行設計:
1. 領域建模
- 核心領域識別
- 實體和值物件設計
- 聚合設計
- 領域服務設計
2. 架構設計
- 分層架構設計
- 模組劃分
- 依賴關係設計
- 介面設計
3. 詳細設計
- 類別設計
- 方法設計
- 資料結構設計
- 演算法設計
4. 設計模式應用
- 創建型模式
- 結構型模式
- 行為型模式
- 架構模式
5. 設計原則遵循
- SOLID 原則
- DRY 原則
- KISS 原則
- YAGNI 原則
輸出格式
# {專案名稱} 軟體設計文件
## 1. 設計概述
### 1.1 設計目標
**主要目標:**
- {目標1}
- {目標2}
- {目標3}
**品質屬性:**
- **可維護性:** {可維護性要求}
- **可擴展性:** {可擴展性要求}
- **可重用性:** {可重用性要求}
- **可測試性:** {可測試性要求}
### 1.2 設計約束
**技術約束:**
- 程式語言: {程式語言}
- 框架: {使用的框架}
- 資料庫: {資料庫類型}
- 部署環境: {部署環境}
**業務約束:**
- 效能要求: {效能指標}
- 安全要求: {安全等級}
- 相容性要求: {相容性需求}
## 2. 領域建模
### 2.1 領域識別
#### 核心領域 (Core Domain)
**領域名稱:** {核心業務領域}
**複雜度:** 高
**業務價值:** 高
**描述:** {領域描述}
**主要概念:**
- {概念1}: {概念描述}
- {概念2}: {概念描述}
- {概念3}: {概念描述}
#### 支援領域 (Supporting Domain)
**領域名稱:** {支援領域}
**複雜度:** 中
**業務價值:** 中
**描述:** {領域描述}
#### 通用領域 (Generic Domain)
**領域名稱:** {通用領域}
**複雜度:** 低
**業務價值:** 低
**解決方案:** {現成解決方案或第三方服務}
### 2.2 實體設計 (Entity)
#### 實體: {實體名稱}
```java
/**
* {實體描述}
* 不變量: {業務規則和約束}
*/
public class {實體名稱} {
// 唯一識別碼
private {ID類型} id;
// 業務屬性
private {屬性類型} {屬性名稱};
// 建構子
public {實體名稱}({參數列表}) {
// 驗證業務規則
validateBusinessRules();
this.{屬性} = {值};
}
// 業務方法
public {返回類型} {業務方法名稱}({參數列表}) {
// 業務邏輯實作
return {結果};
}
// 不變量驗證
private void validateBusinessRules() {
if ({條件}) {
throw new {例外類型}("{錯誤訊息}");
}
}
// equals 和 hashCode 基於 ID
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof {實體名稱})) return false;
{實體名稱} other = ({實體名稱}) obj;
return Objects.equals(id, other.id);
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}2.3 值物件設計 (Value Object)
值物件: {值物件名稱}
/**
* {值物件描述}
* 特性: 不可變、值相等、自驗證
*/
public final class {值物件名稱} {
private final {屬性類型} {屬性名稱};
public {值物件名稱}({參數類型} {參數名稱}) {
validate({參數名稱});
this.{屬性名稱} = {參數名稱};
}
public {屬性類型} get{屬性名稱}() {
return {屬性名稱};
}
private void validate({參數類型} value) {
if ({驗證條件}) {
throw new IllegalArgumentException("{錯誤訊息}");
}
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (!(obj instanceof {值物件名稱})) return false;
{值物件名稱} other = ({值物件名稱}) obj;
return Objects.equals({屬性名稱}, other.{屬性名稱});
}
@Override
public int hashCode() {
return Objects.hash({屬性名稱});
}
@Override
public String toString() {
return "{值物件名稱}{" + "{屬性名稱}=" + {屬性名稱} + '}';
}
}2.4 聚合設計 (Aggregate)
聚合: {聚合名稱}
/**
* {聚合描述}
* 聚合根: {聚合根實體}
* 邊界: {聚合邊界說明}
*/
public class {聚合名稱} {
// 聚合根
private {實體類型} {聚合根};
// 聚合內實體
private List<{實體類型}> {內部實體列表};
// 聚合建構
public {聚合名稱}({參數列表}) {
this.{聚合根} = new {實體類型}({參數});
this.{內部實體列表} = new ArrayList<>();
}
// 業務操作
public void {業務操作名稱}({參數列表}) {
// 驗證聚合不變量
validateAggregateInvariants();
// 執行業務邏輯
{聚合根}.{業務方法}({參數});
// 發布領域事件
publishDomainEvent(new {事件類型}({事件資料}));
}
// 聚合不變量驗證
private void validateAggregateInvariants() {
if ({不變量條件}) {
throw new {例外類型}("{違反不變量訊息}");
}
}
// 取得聚合根 ID
public {ID類型} getId() {
return {聚合根}.getId();
}
}2.5 領域服務設計
領域服務: {服務名稱}
/**
* {服務描述}
* 使用場景: {使用場景說明}
*/
@DomainService
public class {服務名稱} {
private final {依賴類型} {依賴名稱};
public {服務名稱}({依賴類型} {依賴名稱}) {
this.{依賴名稱} = {依賴名稱};
}
/**
* {業務操作描述}
* @param {參數} {參數描述}
* @return {返回值描述}
*/
public {返回類型} {業務操作}({參數列表}) {
// 前置條件檢查
validatePreconditions({參數});
// 業務邏輯執行
{返回類型} result = executeBusinessLogic({參數});
// 後置條件檢查
validatePostconditions(result);
return result;
}
}3. 架構設計
3.1 分層架構
四層架構設計
┌─────────────────────────────────────┐
│ 展示層 (Presentation) │
├─────────────────────────────────────┤
│ 應用層 (Application) │
├─────────────────────────────────────┤
│ 領域層 (Domain) │
├─────────────────────────────────────┤
│ 基礎設施層 (Infrastructure) │
└─────────────────────────────────────┘展示層 (Presentation Layer)
職責:
- 處理使用者介面邏輯
- 請求路由和參數驗證
- 回應格式化
- 錯誤處理和回應
組件設計:
@RestController
@RequestMapping("/api/v1/{資源}")
public class {資源}Controller {
private final {應用服務} {服務};
@GetMapping("/{id}")
public ResponseEntity<{DTO}> get{資源}(@PathVariable String id) {
{DTO} result = {服務}.get{資源}(id);
return ResponseEntity.ok(result);
}
@PostMapping
public ResponseEntity<{DTO}> create{資源}(@Valid @RequestBody {CreateDTO} request) {
{DTO} result = {服務}.create{資源}(request);
return ResponseEntity.status(HttpStatus.CREATED).body(result);
}
}應用層 (Application Layer)
職責:
- 協調領域物件執行業務用例
- 管理事務邊界
- 安全檢查和授權
- 資料轉換和映射
組件設計:
@ApplicationService
@Transactional
public class {資源}ApplicationService {
private final {資源}Repository {資源儲存庫};
private final {領域服務} {領域服務};
private final {外部服務} {外部服務};
public {DTO} create{資源}({CreateDTO} request) {
// 1. 輸入驗證
validateInput(request);
// 2. 業務規則檢查
checkBusinessRules(request);
// 3. 建立領域物件
{聚合} {聚合實例} = {聚合}.create(request.to{聚合}());
// 4. 儲存聚合
{聚合實例} = {資源儲存庫}.save({聚合實例});
// 5. 發布整合事件
publishIntegrationEvent(new {事件}({聚合實例}.getId()));
// 6. 回傳結果
return {DTO}.from({聚合實例});
}
}領域層 (Domain Layer)
職責:
- 實作核心業務邏輯
- 定義業務規則和不變量
- 管理領域事件
- 提供領域服務
組件組織:
domain/
├── model/ # 領域模型
│ ├── {實體}.java
│ ├── {值物件}.java
│ └── {聚合}.java
├── service/ # 領域服務
│ └── {領域服務}.java
├── repository/ # 儲存庫介面
│ └── {儲存庫介面}.java
├── event/ # 領域事件
│ └── {領域事件}.java
└── exception/ # 領域例外
└── {領域例外}.java基礎設施層 (Infrastructure Layer)
職責:
- 實作技術關注點
- 提供持久化實作
- 外部服務整合
- 框架配置
組件設計:
@Repository
public class {資源}RepositoryImpl implements {資源}Repository {
private final {JPA實體}Repository jpaRepository;
private final {資源}Mapper mapper;
@Override
public {聚合} save({聚合} {聚合實例}) {
{JPA實體} entity = mapper.toEntity({聚合實例});
entity = jpaRepository.save(entity);
return mapper.toDomain(entity);
}
@Override
public Optional<{聚合}> findById({ID類型} id) {
return jpaRepository.findById(id)
.map(mapper::toDomain);
}
}3.2 模組劃分
模組結構設計
src/main/java/
├── {專案包名}/
│ ├── {核心模組}/ # 核心業務模組
│ │ ├── domain/
│ │ ├── application/
│ │ ├── infrastructure/
│ │ └── presentation/
│ ├── {支援模組}/ # 支援業務模組
│ │ ├── domain/
│ │ ├── application/
│ │ └── infrastructure/
│ ├── shared/ # 共用組件
│ │ ├── kernel/ # 共用核心
│ │ ├── infrastructure/ # 共用基礎設施
│ │ └── application/ # 共用應用服務
│ └── config/ # 配置類模組依賴規則
/**
* 模組依賴矩陣
* ✓ = 允許依賴
* ✗ = 禁止依賴
*/
// 核心模組 支援模組 共用模組
// 核心模組 ✗ ✗ ✓
// 支援模組 ✗ ✗ ✓
// 共用模組 ✗ ✗ ✗3.3 介面設計
介面隔離原則應用
// 細粒度介面設計
public interface {資源}Reader {
Optional<{資源}> findById({ID類型} id);
List<{資源}> findAll();
}
public interface {資源}Writer {
{資源} save({資源} {資源實例});
void delete({ID類型} id);
}
public interface {資源}Repository extends {資源}Reader, {資源}Writer {
// 複合介面,組合讀寫能力
}介面穩定性設計
@API(status = API.Status.STABLE)
public interface {穩定介面} {
// 穩定的公開 API,版本間保持相容
}
@API(status = API.Status.EXPERIMENTAL)
public interface {實驗性介面} {
// 實驗性 API,可能在未來版本變更
}
@API(status = API.Status.DEPRECATED)
public interface {已棄用介面} {
// 已棄用 API,將在未來版本移除
}4. 詳細設計
4.1 類別設計
類別設計原則
單一職責原則 (SRP):
// 良好設計 - 職責明確
public class {資源}Validator {
public ValidationResult validate({資源} {資源實例}) {
// 只負責驗證邏輯
}
}
public class {資源}Formatter {
public String format({資源} {資源實例}) {
// 只負責格式化
}
}開放封閉原則 (OCP):
// 抽象基類
public abstract class {處理器} {
public final {結果} process({輸入} input) {
{中間結果} intermediate = preProcess(input);
{結果} result = doProcess(intermediate);
return postProcess(result);
}
protected abstract {中間結果} preProcess({輸入} input);
protected abstract {結果} doProcess({中間結果} intermediate);
protected abstract {結果} postProcess({結果} result);
}
// 具體實作 - 擴展而非修改
public class {具體處理器} extends {處理器} {
// 實作抽象方法
}類別關係設計
// 組合優於繼承
public class {服務類} {
// 通過組合使用其他類的功能
private final {驗證器} validator;
private final {轉換器} converter;
private final {儲存庫} repository;
public {服務類}({驗證器} validator, {轉換器} converter, {儲存庫} repository) {
this.validator = validator;
this.converter = converter;
this.repository = repository;
}
public {結果} process({輸入} input) {
// 組合各組件完成功能
validator.validate(input);
{中間結果} converted = converter.convert(input);
return repository.save(converted);
}
}4.2 方法設計
方法簽名設計
/**
* 方法命名和參數設計指引
*/
public class {服務類} {
// 動詞+名詞命名,參數類型明確
public {返回類型} calculate{業務概念}({輸入類型} input, {配置類型} config) {
// 方法實作
}
// 布林方法使用 is/has/can 前綴
public boolean isValid({對象類型} object) {
return {驗證邏輯};
}
// 查詢方法使用 find/get 前綴
public Optional<{對象類型}> findBy{條件}({條件類型} criteria) {
return {查詢邏輯};
}
// 建議方法參數不超過3個,否則使用參數對象
public {結果} complexOperation({參數對象} parameters) {
// 複雜操作使用參數對象
}
}錯誤處理設計
public class {服務類} {
// 使用特定例外類型
public {結果} riskyOperation({輸入} input) throws {業務例外}, {技術例外} {
try {
// 前置條件檢查
validatePreconditions(input);
// 核心邏輯
{結果} result = performOperation(input);
// 後置條件檢查
validatePostconditions(result);
return result;
} catch ({特定例外} e) {
// 特定錯誤處理
throw new {業務例外}("業務錯誤描述", e);
} catch (Exception e) {
// 通用錯誤處理
throw new {技術例外}("系統錯誤", e);
}
}
}4.3 資料結構設計
不可變物件設計
public final class {不可變類} {
private final {屬性類型} {屬性1};
private final List<{元素類型}> {屬性2};
public {不可變類}({屬性類型} {屬性1}, List<{元素類型}> {屬性2}) {
this.{屬性1} = {屬性1};
this.{屬性2} = Collections.unmodifiableList(new ArrayList<>({屬性2}));
}
public {屬性類型} get{屬性1}() {
return {屬性1};
}
public List<{元素類型}> get{屬性2}() {
return {屬性2}; // 已經是不可變的
}
// Builder 模式用於複雜對象建構
public static class Builder {
private {屬性類型} {屬性1};
private List<{元素類型}> {屬性2} = new ArrayList<>();
public Builder {屬性1}({屬性類型} {屬性1}) {
this.{屬性1} = {屬性1};
return this;
}
public Builder add{元素類型}({元素類型} item) {
this.{屬性2}.add(item);
return this;
}
public {不可變類} build() {
return new {不可變類}({屬性1}, {屬性2});
}
}
}集合使用指引
public class {集合使用示例} {
// 優先使用介面類型
private final List<{元素}> items = new ArrayList<>();
private final Map<{鍵}, {值}> cache = new HashMap<>();
private final Set<{元素}> uniqueItems = new HashSet<>();
// 防禦性複製
public List<{元素}> getItems() {
return new ArrayList<>(items);
}
// 空集合處理
public List<{元素}> findItems({條件} criteria) {
List<{元素}> result = performSearch(criteria);
return result != null ? result : Collections.emptyList();
}
}5. 設計模式應用
5.1 創建型模式
工廠方法模式
// 抽象工廠
public abstract class {產品}Factory {
public {產品} create({配置} config) {
{產品} product = createProduct(config);
configureProduct(product, config);
return product;
}
protected abstract {產品} createProduct({配置} config);
private void configureProduct({產品} product, {配置} config) {
// 通用配置邏輯
}
}
// 具體工廠
public class {具體產品}Factory extends {產品}Factory {
@Override
protected {產品} createProduct({配置} config) {
return new {具體產品}(config);
}
}建造者模式
public class {複雜對象} {
private final {必要屬性} {屬性1};
private final {可選屬性} {屬性2};
private final {可選屬性} {屬性3};
private {複雜對象}(Builder builder) {
this.{屬性1} = builder.{屬性1};
this.{屬性2} = builder.{屬性2};
this.{屬性3} = builder.{屬性3};
}
public static class Builder {
// 必要參數
private final {必要屬性} {屬性1};
// 可選參數 - 初始化為預設值
private {可選屬性} {屬性2} = {預設值};
private {可選屬性} {屬性3} = {預設值};
public Builder({必要屬性} {屬性1}) {
this.{屬性1} = {屬性1};
}
public Builder {屬性2}({可選屬性} {屬性2}) {
this.{屬性2} = {屬性2};
return this;
}
public Builder {屬性3}({可選屬性} {屬性3}) {
this.{屬性3} = {屬性3};
return this;
}
public {複雜對象} build() {
return new {複雜對象}(this);
}
}
}5.2 結構型模式
介面卡模式
// 目標介面
public interface {目標介面} {
{結果} operation({輸入} input);
}
// 需要適配的類
public class {被適配類} {
public {不同結果} differentOperation({不同輸入} input) {
// 原有邏輯
}
}
// 介面卡
public class {介面卡} implements {目標介面} {
private final {被適配類} adaptee;
public {介面卡}({被適配類} adaptee) {
this.adaptee = adaptee;
}
@Override
public {結果} operation({輸入} input) {
// 轉換輸入格式
{不同輸入} adaptedInput = convertInput(input);
// 呼叫被適配類的方法
{不同結果} adaptedResult = adaptee.differentOperation(adaptedInput);
// 轉換輸出格式
return convertOutput(adaptedResult);
}
}裝飾者模式
// 基礎介面
public interface {組件} {
{結果} operation();
}
// 具體組件
public class {具體組件} implements {組件} {
@Override
public {結果} operation() {
// 基礎功能實作
}
}
// 抽象裝飾者
public abstract class {裝飾者} implements {組件} {
protected final {組件} component;
public {裝飾者}({組件} component) {
this.component = component;
}
@Override
public {結果} operation() {
return component.operation();
}
}
// 具體裝飾者
public class {具體裝飾者} extends {裝飾者} {
public {具體裝飾者}({組件} component) {
super(component);
}
@Override
public {結果} operation() {
// 前置處理
preProcess();
// 呼叫原有功能
{結果} result = super.operation();
// 後置處理
postProcess(result);
return result;
}
}5.3 行為型模式
策略模式
// 策略介面
public interface {策略} {
{結果} execute({輸入} input);
}
// 具體策略
public class {具體策略A} implements {策略} {
@Override
public {結果} execute({輸入} input) {
// 策略A的實作
}
}
public class {具體策略B} implements {策略} {
@Override
public {結果} execute({輸入} input) {
// 策略B的實作
}
}
// 上下文
public class {上下文} {
private {策略} strategy;
public {上下文}({策略} strategy) {
this.strategy = strategy;
}
public void setStrategy({策略} strategy) {
this.strategy = strategy;
}
public {結果} performOperation({輸入} input) {
return strategy.execute(input);
}
}觀察者模式
// 事件
public class {事件} {
private final {事件資料} data;
private final LocalDateTime timestamp;
public {事件}({事件資料} data) {
this.data = data;
this.timestamp = LocalDateTime.now();
}
}
// 觀察者介面
public interface {觀察者} {
void handle({事件} event);
}
// 主題
public class {主題} {
private final List<{觀察者}> observers = new ArrayList<>();
public void addObserver({觀察者} observer) {
observers.add(observer);
}
public void removeObserver({觀察者} observer) {
observers.remove(observer);
}
protected void notifyObservers({事件} event) {
for ({觀察者} observer : observers) {
try {
observer.handle(event);
} catch (Exception e) {
// 記錄錯誤,但不影響其他觀察者
logError("Observer error", e);
}
}
}
public void performAction({輸入} input) {
// 執行業務邏輯
{結果} result = executeBusinessLogic(input);
// 通知觀察者
notifyObservers(new {事件}(result));
}
}6. 設計原則遵循
6.1 SOLID 原則
單一職責原則 (SRP)
// 違反 SRP - 一個類有多個變更理由
public class BadUserService {
public void createUser(User user) { /* ... */ }
public void sendEmail(String email) { /* ... */ }
public String formatUserReport(User user) { /* ... */ }
}
// 遵循 SRP - 每個類只有一個職責
public class UserService {
public void createUser(User user) { /* ... */ }
}
public class EmailService {
public void sendEmail(String email) { /* ... */ }
}
public class UserReportFormatter {
public String formatUserReport(User user) { /* ... */ }
}開放封閉原則 (OCP)
// 遵循 OCP - 對擴展開放,對修改封閉
public interface PaymentProcessor {
PaymentResult process(Payment payment);
}
public class CreditCardProcessor implements PaymentProcessor {
@Override
public PaymentResult process(Payment payment) {
// 信用卡處理邏輯
}
}
public class PayPalProcessor implements PaymentProcessor {
@Override
public PaymentResult process(Payment payment) {
// PayPal 處理邏輯
}
}
// 新增支付方式無需修改現有程式碼
public class BankTransferProcessor implements PaymentProcessor {
@Override
public PaymentResult process(Payment payment) {
// 銀行轉帳處理邏輯
}
}里氏替換原則 (LSP)
// 遵循 LSP - 子類可以替換父類而不影響程式正確性
public abstract class Bird {
public abstract void move();
}
public class FlyingBird extends Bird {
@Override
public void move() {
fly();
}
protected void fly() {
// 飛行邏輯
}
}
public class WalkingBird extends Bird {
@Override
public void move() {
walk();
}
protected void walk() {
// 行走邏輯
}
}介面隔離原則 (ISP)
// 違反 ISP - 大而全的介面
public interface BadWorker {
void work();
void eat();
void sleep();
}
// 遵循 ISP - 細粒度介面
public interface Worker {
void work();
}
public interface Eater {
void eat();
}
public interface Sleeper {
void sleep();
}
// 實作類只實作需要的介面
public class Human implements Worker, Eater, Sleeper {
@Override
public void work() { /* ... */ }
@Override
public void eat() { /* ... */ }
@Override
public void sleep() { /* ... */ }
}
public class Robot implements Worker {
@Override
public void work() { /* ... */ }
}依賴反轉原則 (DIP)
// 高層模組不應依賴低層模組,都應依賴抽象
public interface NotificationService {
void send(String message, String recipient);
}
public class EmailNotificationService implements NotificationService {
@Override
public void send(String message, String recipient) {
// 郵件發送實作
}
}
public class SmsNotificationService implements NotificationService {
@Override
public void send(String message, String recipient) {
// 簡訊發送實作
}
}
// 高層模組依賴抽象
public class OrderService {
private final NotificationService notificationService;
public OrderService(NotificationService notificationService) {
this.notificationService = notificationService;
}
public void processOrder(Order order) {
// 處理訂單
processOrderLogic(order);
// 發送通知 - 不依賴具體實作
notificationService.send("訂單已處理", order.getCustomerEmail());
}
}6.2 其他設計原則
DRY 原則 (Don’t Repeat Yourself)
// 避免重複 - 提取通用邏輯
public abstract class BaseService<T, ID> {
protected final Repository<T, ID> repository;
public BaseService(Repository<T, ID> repository) {
this.repository = repository;
}
public T save(T entity) {
validate(entity);
return repository.save(entity);
}
public Optional<T> findById(ID id) {
return repository.findById(id);
}
protected abstract void validate(T entity);
}
// 具體服務繼承通用邏輯
public class UserService extends BaseService<User, Long> {
public UserService(UserRepository repository) {
super(repository);
}
@Override
protected void validate(User user) {
// 使用者特定驗證邏輯
}
}KISS 原則 (Keep It Simple, Stupid)
// 簡單直接的實作
public class TaxCalculator {
public BigDecimal calculateTax(BigDecimal amount, TaxRate rate) {
return amount.multiply(rate.getValue());
}
}
// 避免過度複雜的設計
public class SimpleValidator {
public boolean isValidEmail(String email) {
return email != null &&
email.contains("@") &&
email.contains(".");
}
}YAGNI 原則 (You Aren’t Gonna Need It)
// 只實作當前需要的功能,不預先建置可能需要的功能
public class User {
private String id;
private String name;
private String email;
// 只包含目前需要的屬性和方法
// 不要因為"可能會需要"而新增額外功能
public User(String id, String name, String email) {
this.id = id;
this.name = name;
this.email = email;
}
// 基本的 getter 方法
public String getId() { return id; }
public String getName() { return name; }
public String getEmail() { return email; }
}7. 設計驗證和測試
7.1 設計可測試性
依賴注入設計
public class OrderService {
private final PaymentService paymentService;
private final InventoryService inventoryService;
private final NotificationService notificationService;
// 建構子注入 - 便於測試
public OrderService(
PaymentService paymentService,
InventoryService inventoryService,
NotificationService notificationService) {
this.paymentService = paymentService;
this.inventoryService = inventoryService;
this.notificationService = notificationService;
}
public OrderResult processOrder(Order order) {
// 業務邏輯 - 容易進行單元測試
if (!inventoryService.isAvailable(order.getItems())) {
return OrderResult.insufficientInventory();
}
PaymentResult payment = paymentService.processPayment(order.getPayment());
if (!payment.isSuccessful()) {
return OrderResult.paymentFailed();
}
inventoryService.reserveItems(order.getItems());
notificationService.sendConfirmation(order.getCustomer());
return OrderResult.success();
}
}測試案例設計
@ExtendWith(MockitoExtension.class)
class OrderServiceTest {
@Mock
private PaymentService paymentService;
@Mock
private InventoryService inventoryService;
@Mock
private NotificationService notificationService;
@InjectMocks
private OrderService orderService;
@Test
void shouldProcessOrderSuccessfully() {
// Given
Order order = createTestOrder();
when(inventoryService.isAvailable(order.getItems())).thenReturn(true);
when(paymentService.processPayment(order.getPayment()))
.thenReturn(PaymentResult.success());
// When
OrderResult result = orderService.processOrder(order);
// Then
assertThat(result.isSuccessful()).isTrue();
verify(inventoryService).reserveItems(order.getItems());
verify(notificationService).sendConfirmation(order.getCustomer());
}
@Test
void shouldFailWhenInventoryInsufficient() {
// Given
Order order = createTestOrder();
when(inventoryService.isAvailable(order.getItems())).thenReturn(false);
// When
OrderResult result = orderService.processOrder(order);
// Then
assertThat(result.isSuccessful()).isFalse();
assertThat(result.getFailureReason()).isEqualTo("INSUFFICIENT_INVENTORY");
verify(paymentService, never()).processPayment(any());
}
}7.2 設計審查清單
程式碼審查重點
## 設計審查清單
### 1. 職責分離
- [ ] 每個類都有明確且單一的職責
- [ ] 方法長度適中(建議不超過20行)
- [ ] 類別大小合理(建議不超過200行)
### 2. 依賴管理
- [ ] 使用依賴注入而非直接建立對象
- [ ] 依賴介面而非具體實作
- [ ] 避免循環依賴
### 3. 錯誤處理
- [ ] 適當的例外處理策略
- [ ] 使用特定的例外類型
- [ ] 例外訊息具有診斷價值
### 4. 效能考量
- [ ] 避免不必要的物件建立
- [ ] 適當使用快取
- [ ] 資料庫查詢最佳化
### 5. 安全性
- [ ] 輸入驗證
- [ ] 輸出編碼
- [ ] 存取控制
### 6. 可維護性
- [ ] 程式碼可讀性良好
- [ ] 適當的註解和文件
- [ ] 遵循編碼規範8. 工具和資源
8.1 設計工具
- UML 建模: PlantUML, Enterprise Architect
- 程式碼分析: SonarQube, SpotBugs
- 依賴分析: JDepend, ArchUnit
- 重構工具: IntelliJ IDEA, Eclipse
8.2 設計資源
- 設計模式: Gang of Four 設計模式
- 領域驅動設計: Eric Evans DDD
- 企業應用架構: Martin Fowler PoEAA
- 重構技術: Martin Fowler Refactoring
注意事項
- 設計應該根據實際需求演進,避免過度設計
- 保持設計的簡潔性和可理解性
- 重視程式碼的可讀性和可維護性
- 定期重構以保持設計的清潔
- 使用自動化測試保證設計變更的安全性
- 記錄重要的設計決策和變更理由