寻找有关我的服务器设计的一些一般反馈。关于通用方法的使用
这个问题是我上一篇文章的后续问题 这里。马蒂尼奥要求我提供有关我的系统的更多信息。他建议可能有更好的方法来实现我正在尝试的目标。所以,如果这里有一个问题,我想我想知道这是否是糟糕的设计?如果是这样,可以改进什么以及如何改进(我从插图中学到最好的东西)。谢谢。
我正在为工作中的 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) 方法)的任何想法?如果您有建议,我将不胜感激您的改进说明。
提前致谢。
This questions is a follow-up to my previous post here. Martinho has asked me to provide more information regarding my system. He has suggestion that there might be a better way to achieve what I am attempting. So, if there is a question here, I guess I am wondering if this is poor design? If so, what can be improved and how (I learn best from illustrations). Thanks.
I am designing middleware for an iPhone application at work.
Rather than explicitly calling various objects from the client, the developers want to use generics where a "Group" returns a JSON string based on a passed-in parameter. The parameter represents the first screen a user sees when he logs in. We are calling the login screen the "Dashboard".
So, when the client calls the server method:
Contracts.GroupDto IDashboardService.GetGroupById(string groupId)
{
var obj = GroupRepository.GetGroupById(groupId);
return new Contracts.GroupDto
{
...
};
}
The server uses the GroupRepository method GetGroupById to return a generic object type:
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;
}
The object type returned is based on the parameter passed in to GetGroupById. For example, if the value is 1, the method looks at the DashboardGroupType enum:
and passes the parameter of 1, the server looks at the following enum:
public enum DashboardGroupType
{
Countries = 0,
Regions = 1,
Customers = 2,
Facilities = 3,
Lines = 4,
Tanks = 5,
States = 6,
Heiarchy = 7
}
and returns a list of regions of type IEnumerable to the calling client.
Any thoughts regarding this design (especially regarding the IList GetGroupById(int groupId) method? If you have suggestions, I would appreciate an illustration of your improvement.
Thanks in advance.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
该代码对我来说没有多大意义。您的泛型返回一个
IList
,但列表中只添加了一个项目。有时该项目为null
(或default
,当G
是引用时,该项目将为null
类型)。我无法想象为什么开发人员会偏爱
GetGroupById
泛型方法,因为这样做比使用单独的方法更复杂。也就是说,为什么不使用GetFacilities
、GetCustomers
等呢?也许他们更喜欢使用单一的服务方法来返回 JSON。如果有一些令人信服的理由这样做(尽管我无法想象,除了开发人员的懒惰之外),那么我建议您在该方法中进行
switch
而不要弄乱泛型。也就是说:在这种情况下添加泛型方法只是不必要的复杂性——它对简化或增加对代码的理解没有任何作用。相反,它会使代码更难理解。
一般来说,如果泛型方法中的代码根据类型参数的不同而有不同的行为,那么这很好地表明您的泛型方法并不是真正泛型的,可能应该以其他方式实现。
That code doesn't make a lot of sense to me. Your generic returns an
IList<G>
, but the list only ever has a single item added to it. And sometimes that item isnull
(ordefault<G>
, which will benull
whenG
is a reference type).I can't imagine why the developers would favor a
GetGroupById
generic method when doing so is more complicated than having separate methods. That is, why not haveGetFacilities
,GetCustomers
, etc?Perhaps they prefer having a single service method that returns JSON to them. If there's some compelling reason to do that (although I can't imagine one, other than developer laziness), then I would suggest that you do the
switch
in that method and not mess with the generic. That is:Adding the generic method in this case is just needless complexity--it does nothing to simplify or increase understanding of the code. To the contrary, it makes the code harder to understand.
In general, if you have code in a generic method that acts differently based on the type parameter, then it's a very good indication that your generic method isn't really generic and probably should be implemented some other way.
不要使用 switch 语句。它可能会引入错误并且难以维护。
我建议您创建一个具有 GetGroupById() 默认行为的基类(抽象),并为每个 DashboardGroupType 组派生类。
当您只需要存储为变量/属性并且不必根据值执行任何逻辑时,枚举是合适的。
在派生类中,您可以覆盖默认行为或将其保留为默认值(返回 null)。您也可能会考虑使用空对象设计模式。
当出现一些变化时,你会欣赏这个设计,而变化是唯一不变的:)
你可以参考Martin Fowler的《重构》一书
Do not use switch statement. It may introduce bugs and hard to maintain.
I suggest you to create a base class (abstract) with default behavior for GetGroupById() and derive classes for each of the groups DashboardGroupType.
Enum are appropriate when you just need to store as a variable/property and don't have to do perform any logic based on the value.
In your derived classes you can override the default behavior or keep it to default (return null). You may think of using null object design pattern as well.
You will appreciate the design when some change comes up and change is the only constant :)
You can refer to Martin Fowler's book on" Refactoring"