Hacker News new | ask | show | jobs
by spoils19 1230 days ago
I used to be a huge dynamic languages fan, with python being my favorite language over the majority of my career. Then I worked on a large python project of ~100k LOC with a team of ten. That's when I realized that writing code faster isn't the problem. Reading it is, making changes to code someone else wrote is, and refactoring across dozens of modules is a problem. Static languages help a lot with all three. I still love dynamic languages for small tasks, but I'd rather use a static language like Go which still keeps much of the dynamic feel, and helps catch my mistakes at compile time. I actually just set it to watch the project directory for changes and recompile automatically in a terminal on another screen (actually to run the unit tests, which includes compiling.) That's constant feedback and comparable to dynamic languages speed for edit-compile-test runs. But the best part is the unit tests. They run so much faster with Go that I don't get distracted waiting for them to finish, and that keeps me in the zone and much more productive.
2 comments

This is almost always framed in a way that shows large systems need the extra rigidity of some static systems. And that dynamic systems are only about rapid prototyping.

I think that is a bit of a false framing. To wit, any system of 100k LOC will be hard to get into. Even harder to make changes in. There is no getting around that. None. Even worse if you have many entities flying about these 100k LOC. Each change to an entity will be dangerous. Static or dynamic. Especially if they are persisted anywhere, as at that point it is all too easy to get static guarantees that aren't reflecting actual data.

This is a false equivalence.

You need all the help you can get maintaining large codebases and static typing is a huge help.

What did I make an equivalence between? Large codebases are hard, period. That is all I am saying. Having worked on 100k LOC systems in static and in dynamic, I will not claim either has a benefit. That is just hard.

Static analysis is, of course, good. If that is static typing or otherwise. So is running the code making sure it does what you want when running.

What is not a huge help, is a byzantine type hierarchy that nobody understands. Which is all too familiar to me from any codebase I have worked on with folks that dived straight into the type system before they knew what they were doing in the system.

Many strong type proponents have moved to the categories view. If you know the category type of what you are doing, the idea is that that will prevent bugs. But... that hasn't been my experience. Often it just hides what is actually happening behind another layer of jargon. Jargon that is not native to the problem being solved.

"I will not claim either has benefit"

I bet that if you did a survey of developers who have worked on projects of this scale, 90% would disagree with your opinion.

Then do said survey? Find empirical evidence and share it.

My experience, sadly, is the louder a dev on the team is about either dynamic or static typing, the more likely that dev's code is something nobody else in the team wants to work with.

Here is one sample point for your survey.

Static is better than dynamic for large projects, in my experience.

The equivalence you're making is that dynamically-typed large code bases are just as difficult to get into as statically-typed large code bases.
This implies that "difficulty" is a totally ordered set. Which... I find highly unlikely. Things can be very difficult in amazingly unique ways.
Large codebases tend to be harder than smaller ones within one language. But language to language, static typing is such a significant help that it makes a large difference.

I’ve been writing in python for 18 years, and yet I can far more quickly get into a large typescript codebase than a python one of equivalent size.

Amusingly, I hate python.

Static typing is a tool I like. I don't think we have evidence that it is an obvious win. And I've bounced off of several typescript code bases hard. To the point that I currently hate typescript. Despite being impressed with some of its capabilities.

Which is again to say ymmv. Bad code is bad with or without static types.

> any system of 100k LOC will be hard to get into

To get a gut feeling of the system, i.e., to understand the 10000 foot view of a 100k LOC system, is orders of magnitude easier with statically typed languages than dynamic languages.

And that is mostly because those 100k LOC are done by probably dozens of developers and that leads to different styles, approaches, conventions, etc.

A statically typed language would remove a lot of those headaches, because it does force a semblance of structure, that can be easy to reason with.

A language like Python is awesome for a micro-services architecture though.

I call bs in this. To get a 10000 foot view of a codebase, you lean on diagrams and other lies of documentation. Note that I don't mean malicious lies. I mean simplifications and other happy path discussions of how things work.

This is no different from any system. Want to know how your car works? Start with a simplified diagram and gradually add more details.

Cars and other equipment are an amusing case study. What is the strongly typed version of a car schematics? Why does it look so different from what we think the idealized software should look like?

Anecdotal but — I've worked on many-million-LOC codebases in Ruby with large teams (pre-Sorbet and other type checkers, at Airbnb), and many-million-LOC codebases in typechecker-checked Python with large teams (Instagram). The typechecker-checked Python was way easier to reason about and refactor.
Dynamic languages large code based are, in my 14yo experience, much much harder. Today no one a serious project with javascritpt, AFAIK everybody use typescript. Why?
JavaScript is a badly designed language. It was created on the fly over several decades by browser makers. People prefer to code in absolutely anything else.

WASM will probably kill TypeScript shortly.

Actually it was written (so it was done) in roughly two weeks and then released. The rest is part of modern history in terms of distribution of software and backward compatibility/portability.

The two other languages you mention, TypeScript and WASM, are more part of the same platform mutually benefiting from the progress than competing each other.

Actual JS is based on original one, but have been much improved. Still the lack of static typing is a liability fixed by typescript.
A ~100k LOC project in a statically typed system with type hierarchies, interfaces, contracts and boiler plate will boil down to ~10k LOC in a dynamically typed language like Python. A 10k LOC project will be more readable than a 100k LOC project.

Source: I have spent years coding in C++/Java, then Python. I have migrated Java projects into Python

10x seems extreme. ESR went from 14k lines in Python to 21k in Go. http://www.catb.org/~esr/reposurgeon/GoNotes.html
I didn't mean to exaggerate. I think part of the improvement was the luxury of refactoring which should generally reduce the bloat. And, as someone else said, part of the issue is C++/Java, not static typing. When I move from Java to Python, I also get the luxury of organizing code into fewer/meaningful source files. I find this more readable, than having to switch to different files constantly.

I have not had a chance to learn or use a language like Go. But production use of Python, including building large code bases is real. We do resort to numba, cython or using Python API to compiled code.

I'm now involved in converting large codebases from SAS to Python. I don't think I will have the luxury of choosing another language like Go, for a number of reasons.

It's funny, both Java and Python emerged in the 1990s, yet Java feels incredibly crusty and awkward in 2023. I wouldn't choose Java as a fair representative of statically typed languages in 2023, but Python still feels like a reasonable choice for a non-Lisp dynamic language.
I'm wondering how many of the extra lines are those containing only closing bracket
You probably were replacing LoC with libraries or syntactic sugar, you can do the same with java. As a senior I can write same functionality than juniors with half LoC. In my experience Python is totally unusable when dealing with poorly documented 3rd party libs.
Your problem is C++/Java, not static typing. Static typing does not add many extra lines of code. In most cases, it adds no extra lines of code, as declaring variable/param types is done inline.

Heck, just look at static typing in Python.

Static typing is not only about declaring your arguments and variables as simple types (int, float, array of ints etc).

It means having a distinct type for any complex structure you pass around (think pre-normalization API params, post-normalization API params, slightly enriched post-processing data as separate type vs a dict of str to anything in Python), or anything you want to make compatible (think interfaces vs duck typing).

So Generics, Traits, Abstract subclasses, etc... don't exist in static typing?

As soon as the types get complicated, the code bloat begins.