Ruby and Duck Typing: Design by Contract Impossible

Ruby parameter type confirmation

Heh, welcome to Ruby. I too worked in Java in certain past years and I really loved Java at the time.

Now, it's not correct to think of Ruby as lacking type checking. It has at least as much type checking as Java, it's just that types are allowed to change and so the checks are done at runtime.

Plus, all that crushing declaration boilerplate in the old languages is annoying. A type-checked application that doesn't get finished in time to be useful does no one any good. A type-checked program that's too verbose to read is likely to become obsolete.

And if a type doesn't get checked the first time you run your Ruby program, it may well be covered by your tests.

But if you don't test it, you have no idea if it works anyway, so the abstract knowledge that the method call types conform would not be nearly as helpful as you might imagine.

In any case, Ruby has proven itself pretty well at this point as a language. As a real-life platform, RoR has some issues with performance, both in speed and in memory use, but I don't know of any projects complaining about the dynamic typing and wishing they were slogging through getting RSI with some old verbose language.

How is duck typing different from the old 'variant' type and/or interfaces?

The simple answer is variant is weakly typed while duck typing is strongly typed.

Duck typing can be summed up nicely as "if it walks like a duck, looks like a duck, acts like a duck, then it's a duck." It computer science terms consider duck to be the following interface.

interface IDuck {
void Quack();
}

Now let's examine Daffy

class Daffy {
void Quack() {
Console.WriteLine("Thatsssss dispicable!!!!");
}
}

Daffy is not actually an IDuck in this case. Yet it acts just like a Duck. Why make Daffy implement IDuck when it's quite obvious that Daffy is in fact a duck.

This is where Duck typing comes in. It allows a type safe conversion between any type that has all of the behaviors of a IDuck and an IDuck reference.

IDuck d = new Daffy();
d.Quack();

The Quack method can now be called on "d" with complete type safety. There is no chance of a runtime type error in this assignment or method call.

Design by Contract library (interface) thoughts?

If you are looking for a generic solution to this I would recommend the Java Modelling Language. All of the pre/post-conditions (@requires/@ensures) can be specified in the annotations above the method you wish to check. It's my understanding that the JML compiler (jmlc) inserts runtime assertions into the bytecode.

I believe ESC/Java2 has a similar type of functionallity but I've never used it before.

Ruby class types and case statements

You must use:

case item
when MyClass
...

I had the same problem:
How to catch Errno::ECONNRESET class in "case when"?

What are some advantages of duck-typing vs. static typing?

Next, which is better: EMACS or vi? This is one of the running religious wars.

Think of it this way: any program that is correct, will be correct if the language is statically typed. What static typing does is let the compiler have enough information to detect type mismatches at compile time instead of run time. This can be an annoyance if your doing incremental sorts of programming, although (I maintain) if you're thinking clearly about your program it doesn't much matter; on the other hand, if you're building a really big program, like an operating system or a telephone switch, with dozens or hundreds or thousands of people working on it, or with really high reliability requirements, then having he compiler be able to detect a large class of problems for you without needing a test case to exercise just the right code path.

It's not as if dynamic typing is a new and different thing: C, for example, is effectively dynamically typed, since I can always cast a foo* to a bar*. It just means it's then my responsibility as a C programmer never to use code that is appropriate on a bar* when the address is really pointing to a foo*. But as a result of the issues with large programs, C grew tools like lint(1), strengthened its type system with typedef and eventually developed a strongly typed variant in C++. (And, of course, C++ in turn developed ways around the strong typing, with all the varieties of casts and generics/templates and with RTTI.

One other thing, though --- don't confuse "agile programming" with "dynamic languages". Agile programming is about the way people work together in a project: can the project adapt to changing requirements to meet the customers' needs while maintaining a humane environment for the programmers? It can be done with dynamically typed languages, and often is, because they can be more productive (eg, Ruby, Smalltalk), but it can be done, has been done successfully, in C and even assembler. In fact, Rally Development even uses agile methods (SCRUM in particular) to do marketing and documentation.



Related Topics



Leave a reply



Submit