2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

RustのCake Pattern実装で発生した謎の事象

Posted at

はじめに

Rust の DI を考える –– Part 2: Rust における DI の手法の整理と言うすごい記事を見て、自分でもRustのCake Patternを実装してみた。併せてモジュール分割をしたところ、なぜか実装しているtraitを参照できない事象が発生した。

実装結果: cake_pattern

実装の概要

記事にある内容をディレクトリ分割して実装しただけ。traitの名前とかもそのまま。

.
├── Cargo.toml
└── src
    ├── domain
    │ ├── data
    | | └── database.rs 
    │ ├── di
    | | └── app_module.rs 
    │ ├── entity
    | | └── user.rs 
    │ ├── repository
    | | └── user_repository.rs 
    │ ├── service
    | | └── user_service.rs 
    │ ├── data.rs
    │ ├── di.rs
    │ ├── entity.rs
    │ ├── repository.rs
    │ └── service.rs
    └── main.rs

AppModuleにProvidesとかのtraitを実装させてmainから呼び出す想定

AppModuleの実装
impl Database for AppModule {}
impl UserRepository for AppModule {}
impl UserService for AppModule {}

impl ProvidesDatabase for AppModule {
    type T = Self;
    fn database(&self) -> &Self::T {
        self
    }
}

impl ProvidesUserRepository for AppModule {
    type T = Self;
    fn user_repository(&self) -> &Self::T {
        self
    }
}

impl ProvidesUserService for AppModule {
    type T = Self;
    fn user_service(&self) -> &Self::T {
        self
    }
}
mainからの呼び出し
fn main() {
    let app = AppModule {};
    let user = app.user_service().find_user("100".to_string());
    match user {
        Ok(Some(user)) => HttpResponse::Ok().json(user),
        Ok(None) => HttpResponse::NotFound().finish(),
        Err(_) => HttpResponse::InternalServerError().finish(),
    };
}

謎の事象

一見よさげに見えるが、実際にビルドすると下記エラーが発生する

error[E0599]: no method named `user_service` found for struct `AppModule` in the current scope
  --> src/main.rs:18:20
   |
18 |     let user = app.user_service().find_user("100".to_string());
   |                    ^^^^^^^^^^^^ method not found in `AppModule`
   |
  ::: src\domain\di\app_module.rs:5:1
   |
5  | pub struct AppModule;
   | -------------------- method `user_service` not found for this struct
   |
  ::: src\domain\service\user_service.rs:31:8
   |
31 |     fn user_service(&self) -> &Self::T;
   |        ------------ the method is available for `AppModule` here
   |
   = help: items from traits can only be used if the trait is in scope
help: trait `ProvidesUserService` which provides `user_service` is implemented but not in scope; perhaps you want to import it
   |
1  + use crate::domain::service::user_service::ProvidesUserService;
   |

app_module.rsでAppModuleにProvidesUserServiceを実装しているのに、なぜか認識されていない。

回避

やけくそでProvidesUserServiceの実装をmainに移したらなぜかビルド通った。

use crate::domain::service::{UsesUserService, ProvidesUserService};

impl ProvidesUserService for AppModule {
    type T = Self;
    fn user_service(&self) -> &Self::T {
        self
    }
}

fn main() {
    // Cake Pattern
    let app = AppModule {};
    let user = app.user_service().find_user("100".to_string());
    match user {
        Ok(Some(user)) => HttpResponse::Ok().json(user),
        Ok(None) => HttpResponse::NotFound().finish(),
        Err(_) => HttpResponse::InternalServerError().finish(),
    };
}

振り返り

やけくそで何とかなったけど、原因不明でもやもやする。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?