You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
2 moments happened recently that gave me inspiration.
I was refactoring my iOSBlanky project. During this refactor, I realized that a better design pattern when using Teller is to have your DataSourcenot contain any of the actual database/networking logic inside of it. The DataSource should just delegate to a true repository class.
Here is what a DataSource should look like with this delegation:
import Foundation
import RxSwift
import Teller
typealiasReposTellerRepository=TellerRepository<ReposDataSource>
// sourcery: InjectRegister = "ReposTellerRepository"
// sourcery: InjectCustom
extensionReposTellerRepository{}extensionDI{varreposTellerRepository:ReposTellerRepository{TellerRepository(dataSource:inject(.reposDataSource))}}classReposDataSourceRequirements:RepositoryRequirements{letgithubUsername:Stringvartag:RepositoryRequirements.Tag{"Repos for GitHub username: \(githubUsername)"}init(githubUsername:String){self.githubUsername = githubUsername
}}enumResposApiError:Error,LocalizedError{case usernameDoesNotExist(username:String)varerrorDescription:String?{
switch self{case.usernameDoesNotExist(let username):return"The GitHub username \(username) does not exist." // comment: "GitHub returned 404 which means user does not exist.")
}}}
// sourcery: InjectRegister = "ReposDataSource"
classReposDataSource:RepositoryDataSource{typealiasCache=[Repo]typealiasRequirements=ReposDataSourceRequirementstypealiasFetchResult=[Repo]typealiasFetchError=HttpRequestErrorfileprivateletreposRepository:ReposRepositoryinit(reposRepository:ReposRepository){self.reposRepository = reposRepository
}varmaxAgeOfCache:Period=Period(unit:3, component:.day)func fetchFreshCache(requirements:ReposDataSourceRequirements)->Single<FetchResponse<[Repo],FetchError>>{
reposRepository.getUserRepos(username: requirements.githubUsername)}func saveCache(_ fetchedData:[Repo], requirements:ReposDataSourceRequirements)throws{try reposRepository.replaceRepos(fetchedData, forUsername: requirements.githubUsername)}func observeCache(requirements:ReposDataSourceRequirements)->Observable<[Repo]>{
reposRepository.observeRepos(forUsername: requirements.githubUsername)}func isCacheEmpty(_ cache:[Repo], requirements:ReposDataSourceRequirements)->Bool{
cache.isEmpty
}}
When looking at this code, I see lots of boilerplate. The true logic is really just 5 lines of code - all of the code that delegates to the repository. All of the rest is just boilerplate.
Not only is it boilerplate, but introducing a TellerRepository has always caused confusion because I now have to work with ReposRepository and ReposTellerRepository.
I was looking at this very similar project recently. It's trying to solve the same problem as teller is.
When you look at the readme, they have taken advantage of this removing of boilerplate idea.
Now, note that this code above is Kotlin but you get the idea. It's building a repository by just delegation functions.
I was thinking about doing this idea recently but I decided not to because I thought to myself, "The current DataSource and Repository API design right now is very unit testable in the dev's app code". Well, check out my latest test I made for a DataSource:
import Foundation
import RxSwift
import XCTest
classReposDataSourceTests:UnitTest{vardataSource:ReposDataSource!varreposRepositoryMock:ReposRepositoryMock!vardisposeBag:DisposeBag!letdefaultRequirements=ReposDataSource.Requirements(githubUsername:"username")overridefunc setUp(){
super.setUp()
reposRepositoryMock =ReposRepositoryMock()
disposeBag =DisposeBag()
dataSource =ReposDataSource(reposRepository: reposRepositoryMock)}
// At this time, there is little to no logic in the datasource. It's just a wrapper around the repository. Therefore, we are not testing it.
}
Yup. DataSource tests are worthless. That means that the DataSource being it's very own class is also worthless.
The text was updated successfully, but these errors were encountered:
2 moments happened recently that gave me inspiration.
DataSource
not contain any of the actual database/networking logic inside of it. TheDataSource
should just delegate to a true repository class.Here is what a
DataSource
should look like with this delegation:When looking at this code, I see lots of boilerplate. The true logic is really just 5 lines of code - all of the code that delegates to the repository. All of the rest is just boilerplate.
Not only is it boilerplate, but introducing a
TellerRepository
has always caused confusion because I now have to work withReposRepository
andReposTellerRepository
.When you look at the readme, they have taken advantage of this removing of boilerplate idea.
Now, note that this code above is Kotlin but you get the idea. It's building a repository by just delegation functions.
I was thinking about doing this idea recently but I decided not to because I thought to myself, "The current
DataSource
andRepository
API design right now is very unit testable in the dev's app code". Well, check out my latest test I made for aDataSource
:Yup.
DataSource
tests are worthless. That means that theDataSource
being it's very own class is also worthless.The text was updated successfully, but these errors were encountered: