.NET應用架構設計—表模組模式與事務指令碼模式的程式碼編寫

王清培發表於2014-08-25

閱讀目錄:

  • 1.背景介紹
  • 2.簡單介紹表模組模式、事務指令碼模式
  • 3.正確的編寫表模組模式、事務指令碼模式的程式碼
  • 4.總結

1.背景介紹

要想正確的設計系統架構就必須能正確的搞懂每個架構模式的用意,而不是鬍子眉毛一把抓。現在有一個現象是什麼呢,專案的結構從表面上看是很不錯,層分的很合理,其實對業務系統來說也就那麼幾種層設計方法,但是現在很多專案的邏輯架構的設計不是理想,有很多概念大家並不是很瞭解,當然也許每個人對技術的追求不同罷了。不管你追求不追求,事實我們還是要去往正確的方向努力才對的。

很多人包括我自己在內,都是寫過很多年的過程式的程式碼,層對我當年來說就是個擺設而已,最典型的問題就是我們總是將表模組模式和事物指令碼模式一起混著使用,什麼意思呢,就是說我們都會使用一些程式碼生成器來根據資料庫中的表來生成三層架構中的業務層和資料層,有些比較好的程式碼生成器也可以幫你把UI層中的部分檢視也生成好,確實很強大,有些場合下這是一中最合適的過程。

但是現在的系統已經不在是那樣的了,其中重要的一點就是業務複雜了,如果我們還稀裡糊塗的編寫著程式碼,最後只會成為你或者團隊的技術債務。

2.簡單介紹表模組模式、事務指令碼模式

我們簡單瞭解一下這裡所謂的“表模組模式、”事務指令碼模式“到底是什麼樣子的模式,最關鍵是你也許就知道了你目前所使用的業務層架構風格是什麼模式,強調一下“表模組模式”、“事物指令碼模式”都是業務層的構架模式

表模組模式:

簡單講就是你資料庫中的每個表對應著業務層中的一個物件定義,如果你有一個Product表,那麼你在Business Layer中就有一個Product.cs檔案,當然這不是絕對的,你也可以將庫中的檢視也定義一個型別,如,OrderProduct.cs,也是可以的。然後每個類中的所處理的邏輯都是跟這張表相關的,你在Product.cs中的程式碼就不要包含Order.cs中的程式碼了。目前來看是有的,因為現在大部分的專案都是在寫著使用過程式的程式碼,也就是事物指令碼模式,這樣難免會將其他型別中的程式碼寫到本類中。

事物指令碼模式:

事務指令碼模式就是過程式的程式碼,只不過它的指標就是每一個程式碼段獨立完成一個業務單元,而不是到處都是過程程式碼,事物指令碼模式還是很強調邏輯的統一性的。

使用此模式進行寫程式碼時,你就不要單純的使用資料庫中的表名來定義業務類了,因為你是使用事務指令碼模式的,你需要站在業務角度來規劃你的業務層中大概包含哪些業務概念,然後使用這個業務概念來命名你的類。比如:UserOrder,UserOrder,類似這樣的定義,當然這裡只是個假設而已,你不要站在資料庫的指令碼來設計業務層就行了,這樣你就起碼不會使用到很細粒度的型別,哪怕下一次迭代進行重構也是可以的。

3.正確的編寫表模組模式、事務指令碼模式的程式碼

這篇文章的重點就是本節,我們將瞭解一下這兩種模式的程式碼到底該如何編寫。

說程式碼如何編寫似乎有點讓人覺得不是很禮貌,其實我們大部分的程式碼寫的都是正確的,但是如果我們將有些程式碼稍微的羅一下位置就會明顯不一樣。

我們來看一個小例子,例子很簡單,有兩個型別Order、Product,用來完成一般的業務邏輯處理,我們通過不同的模式來看到底如何使用

現在的事務指令碼模式的程式碼:

namespace Business
{
    public class Order
    {
        [Serializable]
        public class OrderField
        {
            public string OId { get; set; } 

            [NonSerialized]
            public List<Product.ProductField> Products { get; set; }
        } 

        public OrderField Field { get; set; } 

        public void AddOrder(OrderField orderField)
        {
            var sendMQOrders = new List<string>();//合格的產品ID集合 

            orderField.Products.ForEach(product =>
            {
                if (product.Price <= 20)//不滿足條件
                    return; 

                sendMQOrders.Add(product.PId);//滿足條件
            }); 

            MqHelper.SendOrder(orderField, sendMQOrders);//傳送訂單資料實體到佇列中
        }
    }
}

Order業務類中有一個新增Order的方法,在該方法中是一些簡單的業務邏輯處理,判斷了要新增的這個商品的價格是否大於20塊錢。最後使用過濾下來的商品ID作為本訂單的有效產品。

這就是我們目前使用的程式碼風格,這裡有兩個問題,第一:類的命名,Order的概念太大了,沒有進行細化,顯然不是按照事務指令碼模式來進行設計的而是按照表模組方式進行劃分的,還有如果我就算你是按照事物指令碼模式來設計的,我就喜歡定義大的概念難道不對嗎?也可以,但是在Order的定義裡面明確使用了Product型別下的子型別,也就說這裡出現了兩個獨立的業務範圍,正常的理解肯定是按照表模組模式來設計的。第二:如果是按照表模組模式來設計的,因為根據這個物件的命名很明顯是此模式,但是仔細閱讀一下程式碼發現職責還是有點不清晰,在Order.AddOrder(OrderField orderField)方法中,有Product的邏輯在裡面if (product.Price <= 20),當然這裡是業務邏輯比較簡單的情況下的,如果是業務比較複雜的時候,就會出現大量的程式碼在Order類中,到最後就會發現我們已經分不清此業務架構到底是使用何種模式來設計的。

我們有兩個做法,第一個做法是:將其改成事務指令碼模式,讓類的命名和設計泛化,也就是說不要定義那麼明顯的資料庫中的表名字,不要清晰的區分Order和Product兩個職責。第二個做法是:將其改成表模組模式,將每個型別中的業務邏輯完全清晰化,將if (product.Price <= 20)提取到Product業務類中去,然後在應用控制器中先處理此邏輯後在呼叫Order.AddOrder(OrderField orderField)方法進行處理,這個方法裡面只做跟當前型別相關的邏輯,參考的依據就是一旦你發現你所寫的程式碼裡出現了別的型別時,此時你應該告訴自己有可能這個地方需要重構職責。

兩個方法來移動此邏輯:

1:(將if (product.Price <= 20)封進Price屬性中)

namespace Business
{
    public class Order
    {
        [Serializable]
        public class OrderField
        {
            public string OId { get; set; } 

            [NonSerialized]
            public List<Product.ProductField> Products { get; set; }
        } 

        public OrderField Field { get; set; } 

        public void AddOrder(OrderField orderField)
        {
            var sendMQOrders = new List<string>();//合格的產品ID集合 

            orderField.Products.ForEach(product =>
            {
                if (product.Price.IsValid()/*執行價格判斷*/) return; 

                sendMQOrders.Add(product.PId);//滿足條件
            }); 

            MqHelper.SendOrder(orderField, sendMQOrders);//傳送訂單資料實體到佇列中
        }
    }
}

此方法有個問題就是商品的價格沒有收到訂單的控制,這看具體的業務需要了,我只是個假設。

2:完全獨立的過濾無效產品的方法

namespace Business
{
    public class OrderApplicationController
    {
        public void SubmitOrder(Order.OrderField field)
        {
            field.Products = new Product().FilterProduct(field.Products);//先過濾 

            new Order().AddOrder(field);//在新增
        }
    }
}

我們先呼叫Product中的業務方法過濾無效的商品,然後在進行訂單新增操作,這樣我們就將各自的職責放到自己的位置去。

4.總結

還是那句話,這只是我學習過程中的一點小小的領悟,給大家一個參考的資料,希望對你有用,謝謝。

 

相關文章