日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
軟件項(xiàng)目架構(gòu)簡(jiǎn)明進(jìn)化史

1引言

曲陽(yáng)網(wǎng)站制作公司哪家好,找創(chuàng)新互聯(lián)!從網(wǎng)頁(yè)設(shè)計(jì)、網(wǎng)站建設(shè)、微信開(kāi)發(fā)、APP開(kāi)發(fā)、自適應(yīng)網(wǎng)站建設(shè)等網(wǎng)站項(xiàng)目制作,到程序開(kāi)發(fā),運(yùn)營(yíng)維護(hù)。創(chuàng)新互聯(lián)2013年開(kāi)創(chuàng)至今到現(xiàn)在10年的時(shí)間,我們擁有了豐富的建站經(jīng)驗(yàn)和運(yùn)維經(jīng)驗(yàn),來(lái)保證我們的工作的順利進(jìn)行。專注于網(wǎng)站建設(shè)就選創(chuàng)新互聯(lián)。

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

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

  業(yè)務(wù)場(chǎng)景

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

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

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

  首先用戶選擇商品。

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

  選擇支付方式。

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

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

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

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

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

  回調(diào)地址接收兩個(gè)參數(shù),一個(gè)是訂單編號(hào),一個(gè)是標(biāo)志。標(biāo)志說(shuō)明是成功還是失敗,或者是更加詳細(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ǔ)過(guò)程傳遞參數(shù)。這樣寫的話,上面的這個(gè)存儲(chǔ)過(guò)程很容易就超過(guò)1k行了,相信大家也寫過(guò)1k行以上的存儲(chǔ)過(guò)程,也維護(hù)過(guò)這樣的存儲(chǔ)過(guò)程,知道個(gè)中的酸甜苦辣。

  如果說(shuō)那一天我們?cè)黾恿艘环N支付方式,需要修改的地方包括哪些呢?

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

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

  調(diào)試不方便

  測(cè)試不方便

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

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

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

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

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

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

 
 
 
 
  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就可以了。

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

  答案是:有。

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

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

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

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

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

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

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

  支付方式的管理。

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

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

  5.1支付方式的管理

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

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

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

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

  5.2支付過(guò)程的抽象

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

 
 
 
 
  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è)處理的代碼,原則來(lái)說(shuō)以后都不需要修改了。后面要做的就是定義一種新的支付方式枚舉量,然后實(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.   /// 
  32.   /// 地址還是內(nèi)部方法
  33.   /// 
  34.   public UriOrFunction UriOrFunction { get; set; }
  35.   /// 
  36.   /// 地址
  37.   /// 
  38.   public string Uri { get; set; }
  39.   /// 
  40.   /// 方法名
  41.   /// 
  42.   public string FunctionName { get; set; }
  43.   enum UriOrFunction
  44.   {
  45.   Uri,
  46.   Function
  47.   }
  48.   }
  49.   public class PaymentMannerManagement1
  50.   {
  51.   public DictionaryFindAvailableManner(decimal moneyOfPay)
  52.   {
  53.   throw new System.Exception();
  54.   }
  55.   }
  56.   public class PaymentResultHandleServiceFactory1
  57.   {
  58.   private static PaymentResultHandleServiceFactory1()
  59.   {
  60.   _serviceMap = new Dictionary();
  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 _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ǔ)過(guò)程中處理業(yè)務(wù),在系統(tǒng)越做越大,你會(huì)越來(lái)越贊同我的說(shuō)法。原因至少兩點(diǎn):1維護(hù)累死人,2數(shù)據(jù)庫(kù)不擅長(zhǎng)數(shù)值計(jì)算和處理。

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


網(wǎng)頁(yè)題目:軟件項(xiàng)目架構(gòu)簡(jiǎn)明進(jìn)化史
網(wǎng)頁(yè)地址:http://www.5511xx.com/article/copooji.html