自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

軟件項(xiàng)目架構(gòu)簡明進(jìn)化史

開發(fā) 架構(gòu)
這里,作者將跟我們分享一個(gè)局部架構(gòu)的進(jìn)化過程。這一演進(jìn)過程,歡迎大家來討論和分析。

  1引言

  在標(biāo)題的取名上,不敢說頗費(fèi)心機(jī),也算得上花費(fèi)了一點(diǎn)功夫的。首先想到的是“架構(gòu)設(shè)計(jì)過程”,又覺得是不是太大了,因?yàn)槔颖容^局部,不是很完整。叫做“結(jié)構(gòu)變化過程”可能更好點(diǎn)。但是又怕名字取的小氣了,進(jìn)來的人少,參與討論的就更少了,最終還是取了這個(gè)有點(diǎn)忽悠人的標(biāo)題“架構(gòu)演進(jìn)”。

  今天的這個(gè)架構(gòu)演進(jìn),使用系統(tǒng)中一個(gè)局部的實(shí)例進(jìn)行推導(dǎo)和演進(jìn),一起來觀察一下,架構(gòu)是如何不滿足需求的?架構(gòu)如何演進(jìn)?更好的架構(gòu)應(yīng)該具備哪些條件?有沒有更好的呢?

  業(yè)務(wù)場景

圖1 業(yè)務(wù)場景圖

  從上圖可以看出,就是一個(gè)電子商務(wù)網(wǎng)站常見的支付、支付的后續(xù)處理,這樣一個(gè)業(yè)務(wù)場景。支持多種支付方式,目前包括銀聯(lián)、支付寶,還有平臺(tái)賬戶。平臺(tái)賬戶就是注冊用戶將資金存儲(chǔ)在平臺(tái)為用戶建立并維護(hù)的一個(gè)賬戶里,購買平臺(tái)的產(chǎn)品,可以使用平臺(tái)賬戶中的資金進(jìn)行支付。

  2業(yè)務(wù)流程

  首先用戶選擇商品。

  下單,進(jìn)行支付。

  選擇支付方式。

  使用相應(yīng)支付方式進(jìn)行支付。第三方支付,會(huì)跳轉(zhuǎn)到第三方的支付頁面進(jìn)行支付。

  平臺(tái)進(jìn)行支付的后續(xù)處理,包括成功之后的修改狀態(tài)等,還包括失敗之后的記錄標(biāo)記等。

  第三方的支付,在打開第三方支付界面的時(shí)候,會(huì)告訴它一個(gè)平臺(tái)的回調(diào)地址,支付之后,通過回調(diào)地址接收第三方支付的結(jié)果,然后進(jìn)行后續(xù)處理。使用平臺(tái)賬戶支付,就直接進(jìn)行后續(xù)處理就可以了。

  當(dāng)然,這其中還會(huì)有一些細(xì)節(jié),不在我們的討論范圍。例如:使用平臺(tái)賬戶進(jìn)行支付,判斷賬戶金額是否充足。使用第三方支付,是否記錄第三方支付的完整過程,以及完整的支付流程。等等具體的業(yè)務(wù)細(xì)節(jié)均不在今天的討論范圍。

  3初級架構(gòu)-用存儲(chǔ)過程搞定它

  回調(diào)地址接收兩個(gè)參數(shù),一個(gè)是訂單編號(hào),一個(gè)是標(biāo)志。標(biāo)志說明是成功還是失敗,或者是更加詳細(xì)的信息。

  1.   CREATE PROCEDURE Proc_PaymentHandle  
  2.   @OrderSeqNo VARCHAR(36), --訂單編號(hào)  
  3.   @ReturnCode VARCHAR(10), --返回狀態(tài)碼  
  4.   @PaymentManner CHAR(1) --支付方式:1銀聯(lián),2支付寶,3平臺(tái)賬戶  
  5.   AS  
  6.   BEGIN  
  7.   IF(@PaymentManner='1')  
  8.   BEGIN  
  9.   --更新訂單狀態(tài)  
  10.   --更新銀聯(lián)支付信息  
  11.   RETURN;  
  12.   END  
  13.   ELSE IF(@PaymentManner='2')  
  14.   BEGIN  
  15.   --更新訂單狀態(tài)  
  16.   --更新支付寶支付信息  
  17.   RETURN;  
  18.   END  
  19.   ELSE IF(@PaymentManner='3')  
  20.   BEGIN  
  21.   --更新定的狀態(tài)  
  22.   --更新平臺(tái)賬戶支付信息  
  23.   RETURN;  
  24.   END  
  25. END 

  配合一段C#代碼,判斷一下支付方式,然后給存儲(chǔ)過程傳遞參數(shù)。這樣寫的話,上面的這個(gè)存儲(chǔ)過程很容易就超過1k行了,相信大家也寫過1k行以上的存儲(chǔ)過程,也維護(hù)過這樣的存儲(chǔ)過程,知道個(gè)中的酸甜苦辣。

  如果說那一天我們增加了一種支付方式,需要修改的地方包括哪些呢?

  界面要修改,存儲(chǔ)過程要打開修改,調(diào)用的C#代碼要修改。真是有點(diǎn)麻煩,最主要的是容易改錯(cuò)了,誤改了不應(yīng)該動(dòng)的地方才是最要命的。好吧,我們簡單分離一下。每種支付方式一個(gè)存儲(chǔ)過程,把對于支付方式的判斷放在代碼中,每種支付對應(yīng)一個(gè)代碼中的方法。這樣需要增加一種的話,只要改改支付方式判斷的代碼,然后重新寫一個(gè)存儲(chǔ)過程,重新寫一個(gè)方法調(diào)用一下新的存儲(chǔ)過程就可以了??墒沁€有一個(gè)問題,更新訂單狀態(tài)好像大家都在做,如果哪一些還需要加一些大家都需要做的事情呢?或者說修改一些大家都需要做的事情的細(xì)節(jié)?又或者說某兩個(gè)支付方式需要增加一個(gè)處理流程呢?打開存儲(chǔ)過程,狂修改吧?。。?!

  存儲(chǔ)過程有幾個(gè)不便利的地方:

  調(diào)試不方便

  測試不方便

  代碼不能折疊,多了之后要拖動(dòng)滾動(dòng)條才能找得到

  邏輯運(yùn)算、大規(guī)模計(jì)算是存儲(chǔ)過程的弱項(xiàng)

  存儲(chǔ)過程的優(yōu)勢至少也有一個(gè),就是修改之后,馬上可以見到效果。不用編譯。

  4中級架構(gòu)-在代碼中分離對每種信息的更新

  之前的架構(gòu)代碼中有很多的重復(fù)地方,例如:對于訂單信息的更新。如何把重復(fù)降低呢?降低重復(fù)也就集中了代碼,集中了將來也好維護(hù)。而且把它分離出來,獨(dú)立出來,好像更好點(diǎn),在需要的地方調(diào)用就可以了。如果需要變更訂單的更新細(xì)節(jié),只要修改一下更新細(xì)節(jié)就可以了,不需要?jiǎng)又Ц兜拇a。減小犯錯(cuò)誤的概率。

  首先,將各種更新信息獨(dú)立出來。

  1.   public class OrderRepository2  
  2.   {  
  3.   public void UpdateState()  
  4.   { throw new System.Exception(); }  
  5.   }  
  6.   public class PlatformAccountRepository2  
  7.   {  
  8.   public void Update()  
  9.   { throw new System.Exception(); }  
  10.   }  
  11.   public class ZhifubaoRepository2  
  12.   {  
  13.   public void Update()  
  14.   { throw new System.Exception(); }  
  15.  }  
  16.  public class YinlianRepository2  
  17.   {  
  18.   public void Update()  
  19.   { throw new System.Exception(); }  
  20.   } 

  使用下面的方法進(jìn)行支付的后續(xù)處理。

  1.   public void HandlePaymentResult(PaymentManner2 paymentManner, string orderSeqNo)  
  2.   {  
  3.   switch (paymentManner)  
  4.   {  
  5.   case PaymentManner2.PlatformAccount :  
  6.   var platformService = new PlatformAccountPaymentResultHandleService2();  
  7.   platformService.Handle(orderSeqNo);  
  8.   break;  
  9.   case PaymentManner2.Yinlian :  
  10.   var yinlianService = new YinlianPaymentResultHandleService2();  
  11.   yinlianService.Handle(orderSeqNo);  
  12.   break;  
  13.   case PaymentManner2.Zhifubao :  
  14.   var zhifubaoService = new ZhifubaoPaymentResultHandleService2();  
  15.   zhifubaoService.Handle(orderSeqNo);  
  16.   break;  
  17.   }  
  18.   } public enum PaymentManner2  
  19.   {  
  20.   Zhifubao,  
  21.   Yinlian,  
  22.   PlatformAccount  
  23.   }  
  24.   public class ZhifubaoPaymentResultHandleService2  
  25.   {  
  26.   private OrderRepository2 _orderManagement;  
  27.   private ZhifubaoRepository2 _zhifubaoManagement;  
  28.   public void Handle(string orderSeqNo)  
  29.   {  
  30.   using (TransactionScope scope = new TransactionScope())  
  31.   {  
  32.   _orderManagement.UpdateState();  
  33.   this._zhifubaoManagement.Update();  
  34.   scope.Complete();  
  35.   }  
  36.   }  
  37.   }  
  38.   public class YinlianPaymentResultHandleService2  
  39.   {  
  40.   private OrderRepository2 _orderManagement;  
  41.   private YinlianRepository2 _yinlianManagement;  
  42.   public void Handle(string orderSeqNo)  
  43.   {  
  44.   using (TransactionScope scope = new TransactionScope())  
  45.   {  
  46.   this._orderManagement.UpdateState();  
  47.   this._yinlianManagement.Update();  
  48.   scope.Complete();  
  49.   }  
  50.   }  
  51.   }  
  52.   public class PlatformAccountPaymentResultHandleService2  
  53.   {  
  54.   private OrderRepository2 _orderManagement;  
  55.   private PlatformAccountRepository2 _platformAccountManagement;  
  56.   public void Handle(string orderSeqNo)  
  57.   {  
  58.   using (TransactionScope scope = new TransactionScope())  
  59.   {  
  60.   this._orderManagement.UpdateState();  
  61.   this._platformAccountManagement.Update();  
  62.   scope.Complete();  
  63.   }  
  64.   }  
  65.   } 

  增加支付方式的話,新建一個(gè)HandleService類,寫一些處理代碼,然后在public void HandlePaymentResult(PaymentManner2 paymentManner, string orderSeqNo)方法的switch中增加一個(gè)case就可以了。

  但是頁面的可選支付方式還是寫死了,沒有動(dòng)態(tài)的變化,支付方式是否可以動(dòng)態(tài)配置呢?而且可以方便的測試呢?例如:雖然我還沒有銀聯(lián)的接口,但是我想測試一些,銀聯(lián)支付之后平臺(tái)的處理是否正確,該更新的信息是否都更新了呢?沒有銀聯(lián)的接口,是不是就不能做了呢?有沒有辦法解決呢?

  答案是:有。

  還有就是上面的switch。。。case,好像會(huì)很長,也很丑,這個(gè)地方能否改進(jìn)呢?很多人在學(xué)習(xí)了重構(gòu)之后,會(huì)提出很多的方法來解決這個(gè)問題,我們再后面也一塊來解決一下。

  5高級架構(gòu)-少用存儲(chǔ)過程處理業(yè)務(wù)的靈活架構(gòu)

  我們的高級架構(gòu)有幾個(gè)目標(biāo)

  減少存儲(chǔ)過程中的業(yè)務(wù)邏輯,讓存儲(chǔ)過程更加純粹的做事,做它擅長的事情。

  可以靈活的增加或者減少支付方式。達(dá)到在增加或者減少支付方式的時(shí)候,盡量少的修改代碼,盡量減少依賴。減少支付對于支付方式的依賴,支付方式對于后續(xù)處理的依賴。

  代碼結(jié)構(gòu)更加清晰。

  為了達(dá)到上面的幾個(gè)目標(biāo),計(jì)劃獨(dú)立幾個(gè)部分。

  支付方式的管理。

  每一種支付方式的處理過程。這個(gè)在中級架構(gòu)里面已經(jīng)做的差不多了,這里會(huì)做的更好一點(diǎn),抽象這個(gè)支付處理過程。

  還有就是要隱藏支付方式和具體的支付方式處理過程映射代碼。具體的支付方式指的是:銀聯(lián)或者是支付寶這種具體的一種支付方式。目的就是讓對于支付訂單的處理獨(dú)立化,固定化,支持變化。

  5.1支付方式的管理

  1.   public enum PaymentManner1{  
  2.   Zhifubao,  
  3.   Yinlian,  
  4.   PlatformAccount  
  5.   }  
  6.   public class PaymentMannerParams  
  7.   {  
  8.   /// <summary>  
  9.   /// 地址還是內(nèi)部方法  
  10.   /// </summary>  
  11.   public UriOrFunction UriOrFunction { getset; }  
  12.   /// <summary>  
  13.   /// 地址  
  14.   /// </summary>  
  15.   public string Uri { getset; }  
  16.   /// <summary>  
  17.   /// 方法名  
  18.   /// </summary>  
  19.   public string FunctionName { getset; }  
  20.   enum UriOrFunction  
  21.   {  
  22.   Uri,  
  23.   Function  
  24.   }  
  25.   }  
  26.   public class PaymentMannerManagement1  
  27.  {  
  28.   public Dictionary<PaymentManner1, PaymentMannerParams >FindAvailableManner(decimal moneyOfPay)  
  29.   {  
  30.   throw new System.Exception();  
  31.   }  
  32.   } 

  通過FindAvailableManner方法獲取支付方式。每種支付方式PaymentManner,都帶有一個(gè)參數(shù)實(shí)體PaymentMannerParams,里面的UriOrFunction來決定是通過網(wǎng)頁還是內(nèi)部方法來支付,Uri就跳轉(zhuǎn)到Uri就可以了,F(xiàn)unction就調(diào)用FunctionName中的方法就可以了。支付的時(shí)候用下面的Pay先獲取支付方式信息,然后根據(jù)每種支付方式的參數(shù)來決定具體的支付。

  1.   public class OrderManagement1  
  2.   {  
  3.   public void Pay(decimal money)  
  4.   {  
  5.   var manner= new PaymentMannerManagement1().FindAvailableManner(money);  
  6.   //后續(xù)支付  
  7.   }  
  8.   } 

  之前說的,如果銀聯(lián)還沒有接口,或者接口暫時(shí)不能用了,想測試一下后續(xù)的處理,就可以將銀聯(lián)這種Manner的UriOrFunction設(shè)置為Function,現(xiàn)用內(nèi)部的方法來測試后續(xù)的處理是否正確。等可以用的時(shí)候,在變更為Uri就可以了。

  5.2支付過程的抽象

  通過建立支付處理的接口,將支付處理的代碼抽象成下面的樣子。

  1.   public class Service1  
  2.   {  
  3.   public void HandlePaymentResult(PaymentManner1 paymentManner,string orderSeqNo)  
  4.   {  
  5.   IPaymentResultHandleService1 handleService = PaymentResultHandleServiceFactory1.GetService(paymentManner);  
  6.   handleService.Handle(orderSeqNo);  
  7.   }  
  8.   } 

  這個(gè)處理的代碼,原則來說以后都不需要修改了。后面要做的就是定義一種新的支付方式枚舉量,然后實(shí)現(xiàn)IPaymentResultHandleService1 接口,寫一些處理的代碼就可以了。

  5.3完整代碼using System;

  1.   using System.Collections.Generic;  
  2.   using System.Linq;  
  3.   using System.Text;  
  4.   using System.Transactions;  
  5.   namespace ConsoleApplication1  
  6.  {  
  7.   public class Service1  
  8.   {  
  9.   public void HandlePaymentResult(PaymentManner1 paymentManner,string orderSeqNo)  
  10.   {  
  11.   IPaymentResultHandleService1 handleService = PaymentResultHandleServiceFactory1.GetService(paymentManner);  
  12.   handleService.Handle(orderSeqNo);  
  13.   }  
  14.   }  
  15.   public class OrderManagement1  
  16.   {  
  17.   public void Pay(decimal money)  
  18.   {  
  19.   var manner= new PaymentMannerManagement1().FindAvailableManner(money);  
  20.   //后續(xù)支付  
  21.   }  
  22.   }  
  23.   public enum PaymentManner1  
  24.   {  
  25.   Zhifubao,  
  26.   Yinlian,  
  27.   PlatformAccount  
  28.   }  
  29.   public class PaymentMannerParams  
  30.   {  
  31.   /// <summary>  
  32.   /// 地址還是內(nèi)部方法  
  33.   /// </summary>  
  34.   public UriOrFunction UriOrFunction { getset; }  
  35.   /// <summary>  
  36.   /// 地址  
  37.   /// </summary>  
  38.   public string Uri { getset; }  
  39.   /// <summary>  
  40.   /// 方法名  
  41.   /// </summary>  
  42.   public string FunctionName { getset; }  
  43.   enum UriOrFunction  
  44.   {  
  45.   Uri,  
  46.   Function  
  47.   }  
  48.   }  
  49.   public class PaymentMannerManagement1  
  50.   {  
  51.   public Dictionary<PaymentManner1, PaymentMannerParams >FindAvailableManner(decimal moneyOfPay)  
  52.   {  
  53.   throw new System.Exception();  
  54.   }  
  55.   }  
  56.   public class PaymentResultHandleServiceFactory1  
  57.   {  
  58.   private static PaymentResultHandleServiceFactory1()  
  59.   {  
  60.   _serviceMap = new Dictionary<PaymentManner1, IPaymentResultHandleService1>();  
  61.   _serviceMap.Add(PaymentManner1.PlatformAccount, new PlatformAccountPaymentResultHandleService1());  
  62.   _serviceMap.Add(PaymentManner1.Yinlian, new YinlianPaymentResultHandleService1());  
  63.   _serviceMap.Add(PaymentManner1.Zhifubao,new ZhifubaoPaymentResultHandleService1());  
  64.   }  
  65.   private static Dictionary<PaymentManner1 , IPaymentResultHandleService1> _serviceMap;  
  66.   public static IPaymentResultHandleService1 GetService(PaymentManner1 paymentManner )  
  67.   {  
  68.   return _serviceMap[paymentManner];  
  69.   }  
  70.   }  
  71.   public interface IPaymentResultHandleService1  
  72.   {  
  73.   void Handle(string orderSeqNo);  
  74.   }  
  75.   public class ZhifubaoPaymentResultHandleService1:IPaymentResultHandleService1  
  76.   {  
  77.   private OrderRepository1 _orderManagement;  
  78.   private ZhifubaoRepository1 _zhifubaoManagement;  
  79.   public void Handle(string orderSeqNo)  
  80.   {  
  81.   using (TransactionScope scope = new TransactionScope())  
  82.   {  
  83.   _orderManagement.UpdateState();  
  84.  this._zhifubaoManagement.Update();  
  85.  scope.Complete();  
  86.   }  
  87.   }  
  88.   }  
  89.   public class YinlianPaymentResultHandleService1 : IPaymentResultHandleService1  
  90.  {  
  91.   private OrderRepository1 _orderManagement;  
  92.   private YinlianRepository1 _yinlianManagement;  
  93.   public void Handle(string orderSeqNo)  
  94.   {  
  95.   using (TransactionScope scope = new TransactionScope())  
  96.   {  
  97.   this._orderManagement.UpdateState();  
  98.   this._yinlianManagement.Update();  
  99.   scope.Complete();  
  100.   }  
  101.   }  
  102.   }  
  103.   public class PlatformAccountPaymentResultHandleService1:IPaymentResultHandleService1  
  104.   {  
  105.   private OrderRepository1 _orderManagement;  
  106.   private PlatformAccountRepository1 _platformAccountManagement;  
  107.   public void Handle(string orderSeqNo)  
  108.   {  
  109.   using (TransactionScope scope = new TransactionScope())  
  110.   {  
  111.   this._orderManagement.UpdateState();  
  112.   this._platformAccountManagement.Update();  
  113.   scope.Complete();  
  114.   }  
  115.   }  
  116.   }  
  117.   public class OrderRepository1  
  118.   {  
  119.   public void UpdateState()  
  120.   { throw new System.Exception(); }  
  121.   }  
  122.   public class PlatformAccountRepository1  
  123.   {  
  124.   public void Update()  
  125.  { throw new System.Exception(); }  
  126.  }  
  127.   public class ZhifubaoRepository1  
  128.   {  
  129.  public void Update()  
  130.  { throw new System.Exception(); }  
  131.   }  
  132.   public class YinlianRepository1  
  133.   {  
  134.   public void Update()  
  135.   { throw new System.Exception(); }  
  136.   }  
  137.   } 

  6總結(jié)

  類的依賴最好使用抽象,避免具體類的直接引用。

  盡量不要再存儲(chǔ)過程中處理業(yè)務(wù),在系統(tǒng)越做越大,你會(huì)越來越贊同我的說法。原因至少兩點(diǎn):1維護(hù)累死人,2數(shù)據(jù)庫不擅長數(shù)值計(jì)算和處理。

  職責(zé)單一,功能獨(dú)立,代碼分離。

原文鏈接:http://www.cnblogs.com/virusswb/archive/2011/08/31/2160708.html

【編輯推薦】

  1. 淺析淘寶數(shù)據(jù)魔方技術(shù)架構(gòu)
  2. 淺析.NET設(shè)計(jì)架構(gòu)十條箴言
  3. 揭秘Google+技術(shù)架構(gòu)
  4. 揭秘新版SkyDrive架構(gòu)的幕后
  5. 97條架構(gòu)師須知
責(zé)任編輯:彭凡 來源: 博客園
相關(guān)推薦

2014-09-01 16:29:34

2011-12-21 16:44:00

信息圖手機(jī)進(jìn)化史

2018-08-22 17:58:01

數(shù)據(jù)平臺(tái)數(shù)據(jù)倉庫架構(gòu)

2010-07-27 14:04:52

2011-11-03 15:25:07

Android

2011-11-29 09:54:20

Google進(jìn)化史

2018-07-19 08:54:48

微服務(wù)架構(gòu)Java

2010-01-21 16:08:26

C++語言

2010-10-09 14:46:20

2024-09-21 10:43:15

數(shù)據(jù)技術(shù)信息

2018-03-23 12:20:25

數(shù)據(jù)中心網(wǎng)絡(luò)數(shù)據(jù)

2010-04-07 14:54:20

Unix操作系統(tǒng)

2020-11-23 10:35:52

Emotet

2025-03-17 11:57:38

2019-08-29 08:13:28

2022-03-25 14:01:20

元宇宙虛擬世界進(jìn)化

2023-11-27 09:23:19

2016-02-04 09:17:59

2023-04-13 13:25:40

ChatGPTGPT神經(jīng)網(wǎng)絡(luò)

2014-08-13 10:31:26

Windows操作系統(tǒng)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)