howtocodeit / hexarch

The complete code for "Master Hexagonal Architecture in Rust"
MIT License
47 stars 9 forks source link

How do I write traits implementation on multiple files? #4

Open frederikhors opened 1 month ago

frederikhors commented 1 month ago

Thank you again for this amazing project!

Is there a way to write the below impl on multiple files?

impl<R, M, N> BlogService for Service<R, M, N>
where
    R: BlogRepository,
    M: BlogMetrics,
    N: AuthorNotifier,
{
    async fn create_author(&self, req: &CreateAuthorRequest) -> Result<Author, CreateAuthorError> {
        let result = self.repo.create_author(req).await;

        // ...

        result
    }
}

The issue is I have many (hundreds) methods and as you can imagine is difficult to write them on a single file.

If I write in a file

impl<R, M, N> BlogService for Service<R, M, N> {
    async fn create_author(&self, req: &CreateAuthorRequest) -> Result<Author, CreateAuthorError> {}
}

and in another file:

impl<R, M, N> BlogService for Service<R, M, N> {
    async fn delete_author(&self, req: &DeleteAuthorRequest) -> Result<Author, DeleteAuthorError> {}
}

I get from the compiler the error Multiple implementations for the same trait.

I thought it would be a solution to use:

impl<R, M, N> Service<R, M, N> {
    async fn create_author(&self, req: &CreateAuthorRequest) -> Result<Author, CreateAuthorError> {}
    async fn delete_author(&self, req: &DeleteAuthorRequest) -> Result<Author, DeleteAuthorError> {}
}

but this way if you forget to write a trait BlogService's method the compiler doesn't warn you and I don't know other issues with this.

Another way could be to call a method for each of them, like:

impl<R, M, N> BlogService for Service<R, M, N> {
    async fn create_author(&self, req: &CreateAuthorRequest) -> Result<Author, CreateAuthorError> {
        create_author(&self, req: &CreateAuthorRequest)
    }
    async fn delete_author(&self, req: &DeleteAuthorRequest) -> Result<Author, DeleteAuthorError> {
        delete_author(&self, req: &DeleteAuthorRequest)
    }
}

but really?!?!

What do you think?

frederikhors commented 1 month ago

And what @TmLev think too... of course!

TmLev commented 1 month ago

If I needed that, I'd do the latter way you described:

use sibling_module::method_implemented_in_another_file;

impl Trait for T {
    fn method(&self) {
        method_implemented_in_another_file(&self)
    }
}