• 1 Post
  • 93 Comments
Joined 11 months ago
cake
Cake day: August 7th, 2023

help-circle
  • I kinda get where he is coming for though. AI is being crammed into everything, and especially in things where they are not currently suited to be.

    After learning about Machine learning, you kind realize that unlike “regular programs” that ML gives you “roughly what you want” answers. Approximations really. This is all fine and good for generating images for example, because minor details being off of what you wanted probably isn’t too bad. A chat bot itself isn’t wrong here, because there are many ways to say the same thing. The important thing is that there is a definite step after that where you evaluate the result. In simpler ML you can even figure out the specifics of the process, but for the most part we evaluate what the LLM said or if the image is accurate to our expectations. But we can’t control or constrain the output to exactly our needs, because our restrictions largely are just input in a almost finished approximation engine.

    The problem is, that companies take these approximation engines, put them in their product and consider their output fact. Like Ai chatbots doing customer support, and make up facts like the user that was told about rules that didn’t exist for an airline, or the search engines that parrot jokes or harmful advice. Sure you and I might realize that these things come from a machine that doesn’t actually think about it’s answers, but others don’t. And throwing a “*this might be wrong because its AI” on it is not an acceptable waiver of accountability.

    Despite this, I use chatgpt and gemini a lot to help me program, they get a lot of things wrong but also do great. It’s a great tool, exactly because I step in after the approximation step, review and decide. I’m aware of the limits. But putting these things in front of “users” without a review step means you are advertising that you are either unaware of this flaw, or just see the cost-benefit analysis and see that if noting else it’ll generate interest during the hype.

    There is a huge potential, but throwing AI into a situation where facts are needed when it’s only making rough guesses, is the wrong way about it.













  • Faster is 90% of the reason for me. It’s just so much more smoother, i can find things faster and do things faster. ButI also use a lot of the developing features, creating/converting properties, functions and such. Probably also in VS but i’m not that used to them. I’m also used to quickly jumping around in the code by going to definitions. Rider is nicer here, because VS is clunky and feel like there is two system competing to do that in VS with Resharper. Not to mention the stutters and slow program.

    I like the git integration better in Rider. I think VS solved it, but selecting a remote branch wasn’t actually getting you that branch before you pulled the changes manually. To the point where i pushed a brand new branch, someone else selected that in VS, and when they ran the build it didn’t work at all because it didn’t have all the changes?? It also did not auto-fetch, so it showed you were up to date with the remote despite not being… Apart from that, it makes swapping branches a lot easier. VS gets angry with uncommited changes. And while i wasn’t a huge fan of the new diff view, diffs without newline changes and such is a killer feature, especially for someone that got a new editorconfig but not the entire codebase refactored… (because, too busy to do such a large change)

    The biggest downside to Rider is hot-reloading of XAML. Rider does not support that for .NET at least. It’s a bit of a bummer since VS allows some very rapid iteration solving layouting issues.

    Just the last week, I have had memory issues where Rider eats up to 10 GB of ram and then starts stuttering after being open for more than a day. I just installed the latest update that hoepfully fixed that. Rider also sometimes just decides not to run one or more programs in a multi-launch config, particularly the first time after starting. That’s a bit annyoing.

    I do not really like the database integration, but we also have a stupid oracle database and the way to handle that is a whole other story.


  • Our main motivator was, and is, that manual testing is very time consuming and uninteresting for devs. Spending upwards of a week before a release because the teams has to setup, pick and perform all featue tests again on the release candidate, is both time and money. And we saw things slip through now and then.

    Our application is time critical, legacy code of about 30 years, spread between C# and database code, running in different variations with different requirements. So a single page may show differently depending on where it’s running. Changing one thing can often affect others, so for us it is sometimes very tiresome to verify even the smalles changes since they may affect different variants. Since there is no automated tests, especially for GUI (which we also do not unit test much, because that is complicated and prone to breaking), we have to not only test changes, but often check for regression by comparing by hand to the old version.

    We have a complicated system with a few intergrations, setting up all test scenarios not only takes time during testing, but also time for the dev to prepare the instructions for. And I mentioned calculations, going through all motions to verify that a calculated result is the same between two version is a awfully boring experience when that is exaclty something automated tests can just completely take over for you.

    As our application is projected to grow, so does all of this manual testing required for a single change. So putting all that effort into manual testing and preparation can intsead often just be put on making tests that check requirements. And once our coverage is good enough, we can only manuall test interfaces, and leave a lot of the complicated edge cases and calculcation tests to automated tests. It’s a bit idealistic to say automated tests can do everything, but they can certainly remove the most boring parts.


  • I’m on a similarly sized team, and we have put more effort into automated testing lately. We got an experienced person in on the team that knows his shit, and is engaged in improving our testing. But it’s definiely worth it. Manual testing tests the code now, automated testing checks the code later. That’s very important, because when 5 people test things, they aren’t going to test everything every time as well as all the new stuff. It’s too boring.

    So yes, you really REALLY should have automated testing. If you have 20 people, I’d guess you’re developing on something that is too large for a single person to have in-depth knowldge of all parts.

    Any team should have automated test. More specifically, you should have/write tests that test “business functionality”, not that your function does exactly what it is supposed to do. Our test expert made a test for something that said “ThisCompentsDisplayValueShouldBeZeroWhenUndefined” (Here component is something the users see, and always exepct to have a value. There is other components that might not show a value).

    And when I had to interact with the data processing because another “component” did not show zero in an edge case. I fixed the edge case, but I also broke the test for that other component. Now it was very clear to me that I also broke something that worked. A manual tester would maybe have noticed, but these were seperate components, and they might still see 0 on the thing that broke becase they had the value 0. Or simply did not know that was a requirement!

    We just recently started enforcing unit tests to be green to merge features. It brings a lot more comfort, especially since you can put more trusting changing systems that deal with caluclations, when you know tests check that results are unchanged.


  • I’m in the MPC-HC gang on Windows. Just so much more practical than other players. The main selling point was that full-screen the controls go away once you move the cursor off them, it was amazing. And no waiting for subs to be processed like VLC had to back then, never turned back so don’t know if that is still a thing.



  • Ah, so I’m actually cheating with the pointer reading, i’m actually making a clone of Arc<T> without using the clone()… And then dropping it to kill the data. I had assumed it just gave me that object so I could use it. I saw other double buffer implementations (aka write one place, read from another palce, and then swap them safely) use arrays with double values, but I wasn’t much of a fan of that. There is some other ideas of lock free swapping, using index and options, but it seemed less clean. So RwLock is simplest.

    And yeah, if I wanted a simple blog, single files or const strings would do. But that is boring! I mentioned in the other reply, but it’s purely for fun and learning. And then it needs all the bells and whistles. Writing html is awful, so I write markdown files and use a crate to convert it to html, and along the way replace image links with lazy loading versions that don’t load until scrolled down to. Why, because I can! Now it just loads from files but if I bother later i’ll cache them in memory and add file watching to replace the cached version. Aka an idea of the issue here.


  • Thanks for the great reply! (And sorry for that other complicated question… )

    Knowing that &str is just a reference, makes sense when they are limited to compile time. The compiler naturally knows in that case when it’s no longer used and can drop the string at the appropriate time. Or never dropped in my case, since it’s const.

    Since I’m reading files to serve webpages, I will need Strings. I just didn’t get far enough to learn that yet… and with that ‘Cow’ might be a good solution to having both. Just for a bit of extra performance when some const pages are used a lot.

    For example code, here’s a function. Simply take a page, and constructs html from a template, where my endpoint is used in it.

    pub fn get_full_page(&self, page: &Page) -> String {
            self.handler
                .render(
                    PageType::Root.as_str(),
                    &json!({"content-target": &page.endpoint}),
                )
                .unwrap_or_else(|err| err.to_string())
        }
    

    Extra redundant context: All this is part of a blog I’m making from scratch. For fun and learning Rust, and Htmx on the browser side. It’s been fun finding out how to lazy load images, my site is essentially a single paged application until you use “back” or refresh the page. The main content part of the page is just replaced when you click a “link”. So the above function is a “full serve” of my page. Partial serving isn’t implemented using the Page structs yet. It just servers files at the moment. When the body is included, which would be the case for partial serves i’ll run into that &str issue.


  • Sorry, but a long and slightly complicated question, for a hypotetical case.

    I wanted to serve pages in my blog. The blog doesn’t actually exist yet (but works locally, need to find out how I can safely host it later…), but lets assume it becomes viral, and by viral i mean the entire internet has decided to use it. And they are all crazy picky about loading times…

    I haven’t figued out the structure of the Page objects yet, but for the question they can be like the last question:

    #[derive(Clone)]
    pub struct Page<'a> {
        pub title: &'a str,
        pub endpoint: &'a str,
    }
    

    I wanted to create a HashMap that held all my pages, and when I updated a source file, the a thread would replace that page in the mapping. It’s rather trivial of a problem really. I didnt find out if I could update a mapping from a thread, so I decided to make each value something that could hould a page and have the page object replaced on demand. It made somewhat sense since I don’t need to delete a page.

    There is a trivial solution. And it’s just to have each HashMap value be a RwLock with an Arc holding my large string. No lagre string copies, Arc make it shared, and RwLock is fine since any number of readers can exist. Only when writing is the readers locked. Good enough really.

    But I heard about DoubleBuffers, and though, why can’t I have a AtomicPointer to my data that always exist? Some work later and I had something holding an AtomicPointer with a reference to an Arc with my Page type. But it didn’t work. It actually failed rather confusingly. It crashed as I was trying to read the title on my Page object after getting it from the Arc. It wasn’t even any thread stuff going on, reading once works, the next time it crashed.

    struct SharedPointer<T> {
        data: AtomicPtr<Arc<T>>,
    }
    
    impl<T> SharedPointer<T> {
        pub fn new(initial_value: T) -> SharedPointer<T> {
            SharedPointer {
                data: AtomicPtr::new(&mut Arc::new(initial_value)),
            }
        }
    
        pub fn read(&self) -> Arc<T> {
            unsafe { self.data.load(Relaxed).read_unaligned() }.clone()
        }
    
        pub fn swap(&self, new_value: T) {
            self.data.store(&mut Arc::new(new_value), Relaxed)
        }
    }
    
    #[test]
    pub fn test_swapping_works_2() {
        let page2: Page = Page::new("test2", "/test2");
        let page: Page = Page::new("test", "/test");
        let entry: SharedPointer<Page> = SharedPointer::new(page.clone());
    
        let mut value = entry.read();
    
        assert_eq!(value.title, page.title);
        value = entry.read();
        assert_eq!(value.title, page.title);
    
        entry.swap(page2.clone());
    
        let value2 = entry.read();
        assert_eq!(value2.title, page2.title);
        assert_eq!(value.title, page.title);
    }
    

    This has undefined behavior, which isn’t too surprising since I don’t understand pointers that much… and I’m actually calling unsafe code. I have heard it can produce unexpected error outside it’s block. I’m just surprised it works a little. This code sometimes fails the second assert with an empty string, crashes with access violation, or one time it gave me a comparison where some of it was lots of question marks! My best understanding is that my Page or it’s content is moved or deallocated, but odd that my Arc seems perfectly fine. I just don’t see the connection between the pointer and Arcs content causing a crash.

    I may just be doing the entire thing wrong, so sticking with RwLock is much better and safer since there is no unsafe code. But I seek to know why this is so bad in the first place. What is wrong here, and is there a remedy? Or is it just fundamentally wrong?