Oop 在构建lexer/scanner时,如何使用面向对象的设计范式?
我正在尝试设计一个小型正则表达式引擎(在Smalltalk中),以帮助提高我的面向对象技能 我用其他语言(以及Smalltalk原生语言)研究了一些正则表达式引擎,它们似乎都有一个单独的“Lexer”或“Scanner”类。这让我感到困惑,因为我认为lexer是一个单一的函数,它应该将模式作为输入(可能是一个“语法”对象,它定义令牌类型),并返回令牌流。我很难弄清楚接口将具有哪些额外功能,以及对象需要保持哪些额外状态 如何将其分解为面向对象的设计?Oop 在构建lexer/scanner时,如何使用面向对象的设计范式?,oop,architecture,smalltalk,lexer,Oop,Architecture,Smalltalk,Lexer,我正在尝试设计一个小型正则表达式引擎(在Smalltalk中),以帮助提高我的面向对象技能 我用其他语言(以及Smalltalk原生语言)研究了一些正则表达式引擎,它们似乎都有一个单独的“Lexer”或“Scanner”类。这让我感到困惑,因为我认为lexer是一个单一的函数,它应该将模式作为输入(可能是一个“语法”对象,它定义令牌类型),并返回令牌流。我很难弄清楚接口将具有哪些额外功能,以及对象需要保持哪些额外状态 如何将其分解为面向对象的设计? 我应该补充一点,当我阅读源代码时,我似乎经常看
我应该补充一点,当我阅读源代码时,我似乎经常看到这一点:一个在名称末尾添加了动词+“er”的类。这似乎与“干净的代码”和“完整的代码”等书所教的“正确的面向对象设计”背道而驰 这是一个非常宽泛的问题,所以我们只能给你同样宽泛的答案。这是我的 在考虑面向对象时,我们试图在数据和行为之间建立明确的区别。一个对象同时具有这两个属性,一般来说,行为与数据越独立越好 这些基本的指导原则并不总能使设计看起来自然。原因是,有时我们倾向于将与某些数据相关的行为附加到非常相同的数据上。这可能会隐藏应该拥有这种行为的实际对象 这种现象的一个典型例子是算法。我们有一些数据:算法输入和一些行为:算法输出,并且认为这些行为应该附加到数据中。因此,我们很难将其作为上述数据的函数来实现 然而,在大多数情况下,这种简单化的方法是有问题的。例如,许多算法可能会产生多个输出。以两个多项式的除法为例,其中输出为商和余数。即使算法生成一个输出,我们可能会询问它需要多长时间,甚至告诉它取消执行并停止自己,等等 由于这些原因(以及其他类似的原因),将算法视为对象而不是函数总是可取的。这样一个对象的实例变量通常会引用
inputs - "one or more depending on the algorithm"
outputs - "idem"
auxiliary - "for holding the algorithm internal state while running"
progress - "for recording degree of advancement"
state - "various uses"
将算法实现为对象将有助于添加以下功能:
#cancel
)如您所见,作为对象的算法比作为函数的算法丰富得多。这并不意味着您必须放弃功能性方法。只需具体化算法,让您的客户端对象提供一个函数,该函数将使用该算法并返回与该上下文相关的结果。从名称Lexer/Scanner/Parser/Compiler/中可以清楚看出。。。我们正在具体化一个函数。但请记住,在Smalltalk中,没有任何功能。只有对象和消息 当然,脑海中浮现的明显目标是:
- 无论是什么节点组成了你将要产生的树状结构
- 如果你想有一个中间的Lexer
- 语法本身(更高级)
首先自己尝试一下,但一旦你取得了足够的进步,我强烈建议你学习PetitPasser,在这里做一个介绍。你会发现语法本身,或者更确切地说是构成语法的节点,可以充当解析器,从而分解为基本、简单、优雅和可组合的对象。如果你对Smalltalk感兴趣,我强烈建议你至少读一本关于这个主题的好书。一个例子是肯特·贝克(Kent Beck)。