The analogy is comparing writing programs to buying goods: | |
writing a program with static types is equivalent to buying | |
with cash, and writing a program with dynamic types is | |
equivalent to buying with credit. | |
The "cost" in either case is mental energy and time. When I | |
write a program with static types I spend a lot of effort up | |
front, guided by the type system and compiler, to handle edge | |
cases and generate a totally correct solution. I have to | |
fully-understand any libraries I'm using and characterize | |
the problem in terms of types. | |
When I write a program with dynamic types, I typically get | |
something I can run much faster, but then I struggle through | |
compose/test/debug cycles until the program is eventually | |
correct. The energy cost here is spread out (potentially | |
over days or weeks) instead of happening earlier. | |
The correct program is the thing I am buying in this analogy, | |
not the currency I'm spending. |
One thing that strikes me as a little odd is the timing: types are first and tests come later? Really? Isn't that just a strawman ... surely nobody really thinks that's an accurate picture? TBH, I don't even think it's a good approximation.
From my completely personal and annecdotal PoV, I do sketching first to rough out a structure and then refine and rework. Types and (some) tests work for me for the initial phase, but I could easily imagine someone with different preferences putting more emphasis on tests up front. But either way this really doesn't feel like the kind of periodization you're you're claiming.
So, I don't know where types and tests came into things, since I was mostly talking about dynamic vs static types.
What I am really talking about is building types/tests into an upfront design, getting things "working" (compiling/passing), then moving on, versus implementing something, seeing it work in an ad-hoc way, moving on, and then returning to fix bugs/refactor/whatever later as needed. Dynamic types are compatible with either strategy, but static types are less amenable to getting something fuzzy working in an ad-hoc way.
I certainly don't spend days in a laboratory slowly building types, so I imagine my workflow is somewhat similar to yours. But I've never built a large project (game, editor, whatever) from start to finish in static types by myself, so usually the static type projects I've work on are smaller and more constrained (building an R-Tree, building a segmented sieve, implementing some algorithms, interval arithmetic, etc).
To be clear, I find a ton of joy in working with static types so that when my program compiles it often works correctly without bugs.
I am just trying to reconcile this with the fact that I haven't yet written any large personal tools comparable to those I built in Python back when that was my go-to language.
Doesn't Spire count?
Well, Spire is an interesting case. I mean, it's a big project, but as a library it's pretty modular. Also, there have been many collaborators (which is something a good type system has made way easier).
I totally agree that I'm ignoring qualitative things like beauty and whatnot, which is definitely a problem. I certainly like some programs more than others!
So, besides time-constrained programming competitions, I guess I have had experiences where I started working on something I knew absolutely nothing about. I've done this with static and dynamic types and I would say that I found the "activation energy" lower with dynamic types. This can apply to a domain I'm totally ignorant of, or a project that's too big to contemplate doing on my own.
For instance, the text editor I wrote (about 10K lines of Python) evolved as I wanted to add features and fix bugs, and didn't have an up-front design. It's possible that the (immense) amount of energy I put into it between 2006 and 2011 would have been much lower with static types, but it's also possible I would never have gotten an initial prototype working well enough to get excited, stick with it, add features, etc. Using it in a day-to-day way was a huge motivation to make it better/faster.
I think I could probably write a better version of this editor in Scala (or Idris or whatever) these days, but I have a good idea of what design will work and why, and what types I'll need. It's possible it would have worked just as well then, but it's also possible I would have struggled and given up (not having enough energy/intelligence/etc for the up-front cost).