heya, I'm designing an API that requires users to implement approximately 12 "big" functions. Some of these functions use common types, e.g. the return type of one function may be a parameter to another.
Two questions:
- Are there runtime performance, size, or other implications between the following designs?
- Intuitively, which design would be more understandable / maintainable from an API consumer point of view?
Design 1: All in one
// Design 1: All in one
#[async_trait]
pub trait ItemSpec {
type Error: std::error::Error;
type State: Serialize + Deserialize;
type Diff: Serialize + Deserialize;
type Data<'d>: Data<'d>;
async fn fn_1(Self::Data) -> Result<Self::State, Self::Error>;
async fn fn_2(Self::Data) -> Result<Self::State, Self::Error>;
async fn fn_3(Self::State, Self::State) -> Result<Self::Diff, Self::Error>;
async fn fn_4(Self::State, Self::State, Self::Diff) -> Result<bool, Self::Error>;
async fn fn_5(Self::State, Self::State, Self::Diff) -> Result<(), Self::Error>;
// ..
async fn fn_12(Self::State, Self::State, Self::Diff) -> Result<(), Self::Error>;
}
Design 2: Split into separate traits (wall of text)
pub trait ItemSpec {
type Error: std::error::Error;
type State: Serialize + Deserialize;
type Diff: Serialize + Deserialize;
type Data<'d>: Data<'d>;
type SubTrait0: SubTrait0<Error = Self::Error, Output = Self::State>;
type SubTrait1: SubTrait1<Error = Self::Error, State = Self::State, Diff = Self::Diff>;
type SubTrait2: SubTrait2<Error = Self::Error, State = Self::State, Diff = Self::Diff>;
}
#[async_trait]
pub trait SubTrait0 {
type Error: std::error::Error;
type Output;
type Data<'d>: Data<'d>;
async fn fn_1(Self::Data) -> Result<Self::Output, Self::Error>;
async fn fn_2(Self::Data) -> Result<Self::Output, Self::Error>;
}
#[async_trait]
pub trait SubTrait1 {
type Error: std::error::Error;
type State: Serialize + Deserialize;
type Diff: Serialize + Deserialize;
async fn fn_3(Self::State, Self::State) -> Result<Self::Diff, Self::Error>;
async fn fn_4(Self::State, Self::State, Self::Diff) -> Result<bool, Self::Error>;
async fn fn_5(Self::State, Self::State, Self::Diff) -> Result<(), Self::Error>;
}
#[async_trait]
pub trait SubTrait2 {
type Error: std::error::Error;
type State: Serialize + Deserialize;
type Diff: Serialize + Deserialize;
async fn fn_6(Self::State, Self::State) -> Result<Self::Diff, Self::Error>;
async fn fn_7(Self::State, Self::State, Self::Diff) -> Result<bool, Self::Error>;
async fn fn_8(Self::State, Self::State, Self::Diff) -> Result<(), Self::Error>;
}