はじめに
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(),
};
}
振り返り
やけくそで何とかなったけど、原因不明でもやもやする。