<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      關于兩個MVC示例的思考(MVCStore和Oxite)

            最近看了一些關于MVC框架的東西,加以之前就研究過一些關于 MVC架構的信息,碰巧在網上又看
      到了這樣一篇文章,是關于微軟內部的開發者對Oxite項目的個人攻擊,讓我產生了寫篇文章來表達一 
      下自己對于這種架構模式的思考。

          聲明,如果之前沒看過這兩個項目的朋友建議下載相應的源碼:
          MVCStore:http://www.codeplex.com/mvcsamples
          Oxite:http://www.codeplex.com/oxite

          好了,開始今天的正文:)

      1.Controller干了些什么

           先說一下我的看法,這個所謂控制器的最大作用應該是“控制和調度”,控制即前臺視圖(view)的
      顯示(顯示那個視圖), 調度即執行相應的業務邏輯 (在這兩個項目中就是那些Services,而Services
      即完成對model數據模型的封裝調用,并實現相關的業務邏輯)。這里業務規則如何定義應該是在Ser-
      vices里進行,與Controller無關。

           就其工作性質而言還是比較簡單的,因此簡要的工作內容就應該有簡單的實現(指代碼),這里可以
      看看MVCStore是如何搞的,請見下面代碼:

        (摘自Commerce.MVC.Web"App"Controller"AuthenticationController.cs):

      public class AuthenticationController : Controller
      {
              .
              
      public ActionResult Login()
              {
                  
      string oldUserName = this.GetUserName();

                  
      string login = Request.Form["login"];
                  
      string password = Request.Form["password"];

                  
      if (!String.IsNullOrEmpty(login) && !String.IsNullOrEmpty(password))
                  {
                      var svc 
      = new AspNetAuthenticationService();
                      
      bool isValid = svc.IsValidLogin(login, password);

                      
      //log them in
                      if (isValid)
                      {
                          SetPersonalizationCookie(login, login);

                          
      //migrate the current order
                          _orderService.MigrateCurrentOrder(oldUserName, login);

                          
      return AuthAndRedirect(login);
                      }
                  }
                  
      return View();
              }
          
      }


           一看便知這是一個登陸驗證操作,其使用Request.Form方式從表單中獲取數據,這里暫不說其獲取的方式
      優不優雅(因為與本文要聊的內容關系不大)。可以看出其實現的過程也之前采用webform方式開發出現的代碼
      也差不多,只不過是將相應的login.aspx.cs中的操作放到這controller中,這種好處主要就是將原本分散但功
      能上應該同屬于認證的類(Authentication類是按架構設時劃分出來的)放置在了一起,這樣在代碼分布上會
      更合理一些。另外就是進行單元測試時也會很容易編寫測試代碼。當然還有好處,我想就是將那些經常變化的
      代碼使用這種方式約束在了controller中,為將來的后續開發,特別是維護以及查找BUG上會有一個比較清晰的
      范圍。

           當然在看Oxite代碼時,這塊會有所差異,即Oxite使用了IModelBinder來實現將表單中的數據綁定到相應
      的類上以完成Model中(實體)類的初始化綁定工作,如下:

      public class UserModelBinder : IModelBinder
      {
          
      public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
          {
              NameValueCollection form 
      = controllerContext.HttpContext.Request.Form;
              User user 
      = null;

              Guid siteID 
      = Guid.Empty;
              
      if (!string.IsNullOrEmpty(form["siteID"]))
              {
                  form[
      "siteID"].GuidTryParse(out siteID);
              }

              
      if (siteID == Guid.Empty)
              {
                  user 
      = new User
                  {
                      Name 
      = form["userName"],
                      Email 
      = form["userEmail"],
                      DisplayName 
      = form["userDisplayName"],
                      Password 
      = form["userPassword"]
                  };

                  Guid userID;
                  
      if (!string.IsNullOrEmpty(form["userID"]) && form["userID"].GuidTryParse(out userID))
                  {
                      user.ID 
      = userID;
                  }
              }

              
      return user;
          }
      }



           其實這種做法有一定的好處,就是將這類在功能上類似的操作進行了封裝。比如大家可以想像通過web請求提交過來
      一個大表單,上面有幾十個字段屬性(不要問我為什么會有這種大表單),而如何將這些字段綁定的操作與controller中
      接下來的業務流程操作放在一起,會讓controller中的相應方法代碼長度增長過快,所以倒不如通過上面這個方法將相應
      的實體類與Web頁面信息的綁定工作分離出來,當然 Oxite使用聲明相應UserModelBinder類的方式進行封裝的做法還
      有待商榷


           說來說去,還是如Rob Conery所說的,要始終保持用Controller與View的輕快,易于測試這一原則。這一點其實正
      與SOA架構中的一些思想相符合,下面結合我的理解來解釋一下:

           在SOA中,有組件(component)的概念,即組件是業務邏輯的原子級功能操作,其按照高內聚低耦合的方式進行設計,
      當業務流程開發運作時,其工作原理就是正確組合相應的業務組件來實現相應的應用。這樣的好處就是可以將這些組件分
      布式布署,同時當業務流程發生變化時,只要調整相應的業務流程邏輯(soa中稱為bpel)即能夠快速響應業務變化。而
      如何構造這種可重用的組件在SOA中也是有相應規范的,被稱為SCA.

           說到這里有些遠了,那在MVC架構中又有什么類似的思想呢?其實在這里controller的一些設計要求與SOA中的bpel
      有著相似的設計理念,即完成對業務組件(即MVCStore解決方案中的Commerce.Services項目下的相應文件)的流程
      編排和調用。這樣即便將來需求變化,而導致了業務流程的變化(不是業務規則變化),也只是修改Controller這一層應
      該可以滿足了,而正確而快速的修改的“前提”,應該就是該Controller應該設計得“盡可能的輕快”。


       
      2.需求變化了,導致了業務規則變化怎么辦?
         
           正如Ivar jacbson 在傳授“明智開發”模型時所說的那樣,“軟件開發中不變的是--需求的不斷變化”。這一點相信
      大家是有強烈共鳴的。

           這里我們先來簡單的看一下MVCStore和Oxite的處理方式,從設計思路上兩個項目基本一致,即使用接口分離方式來
      應對這種變化。比如:Oxite"Services"中就有這樣的代碼:

      public class UserService : IUserService
      {
            
      private readonly IUserRepository repository;
            
      private readonly IValidationService validator;

            
      public UserService(IUserRepository repository, IValidationService validator)
            {
                
      this.repository = repository;
                
      this.validator = validator;
            }

            
      #region IUserService Members

            
      public User GetUser(string name)
            {
                
      return repository.GetUser(name);
            }

            
      public User GetUser(string name, string password)
            {
                User user 
      = string.Compare(name, "Anonymous"true!= 0 ? repository.GetUser(name) : null;

                
      if (user != null && user.Password == saltAndHash(password, user.PasswordSalt))
                    
      return user;

                
      return null;
            }

            
      public void AddUser(User user, out ValidationStateDictionary validationState, out User newUser)
            {
                validationState 
      = new ValidationStateDictionary();

                validationState.Add(
      typeof(User), validator.Validate(user));

                
      if (!validationState.IsValid)
                {
                    newUser 
      = null;

                    
      return;
                }
             .
      }


            其實現了IUserService服務接口。

            而MVCStore中的Commerce.Services項目中的代碼也使用了類似接口定義,比如:

      [Serializable]
      public class OrderService : Commerce.Services.IOrderService {

          IOrderRepository _orderRepository;
          ICatalogRepository _catalogRepository;
          IShippingRepository _shippingRepository;
          IShippingService _shippingService;

          
      public OrderService() { }
          
      public OrderService(IOrderRepository rep, ICatalogRepository catalog,
              IShippingRepository shippingRepository, IShippingService shippingService)
          {
              _orderRepository 
      = rep;
              _catalogRepository 
      = catalog;
              _shippingRepository 
      = shippingRepository;
              _shippingService 
      = shippingService;
          }

          
      /// <summary>
          
      /// Gets all orders in the system
          
      /// </summary>
          
      /// <returns></returns>
          public IList<Order> GetOrders() {
              
      return _orderRepository.GetOrders().ToList();
          }
       .
      }


           定義并實現這些服務接口之后,就可以通過IOC這類方式來實現最終的注入,以決定在程序運行時使用那些具體
      實現類了,比如Oxite中的Oxite/ContainerFactory.cs是這樣進行注冊的(使用了Unity框架):

      public IUnityContainer GetOxiteContainer()
      {
           IUnityContainer parentContainer 
      = new UnityContainer();

           parentContainer
               .RegisterInstance(
      new AppSettingsHelper(ConfigurationManager.AppSettings))
               .RegisterInstance(RouteTable.Routes)
               .RegisterInstance(HostingEnvironment.VirtualPathProvider)
               .RegisterInstance(
      "RegisterRoutesHandler"typeof(MvcRouteHandler));

           
      foreach (ConnectionStringSettings connectionString in ConfigurationManager.ConnectionStrings)
           {
               parentContainer.RegisterInstance(connectionString.Name, connectionString.ConnectionString);
           }

           parentContainer
               .RegisterType
      <ISiteService, SiteService>()
               .RegisterType
      <IPluginService, PluginService>()
               .RegisterType
      <IUserService, UserService>()
               .RegisterType
      <ITagService, TagService>()
               .RegisterType
      <IPostService, PostService>()
               .RegisterType
      <ITrackbackOutboundService, TrackbackOutboundService>()
           ..
      }



          當然這種做法是有普遍性的,好處也是很明顯。就是將來如果業務規則變化時(對應service接口實現類
      也要發生變化),這時不需要真正修改已有的代碼,只需再開發一個相應的實現類即可滿足需求,這種擴展
      方式也是與設計模式中的思想相符合的。

          說到這里,把話題再深入一下,就是微軟模式與實踐小組的Service Layer Guidelines中對象這塊還會
      有一個Application Facade(在其Business層中),如下圖:

         

           其完成的是對這些service組件的“應用層面級”封裝,說的再白一些,其可以包括對業務工作流,業務
      實體,業務組件的三者的封裝。以便于對外實現(暴露)統一的服務訪問接口。就這部分而言,MVCStore
      做的比Oxiete要好,其在工作流中對各類已定義的服務組件的邏輯調用寫的很有味道,比如Commerce.-
      Services項目下的 AcceptPayPalWorkflow.csShipOrderWorkflow.cs

           當然就目前工作流的作用遠不止這些,必定其也可以采用WCF服務的方式把自己暴露給外界。就這一
      點,其自身也可以轉化為一個服務組件,到這里就出現了一個有趣的現象,即:

           已將一些服務組件囊括的工作流自己也成了一個服務組件而被其它服務組件所調用。不是嗎?

           在SOA架構中,這種情況是很普遍的,因為組件是一些基本的業務規則邏輯,其應允許被其它組件訪問
      甚至包含以使業務規則更加清晰,說白了就是可復用性。
         
           對開發者而言只有這樣才可能提升開發速度(重用已有組件的好處不僅僅是少寫代碼,還包括測試和布
      署等方面的成本也會降低),這一點想一想那些開源的框架就會理解了。而對于企業管理者而言就是保護“
      已有投資”


      3.兩個項目中的困惑

         
           的確,看了這兩個MVC之后,還是有些讓我感覺不是太清晰的地方,比如MVCStore中,Commerce.Data
      項目下的Model/Order.cs類,我剛開始一看,還真被震住了,很有充血模型的味,下面是部分代碼:

      Code


           可正當我帶著興趣去觀察其它相應的域模型類時,又回到了貧血域模型。不是嗎?的方法是要感覺好像
      不是一個開發人員寫的才會出現這種情況,因為按其架構設計上來看,這個類中被放到Serivce中實現的,
      因為我不是該項目的開發人員,想不出個所以然來。


           白乎了這些,其它在這兩個項目中還有一些差異,當然本文開頭提到的那篇文章也說出了一些“問題”。
      不過還是那句話,沒有最好的設計只有最適合的設計,這兩個項目都有可圈可點的地方,但對自己所在公
      司部門是不是“完全適合”只能結合自己團隊的情況而定了。

           比如說關于Commerce.MVC.Web中將controller和view放在了一起,就是個問題,比如在團隊中
      有如下分工:

           VIEW開發人員 + Controller開發人員 + Service組件開發

           那么將View目錄與Controller目錄放在不同的項目中應該是個不錯的方式,起碼在項目級別上將這
      兩類開發者進行了分離。當然有人會說,一般情況下VIEW 和Controller的設計者應該是一個人而不是
      兩個人, 但分工明確才能盡一步提升生產力,特別是MVC這個框架還很新,有些開發人員學習是從View
      語法入手,有些人從Controller入手,有些人比如我是從Service入手。這就導致關注和側重點不同,最
      后導致自己的理解和優勢也會不同。將View分離出來的好處在于發揮各自的優勢,讓前臺開發人員可以
      將精力放在與UI設計師交流設計實現,界面實現,js(目前是JQuery)封裝調用等方面。相信隨著項目
      的不斷擴大和開發人員的后續補充勢必會造成這樣的問題。


           好了,今天的內容就先到這里了。
           
          
           原文鏈接:http://www.rzrgm.cn/daizhj/archive/2009/02/26/1398689.html

           作者: daizhj, 代震軍

           Tags: soa,mvc,sca,bpel

           網址: http://daizhj.cnblogs.com
      posted @ 2009-02-26 12:42  代震軍  閱讀(24305)  評論(62)    收藏  舉報
      主站蜘蛛池模板: 国产一区二区黄色在线观看 | 嘉善县| 在线无码中文字幕一区| 中文字幕亚洲人妻系列| 好男人好资源WWW社区| 国产成人精品一区二三区在线观看| 四虎在线成人免费观看| 自拍偷自拍亚洲精品熟妇人| 亚洲伊人精品久视频国产| 国产一区二区高清不卡| 天天燥日日燥| 国产精品久久久久影院亚瑟| 广西| 亚洲人成网站在线播放2019| 日本55丰满熟妇厨房伦| 香格里拉县| 久9re热视频这里只有精品免费| 亚洲欧美日韩成人综合一区| 色欲精品国产一区二区三区av| 国产精品爱久久久久久久电影| 中文字幕国产精品日韩| 国产精品久久久天天影视| 免费一区二三区三区蜜桃| 中文字幕国产日韩精品| 国产精品ⅴ无码大片在线看| 国产午夜亚洲精品福利| 中文字幕日韩有码av| 老熟妇仑乱一区二区视頻| 内射合集对白在线| 国产成人8X人网站视频| 亚洲精品美女一区二区| 欧美亚洲熟妇一区二区三区| 免费无码成人AV片在线| 平和县| 国产精品午夜无码AV天美传媒 | 午夜免费福利小电影| 亚洲日韩av无码一区二区三区人 | 欧美 变态 另类 人妖| 亚洲精品综合久中文字幕| 国产性三级高清在线观看| 亚洲a免费|