I agree with you 100% that it would be foolish to "use instances of user-defined classes where built-in types will suffice."

If we disagree, it's because I don't see "where built-in types will suffice" and immediately think "always", as perhaps you do.

This miscommunication is largely my fault. I shouldn't have marked the repository or its corresponding HN post with "Stop passing naked dictionaries around!” I must admit, my marketing impulse got the best of me there. Naked dictionaries with untyped values are obviously one of Python's strengths, and the very option of using them instead of a heavier system is a big part of why dynamic languages are so important, both to me and to the craft as a whole. It would be a more accurate reflection of my perspective if I had rather said "Stop always passing naked dictionaries around, especially in cases where you have to write schema validators for them!"

Statically typed languages are a drag because you've got type checking always, and you don't always need it -- in fact, as any dynamic programmer knows, you almost never need it.[1]

But sometimes you do. It's a fact that data schemas are useful at times. In instances where your data is in fact naturally schema’d,[2] I’ll invoke some PEP 20 dogma of my own: “Explicit is better than implicit.” There are situations in which you could catch a data problem at the time you’re storing it, but with dictionaries you only catch it later, once it’s being used (hopefully your test coverage surfaces it, or it might not even happen until you’ve deployed to production).[3] Recognizing this, you may then write a one-off schema validator for each of these situations, but that puts the onus on every developer to call that validator every time he or she is populating a dictionary of that classification (not very DRY).

In the six months or so since I wrote the first version, I’ve found DStruct to be extremely useful for lots of scenarios, like remote resources (I just wrote a use case here: https://gist.github.com/1398138), mock objects (I just wrote a use case here: https://gist.github.com/36118077f75eaed8c731), future-proofing, backwards-compatibility, and pretty much any time you’re doing outside-in development (e.g. writing a view or serializer first, and having it build up its own mock data objects, to be replaced by model instances once the model layer is complete).

In my heavily content-driven game framework, the game designer imports content via CSV.[4] With DStruct and a handful of code changes (amounting essentially to `return Decoration(input_dict)` or `return LevelMilestone(input_dict)`, instead of just `return input_dict`), we have been able to save enormous human time, because the server now detects schema-related content problems at content import time, rather than having to wait for the full content test suite to run (and hopefully have enough coverage that it can detect a missing or malformed attribute!).

I put it DStruct out there because it simply kept on saving me time, code, and technical risk in a variety of projects. Everyone is free to take it or leave it, but my preference is that they fully understand it before doing so.

-dorkitude

PS: I don't come from Java; I'm a Pythonist born and raised (even way back at IMSA, where I believe we met once or twice ;) I think in terms of metaprogramming, multiple inheritance, dynamic typing, and runtime mutation. I understand the kneejerk "oh god another Java bureaucrat" reaction, because it's a reaction I myself feel when I see certain patterns being hamfistedly jammed into Python code. DStruct is not such an occurrence.

[1] The debate about DStruct is not a debate dynamic vs. static typing in language design (we’re all pythonists here): it's a debate about the degree of the qualifier "almost" in this sentence.

[2] Sometimes you’re mocking something that’s schema’d; sometimes the interface is beyond your control; sometimes you’re retrofitting a class that used to be ORM and now is not; sometimes you’re importing CSV’s; sometimes you’re writing a feed aggregator; the list of naturally schema’d data sources goes on and on.

[3] This is particularly true in Ruby, where they always seem to use Hash-as-argument in an attempt to get the future-proofing power we get for free in Python via keyword args.

[4] And not just store items, settings, and game objects, but even the rules and economic structure! The game framework referenced here is the best work of my career to date. Unfortunately it is a closed source project, but suffice it to say the concepts baked into DStruct (and a handful of other killer libraries I will release in the coming year) had a significant positive effect in terms of code bloat, development time, quality, and risk.