Given this dummy code, which has an if statement with a verbose code (imagine this is a really verbose if statement), I decide to create a util function to make my code cleaner. When I choose to create a util function, should it be implemented as an interface or can I implement the concrete function instead? I may use this same function again in other class.
Dummy code:
export class UserRepository {
constructor (private readonly database: DatabaseProtocol) {}
async findUserByEmail (data: Record<string, any>): Promise<IUser | null> {
const userCollection = this.database.collection('users')
if (Object.keys(data).length === 0) return null
const user = await userCollection.findOne({ email: data.email })
return user
}
}
Concrete implementation:
export class UserRepository {
constructor (private readonly database: DatabaseProtocol) {}
async findUserByEmail (data: Record<string, any>): Promise<IUser | null> {
const userCollection = this.database.collection('users')
if (isEmpty(data)) return null
const user = await userCollection.findOne({ email: data.email })
return user
}
}
Interface implementation:
export class UserRepository {
constructor (
private readonly database: DatabaseProtocol,
private readonly isEmpty: IsEmptyProtocol
) {}
async findUserByEmail (data: Record<string, any>): Promise<IUser | null> {
const userCollection = this.database.collection('users')
if (this.isEmpty(data)) return null
const user = await userCollection.findOne({ email: data.email })
return user
}
}
Private method:
export class UserRepository {
constructor (
private readonly database: DatabaseProtocol
) {}
async findUserByEmail (data: Record<string, any>): Promise<IUser | null> {
const userCollection = this.database.collection('users')
if (this.isEmpty(data)) return null
const user = await userCollection.findOne({ email: data.email })
return user
}
isEmpty (data: Record<string, any>): boolean {
return Object.keys(data).length === 0
}
}
Which option above would be considered the best practice?