Encapsulating with AsObservable
Poor封装可以避免产生预期之外的副作用。下面有几个泄漏的例子,第一个看似无害,但有许多问题:
可以从例子中看到,把可观测物队列Letters暴露为一个属性时它的setter并没有被隐藏,因此subject可以被整个改变。我们需要对此做一些改变,以使其变得更加的安全:
注意,Letters属性是只读的,返回一个 ReplaySubject<string>,可以调用OnNext/OnError/OnCompleted,这就是Poor封装。
下面的例子中,外部的代码将它们的值pushing到了队列中:
Output:
A
B
C
1
从输出中我们看到,外部代码pushing的1被输出了出来。要解决这个问题,使外部代码无法pushing,只需要使用AsObservable扩展方法,将_letters包裹在IObservable<T>里即可。
Output:
A
B
C
could not sabotage
通过隐藏setter来实现只读属性和AsObservable扩展方法返回IObservable<T>类型可以减少问题的发生。
Mutable elements cannot be protected(可变元素不能被保护)
AsObservable方法可以封装你的队列,但你仍需要考虑到类的最终用途,不能对需要进行操作的可变元素设置保护。
下面是一个如果修改队列中的元素就会搞的一团糟的例子:
Output:
1 Garbage
2 Garbage
3 Garbage
completed
从输出中可以看到,与预期的'Microsoft'、 'Google'、'IBM'不同,得到的全是'Garbage'。
可观测物队列将被视为一个解决了的事件(也就是已发生的事实的陈述)的队列,这意味着两件事:1、每个元素都代表发布时的状态的快照;2、信息从可靠的来源传出。要想消除被篡改的可能性,理想情况是将类型T设为不可变,并解决之前提到的2个问题,这样就可以确认得到的是源队列产生的。但最好的方法是通过Transformation操作,也就是提供更好的封装。
应该尽可能的避免副作用,任何并发状态与共享状态的组合通常需要复杂的lock,深入了解CPU构架以及它们如何与你所使用的语言的lock和用优化功能一起工作。简单和首选的方法是避免共享状态,支持不可变类型数据,并利用query composition和transformation操作。在Where和Select子句中隐藏副作用会使代码变得非常混乱,如果实在需要,使用Do方法显示创造副作用,并标明它。
暂无关于此日志的评论。