提问人:john doe 提问时间:8/30/2021 最后编辑:john doe 更新时间:8/31/2021 访问量:119
避免在函数体内部欺骗参数的正确性
avoid cheecking arguments correctness inside the function body
问:
我最近注意到我们之前在代码库中编写的一个函数,我确信它在逻辑上是不正确的。函数是用 TypeScript 编写的,其主体如下所示:
const getUserInitials = (user: IUser | null) => {
if (!user) { return ""; }
return (user.FirstName.charAt(0) + user.LastName.charAt(0)).toUpperCase();
}
我很确定这是不正确的,因为这种函数签名允许传递不正确的参数,然后在内部尝试通过返回空字符串来修复不正确的参数段落。我认为这应该用用户参数只持有类型(而不是)来重写,并且这种参数检查应该在函数调用之外和之前进行,以便函数将始终接收到正确的参数。IUser
IUser | null
在开发时,是否应该将其视为经验法则?我不是在谈论你收到一个整数的情况,你的函数只有在你的整数必须大于 100 时才需要运行。显然,您需要在函数内部检查这种事情,因为有人可能会传递您无法控制的错误值。这似乎是函数的合理关注点,我们显然需要在内部检查它以提供正确的函数输出。
但是在所呈现的案例中,情况完全不同 - 函数契约说它会给你一个用户的首字母,但在某些情况下,它只会返回一个空字符串“”(这不是用户首字母,所以在我看来,这是一个函数契约违规)。
我什至会更进一步说函数命名不正确,应该调用它
getInitials(user: IUser) => {...}
由于我们清楚地将 user 作为参数,因此函数名称中的“user”一词是多余的。
首先,我对违反契约的理解是否正确,以及在这种情况下在函数调用之前检查参数正确性的必要性?
如果我是对的 - 是否有任何情况,在静态类型语言中检查内部参数的正确性是一个很好的方法(跳过像我的例子中整数需要不超过 100 的情况,当然与语言类型系统无关)?
我关于函数名称冗余中“用户”的陈述是否正确?
先谢谢你。
答:
问题 1:是的,在使用该参数调用函数之前,您应该检查参数是否有效。
问题 3:根据经验,我会说不。GetInitials 含糊不清。在您的示例中,当您调用该函数时,您不一定知道它适用于用户的首字母缩写。
(这在面向对象编程中不是问题,因为在面向对象编程中,您将拥有 User.GetInitials(),因此在某种程度上 User 已经在名称中。
评论
你是部分正确的:
答:检查函数的参数,并在特殊情况下设计其行为,这永远不会有什么坏处。在像 Typescript 这样的语言中尤其如此,它可以从 Javascript 调用,而 Javascript 是非类型化的。您可能是对的,没有人应该在没有有效用户的情况下调用此函数, 但这并不意味着没有人会这样做。
b:如果你能以有意义的方式解释一个 null 参数,那么这样做并返回一个合理的默认值通常是合理的。但是,我认为在这种情况下返回空字符串是不合理的。在这种情况下,最好抛出错误。
c:如果不能返回合理的默认值,则方法签名不应允许空参数...但是您仍然可以检查它们并且 抛出比默认情况下可能发生的任何错误更有意义的错误。不幸的是,许多人使用eslint的配置方式会抱怨这种检查,这通常是方法签名中这些添加的来源。
| null
静态类型是不够的。如果您的语言阻止使用错误类型的参数有意义地调用函数,则无需检查类型。打字稿不是那种语言。
绝对不行。在 typescript 中,方法参数不是方法签名的一部分。 与 的功能相同。如果创建一个名为 的函数,则没有其他人可以在同一范围内创建另一个函数。不要以为无论你在做什么,都是一个值得一个不合格名字的特殊情况。
getInitials(user: User)
getInitials(firstName: string, lastName: string)
getInitials
评论
x
x
评论
language-agnostic
typescript