苛评VCL: 混乱的TStream

<p style="text-indent: 21pt;">为什么这么苛刻地来评论VCL的基础类设计,我已经在前一篇关于TObject的文章中讲过。今天我拿出在一次跟踪VCL代码的过程中发现的问题。在此之前,我没有任何理由会相信会存在这样的情况。</p>
<p style="text-indent: 21pt;">TForm读取dfm文件创建窗体过程大家一定都比较清楚,其中负责读取的是Classes.pas单元中的TReader类,而它在实现的时候,会调用到如下的函数:</p>
<blockquote>
<pre><strong>function</strong> InternalReadComponentRes(<strong>const</strong> ResName: <strong>string</strong>; HInst: THandle; <strong>var</strong> Instance: TComponent): Boolean;<br><strong>var</strong><br>  HRsrc: THandle;<br><strong>begin</strong>                   { avoid possible EResNotFound exception }<br><strong>if</strong> HInst = 0 then HInst := HInstance;<br>  HRsrc := FindResource(HInst, PChar(ResName), RT_RCDATA);<br>  Result := HRsrc &lt;&gt; 0;<br><strong>if</strong> <strong>not</strong> Result <strong>then</strong> Exit;<br><strong>with</strong> TResourceStream.Create(HInst, ResName, RT_RCDATA) <strong>do</strong><br><strong>try</strong><br>    Instance := ReadComponent(Instance);<br><strong>finally</strong><br>    Free;<br><strong>end</strong>;<br>  Result := True;<br><strong>end</strong>;</pre>
</blockquote>
<p style="text-indent: 21pt;">大家请注意TResourceStream的方法ReadComponent。是的,我想说的其实就是这个方法。大家可以回过头来看看TStream的声明:</p>
<blockquote>
<pre>...<br><strong>function</strong> ReadComponent(Instance: TComponent): TComponent;<br><strong>function</strong> ReadComponentRes(Instance: TComponent): TComponent;<br><strong>procedure</strong> WriteComponent(Instance: TComponent);<br><strong>procedure</strong> WriteComponentRes(<strong>const</strong> ResName: <strong>string</strong>; Instance: TComponent);<br><strong>procedure</strong> WriteDescendent(Instance, Ancestor: TComponent);<br><strong>procedure</strong> WriteDescendentRes(<strong>const</strong> ResName: <strong>string</strong>; Instance, Ancestor: TComponent);<br><strong>procedure</strong> WriteResourceHeader(<strong>const</strong> ResName: <strong>string</strong>; <strong>out</strong> FixupInfo: Integer);<br><strong>procedure</strong> FixupResourceHeader(FixupInfo: Integer);<br><strong>procedure</strong> ReadResHeader;<br>...</pre>
</blockquote>
<p style="text-indent: 21pt;">对于Stream这个抽象概念,很多人对它的理解过程都是曲折的。但不管怎么样,它基本特性还是比较清晰的。Read、Write、Position、Seek等等基本方法,构成了流的基本属性。</p>
<p style="text-indent: 21pt;">然而,令我不明白的地方是,为什么Delphi会在基础类TStream中增加上述的那些有关Component的方法。这些显然和流的职责没有关系!</p>
<p style="text-indent: 21pt;">在单一职责原则中,建议将两种不同的职责分成两个类实现,或继承、或组合。要说TStream的这些Component的方法,要么可以定义单独的Component资源类,要么做出TStream的Helper类。但总比像VCL这样设计好吧。</p>
<p style="text-indent: 21pt;">现在猜想VCL当时的设计情形,很可能Classes单元的类,很多是为了Delphi的组件系统的实现(或者说是IDE本身)。所以很多类在设计的时候,默认都引入了TComonent类。</p>
<p style="text-indent: 21pt;">这么说是有根据的,不光是TStream类,在这个单元中的TParser类也是如此。我发现TParser类的时候是非常惊喜的,但是使用后发现,其规则是按照dfm来做的。在分析Delphi的源码的时候,会遇到注释不能识别的问题。</p>
<p style="text-indent: 21pt;">一向认为单一职责最难把握,现在看VCL,呵呵,确实如此啊。</p>

你可能感兴趣的:(Stream)