daniel created this task.
daniel claimed this task.
daniel added subscribers: Addshore, Izno, Glaisher, Ricordisamoa, RobLa-WMF, 
MZMcBride, Tgr, phuedx, GWicke, JeroenDeDauw, bd808, Aklapper, Spage, 
AndyRussG, daniel, JanZerebecki, Qgil.
daniel added projects: Wikidata, MediaWiki-RfCs, Patch-For-Review.

TASK DESCRIPTION
  In order to move MediaWiki towards the use of Dependency Injection (DI) as 
proposed in T384, it will be necessary to provide a //composition root// (aka 
application scope aka top level factory) that provides access to the top level 
services. This role should be taken by suitable //DI container//.
  
  During the discussion of T384 as well as the relevant 
[[https://www.mediawiki.org/wiki/Wikimedia_Developer_Summit_2016/Software_engineering|discussions
 during the 2016 developer summit]], a rough consensus emerged that we should 
move towards DI //if it can be done nicely and without too much disruption//. 
This RFC aims to clarify the implementation details of the heart of the DI 
mechanism: the central service locator.
  
  # we want to use service ”singletons” with narrow interfaces, and ”dumb” 
value objects for our domain model. For the storage layer, this means a 
[[https://en.wikipedia.org/wiki/Data_access_object|DAO]] approach instead of 
”smart” records.
  # we do not want to use 
[[http://symfony.com/blog/new-in-symfony-2-8-service-auto-wiring|auto-wiring]]. 
It's convenient for small systems, but confusing for large, complex systems 
like MediaWiki. We want to avoid magic, and do things explicitly.
  # we want our DI container to be configurable, so that extensions can define 
their own service. Extensions should also be able to replace or wrap existing 
services.
  # we do not want to use a 3rd party DI framework such as Pimple or PHP-DI. 
See below for the rationale.
  # we want services to be injected as constructor argument to avoid strong 
coupling. We do not want to follow the service locator //pattern//. (We just 
call our top level DI container the service locator, because the name is more 
descriptive).
  
  
  === Proposal ===
  
  This RFC proposes the implementation of a generic ServiceContainer class that 
instantiates services on demand based on a registry of callback functions. A 
top level instance of this ServiceContainer, namely MediaWikiServices, is used 
to access well known top level services. The top level services are initialized 
from a "wiring" file that defines a callback for creating each well known 
service.
  
  An implementation of such a ServiceContainer mechanism is up for review on 
gerrit: 
[[https://gerrit.wikimedia.org/r/#/c/264403/|I3c25c0ac17300d3dd13e1cf5100558a605eee15f]].
 Also see the follow-up for added functionality and examples of refactoring 
existing code to use DI.
  
  
  === Why not use a 3rd Party DI Framework ===
  
  One of the recurring discussion topics in this context is whether we should 
use a 3rd party DI framework.  A number of decent DI frameworks available for 
PHP, like 
[[http://symfony.com/doc/current/components/dependency_injection/introduction.html|Symfony
 DI]], [[http://php-di.org/|PHP-DI]], and the more light weight 
[[http://pimple.sensiolabs.org/|Pimple]]. So why not use them?
  
  There are several reasons for using our own, instead of relying on a 3rd 
party framework:
  
  * Overhead. Using a 3rd party library means overhead for maintaining the 
dependency. The overhead isn't huge, but it's clearly non-zero. It should only 
be done if the benefits are clear.
  * Frameowrk isolation. We should avoid multiple components (and extensions) 
depending on a 3rd party framework. Instead, we should at least provide a thin 
layer to isulate the framework we use from MediaWiki code, so we can easily 
change the framework later. So even if we end up using a 3rd party lib, we 
still need to write and maintain the wrapper code anyway.
  * The lib does too much. The basic functionality of the DI container is 
rather simple. Some of the available frameworks do way more than we need or 
want (auto-wiring, for instance). We would drag in weight, and would be open to 
new code using aspects of DI we don't want to use (auch as auto-wiring, or the 
framework's built-in configuration mechanism instead of MediaWiki's).
  * The lib does too little. If we use a 3rd party framework but end up 
implementing half of the features we need on top of it, it may not be woth the 
extra dependency. For example, at least during the migration period, we need a 
mechanism to replace existing services, and run cleanup when an existign 
service is replaces. Also, we need integration with MediaWiki's configuration 
mechanism. Pimple allows us to do both somehow, but doesn't really help with 
doing it. 
  * Performance. MediaWiki has pretty unique requirements for scalability and 
performance, in particular for startup time. For MW, the tradeoff point between 
speed and memory consumption leans a lot further towards using more memory than 
is the case for most other projects. Having control over these aspects of the 
implementation of the DI container is helpful.
  
  So, in essence, if we only save a few hundred lines of trivial code by using 
a 3rd party library, we probably shouldn't.

TASK DETAIL
  https://phabricator.wikimedia.org/T124792

EMAIL PREFERENCES
  https://phabricator.wikimedia.org/settings/panel/emailpreferences/

To: daniel
Cc: Qgil, JanZerebecki, daniel, AndyRussG, Spage, Aklapper, bd808, 
JeroenDeDauw, GWicke, phuedx, Tgr, MZMcBride, RobLa-WMF, Ricordisamoa, 
Glaisher, Izno, Addshore, Wikidata-bugs, aude, jayvdb, Mbch331, Jay8g, Ltrlg, 
Legoktm



_______________________________________________
Wikidata-bugs mailing list
Wikidata-bugs@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/wikidata-bugs

Reply via email to