All Projects → depject → Depject

depject / Depject

Licence: mit
simplest dependency injection

Programming Languages

javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to Depject

RandomProxyRuby
Tiny Library for get random proxy (free).
Stars: ✭ 16 (-82.22%)
Mutual labels:  module, modules
LibPQ
Detach your M code from workbooks to reuse it! Import modules from local or web storage (unlimited number of sources)
Stars: ✭ 55 (-38.89%)
Mutual labels:  module, modules
shopyo
shopyo.readthedocs.org
Stars: ✭ 66 (-26.67%)
Mutual labels:  module, modules
OregonCore-Modules
Modules made for Oregoncore
Stars: ✭ 18 (-80%)
Mutual labels:  module, modules
Graphql Modules
Enterprise Grade Tooling For Your GraphQL Server
Stars: ✭ 962 (+968.89%)
Mutual labels:  modules, dependency-injection
StartupModules
Startup modules for ASP.NET Core.
Stars: ✭ 33 (-63.33%)
Mutual labels:  modules, dependency-injection
laravel-module-loader
THIS PACKAGE HAS BEEN DEPRECATED — A lightweight package to organize your code into contextual modules.
Stars: ✭ 76 (-15.56%)
Mutual labels:  module, modules
nuxt-modules
AX2's Nuxt modules
Stars: ✭ 30 (-66.67%)
Mutual labels:  module, modules
Resolve
Implements the node.js require.resolve() algorithm
Stars: ✭ 622 (+591.11%)
Mutual labels:  module, modules
Modclean
Remove unwanted files and directories from your node_modules folder
Stars: ✭ 309 (+243.33%)
Mutual labels:  module, modules
Android Clean Architecture
Showcasing a Clean Architecture approach from our Android applications framework!
Stars: ✭ 160 (+77.78%)
Mutual labels:  modules, dependency-injection
Html Sass Babel Webpack Boilerplate
Webpack 4 + Babel + ES6 + SASS + HTML Modules + Livereload
Stars: ✭ 35 (-61.11%)
Mutual labels:  module, modules
Registry
Components as records of functions for Haskell
Stars: ✭ 132 (+46.67%)
Mutual labels:  modules, dependency-injection
laravel-admin
Laravel Admin panel with theme , modules ,artisan commands and helper classess.Laravel admin boilerplate with theme and modules
Stars: ✭ 22 (-75.56%)
Mutual labels:  module, modules
Modulation
Modulation - explicit dependency management for Ruby
Stars: ✭ 306 (+240%)
Mutual labels:  module, dependency-injection
Jcnavigator
A decoupled navigator framework of jumping between modules or apps for iOS development.
Stars: ✭ 33 (-63.33%)
Mutual labels:  module, modules
Daggraph
Dagger dependency graph generator for Android Developers
Stars: ✭ 1,140 (+1166.67%)
Mutual labels:  module, dependency-injection
Price Tracker
Price Tracking Application - An experimental Kotlin Android project with complex android app requirements.
Stars: ✭ 80 (-11.11%)
Mutual labels:  dependency-injection
Godot Lang Support
A community-maintained list of Language Support Projects for Godot Engine.
Stars: ✭ 86 (-4.44%)
Mutual labels:  modules
Hub
Android 开发中通过接口获取实现类,可用于module之间的通信,通过注解解决module的依赖初始化问题,良好的多线程环境下的线程安全以及性能。a concise di library which can get implementation class for a interface easily in multiple module app , also avoid check null when want to invoke a implementation by interface.
Stars: ✭ 79 (-12.22%)
Mutual labels:  modules

depject

simplest dependency injection

Installation

$ npm install --save depject

philosophy

A module exposes features to be used by other modules, and may also depend on features provided by other modules. Any module system can do that. In the node module system, modules declare exactly which modules they depend on. That works well when the module does a very well defined task, that can be abstractly solved. In other words, it works well when the module solves a technical problem.

But it doesn't work so well when the module just represents an opinion. Developer tools seem to be dominated by technical problems, but user applications seem to be dominated by opinions. There are many different ways something could be implemented, no objectively optimal solution, and loads of pretty good ones.

The contemporary best practice is to embrace that, and create software that has strong opinions. That takes a strong leader to make decisions, compromises be dammed. I am building a p2p system, and have gone to considerable effort to create a decentralized protocol. But then, if we have a user interface with strong opinions, then that recentralizes development.

My strong opinion is to reject strong opinions. depject is a strategy to deopinionate software. It should be easy to change any particular opinion.

Another way to look at this, is the goal is to make pull-requests that merge easily. with node's module system, a dependant module must declare exactly which modules they depend on. That means, to add a feature, you need to add a new file implementing it, and also update files that use that.

To contrast, in depject if that feature is the same shape as one already existing, you only need to add that file. This means you can add merge two new features, with out a conflict.

patterns

first - use the first module that has an opinion about a thing.

Say we have a system with multiple types of messages. Each type has a renderer. We want to call all the renderers, and get the first one that knows how to handle that value.

map - get each module's opinion about a thing.

Say we have a menu that is actions which may be performed on a thing. We map the modules over that thing, and add all returned items to a menu.

reduce - compose each modules opinion about a thing into one opinion.

We might want to allow other modules to decorate the value given by our module

example

Using first

const combine = require('depject')

const cats = {
  gives: 'animalSound',
  create: () => (type) => {
    if(type !== 'cat') return
    return 'Meow'
  }
}

const dogs = {
  gives: 'animalSound',
  create: () => (type) => {
    if(type !== 'dog') return
    return 'Woof'
  }
}

const speak = {
  needs: {animalSound: 'first'},
  gives: 'speak',
  create: (api) => api.animalSound
}

const sockets = combine([cats, dogs, speak])

const mySpeak = sockets.speak[0]

console.log(mySpeak('dog'))
//Woof

Using map

const combine = require('depject')

const cats = {
  gives: 'name',
  create: () => () => 'Fluffy'
}

const dogs = {
  gives: 'name',
  create: () => () => 'Rex'
}

const animals = {
  needs: {name: 'map'},
  gives: 'animals',
  create: (api) => api.name
}

var sockets = combine([cats, dogs, animals])

var myAnimals = sockets.animals[0]

console.log(myAnimals())
//['Fluffy', 'Rex']

api

modules

Each module is an object which exposes {needs, gives, create} properties. needs and gives describe the module features that this module requires, and exports.

needs is a map of names to types. {<name> : "map"|"first"|"reduce"}

gives Is a string name of it's export, or if there are multiple exports an object where each key is a name {<name>: true,...}.

create Is a function that is called with an object connected to modules which provide the needs and must return a value which provides the gives or an object with keys that match what the module gives.

combine

Actually connect all the modules together! Takes an array of modules, resolves dependencies and injects them into each module.

combine([modules...])

This will return an array object of arrays of exports.

exporting more than one thing from a module

const cats = {
  gives: {name: true, animalSound: true},
  create: () => ({
    name: () => 'Fluffy',
    animalSound: (type) => {
      if(type !== 'cat') return
      return 'Meow'
    }
  })
}

requiring more than one thing into a module

const animalSounds = {
  needs: {name: 'map', animalSound: 'first'}
}

deeply nested modules

It's possible to pass deeply nested modules to combine eg:

const modules = {
  a: {
    b: {
      c: {
        gives: 'yes',
        create: function () {
          return function () {
            return true
          }
        }
      }
    },
    d: {
      e: {
        needs: {
          yes: 'first'
        },
        gives: 'no',
        create: function (api) {
          return function () {
            return !api.yes()
          }
        }
      }
    }
  }
}

const api = combine(modules)

design questions

Should there be a way to create a routed plugin? i.e. check a field and call a specific plugin directly?

How does this interact with interfaces provided remotely? i.e. muxrpc?

License

MIT © Dominic Tarr

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].