• 0 Posts
  • 365 Comments
Joined 1 year ago
cake
Cake day: June 17th, 2023

help-circle
  • Why do we need tests to be understandable by any human. IMO tests that go to that degree do so by obscuring what logic is actually running and make it harder as a developer to fully understand what is going on. I would rather just keep tests plain and simple with as few abstractions around them as possible.

    Cypress cy.get(‘h1’).contains(‘Result’)
    Playwright await expect(page.getByTitle(‘Result’)).toHaveCount(1)
    Testing library expect(screen.getByTitle(/Result/i)).toBeTruthy()

    We can nit pick about syntax here and I prefer the cypress one as it immediately tells me what it is doing and I am not even familiar with those frameworks but:

    UUV Then I should see a title named “Result”

    That tells me nothing about what it is actually doing. How is the framework meant to interpret that or similar things? It is imprecise and I have no way to validate it will do what I expect it should. I do not trust AI or LLMs enough to translate that into a workable test. Even if it works for simple situations like this how does it grow to far more real and complex test cases?

    It would be one thing to use a LLM to generate a test for you that you can inspect - but to generate it probably on every run quite likely without being able to see what it did? Um No thanks. Not with the current state of LLMs.

    At least I assume it is LLM based as there is no other way to do this as far as I am aware, though they dont seem to mention it at all.



  • Of these 25 reasons, most apply to a lot of languages and are far from Java exclusive or even java strong points. Pick any mainstream language and you will hit most of the benefits it lists here. With quite a few being almost meaningless. Like this:

    Java/JVM/JIT can achieve runtime optimization on frequently run code, especially on something that’s running as a service so that you avoid the overheads from JVM startup times.

    Compiled languages generally don’t need a JIT or to be optimized at runtime as they are compiled and optimized at compile time. And most language that don’t have a runtime like Javas already run faster than Java without its heavy startup time. Language with JITs are generally interpreted languages which have these same benefits as java lists here. Though do often suffer from other performance issues. But really at the end of the day all that really matters is how fast the language is and how good its startup times are. Java is not ahead of the pack in either of these regards and does not do significantly better then other languages in its same class (and often still drastically sucks for startup time).

    Or

    Much of a company’s framework can be stable Java, with Scala or Clojure-backed business logic.

    Many languages you can embed other languages inside. Nothing really special about scala or clojure here except that they work well with java. And I don’t really see this as a major benefit as most places I see dont separate their core code and business logic into different languages.

    And the remaining issues that are more java specific are:

    Java was one of the first mainstream GC strongly typed OOP languages. So it got its niche.

    Java has been one of the main programming languages taught in colleges and universities in the last few decades.

    Java’s Legacy Migration: Many banks in particular migrated legacy systems to Java in the early 2000’s when it was getting a lot of popularity and the industry was collectively in the midst of a huge OOP fever dream.

    Which all paint a picture - it was popular long ago and taught in universities and lots of business pushed it when back in the day. And now it is hard to move off it.

    And lastly:

    Oracle

    What? How is this a point? If anything this should be a massive negative.

    Not exactly 25 reasons to pick java in financial enterprise.


  • When I change devices or hit file size limits, I’ll compress and send things to my NAS.

    Whaaatt!?!!? That sounds like you don’t use git? You should use git. It is a requirement for basically any job and there is no reason to not use it on every project. Then you can keep your projects on a server somewhere, on your NAS if you want else something like github/gitlab/bitbucket etc. That way it does not really matter about your local projects, only what is on the remote and with decent backups of that you don’t need to constantly archive things from your local machine.


  • Did you read the article at all?

    “Putting all new code aside, fortunately, neither this document nor the U.S. government is calling for an immediate migration from C/C++ to Rust — as but one example,” he said. “CISA’s Secure by Design document recognizes that software maintainers simply cannot migrate their code bases en masse like that.”

    Companies have until January 1, 2026, to create memory safety roadmaps.

    All they are asking for by that date is a roadmap for dealing with memory safety issues, not rewrite everything.



  • For someone only on chapter 7, this is ok. I would not call it idiomatic but you have not gotten to the Error Handling in chapter 9 yet. I would probably hold on getting feedback on error handling until you have gotten to that point.

    But the TLDR of it is rust has two forms of errors, unrecoverable errors in the form of panic and recoverable ones in the form of returning a Result. In this case you have opted for panicking which IMO is the wrong choice for something that is expected to fail - and http requests and parsing external data is expected to fail (even if only some of the time). Networks fail all the time, servers go down, send back wrong responses and many other things.

    Do you really want to crash your program every time that happens? Probably not - at least not at this level. Instead you likely want to return an error from this function and let the caller deal with it instead as they will likely have more context as to what to do with it rather than in the leaf functions of where the error originates.


    But all that is probably for once you have read through chapter 9. For now it is good to know that when you have the pattern

    match foo {
        Ok(value) => value,
        Err(err) => panic!("it broke! {}", err),
    }
    

    You can generally replace that with a call to expect instead:

    foo.expect("it broke")
    

    Or just unwrap it if you dont need to add more context for what ever reason.


  • It doesn’t technically have drivers at all or go missing. All supporting kernel modules for hardware are always present at the configuration level.

    This isn’t true? The Linux kernel has a lot of drivers in the kernel source tree. But not all of them. Notably NVIDIA drivers have not been included before. And even for the included drivers they may or may not be compiled into the kernel. They can and generally are compiled with the kernel but as separate libraries that are loaded at runtime. These days few drivers are compiled in and most are dynamically loaded depending on what hardware is present on the system. Distros can opt to split these drives up into different packages that you may or may not have installed - which is common for less common hardware.

    Though with the way most distros ship drivers they don’t tend to spontaneously stop working. Well, with the exception of Arch Linux which deletes the old kernel and modules during an upgrade which means the current running kernel cannot find its drivers and stops dynamically loading them - which often results in hotplug devices like USB to stop working if you try to plug them in again after the drivers get unloaded (and need a reboot to fix as that boots into the latest kernel that has its drivers present).


  • I don’t get it? They seem to be arguing in favor of bootc over systemd because bootc supports both split /usr and /usr merge? But systemd is the same. There is really nothing in systemd that requires it one way or another even in the linked post about systemd it says:

    Note that this page discusses a topic that is actually independent of systemd. systemd supports both systems with split and with merged /usr, and the /usr merge also makes sense for systemd-less systems.

    I don’t really get his points for it either. Basically boils down to they don’t like mutable root filesystem becuase the symlinks are so load bearing… but most distros before use merge had writable /bin anyway and nothing is stopping you from mounting the root fs as read-only in a usr merge distro.

    And their main argument /opt and similar don’t follow /usr merge as well as things like docker. But /opt is just a dumping ground for things that don’t fir the file hierarchy and docker containers you can do what you want - like any package really nothing needs to follow the unix filesystem hierarchy. I don’t get what any of that has to do with bootc nor /usr merge at all.


  • TLDR; yes it does affect security. But quite likely not by any meaningful amount to be worth worrying about.

    Any extra package you install is extra code on your system that has a chance to include vulnerabilities and thus could be an extra attack vector on your system. But the chances that they will affect you are minuscule at best. Unless you have some from of higher threat model then I would not worry about it. There are far more things you would want to tackle first to increase your security that have far larger effects than a second desktop environment being installed.


  • Creating functions is IMO not the first thing you should do. Giving variables better names or naming temporaries/intermediate steps is often all you really need to do to make things clearer. Creating smaller functions tends to be my last resort and I would avoid it when I can as splitting the code up can make things harder to understand as you have to jump around more often.


  • Comments are not always a waste of time, but comments that repeat or tell you what the code is doing (rather than why) are a waste. For legacy code you generally don’t have comments anyway and the code is hard to read/understand.

    But if you can understand the code enough to write a comment you can likely refactor the code to just make it more readable to start with.

    For code that does not change generally does not need to be read much so does not need comments to describe what it is doing. And again, if you understand it enough to write a comment to explain what it is doing you can refactor it to be readable to begin with. Even for mathematical equations I would either expect the reader to be able to read them or link to documentation that describes what it is in much more detail to name the function enough that the reader can look it up to understand the principals behind it.


  • And they were arguing the same - just renaming the property rather than reusing it. You should only have one not both but naming them differently can make it clear which one you have.

    But here I am arguing to not have either on the user object at all. They are only needed at the start of a request and should never be needed after that point. So no point in attaching them to a user object - just verify the username and password and pass around user object after that without either the password or hash. Not everything needs to be added to a object.


  • Worse, refactors make comments wrong. And there is nothing more annoying then having the comment conflict with the code. Which is right? Is it a bug or did someone just forget to update the comments… The latter is far more common.

    Comments that just repeat the code mean you now have two places to update and keep in sync - a pointless waste of time and confusion.


  • When is the hashed password needed other than user creation, login or password resets? Once you have verified the user you should not need it at all. If anything storing it on the user at all is likely a bad idea. Really you have two states here - the unauthed user which has their login details, and an authed user which has required info about the user but not their password, hashed or not.

    Personally I would construct the user object from the request after doing auth - that way you know that any user object is already authed and it never needs to store the password or hash at all.



  • and how can I make it easier for them.

    I am wary of this. It is very hard to predict what someone else in the future might want to do. I would only go so far as to ensure nothing I am doing will unnecessarily block a refactor later on but I would avoid trying to add or abstract things in ways that make the current code harder to read because you think it might be easier for someone to add to in the future.

    I have needed, far too many times, to strip out some unused abstraction to do something that abstraction was never intended to allow because someone was trying to save me time and predict what might happen to the code in the future and got it completely wrong. It is far easier to add an abstraction to simple code later on when it actually helps then to try and figure out what the abstraction is and remove it when it is found to be wrong.


  • nous@programming.devtoProgramming@programming.devSelf-documenting Code
    link
    fedilink
    English
    arrow-up
    5
    arrow-down
    2
    ·
    19 days ago

    This is abuse of the separation of concerns concepts IMO. You have taken things far too far many made it far less readable overall. The main concern here is password validation - and the code already separated this out from other code. By separating out each check you are just violating another principal - locality of behavior which says related things should be located close to each other. This makes things far easier to read and see what is actually going on without needing to jump through several classes/functions of abstraction.

    We need to stop trying to break everything down into the smallest possibly chunks we can. It is fine for a few lines of related code to live in the same function.