主頁 > 軟體設計 > 戲說領域驅動設計(十八)——內驗

戲說領域驅動設計(十八)——內驗

2022-03-30 08:58:19 軟體設計

  驗證在我們現實的生活中非常常見,比如您找作業得先整個面試驗證你的能力是否靠譜;找物件得先驗證下對方的顏值和升值空間,有些工程師寫代碼從不驗證,我覺得是有三個原因,一是意識不夠,過于相信前端或外部服務;二是個人缺少主動思考的能力;三是團隊負責人的問題,您都當了領導了為什么不制定一些基本開發規則給團隊樹規矩,實際上,驗證這個事情說簡單也的確不難,不就是個值判斷嗎?可如果想把這個事情做好還真是一個需要值得思考的作業,就和例外的處理一樣,我告訴你就算干了10年的開發都未必知道怎么有效的使用例外,代碼里中充滿了土味,一看就特Low,所以我們把驗證這個事情單獨的提出來,越是越是簡單的東西想寫好才越難,  

  您應該不知道“物件不變性”這個名字吧?領域模型包括物體與值物件都需要遵循這個規則,就是說不論你對一個領域對像做什么操作,不論怎么盤它,其本質應該保持不變,不都說“江沒易改,本性難變”嗎?上述的操作不僅是呼叫物件上的方法,還包括構造物件的程序,有一個例子說“一個沒有角的獨角獸還能稱得上是獨角獸嗎?”,簡單來說就是你需要始終保持領域物件處于合法的狀態或者說是屬性的值不能超出業務規則限制,比如訂單物件:客戶資訊不能為空、價格資訊不能為負數等、訂單項數量要大于0小于100等,不論你在訂單物件上做什么操作,這些屬性值都不可以超出約束,

  想要保證物件的“不變性”,不能依賴于前端的輸入和資料庫本身的約束,那些基本都不靠譜,最好的方式還是首推“驗證”,針對物件本身是否合法的驗證我稱之為“內驗”,相對的,驗證某個業務先決條件的驗證稱之為“外驗”,因為此時的驗證已經超出了物件本身的規則范圍,既然需要對所有的物件都進行驗證,就應該將其做為一種通用的能力放到OOP編程框架中,其實我個人特別不喜歡稱之為“框架”,感覺概念太大了,所以我們就稱呼為基礎類別庫吧,這個類別庫可以提供一些用于檢驗領域物件是否合法的工具隨用隨取,不用重復的造輪子,

  領域物件內驗的實作思想很簡單:為每個領域物件中加入用于驗證的方法和驗證規則,在物件創建后或持久化前通過呼叫每個物件的驗證方法實作驗證邏輯,您一定要注意前面這句話中所說的觸發驗證方法的時機,別回頭不管什么場景就呼叫驗證,這叫過度設計,那代碼會讓人吐的,另外,既然是通用的能力而且用于驗證領域物件,就最好將其放到領域模型的基類中按需在具體類中進行重寫,所以就讓我們從這些基類作為起點開搞,

一、驗證服務基類

  看過前面的文章您應該已經知道了我們在實作驗證的時候使用了一種類“規約模式”,也就是將驗證規則嵌入到領域物件中,并在合適的時機進行驗證方法的呼叫,為此,在設計領域模型基類的時候我們讓其繼承的了一個用于驗證的父類“ValidatableBase”,這個類里面包含了兩個方法,具體代碼如下所示,“ValidatableBase”是一個抽象類,實作了介面“Validatable”,這個介面很重要,但凡需要驗證的物件都會實作這個介面, 您可以看一下下面的類圖,說得挺繞其實就三個組件,

 

public interface Validatable {

    /**
     * 驗證
     * @return 驗證結果
     */
    ParameterValidationResult validate();
}
public abstract class ValidatableBase implements Validatable {

    /**
     * 驗證當前領域模型
     * @return 驗證的結果
     */
    final public ParameterValidationResult validate() {
        RuleManager ruleManager = new RuleManager(this);
        this.addRule(ruleManager);
        return ruleManager.validate();
    }

    /**
     * 增加驗證規則
     * @param ruleManager 驗證規則管理器
     */
    protected void addRule(RuleManager ruleManager) {

    }
}
public abstract class DomainModel extends ValidatableBase {
   protected void addRule(RuleManager ruleManager) { }
}

  “ValidatableBase”類中的方法“validate”用于觸發模型的驗證,方法“addRule”用于將驗證規則加入到一個包含了驗證規則串列的物件“RuleManager”中,所以你可根據需要決定是否在具體類中進行方法的重寫,比如上面的“DomainModel”中我就對它進行了覆寫,當觸發驗證的時候,只需要遍歷這個“RuleManager”物件中的每個規約并將驗證結果合并即可實作統一驗證的目的,RuleManager代碼可參看如下片段,

public class RuleManager implements Validatable {

    //規則擁有者
    private DomainModel owner;

    //規則串列
    private List<Rule> rules = new ArrayList<Rule>();


    /**
     * 增加規則
     * @param rule 規則物件
     */
    public void addRule(Rule rule){
        if(rule != null){
            rules.add(rule);
        }
    }

    public RuleManager(DomainModel owner){
        this.owner = owner;
    }

    /**
     * 執行驗證,呼叫規則的驗證方法來執行具體的驗證,
     * @return 驗證結果
     */
    public ParameterValidationResult validate(){
        CompositeParameterValidateResult result = new CompositeParameterValidateResult();
        for(Rule rule : this.rules){
            //針對嵌入式物件的驗證
            if (rule instanceof EmbeddedObjectRule){
                EmbeddedObjectRule embeddedObjectRule = (EmbeddedObjectRule) rule;
                ParameterValidationResult validationResult = embeddedObjectRule.getTarget().validate();
                if(!validationResult.isSuccess()){
                    result.addValidationResult(new ParameterValidationResult(false, validateHandlingResult.getMessage()));
                }
                continue;
            }
            ParameterValidationResult ruleVerifyResult = rule.validate();
            if(!ruleVerifyResult.isSuccess()){
                result.fail();
                result.addValidationResult(new ParameterValidationResult(false, errorMessage));
            }
        }
        return result;
    }
}

  這里面其實最有意思也最值得一說的是“EmbeddedObjectRule”這一段,其用于對內嵌物件進行驗證,所謂的內嵌物件是指包含于其它物件內部的領域物件,比如下面代碼片段中的“contact”就是一個嵌套物件,我們驗證領域物件的時候不僅要驗證每個簡單型別的屬性,還需要驗證其中嵌入的其它物件,通過這種方式,就可以實作一層層的驗證,使得每個屬性都能被檢驗到,在上面代碼中另外一個有意思的地方是這段“ParameterValidationResult ruleVerifyResult = rule.validate();”,您會發現真正執行驗證操作的其實是“Rule”物件,這些是我們預定好的一組規則,當然您也可以通過實作“Rule”介面自行加入新的規則,使用預定義規則的方式能加速開發的速度,讓我們拎包即可入住,由“Rule”做驗證其實是OOP中使用較為頻繁的方式,把責任分配的非常明確,十分有利用擴展,

public class Order extends EntityModel<Long> {
    private String name;
    private Contact contact;

    protected Order(Long id, String name, Contact contact) throws OrderCreationException {
        super(id);
        this.name = name;
        this.contact = contact;
    }

    @Override
    protected void addRule(RuleManager ruleManager) {
        super.addRule(ruleManager);
        ruleManager.addRule(new EmbeddedObjectRule("contact", this.contact));        
    }

    public String getName() {
        return name;
    }

    public Contact getContact() {
        return contact;
    }
}

  驗證規則定義了待驗證目標需要滿足什么樣的規范,由于規則間有一些通用的屬性,所以我們在設計的時候首先會引入一個“RuleBase”基類,所有的規則都會從他繼承,“RuleBase”實作了“Rule”介面,而“Rule”也對前面我們說過的“Validatable”進行了擴展,類圖與代碼如下所示,其實也是三個組件,

 

 

   

public interface Rule extends Validatable {
    /**
     * 與操作
     * @param rule 目標規則
     * @return 與后的規則
     */
    Rule and(Rule rule);

    /**
     * 或操作
     * @param rule 目標規則
     * @return 或后的規則
     */
    Rule or(Rule rule);
}
public abstract class RuleBase<TTarget extends DomainModel> implements Rule {

    //驗證的目標
    private TTarget target;
    //驗證目標的名稱
    private String nameOfTarget;
    //當規驗證失敗時的錯誤提示資訊
    private String customErrorMessage = GlobalConstants.EMPTY_STRING;

    /**
     * 規則基類
     * @param nameOfTarget 驗證目標的名稱
     * @param target 驗證的目標
     */
    protected RuleBase(String nameOfTarget, TTarget target){
        this(nameOfTarget, target, new String());
    }

    /**
     * 與操作
     * @param rule 目標規則
     * @return 與后的規則
     */
    @Override
    public Rule and(Rule rule) {
        return new AndRule(this, (RuleBase)rule);
    }

    /**
     * 或操作
     *
     * @param rule 目標規則
     * @return 或后的規則
     */
    @Override
    public Rule or(Rule rule) {
        return new OrRule(this, (RuleBase)rule);
    }
}

  “RuleBase”類里除了包含了共用屬性外,還實作了兩個邏輯操作“與”和“或”,也就是說您可以實作規則的組合,比如我們要求:用戶名稱不能為空且長度小于等于30,就可以使用下面代碼表示,這樣寫比較優雅,

new ObjectNotNullRule("name", this.name).and(new LE("name", this.name.length(), 30))

  通過上面提到的驗證規則框架,我們就可以開始著手建立一些具體的規則 ,下面展示了“物件不為空”規則的代碼片段,這里面需要特別關注的是方法“validate”,用于執行實際的驗證邏輯,類似“大于”規則,可以通過使用“compareTo”方法實作,

public class ObjectNotNullRule extends RuleBase<DomainModel> {

    /**
     * 獲取驗證失敗時預設的錯誤提示資訊
     */
    @Override
    protected String getDefaultErrorMessage() {
        return String.format("%s為空物件", this.getNameOfTarget());
    }

    /**
     * 物件非空規則
     * @param nameOfTarget 驗證目標的名稱
     * @param target       驗證的目標
     */
    public ObjectNotNullRule(String nameOfTarget, DomainModel target) {
        this(nameOfTarget, target, GlobalConstants.EMPTY_STRING);
    }

    /**
     * 執行驗證
     * @return 驗證是否成功
     */
    @Override
    public ParameterValidationResult validate() {
        if(this.getTarget() == null){
            return ParameterValidationResult.failed(null);
        }
        return ParameterValidationResult.success();
    }
}

  到目前為止我們已經展示了內驗所具備的一切條件,現在我們就可以在領域模型中加入各類驗證規則了,下面的代碼片段以上面的“ObjectNotNullRule”規則為例展示了如何在業務代碼中設定驗證規則,這樣的代碼是不是看起來非常的漂亮?至少不用寫一堆的“if……else”,

public class Order extends EntityModel<Long> {
    private String name;
    private Contact contact;

    @Override
    protected void addRule(RuleManager ruleManager) {
        super.addRule(ruleManager);
        ruleManager.addRule(new EmbeddedObjectRule("contact", this.contact));
        ruleManager.addRule(new ObjectNotNullRule("name", this.name));
    }
}

二、驗證觸發的時機

  驗證觸發的時機是需要重點說明和解釋的內容,通過上面的代碼您應該可以看出來每個領域模型無論是物體還是值物件都會包含一個叫作“validate”的公有方法,既然是公有就代表您可以隨意的使用,所以如果不加以限制代碼就會變得特別臟……像我這種有代碼潔癖的人是無論如何不能忍受的,所以我們需要確定觸發驗證的時機,這里給的答案很簡單:物件構造完成時,物件構造包括使用建構式和物件工廠兩種方式,一旦不合法就直接拋出例外,因為不合法的物件是一個畸形兒不能該被創造出來,一般情況下也不允許創造出來后做二次加工使其合法,直白一點就是說你只能使用一行代碼構造物件比如“new BusinessEntity()”或“BusinessEntityFactory.create(),比較建議使用工廠的方式創建物件以避免在建構式中拋例外”,如果成功就回傳目標物件失敗則直接報錯,第十七章中我展示過一個“OrderFactory”的案例,您可以翻看一下,

  領域物件的創建其實也只會出現在兩個時機中:新建及反序列化時,針對新建做驗證是因為引數來源于用戶或其它服務的輸入,這些是不可信任的;而反序列化時進行驗證的原因也很簡單,我們在將物件序列化時它其實是合法的,不過一旦存盤到比如資料庫中就不可控了,您知道誰手賤把資料給改了或由于錯誤執行了某些腳本造成資料變質了,您不能或也不應該只依賴于資料庫本身的驗證規則來保障資料的正確性,使用關系型資料庫還好一點,使用如MongoDB這種的,那只能看運氣了,再說了,業務物件的驗證屬于業務代碼要處理的,您把這個責任推給資料庫就不合適了,

  被成功創建后的物件,您就可以為所欲為的進行操作了,包括最后的持久化階段也不需要進行二次驗證(如果我在前面的文章中提及到物件在持久化時進行驗證的話,請務必注意這種后驗的方式很不友好,比如訂單中的客戶資訊由于意外被置成了“null”,如果不進行構造時的檢測,您在使用這個資訊的時候就可能拋NPE),這種說法應該沒讓您驚呆了吧?也許您可能認為這種說法非常的荒唐,我給您解釋一下為什么,

  首先,我們的前提是物件創建后是合法的,這個在前面已經說過,使用建構式或工廠進行保障;第二,由于有了聚合及聚合根的概念,您不可能繞過聚合根而直接修改其聚合內部的物件,比如用戶物體包含了一個值物件“實名資訊”,我們在修改這個資訊的時候不應該繞過用戶物件而直接對其參考或修改,假如此時的用戶是被凍結的狀態,修改實名資訊是沒有意義的,違反了“客戶凍結”時的業務操作限制;而通過讓客戶物件提供修改的方法,就可以在修改前加一些驗證對操作進行限制,也就是說“只能通過聚合根修改聚合”的原則進一步保障了物件的合法性,當然了,您也可以在修改前先把客戶資訊查詢出來判斷一下狀態再做變更邏輯,但這種方式會造成業務規則不夠內聚,而且這也是典型的面向程序的編程思維,第三點,我假設您在呼叫領域物件的公有方法時已經進行了引數的驗證,如果出現違反業務規則的情況則可直接拋出一個業務例外,比如“凍結的用戶不能修改實名資訊”這個規則,您的代碼可能會按如下方式寫,其實第三條的假設就不應該存在,誰寫公有方法的時候不驗證啊?

public class Account extends EntityModel<Long> {
    public void changeRealName(string name, string idCard) throws RealNameModificationException {
        if (this.status == AccountStatus.FREEZEN) {
            throw new RealNameModificationException();
        }
        ……
    }
}

  綜上三條所述,已經覆寫了您使用領域物件時涉及修改的所有場景,每一步都對物件的不變性進行了保障,那創建好的領域物件不就是您手中的小白羊嗎?盤它的時候根本而不用擔心它不服,

總結

  物件的內驗是一種驗證物件合法性的手段,條條大路通羅馬,在實踐中其實有多種驗證的方式可采用,您所關注的其實應該是它的思想,還是要多提醒一句,你應該知道在DDD中要以聚合為存盤單元、事務單元,其實應該還需要多加一條:驗證單元,上述所說的驗證是以聚合為單位的而非某一個物體或值物件,在實踐中您需要多去思考物件的合法性,雖然說不太可能一下子都想全了,但要有一個驗證意識,這樣的代碼安全性才高,其實不論是做什么樣的系統,應該對安全抱有敬畏的態度,今天多想一點,明天您就少吃點虧,

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/452065.html

標籤:其他

上一篇:戲說領域驅動設計(十八)——內驗

下一篇:企業應用架構研究系列二十:創建&發布Docker

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more