2011-02-02 56 views
0

这个问题是我以前的文章here的后续。马蒂尼奥要求我提供更多关于我的系统的信息。他建议可能有更好的方法来实现我的尝试。所以,如果这里有一个问题,我想我想知道这是否是糟糕的设计?如果是这样,什么可以改进和如何(我从插图学习最好)。谢谢。寻找一些关于我的服务器设计的一般性反馈。关于使用通用方法

我正在为iPhone应用程序设计中间件。

开发人员不希望从客户端显式调用各种对象,而是希望使用泛型,其中“Group”基于传入的参数返回JSON字符串。该参数表示用户登录时看到的第一个屏幕。我们将登录屏幕称为“Dashboard”。

所以,当客户端调用服务器方法:

Contracts.GroupDto IDashboardService.GetGroupById(string groupId) 
     { 
      var obj = GroupRepository.GetGroupById(groupId); 

      return new Contracts.GroupDto 
      { 
       ... 
      }; 
     } 

服务器使用GroupRepository方法GetGroupById返回一个通用对象类型:

public static IList<G> GetGroupById<G>(int groupId) 
     { 

      DashboardGroupType type = (DashboardGroupType)groupId; 
      IList<G> result = new List<G>(); 

      var obj = default(G); 

      switch (type) 
      { 
       case DashboardGroupType.Countries: 
        break; 
       case DashboardGroupType.Customers: 
        // this returns a list of typ IEnumerable<Customer> 
        obj = (G) CustomerRepository.GetAllCustomers(); 
        break; 
       case DashboardGroupType.Facilities: 
        // this returns a list of typ IEnumerable<Facility> 
        obj = (G) FacilityRepository.GetAllFacilities(); 
        break; 
       case DashboardGroupType.Heiarchy: 
        break; 
       case DashboardGroupType.Lines: 
        break; 
       case DashboardGroupType.Regions: 
        // this returns a list of typ IEnumerable<string> 
        obj = (G) CustomerRepository.GetRegionsHavingCustomers(); 
        break; 
       case DashboardGroupType.States: 
        // // this returns a list of typ IEnumerable<Customer> 
        obj = (G) CustomerRepository.GetStatesHavingCustomers(); 
        break; 
       case DashboardGroupType.Tanks: 
        break; 
       default: 
        break; 
      } 

      result.Add(obj); 


      return result; 

     } 

返回的对象类型是基于传递给GetGroupById的参数。例如,如果该值为1,则该方法着眼于DashboardGroupType枚举:

并通过1的参数,服务器会查看以下枚举:

public enum DashboardGroupType 
    { 
     Countries = 0, 
     Regions = 1, 
     Customers = 2, 
     Facilities = 3, 
     Lines = 4, 
     Tanks = 5, 
     States = 6, 
     Heiarchy = 7 
    } 

并返回的区域的列表键入IEnumerable到调用客户端。

对于这样的设计(尤其是有关的IList GetGroupById(INT的groupId)方法有什么想法吗?如果您有任何建议,我会提前感谢您的改进的说明。

感谢。

+0

难道你的意思是,*层次*? :) – 2011-02-02 17:39:26

+0

我认为你的意思是“层次结构”。开关语句和强制转换有时是代码异味。这种方法似乎做了不止一件事情(参见单一责任原则)。我不知道你的问题域,所以我没有具体的建议。 – TrueWill 2011-02-02 17:42:07

回答

0

请勿使用switch语句。它可能会引入错误并难以维护。 我建议你创建一个具有GetGroupById()默认行为的基类(抽象),并派生每个组DashboardGroupType的类。 只需要将变量/属性存储并且不必根据值执行任何逻辑时,Enum就是合适的。 在您的派生类中,您可以重写默认行为或将其保留为默认值(返回null)。您也可以考虑使用空对象设计模式。

当一些变化出现和变化是你将欣赏设计,唯一不变的:)

你可以参考Martin Fowler的书“重构”

1

该代码没有按对于我来说很有意义,你的通用返回IList<G>,但是这个列表只添加了一个项目,有时候这个项目是null(或者default<G>,当G是引用类型时,将会是null) 。

我无法想象为什么开发人员会倾向于使用泛型方法,这比使用单独的方法更复杂。那就是为什么没有GetFacilities,GetCustomers等?

也许他们更喜欢使用一种服务方法来向他们返回JSON。如果有一些令人信服的理由可以做到这一点(尽管我无法想象其中一个,除了开发者懒惰),那么我建议你在该方法中使用switch,而不要混淆泛型。那就是:

Contracts.GroupDto IDashboardService.GetGroupById(string groupId) 
{ 
    switch ((DashboardGroupType)groupId) 
    { 
     case DashboardGroupType.Regions: 
      // Get the Regions list, convert to JSON, and return. 
      break; 
     // do the same kind of thing for the other group types. 
    } 
} 

添加在这种情况下,一般的方法就是不必要的复杂性 - 它什么也不做,以简化或增加代码的理解。相反,它使代码更难理解。一般来说,如果你的泛型方法中的代码基于类型参数进行了不同的操作,那么这是一个很好的表示,你的泛型方法不是真正的泛型,可能应该以其他方式实现。