主頁 > 軟體設計 > 阿里高級技術專家方法論:如何寫復雜業務代碼?

阿里高級技術專家方法論:如何寫復雜業務代碼?

2023-01-29 07:31:15 軟體設計

 

張建飛是阿里巴巴高級技術專家,一直在致力于應用架構和代碼復雜度的治理,最近,他在看零售通商品域的代碼,面對零售通如此復雜的業務場景,如何在架構和代碼層面進行應對,是一個新課題,結合實際的業務場景,他沉淀了一套“如何寫復雜業務代碼”的方法論,在此分享給大家,相信同樣的方法論可以復制到大部分復雜業務場景,

 

 1 
一個復雜業務的處理程序

 

業務背景

簡單的介紹下業務背景,零售通是給線下小店供貨的B2B模式,我們希望通過數字化重構傳統供應鏈渠道,提升供應鏈效率,為新零售助力,阿里在中間是一個平臺角色,提供的是Bsbc中的service的功能,

圖片

 

商品力是零售通的核心所在,一個商品在零售通的生命周期如下圖所示:

圖片

 

在上圖中紅框標識的是一個運營操作的“上架”動作,這是非常關鍵的業務操作,上架之后,商品就能在零售通上面對小店進行銷售了,因為上架操作非常關鍵,所以也是商品域中最復雜的業務之一,涉及很多的資料校驗和關聯操作,

針對上架,一個簡化的業務流程如下所示:

圖片

 

程序分解

像這么復雜的業務,我想應該沒有人會寫在一個service方法中吧,一個類解決不了,那就分治吧,

說實話,能想到分而治之的工程師,已經做的不錯了,至少比沒有分治思維要好很多,我也見過復雜程度相當的業務,連分解都沒有,就是一堆方法和類的堆砌,

不過,這里存在一個問題:即很多同學過度的依賴工具或是輔助手段來實作分解,比如在我們的商品域中,類似的分解手段至少有3套以上,有自制的流程引擎,有依賴于資料庫配置的流程處理:

圖片

 

本質上來講,這些輔助手段做的都是一個pipeline的處理流程,沒有其它,因此,我建議此處最好保持KISS(Keep It Simple and Stupid),即最好是什么工具都不要用,次之是用一個極簡的Pipeline模式,最差是使用像流程引擎這樣的重方法,

除非你的應用有極強的流程可視化和編排的訴求,否則我非常不推薦使用流程引擎等工具,第一,它會引入額外的復雜度,特別是那些需要持久化狀態的流程引擎;第二,它會割裂代碼,導致閱讀代碼的不順暢,大膽斷言一下,全天下估計80%對流程引擎的使用都是得不償失的,

回到商品上架的問題,這里問題核心是工具嗎?是設計模式帶來的代碼靈活性嗎?顯然不是,問題的核心應該是如何分解問題和抽象問題,知道金字塔原理的應該知道,此處,我們可以使用結構化分解將問題解構成一個有層級的金字塔結構:

圖片

按照這種分解寫的代碼,就像一本書,目錄和內容清晰明了,

以商品上架為例,程式的入口是一個上架命令(OnSaleCommand),它由三個階段(Phase)組成,

@Command
public class OnSaleNormalItemCmdExe {

    @Resource
    private OnSaleContextInitPhase onSaleContextInitPhase;
    @Resource
    private OnSaleDataCheckPhase onSaleDataCheckPhase;
    @Resource
    private OnSaleProcessPhase onSaleProcessPhase;

    @Override
    public Response execute(OnSaleNormalItemCmd cmd) {

        OnSaleContext onSaleContext = init(cmd);

        checkData(onSaleContext);

        process(onSaleContext);

        return Response.buildSuccess();
    }

    private OnSaleContext init(OnSaleNormalItemCmd cmd) {
        return onSaleContextInitPhase.init(cmd);
    }

    private void checkData(OnSaleContext onSaleContext) {
        onSaleDataCheckPhase.check(onSaleContext);
    }

    private void process(OnSaleContext onSaleContext) {
        onSaleProcessPhase.process(onSaleContext);
    }
}
每個Phase又可以拆解成多個步驟(Step),以OnSaleProcessPhase為例,它是由一系列Step組成的:
@Phase
public class OnSaleProcessPhase {

    @Resource
    private PublishOfferStep publishOfferStep;
    @Resource
    private BackOfferBindStep backOfferBindStep;
    //省略其它step

    public void process(OnSaleContext onSaleContext){
        SupplierItem supplierItem = onSaleContext.getSupplierItem();

        // 生成OfferGroupNo
        generateOfferGroupNo(supplierItem);

       // 發布商品
        publishOffer(supplierItem);

        // 前后端庫存系結 backoffer域
        bindBackOfferStock(supplierItem);

        // 同步庫存路由 backoffer域
        syncStockRoute(supplierItem);

        // 設定虛擬商品拓展欄位
        setVirtualProductExtension(supplierItem);

        // 發貨保障打標 offer域
        markSendProtection(supplierItem);

        // 記錄變更內容ChangeDetail
        recordChangeDetail(supplierItem);

        // 同步供貨價到BackOffer
        syncSupplyPriceToBackOffer(supplierItem);

        // 如果是組合商品打標,寫擴展資訊
        setCombineProductExtension(supplierItem);

        // 去售罄標
        removeSellOutTag(offerId);

        // 發送領域事件
        fireDomainEvent(supplierItem);

        // 關閉關聯的待辦事項
        closeIssues(supplierItem);
    }
}
看到了嗎,這就是商品上架這個復雜業務的業務流程,需要流程引擎嗎?不需要,需要設計模式支撐嗎?也不需要,對于這種業務流程的表達,簡單樸素的組合方法模式(Composed Method)是再合適不過的了,

因此,在做程序分解的時候,我建議工程師不要把太多精力放在工具上,放在設計模式帶來的靈活性上,而是應該多花時間在對問題分析,結構化分解,最后通過合理的抽象,形成合適的階段(Phase)和步驟(Step)上,

圖片

程序分解后的兩個問題

的確,使用程序分解之后的代碼,已經比以前的代碼更清晰、更容易維護了,不過,還有兩個問題值得我們去關注一下:

1、領域知識被割裂肢解

什么叫被肢解?因為我們到目前為止做的都是程序化拆解,導致沒有一個聚合領域知識的地方,每個Use Case的代碼只關心自己的處理流程,知識沒有沉淀,

相同的業務邏輯會在多個Use Case中被重復實作,導致代碼重復度高,即使有復用,最多也就是抽取一個util,代碼對業務語意的表達能力很弱,從而影響代碼的可讀性和可理解性,

2、代碼的業務表達能力缺失

試想下,在程序式的代碼中,所做的事情無外乎就是取資料--做計算--存資料,在這種情況下,要如何通過代碼顯性化的表達我們的業務呢?說實話,很難做到,因為我們缺失了模型,以及模型之間的關系,脫離模型的業務表達,是缺少韻律和靈魂的,

舉個例子,在上架程序中,有一個校驗是檢查庫存的,其中對于組合品(CombineBackOffer)其庫存的處理會和普通品不一樣,原來的代碼是這么寫的:

boolean isCombineProduct = supplierItem.getSign().isCombProductQuote();

// supplier.usc warehouse needn't check
if (WarehouseTypeEnum.isAliWarehouse(supplierItem.getWarehouseType())) {
// quote warehosue check
if (CollectionUtil.isEmpty(supplierItem.getWarehouseIdList()) && !isCombineProduct) {
    throw ExceptionFactory.makeFault(ServiceExceptionCode.SYSTEM_ERROR, "親,不能發布Offer,請聯系倉配運營人員,建立品倉關系!");
}
// inventory amount check
Long sellableAmount = 0L;
if (!isCombineProduct) {
    sellableAmount = normalBiz.acquireSellableAmount(supplierItem.getBackOfferId(), supplierItem.getWarehouseIdList());
} else {
    //組套商品
    OfferModel backOffer = backOfferQueryService.getBackOffer(supplierItem.getBackOfferId());
    if (backOffer != null) {
        sellableAmount = backOffer.getOffer().getTradeModel().getTradeCondition().getAmountOnSale();
    }
}
if (sellableAmount < 1) {
    throw ExceptionFactory.makeFault(ServiceExceptionCode.SYSTEM_ERROR, "親,實倉庫存必須大于0才能發布,請確認已補貨.\r[id:" + supplierItem.getId() + "]");
}
}
然而,如果我們在系統中引入領域模型之后,其代碼會簡化為如下:
if(backOffer.isCloudWarehouse()){
    return;
}

if (backOffer.isNonInWarehouse()){
    throw new BizException("親,不能發布Offer,請聯系倉配運營人員,建立品倉關系!");
}

if (backOffer.getStockAmount() < 1){
    throw new BizException("親,實倉庫存必須大于0才能發布,請確認已補貨.\r[id:" + backOffer.getSupplierItem().getCspuCode() + "]");
}
有沒有發現,使用模型的表達要清晰易懂很多,而且也不需要做關于組合品的判斷了,因為我們在系統中引入了更加貼近現實的物件模型(CombineBackOffer繼承BackOffer),通過物件的多型可以消除我們代碼中的大部分的if-else,

圖片

程序分解+物件模型

通過上面的案例,我們可以看到有程序分解要好于沒有分解,程序分解+物件模型要好于僅僅是程序分解,對于商品上架這個case,如果采用程序分解+物件模型的方式,最終我們會得到一個如下的系統結構:

圖片

 

 2 
寫復雜業務的方法論

 

通過上面案例的講解,我想說,我已經交代了復雜業務代碼要怎么寫:即自上而下的結構化分解+自下而上的面向物件分析,

接下來,讓我們把上面的案例進行進一步的提煉,形成一個可落地的方法論,從而可以泛化到更多的復雜業務場景,

上下結合

所謂上下結合,是指我們要結合自上而下的程序分解和自下而上的物件建模,螺旋式的構建我們的應用系統,這是一個動態的程序,兩個步驟可以交替進行、也可以同時進行,

這兩個步驟是相輔相成的,上面的分析可以幫助我們更好的理清模型之間的關系,而下面的模型表達可以提升我們代碼的復用度和業務語意表達能力,

其程序如下圖所示:

圖片

使用這種上下結合的方式,我們就有可能在面對任何復雜的業務場景,都能寫出干凈整潔、易維護的代碼,

能力下沉

一般來說實踐DDD有兩個程序:

1、套概念階段:了解了一些DDD的概念,然后在代碼中“使用”Aggregation Root,Bounded Context,Repository等等這些概念,更進一步,也會使用一定的分層策略,然而這種做法一般對復雜度的治理并沒有多大作用,

2、融會貫通階段:術語已經不再重要,理解DDD的本質是統一語言、邊界劃分和面向物件分析的方法,

大體上而言,我大概是在1.7的階段,因為有一個問題一直在困擾我,就是哪些能力應該放在Domain層,是不是按照傳統的做法,將所有的業務都收攏到Domain上,這樣做合理嗎?說實話,這個問題我一直沒有想清楚,

因為在現實業務中,很多的功能都是用例特有的(Use case specific)的,如果“盲目”的使用Domain收攏業務并不見得能帶來多大的益處,相反,這種收攏會導致Domain層的膨脹過厚,不夠純粹,反而會影響復用性和表達能力,

鑒于此,我最近的思考是我們應該采用能力下沉的策略,

所謂的能力下沉,是指我們不強求一次就能設計出Domain的能力,也不需要強制要求把所有的業務功能都放到Domain層,而是采用實用主義的態度,即只對那些需要在多個場景中需要被復用的能力進行抽象下沉,而不需要復用的,就暫時放在App層的Use Case里就好了,

注:Use Case是《架構整潔之道》里面的術語,簡單理解就是回應一個Request的處理程序,

通過實踐,我發現這種循序漸進的能力下沉策略,應該是一種更符合實際、更敏捷的方法,因為我們承認模型不是一次性設計出來的,而是迭代演化出來的,

下沉的程序如下圖所示,假設兩個use case中,我們發現uc1的step3和uc2的step1有類似的功能,我們就可以考慮讓其下沉到Domain層,從而增加代碼的復用性,

圖片

指導下沉有兩個關鍵指標:

  • 復用性

  • 內聚性

復用性是告訴我們When(什么時候該下沉了),即有重復代碼的時候,內聚性是告訴我們How(要下沉到哪里),功能有沒有內聚到恰當的物體上,有沒有放到合適的層次上(因為Domain層的能力也是有兩個層次的,一個是Domain Service這是相對比較粗的粒度,另一個是Domain的Model這個是最細粒度的復用),

比如,在我們的商品域,經常需要判斷一個商品是不是最小單位,是不是中包商品,像這種能力就非常有必要直接掛載在Model上,

public class CSPU {
    private String code;
    private String baseCode;
    //省略其它屬性

    /**
     * 單品是否為最小單位,
     *
     */
    public boolean isMinimumUnit(){
        return StringUtils.equals(code, baseCode);
    }

    /**
     * 針對中包的特殊處理
     *
     */
    public boolean isMidPackage(){
        return StringUtils.equals(code, midPackageCode);
    }
}
之前,因為老系統中沒有領域模型,沒有CSPU這個物體,你會發現像判斷單品是否為最小單位的邏輯是以StringUtils.equals(code, baseCode)的形式散落在代碼的各個角落,這種代碼的可理解性是可想而知的,至少我在第一眼看到這個代碼的時候,是完全不知道什么意思,

 

 3 
業務技術要怎么做

 

寫到這里,我想順便回答一下很多業務技術同學的困惑,也是我之前的困惑:即業務技術到底是在做業務,還是做技術?業務技術的技術性體現在哪里?

通過上面的案例,我們可以看到業務所面臨的復雜性并不亞于底層技術,要想寫好業務代碼也不是一件容易的事情,業務技術和底層技術人員唯一的區別是他們所面臨的問題域不一樣,

業務技術面對的問題域變化更多、面對的人更加龐雜,而底層技術面對的問題域更加穩定、但對技術的要求更加深,比如,如果你需要去開發Pandora,你就要對Classloader有更加深入的了解才行,

但是,不管是業務技識訓是底層技術人員,有一些思維和能力都是共通的,比如,分解問題的能力,抽象思維,結構化思維等等,

圖片

用我的話說就是:“做不好業務開發的,也做不好技術底層開發,反之亦然,業務開發一點都不簡單,只是我們很多人把它做‘簡單’了”,

因此,如果從變化的角度來看,業務技術的難度一點不遜色于底層技術,其面臨的挑戰甚至更大,因此,我想對廣大的從事業務技術開發的同學說:沉下心來,夯實自己的基礎技術能力、OO能力、建模能力……不斷提升抽象思維、結構化思維、思辨思維……持續學習精進,寫好代碼,我們可以在業務技術崗做的很“技術”!,

 

 4 
后記

 

這篇文章是我最近思考的一些總結,大部分思想是繼承自我原來寫的COLA架構,該架構已經開源,目前在集團內外都有比較廣泛的使用,

這一篇主要是在COLA的基礎上,針對復雜業務場景,做了進一步的架構落地,個人感覺可以作為COLA的最佳實踐來使用,

另外,本文討論的問題之大和篇幅之短是不成正比的,原因是我假定你已經了解了一些DDD和應用架構的基礎知識,如果覺得在理解上有困難,我建議可以先看下《領域驅動設計》和《架構整潔之道》這兩本書,

 

作者|張建飛

本文來自博客園,作者:古道輕風,轉載請注明原文鏈接:https://www.cnblogs.com/88223100/p/How-to-write-complex-business-code.html

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

標籤:其他

上一篇:阿里高級技術專家方法論:如何寫復雜業務代碼?

下一篇:訊息中間件RabbitMQ

標籤雲
其他(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