1. 程式人生 > >我的BO之數據保護

我的BO之數據保護

res 解決辦法 throw string 有意 delet etc time 故障

我的BO
1-我的BO之強類型
2-我的BO之數據保護

數據保護指什麽

軟件的運行離不開數據,數據一般存在對象中。這種對象在 Java 統稱為 POJO,在 C# 則為 POCO。若 POJO 的Property(屬性)都是可讀寫的(publicget/set),沒有方法或只有少量的持久化方法,這種稱為貧血模型。

貧血模型只存儲數據而對數據沒有控制,對象內部和外部都能修改。業務邏輯一般寫在外部,就算寫在內部也因為 Property 可由外界隨意修改而控制不住數據。從而這個 POJO 只是存儲數據,沒有控制數據的能力,也就沒有保護數據的能力。一個對象相關的邏輯不能被很好地集中管理,而是分散在各個外部方法中。從而產生了幾個不良後果:

貧血模型缺點多

  1. 不同情況下對同份數據的處理有邏輯矛盾,且不易發現。如一處設屬性值為-1,另一處卻沒有考慮值是-1的情況。
  2. 相同的功能寫多份,修改時容易改漏。經常復制粘貼的代碼後果很可怕。
  3. 軟件的質量很差,容易發生改了一個 Bug 產生兩個 Bug。難以交付。

BO 如何保護數據

BO 中全部的 Property 對外都是只讀的,外部無法直接修改 Property。只有 BO 自己內部才能修改屬性,從而保護了數據。外部通過調用 BO 的業務方法修改一個或多個屬性,業務方法可對參數和狀態進行各種判斷,滿足條件才修改數據。從而保證任何時候 BO 的數據都是合法的。由於數據只能在內部修改,所以什麽值代表什麽意思是由 BO 自己決定的,統一決定,而不是由外部分散在各個地方的代碼邏輯決定的,所以有效地保證了數據含義的統一性。

雖然關於這個 BO 自己的業務都寫到 BO 這個類中了(這裏暫無須考慮通過繼承寫到多個類的情況),起到了集中控制的效果。但內部不同的業務方法也可能有共用的邏輯,這些應該通過重構功能,以達到“一個功能只寫一處”的狀態。一個大功能會包含若幹個小功能,這裏的“功能”,是泛指大大小小的任何一個功能。無論是面向對象還是面向過程,都應該努力做到“一個功能只寫一處”。這是解決軟件靈活性與軟件正確性的唯一比較可取的做法。除非把人當作機器,面對之前大量“復制粘貼再改改”的代碼需要修改時也能毫不遺漏地全部修改。

BO 的實例化

BO 被定義為任何時刻都是有意義的,所以並不能new一個空對象,然後再賦值,數據必須在new

時就送來,所以 BO 需要提供一個全部屬性的構造方法。另外為了持久化方便的考慮,也可以接收一個 PO,從 PO 獲取各個屬性的值。

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之數據保護