我的BO之數據保護
我的BO
1-我的BO之強類型
2-我的BO之數據保護
數據保護指什麽
軟件的運行離不開數據,數據一般存在對象中。這種對象在 Java 統稱為 POJO,在 C# 則為 POCO。若 POJO 的Property(屬性)
都是可讀寫的(public
的 get
/set
),沒有方法或只有少量的持久化方法,這種稱為貧血模型。
貧血模型只存儲數據而對數據沒有控制,對象內部和外部都能修改。業務邏輯一般寫在外部,就算寫在內部也因為 Property 可由外界隨意修改而控制不住數據。從而這個 POJO 只是存儲數據,沒有控制數據的能力,也就沒有保護數據的能力。一個對象相關的邏輯不能被很好地集中管理,而是分散在各個外部方法中。從而產生了幾個不良後果:
貧血模型缺點多
- 不同情況下對同份數據的處理有邏輯矛盾,且不易發現。如一處設屬性值為
-1
,另一處卻沒有考慮值是-1
的情況。 - 相同的功能寫多份,修改時容易改漏。經常復制粘貼的代碼後果很可怕。
- 軟件的質量很差,容易發生改了一個 Bug 產生兩個 Bug。難以交付。
BO 如何保護數據
BO 中全部的 Property 對外都是只讀的,外部無法直接修改 Property。只有 BO 自己內部才能修改屬性,從而保護了數據。外部通過調用 BO 的業務方法修改一個或多個屬性,業務方法可對參數和狀態進行各種判斷,滿足條件才修改數據。從而保證任何時候 BO 的數據都是合法的。由於數據只能在內部修改,所以什麽值代表什麽意思是由 BO 自己決定的,統一決定,而不是由外部分散在各個地方的代碼邏輯決定的,所以有效地保證了數據含義的統一性。
雖然關於這個 BO 自己的業務都寫到 BO 這個類中了(這裏暫無須考慮通過繼承寫到多個類的情況),起到了集中控制的效果。但內部不同的業務方法也可能有共用的邏輯,這些應該通過重構功能,以達到“一個功能只寫一處”的狀態。一個大功能會包含若幹個小功能,這裏的“功能”,是泛指大大小小的任何一個功能。無論是面向對象還是面向過程,都應該努力做到“一個功能只寫一處”。這是解決軟件靈活性與軟件正確性的唯一比較可取的做法。除非把人當作機器,面對之前大量“復制粘貼再改改”的代碼需要修改時也能毫不遺漏地全部修改。
BO 的實例化
BO 被定義為任何時刻都是有意義的,所以並不能new
一個空對象,然後再賦值,數據必須在new
import com.abc.enumInfo.RepairStatus;
import com.abc.mybatis.model.Repair;
import com.abc.service.db.RepairDB;
import com.abc.util.BoTrackState;
public class RepairBo extends BoBase {
Repair repair;
@Autowired
RepairDB repairDB;
public RepairBo(Repair repair) { // 傳入PO
if (repair == null)
throw ParameterException.missData("repair");
this.repair = repair;
}
public RepairBo(String code, Long depId, String reportUserName, String contactPhone, Date reportTime,
String address, Long createUserId, Date createTime, RepairStatus status) { // 傳入每個屬性
Repair entity = new Repair();
entity.setCode(code);
entity.setDepId(depId);
entity.setReportUserName(reportUserName);
entity.setContactPhone(contactPhone);
entity.setReportTime(reportTime);
entity.setAddress(address);
entity.setCreateUserId(createUserId);
entity.setCreateTime(createTime);
entity.setStatus(status.toString());
this.repair = entity;
this.trackState = BoTrackState.Added;
}
// region 屬性
public Long getId() {
return repair.getId();
}
protected void setId(Long id) {
repair.setId(id);
setTrackUpdate();
}
public String getCode() {
return repair.getCode();
}
protected void setCode(String code) {
repair.setCode(code);
setTrackUpdate();
}
public Long getDepId() {
return repair.getDepId();
}
protected void setDepId(Long depId) {
repair.setDepId(depId);
setTrackUpdate();
}
public String getReportUserName() {
return repair.getReportUserName();
}
protected void setReportUserName(String reportUserName) {
repair.setReportUserName(reportUserName);
setTrackUpdate();
}
public String getContactPhone() {
return repair.getContactPhone();
}
protected void setContactPhone(String contactPhone) {
repair.setContactPhone(contactPhone);
setTrackUpdate();
}
public Date getReportTime() {
return repair.getReportTime();
}
protected void setReportTime(Date reportTime) {
repair.setReportTime(reportTime);
setTrackUpdate();
}
public String getAddress() {
return repair.getAddress();
}
protected void setAddress(String address) {
repair.setAddress(address);
setTrackUpdate();
}
public Long getCreateUserId() {
return repair.getCreateUserId();
}
protected void setCreateUserId(Long createUserId) {
repair.setCreateUserId(createUserId);
setTrackUpdate();
}
public Date getCreateTime() {
return repair.getCreateTime();
}
protected void setCreateTime(Date createTime) {
repair.setCreateTime(createTime);
setTrackUpdate();
}
public RepairStatus getStatus() {
String sStatus = repair.getStatus();
return RepairStatus.valueOf(sStatus);
}
protected void setStatus(RepairStatus status) {
String sStatus = status.toString();
repair.setStatus(sStatus);
setTrackUpdate();
}
// endregion 屬性
// region 操作
public void delete() {
this.setTrackDeleted(); // 方法在base中
this.save(); // 方法在base中
}
// 業務方法: 派單
public void assignCheck() {
this.setStatus(RepairStatus.已派單);
this.save();
}
// 業務方法: 勘查
public void prospecting(String address) {
this.setAddress(address);
this.setStatus(RepairStatus.故障屬實);
this.save();
}
// endregion 操作
不足之處
沒有對構造時的數據進行合法性驗證。解決辦法可以在構造時檢查,若非法則拋異常。也可以私有化構造方法,並提供public static
方法,若非法則返回null
。
感謝
感謝 Rayman 在我為【BO 的屬性該全只讀,通過方法來修改】還是【可以部分屬性可寫(public set
),並在寫時作業務邏輯】舉棋不定時給我了肯定的回答。我認為這是整個 BO 的關鍵所在。
我的BO之數據保護