[HN Gopher] The slow march of progress in programming language t... ___________________________________________________________________ The slow march of progress in programming language tooling Author : kiyanwang Score : 72 points Date : 2022-07-17 16:32 UTC (6 hours ago) (HTM) web link (earthly.dev) (TXT) w3m dump (earthly.dev) | nsm wrote: | This 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 wrote: | I 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. | armchairhacker wrote: | Tooling 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. | [deleted] | Banana699 wrote: | >Honestly I don't know | | I do, because I'm a Java hater. Here are the reason I hate it | for | | - Baking the difference between primitives and objects into the | language itself : an ugly mistake with far reaching | consequences, made by a language designed in 1995 while another | designed in 1980 (smalltalk), in 1991 (Python) and 1995 (Ruby) | all didn't fall for it. | | The difference is an irrelevant VM-level optimization detail, | there is no reason to uglify the human-level language with it. | Once the initial mistake has been made, the correct response | was NOT to make the even uglier hack of wrapper classes, but to | make the primitives objects in the newer releases of the | language, this won't break old code, as valid uses of objects | are a superset of valid uses of primitives, except perhaps that | objects need to be allocated explictely with "new", but this | can be a special case for primtives (i.e. "int is a special | kind of object that you don't need to allocate explicitly"). | The compiler can figure out whether it needs to be represented | as objects or as primitives, you can leave hooks and knobs for | people to tell the compiler they need to the primitives to be | represented as primitves, but it shouldn't be mandatory. | | - Baking in choices about object representations : Like the | fact that objects are always passed by reference, or that they | are always allocated on the heap. Why the "always" part ? why | not give developers the choice between pass-by-value and pass- | by-reference like C# does ? why not give developers the choice | to allocate on the stack (and complain as loud as you want when | they want to do something unsafe with it, like escaping from | methods), which, unfortunately, even C# doesn't ? | | Everytime you see something like "foo deepCopy()" that's a | failure of the language, forcing you to explicitely pay | attention to the fact that foo objects need to be copied deeply | everytime they are copied, instead of just once when you define | the object by marking it as a "struct" or whatever word to | signify that object has value semantics, and then deep copy is | just assignment or passing as a parameter. Why make it the | default to be inefficient with the heap when it's very easy to | give developers the choice to be efficient in situations where | it's always safe ? | | - No operator overloading : I get the hate, it's a powerful | tool. But it's misguided to ban it, operators should not be | special, languages like Haskell and Raku go even further and | allow you to define new operators entirely and control their | predence and other things. You don't need to go that far, why | can't objects use the already built-in symbols the language | support ? because it might be confusing ? anything can be | confusing, you can write assembly in any programming language, | and it will be even worse than assembly because of the more | powerful and obscure abstractions. | | - Generics : The overall theme of forcing you to do things its | way seems to a staple with java. Why do I need to use type- | erased generics ? why shouldn't I get the choice to specify | whether I need a new class generated for runtime efficiency or | use the type-erased catch-all for size efficiency? there is no | need to bake VM-level support for this, it can all be done at | compile time (possibly with help of additional metadata files | or special fields in the .class of the generic type). | | - Overall verbosity : Why "extends" and "implements" ? do you | really need to know whether you're inheriting a class or an | interface ? and can't those be lighter symbols like "<" and ":" | perhaps ? why is "private/public/protected" a must in front of | every method and field ? most people align fields and methods | by their visibility, C++'s way is that you declare "public:" | and then everything declared below that is public. In the worst | case you can always recover Java's way by "public : <method> ; | private : <method> ; public : <method>" and so on, but it's | nice to at least have the choice of not repeating yourself. | | Why aren't any constructors generated ? there are at least 2 | very obvious ones : the empty one, and the one that assigns all | the non-defaulted fields (and can take optional arguments to | override the default fields). Why aren't generated getters and | setters available with a small and light request, like C#'s | "get ; set ;" ? Java's design is just full of things like this. | It feels like a weird sort of disrespect for your time, "yeah | you must write those routine 25 lines of code all by yourself, | you have anything better to do?", how about actually writing my | application instead of pleasing your language with weird and | unnecessary incantations ? It's like a modern COBOL. | | - Horrible OOP excesses : Not really the language's fault | (except that it encourages verbosity and loves it) and already | mentioned, but worth mentioning again. | | Overall, I treat java as assembly. I write kotlin in my spare | time, and whenever I'm confused about the semantics of some | construct I make intellij show the bytecode then hit | "decompile" to see a Java rendition of the code, the exact | semantics will be obvious but verbose. A language that took | this literally is Xtend, a high-level augmented java which | transpiles to java and is a strict superset of it, but with | option that the Xtend compiler figures out all the verbosity | for you. Groovy also takes the "Superset and Augment" approach | but doesn't transpile. And off course Kotlin is very good with | it's interoperability, every JVM language is but Kotlin's | mixture of being close to Java semantics (unlike say, Scala or | Clojure) and Intellij excellent support for mixed projects | makes it at least somewhat special. | | I like the JVM and it's cutting edge research and performance, | and these days the Java standard writers seem to show signs of | finally waking up to reality after years of being behind every | mainstream language, and they regularly augment and modernize | the language. But you can't undo 20 years or so of bad design, | not easily and not painlessly. | | >Indeed, tooling is the new syntax. | | Very much agreed, long long gone are the days when a compiler | or an interpeter is the only thing expected out of a language. | But it's not a panacea to treat any bad design, at best it's | just a band-aid for bad designs that makes them barely berable. | The language has to be designed from the start with the | knowledge of "this is going to run in an IDE" baked in to make | full use of the full range of fantastic things an IDE can do. | | [1] https://www.eclipse.org/xtend/ | EdwardDiego wrote: | > why is "private/public/protected" a must in front of every | method and field ? | | You can omit them, and then the member is package private. | rr808 wrote: | Java is great, I think many wrinkles need some active | deprecation. Its interesting that the blog likes the extensive | standard libraries, but Java is littered with old APIs and | language features that aren't used or liked any more. Newer | languages avoid having these old warts, its only matter of time | though. | adamgordonbell wrote: | > Newer languages avoid having these old warts, its only | matter of time though. | | That is sort of the summary of the post. | twic wrote: | Agreed (although i hate Lombok myself, as being altogether too | much magic; happily, standard Java language improvements now | provide a lot of the comforts that Lombok does). | | But other languages have quirks on a par with Java. JavaScript | is quirkier, and Ruby is basically a DSL for composing quirks. | | I see two areas where Java fell more dynamic competitors. | | Firstly, Java does not have a great story about being able to | open up an editor, write some code, and ship it. Using a simple | text editor is too tiring, and the extremely sophisticated IDEs | take a lot of learning. Java has never been well supported by | the middle ground of Sublime Text-esque programmer's editors. | Meanwhile, the standard tooling (javac and jar) is simple, but | using it to get to production is cumbersome, and the more | sophisticated build tools are not standard, and either verbose | and maddeningly inflexible (Maven), or crammed with arcane | secrets (Gradle). And none of them make starting a new project | as easy as 'rails new' or 'npm create-react-app' (Maven has | archetypes for this, but i don't think they ever got really | popular). | | Secondly, Java does not have a really good framework for being | highly productive at building webapps right out of the gate. By | which i mean Rails. There's absolutely no technical reason you | couldn't build a Rails equivalent in Java. I am astounded that | (AFAIK!) there was not an urgent effort to do a straight port | of Rails to Java once it became clear that Ruby was eating Java | from the bottom up. Meanwhile, Java had Spring, but until | Spring Boot, Spring was nowhere as easy and consistent to use | as Rails; Spring Boot has helped, but by slathering another | layer of even more complexity on top. I have never used | Dropwizard, but maybe that's closer to the Rails spirit. The | more 'sophisticated' frameworks like Play and Vert.x are not | the answer, because they're so tied up with particular overly | clever concepts. | rightbyte wrote: | > There's absolutely no technical reason you couldn't build a | Rails equivalent in Java. | | Groovy with Grails? Never tried Grails so dunno of it was | mature enought. | the_only_law wrote: | What ever happened to those, I remember years ago Grails | was pretty popular, and groovy was one of the premier | alternative JVM languages. | | Then it felt like it just disappeared after some years, no | one mentioned groovy or Grails anymore. | ModernMech wrote: | Because Java is taught to kids as their first language in high | school and college. It's associated with homework, exams, and | boring corporate jobs. | Nuzzerino wrote: | No. | | 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. | kabdib wrote: | Java 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. " | SNosTrAnDbLe wrote: | I would argue that any language that you use for | enterprise-y program will always result in similar code | bases. These always a lot of standards to satisfy and | eventually this results in people coming up with leaky | abstractions for incorporating those policies. All business | logic cannot be nicely boxed into clean code as much as we | would like to. | adamgordonbell wrote: | Author 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. | Gunax wrote: | It makes me think there isn't any reason old languages cannot | adopt these. | | Or even, come up with a new, batteries included version. | | Eg. keep the Java syntax, but add one standard package manager | (instead of ant, mvn, gradle), one standard test framework, | standard formatter, etc. Call it 'Java++' or whatever. | civilized wrote: | Great 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 wrote: | Thanks 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. ) | lesam wrote: | I've worked in C++ and picked my own tools. The tooling | experience in Go is much more polished for a few reasons. | | First, as the author states, it's hard to get consensus on a | tool if it wasn't baked in from the beginning. I don't think | there will ever be a dependency manager or especially an | option-free formatter for C++ with the same adoption as gofmt | or go modules. | | Second, it helps a lot to have the compiler/runtime authors | think about the tooling. Go runtime developers think about | pprof. GCC developers don't think about the UX of valgrind. | C++ standard authors don't write PR's for code formatting | tools when they change the language spec. | ModernMech wrote: | > I don't think there will ever be a dependency manager | | I know a C++ guy who insists that C++ already has a | dependency manager -- he says it's called Docker. Not sure | I agree, but that's the kind of attitude that seems to grow | when a void exists; people get by with "good enough hack | for my use case in a pinch", and then over time that turns | into "this is the way it's done". | saghm wrote: | > 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? | | I think the first two steps sometimes happen, but the last | one is where things get stuck. Often times a better | experience means incompatibility with the previous solutions, | so adoption happens slowly if at all. Then eventually yet | another incompatible solution comes out, and things fragment. | cercatrova wrote: | That's basically what the Laravel stack does for PHP. It's | great, very ergonomic, I'd use it all the time if not for | having to write PHP which I don't wish to do anymore. | twic wrote: | I'm trying to think of examples of trying this for C or C++. | | * Batteries-Included Standard Library - can't actually be a | standard library, but could be the next best thing, a widely- | used library; things like NSPR and APR for C, or Boost for | C++ | | * Third-Party Package Repositories - Conan, which seems to be | healthy, but hasn't taken over the world | | * Documentation - Doxygen, which has been very successful | | * Write Once, Run Most Places - little progress towards this | for C, but the people in the C++ standards process do at | least think about portability; i think there is an inherent | tension between portability and being close to the metal | which means it is always going to be a lower priority for C | or C++ | | * Package Managers - see under 'Third-Party Package | Repositories'; not clear to me to what extent this is a | different thing | | * Code Formatters - these have long existed, i suspect clang- | format is most popular, but it is far from universal; what's | missing is a universally-accepted strict formatting standard, | as found in Go and Rust, and arguably now Python | | So, it seems that these things do get retrofitted, and do get | adopted, but not to the same extent as if they were there | from the beginning of the language. | chakkepolja wrote: | CMake, sanitizers and more static analysis tooling has seen | good adoption. Yeah progress has been slower than new | languages but improving. | verdverm wrote: | I'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://go.dev/ref/mod | adamgordonbell wrote: | I'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. | jaredcwhite wrote: | The 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. | pixelrevision wrote: | Go strikes a really good balance here. | [deleted] | jjoonathan wrote: | Yeah, 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. | jamincan wrote: | More opinionated solutions such as gofmt/rustfmt/black seem to | be popular in part because they remove some of that cognitive | load. | mikewarot wrote: | The 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. | nsm wrote: | As an example of documentation at the same or better standard, | also look at Racket. I'd say the python ecosystem is also | really getting better at this in the past few years. | burntsushi wrote: | Well, rustdoc lets you include arbitrary Markdown files. So | that case is not eschewed. | | With that said, they serve two different use cases. So as | someone who has probably written more lines of docs than I have | code in Rust, it doesn't make sense to me to ask for one and | not the other. | | API docs with a bit of high level prose and some examples are | very likely good enough for small focused libraries. | | For bigger libraries or projects, you are absolutely free to | write prose that is disconnected from the API. You can do that | in rustdoc or use some other tool (mdbook is very popular). | | But either way, you pretty much always want at least some API | docs. | | > Doing it that way repeats the mistake of HTML. Annotation | should be separate from content, not made into a sausage with | it. | | This doesn't make any sense to me. The API of a library is both | the signatures of items exported by the library _and_ the | documentation on those items. The docs might make certain | guarantees about behavior, error /panic conditions and more. | Those can't be described by the type system, and thus, the | items and the docs are intricately connected. Both are required | to define a library's API. | tialaramex wrote: | One crucial thing about Rust's documentation is that your | _examples_ are run by the test infrastructure. | | This makes logical sense. If the programmer provided an example | of how to call some_function() then we should test that example | works. If it doesn't work their example was wrong, or | some_function() is broken, either way the programmer needs to | fix that. | | For the test infrastructure to run your examples, they must be | code, not some sort of annotation. | | The result is now you don't ship documentation which oops, is | documenting the _old_ some_function which had different | behaviour and so _of course_ that example doesn 't work any | more. Sorry, we didn't rewrite the docs yet, just go read this | Discord thread and the six bug tracker entries it links... | ithkuil wrote: | In rustdoc you actually can include arbitrary markdown files, | unlike godoc. | formerly_proven wrote: | rustdoc 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. | gfody wrote: | I'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 wrote: | https://rust-analyzer.github.io/manual.html#hover | tialaramex wrote: | Two 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 wrote: | Any 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 | tialaramex wrote: | > Any half-decent IDE created in this century gives you both | these features and much more | | _If_ you 've paid for the expensive "Professional" Visual | Studio .NET in 2002, you do indeed get version control. But | it's Visual SourceSafe, which is garbage+. Fortunately, it's | optional, so you probably just never switch it on (it's not | default) and don't use any version control at all, so you're | back to square one. | | If you're just using the (cheaper) Microsoft Visual C++.NET | for example - whose users I imagine would have believed they | had an IDE - you don't get Visual SourceSafe. As we saw | that's probably no problem since you don't want VSS anyway, | but it does mean you do not, in fact, get version control out | of the box, you're going to need to pay Microsoft $$$ (or, | try using anybody else's offerings which are better and many | of them are free...) | | Either way, you're not getting that comparable experience. | | + It's _markedly_ worse than CVS, which itself is awful. | Microsoft actually sold VSS for money rather than giving it | away and so there was (until 2005) a team at Microsoft | maintaining it. As I understand it the revision control of | the Visual SourceSafe software itself was eventually... a | Perforce repo (technically "Source Depot" Microsoft's | internal-use licensed fork of Perforce's software). This is | not an endorsement of your confidence in your own product. | HexDecOctBin wrote: | Too 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. | Wohlf wrote: | For all its warts Visual Studio is hands down the best IDE, | the only thing even close is JetBrains. | rightbyte wrote: | In my experience "IDE lockin" is terrible to work with in | the long run. After 5+ years trying to compile old Visual | Studio or Eclipse projects is a horrible experience. | HexDecOctBin wrote: | Sure, I agree, though not anymore horrible than dealing | with Autotools. Shitty developer tooling is a different | question (and a very important one that I trying to | solve), but I am simply talking about being unaware of | the simplest features because of one's ideological | blinders. | AshamedCaptain wrote: | And I have quite the feeling it will be identical to | compiling one of these "package managed" projects whose | dependencies are expressed as Github URLs. | jiggawatts wrote: | Mine is the opposite. Visual Studio makes it a breeze to | pick up some random person's work, often after decades of | time if the projects can be upgraded. | | Even if not... I recently installed Visual Studio 2015 in | a VM to build an old project and it was perfectly fine. | | Can it show smiley emoji in string literals? No, but it | does a lot more for me as a programmer than a text | editor! | davidkunz wrote: | And with `cargo init --lib` you even get a green unit test! ___________________________________________________________________ (page generated 2022-07-17 23:00 UTC)