利斯科夫代换原理与Streams



存在无法编写或查找的流派生类这一事实是否违反了Liskov替换原则?

例如,无法查找NetworkStream,如果调用方法Seek,它将抛出NotSupportedException

还是因为CanSeek标志的存在就可以了?

考虑到CCD_ 4继承CCD_。。。将标志DoesHeightAffectsWidthDoesWidthAffectsHeight添加到Rectangle会解决问题吗?

这难道不为通过添加旗帜来解决问题打开了大门吗?

CanSeek从技术上防止流类违反LSP。只有当它返回真的,寻求承诺才会奏效。

我个人认为这是ISP和SRP的严重弯曲,我的内部设计师更喜欢SeekableStream子类/接口,可查找流可以从中继承。但我相信这也会带来问题(例如,在只有才能找到的流中,有时会出现问题)。。。坦率地说,现实世界的可用性胜过原则。

这是需要记住的。原则和现实偶尔会发生冲突。在大多数情况下,SOLID原则有助于最大限度地减少不必要的复杂性,并通常保持OO系统的可维护性,防止它们在自己的重量下崩溃。然而,如果纯粹性导致一个更为复杂的系统——例如,因为现在一个只有有时才能找到的流不太适合层次结构——那么偶尔的一点丑陋也许是合理的。

但它不应该仅仅因为法律条文允许而成为第一选择。坚实的原则不仅仅是规则;它们是原则。它们是文字背后的思想——法律的精神。如果你在做律师时坚持字面意思而忽略了精神,你就错过了原则的全部要点。

至于正方形/矩形问题。。。从技术上讲,具有决定改变高度是否也会改变宽度的属性/函数,可以被认为符合LSP的字母。然而,这再次感觉像是律师,并且正在突破其他SOLID原则的界限。从现实的角度来看,这也绝对不是一个最佳解决方案,因为它增加了复杂性,并引入了意外副作用的可能性;现在,所有想要说CCD_ 11的东西也可能无意中改变宽度。

Can...方法意味着Stream不会破坏LSP。Stream提供了读取、写入和查找的功能,但不能保证任何实现类都会遵守它。Can...方法使这成为Stream契约派生类的一个显式功能-派生类必须实现它们,以允许客户端代码在调用之前检查派生类是否实现了某些行为。因此,例如,任何试图写入Stream的代码都应该在调用Write之前检查CanWrite,而这可以通过Stream的任何正确实现的导数来完成。呃,它们是可互换的,正如LSP所要求的那样。

我认为,添加方法来标记派生类是否实现特定功能肯定会被滥用——如果一个团队不守纪律,他们最终可能会得到一个非常宽泛、臃肿的接口,从而破坏ISP。我认为StreamIList<T>在这方面是精心设计的——它们不会破坏LSP,并且它们定义了一个足够窄的密切相关行为契约,以留在ISP内。显然,他们的设计已经被考虑过了。

我认为,在Square继承自Rectangle的情况下,您当然可以添加DoesHeightAffectsWidthDoesWidthAffectsHeight来解决问题,但团队必须决定这是否可以接受,或者添加这些方法是否会破坏ISP。添加AreAllInternalAnglesEqual来支撑梯形是否太远?在某种程度上,这取决于编写代码的工程师。

相关内容

  • 没有找到相关文章

最新更新