【问题标题】:Looking for some general feedback regarding my server design esp. regarding the use of a generic method寻找一些关于我的服务器设计的一般反馈。关于使用泛型方法
【发布时间】:2011-02-02 17:35:16
【问题描述】:

这个问题是我之前的帖子here 的后续问题。 Martinho 要求我提供有关我的系统的更多信息。他建议可能有更好的方法来实现我正在尝试的目标。所以,如果这里有问题,我想我想知道这是否是糟糕的设计?如果是这样,可以改进什么以及如何改进(我从插图中学到最好的东西)。谢谢。

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

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

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

 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) 方法?如果你有建议,我会很感激你的改进说明。

提前致谢。

【问题讨论】:

  • 你不是说,层次结构吗? :)
  • 我认为您的意思是“层次结构”。 Switch 语句和强制转换有时是代码异味。这种方法似乎做了不止一件事(参见单一职责原则)。我不知道你的问题领域,所以我没有具体的建议。

标签: c# design-patterns generics


【解决方案1】:

那段代码对我来说没有多大意义。您的泛型返回一个IList&lt;G&gt;,但该列表只添加了一个项目。有时该项目是null(或default&lt;G&gt;,当G 是引用类型时,它将是null)。

我无法想象为什么开发人员会偏爱GetGroupById 泛型方法,因为这样做比使用单独的方法更复杂。也就是说,为什么没有GetFacilitiesGetCustomers等?

也许他们更喜欢使用单一的服务方法向他们返回 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.
    }
}

在这种情况下添加泛型方法只是不必要的复杂性——它不会简化或增加对代码的理解。相反,它使代码更难理解。

一般来说,如果您的泛型方法中的代码根据类型参数的不同而有所不同,那么这很好地表明您的泛型方法并不是真正的泛型,可能应该以其他方式实现。

【讨论】:

    【解决方案2】:

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

    当一些变化出现并且变化是唯一不变的时候,你会喜欢这个设计:)

    可以参考 Martin Fowler 的《重构》一书

    【讨论】:

    • 感谢 gbsandeep,我喜欢你的想法,但有很多后续问题,我将作为新主题重新发布。我会回来提供链接。感谢您的反馈。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-31
    • 1970-01-01
    • 2020-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多