你能不能有太多的“动态”?在动态语言中?
在过去的几个月里,我一直在从 Java 过渡到 Groovy,我可以体会到它带来的许多好处:更少的代码、闭包、构建器、MOP,最终使像 Grails 这样的框架成为可能、在编写测试时轻松进行模拟等 然而,
我的同事“指责”我的代码不够好。也就是说,我仍然为参数和字段声明类型,倾向于使用继承和多态性而不是鸭子类型等。在我看来,在这些情况下,它不仅是动态与静态,而且是动态与面向对象范例一种困境。在这些情况下,我仍然倾向于选择面向对象。我认为 OO 范式在其基本前提上具有巨大的价值,它允许您抽象代码结构并将其与特定的现实世界概念联系起来。
因此,以下是我需要帮助的特殊问题:
我应该为我的参数、字段等声明类型吗?
当简单方法可以时,我应该将代码块声明为闭包吗?
什么时候应该使用鸭子类型而不是多态动态调度。例如,在groovy中我可以做animal."$action"()或defanimal; Animal.action() ,而不是 Animal Animal = new Dog();动物.action()。我可以在开闭原则的背景下看到第一个问题,但是还有其他原因更喜欢 OO 风格的多态性吗?
我什么时候应该在 groovy 中使用接口(如果有的话)?
我确信还有一些其他类似的困境我没有写下来。我还认为这些问题不仅适用于 groovy,也适用于任何其他动态语言。 你的意见是什么?
In last few months I have been making a transition from Java to Groovy and I can appreciate many of the benefits it brings: less code, closures, builders, MOP that in the end makes framework like Grails possible, ease with mocking when writing tests etc.
However, I have been “accused” by my coworkers that my code is not groovy enough. Namely, I still declare types for my parameters and fields, tend to use inheritance and polymorphism instead of duck typing etc. It seems to me that in these situations it is not only dynamic vs. static, but also dynamic vs. object-oriented paradigm kind of dilemma. In those cases I still tend to prefer OO. I feel that OO paradigm has great value in its basic premise in allowing you to abstract and relate your code constructs to particular real-world concepts.
So, here are particular questions I need help with:
Should I declare types for my parameters, fields, etc?
Should I declare block of code as closure when simple method will do?
When should I use duck typing instead of polymorphic dynamic dispatch. For example, in groovy I can do animal."$action"() or def animal; animal.action() , instead of Animal animal = new Dog(); animal.action(). I can see the problem with first in the context of Open-Closed principle, but any other reasons to prefer OO style polymorphism?
When should I use interfaces in groovy (if ever)?
I am sure that there are some other similar dilemmas I failed to write down. I also think that these questions are valid not just for groovy, but for any other dynamic language.
What is your opinion?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
这并不总是流行的观点,但我认为代码越明确和清晰越好。
我不喜欢让你猜测到底发生了什么的结构...
我在 Ruby 中工作了一年,但一点也不喜欢它。我并不是说它没有擅长的地方,我只是说我真的很喜欢让事情保持干净和明确,并且不认为 Ruby 以此为目标。
我确实弄清楚了一件事——输入的数量并不等于整体开发速度。确实,包含大量重复代码的复杂代码库会导致开发速度非常慢,但是仅仅减少键入内容而不消除重复是没有用的,并且键入更长、更清晰、更明确的代码通常会更快(超过项目的长度)比用简洁、不太正式的语言编写的相同代码要好。
如果您不认为打字与开发速度无关,那么下次您发布项目时,请计算代码行数并除以所花费的人日(包括调试和测试)。换句话说,每天输入多少代码。您会发现结果非常小——实际上,键入代码只是任何软件项目的一小部分。
This isn't always a popular opinion, but I think that the more explicit and clear your code can be, the better.
I dislike constructs that leave you guessing just what's going on...
I worked for a year in Ruby and didn't like it at all. I'm not saying that it doesn't have places where it excels, I'm just saying that I really like to keep things clean and explicit and didn't feel that Ruby had that as a goal.
One thing I did figure out for sure--the amount of typing you do does not equate to overall development speed. It's true that a complicated code base with a lot of repeated code makes for very slow development, but simply reducing what you type without eliminating the duplication is useless, and typing longer, clearer, more explicit code is going to generally be faster (over the length of the project) than the same code written in a terse, less formal language.
If you don't believe that typing has no relation to development speed, next time you release a project count the number of lines of code and divide by the man-days spent (including debugging and testing). In other words, how much code was typed a day. You'll find the result to be a very small number--actually typing code is a very small part of any software project.
我认为对于 Groovy,您应该偏爱用最简单的方式来做某事,只有在情况需要时才使用更 groovy 的功能。 (就像在 Clojure 中编写宏或创建多方法时一样,如果您发现自己经常使用这些工具,您应该质疑自己。)您谨慎的方法对我来说似乎很好,可能您的同事对他们新发现的功能有点陶醉。 (这不是第一次。)
拥有像 Groovy 这样灵活的语言的好处是,您可以从谨慎的方法开始,就像您喜欢知道在需要时可以依靠更强大的替代方案一样。你知道,“最简单的事情可能有效。”
更具体地说,更喜欢鸭子类型而不是接口,并且不关心参数的类型,这似乎是一件好事,它可能会使向测试提供模拟变得更加容易。
I think with Groovy you should favor the simplest way of doing something, and fall back on the groovier features only when the situation calls for it. (Like when writing macros or creating multimethods in Clojure, if you find yourself reaching for those tools a lot you should question yourself.) Your cautious approach seems fine to me, possibly your co-workers are a little intoxicated with their new-found power. (It wouldn't be the first time.)
The good thing about having a flexible language like Groovy is you can start off with the cautious approach like you favor knowing you have more powerful alternatives to fall back on when you need them. You know, "the simplest thing that could possibly work."
More specifically preferring duck typing over interfaces and not bothering with types on parameters seems like it could be a good thing, it may make it a lot easier to supply mocks to tests.
.1.我应该为我的参数、字段等声明类型吗?
我倾向于在用作公共 API 一部分的类上声明类型,其他开发人员会经常使用这些类型,或者我需要 IntelliJ 提供一些额外的自动完成帮助。否则我会“定义”事物。
.2.当简单方法可以时,我应该将代码块声明为闭包吗?
我使用方法,除非它是我计划作为变量传递的东西。尽管有“foo.&bar”方法解引用运算符,但大多数开发人员并不知道这一点,并且在遇到它时会感到困惑。当一小段代码显然保留在更大的方法中而不是出于描述目的放入它自己的方法中时,我也会使用闭包。
.3.我什么时候应该使用鸭子类型而不是多态动态调度。例如,在groovy中我可以做animal."$action"()或defanimal; Animal.action() ,而不是 Animal Animal = new Dog();动物.action()。我可以在开闭原则的背景下看到第一个问题,但是还有其他原因更喜欢 OO 风格的多态性吗?
当我需要这种间接级别时,我只使用animal."$action"() 形式,因为方法名称根据代码执行路径而变化(最常见的是在繁重的元编程期间)。我使用 Animal Animal = new Dog();当我需要 IDE 帮助自动完成时,或者该级别的文档有助于代码清晰(并且不会因可能明显或受限的额外冗长而受到损害)时,我可以使用 Animal.action() 。
.4.我什么时候应该使用 groovy 中的接口(如果有的话)?
我很少使用它们。我可以看到它们主要用作公共 API 调用的预期字段的文档,或者可能用作标记接口,以帮助从元编程的角度区分一组类和另一组类。它们在 groovy 中的用处远不如在 java 中有用。
.1. Should I declare types for my parameters, fields, etc?
I tend declare types on classes that are used as part of a public API, things that other developers will be consuming a lot, or where I'd like some additional autocomplete help from IntelliJ. Otherwise I 'def' things.
.2. Should I declare block of code as closure when simple method will do?
I use methods unless it's something I plan on passing around as a variable. Even though there is the "foo.&bar" method dereference operator, most devs don't know about this and are confused by it when they run across it. I also use closures when it's a small piece of code that is clear to remain in a larger method rather than put in it's own method for descriptive purposes.
.3. When should I use duck typing instead of polymorphic dynamic dispatch. For example, in groovy I can do animal."$action"() or def animal; animal.action() , instead of Animal animal = new Dog(); animal.action(). I can see the problem with first in the context of Open-Closed principle, but any other reasons to prefer OO style polymorphism?
I only use the animal."$action"() form when I need that level of indirection because the method name varies based on the code execution path (most often during heavy metaprogramming). I use Animal animal = new Dog(); animal.action() when I want the IDE's help with autocompletion, or that level of documentation is helpful for code clarity (and not hurt by the extra verboseness that might be obvious or constraining).
.4. When should I use interfaces in groovy (if ever)?
I very rarely use them. I could see using them mostly as documentation of the expected fields for a public API call, or possibly as a marker interface to help distinguish one set of classes from another from a metaprogramming perspective. They're much less useful in groovy than they are in java.
这取决于人们感到舒服的程度。我喜欢使用类型声明和方法调用,因为我对 Java 很熟悉。我编写的代码必须由没有太多动态编程经验的人来维护,因此我将其保持为接近普通的 Java 代码,除非有充分的理由使用高级 Groovy 功能。听起来您的团队应该创建编码标准,尝试解释一般何时应使用 Groovy 的特定功能。
It comes down to what people are comfortable with. I like to use type declerations and method calls because I'm comfortable in Java. The code I write has to be maintained by people with out much dynamic programming experience so I keep it close to normal Java code unless there's a good reason to use an advanced groovy feature. IT sounds like your group should create coding standards that try to explain when specific features of Groovy should generally be used.
面向对象语言有两种主要类型。
Simula 67 系列中的语言(例如 C++ 和 Java)支持静态类型变量、编译器和链接器以及方法 vtable。
Smalltalk 系列中的语言(例如 Ruby)更喜欢动态类型变量、解释和消息传递,而不是函数指针表。
两者都是面向对象的,但是面向对象的概念却截然不同。
There are two dominant types of object-oriented languages.
The languages in the Simula 67 family, such as C++ and Java, favor statically-typed variables, compilers and linkers, and method vtables.
The languages in the Smalltalk family, such as Ruby, favor dynamically-typed variables, interpretation, and message-passing instead of function-pointer-tables.
Both are object-oriented, but very different takes on the concept of object-orientation.
是
-
否
您是否意识到这个问题没有真正的答案?
YES
--
NO
Do you realize there is no real answer for this question?