"If you know what is missing, and you know where it is missing, why not add it back yourself? You useless piece of crap!” -- I only code occasionally, but wouldn't this effectively lower the overall skill in the profession and, also, potentially introduce bugs? Thinking about Bruce Almighty style "yes to all" fixes here.
The typo may not be limited to a semicolon. Introducing one automatically might actually introduce unintended changes (like the huge number of bugs that arise from blockless if statements in C syntax).
I recognise this, and its cousins, from the JS world. It seems to say "how can we possibly innovate without churn!".
But I have been absolutely bowled over, and inspired, by the Rust tooling. Not only helpful error messages, but hints about misunderstandings you might have had, along with concrete suggestions on how to fix it.
I feel like it corresponds to the highly rigorous thought that has gone into the language, which also results in a great language irrespective of the tooling.
> I feel like it corresponds to the highly rigorous thought that has gone into the language
I'd say it's less about rigorous thought, and more about being willing to spend time on purely user-centric things.
You can have both of course, but surely things like proof assistants have a lot of rigorous thought put into them, yet the error reporting is usually horrendous.
And note that the new errors didn't really provide more information (at least initially), instead they formatted the information better, removed redundancies and noise, and called out the relevant bits more clearly. This runs very much opposite of "rigorously" dumping all the stuff you have and letting the user sort it out.
So much so that we have separate technologies to write in Javascript and then build it for Android (PWAs).
The server-client equivalent would be writing one codebase, in one language and building for browser, and server separately. Despite server-client predating Android by decades, that still does not happen.
It's a bit of a rant - but I hate anything that comes with IDE - I face greater cognitive load in undertsanding the IDE than writing logic.
You clearly have more experience with Rust than I do, and maybe you set the bar for 'rigour' higher!
In languages like Python, where you might run into an issue caused by not have implemented an arbitrary method on a callback, or Obj-C where you might have forgotten to implement a delegate, you're on your own as far as the compiler is concerned.
Yesterday my Rust code didn't compile because I was missing a bound on a type parameter on my function that I passed though into the key type of a hashmap. Rust said "hey maybe you want to add this constraint to your declarations".
Some of this you can put down to dynamc vs static. But beyond that, it's clear that the designers and contributors haven't just said "we want to make a language with great safety" but then went on to ask "what specific ergonomic challenges will this bring to users, and how do we help them" .
I don't think you could get those ergonomics from many other languages, even if you wanted, without extra static analysis.
(edit: lazy typing on a phone; in the last para I was referring to the mainstream languages like Python rather than the whole universe of languages.)
> I don't think you could get those ergonomics from many other languages, even if you wanted, without extra static analysis.
You absolutely could. Hell, languages which are much simpler to analyse have worse error reporting, and the language which started the movement of having less shite error message is a fairly simple one: https://elm-lang.org/news/compiler-errors-for-humans
That was a typo on my part -- I meant languages like Python, not the whole universe of languages. Of course anything is possible, I'm sure there are very good languages out there, and that Elm is one of them.
+1 on Golang on this front for rarely creating any confusion on any front, really.
I shudder to think about the next time I have to do npm decency upgrades. Even worse when you have synchronize typescript types. Which requires reading through random GitHub issues to realize that you need to pin a random @types package to 1.20.30 because that’s the one that magically worked for a commenter with 20 thumbs-up reactions.
Hehe I tried to freshen up my frontend coding after 5 years break. Man was I up for a surprise. Reasonml project throwing typescript errors at build time bluh
JavasScript (and PHP for example) is an ecosystem with low barrier to entry and large popularity, combined with rudimentary and bad platform (historic reasons) - it's a recipe for piles of shite.
The amount of signal to noise is low because of low barrier/high user base community spamming NPM packages/and spamming ratings/stars/dependencies - it's hard to determine what's "safe" to use, and because the environment is so barebones you need to depend on a lot of third party code or reimplement everything yourself.
C++/C have a similar legacy burden and barebones platform (although C++ std lib now-days is much better, historically it was unusable which lead to a lot of code duplication) but because the barrier to entry is much higher I'd say an average C++ dev is much more competent than average JS/PHP dev and the libraries commonly used in C++ world are obviously higher quality than JS/PHP (tooling fragmentation is a different story because of the unique problems C/C++ face, but still C++ build tools are probably the most sophisticated out there - out of necessity).
Rust falls in to the category of languages designed by competent people without legacy burden and tackles a complex domain (again higher barrier to entry), most languages I've seen in this category have decent tooling and design (eg. C#, F#, Go, Dart)
Rust has definitely set a new bar for systems programming languages.
Regardless of rust's design in particular, static safety and lifetime management is now non-negotiable, and rust's error messages definitely lead the way although everyone else's are pretty good now.
If D and Rust had a baby I wouldn't anything else.
I definitely agree - this is a problem that is not evenly spread across all programming languages and IDEs. Javascript is easily the worst offender. Java/Android are right up there with it.
Gradle does not do any user research. It never sits down with independent developers, newbies, or seasoned pros. It never tests its error messages. It doesn’t do developer relations. It doesn’t spot bad implementations in the wild and offer helpful suggestion. It doesn’t relentlessly focus on making things easier for users.
Many times I wanted to just ask some library/framework authors that very question, like ‘hey, do you know what real apps using these paradigms look like? Do you think it’s okay for even the most basic apps to look this mutant?’.
The ergonomics of developer tools/libraries is an underrepresented topic. Some would even call it taboo since so many of us don’t want to appear as if we don’t know how to use a technology. It stops us from giving valid feedback in many cases where something is truly unintuitive, or painful to use.
Rust is great. However, because of the ease of creating crates (packages), it seems to be beginning to suffer the same fate as Node and node_modules, with authors bringing in crates (just a `crate install` away) and ending up with ludicrous compile times for the end users.
>“Missing semicolon on line 427.” To which I’d reply “If you know what is missing, and you know where it is missing, why not add it back yourself? You useless piece of crap!”
Because what you mean and what the closest syntactically correct program to what you typed are two very different things.
Right? I bet it's the very same people that complain about JavaScript doing exactly that and are then surprised as to why their code doesn't do what it's supposed to...
So is GCC. The point is you still need to look at where the error is because the closest syntactically correct program to what you wrote is probably not the program you wanted to write.
I see this argument a lot: in the "good old days" there was Unix and apt and it was brilliant, now we have hundreds of toolsets and libraries that are flaky and need updating every year.
I think what these arguments miss is the upside of today. The "good old days" of brilliant developer experience was only brilliant for a small number of people. You had to learn right way of thinking, invest the right amount of time to learn good principles, how Linux was architectured, how not to re-invent the wheel, and so on.
This was a huge barrier to many people getting started with coding and the economics demanded getting more new developers ramped up faster. This pressure caused people to try to quickly develop little "get started quick" ecosystems.
Now we are in a situation where from a pure software engineering perspective we do have a complicated stack of teetering and shifting frameworks, I agree. But on the other hand this has come with enabling an awful lot more people to quickly get started toying with apps and coding.
What I'm trying to say is, these days its quicker to go from Level Zero to Level One, even if that means you've shot yourself in the foot going from Level One to Level Two.
> What I'm trying to say is, these days its quicker to go from Level Zero to Level One, even if that means you've shot yourself in the foot going from Level One to Level Two.
I see this a lot as well. And frankly it scares me. It should not be very easy or quicker to go from Zero to One at the expense of footgunning One to Two and beyond.
Practices and culture are easily learned when you are just starting. And those practices stay with you till the end. It is very difficult to unlearn something, especially when you learned it while starting out as it becomes a kind of second nature.
Those practices might not harm when you are making basic sites or demo apps in your spare time. But when an engineer with these practices goes to work on something like the software for controlling Teslas, it suddenly becomes a big problem.
In my view, it is better to take some time to make a solid foundation than to quickly make a leaning tower of software that could, in these days of software in everything, lead to catastrophe.
> Those practices might not harm when you are making basic sites or demo apps in your spare time. But when an engineer with these practices goes to work on something like the software for controlling Teslas, it suddenly becomes a big problem.
Well, the reality is that most businesses only need basic sites and you don't need trained engineers to build them. Basic developers can do it as well and giving them the tooling to do so helps.
There is a lot of value in making programming for "basic" stuff like a CRUD web/mobile app about learning to use tools rather than learning to understand the whole system (i.e. programmer vs engineer).
A comparison I really like: To build a house, you need one engineer for statics, but a lot of construction workers actually putting it together. And even that one engineer for the statics is more for safety than actually necessary, if you build some basic house with the basic default material. Because it's proven over and over again that it holds and the margin for errors is quite large before there is any risk of collapse.
The old joy of watching logs of a stupid GNU script checking basic features of the GNU C compiler. Just in case someone installed a compiler that had a different implementation.
I was referring to the tedious wait for the configure script. It might not seem so bad now, but what's a mild annoyance on modern computer with an SSD is quite the interruption on a few hundred MHz and spinning rust.
Another thing I wish it would do is give you all of the missing dependencies up front. Aain, not so bad now, but it was a major hassle for me when a missing dependency meant a long walk to the local library, 4gb flash drive in hand.
Especially lovely now when one might want to use clang and some CFLAG you set breaks a bad check. It's also very annoying to correctly pass PIC and PIE flags when the makefile builds both libraries and executables. I loathe automake.
Really not that bad. Almost always, configure make make install. And the main thing is the expectation. We always expect there to be dependencies and we expect to install them by hand and usually they were documented. Any errors would be easily understood (undefined reference or linker error). Now you have these systems that try to do things for you, you expect things to just work, when they don't your expectations are slighted and you get mad. The upside of all this tooling is the same joy you'd get in the 'bad/good old days.'
The FreeBSD or Debian port maintainer maintained it for you.
The seedy underbelly of all of this stuff is that most of the libraries and dependencies and pet projects that somehow became ubiquitous never worked outside of the lone developer's laptop, or the one compsci department's ancient from-scratch installation, etc.
And if you asked him why it didn't work he'd tell you to go fuck yourself.
I remember when I was a kid I tried for days to install gentoo and it just was not working. After so many hours of banging my head against the wall, I realized the CD was corrupted. Re-burning the iso fixed it
Yes, the increase in accessibility seems much nicer now than waves hand before GitHub and Arch Linux Wiki.
But I found the examples given in this blogpost striking:
https://tonsky.me/blog/good-times-weak-men/
One of the most prominent tech companies (Apple) released a new music program to replace their older music program. The replacement program included several easy-to-notice UX bugs.
The bugs surely aren't from a lack of attention, expertise, or resources. And while obviously it's not easy to write a program like that, I think the best explanation would sound something like "towering pile of shit".
I would disagree strenuously with the fact that it's easier to get started now than in the past, unless you're talking about the early 90s when the World Wide Web was still nascent.
10+ years ago, you could just install a server-side rendered web framework on a VPS or dedicated server you rented from a hosting site, and you'd experience a far smoother developing experience compared to today's Javascript churn. I'll take Django over React+Node.js+Docker+etc. any day.
And compare modern devops to ye olde webmaster ways. It's much easier to get started by writing a few bash scripts and customizing Nginx configs than to learn how to use Kubernetes, Docker, Terraform, etc.
Nowadays you can get cheap internet access, and you can buy a used okay-level laptop, get a free domain (like .tk, just a bit better from Google, the .dev), get a free VPS from AWS, and you can run whatever you want on it.
PHP has a built in web server, you can start developing with Laravel/Symfony easier than ever.
You find DigitalOcean tutorials for basic things easily, and you don't have to try to make stuff work on shady adware shared hosting portals.
The old webmaster days. Uh those were horrible. People tried to do blue-green deployments with Capistrano and PHP cache invalidation with atomic rename. And then folks spent years hacking RoR stuff to make it scale.
Yeah, Django is nice, but Python is a mess. Now with mypy finally there's some light at the end of the tunnel.
I think you are misunderstanding the negative implications of “being easy to go from Zero to One”.
The problem with the above is that the easier it becomes to go from Zero to One, the more _replaceable_ One becomes. After all, you can learn it in no time!
Naturally this leads to more and more churn and every developer who is already _at_ One or above has to keep going back and re-learning it in order to “keep up with current trends”.
After a while it becomes tiresome to see yet another front-end state management library promising to fix all the problems caused by the previous iteration... Slowly you become jaded enough to find yourself subconsciously hoping these projects fail so you don’t have to waste your time learning their specific _dogma_ (because of course it can’t just be “entities”, “events”, and “handlers”. This new _snappier_ API uses “atoms”, “signals”, and “transducers”)
The reality is that most of the _real_ problems within a system (at least the interesting ones) are are at Two and above. So the constant churn at One just becomes an annoyance that takes focus away from the important bits.
I’d _gladly_ take some churn at the level of solving _my_ domain problems. Unfortunately, thus far, it seems I’m the only one writing anything that fits that bill...
Nothing has changed, today's web frameworks are pretty much worse on all fronts than the mess of excel, access, vb apps written by people without any formal training. At least many of those utilities worked for years after being created, unlike this mess which requires constant reworking just to continue working.
Compared to Windows, iPhone, and Android. Android has the worst tooling environment of them all. You would expect a big software company like Google to know better, but you'd be mistaken.
All others provide you a native simulator that you can use to ease development ( Windows even provided one for Windows Phone). Android provides an emulator that gobbles up RAM and is painfully slow to use. Most people just prefer to use their local device instead.
Other platforms provide you their own IDE tailor-made for development. Google just took IntelliJ and made some changes it.
Edit: Another point is compile times. Compile times for Android are just atrocious. While Windows and iOS compile quickly in a few seconds and allow you to fast deploy, Android is painfully slow taking over a couple of minutes for compilation.
> Android provides an emulator that gobbles up RAM and is painfully slow to use.
That's not my experience. The official Android emulator works just like any emulator and will take the RAM it needs to run like a real device. If you don't have the RAM to emulate a smart phone (which these days contains anywhere between 6 and 10GB of RAM it seems) while also running the debug tools, you can always lower the RAM you give the virtual device. Android will run on 1GB of RAM though it won't be pretty if you want to emulate interacting between different apps and such.
Oh, and there's a potential gotcha in that Android does a lot of stuff on the mobile GPU, so GPU acceleration will make a huge difference. You don't need a 2080Ti to run the emulator, but integrated Intel graphics are often not up for the task. On my laptop the Intel drivers were also flagged for incompatibilities because of unresolved issues with the driver themselves, making Android run on software rendering and oh boy what a drama that was.
The big problem isn't so much the emulator, it's the IntelliJ-based IDE combined with the java compilers that gobble up RAM worse than Chrome. Each compilation process can quickly grow to 2GB and release it soon after, torturing your OS's memory manager.
My experience running and debugging the emulator with 16GB of RAM have been quite good. 8GB is doable if you don't have too many tabs open and tune your emulator.
The biggest problem I have with Android development is that compiling even a small app takes over a minute in my 7700k.
As a fan of IntelliJ, I applaud their choice of IDE. They used to base their IDE on Eclipse and that was clearly not worth it. As for dedicated IDEs, unlike Microsoft and Apple, Google didn't have an existing IDE lying around for their purposes. When someone did make an IDE from scratch, Xamarin, I found it worse in every single aspect aside from language support. And let's be honest, while Visual Studio is probably one of the best end-user facing pieces of software Microsoft still maintains in-house, it wasn't that great. Typing latency is high, configuration is painful and error messages are vague. Many, if not most, dotnet devs run the Jetbrains tools to enhance their VS experience.
I agree that it works just like any other emulator, but the competition offers simulators which take up far less resources. Google did start work on a simulator which went by the name of 'Arc Welder' and while it seemed promising it was discontinued soon after.
And I wholeheartedly agree with your point about compile times and have added it to my comment.
Windows Phone used the same model as Android, only Windows Phone devices never got to the point where they came out with over 4GB of RAM.
iOS doesn't actually emulate most of the system though, which is why it can run on so little RAM. Apple repurposes the shared components running on macOS to do the heavy lifting of iOS emulation. Their approach, in my opinion, is closer to a Docker container with a display than to a traditional emulator.
This is also why it's technically impossible to port the iOS emulator to Windows or Linux even if they were willing to give up their vendor lock-in.
I haven't worked with the iOS simulator for long, but I found some features the Android emulator offered missing in iOS. There was no installing apps (like WhatsApp, to test sharing) and the tooling for faking following a recorded or generated GPS path were either impossible for me to find or just not there. I also found that the "OS" inside the simulator felt bare-bones and incomplete whereas the Android emulator comes with the complete toolkit, including Google Play. iOS simulation is faster than Android emulation, but in my opinion that comes at a cost.
It's possible to do the same thing on Linux through Anbox, though that might not have all the same API's. The Android kernel is quite different from the Linux kernel it was once just a fork of and on Windows you'll never see the same level of integration with Android that iOS has.
>The big problem isn't so much the emulator, it's the IntelliJ-based IDE combined with the java compilers that gobble up RAM worse than Chrome. Each compilation process can quickly grow to 2GB and release it soon after, torturing your OS's memory manager.
Android Studio isn't necessarily that bad. On a very large project, my AS instance eats up, at the absolute worst, 4GB of RAM. Which, compared to all other IDEs is not that awful.
Gradle however will eat memory and balloon to 8GB on its daemon
>The biggest problem I have with Android development is that compiling even a small app takes over a minute in my 7700k.
Make sure incremental compilation is setup. For small changes, this means that recompiling is lower than 10 seconds.
> Many, if not most, dotnet devs run the Jetbrains tools to enhance their VS experience.
In fact, you don't even need VS as part of the experience anymore – Jetbrains Rider has most of the Resharper features (including "extract class" in the latest version) in an IDE based on the IntelliJ platform. It feels much faster than VS + Resharper.
Well JetBrains' IDEs are actually great so I don't think this is a valid argument. I worked with Android Studio for 2 years after which I moved to .NET development. I missed AS/IntelliJ so bad, I actually made my company buy me a sole Rider license and it's way, way better than the 'tailored IDE' that Visual Studio is. I'm way more productive and most of my colleagues are astounded by it's capabilities. Android Studio is actually decent, even considering it's quirks, and you'll only notice that when you have to use IDE other than JetBrains' one.
> You would expect a big software company like Google to know better, but you'd be mistaken.
I don't think it qualifies as speculation anymore to assert that Google has something really broken about it, organizationally, that keeps it from producing truly good software—and often not even decent software—in most of its projects, for some reason. Even very high-profile ones. There's not really any other explanation for how they consistently behave.
Pure speculation on my part, but it sounds like an organizational case of ADHD or Magpie driven development. A new project is started and everyone jumps ship before it is ready, leaving some other team to come in and continue before jumping. Repeat this over a few times in a product and you end up with an unusable mess. This might explain it.
yeah the culture is all based on promotions.. and you get them by launching something new, not by maintaining or improving existing systems. hence what you said
Friend of mine that worked as a manager for a few years at google. Said he found it extremely difficult to get people to work on stuff that wasn't shiny and to stop refactoring stuff that was good enough.
On the tooling side, I think Steve Yegge's infamous and very entertaining platform rant from 2011 nails it: https://gist.github.com/chitchcock/1281611 tl;dr Google doesn't have the platform mentality in its culture, unlike Amazon and MS.
Google is a large company. I have respect for its core product that is google search. It’s insanely fast and reliable. I can’t remember the last time it was down. Mostly gets the answers I need at the top (I use adblockers so ads aren’t a problem)
The rest of Google has other priorities though. Even gmail’s iOS app had pretty glaring bug that it couldn’t mark a message read.
Google docs fails to save at times. YouTube Kids is just an awful mess. Don’t let your kids even near it. Google Cloud isn’t as reliable as the other clouds. Google can’t do proper human support. They don’t believe in it. If you’re a small shop, going with Google for anything critical is just going to be a disappointment.
Google Search though. I have an insane amount of respect for their engineers who work on performance and reliability.
I can't empathize with this enough. The build stack of Java software is absolute nightmare. I really haven't met anyone who really know this in any detail. There is something seriously wrong with the Java community. I also develop extensively in Python and I rarely encounter the same degree of difficulty in developing complex software.
I think it's a matter of perspective. I develop a lot in Java, and I understand most of the build stack. Most of the time, when I see an error I instantly realise what the problem is. Sometimes, rarely, it's cryptic, and I need to do a lot of digging to figure it out.
I also touch python once in a blue moon. It's always frustrating. To get anything done, I need to install python, then install pip, then make a virtual env, then use pip to install the libraries the project needs in the virtual env, then start the project. At this point, I realize the project does not work on the latest version of python, but on some specific version, and I need to throw away everything and start again. And each time I tell myself: "why wouldn't they write this obviously critical piece of information on the main page?"
I don't think one of the tech stacks is much better than the other. I think we just perceive the one we are knowldgeable in as better, for obvious reasons.
> I also touch python once in a blue moon. It's always frustrating. To get anything done, I need to install python, then install pip, then make a virtual env, then use pip to install the libraries the project needs in the virtual env, then start the project
Oh, that's where the simple projects "start the project".
Even with wheels around, that's where you'll get an error message that eventually decodes as "There is no C-Compiler on this platform". And then you're installing clang or gcc. And make. And configure. And fuckit, just install build-essentials.
And then you start hunting C dependencies. Which I can because I have some experience building C, enough to never to it again. And then you start learning which link error with libpython indicates which minor version of python is actually required. And eventually you start looking into really weird hacks with chroots to be able to have multiple python-devel headers around. Or use containers to compile a python library.
Sorry. I like the language python. But installing python packages to do something... I don't know, it eventually hurt something inside me. I severely never want to deal with python in production anymore unless I can just globally install it in a container and stop caring.
Java tends to be tolerable. People tend to overuse maven beyond all repair, and gradle can be funky. But none of them compare to the hell python requires.
> To get anything done, I need to install python, then install pip, then make a virtual env, then use pip to install the libraries the project needs in the virtual env, then start the project.
These days i spell that
poetry new myproject && cd myproject
poetry add dep1,dep2,...
poetry install
git init .
gi python && git add .gitignore && git commit -am “first commit”
pip can be used by itself to install a poetry managed project, so just
venv/bin/pip install
as normal.
This is ok-not-great; i’d prefer for python and pypi to put some official funding and weight behind one de-facto 517/518 build system and stabilize things a little. However this is python we’re talking about, so it’ll never happen.
As someone that hasn't used Java in production deployment, I tried to play with an open source project that seems to run on JBOSS Wildfly. After about 3 frustrated hours, I cut my losses, deleted the docker containers and images, and decided it was simply not worth it.
I could build the code in IntelliJ IDEA, but I couldn't for the life of me figure out how to actually run it to simply test it and play around with it. I can only concur there is something seriously wrong with the Java world/community. Perhaps it's too focused towards enterprise, where you can afford to have one person specialise in sitting at a desk, monitoring Wildfly?
I never really understood the argument for configuring a build tool in a separate programming language, let alone in two separate languages. I have never once said “thank god I have regular language functionality here”, and more often said “what undocumented function do I need to call again?”
Makes me want XML and Maven back; at least my IDE can guide me based on the schema files it parsed.
This is exactly what I think Everytime my python code (99% I'm forced to use because of library support) breaks because I overwrite a library function in my loop, or every "Wat" with JavaScript.
How many hours and thousands of lines of pointless tests have been wasted because of bad type systems - I really don't get the fuss about about Python, C++ was designed by a committee but python genuinely feels like it wasn't designed at all beyond the basic syntax (which I like)
"buckling under its own weight when a project reaches medium size" is a subjective view!
A counterexample is the company when I worked for 8 years. They took Python very seriously. By the time I left, 4,000 developers were making 20,000 commits a week in a codebase of some 30,000,000 LOC.
I mean, I think it's possible to write quality software in virtually any language if you're serious about it. I would argue that in the case of python, you'd be succeeding in in spite of the language at that scale rather than because of it.
"[Android] development tools are focussed on large teams of highly trained software engineers, who all intimately understand every esoteric aspect of App development."
This really rings true to me. I almost cringe when I have to explain how to do some of the most basic things to non android developers.
Aside from the dozens of libraries you need to include, and need to know where to find and what version is compatible with what, the tooling itself is an insurmountable mess for new developers. It's also not getting any simpler.
I have to admit I often roll my eyes at the state of mobile development, especially on Android. I worked on a few Android apps in 2009-2012 when a "best practice" hadn't really been established yet, and as I tangentially follow the field now it's hard to understand how insanely complicated it's all become. I mean literally for 90% of apps we're talking about doing some REST requests and populating some text and images on screen. Why dozens of libraries are needed to achieve this I cannot understand.
Like I was interviewing a guy for an Android role, and he was walking me through a pet project of his which consisted of literally one list view which updated it's contents to filter results out of an SQLite database as you type into a text field, and the project had literally dozens of files. It just made me sad.
I mean maybe there is something I don't understand, but the state of the field seems to be heavily driven by following what the "cool kids" are doing, and the tooling seems to have more to do with signaling that you're in the in-crowd than it has to do with actually delivering value.
With Android, part of the problem is that a solid ~80% of the "how to" information out there (and a distressingly high percentage of the official documentation) tells you to use things that were either deprecated years ago or are about to be deprecated in the next version of Android. Since the framework has gone through multiple iterations of this dance, you basically need to learn the whole history of any API you're using before you can decide how some part of your app is going to work.
Or you can pull in a library that seems to be popular and maintained and solves the problem that you have.
That, and there's a lot of "folk knowledge" around how to do things that the docs ignore. The cleanest and most efficient (or even just non-broken) way to do even basic shit is often to ignore how the docs say to do it and use some library. The whole platform feels badly neglected, like the only time anyone gives it serious attention is to throw some half-implemented shiny feature on top so they can announce it at an event, then never touch it again.
I think a large part is that the first-party documentation is pretty bad. My only exposure to the Android toolchain has been writing my own toy application, and it's just sad that the docs are terrible. Things like "this thing that used to be in the platform API had been replaced by that thing in appcomapt" → "nope it's in androidx now" → "this replaces that thing in the platform API, go read the docs for that instead". Essentially, you _have_ to read deprecated documentation to do anything…
At least it's better than some other ecosystems, where it's "this thing is deprecated now. Nothing replaces it and you can't do similar functionality any other way, it's just deprecated." Or maybe I just haven't gotten to that part yet.
I once did small project for Android (basically created a library that would receive stream of data over BlueTooth from some device). Setting up the development environment (I've created full system backup prior to installation) and then using it made me hope that it is the first and last time I touch this pile of s... .
I tried flutter and while it seems better than Android studio, it has its own problems.
I precached but it still required internet access to get some maven deps for android build. Updating is full of hassles and gradle, as always, unexpectedly fails somewhere eg in "assembleDebug" step. Maybe some version mismatch and I am not in a situation to do clean installs that require GiBs of internet. And no guarantee it works even on clean install.
I have come to a conclusion that front end (web or app development) is a mess and it is not for me. Look at Go, or Rust to know how to keep tooling simple and straightforward.
I agree with most of the post but this line confused me.
> The compiler would say “Missing semicolon on line 427.” To which I’d reply “If you know what is missing, and you know where it is missing, why not add it back yourself? You useless piece of crap!”
How can you add a feature like this without any extra complexity?
It sounds great in theory but in practice most code depend on another piece of code. Most of the time blindly changing one line can introduce more bugs.
Why is this bad? As someone who has spent a lot of time writing code with auto formatting turned on, I’m genuinely curious which parts of your workflow break when the whitespace changes out from under you.
I tried Atom for ten minutes and then gave up on it because it made undesirable whitespace changes by default.
Doing code formatting is fine; doing code formatting on lines from a checkout that I didn't change is bad. Yes, the file should be reformatted. But let me know before doing it, so I can make a formatting-only commit so it's easier to review when I put up the PR.
When I'm working on new code, sure, I'll enable it, but other times when working on existing code I just want to make the minimum changes necessary. For example if I'm explaining to someone why their code doesn't work when I try it and what little change would help, sending them their code with dozens of irrelevant changes in addition to the relevant one isn't going to help my case.
"Expected a colon here, found a <" (ascii-art pointer to the place) "did you forget to close a bracket here?" (ascii-art pointer to 12 lines above that, where, indeed you forgot to close a bracket.
It does this for semi-colons (they are not always required), closing brackets (maybe you are nesting something horrendously deep?) etceteras.
The idea, basically is "I see this is wrong. But I'm not the one to decide how to fix it for you, but here's a suggestion".
I remember being baffled for an hour or two after accidentally putting a trailing opening { in a c++ file and then getting thousands of compilation errors all through the standard library headers my application included.
I don't mind missing semicolons. In c++ paren/bracket mismatches are the bane of my existence. Specifically, if you open a paten in a header file and forget to close it, gcc will dump reams of errors and warnings, even on fairly small projects. Usually the problem is the first error, but for a dangling paren, that one's a red herring, you want the last error. It says you have an unclosed curly-brace in the top-level file. This appears to be due to a confluence of footguns:
1. Files are allowed to have different numbers of open & closed brackets. So who knows where the real error is? For all the compiler knows, you left that paren open deliberately in one file and forgot to include the paren-closing file?
2. C++ syntax generally lets you put anything anywhere -- the compiler doesn't seem to mind that I'm defining a new class literally inside the parentheses of a function call? Is that actually legal? Who knows. But I'm still a little confused... after opening that paren I almost immediately use too many closing braces -- why isn't that spotted immediately?
The Vax C compiler used to do this, and mostly got it right.
It was a complete nightmare trying to port code that compiled and ran perfectly well on the dept microvax when we all transitioned to Ultrix and Linux.
As a result of those months of pain, even thirty years later I’m a huge fan of strongly typed languages, compiling with -Wall and -Werror, and have a zero-warning policy.
If you’ve never gone through it, you wouldn’t understand...
The popularity of Gradle utterly baffles me. It is one of the most infuriating tool I have to deal with, and the one I most regularly flail around with trying to find out the magic song and dance that’ll make it happy. The existence of two separate programming languages has made the doc situation a nightmare, and I genuinely do not understand why I have to use a real programming language to configure my build.
When Gradle got popular the main competition was Maven which involves copy and pasting random pieces of XML from the internet, gave stack traces rather than clear error messages and didn't used to support incremental builds.
Before I continue, I would like to point out that Gradle is so bad that it’s making me say “I’d like to go back to XML please”. In any other context this would be an insane thing for me to say, but Gradle is that bad.
XML & Maven has the benefit of having a schema. This means that not only do all my pom.xml files look similar, but the IDE can do meaningful autocompletion and semantic checking for me. It’s verbose and ugly, but at least it’s consistent and has good tooling.
Gradle on the other hand is a Turing complete system, which just adds another layer of potential errors on top of Java compilation, which is the exact opposite of what I wanted. Now also all of my Gradle files are different and I have no idea why, and what the relative pros and cons of each style is.
Could Maven be improved? Sure. I’d kill for something like Cargo for Java. But I did not want to find myself debugging by build tool’s state because I used a setter wrong (true story).
> copy and pasting random pieces of XML from the internet
Also, I don't see that this is a big deal when dealing with a declarative paradigm. In fact, cutting and pasting random bits of declarative code makes a lot of sense to me. You don't need to understand how it's doing what it's doing, only that it will.
I have yet to discover a situation where some custom thing I needed couldn't be handled with the Exec Plugin or a custom plugin, which are easy to write. The truth is that these uber-custom things are actually pretty rare if you stick to conventions.
NodeJS building tool? Do you mean gyp (which is bad) or high level stuff run via npm/yarn (which is meh) like gulp/webpack/ng whose config files are all horrible?
I too would like clarity. Every time I end up having to do frontend stuff with gulp/webpack/etc I want to shoot myself, and that's fair. The few times I've had to compile native dealing with gyp has been a crapshoot (sometimes just work, sometimes painful; never as bad as gulp/webpack/etc). But most of the time, for Node development, I just need other node libraries, and it's pretty painless. Not as good as some others, but still -miles- better than Gradle.
Why do I have to learn a second programming language just to configure my build? /s
Builds need Turing completeness surprisingly often. Build languages then expand to accommodate, with spaghetti disasters as the result.
“But it has to be accessible to new users and can’t be tied to just one language” said SBT as it jumped the shark with its .sbt files.
Sigh.
Developers get crap tools because developers won’t pay for tooling - if it’s not open source and free we don’t touch it outside of an enterprise environment. And Lo and behold, most tooling is either cobbled together by Enthusiasts, or as user friendly as enterprise ware usually is.
(There are, of course, shining exceptions to this, which is great)
What’s frustrating is seeing new communities and languages make unforced errors that a review of prior mistakes should easy uncover. The lack of a unified, coherent build tool in Java was a huge mistake. New languages would be well advised to focus on good tooling right out of the gate, rather than putting it off until later.
The problem of tooling is that that's the place where ugly hacks most often go. Where the beautiful elegant abstractions meet the reality, where third party dependency cruft seeps in, where cross-version compilation gets orchestrated, where all the dev/test/prod compile time configuration, optimization, obfuscation, etc. happens.
And sbt is just bad all around on top of all this, and it should feel bad.
> if it’s not open source and free we don’t touch it outside of an enterprise environment.
To be fair, this is due also to the fact that opensource tools are mostly guaranteed to outlive their developers. Should Microsoft go bankrupt tomorrow (don't laugh, it basically happened to SUN), most of their traditional tooling would disappear. In contrast, Gcc might be old and crusty, but it will go on forever like a cockroach.
> crap tools because developers won’t pay for tooling
I'm not sure i understand this argument
crap Linux because developers won’t pay for Linux
crap git because developers won’t pay for git
...that's clearly not the case, no? Every day we use a bunch of developer tools that are not just crap, but amazing and great to work with, and were built as open source. So I'm not sure about equating open source with crap experience.
Not only the tool is infuriating, the language is baffling. With most tools the first time I ever set eyes on the configuration I had a pretty good idea what was going on without reading any documentation. With Gradle it's like someone invented proto-Java and just left it at that. A build file which was actual Java would be much easier to understand and most importantly edit, because then I could get the IDE to help explore the API.
As a side note, this is probably (intentionally or not) the same tactic that Microsoft used in the 00s to avoid competition: keep changing things fast so that anybody using your tool chain a) has to follow your lead to keep up, b) ends up with huge sunk cost, and c) (if they trust whoever's behind Gradle) keeps being reminded how much they innovate.
So much this. I've tried multiple times to grok it and it just slid straight back out of my brain leaving me with the same puddle of syntax soup I started with. I've never encountered anything else even close to this bad.
Not to mention that build config is probably the absolute last place you want a weird unreadable language nobody knows, because it tends to be touched so rarely that nobody builds up any familiarity with it.
You can write nearly all of your gradle build logic in java if you want. Place the java files to configure your gradle build in buildSrc/src/main/java, then write a single line of kotlin in your build.gradle.kts to call your java code.
It's worth considering Bazel instead which is much cleaner and easier to understand. Unfortunately its official support and platform adoption are limited
This post does put the finger on one widespread problem: Bad error messages.
When you're designing an error message, don't just tell the user that something went wrong. The mere fact that they're getting an error message already conveys that. Instead, concentrate on telling them what is being expected or what they can do to fix it.
Totally agree! I have to say, as an author of preprocessor/compiler toolchains, I’ve struggled a lot with designing error reporting in a way that maintains abstractions in the toolchains, but still produces useful error messages. Oftentimes, I’ve fallen back to hard coding error messages that assume a particular code path. I’d be really interested in seeing examples of error reporting patterns that work well across multiple levels of abstraction.
Android (Studio) seems extra bad in this regard. I once decided to start a new app project, and it instantly didn't build because the generated build configuration was referring to incompatible versions of different components.
I thought the entire point of automatically generating boilerplate was that you could ignore it until you needed something other than the defaults. When all of that magically introduced complexity is wrong, why make me start with it in the first place?
This was also my experience when I wanted to try my hand at app development. The tutorial wouldn't build. Decided that I didn't want to be beholden to an ecosystem like that.
> The fix was simple. I manually replaced the word “compile” with the word “implementation”.
I really wonder why are we letting this happen. Really
A similar thing to when I see a command or an API call that does what you want then says "deprecated" (with no clue of why or how to do that now). Sure, because nobody does this anymore right? (and I'm not talking about complicated stuff) Or the new function works in some mysterious way when the old one was straightforward
I mean, really
But it seems people are "moving fast, breaking things and who cares if it's broken? it works for me"
> A similar thing to when I see a command or an API call that does what you want then says "deprecated" (with no clue of why or how to do that now).
Hm, that is actually a point where (in my experience at least) the Java community tends to do pretty well: in nearly all cases where I see an API that is deprecated there is a comment that at least tells you what you should use instead. Additionally, "deprecated" usually means that it still works, which is a whole lot better than having it simply disappear.
The compile keyword produced warnings for over three years now. The author was likely developing with an old or bad guide in hand, because the warnings were there.
In my experience, many of the Android methods marked as deprecated also contained docstrings to the new API and how to use it. In some cases it can even automatically insert the boilerplate code to do what the old, deprecated function did with the extra error handling for changes to the platform.
compile and implementation aren't the same thing. Depending on your use case, compile needs to be either changed to api or implementation. They aren't the same thing, so just a quick replace by the IDE would likely break more than it fixes. The problem is that most guides treat them as the same thing and make people think the compiler is being stupid for changing the word they need.
I can't speak for other projects, but for Android, where most of my deprecation struggles came from, the change was the result of changing requirements. Early Android was a wild west where every app could copy the contents of your SD card and upload it to their servers without even so much as a warning, where IMEI numbers were widely used as identifiers in databases for analytics and where permissions were more of theory than a practical requirement. Killing random apps was a permission any application could obtain, app databases appeared on your SD card which sometimes included credentials and secretly turning on cameras was easy to do by rendering the preview to a 1x1 pixel area. Screen hijacks were also commonly possible, causing major concern for apps for banking and such. Google had to retroactively restrict applications with new permission systems and applications often crashed without workarounds because the developers often never bothered with exception handling for stuff like file I/O. This isn't moving fast and breaking things, this is trying to fix fatal flaws in the design of a running train.
When I encounter deprecation, it's because the underlying design of the API I use has significantly changed, often for good reason. It's annoying when features turn from a simple function call to a complicated code structure, but there's often a good reason behind it. I just wish people would put those reasons in their docstrings and release notes instead of marking stuff as deprecated and leaving it at that.
That’s not the point of the article, the point is that if a developer gets to the point of having to break things, it should think on how to mitigate the work is forcing upon those who use its tools.
It’s about being conscious about others time and the impact your work has on theirs.
They might be a good reason for changing “compile” to “implementation”, but it costs nearly nothing for the dev to add a specific rule that if “compile” is in the code, the compiler should show a link or point to the docs or explain how to solve it.
On the other side it’s painfully costly for anyone using that tooling to understand what’s happening, why the change, how to solve it. The end result is that a lot of inexperienced users will find a fix that works for them (like bulk replace of one for the other), and the end result tends to be a worse ecosystem for all.
I don't think that's true. This is what the author wants. Or rather, demands:
> Why doesn’t Android Studio / Gradle / Whatever just go “Mate – you’ve used compile here – that won’t work. Want me to automatically update the syntax? It’ll probably be fine.”
But the machine can't make the decision, since it doesn't know the intent. The informed human in charge of the project does. What if there's automation, and tool ends up making the wrong decision? I bet that the author would be complaining about that instead.
Reading the Twitter threads that the author links to are quite illuminating, and it's surprising to me he feels it's showing him in a good light. It's an amazing display of both entitlement and intentional ignorance.
I use this (and frequently use it) - but I wish it were a feature of the shell, more generic than just for git (or everything independently). Seems like it shouldn't be too hard on the shoulders of completions.
On the flip side, I have the NextDNS CLI running on a Jetson Nano. I found it was logging too much for my comfort (meaningless reverse DNS logs, and I'm somewhat paranoid about flash exhaustion) so I cloned the repo, commented out a couple of lines, and did go build.
Actually built for Linux on my MBP.
Boom, all dependencies, and in seconds a perfect binary. I've had similar experiences with a number of projects, including huge projects like Firefox.
Like it all things in life, it varies. Some projects and toolsets are perilous mountains of crapitude. Others are just magically delightful.
If manufacturers would provide an option for unlocking bootloaders on all phones, and component manufacturers would release driver source code (or at the very least datasheets), then I could/would gladly update my phones.
I fully disagree with "Fail 2". Tools shouldn't automatically update dependencies, developers should be full control of what and when to update them. Dependency handling is a very complex topic, it's hardly something you can just left to the computer, maybe minor bumps when everyone agree that only minor bugs got fixed, but that sometimes can break the whole world.
As with the missing semicolon; the compiler can't be sure if that's a typo, so the line should end there, or you just really missed the semicolon only. It doesn't understand the code the way you do.
As for "Don’t make me think." - the whole software development is about thinking. Can't do any part on autopilot.
> the whole software development is about thinking
Sure, but I'd prefer to think about the problem that I'm solving, and not about which combination of packages I need to successfully compile and run the application.
I don't want to spend time manually upgrading dependencies, or syntax, especially if this is something that can be automated by build tools or IDEs.
Unpopular HN opinion: we need more commercial SWE tools. This is the expected outcome of under-organized underfunded ad-hoc development of professional tools.
Whilst reading about this I found myself thinking back to my days as a student, writing C++ with Visual Studio 6.
If you were able to install everything, including the documentation, to your hard drive you never really needed anything else (which was good, because I didn't have internet access at home to begin with - too pricey).
You had high quality development and debugging tools, and then in MSDN you had this absolutely exhaustive, encyclopaedic documentation that covered every possible topic in depth, and a good enough search function that you could usually find what you were looking for without too much difficulty.
In some ways - not all ways - those were the days.
I find that it's nearly impossible to argue for this when it matters. It's kind of magical how the reasoning works. We can't increase development capacity by paying for more person-hours, because developer time is far too expensive. We can't increase development capacity by paying for more productive tools, because developer time is basically free.
> The compiler would say “Missing semicolon on line 427.” To which I’d reply “If you know what is missing, and you know where it is missing, why not add it back yourself? You useless piece of crap!
That’s not the role of a compiler, for good reason. I stopped reading the article after reading this line.
Having spent at least 5 years fulltime in (each) Android, iOS, and Javascript client development, I'd say they're all about the same from how "shite" they get in a growing project. The magic incantations in gradle just become magic incantations in webpack.config.js and magic incantations in Xcode menus.
If anything, Javascript clients have the advantage of being able to bring your own fundamental abstractions since you're not stuck having to compile your abstraction to a narrow API like UIKit.
Web development gets the worst reputation because it's the only one most people have experience with.
207 comments
[ 3.3 ms ] story [ 236 ms ] threadThis is the main appeal of Rust to me.
I get error messages that contain the word "perhaps" with a gentle suggestion on what I might have wanted here instead. Quite often it's correct.
More and more, though, there’s such magic being performed by complete and libraries that you sometimes want DAIS.
But I have been absolutely bowled over, and inspired, by the Rust tooling. Not only helpful error messages, but hints about misunderstandings you might have had, along with concrete suggestions on how to fix it.
I feel like it corresponds to the highly rigorous thought that has gone into the language, which also results in a great language irrespective of the tooling.
Thank you Rust team.
I'd say it's less about rigorous thought, and more about being willing to spend time on purely user-centric things.
You can have both of course, but surely things like proof assistants have a lot of rigorous thought put into them, yet the error reporting is usually horrendous.
Improvements to Rust's error reporting is the result of a specific and dedicated effort in that direction: https://blog.rust-lang.org/2016/08/10/Shape-of-errors-to-com... (and https://internals.rust-lang.org/t/new-error-format/3438 and https://web.archive.org/web/20160807033841/http://www.jonath...).
And note that the new errors didn't really provide more information (at least initially), instead they formatted the information better, removed redundancies and noise, and called out the relevant bits more clearly. This runs very much opposite of "rigorously" dumping all the stuff you have and letting the user sort it out.
So much so that we have separate technologies to write in Javascript and then build it for Android (PWAs).
The server-client equivalent would be writing one codebase, in one language and building for browser, and server separately. Despite server-client predating Android by decades, that still does not happen.
It's a bit of a rant - but I hate anything that comes with IDE - I face greater cognitive load in undertsanding the IDE than writing logic.
In languages like Python, where you might run into an issue caused by not have implemented an arbitrary method on a callback, or Obj-C where you might have forgotten to implement a delegate, you're on your own as far as the compiler is concerned.
Yesterday my Rust code didn't compile because I was missing a bound on a type parameter on my function that I passed though into the key type of a hashmap. Rust said "hey maybe you want to add this constraint to your declarations".
Some of this you can put down to dynamc vs static. But beyond that, it's clear that the designers and contributors haven't just said "we want to make a language with great safety" but then went on to ask "what specific ergonomic challenges will this bring to users, and how do we help them" .
I don't think you could get those ergonomics from many other languages, even if you wanted, without extra static analysis.
(edit: lazy typing on a phone; in the last para I was referring to the mainstream languages like Python rather than the whole universe of languages.)
You absolutely could. Hell, languages which are much simpler to analyse have worse error reporting, and the language which started the movement of having less shite error message is a fairly simple one: https://elm-lang.org/news/compiler-errors-for-humans
I shudder to think about the next time I have to do npm decency upgrades. Even worse when you have synchronize typescript types. Which requires reading through random GitHub issues to realize that you need to pin a random @types package to 1.20.30 because that’s the one that magically worked for a commenter with 20 thumbs-up reactions.
The amount of signal to noise is low because of low barrier/high user base community spamming NPM packages/and spamming ratings/stars/dependencies - it's hard to determine what's "safe" to use, and because the environment is so barebones you need to depend on a lot of third party code or reimplement everything yourself.
C++/C have a similar legacy burden and barebones platform (although C++ std lib now-days is much better, historically it was unusable which lead to a lot of code duplication) but because the barrier to entry is much higher I'd say an average C++ dev is much more competent than average JS/PHP dev and the libraries commonly used in C++ world are obviously higher quality than JS/PHP (tooling fragmentation is a different story because of the unique problems C/C++ face, but still C++ build tools are probably the most sophisticated out there - out of necessity).
Rust falls in to the category of languages designed by competent people without legacy burden and tackles a complex domain (again higher barrier to entry), most languages I've seen in this category have decent tooling and design (eg. C#, F#, Go, Dart)
Regardless of rust's design in particular, static safety and lifetime management is now non-negotiable, and rust's error messages definitely lead the way although everyone else's are pretty good now.
If D and Rust had a baby I wouldn't anything else.
Gradle does not do any user research. It never sits down with independent developers, newbies, or seasoned pros. It never tests its error messages. It doesn’t do developer relations. It doesn’t spot bad implementations in the wild and offer helpful suggestion. It doesn’t relentlessly focus on making things easier for users.
Many times I wanted to just ask some library/framework authors that very question, like ‘hey, do you know what real apps using these paradigms look like? Do you think it’s okay for even the most basic apps to look this mutant?’.
The ergonomics of developer tools/libraries is an underrepresented topic. Some would even call it taboo since so many of us don’t want to appear as if we don’t know how to use a technology. It stops us from giving valid feedback in many cases where something is truly unintuitive, or painful to use.
Because what you mean and what the closest syntactically correct program to what you typed are two very different things.
I think what these arguments miss is the upside of today. The "good old days" of brilliant developer experience was only brilliant for a small number of people. You had to learn right way of thinking, invest the right amount of time to learn good principles, how Linux was architectured, how not to re-invent the wheel, and so on.
This was a huge barrier to many people getting started with coding and the economics demanded getting more new developers ramped up faster. This pressure caused people to try to quickly develop little "get started quick" ecosystems.
Now we are in a situation where from a pure software engineering perspective we do have a complicated stack of teetering and shifting frameworks, I agree. But on the other hand this has come with enabling an awful lot more people to quickly get started toying with apps and coding.
What I'm trying to say is, these days its quicker to go from Level Zero to Level One, even if that means you've shot yourself in the foot going from Level One to Level Two.
I see this a lot as well. And frankly it scares me. It should not be very easy or quicker to go from Zero to One at the expense of footgunning One to Two and beyond.
Practices and culture are easily learned when you are just starting. And those practices stay with you till the end. It is very difficult to unlearn something, especially when you learned it while starting out as it becomes a kind of second nature.
Those practices might not harm when you are making basic sites or demo apps in your spare time. But when an engineer with these practices goes to work on something like the software for controlling Teslas, it suddenly becomes a big problem.
In my view, it is better to take some time to make a solid foundation than to quickly make a leaning tower of software that could, in these days of software in everything, lead to catastrophe.
Well, the reality is that most businesses only need basic sites and you don't need trained engineers to build them. Basic developers can do it as well and giving them the tooling to do so helps.
There is a lot of value in making programming for "basic" stuff like a CRUD web/mobile app about learning to use tools rather than learning to understand the whole system (i.e. programmer vs engineer).
A comparison I really like: To build a house, you need one engineer for statics, but a lot of construction workers actually putting it together. And even that one engineer for the statics is more for safety than actually necessary, if you build some basic house with the basic default material. Because it's proven over and over again that it holds and the margin for errors is quite large before there is any risk of collapse.
Uncompress tgz
./configure.sh
Missing dependencies
Find those tgzs
./configure.sh
Missing dependencies
Find those tgzs
One won't run on your system
Try to hack the dependency out
Give up, you didn't really need that anyways
Another thing I wish it would do is give you all of the missing dependencies up front. Aain, not so bad now, but it was a major hassle for me when a missing dependency meant a long walk to the local library, 4gb flash drive in hand.
The seedy underbelly of all of this stuff is that most of the libraries and dependencies and pet projects that somehow became ubiquitous never worked outside of the lone developer's laptop, or the one compsci department's ancient from-scratch installation, etc.
And if you asked him why it didn't work he'd tell you to go fuck yourself.
Apt is still here.
The author is not pining for the good old days. In fact, he specifically says that when he was starting out, the tooling was terrible.
But I found the examples given in this blogpost striking: https://tonsky.me/blog/good-times-weak-men/ One of the most prominent tech companies (Apple) released a new music program to replace their older music program. The replacement program included several easy-to-notice UX bugs.
The bugs surely aren't from a lack of attention, expertise, or resources. And while obviously it's not easy to write a program like that, I think the best explanation would sound something like "towering pile of shit".
10+ years ago, you could just install a server-side rendered web framework on a VPS or dedicated server you rented from a hosting site, and you'd experience a far smoother developing experience compared to today's Javascript churn. I'll take Django over React+Node.js+Docker+etc. any day.
And compare modern devops to ye olde webmaster ways. It's much easier to get started by writing a few bash scripts and customizing Nginx configs than to learn how to use Kubernetes, Docker, Terraform, etc.
Nowadays you can get cheap internet access, and you can buy a used okay-level laptop, get a free domain (like .tk, just a bit better from Google, the .dev), get a free VPS from AWS, and you can run whatever you want on it.
PHP has a built in web server, you can start developing with Laravel/Symfony easier than ever.
You find DigitalOcean tutorials for basic things easily, and you don't have to try to make stuff work on shady adware shared hosting portals.
The old webmaster days. Uh those were horrible. People tried to do blue-green deployments with Capistrano and PHP cache invalidation with atomic rename. And then folks spent years hacking RoR stuff to make it scale.
Yeah, Django is nice, but Python is a mess. Now with mypy finally there's some light at the end of the tunnel.
The problem with the above is that the easier it becomes to go from Zero to One, the more _replaceable_ One becomes. After all, you can learn it in no time!
Naturally this leads to more and more churn and every developer who is already _at_ One or above has to keep going back and re-learning it in order to “keep up with current trends”.
After a while it becomes tiresome to see yet another front-end state management library promising to fix all the problems caused by the previous iteration... Slowly you become jaded enough to find yourself subconsciously hoping these projects fail so you don’t have to waste your time learning their specific _dogma_ (because of course it can’t just be “entities”, “events”, and “handlers”. This new _snappier_ API uses “atoms”, “signals”, and “transducers”)
The reality is that most of the _real_ problems within a system (at least the interesting ones) are are at Two and above. So the constant churn at One just becomes an annoyance that takes focus away from the important bits.
I’d _gladly_ take some churn at the level of solving _my_ domain problems. Unfortunately, thus far, it seems I’m the only one writing anything that fits that bill...
Nothing has changed, today's web frameworks are pretty much worse on all fronts than the mess of excel, access, vb apps written by people without any formal training. At least many of those utilities worked for years after being created, unlike this mess which requires constant reworking just to continue working.
All others provide you a native simulator that you can use to ease development ( Windows even provided one for Windows Phone). Android provides an emulator that gobbles up RAM and is painfully slow to use. Most people just prefer to use their local device instead.
Other platforms provide you their own IDE tailor-made for development. Google just took IntelliJ and made some changes it.
Edit: Another point is compile times. Compile times for Android are just atrocious. While Windows and iOS compile quickly in a few seconds and allow you to fast deploy, Android is painfully slow taking over a couple of minutes for compilation.
Tensorflow is another data point to say that you are wrong.
That's not my experience. The official Android emulator works just like any emulator and will take the RAM it needs to run like a real device. If you don't have the RAM to emulate a smart phone (which these days contains anywhere between 6 and 10GB of RAM it seems) while also running the debug tools, you can always lower the RAM you give the virtual device. Android will run on 1GB of RAM though it won't be pretty if you want to emulate interacting between different apps and such.
Oh, and there's a potential gotcha in that Android does a lot of stuff on the mobile GPU, so GPU acceleration will make a huge difference. You don't need a 2080Ti to run the emulator, but integrated Intel graphics are often not up for the task. On my laptop the Intel drivers were also flagged for incompatibilities because of unresolved issues with the driver themselves, making Android run on software rendering and oh boy what a drama that was.
The big problem isn't so much the emulator, it's the IntelliJ-based IDE combined with the java compilers that gobble up RAM worse than Chrome. Each compilation process can quickly grow to 2GB and release it soon after, torturing your OS's memory manager.
My experience running and debugging the emulator with 16GB of RAM have been quite good. 8GB is doable if you don't have too many tabs open and tune your emulator.
The biggest problem I have with Android development is that compiling even a small app takes over a minute in my 7700k.
As a fan of IntelliJ, I applaud their choice of IDE. They used to base their IDE on Eclipse and that was clearly not worth it. As for dedicated IDEs, unlike Microsoft and Apple, Google didn't have an existing IDE lying around for their purposes. When someone did make an IDE from scratch, Xamarin, I found it worse in every single aspect aside from language support. And let's be honest, while Visual Studio is probably one of the best end-user facing pieces of software Microsoft still maintains in-house, it wasn't that great. Typing latency is high, configuration is painful and error messages are vague. Many, if not most, dotnet devs run the Jetbrains tools to enhance their VS experience.
And I wholeheartedly agree with your point about compile times and have added it to my comment.
iOS doesn't actually emulate most of the system though, which is why it can run on so little RAM. Apple repurposes the shared components running on macOS to do the heavy lifting of iOS emulation. Their approach, in my opinion, is closer to a Docker container with a display than to a traditional emulator.
This is also why it's technically impossible to port the iOS emulator to Windows or Linux even if they were willing to give up their vendor lock-in.
I haven't worked with the iOS simulator for long, but I found some features the Android emulator offered missing in iOS. There was no installing apps (like WhatsApp, to test sharing) and the tooling for faking following a recorded or generated GPS path were either impossible for me to find or just not there. I also found that the "OS" inside the simulator felt bare-bones and incomplete whereas the Android emulator comes with the complete toolkit, including Google Play. iOS simulation is faster than Android emulation, but in my opinion that comes at a cost.
It's possible to do the same thing on Linux through Anbox, though that might not have all the same API's. The Android kernel is quite different from the Linux kernel it was once just a fork of and on Windows you'll never see the same level of integration with Android that iOS has.
Android Studio isn't necessarily that bad. On a very large project, my AS instance eats up, at the absolute worst, 4GB of RAM. Which, compared to all other IDEs is not that awful.
Gradle however will eat memory and balloon to 8GB on its daemon
>The biggest problem I have with Android development is that compiling even a small app takes over a minute in my 7700k.
Make sure incremental compilation is setup. For small changes, this means that recompiling is lower than 10 seconds.
In fact, you don't even need VS as part of the experience anymore – Jetbrains Rider has most of the Resharper features (including "extract class" in the latest version) in an IDE based on the IntelliJ platform. It feels much faster than VS + Resharper.
Why can't it be as simple as a bunch of files in a folder, a build file, a manifest, and an asset directory? That's what most apps need.
These are Google engineers we are talking about. The same people who bring you gcp. Why are you surprised.
I don't think it qualifies as speculation anymore to assert that Google has something really broken about it, organizationally, that keeps it from producing truly good software—and often not even decent software—in most of its projects, for some reason. Even very high-profile ones. There's not really any other explanation for how they consistently behave.
The rest of Google has other priorities though. Even gmail’s iOS app had pretty glaring bug that it couldn’t mark a message read.
Google docs fails to save at times. YouTube Kids is just an awful mess. Don’t let your kids even near it. Google Cloud isn’t as reliable as the other clouds. Google can’t do proper human support. They don’t believe in it. If you’re a small shop, going with Google for anything critical is just going to be a disappointment.
Google Search though. I have an insane amount of respect for their engineers who work on performance and reliability.
I also touch python once in a blue moon. It's always frustrating. To get anything done, I need to install python, then install pip, then make a virtual env, then use pip to install the libraries the project needs in the virtual env, then start the project. At this point, I realize the project does not work on the latest version of python, but on some specific version, and I need to throw away everything and start again. And each time I tell myself: "why wouldn't they write this obviously critical piece of information on the main page?"
I don't think one of the tech stacks is much better than the other. I think we just perceive the one we are knowldgeable in as better, for obvious reasons.
Oh, that's where the simple projects "start the project".
Even with wheels around, that's where you'll get an error message that eventually decodes as "There is no C-Compiler on this platform". And then you're installing clang or gcc. And make. And configure. And fuckit, just install build-essentials.
And then you start hunting C dependencies. Which I can because I have some experience building C, enough to never to it again. And then you start learning which link error with libpython indicates which minor version of python is actually required. And eventually you start looking into really weird hacks with chroots to be able to have multiple python-devel headers around. Or use containers to compile a python library.
Sorry. I like the language python. But installing python packages to do something... I don't know, it eventually hurt something inside me. I severely never want to deal with python in production anymore unless I can just globally install it in a container and stop caring.
Java tends to be tolerable. People tend to overuse maven beyond all repair, and gradle can be funky. But none of them compare to the hell python requires.
These days i spell that
This is ok-not-great; i’d prefer for python and pypi to put some official funding and weight behind one de-facto 517/518 build system and stabilize things a little. However this is python we’re talking about, so it’ll never happen.
With poetry init, the tool walks you through project setup
I could build the code in IntelliJ IDEA, but I couldn't for the life of me figure out how to actually run it to simply test it and play around with it. I can only concur there is something seriously wrong with the Java world/community. Perhaps it's too focused towards enterprise, where you can afford to have one person specialise in sitting at a desk, monitoring Wildfly?
Building a jvm project these days can be a matter of cloning the git repo and running `./gradlew build`.
It’s a real embarrassment to our industry.
Makes me want XML and Maven back; at least my IDE can guide me based on the schema files it parsed.
How many hours and thousands of lines of pointless tests have been wasted because of bad type systems - I really don't get the fuss about about Python, C++ was designed by a committee but python genuinely feels like it wasn't designed at all beyond the basic syntax (which I like)
But like most interpreted languages, the up-front friction is low, but it starts to buckle under it's own weight when a project reaches medium size.
A counterexample is the company when I worked for 8 years. They took Python very seriously. By the time I left, 4,000 developers were making 20,000 commits a week in a codebase of some 30,000,000 LOC.
This really rings true to me. I almost cringe when I have to explain how to do some of the most basic things to non android developers.
Aside from the dozens of libraries you need to include, and need to know where to find and what version is compatible with what, the tooling itself is an insurmountable mess for new developers. It's also not getting any simpler.
Like I was interviewing a guy for an Android role, and he was walking me through a pet project of his which consisted of literally one list view which updated it's contents to filter results out of an SQLite database as you type into a text field, and the project had literally dozens of files. It just made me sad.
I mean maybe there is something I don't understand, but the state of the field seems to be heavily driven by following what the "cool kids" are doing, and the tooling seems to have more to do with signaling that you're in the in-crowd than it has to do with actually delivering value.
Or you can pull in a library that seems to be popular and maintained and solves the problem that you have.
At least it's better than some other ecosystems, where it's "this thing is deprecated now. Nothing replaces it and you can't do similar functionality any other way, it's just deprecated." Or maybe I just haven't gotten to that part yet.
I precached but it still required internet access to get some maven deps for android build. Updating is full of hassles and gradle, as always, unexpectedly fails somewhere eg in "assembleDebug" step. Maybe some version mismatch and I am not in a situation to do clean installs that require GiBs of internet. And no guarantee it works even on clean install.
I have come to a conclusion that front end (web or app development) is a mess and it is not for me. Look at Go, or Rust to know how to keep tooling simple and straightforward.
> The compiler would say “Missing semicolon on line 427.” To which I’d reply “If you know what is missing, and you know where it is missing, why not add it back yourself? You useless piece of crap!”
How can you add a feature like this without any extra complexity?
It sounds great in theory but in practice most code depend on another piece of code. Most of the time blindly changing one line can introduce more bugs.
Using indentation for control flow was a bad decision, even if most modern IDEs now have good solutions for it.
Doing code formatting is fine; doing code formatting on lines from a checkout that I didn't change is bad. Yes, the file should be reformatted. But let me know before doing it, so I can make a formatting-only commit so it's easier to review when I put up the PR.
"Expected a colon here, found a <" (ascii-art pointer to the place) "did you forget to close a bracket here?" (ascii-art pointer to 12 lines above that, where, indeed you forgot to close a bracket.
It does this for semi-colons (they are not always required), closing brackets (maybe you are nesting something horrendously deep?) etceteras.
The idea, basically is "I see this is wrong. But I'm not the one to decide how to fix it for you, but here's a suggestion".
I love Rust for this.
1. Files are allowed to have different numbers of open & closed brackets. So who knows where the real error is? For all the compiler knows, you left that paren open deliberately in one file and forgot to include the paren-closing file?
2. C++ syntax generally lets you put anything anywhere -- the compiler doesn't seem to mind that I'm defining a new class literally inside the parentheses of a function call? Is that actually legal? Who knows. But I'm still a little confused... after opening that paren I almost immediately use too many closing braces -- why isn't that spotted immediately?
It was a complete nightmare trying to port code that compiled and ran perfectly well on the dept microvax when we all transitioned to Ultrix and Linux.
As a result of those months of pain, even thirty years later I’m a huge fan of strongly typed languages, compiling with -Wall and -Werror, and have a zero-warning policy.
If you’ve never gone through it, you wouldn’t understand...
When Gradle got popular the main competition was Maven which involves copy and pasting random pieces of XML from the internet, gave stack traces rather than clear error messages and didn't used to support incremental builds.
XML & Maven has the benefit of having a schema. This means that not only do all my pom.xml files look similar, but the IDE can do meaningful autocompletion and semantic checking for me. It’s verbose and ugly, but at least it’s consistent and has good tooling.
Gradle on the other hand is a Turing complete system, which just adds another layer of potential errors on top of Java compilation, which is the exact opposite of what I wanted. Now also all of my Gradle files are different and I have no idea why, and what the relative pros and cons of each style is.
Could Maven be improved? Sure. I’d kill for something like Cargo for Java. But I did not want to find myself debugging by build tool’s state because I used a setter wrong (true story).
Also, I don't see that this is a big deal when dealing with a declarative paradigm. In fact, cutting and pasting random bits of declarative code makes a lot of sense to me. You don't need to understand how it's doing what it's doing, only that it will.
I have yet to discover a situation where some custom thing I needed couldn't be handled with the Exec Plugin or a custom plugin, which are easy to write. The truth is that these uber-custom things are actually pretty rare if you stick to conventions.
Simple builds have simple config. Doing more complicated things means you need to learn how the tool works, and that can certainly take some time.
I'm really liking the new kotlin DSL, having great IDE support, really makes writing gradle scripts much more pleasant.
I do a fair bit of work on node based projects, and the building tooling in the node ecosystem is just so horrible in comparison.
Builds need Turing completeness surprisingly often. Build languages then expand to accommodate, with spaghetti disasters as the result.
“But it has to be accessible to new users and can’t be tied to just one language” said SBT as it jumped the shark with its .sbt files.
Sigh.
Developers get crap tools because developers won’t pay for tooling - if it’s not open source and free we don’t touch it outside of an enterprise environment. And Lo and behold, most tooling is either cobbled together by Enthusiasts, or as user friendly as enterprise ware usually is.
(There are, of course, shining exceptions to this, which is great)
Even when I'm writing Scala I prefer Maven to SBT, I just prefer declarative build tools to DSLs up in my grill.
And sbt is just bad all around on top of all this, and it should feel bad.
To be fair, this is due also to the fact that opensource tools are mostly guaranteed to outlive their developers. Should Microsoft go bankrupt tomorrow (don't laugh, it basically happened to SUN), most of their traditional tooling would disappear. In contrast, Gcc might be old and crusty, but it will go on forever like a cockroach.
I'm not sure i understand this argument
crap Linux because developers won’t pay for Linux
crap git because developers won’t pay for git
...that's clearly not the case, no? Every day we use a bunch of developer tools that are not just crap, but amazing and great to work with, and were built as open source. So I'm not sure about equating open source with crap experience.
As a side note, this is probably (intentionally or not) the same tactic that Microsoft used in the 00s to avoid competition: keep changing things fast so that anybody using your tool chain a) has to follow your lead to keep up, b) ends up with huge sunk cost, and c) (if they trust whoever's behind Gradle) keeps being reminded how much they innovate.
Not to mention that build config is probably the absolute last place you want a weird unreadable language nobody knows, because it tends to be touched so rarely that nobody builds up any familiarity with it.
Here's the javadoc: https://docs.gradle.org/current/javadoc/org/gradle/api/Proje...
If you switch to the Kotlin flavor of Gradle then this goes away. You just have to make the compiler happy then, same as for application code.
When you're designing an error message, don't just tell the user that something went wrong. The mere fact that they're getting an error message already conveys that. Instead, concentrate on telling them what is being expected or what they can do to fix it.
I thought the entire point of automatically generating boilerplate was that you could ignore it until you needed something other than the defaults. When all of that magically introduced complexity is wrong, why make me start with it in the first place?
I really wonder why are we letting this happen. Really
A similar thing to when I see a command or an API call that does what you want then says "deprecated" (with no clue of why or how to do that now). Sure, because nobody does this anymore right? (and I'm not talking about complicated stuff) Or the new function works in some mysterious way when the old one was straightforward
I mean, really
But it seems people are "moving fast, breaking things and who cares if it's broken? it works for me"
Hm, that is actually a point where (in my experience at least) the Java community tends to do pretty well: in nearly all cases where I see an API that is deprecated there is a comment that at least tells you what you should use instead. Additionally, "deprecated" usually means that it still works, which is a whole lot better than having it simply disappear.
In my experience, many of the Android methods marked as deprecated also contained docstrings to the new API and how to use it. In some cases it can even automatically insert the boilerplate code to do what the old, deprecated function did with the extra error handling for changes to the platform.
compile and implementation aren't the same thing. Depending on your use case, compile needs to be either changed to api or implementation. They aren't the same thing, so just a quick replace by the IDE would likely break more than it fixes. The problem is that most guides treat them as the same thing and make people think the compiler is being stupid for changing the word they need.
I can't speak for other projects, but for Android, where most of my deprecation struggles came from, the change was the result of changing requirements. Early Android was a wild west where every app could copy the contents of your SD card and upload it to their servers without even so much as a warning, where IMEI numbers were widely used as identifiers in databases for analytics and where permissions were more of theory than a practical requirement. Killing random apps was a permission any application could obtain, app databases appeared on your SD card which sometimes included credentials and secretly turning on cameras was easy to do by rendering the preview to a 1x1 pixel area. Screen hijacks were also commonly possible, causing major concern for apps for banking and such. Google had to retroactively restrict applications with new permission systems and applications often crashed without workarounds because the developers often never bothered with exception handling for stuff like file I/O. This isn't moving fast and breaking things, this is trying to fix fatal flaws in the design of a running train.
When I encounter deprecation, it's because the underlying design of the API I use has significantly changed, often for good reason. It's annoying when features turn from a simple function call to a complicated code structure, but there's often a good reason behind it. I just wish people would put those reasons in their docstrings and release notes instead of marking stuff as deprecated and leaving it at that.
It’s about being conscious about others time and the impact your work has on theirs.
They might be a good reason for changing “compile” to “implementation”, but it costs nearly nothing for the dev to add a specific rule that if “compile” is in the code, the compiler should show a link or point to the docs or explain how to solve it.
On the other side it’s painfully costly for anyone using that tooling to understand what’s happening, why the change, how to solve it. The end result is that a lot of inexperienced users will find a fix that works for them (like bulk replace of one for the other), and the end result tends to be a worse ecosystem for all.
> Why doesn’t Android Studio / Gradle / Whatever just go “Mate – you’ve used compile here – that won’t work. Want me to automatically update the syntax? It’ll probably be fine.”
But the machine can't make the decision, since it doesn't know the intent. The informed human in charge of the project does. What if there's automation, and tool ends up making the wrong decision? I bet that the author would be complaining about that instead.
Reading the Twitter threads that the author links to are quite illuminating, and it's surprising to me he feels it's showing him in a good light. It's an amazing display of both entitlement and intentional ignorance.
https://git-scm.com/book/en/v2/Customizing-Git-Git-Configura...
Actually built for Linux on my MBP.
Boom, all dependencies, and in seconds a perfect binary. I've had similar experiences with a number of projects, including huge projects like Firefox.
Like it all things in life, it varies. Some projects and toolsets are perilous mountains of crapitude. Others are just magically delightful.
As with the missing semicolon; the compiler can't be sure if that's a typo, so the line should end there, or you just really missed the semicolon only. It doesn't understand the code the way you do.
As for "Don’t make me think." - the whole software development is about thinking. Can't do any part on autopilot.
Sure, but I'd prefer to think about the problem that I'm solving, and not about which combination of packages I need to successfully compile and run the application.
I don't want to spend time manually upgrading dependencies, or syntax, especially if this is something that can be automated by build tools or IDEs.
If you were able to install everything, including the documentation, to your hard drive you never really needed anything else (which was good, because I didn't have internet access at home to begin with - too pricey).
You had high quality development and debugging tools, and then in MSDN you had this absolutely exhaustive, encyclopaedic documentation that covered every possible topic in depth, and a good enough search function that you could usually find what you were looking for without too much difficulty.
In some ways - not all ways - those were the days.
That’s not the role of a compiler, for good reason. I stopped reading the article after reading this line.
If anything, Javascript clients have the advantage of being able to bring your own fundamental abstractions since you're not stuck having to compile your abstraction to a narrow API like UIKit.
Web development gets the worst reputation because it's the only one most people have experience with.