3 ms·
> What I find to be of highest importance is the ability to reason about parts of the application in isolation, and types don't provide much help in that regard
by yawn 8y ago
> What I find to be of highest importance is the ability to reason about parts of the application in isolation, and types don't provide much help in that regard. When you have shared mutable state, it becomes impossible to track it in your head as application size grows. Knowing the types of the data does not reduce the complexity of understanding how different parts of the application affect its overall state.
Ironically, I find having types allows me to reason more about an app in isolation. Pick any function in isolation with a typed language and I know the shape/contents of the data I'm dealing with. I know what these things "are". With something like Clojure and no Spec, I have no idea what I'm dealing with until I find the source of where the original data came from. Having worked on an application that used a Clojure library that read sql from a file and translated the queries into maps, I had to look at the sql file every time to make sure I had the data I thought I did. In my experience, worrying about what could be changing the data is overrated. In a typed language, I know exactly what's changing the data since I can statically guarantee what other parts of the codebase are mutating it. It can definitely become a problem with concurrent code, but that happens so rarely in the codebases I've worked on that isn't really a concern and there are ways to mitigate it when it is.
- yogthos 8y agoI don't find knowing the shape of the data to be problematic in the applications I work on. I find the REPL tends to play a big part for me here. Any time I develop a feature, I run the code to see what it's doing. So, say I'm adding a new feature that needs some data from the database. I'll run the query to get the data and see it, then I'll write a function to transform it in the desired way, run it, see the output, take the next step, and so on. When I'm updating or changing the feature, I do the same thing. I'll get the application in the desired state, find the spot where I want to make the change, run the current code, and work from there. Meanwhile, without immutability the types do little to help with tracking side effects which create implicit coupling. To know whether it's safe to change data, you have to know how it's used in every location it's referenced. This completely precludes the ability to do local reasoning about your code. This is a completely separate problem from concurrency.