14 ms·
The slow march of progress in programming language tooling
- mamcx 4y agoAnother hint on all this, is that the most "loved" languages and special here, Rust, Go, Zig, ... are HOLISTIC. C, C++, JS are badly designed languages and that is something that will never, ever, for all eternity ( :) ), allows to make great tooling. "Badly designed" here is related, but not the same, to "bad languages". All this tooling is a circle that start from the syntax, paradigms, tastes and feedbacks that reinforce the whole thing. A good example is Rust clipply. Is amazing how great is (past week it help me turn a mess of logic with 2-3 steps of refactoring that turn like 10/15 lines of code on 5!). But you CAN'T have that good without a) GOOD design or b) TOO MUCH effort. For a great linter, Rust design has: - Cargo and sub-commands, so `cargo clippy` - A formatter, so it exist some guidance in how "good code" *look like (try guessing a lint that show a compressed line of code: Not helpful!) - A idea of what are "idiomatic looking apis" - That is based in traits and some enforced idioms - That is based in the Rust type-system and checks (so it knows when you are cloning a copy value) - That is based in a explicit syntax - That is based in extensive annotations of code - That has a GREAT error reporting machinery - That DEMAND a sophisticate parser that is resilient to errors and has full access to the source code - That run alongside the whole chain so you can start again in each cycle. And more importantly: - That is made by the same guys that made Rust, not somewhere else guessing what to do with that! Too much things to align, and that show how a "well designed" language is a holistic endeavor.
- adamgordonbell 4y agoAuthor here. This was fun to write. I think there are counter-examples, but this was my main idea: When a new developer tooling innovation is discovered, newer programming languages get a chance to bake that innovation into their language tooling. Doing so gives them an incremental advantage, and these increments add up over time to a better developer experience. So newer languages have one clear, well thought out way to do something, and older languages will have either many contradictory ways, or no ways at all, to do the same thing. And this makes older languages feel old.
- verdverm 4y agoI'm surprised you didn't talk about Go's novel dep management system. They have put as much thought into that design as the stdlib https://verdverm.com/go-mods/ https://verdverm.com/go-mods/ https://go.dev/ref/mod https://go.dev/ref/mod
- adamgordonbell 4y agoI'm not an advanced user of either but both go.mod and cargo.toml seem like great examples of well thought out approaches to a problem, where they've learned from previous languages and came up with a pretty polished solution.
- verdverm 4y agoIt's not the file format that's important. For one, it's the algorithm used to select the right version of a transient dependency. Go uses MVS which is a polynomial time algo, rather than requiring SAT solver (NP-complete). Go does not allow dependency versions to be specified as ranges. Second, it's all the other checks and infra behind the scenes. A serious amount of thought went into the design of a dependency system that is far more resistant to software supply chain attacks.
- civilized 4y agoGreat post. Now, why can't someone just come up with a great tooling system for a "dreaded" language, put it out there, and everyone start using that when they see it's better? Doesn't the answer just go back to the Green and Brown Language split? People who use these languages mostly work on legacy projects where they don't get to decide the tooling used. Because otherwise why would they use that language with all the trendy new options available?
- adamgordonbell 4y agoThanks for reading. Yeah true, legacy code must be a factor. If most people in C++ are working in legacy code bases that don't leverage many thrid-party packages then I guess there is little desire to standardize on a third-party package manager. Another issue is more social. C++ has lots of package managers which is almost worse than declaring Conan the standard. Communities standards are hard to retro fit I guess? (Not to pick on C++ by the way. Every popular language eventually sees itself competing with newer incumbents. It's like the innovators dilemma for PL. )
- tialaramex 4y agoTwo things this doesn't mention about Rust that I think we can expect to see in new languages: 1. Version control. If you ask Cargo to make you a new Rust project, and you have git (which, if you're a software developer you almost certainly do) it makes you a Git repository for the new project, with its target directory ignored. As with formatting you might have very strong opinions about revision control, or you might be subject to a company policy, maybe you must use Bob's Special Version Control Program for all Company Projects. Cargo won't stop you doing that, but if you don't have an opinion you get git which is definitely better than nothing. And if you want to, somebody can teach Cargo about Bob's SVCP and make 'svcp' one of the possible choices in the config for the few people who do care. 2. Hello World. If you ask Cargo for a new Application, the project it gives you prints "Hello, World!" because why not. Rust's boilerplate for such an application isn't very heavy, but like a blank piece of paper is intimidating when writing an essay or novel, it's nice to have something to start from. Step #1 remove the part where it prints "Hello, World!". Step #2 write my actual program. Hey, we're off to a great start already. This also means you have a correct, valid program to check your tooling. A new Cargo Application is a Hello, World program that will compile, and run, showing that your tools work as intended before you write a single line of Rust. It doesn't have any tests, nor any documentation, but since it's a working program the test infrastructure and doc builder work, the results will just be not very exciting.
- usrnm 4y agoAny half-decent IDE created in this century gives you both these features and much more. I remember selecting the type of the new project in Visual Studio 6.0 and getting either a console "Hello, world" or a full-blown GUI application. VS 6.0 is literally older than some engineers I work with today
- HexDecOctBin 4y agoToo many people believe in the superiority of Linux as an OS for software development that they would consider it beneath them to even notice Windows toolchains, and would then be flabbergasted by the idea of project templates.
- armchairhacker 4y agoTooling is extremely important. However there’s one thing I think is worth mentioning: Java tooling (IntelliJ and Lombok) is incredible. Yet Java is still on the most dreaded list. Why is that? Honestly I don’t know, and I actually think Java is a good language exclusively because of its tooling. That being said, current tooling doesn’t fix all of Java’s flaws. - Gradle and maven are reliable like npm and cargo, but super verbose and confusing - Standard library has some issues and quirks. Like URL#equals sends a network request, apparently that will never be changed. Some other packages (log4j, JAX) are similarly bloated - The “billion dollar mistake” untyped null. People tried to fix this with @NonNull annotations but it’s not far enough. - Java is in a lot of legacy software, which often cannot use Lombok and requires Java 8 or even Java 7. - I just have to say, IntelliJ and Lombok really do fix Java’s verbosity. Both reading and writing. Indeed, tooling is the new syntax. But maybe some disagree.
- ModernMech 4y agoBecause Java is taught to kids as their first language in high school and college. It’s associated with homework, exams, and boring corporate jobs.
- celdon25 4y agoNo. Edit: apparently some people think I am disagreeing with the statement in and of itself. Yes, Java is a homework language, but it’s real problems are far worse than that. Worst of all is the generation of developers that it produced.
- ModernMech 4y ago> Worst of all is the generation of developers that it produced. Care to expand on that? Interested to hear more of what kind of developer you're thinking of.
- kabdib 4y agoJava was my first introduction to full bull-goose, consultant-class enterprise architecture, where I think that salaries and hourly rates are proportional to the number of cascaded factory classes your solution requires. At least four or five, or you're bush leagues. Wait, am I sounding shocked, wounded and bitter again? "This thing is so enterprise-y that the documentation alone can send email."
- mikewarot 4y agoThe article states that Rust Docs are the best form of documentation, "state of the art" I'm all for good documentation, but why embed it in the source code? Why not have good documentation files that stand alone? Doing it that way repeats the mistake of HTML. Annotation should be separate from content, not made into a sausage with it.
- gfody 4y agoI'm not sure if rust does this but C#'s embedded docs are integrated throughout the toolchain so they appear alongside intellisense as your writing or navigating etc. Keeping them with the code makes sense to me because they have the same reasons to change.
- notriddle 4y agohttps://rust-analyzer.github.io/manual.html#hover https://rust-analyzer.github.io/manual.html#hover
- ithkuil 4y agoIn rustdoc you actually can include arbitrary markdown files, unlike godoc.
- formerly_proven 4y agorustdoc may be good for reference documentation (as a Rust noob, I don't really think it is, most docs are pretty messy and the UX isn't very good, it's often better/easier to read the docs in-situ in the code), but it seems to lack any and all facilities for non-refence docs, which most Rust projects basically don't have at all, some put in the top-level module docs (which usually limits the size) and a few have completely separated docs for anything non-reference. (Or one of the creative hacks to get around it, like creating empty public modules or useless macros to have additional pages). In these areas rustdoc is a significant regression compared to say, Sphinx. The upside of rustdoc is no settings, no setup, no friction. Which also means that the deficiencies as far as the reference functionality is concerned can actually be fixed.
- jaredcwhite 4y agoThe counter argument to this is that developers requiring more and more tooling surrounding what is arguably just a text file with some code in it can cause friction, yak shaving, and cognitive load over time. Listen, there's nothing wrong with IDEs, linters, formatters, test frameworks, advanced dependency management across multiple projects & repos, yada yada yada. But there's also something to be said for being able to open up a blank file in a blank folder, writing some lines of code, and running a command to execute said code. That's it. That's the stack. Programmers are constantly tempted throughout the ages to overcomplicate and overburden language ecosystems and stacks such that a newbie coming in has to learn an inordinate amount of knowledge about everything surrounding the language before they can even learn the language itself. I guess what I'm trying to say is I'll always push back against this idea of "progress" == more complexity. Tools, frameworks, languages, and ecosystem evolve over time. Best practices change and adapt. That's to be expected. Is it progress though? Is it actually better? I remain entirely skeptical.
- deleted 4y ago[deleted]
- jjoonathan 4y agoYeah, it's definitely possible to make tooling "investments" that never amortize, but I've also seen an awful lot of programmer-minutes become programmer-days when tooling degraded to the point of printf/run/printf/run/printf/run/bisect/repeat.
- pixelrevision 4y agoGo strikes a really good balance here.
- jamincan 4y agoMore opinionated solutions such as gofmt/rustfmt/black seem to be popular in part because they remove some of that cognitive load.
- returningfory2 4y agoI don't think this is a counter argument at all? If anything, it's reinforcing the argument in the article. > But there's also something to be said for being able to open up a blank file in a blank folder, writing some lines of code, and running a command to execute said code. E.g., in Go the tooling is so good that you can just create a file and run it using `go run .`. This is sort of the point the author is making? No need to worry about build systems, dependencies, etc.
- nsm 4y agoThis is a good article. It covers a bunch of "ecosystem" stuff. At the same time I'd generally encourage a lot of developers using plain editors and modern, but not widely used languages, to give IDEs and common languages a try. That addresses the "iteration" experience. Modern IDEs for java, C++, C# area huge step up from whatever cobbled together setup one is likely using in neovim (saying as something who mainly used vim till about 2 years ago). VCS integration, build integration, debugging facilities, refactoring, linting etc. are just amazing. Jetbrains IdeaVIM is also really good at getting a fast editing experience. At this point, as soon as I'm beyond a small script, it is worth it to open the project in an IDE. We still aren't at the smalltalk or lisp machine level in certain aspects, but that is more a limitation of our larger computing platforms.
- tialaramex 4y agoI use an IDE for my day job (because when in Rome...) and I use Vim the rest of the time. There genuinely are things to like about the IDE. But, they're fewer and further between than I'd anticipated. For example the debugger is more intuitive to work with. If I have no idea what's actually wrong, so that I'd be resorting to just poking around hoping I see something weird to investigate, this makes the IDE a better choice. I expected several things to be nicer, or to be roughly the same but perhaps with a cute GUI that I'd ignore - but they were generally worse. Test infrastructure is worse: Just tell me what failed and how. Don't waste my time making some sort of chart, I'm not trying to impress some middle manager I have work to do. Revision control is worse: the IDE forgets which files are modified! Sometimes restarting it helps. Buggy software is annoying all the time, but buggy development software is awful. Now, maybe JetBrains is amazing, I haven't used it. But I have used a famous IDE that got mentioned elsewhere in this HN discussion and it was... not good. Not so terrible that I told my boss I can't put up with it. But definitely not better than Vim.
- deleted 4y ago[deleted]
- spc476 4y agoA few years ago I did just that. C (a very common langauge) and a popular IDE (either Eclipse or IntelliJ, I don't recall which one). I loaded up a simple two-file C project into the IDE and it promptly crashed. I think I'll stick with my text editor I've been using for 30 years. I've never had a problem with editing any language.
- skybrian 4y agoOne reason that progress is slow is that new language that comes along often have to start over. The article points out how some new languages have benefited from this, but it also means that getting to parity with the best of existing mainstream languages is quite difficult. An exception is languages that piggyback on an existing ecosystem (for example, Kotlin on Java's ecosystem). But they're not advancing the tooling state of the art.
- MBCook 4y agoThere’s something I’ve never quite understood and I wondered if someone who knows this history might be able to explain it. I’m used to Java and Maven. My package manager (mvn) downloads 3rd party packages into my local repo, and all my Java projects have access to it. So I only have to download a specific version of a specific package once. Node and NPM came along, and I think were written by a former Java developer. But NPM puts a full (unzipped!) copy of every package in each of my projects. This leads to pointless duplication of files, and in Windows is slow as dirt due to how NTFS works. Yarn’s PNP mode sort of solves this, and it seems like recent versions of NPM may be changing things. I’m not sure. But why did it start that way? Does anyone know?
- webkike 4y agoThe reason is that JavaScript is not compiled and needs the dependency’s source files to run, and those files need to be there when packaged.
- wging 4y agoThat's not an obstacle to a central cache - you can solve that with symlinks. A build tool should make node_modules/foo a symlink to ~/.npm/cache/foo-1.23 if foo 1.23 is what you need. A packaging tool should be able to follow symlinks easily.
- MBCook 4y agoRight. And Node/Webpack/whatever could easily be taught to read inside zip files instead of needing things unpacked on disk. That’s actually already been done for Yarn PNP support in Webpack.
- jonahbenton 4y agoThe reason for a centralized local cache in Java is just because Java and jar files date back to the mid 1990s. Maven to the early 2000s. Storage was expensive. I wrote my first Java programs on a machine that had 16mb of RAM and a couple hundred mb of disk space. Centralized caches of compiled code present all sorts of logistical issues when it comes to deployment. Java has suffered through several generations of uberjar-like designs. Python, also dating to the 90s, as a source based language tried to solve for both local and centralized trees and the result is a horrendous soup. In contrast, PHP- yet another 1990s language- had a model of just dumping files into the directory and serving them, which was comparatively simple and uniform. Node, invented in the late 2000s by a C++ and Ruby programmer, was intended to simplify all sorts of aspects of writing webservers, leveraging in particular the deployment model of PHP (all needed files in source code in the local file tree) with the superior runtime performance and scalability, including support for async, of the Javascript V8 runtime, and with the benefit of having the same language both client and server side, something that was first tried with both Java and Javascript in the late 1990s but for various reasons failed. The other major envisioned benefit to Node was that it was its own webserver, and this has led to many other innovations. That Windows still after 25 years of the NT architecture has a file system that doesn't scale is not something most tooling in the web ecosystem doesn't concern itself with. Node, like PHP, was linux first and foremost. HTH.
- waynesonfire 4y agoI'm really wishing that the innovation that language server brought to the editor ecosystem can be expanded to other dev tools. I'd love for dependancy management and build systems to be a solved problem and not reinvented by every new programming language that has gained enough popularity that some volunteer decides to build these basic dev tools. Imagine learning one tool and using it for every language. They all solve the same problem. What's the common interface?
- doliveira 4y agoNix sounds like it could be such a tool. But it seems to also suffer from Linux's wizard syndrome
- Kaze404 4y agoI agree with this. With Nix I can finally stop using nightmarish tools like nvm and rvm. I have my development tools where I need them: my projects. There's no reason for me to have, say, node or eslint available anywhere else.
- ghoward 4y agoThe common interface is dependencies and dependents, but the problem with existing build systems is that they make assumptions about those two things. They also place other restrictions. For example, the Go build system assumes you set up the project according to the Go standard. Cargo sets things up a certain way too. They also assume certain build tools, like the Go compiler and `rustc`. Restrictions for ease of implementation are the reasons why every build system sucks. Figure out how to remove the restrictions and implement that, and you will have a universal build system. Source: I am building such a build system, so whether I'm right will only become clear over time.
- Too 4y agoOne difficulty is that dependency resolution need to be language-aware, to understand the semantics of #include, import, require, CLASSPATH, compiler -i flags etc etc. Best would be if compiler could export this in a standard format for consumption by a build system. Like the language server. Looking at build tools that try to be cross language, you have Bazel probably being the most serious contender, which often requires you to vendor your dependencies and rewrite the build files entirely in a different mindset than how upstream packaged it.
- transfire 4y agoThey are dreaded because people have jobs using it.
- lumb63 4y agoIt’s interesting to me the emphasis placed on tooling. The tooling in Rust’s ecosystem, while good, is far from my favorite part. I very much enjoy how expressive and ergonomic the language is. Coming from primarily C and C++, it was eye opening to me to see all the things I never knew I was missing out on (borrow checking, const by default, ? operator, monadic types, the list goes on…)
- phlogisticfugu 4y agothe old language that's a bit of a counter example to this is php. folks came out with a package manager in composer that was just so much better that everyone jumped to it. and then the IDE's finally got modern features, and then the runtime got much faster in php 7. It's just by the time all this happened, "PHP sucks" had become"common knowledge" and it really fell off the popularity ladder. but not for lack of tooling. C++ has also made a lot of strides in developer productivity, it just still has a bad rep.
- Shish2k 4y agoDoes PHP have a debugger which doesn’t totally cripple performance just by being installed yet?
- tored 4y agoxdebug 3 has been released with great performance improvements. https://php.watch/articles/xdebug2-vs-3-benchmark https://php.watch/articles/xdebug2-vs-3-benchmark And you actually can have xdebug installed without performance degradation if it is not automatically enabled on every request (think that was true for xdebug 2 as well). What you do is to send a special request payload to enable it when needed, can be done with a browser extension. There is also phpdbg, shipped with php, it does not suffer from the same performance penalties that xdebug prior to version 3 had (not sure how it compares to xdebug 3). However it is a command line debugger only, it does not support remote debugging or IDE integration. https://youtrack.jetbrains.com/issue/WI-21414 https://youtrack.jetbrains.com/issue/WI-21414
- oxff 4y agoIt is underrated how hard it was Microsoft with VSCode that made e.g. Language Server a mandatory / must have for any non-joke language.
- hutattedonmyarm 4y agoI actually hate the tooling for Rust. VSCode on Windows sometimes refuses to launch the project or the debugger crashes on launch. IntelliJ Community doesn't do debugging in Rust at all, neither does Sublime Text. Nova for macOS does have a Rust extension, but it also doesn't support debugging. It's pretty good with IntelliJ IDEA Ultimate on Linux though