Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Love Stole the Day
Nov 4, 2012
Please give me free quality professional advice so I can be a baby about it and insult you
Did a bunch of tutorials and am mostly through the official Rust book. Really liking the convenience of "cargo build" and the .toml file as opposed to cmake, which has been my White Whale for many years because I am dumb and bad. It feels like a compromise between Javascript's npm stuff and C/C++'s make files.

Adbot
ADBOT LOVES YOU

Love Stole the Day
Nov 4, 2012
Please give me free quality professional advice so I can be a baby about it and insult you
What do you guys recommend for GUI crates? I've heard good things about using GTK bindings for Rust but since I'm using Windows and MSVC it looks like I'd have to go out of my way to do everything in a separate IDE or whatever. Tried Googling it but I don't see any simple solution, but maybe I'm just bad and dumb.

I learned about the Rocket crate recently and think it might be a good exercise to try to do for a web project.

Love Stole the Day
Nov 4, 2012
Please give me free quality professional advice so I can be a baby about it and insult you
Did anyone itt ever post about ideas for projects to make or whatever? Because I'm looking through the popular crates on crates.io and trying to come up with simple stuff to make for my Github portfolio. Sorry if this is a dumb question.

Love Stole the Day fucked around with this message at 07:07 on Oct 26, 2017

Love Stole the Day
Nov 4, 2012
Please give me free quality professional advice so I can be a baby about it and insult you
The Rust youtube channel has just uploaded a bunch of lectures from some recent conference called Fosdem: https://www.youtube.com/channel/UCaYhcUwRBNscFNUKTjgPFiA/videos

Love Stole the Day
Nov 4, 2012
Please give me free quality professional advice so I can be a baby about it and insult you
Bevy, the game engine, came out with v0.7 recently. Now you can do animations and skeletal meshes with the glTF 3D format. :yotj:

Love Stole the Day
Nov 4, 2012
Please give me free quality professional advice so I can be a baby about it and insult you
Trying to figure out the right pattern to use here.



Am using a minimal HTTP client crate, called ehttp, to try and grab data.

It forces us to use a Callback method, so of course we should avoid entering Callback Hell somehow.

In other languages, we'd use Reactive programming and so it looks like we should just add the rxrust crate... but even so, the fetch method doesn't return anything and even so, we don't have any clean way to convert that callback into an Observable/Mono/etc.

Using a Future seems appropriate here, but it seems like a round peg and square hole scenario.

Am currently trying to use Arc's, but probably it's being used incorrectly.

Love Stole the Day
Nov 4, 2012
Please give me free quality professional advice so I can be a baby about it and insult you
My goal is to do this in a non-blocking way, while also avoiding callback hell.

If I run this method in a separate thread, then even if I use fetch_blocking in that separate thread I still have the usual race condition issue where I need to access its result eventually.

The choice of crate here is mostly because it's the most minimal and versatile: it will work for both native and wasm, while not being dependent on larger crates with features I don't need (most things such as reqwest, hyper, etc, have tokio in their dependency tree... and I don't need all of those features to just do a simple call).

It sounds like backpressure (i.e. ReactiveX) is what I need, so maybe I can't avoid it. I just wonder whether there's a cleaner way to do avoid callback hell while still being able to return something useful.

Running the method in a different thread and then returning a Future of its result might make sense, but I would need to share it across threads and poll the Future it until it's available. Just feels weird, is all.

Love Stole the Day
Nov 4, 2012
Please give me free quality professional advice so I can be a baby about it and insult you
Because I'm bad and I suffer from Java Brain

Love Stole the Day
Nov 4, 2012
Please give me free quality professional advice so I can be a baby about it and insult you

fritz posted:

Had a failure of intuition today.

code:
struct Dummy {
   pub data : Vec<f64>
}

let mut data : Vec< (usize, Dummy) > = Vec::new();
let mut table : HashMap< usize, Dummy > = HashMap::new();
// data gets filled somewhere along the way
for (i,j) in data {

   table.entry(i)
   .and_modify(|v| *v = j)
   .or_insert(j)
}
rustc errors at the or_insert because j is already moved in the and_modify. I'm confused because I would have thought that it wasn't possible for both code paths to execute, i.e. if it goes thru .and_modify, it won't go thru .or_insert, and vice versa.

Looks like the problem is the = sign: because Dummy doesn't/can't #[derive(Copy, Clone)] due to the Vec<> inside of it, it defaults to using the = sign as an opportunity to move ownership of j into the FnOnce, because the FnOnce owns V, which is the thing it's assigning ownership. The Programming Rust book explains it on p90 using Strings instead of structs.

edit: since it's functional, even though only one code path will end up happening, the lambda closure (FnOnce) stuff will still act as its own scope and be entitled to owning anything that gets moved into it.

Love Stole the Day
Nov 4, 2012
Please give me free quality professional advice so I can be a baby about it and insult you

gonadic io posted:

With stuff like that, ditching the functional constructs and using an explicit match is usually enough to fix it these days, because the borrow checker can see through them in a way it can't for closures . Or just clone or copy.

And there's a special matching pattern syntax you can use for those situations where you just want to map something that cannot be Copy+Cloned. You just add an @ symbol. https://doc.rust-lang.org/book/ch18-03-pattern-syntax.html#-bindings

Love Stole the Day
Nov 4, 2012
Please give me free quality professional advice so I can be a baby about it and insult you

notwithoutmyanus posted:

Well I haven't seen any other languages using :: or <> like that. In that sense I was more used to JavaScript with function.thing

MyStruct::my_function is like MyClass.prototype.my_function you probably already know this idk

Love Stole the Day
Nov 4, 2012
Please give me free quality professional advice so I can be a baby about it and insult you
Looking for examples of good abstractions and separation of concerns to use for web dev use cases (e.g. CRUD). Preferably involving `actix_web`.

Only good example from arewewebyet.com is this one: https://github.dev/LemmyNet/lemmy however their abstractions (such at in api_routes_http.rs) don't seem to be well enough organized that I'd want to replicate that in my own project.

Am feeling it out as I go, but it'd be helpful if there was a good, clean demonstration from which to learn.

Love Stole the Day
Nov 4, 2012
Please give me free quality professional advice so I can be a baby about it and insult you

gonadic io posted:

Don't use actix web if you can help it imo
It's pretty abandoned. We still have the legacy of actix itself at work and it's painful every day.

I know tokio is very popular, but all of the back-end web frameworks which leverage it seem to be immature, 0.x versions. What's the mature, production-ready, back-end web framework to use, if not actix_web?

Love Stole the Day
Nov 4, 2012
Please give me free quality professional advice so I can be a baby about it and insult you
Okay, axum it is. Sounds good!

What about the abstractions you all use to organize everything for your web services? Are there any open source examples worth following?

Love Stole the Day
Nov 4, 2012
Please give me free quality professional advice so I can be a baby about it and insult you
Here's what I came up with. Please flame me, starting with the lack of unit tests and functional tests: https://github.com/wanderrful/myaxumserv

Readme has a sequence diagram to show the separation of concerns, along with sample curl requests to run, if you build and run it locally

Love Stole the Day
Nov 4, 2012
Please give me free quality professional advice so I can be a baby about it and insult you

Love Stole the Day posted:

Here's what I came up with. Please flame me, starting with the lack of unit tests and functional tests: https://github.com/wanderrful/myaxumserv

Readme has a sequence diagram to show the separation of concerns, along with sample curl requests to run, if you build and run it locally

FYI I've updated this with dependency injection and I like how it's starting to come together. This is kind of snowballing into a fully-featured thing. Just need to add opentelemetry stuff, configuration stuff, testing stuff, some downstream calls, API versioning, maybe a Swagger codegen thing, etc... and it'll be almost like an enterprise-level service!

Haven't been able to find any demo CRUD web service projects on Github using this "tech stack", so I like to think I'm doing something useful for the community here.

Love Stole the Day
Nov 4, 2012
Please give me free quality professional advice so I can be a baby about it and insult you

prom candy posted:

This is cool! Not a Rust-specific critique but organizationally it kinda feels like there aren't clear boundaries between the responsibilities of Resources and Managers. If I was building a framework from scratch I'd probably omit Managers but provide examples of how to call encapsulated service-layer code if necessary. Just my two cents.

Yeah I agree with you as it is right now: the Manager takes the request DTO and returns the response DTO, whereas the Resource is only validating the request and dealing with the outcome of the operation.

So, the Manager is responsible for orchestrating everything, and the Resource is responsible for validation and assembling the final response (i.e. if the manager fails for some reason, then the Resource would be mapping the error to whatever error response and HTTP error code is needed).

There is probably a better pattern I should use here (edit: maybe wrap the Manager with a "before Aspect" and an "after Aspect"? But I think Aspects for side-effects, not validation and exception->error mapping). As-is, the code doesn't have validation or error handling and so I agree with you that the Resource doesn't have much reason to exist right now.

I feel like if we move the "validation" and "exception -> error response" responsibilities into the Manager, then it will have too much stuff to do. I think the Manager should just focus on the operation and nothing else.

Controller-Service-Repository/Delegate are the analogous concepts in Spring Boot (Java) world to which I'm more accustomed.

Love Stole the Day fucked around with this message at 22:55 on Jun 23, 2023

Love Stole the Day
Nov 4, 2012
Please give me free quality professional advice so I can be a baby about it and insult you

prom candy posted:

My thought is more that the Controller-type resource (actually Resource in this case) should be responsible for taking in a request and returning a response and anything beyond that is potentially overly prescriptive. A Manager pattern could be a recommendation ("Help, my Resources are doing too much!") but from my general experience working with web frameworks if I had to pick between one object or method that's doing a bit too much vs. two objects or methods that appear to be tag teaming the same simple task. That said I've been finding myself preferring longer functions in code in general lately and that may not be a majority opinion. A lot of the stuff that I took as gospel about programming from OOP gurus like short methods and SRP I've started to discover can actually just make it really hard to find where the actual behaviour you're looking for is.

Again just my opinion.

I agree with you about the Manager pattern. I should've put more thought into the naming of these concepts. Maybe I should just stick to the Controller-Service-Delegate/Repository naming convention for this separation of concerns.

What you describe as a Controller-type resource, I suppose, would be the `UserRouter`, because it has those async functions which do exactly that. Maybe I should turn that into some kind of Factory, but I'm not sure if that'd add any value because there is only one use case such a concept will ever need to support. `UserRouter::new()` looks like a Builder or Factory pattern, though. I should try refactoring it into a `tower_service::Service` type and see how that looks.

--

By the way, side question: what crate do you all recommend for configuration management? I can do it manually with `serde` to open and serialize a YAML or JSON file, of course, but I worry about the more general use cases an enterprise service would need and think it'd be bad to implement that from scratch for myself.

Love Stole the Day
Nov 4, 2012
Please give me free quality professional advice so I can be a baby about it and insult you
Here, this might be better for what you're trying to do:

code:
struct Container {
    cache: std::collections::HashMap<u32, String>,
}

impl Container {
    pub fn get(&mut self) -> &str {
        let id = 42;
        let default = "foo";
        let mut output = "";

        if self.cache.contains_key(&id) {
            output = self.cache.get(&id).unwrap();
        } else {
            self.cache.insert(id, String::from(default));
            output = default;
        }

        return output;
    }
}

Love Stole the Day
Nov 4, 2012
Please give me free quality professional advice so I can be a baby about it and insult you
Today I learned you can yeet in Rust:



https://www.youtube.com/watch?v=BgCXrf_SG2E&t=110s

Love Stole the Day
Nov 4, 2012
Please give me free quality professional advice so I can be a baby about it and insult you

Rocko Bonaparte posted:

I am late to the party, but I saw a lot of talk of stuff being "managers." That's always been a cringe sign for me that I don't know where my abstractions really are. I can't think of a better term but I know there's something in common, so it becomes a manager.

I still suck at the traits stuff and how abstraction is done in Rust, so I don't have any better thing to say about that. Even if I did, the situations are all contextual and independent of each other. I just wanted to flag a potential code smell.

Agreed! Naming things is hard

Adbot
ADBOT LOVES YOU

Love Stole the Day
Nov 4, 2012
Please give me free quality professional advice so I can be a baby about it and insult you
To translate what we would do in Java world, the way to solve this problem is to move all of these empty dataclass structs into their own separate Crate package, call it an "interface", and then tell that entire crate to ignore that, by doing `#![allow(dead_code)]` (with the exclamation point) at the crate's root file. That way, your project will have the important stuff, and all those empty dataclass structs will sit alone in their own special place... which you access by specifying it as a dependency in your Cargo.toml file

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply