From: Eivind Eklund Date: 2008-02-02T20:36:57+09:00 Subject: Re: Gedankenexperiment on method duck type safety On Jan 31, 2008 11:25 PM, Tim Connor wrote: > > See code implementing something similar athttp://people.freebsd.org/~eivind/ruby/types/ > > I like your warning in the readme: http://people.freebsd.org/~eivind/ruby/types/README > and I wouldn't be surprised to find that being the case. I was > considering though if a less verbose approach would be more rubyish > and less painful. None of the extra pre-declaration required in the > usual type system, but just how to make method declarations more > explicitly contractual (looking at the contractual aspect more than > the type system aspect). I suspect it is still a case of YAGNI, as I > haven't really needed it yet, too much, but there are just some odd, > harder than they should be bugs I've had to trace. > > Yeah tests and BDD helps a lot, and maybe a convention of always > testing the nil and edge cases for each parameter. But when something > nested goes awry, in a situation you know exactly what the function > wants (even if it's just a responds_to), it might be nice to get a > more immediate failure. Maybe that would interfere with refactoring > and lead to a more Javaesque inflexibility, though. I dunno, to be > honest. Which is why I posted. ;) > > Apparently in your experience it just led to additional pain with > little benefit? Yes, though this may be due to me not having learned when to apply this and not - I've only tested it out for fairly small projects. Probably the core problem in how I used it was that I added checks "all over the place". This got in the way of refactoring; in quite a bit of code, things are passed through that are used elsewhere, and when I added more checks for this, it was no longer trivial to change the type of the pass-through parameter. For instance, I was working on a firewall maintenance application, and at some point I wanted to change from an IP address to a rule number (or vice versa, I don't remember) as an identifier for what to manipulate. Without checks, it was a three line change - change at the original originator of the ID, change at the two consumers. With type checks, I ended up needing to modify things all over the place. The mistake, of course, was that I'd been using more concrete types than I should at the point where I declared the checks - but - this is a thinking shortcut that I think we all do at times. I was thinking of that IP address as an IP address, not as an identifier for something that could be identified another way, and it was natural to check for what I was actually dealing with. It is possible that conservative application of the type checking library could be useful. I have, for instance, used it to add checks to a hash to enforce that only Integers were inserted/indexed into it, because I was processing data that both came from a database and from text files, and wanted to make sure that the same kind identifier was used (ie, that I didn't get a string "1234" from the text file and tried to use it as an identifier, checking to find the record 1234). Adding this check to the hash was useful - it was part of debugging process, and meant that I could be sure that the bugs I was seeing at least didn't come from that particular error. Apart from that, I wonder if it might be useful to add checks at the "edges of libraries" - the public APIs that people consume. This would both function as very formal documentation and trap errors in cases where they are more likely to occur. Eivind.