lawlorslaw
03/31/2023, 8:32 AMImpl
Imp
prefix or suffix for the concrete implementation and leave the Interface without any prefix or suffix ... mean while other devs use an I
prefix or suffix to denote the Interface and they leave the concrete implementation without any prefix or suffix.
For example: interface UserRepository
and class UserRepositoryImpl: UserRepository
vs
interface IUserRepository
and class UserRepository: IUserRepostiory
which version is better or is there a better alternative?
My question also applies to LocalDataSource
and RemoteDataSource
interface vs concrete implementation naming.s3rius
03/31/2023, 8:51 AMI
isn't conventionally used for interfaces in the Android world
(2) We don't usually prefix anything with its type anymore. (There was a time where people would use iNumOfItems
or strUserName
because IDEs weren't that great yet.)s3rius
03/31/2023, 8:57 AMLogger : ILogger
seems sensible if you want everyone to use Logger
, with an option to write their own if needed. xxImpl
implies that its an internal implementation which shouldn't be handled directly).lawlorslaw
03/31/2023, 9:25 AMlawlorslaw
03/31/2023, 9:25 AMlawlorslaw
03/31/2023, 9:25 AMCLOVIS
03/31/2023, 9:44 AMImpl
and make it private. Provide a factory named after the interface.
• If it is important for downstream users, give it a proper name!
Everything visible from outside your module should have a proper name.lawlorslaw
03/31/2023, 9:46 AMCLOVIS
03/31/2023, 9:47 AMlawlorslaw
03/31/2023, 9:47 AMlawlorslaw
03/31/2023, 9:48 AMCLOVIS
03/31/2023, 9:48 AMlawlorslaw
03/31/2023, 9:48 AMCLOVIS
03/31/2023, 9:49 AMlawlorslaw
03/31/2023, 9:49 AMCLOVIS
03/31/2023, 9:51 AMlawlorslaw
03/31/2023, 9:52 AMlawlorslaw
03/31/2023, 9:52 AMlawlorslaw
03/31/2023, 9:52 AMCLOVIS
03/31/2023, 9:53 AMlawlorslaw
03/31/2023, 9:54 AMlawlorslaw
03/31/2023, 9:54 AMCLOVIS
03/31/2023, 9:54 AM// domain/src/…
interface UserRepository {
suspend fun getAll(): List<User>
}
// mongodb/src/…
class MongoUserRepository {
override suspend fun getAll(): List<User> { … }
}
lawlorslaw
03/31/2023, 9:55 AMlawlorslaw
03/31/2023, 9:55 AMlawlorslaw
03/31/2023, 9:56 AMCLOVIS
03/31/2023, 9:56 AMCLOVIS
03/31/2023, 9:56 AMlawlorslaw
03/31/2023, 9:57 AMlawlorslaw
03/31/2023, 9:57 AMlawlorslaw
03/31/2023, 9:58 AMCLOVIS
03/31/2023, 9:59 AMinterface UserRepository {
suspend fun getAll(): List<User>
}
private class UserRepositoryImpl(
private val source: DataSource,
) {
override fun getAll(): List<User> =
source.getAllUsers()
}
fun userRepositoryFor(source: DataSource) = UserRepositoryImpl(source)
CLOVIS
03/31/2023, 10:00 AMCLOVIS
03/31/2023, 10:00 AMlawlorslaw
03/31/2023, 10:02 AMlawlorslaw
03/31/2023, 10:04 AMlawlorslaw
03/31/2023, 10:05 AMCLOVIS
03/31/2023, 10:08 AMUser
for tests, you probably have just a data class User
, right?
If the repository just delegates to the data source, and the data source is the thing that has the logic, then you never need to mock the repository, you can mock the data source instead.
I don't see the factory pattern in your code snippet above.It's the top-level
userRepositoryFor
function. There is no need to create classes for factories in Kotlin.lawlorslaw
03/31/2023, 10:11 AMuseRepositoryFor
need to define in the same Kotlin file as class UserRepositoryImpl
?lawlorslaw
03/31/2023, 10:13 AMCLOVIS
03/31/2023, 10:13 AMlawlorslaw
03/31/2023, 10:15 AM