views:

185

answers:

5

It seems like people who would never dare cut and paste code have no problem specifying the type of something over and over and over. Why isn't it emphasized as a good practice that type information should be declared once and only once so as to cause as little ripple effect as possible throughout the source code if the type of something is modified? For example, using pseudocode that borrows from C# and D:

MyClass<MyGenericArg> foo = new MyClass<MyGenericArg>(ctorArg);

void fun(MyClass<MyGenericArg> arg) {
    gun(arg);
}

void gun(MyClass<MyGenericArg> arg) {
    // do stuff.
}

Vs.

var foo = new MyClass<MyGenericArg>(ctorArg);

void fun(T)(T arg) {
    gun(arg);
}

void gun(T)(T arg) {
    // do stuff.
}

It seems like the second one is a lot less brittle if you change the name of MyClass, or change the type of MyGenericArg, or otherwise decide to change the type of foo.

+2  A: 

I don't think you're going to find a lot of disagreement with your argument that the latter example is "better" for the programmer. A lot of language design features are there because they're better for the compiler implementer!

See Scala for one reification of your idea.

Other languages (such as the ML family) take type inference much further, and create a whole style of programming where the type is enormously important, much more so than in the C-like languages. (See The Little MLer for a gentle introduction.)

Jonathan Feinberg
+1  A: 

Repetition may lead to more readable code, and sometimes may be required in the general case. I've always seen the focus of DRY being more about duplicating logic than repeating literal text. Technically, you can eliminate 'var' and 'void' from your bottom code as well. Not to mention you indicate scope with indentation, why repeat yourself with braces?

Repetition can also have practical benefits: parsing by a program is easier by keeping the 'void', for example.

(However, I still strongly agree with you on prefering "var name = new Type()" over "Type name = new Type()".)

Roger Pate
"Not to mention you indicate scope with indentation, why repeat yourself with braces?" There's at least one major programming language (Python) which says exactly that, and therefore uses indentation for scope. I think it's for the better.
Edan Maor
Though I avoided mentioning it by name so people who are otherwise prejudiced against Python might see one merit in the idea! :P
Roger Pate
+1 (for Vinko too) - I agree on both counts. It's all about readability, and in the simple case with "new Type" repeating Type adds nothing but noise.
TrueWill
+1  A: 

It isn't considered a bad thing at all. In fact, C# maintainers are already moving a bit towards reducing the tiring boilerplate with the var keyword, where

MyContainer<MyType> cont = new MyContainer<MyType>();

is exactly equivalent to

var cont = new MyContainer<MyType>();

Although you will see many people who will argue against var usage, which kind of shows that many people is not familiar with strong typed languages with type inference; type inference is mistaken for dynamic/soft typing.

Vinko Vrsalovic
A: 

Albert Einstein said, "Everything should be made as simple as possible, but not one bit simpler."

Your complaint makes no sense in the case of a dynamically typed language, so you must intend this to refer to statically typed languages. In that case, your replacement example implicitly uses Generics (aka Template Classes), which means that any time that fun or gun is used, a new definition based upon the type of the argument. That could result in dozens of extra methods, regardless of the intent of the programmer. In particular, you're throwing away the benefit of compiler-checked type-safety for a runtime error.

If your goal was to simply pass through the argument without checking its type, then the correct type would be Object not T.

Type declarations are intended to make the programmer's life simpler, by catching errors at compile-time, instead of failing at runtime. If you have an overly complex type definition, then you probably don't understand your data. In your example, I would have suggested adding fun and gun to MyClass, instead of defining them separately. If fun and gun don't apply to all possible template types, then they should be defined in an explicit subclass, not as separate functions that take a templated class argument.

Generics exist as a way to wrap behavior around more specific objects. List, Queue, Stack, these are fine reasons for Generics, but at the end of the day, the only thing you should be doing with a bare Generic is creating an instance of it, and calling methods on it. If you really feel the need to do more than that with a Generic, then you probably need to embed your Generic class as an instance object in a wrapper class, one that defines the behaviors you need. You do this for the same reason that you embed primitives into a class: because by themselves, numbers and strings do not convey semantic information about their contents.

Example:

What semantic information does List convey? Just that you're working with multiple triples of integers. On the other hand, List, where a color has 3 integers (red, blue, green) with bounded values (0-255) conveys the intent that you're working with multiple Colors, but provides no hint as to whether the List is ordered, allows duplicates, or any other information about the Colors. Finally a Palette can add those semantics for you: a Palette has a name, contains multiple Colors, but no duplicates, and order isn't important.

This has gotten a bit far afield from the original question, but what it means to me is that DRY (Don't Repeat Yourself) means specifying information once, but that specification should be as precise as is necessary.

Craig Trader
Ok, but that was just a simple example. What if fun and gun are members of a different class? What if they take two instances of MyClass as an argument? etc.Also, as far as understanding your data, what about generic types from libraries?
dsimcha
A: 

It's a bad thing. This very topic was mentioned in Google's Go language Techtalk.

Shawn J. Goff