Code Monkey home page Code Monkey logo

dikit's Introduction

DIKit

Build Status

A statically typed dependency injector for Swift.

Overview

DIKit provides interfaces to express dependency graph. A code generator named dikitgen finds implementations of the interfaces, and generate codes which satisfies dependency graph.

The main parts of DIKit are injectable types and provider methods, and both of them are to declare dependencies of types.

Injectable types are types that conform to Injectable protocol.

public protocol Injectable {
    associatedtype Dependency
    init(dependency: Dependency)
}

A conformer of Injectable protocol must have associated type Dependency as a struct. You declare dependencies of the Injectable conformer as stored properties of Dependency type. For example, suppose we have ProfileViewController class, and its dependencies are User, APIClient and Database. Following example code illustrates how to declare dependencies by conforming Injectable protocol.

final class ProfileViewController: Injectable {
    struct Dependency {
        let user: User
        let apiClient: APIClient
        let database: Database
    }

    init(dependency: Dependency) {...}
}

Provider methods are methods of inheritor of Resolver protocol, which is a marker protocol for code generation.

public protocol Resolver {}

Provider methods declares that which non-injectable types can be instantiated automatically. In the example above, APIClient and Database are non-injectable type, but they can be provided in the same ways in most cases. In this situation, define provider methods for the types in an inheritor of Resolver protocol, so that instances of the types are provided automatically.

protocol AppResolver: Resolver {
    func provideAPIClient() -> APIClient
    func provideDatabase() -> Database
}

In short, we have following situation so far:

  • Dependencies of ProfileViewController are User, APIClient and Database.
  • Instances of APIClient and Database are provided automatically.
  • An instance of User must be provided manually to instantiate ProfileViewController.

dikitgen generates following code for the declarations:

extension AppResolver {
    func resolveAPIClient() -> APIClient {
        return provideAPIClient()
    }

    func resolveDatabase() -> Database {
        return provideDatabase()
    }

    func resolveViewController(user: User) -> ProfileViewController {
        let apiClient = resolveAPIClient()
        let database = resolveDatabase()
        return ProfileViewController(dependency: .init(user: User, apiClient: apiClient, database: Database))
    }
}

To use generated code, you have to implement a concrete type of AppResolver.

final class AppResolverImpl: AppResolver {
    let apiClient: APIClient = ...
    let database: Database = ...

    func provideAPIClient() {
        return apiClient
    }

    func provideDatabase() {
        return database
    }
}

Since AppResolver is a protocol, all implementations of provider methods are checked at compile time. If you would like to create mock version of AppResolver for unit testing, define another concrete type of AppResolver. It can be used the same as AppResolverImpl.

Now, you can instantiate ProfileViewController like below:

let appResolver = AppResolverImpl()
let user: User = ...
let viewController = appResolver.resolveViewController(user: user)

Installation

Install code generator dikitgen first.

mint install ishkawa/DIKit dikitgen

From Source

git clone https://github.com/ishkawa/DIKit.git
cd DIKit
make install

Then, integrate DIKit.framework to your project. There are some option to install DIKit.framework.

  • Manual: Clone this repository and add DIKit.xcodeproj to your project.
  • Carthage: Add a line github "ishkawa/DIKIt" to your Cartfile and run carthage update.

Optionally, insert shell script running dikitgen to early part of build phases.

if which dikitgen >/dev/null; then
  dikitgen ${SRCROOT}/YOUR_PROJECT > ${SRCROOT}/YOUR_PROJECT/AppResolver.generated.swift
else
  echo "warning: dikitgen not installed, download from https://github.com/ishkawa/DIKit"
fi

dikit's People

Contributors

ikesyo avatar ishkawa avatar mshibanami avatar nakiwo avatar takasek avatar yutailang0119 avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.