Can you have too much of “dynamic” in dynamic languages?
Asked Answered
R

6

11

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:

  1. Should I declare types for my parameters, fields, etc?

  2. Should I declare block of code as closure when simple method will do?

  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?

  4. 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?

Revanchism answered 9/12, 2009 at 20:53 Comment(1)
Another reason to declare types is when programming SOAP web services so that generated WSDL can contain some type information...Revanchism
T
1

.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.

Threadfin answered 10/12, 2009 at 4:49 Comment(0)
G
6

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.

Guanabara answered 9/12, 2009 at 21:44 Comment(2)
I like the opt-in approach to dynamic that C# (for example) is taking - static whenever possible, dynamic when required or when there is a clear benefit.Stuck
Mostly I think that your code depends on the team. A good team can make good code in any language. A bad team can make bad code in any language--but amazingly bad code takes both a bad team, a flexible language and a very talented programmer... Restricting the smart programmer of the group who finds a construct that helps him create "Concise" or "Expressive" code before he learns to view his code from the Point of View of the next programmer is probably the best thing a language can do.Guanabara
T
2

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.

Tivoli answered 9/12, 2009 at 21:15 Comment(3)
I usually would use static typing where it makes sense (my code is designed to work for a specific case and I don't want to offer any further guarantees), and allow for dynamic anywhere else (or at least, as dynamic as I would agree to support). It's more of a question of what your code "promises" it does vs. all the potential (mis|ab)uses thereof.Anselma
Is adding static types to your signatures "the simplest way of doing something"?Trophoblast
@Trophoblast - maybe; constraints can greatly simplify things as when there are constraints applied you can let the compiler reason about what types are represented in the codebase rather than having to keep that information in your head.Stuck
T
1

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.

Tynes answered 9/12, 2009 at 21:40 Comment(1)
I must respectfully disagree. An answer along the lines of 'what ever' is a non-answer. Failing to put parameter types in method definitions makes the code much harder to read by an new pair of eyes. It is important to have standards for coding, but it is more important to have standards that demand the best coding practices. And the best coding practices always put code readability as the most important criteria.Akiko
T
1

.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.

Threadfin answered 10/12, 2009 at 4:49 Comment(0)
J
0

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.

Justifiable answered 9/12, 2009 at 21:59 Comment(0)
P
-1

YES

--

NO

Do you realize there is no real answer for this question?

Propel answered 9/12, 2009 at 20:53 Comment(2)
and that mine should've been a comment instead?Propel
I don't think that all points are down to personal preference. For example animal."$action"() breaks OCP; a reason enough to prefer polymorphism.Revanchism

© 2022 - 2024 — McMap. All rights reserved.