I'm curious if there are any senior engineers who have swapped from using statically typed languages to dynamically typed languages later in their career and prefer this way of working?<p>I've met many senior engineers (myself included) who have made the opposite transition (dynamic -> static) and now the thought of using a dynamic language for anything outside of small scripts is uncomfortable.
My preferred language (Ruby) happens to be dynamic, but at this point in my career (Staff-level) I've come to believe that the whole static vs. dynamic argument is way overblown.<p>90% of the issues that come up on the teams I've been a part of are caused by developers who are lacking architecture (and related) skills, regardless of the language we're working in. They struggle to find the core metaphors for the problem space they're working in, they struggle to name things, they struggle to find clear and effective refactor points, they struggle to consider the medium and long term implications of their decisions, they struggle to organize code well, etc.<p>(The other 10% of issues are constantly changing business requirements.)<p>Static vs. Dynamic has nothing to do with those problems — they all exist in both worlds.<p>Personally, my most recent stint with a statically typed language (Swift) was hella frustrating. I felt like I was fighting the type system <i>all the time</i>. (Several of my biggest complaints have been address since I moved on from Swift, to be fair). But some people just love it — and good for them!<p>For me, Ruby is the closest language to how my brain works. It has the least friction between Idea and Running Code. I hope to write in Ruby (or similar) for the rest of my life.<p>If I really want a static analyzer for my Ruby, I can try Sorbet. If I desperately need to be running a compiled binary for speed or flexibility, I'll have to choose something else. These are just the tradeoffs.<p>The world is a big place. I'd want everyone to be able to find a niche where you can write the code you want in the language(s) you want.
I'm a polyglot, and I reach for the appropriate tool for the task at hand. I've done basic(s), Perl, python, Ruby, lisp; C, C++, Java. For some tasks, static typing can turn into a huge chore, but my favorite there is C++ because templates provide enough flexibility that you can hand-wave a solution and the compiler will figure it out (or scream). Dynamic typing reduces the character count, and can get a prototype out the door quicker, but in many languages that comes at a cost to performance. I find that I have about the same number of bugs in any language; and I've even had stupid type failures that only crop up at runtime in C++ (sometimes hand-waving at your type system has pitfalls).<p>Watching juniors at work, I find that it takes them less time to complete a task in dynamic languages, but I think they get better results when the language forces them to think a bit harder.<p>I'm in a bit of a minority on gradual typing. Give me static types or none at all. Python's approach to typing gives me the heebie-jeebies.
Not sure if I qualify as senior having been programming for just a little more than a decade but I fall into that category. The first language I learned was Java and it was the first language I wrote for a living as well as C++. Nowadays I mostly work in Python and Clojure (including on sizeable codebases) and I greatly prefer it. I've come to like Lisps more and more the longer I program and a lot of the power they afford you comes from their dynamic features.
I spent a couple of decades with static typing (mostly Java) before spending another 5 years doing nothing but JavaScript. I definitely, I initially like the freedom of dynamic typing and one could argue that as long as you have sufficient tests in place, one is not better than the other. In practice, when working on a team, dynamic typing tends to fall short because it's difficult to enforce the patterns that are needed to actually have a maintainable code base. With dynamic typing different opinions about what patterns should be used in dynamic typing has lead to chaos where each team has to invent their own versions of accepted patterns meaning that each development team becomes an island of their own invention. Human progress relies on organizing many individuals with the same purpose and same way of doing things, which is very difficult to do with dynamic typing.
When you’re charged with making product iteration in your org more efficient (as a senior dev might be), a lot of what you end up doing is lifting certain things from hard-coded to config and DSL driven. Carefully and selectively introducing dynamism to overall statically typed and compiled codebases. These are almost always interpreted by our statically typed codebase though. We would never run a dynamic language runtime by itself in prod.<p>I use Go at work but mostly Python for personal projects currently, and am pushing towards Clojure for personal projects in the future. But that’s because personal programming for me is a cathartic escape from the straitjacket of zero abstraction power and the tedium of manual error handling; I care about my own satisfaction more than I care about scalability to a team of varying skill levels in that context.
I've done so, if I can choose, Clojure is now my language of choice, which is a dynamic language.<p>I'd happily use Elixir as well, another dynamic language, if I had that option and couldn't use Clojure.<p>Only when I can't use those would I go back to Java, Kotlin, Scala, C# or C++ (all which I have prior experience with).
I've found that it's a chore to maintain large-scale software written in dynamic and static languages for different reasons. Large projects written in dynamic languages have turned into insane messes because people with varying levels of ability can not develop with confidence unless the unit test coverage is high and everyone is generally consistent and disciplined in their usage of language features. Sooner or later velocity goes down significantly because the value of the code has increased due to business growth and there is a very high level of anxiety about the ability (or lack thereof) to reason about far-reaching code changes, or even medium-sized code changes.<p>With static languages, on the other hand, writing routine things becomes a chore and people end up needing crutches in the form of advanced IDEs to generate boilerplate code that is a pain to read because of templating and such. Of course, error messages when templating/generics becomes involved are just horrible. Without generics you tend to lose a bit of the benefit of statically typed languages.<p>At the end of the day it's the size of the codebase, team discipline, and an emphasis on simplicity that matters more.<p>It is my experience, though, that people start out enamored of dynamically typed languages because of their expressivity and high productivity but then end up gravitating towards statically typed languages for large codebases, because they are more willing to trade convenience and coolness for safety and reliability the more senior they are.
I started in CPP and now mostly write Python. Honestly, it is just so much easier. Gone are the insane number of helper functions and custom types you have to wade through to make a tiny change.
The reality is that boundary-level checking is all done with validation libraries (like Pydantic) anyway, and invalid types traversing an interface between sections of the codebase, in an unexpected way, happens so infrequently as to be almost a non-issue.
I like regular JS or python over more typed alternatives. Catching bugs in your IDE still means you made them, and there are other ways to catch and resolve them later in the chain. In the meanwhile, I find that strongly typed setups can devolve into verbosity and get in the way of shipping.<p>For context, I usually work in <50 size engineering dpts, if not companies. If you're scaling to thousands you can spare the scale, probably.
I feel more comfortable with statically typed languages, but in the end they're all just different tools for the job. I switched from years of C# and Go (back to) to JavaScript recently. I use TypeScript wherever I can, but it's not always feasible and that's alright. In the end I definitely favor static typing as a personal preference, but don't have any aversion to writing vanilla JS either. It's just different approaches for different things.
I am a 53 years old C# developer by hart. I have been working in .net world since the first beta long time ago. I don't mind writing in dynamic languages. In my case that will be typescript / javascript but I wouldn't want to write dynamic language full time. It is not because of the dynamic nature of the language that I don't want to do it full time. It is the editor support especially when it comes to refactoring. I am so used to the amazing tool that Visual Studio (full, not code) is. Hit F2. Rename something and you can almost with absolute trust that the refactoring changed what needed to be changed in the correct places. I dont have the same level of confident in vs code / type script. Too often one needs to perform a risky search and replace.<p>Then there is the debugging support in Visual Studio Full. Yes, there is debugging in vs code / typescript, but it is far away from how easy it is to debug a C# application in Visual Studio. Too often I have to resort to printf type of debugging to gain insight into which code line was the last line to run before the error.<p>Yes, I like dynamic languages because some of your things you can do with them are freaking awesome, but at the end of the day I like the comfort feeling that Visual Studio and a static language provides.
Different tasks, different languages.<p>I'm happy to use Python for a lot of stuff. I also use C or C++ for a lot of stuff. It's usually pretty obvious what the right choice is.<p>Using a more dynamic language for larger projects takes more discipline, and that effort reduces the productivity that is otherwise the hallmark of dynamic typing. There's a point where static typing becomes a net win.<p>For me, Python's type annotations extend that cross-over point. Both as documentation for humans, and driving IDE or CI-based type checks, I think they've made Python more scalable.<p>If I've been doing heavy C++ work for a while, switching back to Python is like throwing off a whole lot of bureaucratic overhead: it feels like you can turn ideas into running code almost effortlessly. Going from Python to C++ feels like being super defensive and precise: every single thing is nailed down hard, and has to be just 100% lined up. It's satisfying, gratifying, solid, in a way Python code isn't.<p>Different projects, different goals, different timescales. Both can be good.
I just switched over from Haskell to Typescript.<p>I spent a lot of time in Haskell and the type system is great, the issues I ran were the stuff around it: an ecosystem often missing libraries available in other languages, Haskell solutionism, and working on code bases where Haskell language experts were empowered (not necessarily the best software engineers), which caused the company to re-invent a lot of services we could have just bought.<p>I really do think Haskell is the world class typed functional programming language, but I'm also not convinced using typed FP is the panacea some claim it to be. Typed FP doesn't make up for bad architecture or poor dev practices, and it's still 100% possible to code your applications into a mess even with outstanding and talented devs.<p>So right now I like Typescript, JS, the nvim support that took 20 minutes to set up and the incredible amount of libraries and dev tools. I've only been using typescript for a month or two, so maybe my opinion will change...
It depends on the task at hand and what I have to deal with in terms of data inputs (ambiguously typed JSON comes to mind) and size of project. Generally though I lean for statically typed, compiled languages just because the development experience and tooling taking advantage of it feels a lot smoother and ends in a more performant product in terms of execution overhead. I think it's important to write as many tests as you would for something written in a statically typed language as you would to cover for losses incurred by a dynamically typed one, so often (project size dependent) it kinda evens out in terms of effort you need to put into it.<p>What's most important also is making sure that you take away and learn from every language you work in and apply those lessons to other languages as well. Type hints on otherwise dynamic languages are a great middle ground.
The dynamic vs static argument seems to always revolve around bugs. Dynamic typing people say their code is not buggy. I too do a fair amount of javascript and I don’t think my code is particularly buggy either.<p>What static typing offers you though is the ability to refactor large project with much greater ease.<p>I spend most of my time refactoring a large C# codebase (10m+ loc) while other people are actively working on the code as well.<p>This just wouldn’t be possible without some kind of static typing. If there is a type that is used in 500 places and you have to update all uses, static typing gives you some form of insurance that you’re not breaking much.
I'm sure there are such devs, but just yesterday I had a scenario where hours of time would have been saved by just having the "compiler"/build-tool tell me that I'd misspelled a property in some javascript code (in QML in fact, so the property name was defined at the C++ level - perhaps there are IDEs that could have flagged this automatically but mine didn't). That was enough to remind me static typing is virtually always preferable.
Static typing is machine and human readable documentation that is tightly integrated in the development loop. Like all documentation, it requires devs to spend a bit more time upfront create.<p>In large constant systems, code is read more times it is written. Documentation is usually worth the pain.<p>In small, transitory, or experimental systems, documentation may not be worth the additional burden.
I started with dynamic languages, ruby is my favorite, and I use it everywhere where it’s suitable. As I observe, over years static languages getting abit more dynamic or less explicit (as they can), and dynamic languages getting some support for type checking. I guess having both in one language would be a best thing. So when code gets larger or I want to be more confident in some part I can add type validation (it could be a code that run as shared library, or communication between modules)<p>I also think that parameter strong typing and splitting code into service helps to design better, more clear messaging between components. Having done that for some time we can train ourselves to always pay attention to it, and it will help up to build larger code bases in a maintainable way. (I think larger code bases are more efficient from “time spent” point of view)<p>I often see people do same mistake: they trying very hard not to repeat themselves, and the highly reusable functions become very dangerous piece to refactor. I would rather have code copied in different modules, unless it’s very general thing that never change like array sorting or date formatting
Once I was impressed with Java.<p>Then I started Ruby and was carried away by amazing devx even though missed static typing sometimes.<p>Then I discovered Typescript.<p>Typescript has found the perfect balance between flexibility and type checking.<p>Now i feel literally pain when I have to deal with static languages. It’s like im thrown to jail.<p>Not to mention terrible devx of the most of them.
This sort of preloads the term "senior". Nowadays, every new grad gets to put "senior" on their business card, and it means exactly that much.<p>So, probably the question should be for people with, explicitly, 20 years' professional experience, if it is to mean anything.
Me: dynamic -> static<p>What did I feel during the transition: Feel like an insulted because of the under-expressiveness. Everyday I find some ideas that are natural to me and non-tech people couldn't be codified directly.<p>Although statically typed languages are getting better each year, I still think there's a trade-off among three camps:<p>1. Dynamic (Ruby, JavaScript)<p>2. Under-expressive static (Java, C#)<p>3. Expressive static (Scala, TypeScript)<p>I worked on a full-stack project and people have different backgrounds and have to switch from time to time, here's my impression:<p>- Most "underexpressive-static -> dynamic" people hate dynamic programming, because they mostly lose typing for nothing - they usually don't leverage the expressiveness because that is how they were coding all along.<p>- Some "dynamic -> underexpressive-static" people liked the discipline, while some hated the under-expressiveness, it depends.<p>- The "Expressive static" was the new thing. Everybody need to learn some part. Usually, there's a learning curve, some people like the challenge while some people hate it. That also depends on how steep the curve is (TypeScript is very smooth but not Scala).<p>Even though I think it's still trade-off, I can see the balance is shifting toward the "expressive static" camp:<p>- People get more familiar when they're exposed to the concepts. Higher-order functions like map/filter/reduce were considered exotic in the 90s, but now they're everywhere. Monadic-like programming like Promise or Optional is also popularized, they're not hard at all once "everybody else" learned that. Advanced type systems are no different.<p>- Language creators have more experience in choosing trade-offs that makes sense. Scala was getting a bad rap during its day, but Kotlin didn't. In other words, the creators are getting better at spending their "novelty budgets"[0] to yield optimal results.<p>P.S. I still couldn't wrap my head that Dart spent NO "novelty budget" whatsoever... They have zero chance against TypeScript if there was no Flutter or other Google platforms that use Dart.<p>[0] <a href="https://shimweasel.com/2018/08/25/novelty-budgets" rel="nofollow">https://shimweasel.com/2018/08/25/novelty-budgets</a>
I switched from Java to Python and liked it. The downside was mostly navigating existing code bases. But in general, well designed code trumps static/dynamic. Also, when I think back to products I have worked on, I mostly think of what the code did, not so much about what language I used.<p><a href="https://henrikwarne.com/2014/06/22/switching-from-java-to-python-first-impressions/" rel="nofollow">https://henrikwarne.com/2014/06/22/switching-from-java-to-py...</a>
Static and dynamic langs both can be nice to work with IMHO. Not a big difference these days. The thing I really don't like very much, as it does weird unpredictable hard-to-test things, is asynchronous programming. Maybe I'm stupid or not-yet-good at async programming but I'm not the only one. But with JS, seems you're stuck with that.
I have been programming in statically typed languages for 40+ years and have tried quite a few times to use dynamic languages (Ruby,Clojure,JS). However I always switched back. I am currently playing around with Typescript and it might be the best of both worlds because you can use the “any” type when that makes sense and strong types when that makes sense.
I’ve switched around a lot, basically don’t care if static or dynamic, what is important is the discipline of the programmer and the quality of what they produce. Static vs dynamic have trade offs, however not normally the deciding factor when choosing a language for a project.
I switched from Pascal to Python. I believe gradual typing (Python/Typescript/Dart) is the right path forward. Today static typing systems are not helpful for database programming.
There’s no one language that can rules them all. Different languages are suitable for different tasks not only because of the traits of the language itself but also the ecosystem.
Yep! I switched from C# to Ruby in 2018 and haven't looked back. I'm a web developer and the Rails framework is just so much easier to work with than ASP.NET MVC.
you can write absolutely incredible messes in either type of language, especially with statically typed languages that support reflection. i've switched back and forth multiple times. (i'm using golang these days.)<p>i will say that mocking/stubbing is much easier to do with dynamic languages, but this, in theory, forces cleaner integration points in static languages (i.e. accept interfaces, return types)
for some projects I prefer static, for some others dynamic.<p>recently I regretted using C for a big library as I had to tack on dynamic-like features, like huge hash tables for all it's objects and methods, so that I can dispatch dynamically. in a proper dynamic language the project would be 10x smaller and safer.
Most of the cost of systems comes from maintenance. Most maintenance effort is spent reading code and trying to understand it. Types are documentation that speed up reading and comprehending. They're documentation that cannot get out of date because they compiler checks them. Don't think of type signatures as boilerplate or extra verbosity. Think of them as electromagnets waiting to accelerate future you.<p>Professionally, over about 12 years, I have used Java, C++, Golang, Rust, Dart, Python, Perl, and Swift. Since learning Rust, every other type system seems slightly broken. Fixing a red-underline takes a few seconds. Debugging runtime errors takes 10-times as long. And debugging runtime errors in a long CI run can take 100-times as long. Because static types let us catch errors earlier, they speed up writing and changing code.