Java中各種O(PO,BO,DTO,VO等) 是不是人為增加系統復雜度?

Java中各種O(PO,BO,DTO,VO等) 是不是人為增加系統復雜度?

在Java和其他編程語言的開發過程中,經常會用到幾個以"O"結尾的縮寫,比如PO,BO,DTO,VO等等,O在這里是Object的縮寫,不同的O代表了不同的數據類型,很多時候這些O中的屬性看起來都是差不多的,干的事情好像也只是一個簡單的封裝,那么搞出這么多O出來是不是人為增加了系統的復雜度呢?

各種O都是干什么的?

想要搞清楚標題中的問題,我們首先得了解這些O都是什么東西?這里給大家介紹幾種常見的O:

  1. PO (Persistent Object) - 持久化對象。持久化對象通常對應數據庫中的一個表,主要用于表示數據庫中存儲的數據。PO中的屬性通常和數據表的列一一對應,用于ORM(對象關系映射)框架中,如Hibernate,JPA等。
  2. BO (Business Object) - 業務對象。業務對象主要封裝了業務邏輯。它可以包含多個PO,或者是一個PO的擴展,增加了業務處理的邏輯。BO通常在業務層被使用,用于實現業務操作,比如計算、決策等。
  3. VO (Value Object) - 值對象。值對象是一種用于傳輸數據的簡單對象,它通常不包含業務邏輯,只包含數據屬性和get/set方法。值對象主要用于業務層與表示層之間的數據傳遞,它的數據可能是由多個PO組合而成。
  4. DTO (Data Transfer Object) - 數據傳輸對象。數據傳輸對象類似于VO,它也是用于層與層之間的數據傳遞。DTO通常用于遠程通信,比如Web服務之間的數據傳遞。DTO通常不包含任何業務邏輯,只是用于在不同層次或不同系統之間傳輸數據。

有時候我們還會看到DO、POJO等概念,它們又是什么呢?

  1. DO (Domain Object) - 領域對象。領域對象是指在問題領域內被定義的對象,它可以包含數據和行為,并且通常代表現實世界中的實體。在DDD(領域驅動設計)中,領域對象是核心概念,用于封裝業務邏輯和規則。這里需要注意DO和BO的區別,雖然都是搞業務邏輯,DO通常是業務領域中單一實體的抽象,它關注于單個業務實體的屬性和行為;而BO則通常涉及到業務流程的實現,可能會協調多個DO來完成一個業務操作。
  2. POJO (Plain Old Java Object) - 簡單老式Java對象。POJO是指沒有遵循特定Java對象模型、約定或框架(如EJB)的簡單Java對象。POJO通常用于表示數據結構,它們的實例化和使用不依賴于特定的容器或框架。

為什么要劃分各種O?

在軟件開發中劃分不同的O主要是為了實現關注點分離(Separation of Concerns,SoC),提高代碼的可維護性、可讀性和可擴展性。

下面展開列舉了一些劃分這些對象的原因:

  1. 明確職責:通過將不同的職責分配給不同的對象,可以使每個對象都有明確的職責,這樣代碼更容易理解和維護。
  2. 減少耦合:不同層次之間通過定義清晰的接口(如特定的對象)交互,減少了直接的依賴關系,降低了耦合度。
  3. 抽象層次:通過定義不同的對象,可以在不同的抽象層次上操作,比如在數據層處理PO,在業務層處理BO,這樣可以在合適的層次上做出決策。
    • 靈活性:當系統需要變更時,由于職責和層次的清晰劃分,更容易做出局部的修改而不影響到整個系統。不同的對象可能針對性能有不同的優化,例如PO可能被優化以提高數據庫操作的性能。
    • 安全性:通過使用不同的對象,可以控制敏感數據的暴露。例如,可以在DTO中排除一些不應該傳輸到前端的敏感信息。
    • 測試性:分離的對象使得單元測試變得更加容易,因為可以針對每個對象進行獨立的測試。
  1. 交互清晰:在不同的系統組件或層次之間傳遞數據時,清晰的對象定義可以讓數據交互更加清晰,減少數據傳遞中的錯誤。

總之,通過劃分各種“O”對象,開發者可以更好地組織代碼,將復雜系統分解為更小、更易于管理的部分,同時也有助于團隊成員之間的溝通和協作。這種劃分在設計模式和軟件工程實踐中是一種常見且有效的方法。

OO不分的慘痛經歷

說個實際的慘痛經驗。

很多時候我會感覺這些O之間存在很多重復的代碼,比如重復的屬性定義、簡單的方法封裝,DRY(Don't Repeat Yourself)原則不是說讓大家避免重復嘛,所以我也曾經嘗試在程序中統一它們。

但是總有一些O之間存在或多或少的差異,比如:

  • 這個O需要一個A屬性,僅用于內部狀態管理,不會暴露到外部,其它O都不需要。
  • 還有這個接口需要返回一個B屬性,其它接口都不需要。

這時候,你怎么辦?如果使用同一個類型,那就得加上這些屬性,盡管它們在某些時候用不到。根據你的選擇,你可能在所有的地方都給這個屬性賦值,也可能僅在業務需要的時候給他們賦值。

看個實際的例子:在一個復雜的電商系統中,商品的管理可能涉及到庫存管理、價格策略、促銷信息等多個方面。

// 商品類
public class Product {private Long id; // 來自商品表private String name; // 來自商品表private double price; // 來自商品表,傳輸時需要特殊格式private int stock; // 來自庫存表,僅在下單判斷中需要,展示層不需要private String promotionInfo; // 來自促銷表,展示層需要// 構造器、getter和setter方法省略
}

但是這卻帶來了很大的危害:

  • 調用接口的同學會問,這個屬性什么時候會有值,什么時候會沒值?
  • 優化的同學會問,計算這個屬性的值會影響性能,能刪掉嗎?
  • 交接的同學會問,這個屬性是干什么用的,為什么不給他賦值?

總之會增加了大量的溝通成本與維護難度。一旦這樣做了,后邊就會特別別扭,改不完,根本改不完。

在軟件工程化的今天,各類O的設計看似增加了復雜度,但是實際上是對系統模塊化、職責劃分以及實際應用場景的合理抽象和封裝,有助于提高軟件質量和團隊協作效率。

老老實實寫吧,不同的O就是不同的東西,它們不是重復的,只是在代碼上看著像,就像人有四肢,動物也有四肢,但是它們不能共用,否則出來的就是四不像。

圖片來源:https://ozhanozturk.com/2018/01/28/chimera-kimera-mitoloji/

當然如果只是一個很簡單的程序或者一次性的程序,我們確實沒必要劃分這么多的O出來,直接在接口方法中訪問數據庫也不是不可以的。

前端中O的使用

雖然各種O一般活躍在各種后端程序中,但是前端也不乏O的身影,只是沒有后端那么形式化。

以下是一些可能在前端開發中遇到的以“O”結尾的數據對象:

  1. VO (View Object) - 視圖對象。在前端框架中,VO可以代表專門為視圖層定制的數據對象。這些對象通常是從后端接口獲取的數據經過加工或格式化后,用于在界面上顯示的對象。
  2. DTO (Data Transfer Object) - 數據傳輸對象。雖然DTO通常用于后端服務間的數據傳輸,但在前端中也可以用來表示從后端接口獲取的數據結構。前端的DTO通常是指通過Ajax或Fetch API從服務器獲取的原始數據結構。
  3. VMO (ViewModel Object) - 視圖模型對象。在MVVM(Model-View-ViewModel)架構中,VMO可以代表視圖模型對象,它是模型和視圖之間的連接器。在Vue.js中,Vue實例本身就可以被看作是一個VMO,因為它包含了數據和行為,同時也是視圖的反映。
  4. SO (State Object) - 狀態對象 盡管不是標準的術語,但在使用如Vuex這樣的狀態管理庫時,SO可以用來指代代表應用狀態的對象。這些狀態對象通常包含了應用的核心數據,如用戶信息、應用設置等。

在實際的Vue開發過程中,開發者可能不會嚴格區分這些概念,而是更多地關注于組件的狀態、屬性(props)、事件和生命周期。組件內部的數據通常以數據屬性(data)的形式存在,而組件間的數據傳遞通常使用屬性(props)和事件(emits)。在處理與后端的數據交互時,開發者可能會定義一些專門的對象來適應后端的接口,但是這些都不是Vue框架強制的概念或規則。


簡單地說,這些“O”其實就是幫我們把代碼寫得更清晰、更有條理,雖然一開始看著很麻煩,但時間一長,你會發現這樣做能省下不少力氣。就像我們的衣柜,雖然分類放好衣服需要點時間,但每天早上起來挑衣服的時候,不就輕松多了嗎?

所以,別被這些專業術語嚇到,它們其實就是幫我們把事情做得更好的小工具。每個“O”都有它的用處和場景,我們要做的,就是搞清楚什么時候戴哪頂帽子,這樣生活和編程都能變得輕松愉快。記住,合適的工具用在合適的地方,能讓你事半功倍!

關注螢火架構,加速技術提升!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/697764.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/697764.shtml
英文地址,請注明出處:http://en.pswp.cn/news/697764.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

onlyoffice7.5.1 實現填寫表單 word+html form雙向綁定功能

說明:目前官方已經更新wordhtml為8.0以前的,目前官方新版本8.0增加了pdf綁定,這個我考慮在以后研究努力實現。 onlyoffice雙向綁定form表單數據

Java基礎 - 13 Queue之DelayQueue、PriorityQueue、PriorityBlockingQueue講解

在Java的隊列世界里,有三位大佬,他們分別是DelayQueue、PriorityQueue和PriorityBlockingQueue。今天,讓我們一起揭開他們神秘的面紗,看看他們各自的特點和用途吧! DelayQueue 首先,讓我們來認識一下Delay…

2.22 作業

順序表 運行結果 fun.c #include "fun.h" seq_p create_seq_list() {seq_p L (seq_p)malloc(sizeof(seq_list));if(LNULL){printf("空間申請失敗\n");return NULL;}L->len 0; bzero(L,sizeof(L->data)); return L; } int seq_empty(seq_p L) {i…

工廠方法模式Factory Method

1.模式定義 定義一個用于創建對象的接口,讓子類決定實例化哪一個類。Factory Method 使得一個類的實例化延遲到子類 2.使用場景 1.當你不知道改使用對象的確切類型的時候 2.當你希望為庫或框架提供擴展其內部組件的方法時 主要優點: 1.將具體產品和創建…

PHP+vue+mysql倉庫進銷存管理系統8jeqj

開發語言:php 后端框架:Thinkphp 前端框架:vue.js 服務器:apache 數據庫:mysql 運行環境:phpstudy/wamp/xammp等 數據庫工具:Navicat/phpmyadmin 登錄模塊:此模塊主要有4個部分,基…

實驗中用戶行為的檢測

[1] Makris S , Karagiannis P , Koukas S ,et al.Augmented reality system for operator support in human–robot collaborative assembly[J].CIRP Annals - Manufacturing Technology, 2016:S0007850616300385.DOI:10.1016/j.cirp.2016.04.038. —————————————…

gem5學習(24):緩存一致性協議——Cache Coherence Protocols

目錄 一、Common Notations and Data Structures 1、Coherence Messages 2、Access Permissions 3、Data Structures 二、Coherence controller FSM Diagrams 官網教程:gem5: Cache Coherence Protocols 一、Common Notations and Data Structures &#xff…

什么是SSD型云服務器?

?  SSD云服務器是一種使用固態硬盤代替傳統HDD進行存儲的虛擬機。SDD 使用閃存單元來存儲數據,與云計算技術相結合,形成強大且高效的存儲解決方案,可以隨時隨地訪問。 SSD云服務器如何工作? SSD云服務器是利用虛擬化和云計算技術創建的。…

C++最佳實踐之編譯篇

C最佳實踐之工程編譯 在大型c/c工程開發中,往往會涉及多級CMakeLists.txt的調用,并且調用方式錯綜復雜,主要有以下兩種方式: 1. 子目錄中的CMakeList.txt獨立生成目標,不作為主目標生成過程的依賴關系(比…

virtualenv env_name 使用 virtualenv 創建 python 虛擬環境

為什么要用這個 win7 32 環境下 pycharm 只能用低版本的,比如 2016,2018 此時pycharm 圖形界面創建的 虛擬環境版本很低,有些包不兼容,因此用 virtualenv 模塊,可以創建 20 版本以上的虛擬環境 virtualenv env_name官方文檔 http…

如何選擇最適合的圖紙加密軟件?安秉網盾軟件用戶體驗及性價比

安秉網盾圖紙加密軟件是一款功能強大的圖紙加密工具,具有以下特點和優勢: 全盤加密:安秉網盾采用先進的加密算法,能對文件、文件夾、磁盤等數據進行全面加密,確保數據在存儲和傳輸過程中的安全性。 監控與審計&#x…

Swift基礎知識:26.Swift類型轉換

在 Swift 中,類型轉換是指將一種類型的實例轉換為另一種類型的操作。Swift 提供了三種類型轉換操作:as?、as! 和 is。 as? 和 as! as?:可選類型轉換。如果轉換成功,返回一個可選類型,值為轉換后的類型&#xff1b…

編程筆記 Golang基礎 024 映射

編程筆記 Golang基礎 024 映射 一、映射二、映射的定義與初始化三、基本操作四、綜合示例程序 Go語言中的映射(map)是一種關聯數組或哈希表數據結構,它存儲鍵值對,其中每個鍵都是唯一的。在Go中,你可以使用 map[keyTy…

關于el-select值的回顯問題 : 框內顯示label值還是value值

<el-form-item label"狀態" prop""><el-selectv-model"roleForm.state"class"m-2"size"large"style"width: 240px"placeholder"請選擇狀態"value-key"value"//value-key 與下面的ke…

How to implement multiple file uploads based on Swagger 3.x in Spring boot 3.x

How to implement multiple file uploads based on Swagger 3.x in Spring boot 3.x Projectpom.xmlOpenAPIConfigFileUploadControllerapplication.yaml Project pom.xml <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://…

軟件壓力測試:測試方法與步驟詳解

隨著軟件應用的不斷發展&#xff0c;用戶對系統性能的要求也逐漸提高。在不同的負載條件下&#xff0c;系統必須能夠保持穩定、高效的運行。軟件壓力測試是一種驗證系統在各種負載情況下性能表現的關鍵手段。本文將詳細探討軟件壓力測試的方法和步驟。 1. 明確測試目標 在進行壓…

vue源碼分析之nextTick源碼分析-逐行逐析-錯誤分析

nextTick的使用背景 在vue項目中&#xff0c;經常會使用到nextTick這個api&#xff0c;一直在猜想其是怎么實現的&#xff0c;今天有幸研讀了下&#xff0c;雖然源碼又些許問題&#xff0c;但仍值得借鑒 核心源碼解析 判斷當前環境使用最合適的API并保存函數 promise 判斷…

2024年2月17日~2月23日周報

文章目錄 一、前言二、DDNet架構學習2.1 數據預處理2.2 網絡模型構建 三、基于深度學習地震數據去噪處理3.1 深度學習在地震數據去噪中的研究方向3.2 深度學習地震數據去噪流程3.2.1 數據集準備3.2.2 模型構建3.2.3 訓練網絡 3.3 基于DnCNN的地震數據去噪實驗 四、小結4.1 存在…

xxl_job系列---【GLUE(shell)模式如何傳多個參數,并被shell接收】

1.場景 我需要傳入多個參數&#xff0c;在執行任務時傳入的任務參數用逗號隔開&#xff0c;到shell中都被$1當做字符串接收到了&#xff0c;沒辦法&#xff0c;只能在shell中截取字符串&#xff0c;截成多個參數。 2.編輯入參 CRON:0 0 0 1 * ? #每月1號0點執行 點擊“任務管理…

Javascript數字精度丟失的問題

一、問題 0.1 0.2 0.3 // false 二、浮點數 “浮點數”是一種表示數字的標準&#xff0c;整數也可以用浮點數的格式來存儲 我們也可以理解成&#xff0c;浮點數就是小數 在JavaScript中&#xff0c;現在主流的數值類型是Number&#xff0c;而Number采用的是IEEE754規范中…