首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >这就是动态语言处理动态需求的方式吗?

这就是动态语言处理动态需求的方式吗?
EN

Software Engineering用户
提问于 2012-12-11 07:46:36
回答 5查看 559关注 0票数 3

问题就在标题里。我想让有经验的人来验证我的想法。你可以补充更多,也可以无视我的意见,但请给我一个理由。

下面是一个示例要求:假设您需要实现一个战斗游戏。最初,游戏中只包括战斗机,他们可以互相攻击。每个战士都可以打、踢或阻挡来袭。拳击手可以有不同的格斗方式:空手道,柔道,功夫.这就是游戏中简单的宇宙。在像Java这样的OO中,它可以类似于这样实现:

代码语言:javascript
复制
abstract class Fighter {
    int hp, attack;

    void punch(Fighter otherFighter);
    void kick(Fighter otherFighter);
    void block(Figther otherFighter); 
};

class KarateFighter extends Fighter { //...implementation...};
class JudoFighter extends Fighter { //...implementation... };
class KungFuFighter extends Fighter { //...implementation ... };

如果游戏永远都是这样的话,这是很好的。但是,游戏设计者决定改变游戏的主题:游戏不再是简单的格斗游戏,而是演变成一个角色扮演角色,角色不仅可以战斗,还可以执行其他活动,即角色可以是牧师、会计师、科学家等等。在这一点上,为了使它更加通用,我们必须改变我们最初设计的结构:Fighter不再用于指一个人;它指的是一个职业。战斗机的专业课(KaraterFighter,JudoFighter,KungFuFighter)。现在我们必须创建一个名为Person的泛型类。但是,为了适应这一变化,我必须更改原始操作的方法签名:

代码语言:javascript
复制
class Person {
    int hp, attack;
    List<Profession> skillSet;
};

abstract class Profession {};

class Fighter extends Profession {         
    void punch(Person otherFighter);
    void kick(Person otherFighter);
    void block(Person otherFighter); 
};

class KarateFighter extends Fighter { //...implementation...};
class JudoFighter extends Fighter { //...implementation... };
class KungFuFighter extends Fighter { //...implementation ... };

class Accountant extends Profession {
     void calculateTax(Person p) { //...implementation...};
     void calculateTax(Company c) { //...implementation...};
};
//... more professions...

以下是问题所在:

  1. 为了适应方法的更改,我必须修复调用更改方法的位置(重构)。
  2. 每当提出新的要求时,就必须打破现有的结构设计,以适应变化。这就引出了第一个问题。
  3. 僵化的结构使得代码重用变得困难。函数只能接受预定义的类型,但不能接受未来的未知类型。编写的函数绑定到其当前空间,无法适应新类型,无需从头修改或重写。我看到Java有很多不推荐的方法。

OO是一个极端的例子,因为它有继承来增加复杂性,但是对于静态类型化语言来说,类型是非常严格的。

相反,动态语言可以按以下方式处理上述情况:

代码语言:javascript
复制
;;fighter1 punch fighter2
(defun perform-punch (fighter1 fighter2) ...implementation... )

;;fighter1 kick fighter2
(defun perform-kick (fighter1 fighter2) ...implementation... )

;;fighter1 blocks attacks from fighter2
(defun perform-block (fighter1 fighter2) ...implementation... )

只要fighter1fighter2具有计算所需的数据或方法(鸭类型),它就可以是任何东西。您不必从Fighter类型更改为Person类型。在Lisp的例子中,因为Lisp只有一个数据结构: list,所以更容易适应变化。然而,其他动态语言也可以有类似的行为。

我主要使用静态语言(主要是C和Java,但使用Java是很久以前的事了)。今年我开始学习Lisp和其他一些动态语言。我能看到它如何帮助提高我的生产力。

EN

回答 5

Software Engineering用户

发布于 2012-12-31 16:12:11

我不太清楚你的问题是什么,因为这个问题包含了一些模糊的术语:“动态语言”、“这个”和“动态需求”。

"Dynamic“指的是任何一种编程语言,这些语言可以在编译时完成其他语言可能做的事情。这可以包括数据值的方面(null或null)、类型系统的方面(例如在运行时创建新类型)、方法和函数分派的方面以及许多其他方面。您的问题似乎主要涉及动态方法分派(尽管稍后将讨论静态类型)。我对此的态度是,不同的语言为如何处理需求和不断变化的需求提供了不同的工具。从这个意义上说,你的问题的答案可能是“是”。在Java或Scala这样的语言提供接口和特性以使程序的设计更容易适应不断变化的需求的情况下,Clojure这样的语言提供动态调度,Groovy提供元编程,而其他语言则不提供或很少提供工具。我认为这些工具中哪一个更适合这个任务取决于任务的细节、“更好”定义的细节(开发时间和精力、程序员的可用性、代码的性能、运行时某些类型错误的可能性等等)。以及个人喜好,一般都无法回答。

票数 2
EN

Software Engineering用户

发布于 2014-01-28 13:39:00

我认为答案可以归结为:是的,一种“动态”语言可以帮助您提高编码效率,因为您可以快速、轻松地进行全面的更改。然而,它损害了您的发布效率,因为您已经创建了一堆没有一致结构的代码,以及许多只需要在运行时检测到的错误,这些错误需要稍后修复,而不是像您在“静态”语言中得到的那样快。

没有什么可以代替正确地做事情,这意味着思考、设计和仔细考虑更改的影响。

票数 1
EN

Software Engineering用户

发布于 2014-01-28 18:31:53

在重构时,动态语言的抱怨可能较少,但它也可能对您隐藏静态类型语言编译时捕获的类型错误。通常,无论您使用的是动态类型语言还是静态类型语言,当需求发生变化时,您都必须重构代码。那里没有银弹。

C和Java对于静态语言来说不是很好的基准测试,因为它们有非常有限的类型系统和特性。在没有极端详细的情况下,您无法在Java中完成任何事情。想通过一个元组吗?嗯,你不能。唱片?不行,想要匿名函数吗?你必须为一个有效载荷写4行样板,它可能短到2 +2。如果你想要整理或组合函数,上帝保佑你。

你必须求助于一堆OO黑客来解决这些缺失的特性,即使这样,你仍然可以用继承和空来攻击自己,因为很多人不知道他们有多危险。因此,如果这是您唯一的参考点,那么几乎任何动态语言都将允许您编写更少的代码,但不一定是因为它们的动态类型。像Standard或F#这样的语言也提供了这些特性,而无需为您添加类型注释,因为编译器可以推断这些类型。

好的静态类型化语言比具有等价特性的动态类型化语言更具表现力.动态键入剥夺了使用类型系统表示数据约束的能力。这是因为动态类型是静态类型的一种特例--将这些语言看作是统一类型更正确。如果这对您来说很奇怪,那么想象一下在Java中只使用对象变量和强制转换进行编码。问题是主流静态类型化语言被削弱了。但是如果您正在Lisp中编码,我认为您并不太关心什么是主流。

票数 1
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/179000

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档