Last active
March 11, 2017 13:11
-
-
Save vittoriom/3429bd2b342243416fc5 to your computer and use it in GitHub Desktop.
A wrap-up of the Swifty Service Locator implementation as described in http://vittoriomonaco.it/blog/swifty-service-locator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Since in this class we'll use other objects, we define a typealias at the beginning of the file that will have 2 functions: | |
// 1) It will provide an interface for service locators that want to locate dependencies for this object, type-safe, not more and not less | |
// 2) It will show in a readable way what dependencies this object needs | |
typealias ArticleInteractorServiceLocatorInterface = protocol<ArticleRepositoryLocator, ReachabilityLocator> | |
// Then we define a class implementing this protocol, that will get all the default implementations of the protocols it inherits from, for free | |
class ArticleInteractorServiceLocator: ArticleInteractorServiceLocatorInterface { | |
// We can just override the default implementation in this specific service locator! | |
func reachability() -> ReachabilityInterface { | |
return OfflineSimulator() | |
} | |
} | |
class ArticleInteractor { | |
// dependencies | |
let repository: ArticleRepositoryInterface // Always code against interfaces! | |
let reachability: ReachabilityInterface | |
init(serviceLocator: ArticleInteractorServiceLocatorInterface = ArticleInteractorServiceLocator()) { | |
self.repository = serviceLocator.articleRepository() // We don't know which implementation we'll get, we just care about the API | |
self.reachability = serviceLocator.reachability() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ArticleInteractorTests.swift | |
// As in the app case, we define our own implementation of the ArticleInteractorServiceLocatorInterface | |
class ArticleInteractorServiceLocatorTestImpl: ArticleInteractorServiceLocatorInterface { | |
lazy var fakeReachability = FakeReachability() | |
lazy var fakeArticleRepository = FakeArticleRepository() | |
func articleRepository() -> ArticleRepositoryInterface { | |
return fakeArticleRepository | |
} | |
func reachability() -> ReachabilityInterface { | |
return fakeReachability | |
} | |
} | |
// We use Quick & Nimble, but it doesn't matter except for the syntax | |
class ArticleInteractorTests: QuickSpec { | |
override func spec() { | |
describe("An article interactor") { | |
var sut: ArticleInteractor! | |
var serviceLocator: ArticleInteractorServiceLocatorTestImpl! | |
beforeEach { | |
serviceLocator = ArticleInteractorServiceLocatorTestImpl() | |
// We now use our own service locator | |
sut = ArticleInteractor(serviceLocator: serviceLocator) | |
} | |
context("when offline") { | |
beforeEach { | |
// We can operate on our fakes | |
serviceLocator.fakeReachability.isOffline = true | |
} | |
it("should do something") { | |
//test something | |
//... | |
} | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ArticleRepository: ArticleRepositoryInterface { | |
func articlesList() -> [Article] { | |
return [] | |
} | |
} | |
// In 95% of the cases, we'll always use this implementation when locating ArticlePersistenceInterfaces in the main app. For the tests, we'll provide a different implementation anyway. | |
// So, contextually with the definition of the main class conforming to the protocol, we also extend the locator to provide this implementation | |
extension ArticleRepositoryLocator { | |
func articleRepository() -> ArticleRepositoryInterface { | |
return ArticleRepository() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is a dependency we want to inject into one or more objects later | |
protocol ArticleRepositoryInterface { | |
func articlesList() -> [Article] | |
} | |
// Contextually with the definition of a dependency interface we also define a protocol that will locate objects conforming to this interface | |
protocol ArticleRepositoryLocator { | |
func articleRepository() -> ArticleRepositoryInterface | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class OfflineSimulator: ReachabilityInterface { | |
func isConnected() -> Bool { | |
return false | |
} | |
} | |
// We can't provide a second default implementation for the ReachabilityInterfaceLocator, which is good because this would be a developer error that is now catched by the compiler. Also, we don't want this implementation to be the default ;) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Reachability: ReachabilityInterface { | |
func isConnected() -> Bool { | |
return true | |
} | |
} | |
extension ReachabilityInterfaceLocator { | |
func reachability() -> ReachabilityInterface { | |
return Reachability() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
protocol ReachabilityInterface { | |
func isConnected() -> Bool | |
} | |
protocol ReachabilityLocator { | |
func reachability() -> ReachabilityInterface | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment