Skip to content

Instantly share code, notes, and snippets.

@vicaba
Created December 3, 2023 09:40
Show Gist options
  • Save vicaba/cb01dce0c297f940e46d0f12bac6b032 to your computer and use it in GitHub Desktop.
Save vicaba/cb01dce0c297f940e46d0f12bac6b032 to your computer and use it in GitHub Desktop.
Liskov Substitution Principle in Scala
case class User(name: String, email: String)
val dummyUser = User("Dummy", "[email protected]")
// Not using LSP
object NotUsingLsp {
trait UserRepository {
def insert(user: User): Int
def read(id: Int): User
}
class MysqlUserRepository extends UserRepository {
def insert(user: User): Int = ???
def read(id: Int): User = ???
}
class MongoDbUserRepository extends UserRepository {
def insert(user: User): Int = ???
def read(id: Int): User = throw new Exception("This Mongo doesn't support read")
}
class MyController(userRepository: UserRepository) {
userRepository.read(1)
userRepository.insert(dummyUser) // 1. Will the insert work?
// 2. If the injected repository is a MysqlUserRepository: we are good!
// 3. If the injected repository is a MongoDbUserRepository: exception.
// 4. Same interface, but: sometimes it works, sometimes it doesn't...
}
}
// Using LSP
object UsingLsp {
// 1. We can seggregating interfaces, so we have more flexibility in the composition
trait WriteUserRepository {
def insert(user: User): Int
}
trait ReadUserRepository {
def read(id: Int): User
}
class MysqlUserRepository extends WriteUserRepository with ReadUserRepository {
def insert(user: User): Int = ???
def read(id: Int): User = ???
}
class MongoDbUserRepository extends WriteUserRepository {
def insert(user: User): Int = ???
}
class MyController(
readUserRepository: ReadUserRepository,
writeUserRepository: WriteUserRepository
) {
readUserRepository.read(1)
writeUserRepository.insert(dummyUser)
// 2. We are seggregating interfaces, so we have more flexibility in the composition
}
// 3. Or we can use intersection types! Here, the only valid implementation is Mysql
class AnotherMyController(readAndWriteUserRepository: ReadUserRepository & WriteUserRepository) {
readAndWriteUserRepository.read(1)
readAndWriteUserRepository.insert(dummyUser)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment