News for hackers. Stuff that matters.
Re:Dynamic type systems are not inherently more open by david_draco on Sunday January 19, 2020 @07:50AM (#22091167)
Interesting, I would have said static typing allows more technical debt. Illustrating example: Lets say you pass a double variable from some part of your code through 13 layers of APIs until it is actually looked at and acted upon. Now you realise that you not only need a double, but also a boolean. In dynamic typing, you can make a tuple containing both and only modifying the beginning and end points. In static typing you have to alter/refactor the type everywhere.
Re:Dynamic type systems are not inherently more open by codeflo on Sunday January 19, 2020 @08:00AM (#22091213)
It’s often considered bad practice to pass around raw values for that very reason. Introduce a (minimal) abstraction, that is, give the thing you’re passing through those layers a name. Then you can change the endpoints at will and still get static checking (as a plus, you can‘t accidentally pass the wrong bool, or mix up the tuple order).

I agree with the GP‘s point that static typing forces you to do that kind of design work earlier.

(Edit: You raise a good point, though. I think a lot of people run into this kind of problem with static typing.)

Re:Dynamic type systems are not inherently more open by sethammons on Sunday January 19, 2020 @09:27AM (#22091568)
You'd love Perl. Just pass @_ through your callstack. Want a new value available 20 functions deep that is available at the top? Just toss it in @_ at the top and you are done.

The problem? Every one of your 20 levels of functions/subroutines has an unnamed grab bag of variables. You get to keep that in your head. If you want to know if you have a value in a given branch of code, your best bet, aside from reading the code of the entire callstack, is to dump @_ in a print statement and run the entire program and get it to call the function you are in. Oh, and if one of those values contains a few screens worth of data, you will need to filter that out manually. Even "documentation" in the form of comments or tests will be unreliable due to comment-rot or mocked test assumptions.

Even in Python, I'll often have to go up the callstack to know what a named parameter actually is. And if similar shenanigans are going on, I again have to pull out a debugger or print statements to know what I can do with an argument.

With a static type, I see plain as the text on my screen what type I have as a parameter and I immediately know what I can do with it. As weak as Go's type system is, it is worlds better than Perl and Python for maintaining and creating large, non-trivial codebases. The price is passing it around at the time of writing.

Re:Dynamic type systems are not inherently more open by dmux on Sunday January 19, 2020 @12:37PM (#22092647)
Isn't passing @_ around similar to a concatenative language pushing and popping things off the stack?
Re:Dynamic type systems are not inherently more open by toastal on Sunday January 19, 2020 @07:56AM (#22091194)
And on layer 10 you missed that you were using and treating the argument as if it were the double. Now you have a bug that the type system would have solved. Or you can alias that input early if you know with a good certainty it has possiblity to change, and now you just update the alias and everything gets checked all the way down without a refractor.
Re:Dynamic type systems are not inherently more open by k__ on Sunday January 19, 2020 @08:04AM (#22091225)
AFAIK, the problem here isn't "bad static typing" but "bad type inference"

If you only have to write the type once at the top of the 10 layer, you don't have to do much to change it.

Re:Dynamic type systems are not inherently more open by caseymarquis on Sunday January 19, 2020 @08:41AM (#22091371)
I think at that point you probably need a major refactor, regardless of the language being used. While I don't want to be in that situation, I'll typically use a helper class if I'm forced to pass something through 13 layers (a class containing all the arguments).

However, that's pretty much the textbook example for designing with dependency injection in mind. Static typing won't fix a terrible architecture.

Re:Dynamic type systems are not inherently more open by galangalalgol on Sunday January 19, 2020 @09:42AM (#22091652)
I haven't read that textbook. Do you have a good reference. I may have been intentionally been using an anti pattern. I often have a POD class that gets passed down a processing chain.
Re:Dynamic type systems are not inherently more open by caseymarquis on Sunday January 19, 2020 @03:20PM (#22093754)
YMMV. There's probably at least one good use case for virtually every design. What you're doing could be totally reasonable.

The original description sounded like 13 functions being manually chained together, each inside the last. Where to go from there is very situational.

Using a POC is pretty much a given.

For transformation in the simplest form, I'd typically have a series of extension methods (or some equivalent, like a transformation class which only has methods and holds a reference to the object) which can be called to transform and return the object or return a modified copy of the object. That's easier to test and debug as each method doesn't need to know about the one above/below it (they get called in parallel). You can also easily modify the order of the transformation, or cut out parts of it. When testing/debugging, you just initialize data to some state, then test the broken piece of the pipeline.

If the 13 vertical calls are for initialization, DI allows you to turn that into 0 calls. You probably need reflection in your language to make DI work though. I've never liked DI frameworks built by others, and have generally made my own.

All that said, I'd stand by my point that if 1 item is passed vertically through 13 functions before it gets used, then there's probably some way to either make things a bit more horizontal, or to automate the passing.

Another strong belief: If DI or some other "good" design tool results in more lines of code or significantly more confusing code, then either it's being done wrong, or it isn't applicable to the situation. There are generally more wrong places to use a tool or pattern than there are right places to use them. A power drill is a terrible hammer.

Re:Dynamic type systems are not inherently more open by galangalalgol on Sunday January 19, 2020 @04:51PM (#22094362)
I'm keeping that line. More wrong places... That is koan worthy. What is DI dynamic initialization? I can't imagine passing a const bit of POD through 13 layers without it bein used, but not every layer uses all of it probably.
Re:Dynamic type systems are not inherently more open by caseymarquis on Sunday January 19, 2020 @07:15PM (#22095153)
Dependency injection.

It's basically a fancy way of saying 'Use reflection to read all of the dependencies that exist in my code, and then automatically initialize those dependencies and pass them to the classes which need them.' This (for me) is a recursive process which starts at root "singleton" objects (single per DI session), then moves down through the tree that is my code and its dependencies.

Typically, dependencies are passed via constructor then stored in a field. I personally think that's a dumb way to do it, as I'm using DI to eliminate boilerplate code, and you don't often get code more boilerplate and tedious than copying a variable into a field. I instead mark fields with obvious attributes that show that DI is used for initialization, then have my DI framework automatically fill them in.

People often overuse interfaces with DI, which leads to very difficult to trace code. I consider that an anti-pattern unless writing a library for others. Unfortunately, I think the people doing this have made DI seem like a trade off: you remove boilerplate code, but you lose clarity. You'll see this in virtually every DI tutorial, which is unfortunate. DI can be done just as well with concrete objects.

If you're using a language with reflection, I'd highly recommend learning a DI framework. Once you've figured out what you don't like you can find a framework that works the way you prefer, or in the worst case write your own. You definitely have to structure your code for DI, and it's difficult to add after the fact. That said, I was able to chop 5 to 10k lines off a 100k project I converted last year, and more importantly adding new functionality became much faster and easier. Again YMMV.

Re:Dynamic type systems are not inherently more open by _pmf_ on Sunday January 19, 2020 @11:56AM (#22092390)
> Lets say you pass a double variable from some part of your code through 13 layers of APIs until it is actually looked at and acted upon. Now you realise that you not only need a double, but also a boolean. In dynamic typing, you can make a tuple containing both and only modifying the beginning and end points. In static typing you have to alter/refactor the type everywhere.

Adding a double and boolean field to a Context object, I don't have to touch anything at the intermediary API layers. Just as with your tuple/dict.

Re:Dynamic type systems are not inherently more open by sweeneyrod on Sunday January 19, 2020 @10:59AM (#22092063)
You could also only modify the endpoints in a statically typed language with type inference.