我和一位同事进行了一些辩论。简而言之,是否有充分的理由隐藏/封装纯函数?
“纯”是指维基百科定义:
- 始终从相同的输入返回相同的结果。(出于讨论的
Foo Create(){ return new Foo(); }
目的,如果Foo
不具有值语义,则认为这是不纯的。) - 不使用可变状态(局部变量除外)或I / O。
- 不会产生副作用。
我和一位同事进行了一些辩论。简而言之,是否有充分的理由隐藏/封装纯函数?
“纯”是指维基百科定义:
Foo Create(){ return new Foo(); }
目的,如果Foo
不具有值语义,则认为这是不纯的。)Answers:
纯函数仍然可以是实现细节。尽管该函数可能不会造成任何危害(从不破坏重要的不变式/合同的角度来看),但通过暴露该函数,该类/模块/程序包的作者和用户都将遭受损失。作者之所以失败,是因为现在即使实现更改并且该功能不再对他有用,他也无法将其删除。用户会迷失方向,因为他们不得不仔细检查并忽略与使用该API无关的其他功能,以了解它。
问题是向后的。
您并没有寻找使函数不公开的理由。一开始(我认为)是一种错误的心态。推理应该走另一条路。
换句话说-不要问“为什么要将其设为私有?”。问:“为什么要公开?”
如有疑问,请不要暴露它。这有点像奥克汉(Ockham)的剃刀-不要在不必要的时候增加实体。
编辑:解决@Telastyn在评论中提出的反对意见(以避免在那里进行扩展讨论):
我听说过一段时间,甚至在相当一段时间内都拥护它,但是以我的经验,事情往往过于私密。
是的,有时候,如果一个类是开放继承的,那会很痛苦,但是您不能覆盖某些私有方法(您想改变其行为)。
但是protected
就足够了-而且它仍然是非公开的。
这会导致大量代码重复和开销,导致无法“访问”不应该公开的事物。
如果出现问题,只需将其公开!有我在谈论的必要:)
我的观点是,您不应该只是为了以防万一(YAGNI等)。
请注意,将私有功能公开比将其私有化总是容易的。后者可能会破坏现有代码。
班级应遵守单一责任原则。虽然一个类可能需要调用其他功能来实现其目标,但它只应公开属于其单一职责的功能。
这只是可见性可能导致问题的一种示例。
考虑一个类化小部件的类。也许作为其基础代码的一部分,它需要一些实用程序函数来解析字符串:也许它需要以标准字符串函数不支持的方式来转换小部件名称。
由于这是一个纯函数(字符串进来,以某种方式对其进行转换,返回新字符串),因此它可以是公共的或私有的,而不会产生任何后果。可以吗
如果将其公开,则您的班级现在有两个职责:整理窗口小部件和转换字符串。这违反了SRP,如果其他类开始依赖该功能,则可能导致问题。由于您认为这只是在类内部使用的,因此您可能会更改其接口或可见性。现在,系统其他部分的类已损坏。
通过保持该函数的私有性,任何人都没有机会依赖不属于该类单一责任一部分的代码。
StringTransformer
类来封装仅在一个地方使用的两三行代码?我同意,一旦在多个地方使用了代码,最好将代码分担到一个新的类中,但要权衡取舍。