项目刚开始的时候会遇到很多问题,特别是架构的设计会出现很多变故。昨天刚经历了“过度设计”事件,使我更加认识到真实项目的艰险——这仅仅是一个实验项目,难度也不高,但前两天过的就那么有声有色,还是有点出乎意料。可以想像,今天也绝对不会平淡。
果然,“作坊”出事了!
还是先回顾一下“作坊”的作用吧。作坊主要的工作是把词元(零件)进行分类,而分类的原理则是基于以下事实(请原谅我们最初对ASN的肤浅认识吧,以后我会用正确的认识更正这些误解):所有用ASN语法的定义数据结构都能够规约成typereference ::= Type Definition Constraint的形式,而其中的Type包括SEQUENCE、CHOICE和SET,以及其他更加简单的格式。SET和其他格式我并没有介绍,不过这不影响本文叙述。Definition是大括号之间的,Constraint则可以为空。例如:
A ::= SEQUENCE
{
b BOOLEAN,
c INTEGER
}
其中,typereference="A",Type="SEQUENCE",Definition="{ b BOOLEAN, c INTEGER }",Constraint=""。
又如:
B ::= INTEGER (1..255)
其中,typereference="B",Type="INTEGER",Definition="",Constraint="(1..255)"。该Constraint表明,B类型的变量只能是范围在[1, 255]的整数。
既然有这个前提假设,那么再来看看Definition怎么解析比较好。注意到去掉大括号之后,Definition就变成"b BOOLEAN, c INTEGER",而且事实上c INTEGER还可以扩充为c INTEGER (1..255) 这样的形式,也可以写成c SEQUECE {...},这正表明c INTEGER这样的式子也可以表达为 typereference Type Definition Constraint的形式。
于是,作坊中很自然地出现了专门处理类型的工人(就是处理带有“::=”的式子)和专门处理成员的工人(就是处理不带“::=”的式子),然后界定工人的处理范围和收集工人的处理结果就由经理来负责。经理可以仅通过大括号和逗号就能方便的界定工人工作的范围。
这看起来很好,但是在真正工作的过程中,经理突然失业了。主要是因为出现了这种情况:
A ::= SEQUENCE
{
b SEQUENCE
{
c INTEGER
} OPTIONAL
}
请注意看这个b和OPTIONAL,其实OPTIONAL是用来修饰b的。那么,如何界定工作范围好呢?不知道!这个东西似乎更应该变成递归调用方式比较好,也就是,处理类型的工人遇到大括号就停止手头的工作去找处理成员的工人帮忙,而处理成员的工人遇到大括号就停止手头的工作找另外处理成员的工人帮忙,这样一直处理下去就可以。不过似乎还是需要经理来协调各个工人的输出,但是工人在工作的时候本来就需要以前工作的资料才行,所以工人本身就可以把输出整理得很好。
看来控制生产资料的经理失业了。
回过头来再想想,经理的存在本身就违反了单一职责原则,他既界定工作范围又收集资料,而且在这种特定的语法之下,他还需要带有一定的递归(或者用栈来模拟递归),实在太累了。况且工人工作的时候本身就可以获得几乎跟经理一样多的信息,这样的工人当然要造反了。不过现在的工人也同时拥有多种职责,这只要从基类上进行划分应该就能解决问题,这已经比经理存在时好多了。
