I have 3 Vec<T>
structs that shared the same function:
Vec<RawTransaction>
Vec<RawCashTransaction>
Vec<RawAdjustmentTransaction>
All three shared the same VerifyableRaw
traits and the verify()
function. I use the verify()
function check the validity of the content of that array/vector.
Here's my implementation. As you can see, all of them shared the same basic fields, namely: date
, total
, credit
, and debit
.
My problem is: since I use the same fields that those structs shared, the verify()
function is the same for all of them. In verify
function, I need to access the date
, total
, credit
, and debit
fields so I just copy and paste the code from one implementation to another.
My question is: Can I refactor this trait implementation into a single function definition ?
I found out that I need to repeat myself each time I need to use verify()
function and VerifyableRaw
trait to another struct that needs it
pub struct RawTransaction {
pub date: Option<NaiveDate>,
pub contact_name: String,
pub total: Option<Decimal>,
pub credit: String,
pub debit: String,
}
pub struct RawCashTransaction{
pub tr_type: String,
pub date: Option<NaiveDate>,
pub contact_name: String,
pub total: Option<Decimal>,
pub credit: String,
pub debit: String,
}
pub struct RawAdjustmentTransaction{
pub date: Option<NaiveDate>,
pub info: String,
pub total: Option<Decimal>,
pub credit: String,
pub debit: String,
}
Here's my trait implementation:
#[async_trait]
pub trait VerifyableRaw {
async fn verify(&self, cid: String, db: Database) -> Result<bool, Err>;
}
#[async_trait]
impl VerifyableRaw for Vec<RawTransaction> {
async fn verify(&self, cid: String, db: Database) -> Result<bool, Err> {
/// .... this function is the same for all three
let data = &self; // access the vector
for (i, row) in data.iter().enumerate() {
// enumerate each item in this vector
let date = row.date.unwrap(); // check if the date is valid, etc
let de = row.debit.clone(); // check if this value is valid
let cr = row.credit.clone(); // check if this value is valid
// ... another process here ...
}
}
}
#[async_trait]
impl VerifyableRaw for Vec<RawCashTransaction> {
async fn verify(&self, cid: String, db: Database) -> Result<bool, Err> {
/// .... this function is exactly the same as RawTransaction above
}
}
#[async_trait]
impl VerifyableRaw for Vec<RawAdjustmentTransaction> {
async fn verify(&self, cid: String, db: Database) -> Result<bool, Err> {
/// .... this function is exactly the same as RawTransaction above
}
}