2

我正在考虑利用一些空闲时间来设计和实施形式语言和自动机理论课程的教学工具。我正在尝试确定 OOP 实现是否合适,如果合适,是否有人可以建议对我在下面概述的设计进行高级改进。

语言分析中揭示了许多潜在的类别。一些(如果我错过了任何基本内容,请告诉我)是:语法;非终结符;终端; 生产; 常规语法;上下文无关语法;上下文相关的语法;不受限制的语法;自动机;状态; 象征; 过渡; DFA;NFA;NFA-拉姆达;DPDA;掌上电脑;体重秤;图灵机。

问题1:每种语法在实现中是否应该有自己的类,或者一个总体语法类是否应该有方法来确定它是哪种语法(例如,“isRegular()”、“isContextFree()”等.) (更一般地说,在领域模型中只有一点点不同的类,并且仅在行为方面,应该通过实现中的继承来表示,还是将不同类型的行为简单地推送到父类中更好?)

问题 2:“Symbol”、“State”、“Nonterminal”等是否应该在实现中拥有自己的类,还是应该由它们的容器控制? (更一般地说,是否应该在实现中为域模型中的非常简单的类赋予它们自己的类 - 例如为了可扩展性 - 还是应该将其推入容器类中?)

问题 3:Transition 在实现中是否应该是它自己的类,如果是,我是否需要对它进行子类化以支持每种自动机(因为除了在状态方面有所不同,它们在发生的情况方面也有所不同在过渡期间)? (更一般地说,有两个抽象父类,其中一个的孩子和另一个的孩子之间存在双射......耦合是一种好习惯吗?)

我意识到,归根结底,很多这些决策只是设计决策,但我想知道你们对 OOP 设计中的最佳实践有何看法。此外,我不只是将“更普遍”的问题作为纯 OOP 设计问题提出的原因是,我希望从具有此类领域(语言和自动机)经验的人那里获得特殊的观点。

任何帮助是极大的赞赏。

4

3 回答 3

2

more generally, should classes which differ only a little in the domain model, and only in terms of behavior, be represented via inheritance in the implementation, ...

Behavior is not "only". Behavior is most important part of objects.

or is it better to simply push different kinds of behavior into the parent class?

Certainly not. That would be violation of Liskov substitution principle.
Inheritance should not be used for "easier access to common stuff".

Content of parent class muss be completely ubiquitous with child classes, avoid inheritance and use composition if child does not comply w/ it.

more generally, should very simple classes in the domain model be given their own classes in the implementation - e.g. for extensibility - or should that be pushed into the container class?

It kind a depends on how "deep" Your logic is going to go.

Usually it's a good idea to start decomposition only when you hit some limits.
Some people call it evolutionary design.

E.g. - I have "class must not be larger than ~200 lines of code", "object must not talk with more than 5-7 other objects", "method should not be larger than ~10 lines of code", "same logic should be written once only" etc...

Also - it's easy to underestimate semantics. if order.isOverdue() is much more easily readable and understandable than if order.dueDate<date.Now(). Introducing classes that reflect concepts of domain greatly "humanizes" code - increases abstraction level (think "asm vs java").

But decomposition for the sake of decomposition leads to unnecessary complexity.
It always must be justified.

Should Transition be its own class in the implementation and, if so, will I need to subclass it in order to support each kind of automaton (since, besides differing in terms of the state, they also differ in terms of what happens during transitions)?

There is nothing wrong with that as long as it complies with Your domain.

Creation of abstractions is artistic activity that highly depends on Your domain (e.g. advises from experts at formal languages & automata might be severely over-complicated if requirement that Your code is supposed to be as a teaching tool for a course is forgotten).

于 2011-08-02T16:21:03.897 回答
2

好主意。做过类似的事情,首先是过程编程,首先是面向对象,然后是。

答案 1:两者都有。一些语法或标记将具有特定的方法或属性,而另一些则应在所有语法之间共享。

答案2:它们应该有自己的类,可能有共同的祖先。

答案 3:可以两种方式处理,但定义一个特定的类可能会很有用。我同意其他类/对象之间存在交叉或关联,但是它们很难建模。“代理”设计模式就是一个例子。

用 LEX、Bison、yacc 教授语言设计很困难。我“听说”ANTLR 是一个很好的设计工具,用于教授编译器相关的东西。

你想让我做什么 ?

面向对象的解析器/扫描器?

已经有一些了,我很难理解如何使用它们。其中一些声明了新语法,例如定义新类,但是在这种情况下,我发现函数式编程(语法)或逻辑编程(语法)更适合声明规则。

视觉相关工具:

http://www.ust-solutions.com/ultragram.aspx

http://www.sand-stone.com/

http://antlr.org/

http://antlr.org/works/index.html

祝你好运 ;-)

于 2011-08-02T15:13:38.907 回答
2

如果您想使用现有解决方案而不是编写一个解决方案,我在 NCSU 的一些朋友编写了一个名为ProofChecker的工具,它可能适合您。

它是用 Java 编写的,因此也可以满足您的 OO 角度。

于 2011-08-02T20:56:39.593 回答