是否存在无法编写或寻求的Stream派生类的事实是否打破了Liskov替换原则?
例如,无法搜索NetworkStream,NotSupportedException
如果Seek
调用该方法,它将抛出一个.
或者因为CanSeek
旗帜的存在可以吗?
鉴于众所周知的例子Square
继承Rectangle
......会标志的加入DoesHeightAffectsWidth
,并DoesWidthAffectsHeight
以Rectangle
解决这个问题?
这不是通过添加标志来打开固定东西的大门吗?
CanSeek
从技术上讲,保持流类不会违反LSP.只有它返回真实,才会寻求工作的承诺.
我个人认为这是一个严重弯曲的ISP和可能是SRP,我的内部设计师会更喜欢类似于可搜索SeekableStream
流可以继承的子类/接口.但我确信这带来了自己的问题(例如,在有时只能搜索的流中)......坦率地说,现实世界的可用性胜过原则.
这是要记住的事情.偶尔,原则与现实相互碰撞.在大多数情况下,SOLID原则有助于最大限度地减少不必要的复杂性,并且通常可以保持OO系统的可维护性并防止它们在自身重量下崩溃.如果纯度导致系统更复杂,但是 - 例如,因为现在只有有时可寻找的流不能很好地适应层次结构 - 那么偶尔的丑陋可能是合理的.
但它永远不应该只是因为法律条文允许它的第一选择.SOLID原则不仅仅是规则; 他们是原则.他们是这些词语背后的思想 - 法律的精神.如果你在通过精神律师的过程中坚持这封信,那么你就错过了原则的全部要点.
至于Square/Rectangle问题......从技术上讲,确定改变高度是否也会改变宽度的属性/函数可以被认为与LSP 的字母保持一致.尽管如此,感觉就像律师一样,并且正在推动其他SOLID原则的界限.从现实的角度来看,它绝对不是最佳解决方案,因为它增加了复杂性并引入了偶然副作用的可能性; 现在所有想说的话rect.Height = 50;
都会无意中改变宽度.
这些Can...
方法意味着Stream
不破坏LSP.Stream
提供读,写和寻找的能力,但不保证任何实施类都会尊重它.这些Can...
方法使这成为Stream
契约的显式特征- 派生类必须实现它们,以允许客户端代码在调用之前检查派生类是否实现某些行为.因此,任何尝试写入a的代码Stream
都应该CanWrite
在调用之前检查Write
,例如,这可以通过任何正确实现的派生来完成Stream
.因此,它们可以互换,因为LSP需要.
我认为添加标记派生类是否实现特定功能的方法肯定会被滥用 - 如果一个团队没有纪律,他们最终可能会有一个非常宽泛,臃肿的界面打破ISP.我认为Stream
并且IList<T>
在这方面设计得很好 - 它们不会破坏LSP,并且它们定义了一个足够狭窄的密切相关行为的合同以留在ISP中.显然,他们的设计已经考虑过了.
我认为,在Square
继承的情况下Rectangle
,您当然可以添加DoesHeightAffectsWidth
并DoesWidthAffectsHeight
解决问题,但团队必须决定是否可以接受,或者这些方法的添加是否会破坏ISP.增加AreAllInternalAnglesEqual
支持梯形太远了吗?在某种程度上,由编写代码的工程师决定.