• 7 posts
  • 78 comments
Joined 3 years ago
Cake day: September 7th, 2023
  • The number-one frustration, cited by 45% of respondents, is dealing with “AI solutions that are almost right, but not quite,” which often makes debugging more time-consuming. In fact, 66% of developers say they are spending more time fixing “almost-right” AI-generated code.

    Not surprising at all. When you write code, you’re actually thinking about it. And that’s valuable context when you’re debugging. When you just blindly follow snippets you got from some random other place, you’re not thinking about it and you don’t have that context.

    So it’s easy to see how this could lead to a net productivity loss. Spend more time writing it yourself and less time debugging, or let something else write it for you quickly, but spend a lot of time debugging. And on top of it all, no consideration of edge cases and valuable design requirement context can also get lost too.

  • I’m a slow adopter of new technologies like AI LLMs. My reasoning is that if it turns out to actually be a good product, then it will eventually prove itself, and the early adopters can be the “beta testers” so to speak. But if it turns out to be a bad product, then I won’t have wasted my time on something that isn’t worthwhile.

    Maybe a day comes when I start using these tools, but they clearly just aren’t all that useful in their current form. In all honesty, I’m pretty sure that they will never be useful enough for me to consider them worth learning, but definitely not so today.

  • I wrote a program that scanned object files (compiled from a large C++ project) to see how they were interdependent. It was pretty useful for detecting cycles in the shared libraries that we were compiling from them, but the biggest benefit was it enabled me to very easily rewrite the build system from scratch.

    It was surprisingly simple - most ELF parsers can read a file and dump the symbol tables in them. (In this context, a symbol means a defined function, so if a C/C++ source file has int main() in it, the corresponding .o file will have a main symbol in it.) They also include information about which symbols are defined in the .o file, as well as which symbols it depends on which are undefined. This allows you to figure out a dependency graph, which you can easily visualize using graphviz or use to autogenerate build files for CMake or any other build system you may wish to use.

    In my case, I wrote this kind of program twice in two separate jobs. Both of them had a very janky build system using custom Makefiles. I used this program to rewrite the build systems in CMake. The graphviz dependency graphs are also just generally helpful to have as project documentation. CMake can do this natively, by the way - here’s the documentation for it: https://cmake.org/cmake/help/latest/manual/cmake.1.html#cmdoption-cmake-graphviz

  • Yeah, I’ve seen a lot of those videos where they do things like {} + [], but why would anyone care what JS does in that case? Unless you’re a shit-ass programmer, you’re never going to be running code like that.

    By this same logic, memory safety issues in C/C++ aren’t a problem either, right? Just don’t corrupt memory or dereference null pointers. Only “a shit-ass programmer” would write code that does something like that.

    Real code has complexity. Variables are written to and read from all sorts of places and if you have to audit several functions deep to make sure that every variable won’t be set to some special value like that, then that’s a liability of the language that you will always have to work around carefully.

  • I don’t even know where to start to make vim or neovim do all that. If it can’t do that seamlessly and just as well, vimlike editors will never be a replacement for a proper IDE. It’s fast, capable single file and small scope editor for me.

    If you’re interested in learning how to do it, I found this guide extremely helpful for getting started. it’s in both blog and video format, and it shows how to install Lazy (a package manager for vim), and which plugins to install to get LSP working (which is what would provide all the hotkeys that you were mentioning above).

    It’s definitely not a task for the faint of heart, but I found it very rewarding once I figured out how to work with the plugin systems because it’s so powerful and easy to customize. I found it helpful to just watch the video a few times to see everything working, then slowly started building up my own configuration (which was a bit more minimal than the linked guide I provided - I only installed about 30-40% of the plugins he listed on that page).

    Another alternative is Lazyvim, which provides an out-of-the-box configuration experience for you. It installs a lot of plugins and most things should work out of the box with very little configuration. It is a massive beast though, but still pretty good for a first start.

  • I completely agree. For basic things, it is very good. But for productivity, it leaves a lot to be desired, because they (the developers) simply cannot accept that different people work in different ways and they refuse to accommodate that… I prefer environments that can be adapted to my workflows - I don’t want an environment that forces me to adapt to it. And it doesn’t help that extensions tend to break on upgrades.

  • Interesting, I was not aware of libdecor. Sorry to hear that it degraded your experience - it really sucks when things like that happen. For what it’s worth, I have seen some interesting themes which could be a reasonable solution to that problem - basically, they made the titlebar very thin or completely missing, except in the area where the window buttons were located, which were enlarged. Not sure which window manager they were made for though - I think it was either xfwm or openbox.

    But in any case, this is the problem with CSD - it doesn’t really have a complete, holistic vision. It’s great that they’re trying to be innovative, but then they very quickly run into problems like the one described by the Factorio developer above. So now they’re in a very awkward position that simply cannot meet everyone’s needs.

    And yet, we never had this problem before they went on their quixotic CSD journey - that’s why many people think it was a really bad idea.

  • I don’t understand what change has to do with it. The problem is, lots of people have used it, tried it, criticized it, and been ignored. It has nothing to do with change.

    Change is fine, as long as the new version is better than the old one. Look at how KDE evolved. Sure, there were a lot of people that didn’t like the 3 -> 4 transition (not me personally, I loved KDE4), but very few people lament what KDE has become today and it certainly is very different from what it was during the 3.x days.

    Personally, yes, I and a lot of other users have read why GNOME does not implement SSDs, and frankly their reasoning is not very convincing, but I don’t think it matters that much. The fact is, users don’t care why it’s not implemented - if they don’t like it, they’re just going to criticize the project and that’s just why GNOME is so widely hated.

    Trust me, I don’t want to hate GNOME - I wish I could just make my life easy and use it as a sane default. But if it’s not good, then I can’t do that - and by “good”, I mean how I define a good desktop, not whatever creative definition they dreamed up.

  • Another thing, he confirms something I was worried about, in his comments on parallelism / Python without the Global Interpreter Lock (aka GIL): Some developments in the language serve rather the big companies, than the community and open source projects. For example, lock-less multi-threading in Python serves mostly the largest companies, while having little value for small projects.

    Absolutely agree. The significance of the GIL is heavily overstated in my opinion. There’s a narrow set of use-cases where it matters, ie. if you must use threads and something like multiprocessing or a message queue (ie. Celery) doesn’t do what you need. These are pretty rare circumstances, from my experience at least.

  • One principle I try to apply (when possible) comes from when I learned Haskell. Try to keep the low-level logical computations of your program pure, stateless functions. If their inputs are the same, they should always yield the same result. Then pass the results up to the higher level and perform your stateful transformations there.

    An example would be: do I/O at the high level (file, network, database I/O), and only do very simple data transformations at these levels (avoid it altogether if possible). Then do the majority of the computational logic in lower level, modular components that have no external side effects. Also, pass all the data around using read-only records (example: Python dataclasses with frozen=True) so you know that nothing is being mutated between these modules.

    This boundary generally makes it easier to test computational logic separately from stateful logic. It doesn’t work all the time, but it’s very helpful in making it easier to understand programs when you can structure programs this way.

  • Interesting, I had never heard of ccache before, though yes, all good build systems (CMake, Ninja, etc.) should cache intermediate object files.

    But the projects I was working on were so large that even binary and unit test executables were so large that even they would take ~20 seconds to link. You can’t use caching to alleviate that buildtime cost unfortunately.

  • I think it’s just because it is always recommended as an “easy” language that’s good for beginners.

    The only other thing it has going for it is that it has a REPL (and even that was shit until very recently), which I think is why it became popular for research.

    If that’s the case, then why didn’t Javascript take its place instead? It’s arguably even better at Python in both of those areas…

  • Sure, but as with all things, it can depend on a lot of factors. All code needs some degree of testing, though one could certainly argue that Python needs more than Java and Java needs more than Rust/Haskell/etc. So you could argue that the productivity gain of using Python is offset by the productivity loss of extra testing. It’s still hard to say which one wins out in the end.

  • Python’s type system is dramatically better than Javascript’s though. Try doing things like '' + True and Javascript will do incredibly stupid things. Python will just give you a type error. Also, look at things like == vs === in Javascript as well. That’s the biggest reason why Typescript replaced it overnight. Python has found a better balance between productivity and error safety.

    In my opinion, the biggest shortcoming of Python’s dynamic typing system is that you need to have very thorough test coverage to be sure that your code doesn’t have semantic errors (a lot more than, say, Java). It has gotten better with the introduction of type hints, those I don’t have much experience with them, so I can’t say how much.