在模型中放入诸如“ FullName”或“ FormattedPhoneNumber”之类的吸气剂是“一种模式的气味”吗?


13

我正在开发ASP.NET MVC应用程序,并且已经养成了将看起来有用且方便的吸气剂放入模型/实体类的习惯。

例如:

public class Member
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string PhoneNumber { get; set; }

    public string FullName
    {
        get { return FirstName + " " + LastName; }
    }

    public string FormattedPhoneNumber
    {
        get { return "(" + PhoneNumber.Substring(0, 3) + ") " + PhoneNumber.Substring(3, 3) + "-" + PhoneNumber.Substring(6); }
    }
}

我想知道人们在考虑FullNameFormattedPhoneNumber吸气剂。

它们使在整个应用程序中创建标准化数据格式变得非常容易,而且似乎可以节省大量重复代码,但是可以肯定地说,数据格式是在从模型到视图模型的映射中应该处理的东西。

实际上,我最初是在我进行映射的服务层中应用这些数据格式的,但是,这一直成为一种负担,必须不断编写格式器,然后将其应用到许多不同的地方。例如,在大多数视图中,我都使用“全名”,而不得不model.FullName = MappingUtilities.GetFullName(entity.FirstName, entity.LastName);在各处键入类似的内容似乎比仅仅键入model.FullName = entity.FullName(或者,如果您使用类似AutoMapper的内容,可能根本不键入任何内容)要优雅得多。

因此,在数据格式化方面您会在哪里划清界线。在模型中进行数据格式化是否“还可以”,还是“图案异味”?

注意:我的模型中绝对没有任何HTML。我为此使用HTML帮助器。我严格地说的是格式化或合并数据(尤其是经常使用的数据)。


1
这样做很方便。但是希望并祈祷您永远不必使该代码国际化。
btilly 2011年

@btilly,很好,但是我大约99.99%的人相信我不会。
devuxer 2011年

当然,特定于FullName和PhoneNumber。这个问题是专门针对那些问题,因为它们在不同文化中格式不一致吗?或者@DanM只是选择了一个对于较笼统的问题没有很好地国际化的示例?
格雷格·杰克逊

@格雷格·杰克逊(Greg Jackson),绝对是阶梯。正如ammoQ指出的,它PhoneNumber可能属于自己的类(我现在已经实现了)。但是FullName确实是促使我写这个问题的人。但我有兴趣了解通常情况下,将数据格式化/合并等放入模型中是否适用于整个应用程序。从下面的答案来看,这似乎不是反模式,但应谨慎做出决定。
devuxer 2011年

请记住,这种全名的特定格式也可能无法很好地国际化。例如,在东亚,名称顺序与西方世界相反。您是否真的需要明确处理此问题?也许不是,但是请记住,格式化数据时会遇到很多棘手的事情。
格雷格·杰克逊

Answers:


9

在您的示例中,我喜欢FullNamegetter(出于您给出的所有原因),但我不喜欢FormattedPhoneNumber getter。其原因是:它可能不是那么容易(一旦你有国际电话号码等),如果你把逻辑中的方法在格式化的电话号码Member,那么你将需要重构(或复制粘贴caugh),一旦你也需要格式化的电话号码InstitutionVendor等等。

编辑:IMO最好有一个PhoneNumber带有Formatted吸气剂的课程。


+1,谢谢。但是,如果我实际上将电话号码格式代码放在扩展方法中怎么办?这样,任何模型都可以使用它,并且不会进行重构或复制/粘贴。与将格式化程序应用于出现在每个视图中的每个电话号码相比,此解决方案的重复性仍然要低得多。
devuxer 2011年

3
为此,使用扩展方法将是“功能分解”反模式的快速方法。通过使用扩展方法(String我假设是针对该类的),您可以“教” String该类如何设置电话号码格式。String知道电话号码真的是全班的责任吗?我不这么认为。像这样使用扩展方法是语法上的糖,它使看起来显然不是面向对象的东西看起来像以前那样。
user281377 2011年

1
好吧,忘了我说的扩展方法。假装我说过实用程序方法或格式化程序类。我只是说不需要重构/复制粘贴,无论我是否拥有模型获取器或在其他地方进行格式化。
devuxer 2011年

1
我确实喜欢PhoneNumber上课的想法。我一直打算这样做,因为我也PhoneType有财产。
devuxer 2011年

我不喜欢将其PhoneNumber作为实例类的想法,因为数据是本地的string。相反,它应该是一个静态类,其方法如public static string Format(string phoneNumber, PhoneNumberStyle style)
安德森先生

5

编写代码时需要考虑的事情:是否正确?可读吗?有效率吗?它可以维护吗?正如@btilly所言,我会争辩说由于特定于文化的格式,它是不可维护的,但是问题似乎更笼统。

使用这样的访问器可以使您的代码更具可读性,并且根据您的使用方式,可能会使代码的其他部分更清晰。我认为这根本没有味道。如果您具有可能要打印的任何类型的字符串的格式化访问器(public string FirstLastName; public string FullName; public string FullNameWithMiddleInitial; public string PhoneNumberWithAreaCode; public string PhoneNumberWithoutAreaCode; public string PhoneNumberWithCountryCode;,等等),它就会开始发出气味。

或者,换句话说,使用模式不会自动使您的代码具有“模式气味”。如果您想获得该属性,则需要滥用它。


谢谢,格雷格。+1。我同意您提出的所有建议。我真的只是想提出一种最干净的方法来标准化如何查看数据。
devuxer 2011年

3

打破了单一责任原则。为什么不进行电话号码分类等?


好的,我实际上同意这一点(请参阅ammoQ的回答中的讨论),但我也应该FullName上课吗?
devuxer 2011年

是的,应该,但是您应该将拼写从“ FullName”更改为“ FoolName”。也许是“ PersonalName”,因为它是一个人的名字,而不是完整的名字。
凯文·克莱恩

1
真?除非给定的班级有望增长,否则到底有什么问题呢?即使它确实增长了,那么重构到底有多难呢?
工作

@DanM:那就是您要的,即要求他们输入其完整的法定名称。如果按名字排序,实际上是对名字的第一个字母(然后是第二个,依此类推)进行排序,因此无论如何名称都将进行相同的排序。
Matt Ellen


1

对于您的示例,我认为使用特定格式没有什么大不了的。它是一两个,应用程序的所有部分都使用相同的格式。

当您将相同的数据发送到需要不同格式的多个不同位置时,该决定就会开始崩溃。

如果发生这种情况,我很想将Member课程拉回到:

public class Member
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string PhoneNumber { get; set; }  
}

然后为每个目标执行不同的适配器。例如,假设信息是CSV格式所必需的:

public static class CSVMemberAdapter
{
    public static string ToCSV(this Member mbr)
    {
         return mbr.Id + "," + mbr.LastName + "," + mbr.FirstName, "," mbr.PhoneNumber;
    }
}

始终假定您已经清理了数据,所以字符串中没有逗号等。

适配器不一定必须是扩展方法,但对于这种虚假的情况,它似乎很合适。


自从我写C#已经有一段时间了,但是肯定有序列化类可以处理这个问题,而不是一遍又一遍又一遍又一遍又一遍又一遍地写着像toCSV这样繁琐的方法一遍又一遍又一遍又一遍...
kevin cline

@kevin cline:这取决于您在每个接收器上需要什么。如果他们只需要序列化的XML,就可以了。许多系统没有。如果必须重复进行over多次,则说明设计存在问题。
Peter K.

通常会有许多类要序列化。应该有可能编写单个CSV或其他序列化程序,它可以通过反射来处理大多数类,而不是像您的示例那样手工编码它们。
凯文·克莱恩

@kevin cline:强烈同意!我只是在写一些非常具体的问题。具体的,简单的示例往往可以更好地说明问题。
Peter K.
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.