Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

``` breaking things up into small isolated components that can be reasoned about independently ``` - This is insufficient for the same reasons unit tests are not enough and you also need integration tests. The moment you cross namespace boundaries, you will end up not setting keys /entries in maps , missing logic etc and end up needing something like Spec/Schema....


Sure, and my team uses Spec at component boundaries to define APIs for that reason. I actually prefer this approach to static typing because it makes it possible to add a specification at the level where it provides the most value, and it's much easier to express semantic constraints using this approach.

It does take more discipline to work with a dynamic language, but once you develop a process then it can be very effective. It's also worth noting that immutable by default plays a huge role here. With Clojure it's natural to create truly isolated components while it takes a lot more discipline in an imperative language where things are passed by reference creating implicit coupling.


> you will end up not setting keys /entries in maps

This is what I run into. But that's not exactly a dynamic language problem. It's more of a data-oriented programming (in the Clojure sense) problem.

I'm coming to the opinion that data-oriented programming techniques only make sense inside a fairly tightly bounded context. One that's small enough that you can see and understand the whole thing at once. As soon as you've got ad-hoc data structures crossing logical boundaries, you lose the ability to keep track of it all, and it becomes very difficult to ensure everyone's interacting with these ad-hoc types in a compatible manner.

Incidentally, this is also exactly why I dislike JSON for APIs. I'd much rather share data across boundaries using data structures with explicit, nominal, static types. Like what you get in gRPC.

Anyway, my Clojure experience is limited, but I think this is why I have an easier time letting Python code get big than I did Clojure. With Python, I've got myself into some problems with data oriented programming, too. But with Python, it was easy (and idiomatic) to walk that back and switch to using dataclasses.


> This is what I run into. But that's not exactly a dynamic language problem. It's more of a data-oriented programming (in the Clojure sense) problem.

Yes, all dynamic languages have this problem. I have transitioned to statically typed languages and it has been very peaceful so far :)


To go at it from another angle: I'm working in a relatively large Java codebase that also likes to pass around generic ad-hoc data-structures such as maps. And I'm having exactly the same problem problems there. Static typing does nothing to help the situation.

I realize that data-oriented programming is more likely to happen in dynamic languages. But correlation is not causation.


IMHO Static typing => structure, not necessarily Map<String, String> (which is also a type). Shaping data is quite important and having an associative array doesn't necessarily means that the data is shaped.


Right. . . but, way up at the start of this, you specifically called out using associative arrays for all your data. And what I'm saying is that, while that's absolutely true, it's also technically an orthogonal question from whether you're working in a dynamic or static language.

Yes, sure, we can say that no true Scotsman would use a static language that way. But I think that's maybe missing the point. If you can dismiss this practice in static languages by just saying, "Well, maybe you shouldn't do that," why not also apply the same dismissal to dynamic languages?

That said, there's a specific subset of dynamic languages that make it more difficult to do your domain modeling any other way. Clojure and JavaScript belong in this group. I'm not sure of other examples. Basically, if the type system has been set up such that everything is either a map or a glorified map, you aren't left with a whole lot of other options. But not every dynamic language does that.

In Python, for example, I always use dataclasses for data. As long as I'm being good about this, I don't actually need to explicitly write unit tests to verify that types are being handled properly. MyPy's got my back. And, even if I'm not using it, unit tests for covering actual behavior will typically blow up with a type error in about the same amount of time that it takes a static language's compiler to detect one.


Humans are weak. The easier it is for them to do the wrong thing, they'll do it.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: