All Projects → orakaro → Pure Swift Dependency Injection

orakaro / Pure Swift Dependency Injection

Licence: mit
Dependency Injection in Pure Swift

Programming Languages

swift
15916 projects

Projects that are alternatives of or similar to Pure Swift Dependency Injection

Ios
A sample project demonstrating MVVM, RxSwift, Coordinator Pattern, Dependency Injection
Stars: ✭ 49 (-26.87%)
Mutual labels:  dependency-injection
Poodinis
A dependency injection framework for D with support for autowiring.
Stars: ✭ 57 (-14.93%)
Mutual labels:  dependency-injection
Lagom
📦 Autowiring dependency injection container for python 3
Stars: ✭ 61 (-8.96%)
Mutual labels:  dependency-injection
Android Mvvm Rxjava2 Dagger2
This repository contains a detailed sample application that uses MVVM as its presentation layer pattern. Essential dependencies are Dagger2 with Dagger-android, RxJava2 with RxAndroid, Room, Retrofit and Espresso.
Stars: ✭ 50 (-25.37%)
Mutual labels:  dependency-injection
Simplify
Simplify is a set of .NET libraries that provide infrastructure for your applications. DI and mocking friendly.
Stars: ✭ 52 (-22.39%)
Mutual labels:  dependency-injection
Danf
Danf is a Node.js full-stack isomorphic OOP framework allowing to code the same way on both client and server sides. It helps you to make deep architectures and handle asynchronous flows in order to help in producing scalable, maintainable, testable and performant applications.
Stars: ✭ 58 (-13.43%)
Mutual labels:  dependency-injection
Zenject Hero
Zenject 7 - Game example (WIP)
Stars: ✭ 44 (-34.33%)
Mutual labels:  dependency-injection
Daggraph
Dagger dependency graph generator for Android Developers
Stars: ✭ 1,140 (+1601.49%)
Mutual labels:  dependency-injection
Complex Redux Project Architecture
Redux architecture extended with a layer of services.
Stars: ✭ 53 (-20.9%)
Mutual labels:  dependency-injection
Rea Di
Dependency injection for React done right. Hierarchical injection on both component and service layer powered by injection-js (Angular DI framework) 🖖
Stars: ✭ 62 (-7.46%)
Mutual labels:  dependency-injection
Factory
Factory for object creation and dependency injection. Works with normal C# apps or under Unity3d
Stars: ✭ 50 (-25.37%)
Mutual labels:  dependency-injection
Aiodine
🧪 Async-first Python dependency injection library
Stars: ✭ 51 (-23.88%)
Mutual labels:  dependency-injection
Pioneer Console Boilerplate
Dependency injection, logging and configuration in a .NET Core console application.
Stars: ✭ 60 (-10.45%)
Mutual labels:  dependency-injection
Dijs
JavaScript dependency injection for Node and browser environments.
Stars: ✭ 49 (-26.87%)
Mutual labels:  dependency-injection
Singularity
A extremely fast ioc container for high performance applications
Stars: ✭ 63 (-5.97%)
Mutual labels:  dependency-injection
Vue.js With Asp.net Core Sample
This provides a sample code using vue.js running on ASP.NET Core
Stars: ✭ 44 (-34.33%)
Mutual labels:  dependency-injection
Macwire
Lightweight and Nonintrusive Scala Dependency Injection Library
Stars: ✭ 1,095 (+1534.33%)
Mutual labels:  dependency-injection
App
Reusable framework for micro services & command line tools
Stars: ✭ 66 (-1.49%)
Mutual labels:  dependency-injection
Typesafeconfig Guice
Allows Guice Injection of configuration values from Typesafe Config
Stars: ✭ 64 (-4.48%)
Mutual labels:  dependency-injection
Fx Guice
Google Guice integration for FXML-based JavaFX applications
Stars: ✭ 61 (-8.96%)
Mutual labels:  dependency-injection

You don't need (Swift) Dependency Injection Framework

There is Cake Design Pattern in Scala to do Dependency Injection (DI), and a minimal version called Minimal Cake Design Pattern.

We don't really need a framework to do DI in Swift. With pure Swift code only, I will introduce you how to use Minimal Cake Design Pattern to do DI at production and test code.

Every class need Interface and Implementation

With every class, I will create an Interface using protocol, which name started withUses..., and an Implementation using class which name started with MixIn....

Interface only declares what the protocol can do, and Implementation declares how.

protocol UserRepository {
    func findById(id: Int) -> User?
}

// Interface
protocol UsesUserRepository {
    var userRepository: UserRepository { get }
}
// Implementation
class MixInUserRepository: UserRepository {
    func findById(id: Int) -> User? {
        return User(id: id, name: "orakaro", role: "member")
    }
}

When instance of UserRepository is used by another class, for example UserService, I will use above Interface to declare a new pair protocol/extension, and of course another Interface and Implementation for UserService itself.

Sounds more complicated than it is. Let’s look at the code.

protocol UserService: UsesUserRepository {
    func promote(asigneeId: Int) -> User?
}
extension UserService {
    func promote(asigneeId: Int) -> User? {
        guard var asignee = userRepository.findById(id: asigneeId) else {return nil}
        asignee.role = "leader"
        return asignee
    }
}

// Interface
protocol UsesUserService {
    var userService: UserService { get }
}
// Implementation
class MixInUserService: UserService {
    let userRepository: UserRepository = MixInUserRepository()
}

What if UserService is used by another TeamService again? Well the same logic is applied, UsesUserService is used to declare a pair of protocol/extension, and there will be Interface/Implementation for the new service also.

protocol TeamService: UsesUserService {
    func buildTeam(leader: User) -> [User?]
}
extension TeamService {
    func buildTeam(leader: User) -> [User?] {
        return [userService.promote(asigneeId: leader.id)]
    }
}

// Interface
protocol UsesTeamServvice {
    var teamService: TeamService { get }
}
// Implementation
class MixInTeamService: TeamService {
    let userService: UserService = MixInUserService()
}

All this kind of wiring is statically typed. If we have a dependency declaration missing or something is misspelled then we get a compilation error. Furthermore implementation is immutable (declared as let).

Application use Implementation

For example our application using TeamService can be like this

let applicationLive = MixInTeamService()
let team = applicationLive.buildTeam(leader: User(id: 1, name: "orakaro", role: "member"))
print(team) // [Optional(User(id: 1, name: "orakaro", role: Optional("leader")))]

DI using Interface

At this time we already can inject a mock repository into UserService to test the promote method even without mocking framework. We are not merely creating mocks but the mocks we create are wired in as the declared dependencies wherever defined.

class MockUserRepository: UserRepository {
    func findById(id: Int) -> User? { return nil }
}
class UserServiceForTest: UserService {
    let userRepository: UserRepository = MockUserRepository()
}
let testService = UserServiceForTest()
print(testService.promote(asigneeId: 1)) // nil

The same way can be used to inject TeamService to test buildTeam method.

class TeamServiceForTest: TeamService {
    let userService: UserService = UserServiceForTest()
}
let applicationTest = TeamServiceForTest()
let testTeam = applicationTest.buildTeam(leader: User(id: 1, name: "orakaro", role: "member"))
print(testTeam) // [nil]

The big picture is now:

For more detail see playground in this repo.

Summing up

I found this solution to be a simple, clear way to structure Swift code and create the object graph. It uses only pure Swift protocol/extension, does not depend on any frameworks or libraries, and provides compile-time checking that everything is defined properly.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].