Skip Navigation

InitialsDiceBearhttps://github.com/dicebear/dicebearhttps://creativecommons.org/publicdomain/zero/1.0/„Initials” (https://github.com/dicebear/dicebear) by „DiceBear”, licensed under „CC0 1.0” (https://creativecommons.org/publicdomain/zero/1.0/)SY
Posts
16
Comments
573
Joined
2 yr. ago

  • Yeah, package maintainers should have their dependencies figured out. "Managing dependencies is too hard" is a distro packager's problem to figure out, and isn't a user problem. When they solve it and give you a package, you don't need to figure it out anymore.

    Plus, frequent breaking changes in library APIs is a big no-no, so this is avoided whenever possible by responsible authors. Additionally, authors relying on libs with shitty practices is also a no-no. But again, you don't need to worry about dependences because your packager figured this out, included the correct files with working links, and gave them to you as a solved problem.

  • A package typically includes the program and its data inside the package. It's not just an install script. Imagine if Chrome's MSI installer was simply a wrapper that also downloaded the browser. Imagine if there was a vulnerability with this, and it downloaded and installed something else. Since the package didn't include the program files, it wouldn't be able to tell if they were genuine. It only fetched the MSI, which was a download that initially passed the expected checksum (if it even does that).

    Additionally, file lists help ensure that programs and packages don't conflict with one another. What if you wanted Chromium and Chrome at the same time. Can you do that? Simply wrapping an MSI doesn't guarantee that. Perhaps there are conditionals in an installer that includes a vendored library under some circumstances, which would make them conflict.

    What about package removals? Some programs leave a bunch of junk behind in their uninstaller. Typically, since packages very often contain their own files, they simply delete their files when they're being upgraded or removed. If a package manager puts full trust in an MSI to always be exactly correct, then it loses complete control over correctly managing file removals.

    I could go on and on, with more examples, but "run this binary installer" is the Wild West of putting software on your system. This is mostly the status quo on Windows, but this is a very poor standard. Other operating systems have solved this problem with proper packaging for decades.

    When building a package from sources, it makes sense to wrap installers, but then you produce a package that is typically distributed by a mirror. These packages would then by downloaded by you, and contain the source of truth that is trusted to be what it is and that it'll do what it's supposed to do without any doubts to consistency and security.

  • You can only teach someone Linux if they have a desire to learn it. If they don't want to learn it, then they might learn that it's "bad" or "weird" compared to mainstream OSes, which would be working backwards.

  • All you need is the TOTP secret, and it will generate OTPs. If you enter the secret in another TOTP app, you'll also get OTPs. Here's a Ruby lib that will render OTPs from a secret, for example: https://github.com/mdp/rotp

    For an Android TOTP tool, I like FreeOTP+. You can even use it for Steam OTPs.

  • You don't typically have permissions "become defective" or need them to be "repaired" in a Linux system. Nearly all system files, with their permissions, are included in packages. Everything else should be considered user data.

    If you logged in as root and did something dumb, you could attempt to fix the permissions by reinstating packages.

  • Yup :) Everything in Ruby inherits Object, too. It's a really neat language, and when you get accustomed to it, you might wonder why some other languages aren't written like it.

    For the 0 value being truthy, consider that Ruby is a dynamic language. Imagine if you asked a user how many motorcycles they own. If they answer, you'll have an Integer. If they don't, you'll have nil, from NilClass. 0 is just as valid of an answer as 2, so you can do something like this:

     
        
    raise NoResponse unless motorcycles
    
    save_motorcycles(motorcycles)
    
      
  • Ruby has a method for this :)

     
        
    [1] pry(main)> vars = ["one", "two", nil, "three"]
    => ["one", "two", nil, "three"]
    [2] pry(main)> vars.compact
    => ["one", "two", "three"]
    
      

    In Ruby, 0 and "" is truthy, so this would be a little different than the Python interpretation. You could filter with #select, but you'd typically write your code around this instead.

  • Imagine your "code" as English sentences. If it is hard to read, you might rephrase it. If something is getting long and drawn out, use paragraphs (methods and functions). At the end of the day, the easier it is to read, the better, unless there's a performance cost that's worthy of considering.

    Like the top-level comment suggests, you should comment your methods. I would go one step further and use a standard comment format. I like Ruby, so immediately, I think YARDoc. With a YARDoc comment, you define what it does, the parameter types and descriptions, what it returns, possible exceptions that could be returned, etc.

    Even better, by using standardized comments, not only does this make it easier to read by you and others, but most of the time, you get documentation rendered for free. For example, here is a library I wrote:

    And here is the automatically-generated HTML documentation:

    More specifically, here's some YARDoc for a method:

    And here is the generated documentation from this comment:

    This style of auto-generated documentation is available for pretty much all mature languages, and I highly recommend that you hit the ground running with them 👍