Why isn't DRY considered a good thing for type declarations?

It seems that people who never dare to cut and paste the code have no problem finding the type of something over and over again. Why is it not emphasized, as a good practice, that type information should be declared once and only once in order to cause the smallest possible ripple effect in the entire source code if the type changes something? For example, using pseudocode, which 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 that the second is much less fragile if you change the name MyClass or change the type of MyGenericArg or otherwise decide to change the type of foo.

+4
source share
5 answers

This is not considered bad. In fact, supporting C # is already making some headway towards reducing a tired template with the var keyword, where

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

exactly equivalent

 var cont = new MyContainer<MyType>(); 

Although you will see many people discussing use against var , which shows that many people are not familiar with strong typed languages ​​with output types; input type is mistaken for dynamic / soft input.

+1
source

I don’t think you will find much disagreement with your argument that the last example is “better” for the programmer. There are many design features of the language, because they are better for the compiler developer!

See Scala for one confirmation of your idea.

Other languages ​​(for example, the ML family) take the type inference much deeper and create a whole programming style where this type is extremely important, much more than in C-type languages. (See The Little MLer for a gentle introduction.)

+2
source

Repetition can lead to more readable code, and sometimes it may be required in the general case. I have always seen that DRY focuses more on duplicating logic than repeating literal text. Technically, you can exclude "var" and "void" from your lower code. Not to mention the fact that you specify an indented area, why repeat with curly braces?

Repetition can also have practical advantages: parsing a program is easier, for example, saving "void".

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

+1
source

Albert Einstein said: "Everything should be made as simple as possible, but not more simple."

Your complaint does not make sense in the case of a dynamically typed language, so you should call it a reference to statically typed languages. In this case, your replacement example implicitly uses Generics (aka Template Classes), which means that whenever fun or gun , the new definition is based on the type of the argument. This can lead to dozens of additional methods, regardless of the programmer’s intentions. In particular, you are throwing away the benefit of compiler-type security checks for runtime errors.

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

Type declarations are intended to simplify the life of a programmer by trapping errors at compile time, and not to fail at runtime. If your type definition is too complicated, you probably don’t understand your data. In your example, I would suggest adding fun and gun to MyClass instead of defining them separately. If fun and gun do not apply to all possible types of templates, then they should be defined in an explicit subclass, and not as separate functions that take a template argument of the class.

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

Example:

What semantic information does the list convey? It’s just that you work with several triples of integers. On the other hand, List, where the color has 3 integers (red, blue, green) with limited values ​​(0-255), conveys the intention that you work with several colors, but does not give any hints as to whether the List is ordered , allows you to duplicate or any other color information. Finally, the Palette can add these semantics for you: The palette has a name, contains several colors, but no duplicates and the order does not matter.

This has become a bit far from the original question, but for me it means that DRY (Do not Repeat Yourself) means indicating the information once, but this specification should be as accurate as necessary.

0
source

This is bad. This topic was mentioned in Google Go language Techtalk .

0
source

All Articles