Jump to content

Requests for comment/Dependency injection: Difference between revisions

From mediawiki.org
Content deleted Content added
 
Initial overview
Line 1: Line 1:
{{ambox
#REDIRECT [[Requests for comment/Dependency injection/2014]]
| type = warning
| text = This proposal was rewritten in October 2015. For the older proposal, see [[Requests for comment/Dependency injection/2014]]
}}
{{RFC
| created = 2015-10-01
| authors = [[User:Daniel Kinzler (WMDE)|Daniel Kinzler (WMDE)]] ([[User talk:Daniel Kinzler (WMDE)|talk]])
| bug = T384
| status = in draft
}}
This RFC proposes pest practices for establishing the [[w:Dependency injection|dependency injection]] pattern in MediaWiki ''without'' relying on a DI framework.

== Proposal Summary ==

This RFC proposes the following to be adopted as best practice:
# Services should be represented by narrow interfaces.
# When a service (or application logic) needs access to another a service, it asks for it in the constructor. This is the actual ''injection of dependencies''.
# Injecting/passing around factories, registries, and especially "kitchen sinks" like RequestContent should be avoided.
# Services are constructed by other services (factories and registries being special types of service). At the top of this chain of registries/factories there is the ''top level registry'' aka ''application scope''.
# Objects that need access to services can only be constructed via factories (not directly using the new operator).
# Registries use constructor callbacks (aka factory functions) to instantiate services.
# Access to global default instances ("singletons") should be restricted to static entry points (e.g. hook handlers and constructor callbacks).
# Bootstrap code should avoid instantiating services.
# Mutable global state should escpecially be avoided.

== Rationale ==
[[w:Dependency injection|Dependency injection]] (DI) is a design pattern that can facilitate unit testing, loose coupling and architecture description.<ref>http://martinfowler.com/articles/injection.html</ref><ref>http://blog.crazybob.org/2007/06/introduction-to-guice-video-redux.html</ref><ref>http://code.tutsplus.com/tutorials/dependency-injection-in-php--net-28146</ref> Although it's more useful in some languages than in others, it is a well-established pattern, and there is a solid ecosystem of DI libraries for PHP.<ref>https://packagist.org/packages/symfony/dependency-injection</ref><ref>http://phptrends.com/category/73</ref>

Mediawiki doesn't have a dedicated DI mechanism, though adding one [[#Previous Discussions|has been discussed]].

Adding simple DI support to core would be a first step towards consistent, concise use of this pattern. Since we'll probably need at least a few iterations and use cases to get it right, this first step could be a kind of "[[#Proposed methodology|internal API beta feature]]".

== Previous Discussions ==
Using DI in Mediawiki has been considered before. Here are some earlier conversations about it:
* [[Talk:Requests_for_comment/Dependency_injection/2014|Previous incarnation of this RFC]]
* [[Architecture meetings/Wikimania_2013#Changes|Discussion of changes to Architecture guidelines at Wikimania 2013]]
* [[Talk:Architecture guidelines#Use_dependency_injection_for_external_resources|Section on DI for external resources in Talk:Architecture guidelines]]
* [[Architecture Summit_2014/TitleValue#Goal|Discussion of TitleValue at the Arcitecture Summit 2014]]
* The [[Requests for_comment/TitleValue|TitleValue RFC]] and the [[#Talk:Requests for_comment/TitleValue#ServiceRegistry_singleton_33334|ServiceRegistry section on that RFC's Talk page]]

== References ==
<references />

Revision as of 15:29, 1 October 2015

Request for comment (RFC)
Dependency injection
Component General
Creation date
Author(s) Daniel Kinzler (WMDE) (talk)
Document status in draft
See Phabricator.

This RFC proposes pest practices for establishing the dependency injection pattern in MediaWiki without relying on a DI framework.

Proposal Summary

This RFC proposes the following to be adopted as best practice:

  1. Services should be represented by narrow interfaces.
  2. When a service (or application logic) needs access to another a service, it asks for it in the constructor. This is the actual injection of dependencies.
  3. Injecting/passing around factories, registries, and especially "kitchen sinks" like RequestContent should be avoided.
  4. Services are constructed by other services (factories and registries being special types of service). At the top of this chain of registries/factories there is the top level registry aka application scope.
  5. Objects that need access to services can only be constructed via factories (not directly using the new operator).
  6. Registries use constructor callbacks (aka factory functions) to instantiate services.
  7. Access to global default instances ("singletons") should be restricted to static entry points (e.g. hook handlers and constructor callbacks).
  8. Bootstrap code should avoid instantiating services.
  9. Mutable global state should escpecially be avoided.

Rationale

Dependency injection (DI) is a design pattern that can facilitate unit testing, loose coupling and architecture description.[1][2][3] Although it's more useful in some languages than in others, it is a well-established pattern, and there is a solid ecosystem of DI libraries for PHP.[4][5]

Mediawiki doesn't have a dedicated DI mechanism, though adding one has been discussed.

Adding simple DI support to core would be a first step towards consistent, concise use of this pattern. Since we'll probably need at least a few iterations and use cases to get it right, this first step could be a kind of "internal API beta feature".

Previous Discussions

Using DI in Mediawiki has been considered before. Here are some earlier conversations about it:

References