前言:什麼是反模式?
設計模式是經驗的結晶,而「反模式」則是常見的錯誤決策與其負面後果。在 J2EE 專案中,受限於規格複雜度、團隊經驗與時程壓力,以下四大反模式最為普遍。及早識別並修正,能大幅降低維護成本與系統風險。
反模式一:沒有 EJB 就不叫 J2EE
現象
團隊認為「使用 EJB」是 J2EE 專案的必要條件,即使業務邏輯簡單、無需分散式交易、無需遠端呼叫,仍強行引入 Session Bean、Entity Bean,導致專案充滿 Home/Remote 介面、JNDI 查詢、部署描述檔等樣板程式碼。
後果
- 開發效率低落:大量時間花在 EJB 基礎建設而非業務邏輯。
- 效能開銷大:遠端介面序列化、容器管理生命週期帶來額外負擔。
- 測試困難:需啟動完整容器才能執行單元測試。
改善方向
- 評估是否真正需要分散式交易、安全傳播、遠端存取等 EJB 核心功能。
- 採用 POJO + 輕量級容器 (Spring) 開發,僅在必要時以 Session Facade 包裝為 Stateless Session Bean。
- Entity Bean 改用 BMP + 本地介面,或直接改用 Hibernate/JPA 等 ORM 框架。
現代觀點:Spring 框架證明「完全不使用 EJB」也能構建企業級應用。EJB 3.0 後大幅簡化 (Annotation、POJO 化),但核心原則不變:按需引入,勿為用技術而用技術。
反模式二:過度分層
現象
受 J2EE 藍圖影響,機械套用「表現層、業務邏輯層、資料存取層、領域模型層、傳輸物件層...」甚至每層再細分介面與實作,導致簡單的 CRUD 操作需穿越 6-8 個類別。
後果
- 程式碼膨脹、追蹤困難、修改成本高。
- 效能損耗:層層轉換 DTO/VO、重複驗證邏輯。
- 新人上手門檻極高。
改善方向
- 依專案規模、團隊熟悉度、變更頻率決定分層粒度。
- 簡單模組採用「Controller → Service → Repository」三層即可。
- 複雜領域模型才引入 DDD 分層 (Application/Domain/Infrastructure)。
- 避免為了分層而分層:層次是為了解耦服務,而非儀式。
反模式三:頻繁的遠端往返調用
現象
開發者習慣在迴圈中逐筆呼叫遠端 EJB 方法,或對 Entity Bean 逐欄位呼叫 Setter,忽略每次呼叫都是跨網路的 RMI/IIOP 往返。
後果
- 網路延遲放大:原本 1ms 本地呼叫變成 50-200ms 遠端呼叫,迴圈放大百倍。
- 交易邊界模糊:難以在單一交易中完成多步驟操作。
改善方向
- 採用 DTO (Data Transfer Object) / Value Object 一次性傳輸聚合資料。
- Service 層提供粗粒度業務方法 (Coarse-grained),封裝細粒度操作。
- 批次操作設計單一 API (如
saveAll(List<Order>)) 取代迴圈呼叫。
反模式四:濫用 Stateful Session Bean
現象
為了保存使用者會話狀態 (購物車、精靈式表單進度),大量使用 Stateful Session Bean (SFSB),甚至將大型物件圖存放在 Bean 實例欄位中。
後果
- 擴展性差:SFSB 專屬於單一用戶,無法像 Stateless Bean 那樣從 Pool 重用,記憶體佔用隨併發用戶線性增長。
- 容錯複雜:需配置狀態複製 (State Replication) 或持久化,增加基礎建設複雜度。
- 序列化風險:欄位包含非序列化物件導致 Passivation 失敗。
改善方向
- 將會話狀態外部化:HttpSession、資料庫、Redis、Client-side Cookie/Token。
- Stateless Session Bean + 外部狀態存儲 = 可水平擴展、易叢集、易測試。
- 僅在極少數「會話期極短、狀態極簡單、強一致性要求高」場景考慮 SFSB。
總結:反模式檢核清單
| 反模式 | 警訊 | 核心對策 |
| 無 EJB 不叫 J2EE | 專案滿是 Home/Remote 介面、JNDI 查詢、ejb-jar.xml | POJO + Spring,按需引入 EJB |
| 過度分層 | CRUD 需穿越 6+ 類別、DTO 到處轉換 | 依複雜度決定層次,三層起步 |
| 頻繁遠端往返 | 迴圈呼叫 Remote 介面、逐欄位 Setter | DTO 聚合傳輸、粗粒度 Service API |
| 濫用 SFSB | 大量 SFSB、記憶體隨用戶增長、Passivation 錯誤 | 狀態外部化,改用 Stateless + 外部存儲 |
結語
J2EE 規範提供豐富工具箱,但「工具越多、越容易誤用」。反模式本質上是將解決方案複雜度強加於問題本身之上。保持務實:先理解問題本質,再選擇最簡單可行的技術組合。Spring、Hibernate、JPA 等輕量級框架的興起,正是對早期 J2EE 重型反模式的最佳回應。