Transfer an struct instance from a struct to an other, but move error

Hi everyone,

First post on this forum, and first post at all in the Rust community, so empathize :sweat_smile:

I came from Java, and I am trying to do a clean architecture in Rust.

You could see what I have already done here : https://github.com/Azel-ytof/rust-clean-architecture-example

But the project do not compile ! :sob:

Indeed, I think that in Interactor (the usecase) the OutpuMessage must take ownership of the UserEntity. And the presenter must take ownership of OutputMessage, so that ViewModel take ownership of UserEntity, wich is contained by OutputMessage and passed to the ViewModel in the Presenter sucess or error function.

It may be confusing like that, but if you take a loot at the Github repository, you may understand.

So finally, I found that I must implement 'Clone' on UserEntity, but next a lot of search, I have read that it is not a best practice.
I have read too that a '&str' in a struct is when the value could be change, and with a 'String', the goal is that the value not changed.

So, what are the best practices ? Keep String and put Clone ? Change to &str ? Keep String but don't give ownership, but just give references ?

Sorry for my english, I have tried to be clear as possible.
I can try to explain in other way if you don't understand what I tried to explain and ask :slight_smile:

You should typically only have one "owned" copy of your UserEntity at any time. If you only want to refer to an existing UserEntity, store it by reference (or Rc or some other means) in the location referencing it:

pub struct AddUserOutputMessage<'a> {
    user: Option<&'a UserEntity>
}

If you want a new entity based on another entity, or plan on modifying a UserEntity, store it by value and use Clone instead.

1 Like

Hi and thanks for your answer.

I have follow your advice and done it with Rc.
It now works !!! :partying_face:

Thanks a lot ! :grin:

If you have a bit of time, could you take a look at the code and tell me if i do not respect some best practices ?

I would recommend reorganizing your crates a bit. Depending on what you like best, you can either keep your crates separate and put your them into a workspace or just have them all be modules within one crate. I've forked your repo and made two branches as examples.

Organized as a workspace with a root package:
https://github.com/J-M0/rust-clean-architecture-example/tree/workspace-root-package

Organized as a workspace without a root package:
https://github.com/J-M0/rust-clean-architecture-example/tree/workspace-no-root

Organized as modules:
https://github.com/J-M0/rust-clean-architecture-example/tree/modules

Given how you have your Java example laid out, I think you will prefer the first workspace layout.

1 Like

Thanks a lot !

In fact, I prefer the second example.
Indeed, the goal of clean architecture is to allow multiple applications to call usecases.

In my simple example, I have written a batch application, but you can have a webservice application, or website, etc...

I see that you rename 'mod.rs' files. I have seen 'mod.rs' while browsing internet for help. It may be an old version ?
I also see that you delete 'cargo.lock'. These files are not usefull to keep a coherant environment between multiple developers ?

You're welcome!

Yes, in Rust 2018 using mod.rs files to define modules is discouraged in favor of naming the files with the module name and putting and submodules in a directory of the same name.

https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-clarity.html#no-more-modrs

No, Cargo.lock is still important for keeping a consistent environment. The ones I deleted simply are not used when in a workspace. If you look in the Cargo Book you will find the following (emphasis mine):

Key features

The key points of workspaces are:

  • All packages share a common Cargo.lock file which resides in the workspace root .
  • All packages share a common output directory, which defaults to a directory named target in the workspace root .
  • The [patch] , [replace] and [profile.*] sections in Cargo.toml are only recognized in the root manifest, and ignored in member crates' manifests.

You will notice that I still kept the Cargo.lock in the root directory. That file will be shared by all of the packages in the workspace, making sure that if any member packages depend on the same external crate they will both get the same version of that external crate.

For the 'mod.rs', that's why I did not read it in the Rust book :sweat_smile:

For the 'Cargo.lock', yeah, now I remember what I have read before.
I think that is just because I have try something and forget to clean the directory.

Again, thank you for your explanations and you help :grin:

(Could we force close topic, or we must wait 3 months ?)

We just have to wait if we're done with this topic. Slightly off topic though, I noticed there might be something wrong with your git configuration. It appears that you have your username and email address switched in your commits.

Yep, I have try to update Github properties, but it does not apply :confused:
So I gave up

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.