7年前关闭。
我正在考虑利用业余时间来设计和实施有关形式语言和自动机理论课程的教学工具。我试图确定OOP实现是否合适,如果合适,是否有人可以对我在下面概述的设计提出高水平的建议。
语言分析揭示了许多潜在的类别。一些(请让我知道是否错过了基本知识)是:语法;非终端终奌站;生产;常规语法上下文无关的语法;上下文相关的语法;语法不受限制;自动机州;符号;过渡; DFA; NFA; NFA-Lambda; DPDA; PDA; LBA;图灵机。
问题1:每种语法应在实现中获得自己的类,还是总体语法类具有确定其类型的方法(例如,“ isRegular()”,“ isContextFree()”等) 。)(通常,应该在实现中通过继承来表示在域模型中仅在行为方面仅稍有不同的类,还是将不同种类的行为简单地推入父类会更好?)
问题2:“符号”,“状态”,“非终端”等之类的东西是否应在实现中获得自己的类,还是应由其容器来控制? (通常,应该在实现中为域模型中的非常简单的类赋予它们自己的类(例如,出于可扩展性),还是应该将其推入容器类中?)
问题3:在实现中是否应将Transition作为其自己的类,如果是的话,我将需要对其进行子类化以支持各种自动机(因为除了状态方面有所不同外,它们在发生的情况方面也有所不同在过渡期间)? (更一般而言,在两个孩子的父类和另一个孩子的子类之间存在双射的情况下,是否有两个抽象的父类是一种好习惯?)
我意识到,最终,这些决定中有很多只是设计决定,但是我想知道你们对OOP设计最佳实践的看法。而且,我之所以不只是将“更一般的”问题作为纯OOP设计问题而提出的原因是,我希望从具有这种领域(语言和自动机)经验的人们中获得特殊的见解。
任何帮助是极大的赞赏。
最佳答案
更一般地,应该在实现中通过继承来表示在域模型中仅在行为方面仅稍有不同的类,...
行为不是“唯一的”。行为是对象最重要的部分。
还是简单地将不同种类的行为推送到父类中更好?
当然不是。这将违反Liskov替代原则。
继承不应用于“更轻松地访问常见内容”。
父类的内容绝对是子类的全部内容,如果子代不遵守,则避免继承并使用合成。
更笼统地说,应该在实现中为域模型中的非常简单的类赋予自己的类-例如扩展性-还是应该将其推入容器类?
这取决于您的逻辑有多“深”。
通常,只有在达到某些限制时才开始分解是一个好主意。
有人称它为进化设计。
例如。 -我有“类不得大于〜200行代码”,“对象不得与5-7个以上其他对象交谈”,“方法不得大于〜10行代码”,“逻辑应相同只写一次”等...
另外-很容易低估语义。 if order.isOverdue()
比if order.dueDate<date.Now()
更易于阅读和理解。引入反映域概念的类可以极大地“人性化”代码-增加抽象级别(请考虑“ asm vs java”)。
但是,为了分解而进行分解会导致不必要的复杂性。
它总是必须合理的。
在实现中是否应将Transition作为其自己的类,如果是的话,我将需要对其进行子类化以支持各种自动机(因为除了状态方面有所不同外,它们在过渡期间发生的事情方面也有所不同) ?
只要符合您的域,这没有什么错。
创建抽象是高度依赖您的领域的艺术活动(例如,如果忘记了要求将您的代码作为课程的教学工具的要求,那么来自正式语言和自动机的专家的建议可能会变得过于复杂)。
关于oop - 形式语言和自动机教学工具的OOP设计,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6913836/