主頁 > 軟體設計 > 如何落地業務建模(2) 實踐DDD時常見的問題

如何落地業務建模(2) 實踐DDD時常見的問題

2022-01-17 18:00:43 軟體設計

  • 關聯物件
    • 無法封裝的資料庫開銷
    • 引入關聯物件
  • 背景關系過載
    • 因富含邏輯而產生的過大類
    • 邏輯匯聚于背景關系還是物體
    • 通過角色物件分離不同背景關系的邏輯
    • 通過背景關系物件分離不同背景關系的邏輯
  • 架構分層
    • DDD中的分層的問題
      • 基礎設施層與領域層誰更穩定
      • 基礎設施不是層
    • 能力供應商模式
      • 從基礎設施到有業務含義的能力
        • 將技術組件進行擬人化處理
      • 使用能力供應商的多層架構
      • 能力供應商模式的缺點

如何落地業務建模

在落地DDD時,關聯模型與軟體實作總有讓人糾結與苦惱的地方,引起這些苦惱的的主要原因是架構風格的變化,我們已經從多層單體架構時代,過渡到了云原生分布式架構,但所采用的建模思路與編程風格并沒有徹底跟上時代的步伐,這種差異通常會以性能問題或是代碼壞味道的形式出現,
想要真正發揮出DDD的作用,就需要在不同架構風格下,找到能夠維持模型與軟體實作統一的辦法,

關聯物件

DDD中的聚合關系在具體實作中會存在一些問題,

無法封裝的資料庫開銷

聚合與聚合根是構成"富含知識的模型"的關鍵,通過聚合關系,可以將被聚合物件的集合邏輯放置在聚合或聚合根,而不是散落在外,或是放在其它無關的服務中,以避免邏輯泄露,
但在落地時,經常會遇到一個挑戰,即:這些被聚合的物件,通常都是被資料庫持久化的集合,對資料庫系統操作無法被介面抽象隔離,而將技術實作引入領域模型,則有悖領域驅動設計的理念,

比如在極客時間的例子里,要對用戶已經訂閱過的專欄進行分頁顯示,因為性能原因,不能將DB中的Subscription資料全部讀取到記憶體中再進行分頁,而要在查詢DB時包含分頁邏輯,
那么分頁邏輯放在哪里,才能保持模型與軟體實作的關聯呢?

  • 一種做法是為Subscription構造一個獨立的Repository物件,將分頁邏輯放在里面,但這種做法會導致邏輯泄露,因為Subscription被User聚合,那么User所擁有的Subscription的集合邏輯應該被封裝在User中,為非聚合根提供Repository是一種壞味道,
  • 那么把分頁邏輯放到User上呢,這樣其實也不合適,因為這樣會將技術實作細節引入領域邏輯中,無法保持領域邏輯的獨立,

造成上面兩難局面的根源在于:我們希望在模型中使用集合介面,并借助它封裝具體實作的細節;這基于一個前提,即記憶體中的集合與資料庫是等價的,都可以通過集合介面封裝,但實際情況是,我們無法忽略資料庫帶來的額外開銷,兩者并不等價,

引入關聯物件

關聯物件是將物件間的關聯關系直接建模出來,然后再通過介面與抽象的隔離,把具體技術實作細節封裝到介面的實作中,

User與Subscription間存在關聯關系,所以新增一個關聯物件來表達:

public interface IMySubscriptions : IQueryable<Subscription>
{
  ...
}

public class User
{
  private IMySubscriptions _mySubscriptions;
}

這里的關聯物件為IMySubscriptions,User是Subscription的聚合根,與之相關的邏輯通過_mySubscriptions完成,仍然在User的背景關系中,沒有邏輯泄露,
然后,再通過介面與實作分離的方式,從領域物件中移除對具體技術實作的依賴,通過依賴注入的方式提供介面的具體實作:

public class MySubscriptionsDB : IMySubscriptions
或者資料來源于Restful API
public class MySubscriptionsAPI : IMySubscriptions

關聯物件實際上是通過將隱式的概念顯式化建模來解決問題的,這是面向物件技術解決問題的通則:永遠可以通過引入另一個物件解決問題,

背景關系過載

背景關系過載(Context Overloading)就是指領域模型中的某個物件會在多個背景關系中發揮重要作用,甚至是聚合根,這會導致物件本身變得很復雜、模型僵化;還可能帶來潛在的性能問題,

因富含邏輯而產生的過大類

假設之前的極客時間例子中,模型經過擴展后,包含了三個背景關系:

  1. 訂閱:用戶閱讀訂閱內容的背景關系,根據訂閱關系判斷哪些內容是用戶可見的;
  2. 社交:用戶維持朋友關系的背景關系,可以分享動態與資訊;
  3. 訂單:用戶購買專欄的背景關系,通過訂單與支付,完成對專欄的訂閱,

按照這個模型,得到的富含知識的實作為:

public class User
{
  // 社交背景關系
  private List<Friendship> _friendships;
  public void Make(Friendship friendship)
  {
  }

  // 訂閱背景關系
  private List<Subscription> _subscriptions;
  public void Subscribe(Subscription subscription)
  {
  }

  // 訂單背景關系
  private List<Order> _orders;
  public void PlaceOrder(Order order)
  {
  }
}

這個實作的問題在于一個物件包含了不同的背景關系,即壞味道:過大類,壞處有

  • 模型僵硬,想要理解這個類的行為,就必須理解所有的背景關系,只有理解了背景關系,才能判斷其中的代碼和行為是否合理,于是背景關系的過載就變成了認知的過載,而認知的過載又會造成維護的困難,出現“看不懂、改不動”的祖傳代碼,而改不動的代碼就是改不動的模型,最終提煉知識的回圈也就無法進行了;
  • 過大類還容易滋生重復代碼、引入偶然耦合造成的意外缺陷;
  • 性能問題,在不同的背景關系中,需要訪問的資料也不盡相同(這個問題可以通過引入關聯物件緩解)

邏輯匯聚于背景關系還是物體

背景關系過載的根本癥結在于:邏輯匯聚于背景關系還是物體,
DDD的默認風格是匯聚于物體,類似這里的User類;而如果根據DCI范型(Data-Context-Interaction,資料-背景關系-互動),則應該匯聚于顯式建模的背景關系物件(Context Object)中,或者背景關系中的角色物件(Role Object)中,
這樣做的原因是因為,在不同的背景關系中,用戶是以不同的角色與其他物件發生互動的,User在訂閱背景關系中的角色是Reader,在訂單背景關系中是Buyer,在社交背景關系中則是Contact,
而發生背景關系過載的根源為:物體在不同的背景關系中扮演的多個角色,再借由聚合關系,將不同背景關系的邏輯富集于物體中,導致了背景關系過載,
所以解決方案就是:針對不同背景關系的角色建模,將對應的邏輯富集到角色物件中,再讓物體物件去扮演不同的角色,

通過角色物件分離不同背景關系的邏輯

一種實作思路是通過裝飾器模式,構造一系列角色物件(Role Object)作為User的裝飾器:

public class Buyer
{
  private User _user;
  private List<Order> _orders;

  public Buyer(User user)
  {
    _user = user;
  }

  public void PlaceOrder(Order order)
  {
  }
}
public class Reader
{
  private User _user;
  private List<Subscription> _subscriptions;
  
  public Reader(User user)
  {
    _user = user;
  }
  
  public void Subscribe(Subscription subscription)
  {
  }
}
...

在具體的Repository實作中使用這些角色物件:

public class UserRepositoryDB : IUserRepository
{
  public User FindById(long id)
  {
    return db.ExecuteQuery(...);
  }

  public Buyer AsBuyer(User user)
  {
    return new Buyer(user, db.ExecuteQuery(...));
  }

  public Reader AsReader(User user)
  {
    return new Reader(user, db.ExecuteQuery(...));
  }
}

之后,就可以類似下面這樣獲取角色物件了:

var user = repo.FindById(1);
var buyer = repo.AsBuyer(user);
var reader = repo.AsReader(user);

使用角色物件的好處:

  • 把不同背景關系中的邏輯分別富集于不同的角色物件中;解決了認知過載的問題,同時也通過封裝隔離了不同背景關系的變化,
  • 從物體物件轉化到角色物件經由了顯式的方法呼叫,這實際上清晰地表示了背景關系的切換,

但這個方案在揭示意圖、技術解耦上還做得不夠好;比如假設不是所有資料都來自資料庫,社交背景關系中的朋友關系來自Restful API呼叫,這種情況下,將AsContact放到UserRepositoryDB就不合適了,

通過背景關系物件分離不同背景關系的邏輯

既然將角色轉換的邏輯放到UserRepositoryDB不合適,那么借鑒前面關聯物件的思路,將背景關系直接建模出來,并通過介面隔離具體實作:

public interface IOrderContext
{
  interface IBuyer
  {
    void PlaceOrder(Order order);
  }

  IBuyer AsBuyer(User user);
}
public interface ISocialContext
{
  interface IContact
  {
    void Make(Friendship friendship);
  }

  IContact AsContact(User user);
}
public interface ISubscriptionContext
{
  interface IReader
  {
    void Subscribe(Subscription subscription);
  }

  IReader AsReader(User user);
}

然后將背景關系物件的獲取放置到IUserRepository介面中,并在其實作中使用依賴注入獲取不同的背景關系物件:

public interface IUserRepository
{
  User FindUserById(long id);
    
  ISubscriptionContext InSubscriptionContext();
  ISocialContext InSocialContext();
  IOrderContext InOrderContext();
}

public class UserRepositoryDB: IUserRepository
{
  //通過依賴注入獲取不同的背景關系物件
  private ISubscriptionContext subscriptionContext;
  private ISocialContext socialContext;
  private IOrderContext orderContext;
  ....
}

最后的使用方式就成了:

var buyer = repo.InOrderContext().AsBuyer(user);
var reader = repo.InSubscriptionContext().AsReader(user);
var contact = repo.InSocialContext().AsContact(user);

使用背景關系物件重構后得到的好處有:

  • 借由背景關系的封裝,不同背景關系中的技術實作可以是異構的,不管資料來自資料庫還是第三方API,這些細節都不會暴露給使用者;
  • 軟體實作、模型、統一語言更加緊密地關聯在了一起,背景關系物件與界限背景關系對應,
  • 更加清楚地揭示了領域知識的意圖,如下圖的領域模型:
    包含背景關系的模型
    通過如下IUserRepository的定義可知,User在三個不同的背景關系中扮演不同的角色,
public interface IUserRepository
{
  User FindUserById(long id);
    
  ISubscriptionContext InSubscriptionContext();
  ISocialContext InSocialContext();
  IOrderContext InOrderContext();
}

架構分層

如何組織領域邏輯與非領域邏輯,才能避免非領域邏輯對模型的污染,通常會使用分層架構來區分不同的邏輯,將不同的關注度的邏輯封裝到不同的層中,以便擴展維護,同時也能有效地控制變化的傳播,
不同層有不同的需求變化速率(Pace of changing),分層架構對變化傳播的控制,是通過層與層之間的依賴關系實作的,因為下層的修改會波及到上層,所以希望通過層來控制變化的傳播,只要所有層都單向依賴比自己更穩定的層,那么變化就不會擴散了,

DDD中的分層的問題

在DDD中通常會將系統分為四層:
四層架構

  1. 展現層(Representation Layer),負責給最終用戶展現資訊,并接受用戶的輸入作為功能的觸發點,如果不是人機互動系統,用戶也可以是其他軟體系統,
  2. 應用層(Application Layer),負責支撐具體的業務或者互動流程,將業務邏輯組織為軟體的功能,
  3. 領域層(Domain Layer),核心的領域概念、資訊與規則,它不隨應用層的流程、展現層的界面以及基礎設施層的能力改變而改變,
  4. 基礎設施層(Infrastructure Layer),通用的技術能力,比如資料庫、MQ等,

基礎設施層與領域層誰更穩定

在上圖的四層架構中

  • 展現層最容易改變:新的互動模式、不同的視覺模板都會導致改變;
  • 應用層的邏輯會隨著業務流程以及功能點的變化而改變,比如流程的重組與優化、新功能點的引入;
  • 領域層是核心領域概念的提取,理論上來說,如果通過知識消化完成模型的提取,那么由模型構成的領域層應該就是穩定態了,不會發生重大變化;
  • 基礎設施層的邏輯由所選擇的技術堆疊決定,更改技術組件、替換框架都會造成基礎設施層的變化,基礎設施層的變化頻率與所用的技術組件有關,越是核心的組件,變化就越緩慢,比如相對資料庫,快取系統的變化頻率往往會更快,

此外,基礎設施層還可能發生不可預知的突變,比如過去的NoSQL、大資料、云計算都曾為基礎設施層帶來過突變,而且,周圍系統生態的演化與變更也會造成影響,比如訊息通知系統從短信變成微信,支付從網銀變成移動支付等等,

總之基礎設施層沒有領域層穩定,但上圖中,怎么能讓領域層依賴基礎設施層呢?

基礎設施不是層

領域模型對基礎設施的態度是非常微妙的,一方面,領域邏輯必須依賴基礎設施才能完成相應的功能,另一方面,領域模型必須強調自己的穩定性,才能維持它在架構中的核心位置,為了解決這個矛盾,要么承認領域層并不是最穩定的;要么就別把基礎設施當層看,

領域層被人為地設定為最穩定的,實際上可以將領域層看做“在特定技術堆疊上的領域模型實作”;但這樣可能無法被大多數DDD實踐者接受,所以剩下一個選擇:基礎設施不是層,

能力供應商模式

如何才能取消基礎設施層,但仍然不影響領域模型的實作呢,可以使用能力供應商(Capability Provider)模式,

從基礎設施到有業務含義的能力

假設極客時間的訂單需要通過網銀來支付,并通過郵件將訂單狀態發送給客戶,模型為:
訂單支付模型1
偽代碼:

public class Order {
    public void Pay(){
        bank.pay(...);
        email.send(...);
    }
}

這樣的實作有個問題是領域層的Order直接依賴了基礎設施層的網銀支付、發郵件功能;而領域層是絕對穩定的,它不能依賴任何非領域邏輯(除了基礎庫),

怎么辦呢,需要將對基礎設施層的依賴,看做一種未被發現的領域概念進行提取,這樣其實就發揮了我們定義業務的權利,從業務角度去思考技術組件的含義,

將技術組件進行擬人化處理

通過擬人化,可以清楚地看到技術組件幫我們完成了什么業務操作,比如轉賬的時出納(Cashier),通知用戶的是客戶(Customer Service),于是模型就能轉化為:
擬人化

這樣就可以將具有業務含義的能力抽象成介面納入領域層,而使用基礎設施的技術能力去實作領域層的介面,即基礎設施層成為了能力供應商,
雖然從實作上看,只是將對具體實作的依賴,轉化為對介面的依賴,但這樣做的好處卻契合了“兩關聯”:

  • 領域模型與軟體實作關聯
  • 統一語言與模型關聯

使用能力供應商的多層架構

可以將基礎設施看做對不同層的擴展或貢獻,它雖被介面隔離,卻是其它層的有機組成部分,作為能力供應商,參與層內、層間的互動,
使用能力供應商的多層架構

能力供應商是一個元模式,關聯物件、角色物件、背景關系物件都可以看做它的具體應用,

能力供應商模式的缺點

能力供應商模式有一個缺點是將顯式的依賴關系,轉化為了隱式的依賴關系,這就對知識管理有了更高的要求,
這里把技術概念轉換成了領域概念,并反映到統一語言上,這就需要團隊不斷地執行回圈,才能把知識消化掉,業務方與技術方也需要緊密地配合與信任,

不要用解決方案去定義問題,而是問題定義解決方案,相同的解決方案,在面對不同的問題是就是不同的模式,比如代理模式 裝飾器模式 中介者模式,解決方案都是一個類代理給另一個類,但它們并不是同一個東西

參考資料
極客時間:如何落地業務建模 徐昊

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

標籤:其他

上一篇:指紋登錄是怎么跑起來的

下一篇:微服務架構 | 1. 微服務相關基礎知識

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