Skip to content

Instantly share code, notes, and snippets.

@cjnevin
Last active November 29, 2017 01:08
Show Gist options
  • Save cjnevin/2f7c17f3ee973707f675cfa4c55e7b4e to your computer and use it in GitHub Desktop.
Save cjnevin/2f7c17f3ee973707f675cfa4c55e7b4e to your computer and use it in GitHub Desktop.
Login UseCase/Repository/Service setup
//: Domain
struct User {
let firstName: String
let lastName: String
}
struct LoginUseCase {
enum Error: Swift.Error {
case invalidCredentials
case invalidResponse
}
struct Request {
let username: String
let password: String
}
struct Response {
let user: User
}
enum Result {
case success(Response)
case failure(Error)
}
let repository: LoginRepositoryType
func login(with request: Request, completion: @escaping (Result) -> ()) {
repository.login(with: request.username, password: request.password, completion: { (user, error) in
guard let user = user else {
guard let error = error as? Error else {
completion(Result.failure(.invalidResponse))
return
}
completion(Result.failure(error))
return
}
completion(Result.success(.init(user: user)))
})
}
}
protocol LoginUseCaseProviderType {
func makeLoginUseCase() -> LoginUseCase
}
protocol LoginRepositoryType {
func login(with username: String, password: String, completion: @escaping (User?, Error?) -> ())
}
//: Platform
protocol NetworkType { }
struct Network: NetworkType { }
protocol LoginStorageType { }
struct LoginStorage: LoginStorageType { }
struct LoginUseCaseProvider: LoginUseCaseProviderType {
let repository: LoginRepositoryType
func makeLoginUseCase() -> LoginUseCase {
return LoginUseCase(repository: repository)
}
}
struct LoginRepository: LoginRepositoryType {
private let network: NetworkType
private let storage: LoginStorageType
init(network: NetworkType, storage: LoginStorageType) {
self.network = network
self.storage = storage
}
func login(with username: String, password: String, completion: @escaping (User?, Error?) -> ()) {
completion(User(firstName: "first", lastName: "last"), nil)
}
}
protocol LoginRepositoryProviderType {
func makeRepository() -> LoginRepositoryType
}
struct LoginRepositoryProvider: LoginRepositoryProviderType {
private let network: NetworkType
private let storage: LoginStorageType
init(network: NetworkType, storage: LoginStorageType) {
self.network = network
self.storage = storage
}
func makeRepository() -> LoginRepositoryType {
return LoginRepository(network: network, storage: storage)
}
}
struct RepositoryProvider {
let loginRepositoryProvider: LoginRepositoryProviderType
init() {
loginRepositoryProvider = LoginRepositoryProvider(network: Network(), storage: LoginStorage())
}
}
struct ServiceProvider {
let loginUseCaseProvider: LoginUseCaseProviderType
init(repositoryProvider: RepositoryProvider) {
self.loginUseCaseProvider = LoginUseCaseProvider(repository: repositoryProvider.loginRepositoryProvider.makeRepository())
}
}
let repositoryProvider = RepositoryProvider()
let serviceProvider = ServiceProvider(repositoryProvider: repositoryProvider)
let useCase = serviceProvider.loginUseCaseProvider.makeLoginUseCase()
let request = LoginUseCase.Request(username: "username", password: "password")
useCase.login(with: request) { (result) in
switch result {
case let .failure(error):
print(error)
case let .success(user):
print(user)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment