一串IsNullOrEmpty(myString)或字符串.IsNullOrWhiteSpace(myString)未违
本文关键字:myString IsNullOrWhiteSpace 未违 字符串 一串 IsNullOrEmpty | 更新日期: 2023-09-27 18:27:00
如问题所示,
正如函数名称所示,我们正在使用像IsNullOrEmpty或IsNullOrWhiteSpace这样的字符串函数,这些函数正在做不止一项工作,这不是违反SRP吗?
应该不是string.isValid(Enum typeofValidation),而不是使用策略模式来选择要验证的正确策略。
或者在实用程序类或静态类中违反SRP是完全可以的。
SRP说一个函数或类应该只有一个改变的原因。改变的理由是什么?更改的原因是请求更改的用户。因此,一个类或函数应该只有一个请求更改的用户。
现在,一个先进行一些计算,然后进行一些格式化的函数,有两个不同的用户可以请求更改。一个将请求更改计算,另一个将要求更改格式。由于这些用户有不同的需求,会在不同的时间提出他们的请求,我们希望他们能得到不同的功能。
IsNullOrEmpty(String)不太可能为两个不同的用户提供服务。关心null的用户可能与关心empty的用户相同,因此isNullOrEmpty不会违反SRP。
在面向对象编程中,单一责任原则规定每个对象都应该有一个单一责任
你在描述方法:IsNullOrEmpty或IsNullOrWhiteSpace,它们也在自我描述它们的作用,它们不是对象。string
只有一个责任——负责文本字符串!
如果您愿意,静态助手可以执行许多任务:单一责任原则的全部目的是最终使您的代码对未来的团队和您自己更具可维护性和可读性。正如一条评论所说,不要想得太多。你在这里不是在设计框架,而是在使用其中的一些部分,这些部分将为你清理字符串,并验证传入的数据。
SRP适用于类,而不是方法。尽管如此,使用只做一件事的方法还是个好主意。但你不能把它推向极端。例如,如果控制台应用程序的Main方法只能包含一条语句(并且,如果该语句是方法调用,则该方法也只能递归地包含一条声明,等等),那么它将是相当无用的。
思考IsNullOrEmpty的实现:
static bool IsNullOrEmpty(string s)
{
return ReferenceEquals(s, null) || Equals(s, string.Empty);
}
所以,是的,它做了两件事,但它们是在一个表达中完成的。如果你进入表达式的层次,任何涉及二进制布尔运算符的布尔表达式都可以说是"做了不止一件事",因为它正在评估多个条件的真值。
如果方法的名称让您感到困扰,因为它们意味着单个方法的活动太多,请使用暗示单个条件求值的名称将它们封装在您自己的方法中。例如:
static bool HasNoVisibleCharacters(string s) { return string.IsNullOrWhitespace(s); }
static bool HasNoCharacters(string s) { return string.IsNullOrEmpty(s); }
回复您的评论:
比如说,我写了一个类似SerializeAndValidate(ObjectToSerializeAndvalide)的函数,很明显,这个方法/类正在做两件事,Serialize和Validation,显然是一个违规行为,一个类中的一些方法有时会导致维护噩梦,比如上面的序列化和验证的例子
是的,你关心这一点是正确的,但同样,你不能有只做一件事的方法。请记住,不同的方法将处理不同级别的抽象。您可能有一个非常高级的方法,它将调用SerializeAndValidate
作为一长串操作的一部分。在这个抽象级别上,将SerializeAndValidate
视为单个操作可能是非常合理的。
想象一下,为一位经验丰富的用户编写一套循序渐进的说明,以打开文件的"属性"对话框:
- 右键单击文件
- 选择"属性"
现在想象一下,为从未使用过鼠标的人写同样的指令:
- 将鼠标指针放在文件的图标上
- 按下并释放鼠标右键
- 此时会出现一个菜单。将鼠标指针放在单词"Properties"上
- 按下并释放鼠标左键
当我们编写计算机程序时,我们需要在两个抽象级别上操作。或者,更确切地说,在任何给定的时间,我们都在一个或另一个抽象级别上操作,以免混淆自己。此外,我们仍然依赖于在较低抽象级别上运行的库代码。
方法还允许你遵守"不要重复自己"的原则(通常被称为"DRY")。如果您需要在应用程序的许多部分中序列化和验证对象,那么您希望有一个SerializeAndValidate
方法来减少重复的代码。建议您将该方法作为一种简单方便的方法来实现:
void SerializeAndValidate(SomeClass obj)
{
Serialize(obj);
Validate(obj);
}
这使您可以方便地调用一个方法,同时保留序列化逻辑与验证逻辑的分离,这将使程序更易于维护。
我不认为这是在做不止一件事。它只是确保您的字符串通过一个必需的条件。