[19:06:35] nothing on the showcase live stream yet [19:07:09] adam hasn't hit the button yet [19:07:42] the broadcast button has been pushed [19:07:55] I can't see anything yet :-/ [19:07:58] let me know when you see yuri on the stream [19:08:04] I think there is usually a ~30 sec delay [19:08:17] oh there we go [19:08:20] thx [19:08:21] there he is [19:09:17] screenshare isn't coming across [19:09:24] ^ [19:09:30] we're not seeing it either [19:09:31] yurik: ^ [19:10:02] youtube stream is not working [19:10:07] the screen share [19:10:19] i think it's not working for the people in the hangout either? [19:10:25] k [19:10:55] moving to a different presenter now [19:11:53] :( hopefully yuri can figure it out and present at end [19:12:02] yeah I would like to see it [19:12:23] still seeing the office [19:12:27] me too [19:12:33] can you select the presenter? [19:12:36] please [19:12:37] dr0ptp4kt: ^ [19:12:48] dr0ptp4kt: can you select the screen of the presenter? [19:12:58] niedzielski: josh's screen is the presenter. what are you seeing? joakino cc [19:13:05] dr0ptp4kt: office [19:13:06] we are seeing the room [19:13:06] the office dr0ptp4kt [19:13:10] dr0ptp4kt: i just see the conference room :| [19:13:13] dr0ptp4kt: on youtube we only see the office but not ht epresentation [19:13:25] dr0ptp4kt: we see the hangout icons at the bottom too [19:13:31] done, hopefully [19:13:39] meeple27: no change [19:13:45] 30 second delay [19:13:57] now? [19:14:04] dr0ptp4kt: same [19:14:05] still no :/ [19:14:07] not for me [19:14:08] no [19:14:42] not workiiing [19:14:55] now? [19:14:59] actually, in 30 secs? [19:15:15] was it presenting yuri (at least his face?) [19:15:20] when he was speaking? [19:15:24] yes [19:15:36] until he tried to screenshare and it didn't work [19:15:40] (( [19:15:42] then it went back to the office [19:15:49] still at office [19:15:58] and stayed there, even when he went back to his webcam [19:16:05] nice office [19:16:11] yei, i closed a whole bunch of apps and it stoped showing [19:16:28] okay, i have a theory. [19:16:36] started showing [19:16:43] i'm going to mute the room audio and unmute his laptop [19:16:47] nevermind [19:16:54] yurik, it's working now? [19:16:54] still not showing for me [19:16:57] others? [19:17:02] nope [19:17:12] nope [19:17:13] yurik: are you seeing the slides? [19:17:20] dr0ptp4kt: how does hangout work?are you doing hangout from the room hangout or your personal hangout adam? [19:17:42] dr0ptp4kt, yes, but i'm viewing it via the presenter hangout [19:17:48] if you select the thumb of the laptop on the on-air hangout it should show it to us [19:19:07] dr0ptp4kt: we have audio [19:19:12] nice [19:19:16] there we go [19:19:18] dr0ptp4kt: \o/ [19:19:20] dr0ptp4kt: yea! [19:19:27] woot [19:19:56] yeah [19:19:57] works [19:20:03] "we were just building suspense" [19:20:24] participants bar is hidden for us btw [19:20:26] :) [19:20:28] when Josh was asking about it [19:20:34] it was already hidden [19:20:51] so don't freak out too much about that one on the stream ;) [19:23:23] everyone seeing trey's spreadsheet? [19:23:31] yes [19:23:36] dr0ptp4kt: yes [19:23:37] yup [19:23:38] ye [19:23:42] hooray [19:24:01] mhurd bgerstle coreyfloyd: looking super sharp! [19:24:06] will need to add order of operations for muting and unmuting to the steps table. eek [19:24:14] niedzielski: thanks! [19:24:24] and thank apple ;-) [19:26:16] dr0ptp4kt, after a reboot i think its working now, will need about 1-2 min to demo [19:26:52] yurik: ok. let's go to you next. do a 15 second description to lead in so video editing will be easier later [19:28:30] you should see yuri's screen in 30 seconds [19:28:33] guys able to see yurik's screen? [19:28:49] not yet [19:28:50] nope [19:28:54] yes [19:28:55] now we can [19:28:56] yes [19:28:56] yay! [19:28:59] yeaa [19:29:00] yay^2 [19:29:10] or ** 2 [19:30:23] or pow(yay, 2) [19:30:23] should see/hear next presenter in 30 seconds [19:30:59] working :) [19:31:02] working! [19:31:03] y [19:31:08] thx jhobs and niedzielski and joakino [19:31:58] who is doing dynamic graphs? [19:32:17] yurik: ^ are you doing dynamic graphs? [19:32:28] dr0ptp4kt, skip it [19:32:46] i was hoping to do two presentations, but its already too crazy for time [19:33:48] yurik: move it to the bottom, okay? [19:34:14] should see/hear next presenter in 30-ish [19:34:52] yes [19:34:55] yep [19:36:27] switched to replay [19:37:09] it's up on our screens [19:38:18] bearloga: that looked awesome - can you put the link to the app in the etherpad? [19:38:57] HaeB: aw, thanks! and sure :D [19:40:09] dbrant: cool shit dude! [19:40:52] dbrant: very cool! [19:41:05] dbrant: is it a java app? [19:41:07] dbrant: so when you compiling the version i can use on my dk2? :) [19:41:07] thx!! [19:41:20] working on it [19:41:36] yes [19:41:37] joakino: yep, it's basically an Android app. [19:41:46] 👍 [19:41:54] dbrant: really neat! do the planets and closer objects have their own models or are they just assumed to be spheres? [19:42:06] ebernhardson: as soon as I get one to test with! [19:42:11] dr0ptp4kt: we can hear you [19:42:14] should see next presention in 30-ish [19:42:15] we hear you dr0ptp4kt [19:42:16] we can hear and see [19:42:23] and see gergo's face [19:42:34] screen! [19:42:38] dbrant: awesome sauce(rs) [19:42:40] dr0ptp4kt: we see a picture of gergo [19:42:44] ye [19:42:49] dr0ptp4kt: screen is up! [19:43:05] niedzielski: each object can have its own mesh (i'm just using the same sphere for now). [19:43:15] who is doing "our ui library"? [19:43:16] niedzielski: and i think it supports bump maps [19:43:30] dbrant: i use mine too often lately, can't loan it out cross-continent :P [19:43:35] but super cool ap [19:44:53] next presentation in 30-ish [19:45:27] yes [19:45:31] yup [19:45:32] dr0ptp4kt: yep [19:45:37] yep [19:45:40] yep [19:46:06] dr0ptp4kt: it looks like everything works properly by default as long as the conference room (and other non-attendees) are muted [19:46:51] niedzielski: yeah, i think so, although gergo was using the room mic. but i guess in that case everyone was muted? [19:48:29] jdlrobson: you ready? [19:52:20] cool [19:52:25] yes can see [19:52:27] and hear [19:52:30] yay [19:52:30] ye [19:52:51] seeing robson's screen and hearing audio? [19:52:56] yes [19:53:19] yes [19:55:12] jdlrobson: neat! [19:55:52] attempting a tricky switching maneuver... [19:56:11] woo [19:56:20] screen 1 up [19:57:28] we're not seeing it either [19:57:51] ok screen 2 up [19:58:13] i'm just seeing a face [19:58:28] ok no [19:58:30] now [20:00:36] thanks everyone! [20:00:58] adios [20:01:52] I like the changes to the search interface a lot [21:00:18] #startmeeting RFC meeting [21:00:18] Meeting started Wed Oct 28 21:00:17 2015 UTC and is due to finish in 60 minutes. The chair is TimStarling. Information about MeetBot at http://wiki.debian.org/MeetBot. [21:00:18] Useful Commands: #action #agreed #help #info #idea #link #topic #startvote. [21:00:18] The meeting name has been set to 'rfc_meeting' [21:00:27] \o/ [21:00:41] o/ [21:00:51] \o [21:00:58] #topic RFC meeting | Wikimedia meetings channel | Please note: Channel is logged and publicly posted (DO NOT REMOVE THIS NOTE) | Logs: http://bots.wmflabs.org/~wm-bot/logs/%23wikimedia-office/ [21:01:22] so we're starting off with a quick meeting planning discussion [21:01:42] o/ [21:01:49] * aude waves [21:02:15] for the timing of next week's meeting, we'd like to keep it at 2pm SF time (PST). [21:02:19] the eventbus implementation is moving forward as we speak, so we'd like to discuss this sooner rather than later [21:02:50] one option we could consider would be tomorrow at the same time as today [21:03:04] gwicke: vaguely aware (since wikidata) is on the bugs and sounds interesting [21:03:17] the ArchCom agreed that T384 has priority in today's discussion (starting at the 10 minute mark), and we're presuming it'll take the bulk of the hour [21:03:32] this is https://phabricator.wikimedia.org/T114443, https://phabricator.wikimedia.org/T88459, https://phabricator.wikimedia.org/T116247 [21:03:40] but tomorrow is wikidata birthday party :) so probably not around tomorrow [21:03:40] ottomata: is that ok for you? [21:04:02] gwicke make the case that if we don't get around to discussing T114443 + companions, that we should have a followup meeting this week. [21:04:05] but can keep an eye on phabricator [21:04:07] can do this time tomorrow, sure, but we were hoping to get paravoid and/or _joe_ involved, and it is late for them [21:04:13] paravoid mentioned he has a meeting full day tomorrow [21:04:50] full day is hard [21:04:53] time is generally okay with me with some notice (as it's social time), but I can't make tomorrow for sure [21:05:13] ottomata: should we plan to have a T114443 meeting at a more Europe-friendly time, at the expense of SF and/or Australia participants? [21:05:27] <_joe_> I'd prefer friday if possible, time is ok for me too [21:05:31] I can do friday and I can do next week's RFC meeting as well [21:05:35] jzerebecki: would you want to discuss the Composer Streamlining RFC next week? we were thinking of scheduling it for the irc meeting (if we don't end up talking about EventBus in that slot) [21:05:38] i'd like to have ori too, as long as it doesn't expense him too much :) [21:05:40] ori: ? [21:05:49] wfm [21:05:57] earlier on friday then? [21:06:02] sure [21:06:08] this time wfm [21:06:16] oh, i can do this time friday too [21:06:21] I guess Tim might not be able to make Friday [21:06:22] I don't mind missing it, if you want to schedule it earlier, as long as you don't mind me missing it [21:06:24] so late! weekend! oh well :) [21:06:26] _joe_: ? [21:06:37] <_joe_> it's ok for me [21:06:38] oh friday is saturday for Tim, right [21:06:45] <_joe_> oh, right [21:06:49] yeah the only reason I would be working at 3am on a saturday is if the site is down for an hour or more [21:06:56] sunday is monday, though ;) [21:06:58] heh :> [21:07:04] TimStarling: there is some discussion about core vs extension for mw eventbus client, but i think that one can probably be figured out offline [21:07:11] aside from that its ok if you miss i think [21:07:42] Friday works for me [21:07:45] ok, so same time friday then? [21:07:46] alright, friday at what time? [21:08:00] T-7min+24h [21:08:03] _joe_ and paravoid are ok with this time, so that is fine with me [21:08:03] if we don't need to cater for Australia, then I'd propose earlyish [21:08:04] 21:00 UTC on Friday? [21:08:09] i can do earlier too [21:08:11] <_joe_> 9 PM UTC [21:08:24] 9 PM UTC wfm [21:08:41] +1 [21:08:47] anything but 17:00 UTC wfm too [21:08:48] DanielK_WMDE_: yes composer streamlining next week works for me [21:08:59] I love how a bunch of Europeans just said that 9pm/10pm/11pm their time is "early-ish" [21:09:00] robla: ---^ [21:09:12] okay, so lets schedule @ 9 PM UTC [21:09:14] ok, let's leave any further discussion on that for email/irc, and move on to Daniel's RFC now [21:09:21] RoanKattouw: hehe ;) [21:09:22] ok [21:09:44] RoanKattouw: on a friday no less :) [21:09:45] #topic Dependency Injection for MediaWiki core | Wikimedia meetings channel | Please note: Channel is logged and publicly posted (DO NOT REMOVE THIS NOTE) | Logs: http://bots.wmflabs.org/~wm-bot/logs/%23wikimedia-office/ (Meeting topic: RFC meeting) [21:09:51] Right! [21:09:52] that's going to be at the same time a bunch of SF folks are going to be having Halloween party stuff, so attendeance will be light then too [21:09:54] #link https://www.mediawiki.org/wiki/Requests_for_comment/Dependency_injection [21:10:11] there is a phab ticket but most of the interesting stuff is on the mw.org page [21:10:13] yay :) [21:10:16] oh we can do earlier! [21:10:20] should we say 19:00 UTC? [21:10:31] 9am SF time would be fine for me as well [21:10:39] ottomata: can you own figuring out the time? [21:10:42] i have standup then, but could skip [21:10:45] robla, yes [21:10:51] that's 4pm utc [21:10:55] I wrote this RFC because I hope we can move forward a bit with dependency injection in mediawiki [21:10:56] ok, dependency injection [21:10:57] it sounds like most of the people i know i want to attend are free on friday [21:11:01] i'll just figure out calendars now [21:11:07] everybody update your calendars! [21:11:12] ottomata: let's clear room for DanielK_WMDE_ [21:11:16] k, go ahead! [21:11:17] thanks all. [21:11:33] We made some good experiences with DI in wikibase, and I hope we can use the same approach in core too [21:12:16] My only knock on this is that constructor based injection is not as easy as setter based injection in my experience [21:12:43] setter based might be ok for legacy stuff like maintenance scripts [21:12:55] "easy" meaning that if a component needs 7 services to get it's job done that's a lot of constructor arguments [21:12:55] but constructor would be nicer, generally and think it would work [21:12:56] my hope for today is to get agreement, or at least useful comments, on the 9 points i propose at the top of the page [21:13:12] Ideally we should have an approach that allows for multiple types of injection [21:13:17] (Sorry I'm late) [21:13:18] bd808: then we would want factory... and 7 is a sign that maybe stuff needs splitting [21:13:23] Yeah that's kind of why I asked DanielK_WMDE_ (about half an hour ago, so he hasn't had a chance to do anything) to add examples of how DI would be used in the receiving classes [21:13:24] in particular, i hope i can get agreement to, or at least comments, to the patches i proposed on gerrit for a top level service locator [21:13:31] #link https://gerrit.wikimedia.org/r/#/c/245483/ [21:13:45] DanielK_WMDE_: our beloved sites stuff :) [21:14:03] but agree it's the right direction for the services [21:14:10] bd808: setter based injection means your constructor has to get defaults from somewhere... and that somewhere is usually global state [21:14:20] aude: yes, indeed :) [21:14:42] right now, we instantiate a site store for wikibase client and another for wikibase repo [21:14:46] My obvious question would be why are we adding our own custom DI container and service locator rather than just using a library [21:14:47] DanielK_WMDE_: no, it means that if you call a working function before injecting the dependencies things blow up [21:14:57] would be obviously better to have what daniel proposed to have one instance for mediawiki [21:15:03] "Right now this random piece of code calls User::newFromId(), what would it look like in a DI world? Where does it get a UserLookup object from?" (Presumably via a constructor param or something but I think it'd be helpful to have that written out as examples0 [21:15:23] I like this top-level service locator [21:15:23] bd808: then calling code needs to know all the setters it needs to call. much more tricky. but i'm not toally stuck on constructor based injection [21:15:33] i prefer it, but *any* type of injection is better than global state [21:15:35] parent5446, DanielK_WMDE_ Flow uses Pimple for DI. ebernhardson knows about it [21:15:36] RoanKattouw: i think it would be from a factory [21:15:46] TimStarling: \o/ [21:15:56] User::newFromId in a UserFactory or something [21:16:00] you know I strongly promoted the idea of a singleton instance manager, but I was shouted down [21:16:10] DanielK_WMDE_: a general point: it is always a little unconvincing when the power of an architectural pattern is demonstrated on code that the person proposing the pattern has written or has been intimately involved with writing [21:16:11] calling it a service locator makes it much cooler [21:16:20] AIUI that's what Pimple has too, a singleton instance manager [21:16:32] it'd be much more persuasive if you started with something other than the site manager [21:16:33] heh [21:16:33] parent5446: i find that such libraries tend to be bloated and inflecxible. and i'm not too keen on declaring service dependency using json or whatever. [21:16:34] DanielK_WMDE_: no different than constructor args IMO. Ideally things are all mostly magically handled in the system entry points, but for things like Parser it will be different of course [21:17:00] DanielK_WMDE_: I understand, but at the very least Pimple isn't that bad. It's a lot simpler than others [21:17:19] It doesn't use config files [21:17:26] http://pimple.sensiolabs.org/ [21:17:30] parent5446: but it's not on the table for discussion [21:17:39] I like the locator part too, but am less sure about the use of globals to access it, rather than explicitly passing it in [21:17:44] is https://www.mediawiki.org/wiki/Requests_for_comment/Dependency_injection#Registry_Bootstrap an example of what an extension would do? [21:17:45] ori: noted [21:17:53] I'm all for re-using libraries but I think in this case we'll want to embrace the invisibility of a library. Passing constructor arguments doesn't require a library. Code still has to create objects and pass them around, it's probably easier to maintain if that code doesn't have dependencies (tends to infect all usage so makes librisation and re-use harder) [21:17:53] and lives inside the code directly. [21:17:57] Item #2 in the list "Objects that need access to services can only be constructed via factories" -- why? [21:18:10] #action daniel to hack up a code experiemnt porting an api module or special page to constructor based injection using the service locator. [21:18:17] \o/ thanks [21:18:28] Agreed that having 7 parameters means you should take an options object, or abstract better , maybe with an an intermediary [21:18:40] DI seems more like a pattern than a library to me [21:18:40] Why exactly is it not on the table? [21:18:41] yay [21:18:49] Yeah TimStarling [21:19:05] bd808: so that there is no strong binding between the implementations, and they can be tested separately. if service X instantiates service Y internally, you cannot test X without Y. [21:19:14] (Though Flow does use a library for it, http://pimple.sensiolabs.org/ – though I'm somewhat puzzled about what it solves) [21:19:17] but you are injecting? [21:19:19] (also, you cannot replace Y for other reasons) [21:19:21] * bd808 got lost there [21:19:29] Pimple does some clever stuff that might be worth using. See container.php in Flow for how it's used [21:19:49] how is there tight coupling in an injected dependency that inhibit testing? [21:20:16] ultimately, injection means that you are parametrizing access to needed services [21:20:35] gwicke: the locator should be accessed directly if it's not possible to inject anything. that is, in static hook handlers or constructor callbacks defined by bootstrap code. on all other levels, services, not the locator, should be injected [21:20:51] Basically the $c passed to each callback is a magical thing that implements ArrayAccess so that using $c['foo'] causes the callback for instantiating foo to be called, and that allows you do define things like $c['bar'] = function ( $c ) { new Bar( $c['foo'] ) ; } without then explicitly declaring that Bar depends on Foo [21:21:05] Krinkle: ---^^ for what Pimple solves [21:21:17] the Parser is my classic example of the need for a service locator. YOu don't know what you will need until you are mid parse and you can't inject the whole world [21:21:26] DI woudl also make testing things easier by not having code break out of its context and use e.g. use a backend directly. E.g. simply pass Hash or EmptyBagOStuff in place of $wgMemc etc. [21:21:27] #action daniel to check out http://pimple.sensiolabs.org/ [21:21:38] .oO(is #action the correct syntax?) [21:21:39] DanielK_WMDE_: I would argue that both are viable options [21:21:52] So essentially Pimple encourages a GlobalRequestContext from which everything is drawn. [21:21:59] Pimple, or at least what we use of it, is ~300 LOC, see extensions/Flow/vendor/Pimple. Really all it is is that magical ArrayAccess thing and an interface [21:22:11] gwicke: passing the locator? that would mean the code that uses it depends on *all* services. [21:22:18] Krinkle: Yes, you call Config::get( 'blahcache' ) to get the blah cache [21:22:22] (parent5446: re: why not on the table -- because the current proposal is written up in full, contains details and examples, and has patches to go with it. This raises the bar for proposing alternatives -- it's not enough (and not polite) to simply sketch out another approach that could plausibly work; it's necessary to actually pinpoint some serious defect with the current proposal.) [21:22:34] So there's a global singleton that knows how to construct everything [21:22:43] Krinkle: yes. this works quite nicely, check out the wikibase test cases [21:22:43] DanielK_WMDE_: the locator can implement several interfaces, and code could define which of those interfaces it needs [21:22:51] (That's /not/ the same as a global RequestContext necessarily) [21:23:14] gwicke: the only difference then is whether it implements X, or returns an X from a method. [21:23:17] with typed accessors, this will be type-checked as well [21:23:27] RoanKattouw: Seems like that isn't mutually exclusive with DI, as long as you call get() in the consuer of a class, instead of in the class itself (e.g. not Bar:construct: $this->foo = get(foo) but new Bar(get(foo)). But then you'd probably just want to put that factory in the code where it belongs, not all in one central place. [21:24:04] RoanKattouw: the service locator is basically a global singleton that knows how to construct everything. the important bit is to use it *only* as a last resort, and *alwys* inject narrow interfaces if you can. [21:24:06] I like this proposal, FWIW. +1 from me. [21:24:22] Sure, but it's meant to be used to facilitate DI. Look at the container.php file and you'll see a lot of stuff like $c['wiki_link_fixer'] = function( $c ) { return new Flow\Parsoid\Fixer\WikiLinkFixer($c['link_batch'] ); }; [21:24:29] Krinkle: there is no difference between a service locator object and a dependency injection container [21:24:38] the difference is in how you use them [21:24:40] gwicke: I think you are arguing for auto-wiring and in my personal past experience this becomes a nightmare. Spring auto-wiring of dependencies based on interface type becomes very ahrd to overload for a non-typical use case in Java land. [21:24:46] I don't feel like I have a clear idea of where the 'last resort' / 'inject narrow interfaces if you can' line is to be drawn [21:24:51] DanielK_WMDE_: there is an ergonomic trade-off there; being explicit gives you flexibility, but can also get very verbose [21:24:53] a DIC is never accessed outside initialization code [21:24:58] ori: Simply having a written proposal that looks nice and is comprehensive is not an excuse to ignore alternatives. The RFC has *one* sentence concerning third party implementations, and that is the intro sentence. My flaw with this RFC is that I do not see any conclusive argument against using a third party library, and as such my stance that we should use an external library rather than waste effort on maintaining our own is [21:24:58] still valid. [21:25:09] #info Krinkle: there is no difference between a service locator object and a dependency injection container; the difference is in how you use them [21:25:34] bd808: i agree, auto-wiring please! [21:25:41] tgr: I agree in theory, but I think a container requires much higher decline to avoid tight coupling. Something I don't expect "us at large" to uphold. [21:25:47] I want *no* auto-wiring [21:25:57] not sure what auto-wiring is [21:26:01] brion: only access the service locator in static context. never in an object. [21:26:12] I mean explicitly passing in an object implementing a set of factory interfaces [21:26:13] the container deciding what implemention of an interface to inject [21:26:19] we have a lot of legacy code, you can't change everything at once [21:26:27] brion: if it's an object, ask for a narrow interface in the constructor. [21:26:28] ori: the problem with not using a dependency injection container (it is not entirely clear to me whether the current proposal says that) is that changes become very cumbersome [21:26:28] decline * discipline [21:26:46] I think that's part of the reason why we don't have much DI-style code, it's hard to know where to start [21:27:04] with a top-level service locator you at least have a migration path [21:27:25] ori: object A creates B which creates C which creates D, you need a new service in D, you need to go through and update the whole chain [21:27:25] TimStarling: with top-level, you mean in global scope? [21:27:36] in new code, it should presumably never be used in an object [21:27:52] in old code, there will be more uses for it [21:28:13] TimStarling: that's the idea, yes. one dirty trick i have used for migration is to access the locator in the construcor of classes that should have the respective service injected "really soon now". works great as an intermediate step [21:28:20] I agree with TimStarling, primarily because I've done it before, i.e., making a global-level service locator and slowly migrating more and more of the codebase into it. [21:28:22] TimStarling: the typical migration path is optional injection parameters which default to calling the service location [21:28:23] so our traditional code tends to be factory-driven; Foo::newFoo() gives you the appropriate implementation subclass, if subclasses are appropriate. The service locator just looks like a big global factory to me. [21:28:27] gwicke: yes, global as in class static [21:28:31] then at some point you make them non-optional [21:29:03] is the service locator specifically key to this proposal, or is the idea of narrowing interfaces the key? [21:29:19] brion: it is in most respects. The power of it comes from removing all the other factories and centralizing the configuration [21:29:38] bd808: *nod* common config methods can be very useful yes [21:29:49] especially if overriding default implementations things... [21:29:53] leaving the "normal" code as objects that expect injection and don't know how to live without it [21:29:56] tgr: good points [21:30:24] this is how things get decoupled enough to allow testing via mocks and stubs [21:30:44] tgr, DanielK_WMDE_ : how would we transition MediaWiki's global objects to DI? [21:30:51] how do we introduce injection parameters to existing classes? [21:30:56] brion: injecting narrow interfaces into constructors is the goal (well, the ultimate goal is to avoid strong coupling). the service locator is a tool to achieve that, a tool that provides a usable migration path [21:31:11] DanielK_WMDE_: I gotta run now, but when you look at Pimple, perhaps you can also write up a short blurb about what the salient differences between Pimple and your proposal are? [21:31:37] Normally I would ask you to describe that here and now, but you've been aware of its existence for like 10 minutes so that's not fair [21:31:56] brion: if the classes are instantiated directly all over the place, you can only introduce opotional injection. if the constructor is called only in a few places, we should add a required parameter [21:31:59] Yeah, so the reason we want to split UserLookup from User is so that User doesn't hardcode where it gets Config and Database from? [21:32:05] as an example; Revision knows how to create User objects via an id or text lookup from rev_user_text/rev_user values [21:32:09] RoanKattouw: will do [21:32:10] Krinkle: Exactly [21:32:19] would we need to introduce a UserLookupService parameter to Revision constructors/factories? [21:32:27] or would that come from a common place? [21:32:28] brion: ideally, yes [21:32:45] yes (factory/service to hand out users) [21:32:46] But then how do you access UserLookup, and how does it get access to Config and Database :) I imagine UserLookup will not be static but rather a (mostly) singleton object. [21:32:52] spagewmf: which global objects? most of them could be member variables in the service locator. it would pass them into the constructors of the service objects it creates., [21:32:53] do we need separate RevisionLookupService and UserLookupService, or just a WikiService that knows all the things in a wiki? [21:32:58] DanielK_WMDE_: just to be clear, https://www.mediawiki.org/wiki/Requests_for_comment/Dependency_injection#Proposal_Summary is proposed as an end goal, not a migration path (ie. not something we should start doing right now), right? [21:33:23] brion: one per object/concern in my perfect world [21:33:38] brion: Revision is smart record, which makes it hard to introduce DI. DI favors services and dumb objects. [21:33:39] generally one per entity table in the backing database [21:33:51] #action DanielK_WMDE_ to write up a short blurb about what the salient differences between Pimple and his proposal are [21:33:58] smart models should die [21:34:03] :) [21:34:06] I guess this also ties in with the idea of separating API/DB handling from consuming code so that all database interaction is exclusively in the Lookup service. but that suggests Lookup is both read and write. [21:34:14] they should have a data access object of some type [21:34:20] brion: Revision can probably not be fully ported to DI, it would be replaced by RevisionRecord and the services RevisionLookup, and RevisionUpdater or something. [21:34:30] ^was going to say what Krinkle said. It's the beginning of moving to a more ORM-like pattern for DB access [21:34:53] (with the option to later change the access layer from SQL to HTTP for example) [21:34:59] so that would leave us with RevisionLookupService, RevisionRecord, UserLookupService, UserRecord -- and instead of $rev->getUser() you call $userLookupService->userFromRevision( $rev ) ? [21:35:03] tgr: the service locator is not just a migration tool. but choosing the locator approach makes migration earlier. [21:35:05] err, easier [21:35:13] DanielK_WMDE_: ah, OK, so DI-aware code would replace $wgUser with MediaWikiServices->getInstance()->GetUserLookup() ? [21:35:39] I prefer the https://en.wikipedia.org/wiki/Data_access_object pattern for get/store services [21:35:49] well, $wgUser would probably be something you get from the session singleton service [21:35:55] Krinkle: in my experience, there should be different interfacesy for read and write, but they can often should be implemented by the same concrete class. [21:35:59] or ..... a user id? that you then hand to the user lookup service? [21:36:02] DanielK_WMDE_: sure. What I mean is, do you think that "The service locator should never be passed as a parameter" is realistic to start doing right now? [21:36:34] DanielK_WMDE_: Right, so it's not unrelated to the earlier proposals of Value/Service objects or whatever we call them. [21:36:44] I'm assuming accessing it as a global singleton also counts as passing around [21:36:44] spagewmf: yes, and push that up the stack as far as possible, until no non-static code ever accesses MediaWikiServices [21:37:03] bd808: yes, +1 to DAO [21:37:09] tgr: +1 [21:37:10] i guess we'd need an abstract UserIdentifier or something that covers both id and name/ip lookups [21:37:24] brion: pretty much, yea [21:37:35] ok that all makes some kind of sense *and* gives a migration path :D [21:37:38] interesting [21:37:43] \o/ [21:37:56] brion: you can have a DOA with multiple getter methods too: userForId(, userForName(), ... [21:37:58] you may be selling me on this :D [21:38:21] Krinkle: no, it kind of goes hand in hand. DI and smart records don't really mix (unless you plan it carefully from the beginning) [21:38:25] bd808: yeah i just want to avoid lots of if($rev->user_id) { ... } :D [21:38:37] Krinkle: *no, it's not unrelated. [21:38:54] * brion apologizes for introducing the Revision smart record ;) [21:39:08] DanielK_WMDE_: Yeah, so when we split an object into Record and Lookup (or Value and Manager etc.) we might as well do that at the same time, kind of forced to anyway. [21:39:13] brion: that'S allright, you were young and needed the money ;) [21:39:17] brion: it was better than what came before [21:39:18] DanielK_WMDE_: when you said "most of them (global objects) could be member variables in the service locator", isn't that exactly the kitchen sink / request context you are arguing against? [21:39:21] lol [21:39:26] * DanielK_WMDE_ apologizes for introducing the Content smart record [21:39:33] :) [21:39:56] I don't regret any refactoring I did, the second refactor is always easier than the first [21:40:04] +1 [21:40:14] gwicke: yes. that's why the locator should never be passed as a parameter to anything. because it drags in half the world. [21:40:20] gwicke: You have a point, but the difference is that objects will be given their dependencies to them from the injection container, rather than getting the dependencies themselves using $wgUser [21:40:30] (or similar global) [21:40:44] Also what DankielK_WMDE_ said [21:41:16] One area recently cleaned up a lot (and still in progress) is object cache. [21:41:22] I'd like to volunteer to integrate that with this. [21:41:26] so related question: would we deprecate the current RequestContext stuff or just sorta leave it around for now [21:41:26] well, if the locator is accessed via some static context (global effectively), then it becomes a parameter that's hard to control [21:41:33] The apps are much less complex than MW, but Wikimania Scholarships and IEG Grant REview are both completely based on DI with the wiring being done in the router that dispatches requests based on URL [21:41:38] It's a few days/weeks away from becoming a composer library. [21:41:44] Krinkle: but it has nasty global state that messes with unit testing. we ran into issues with that recently. [21:42:26] to me, passing in such a locator explicitly would be preferrable over accessing it as a global, as an explicit parameter can be overridden for tests [21:42:31] Krinkle: a cache factory you can get from the service locator would be better. [21:43:00] so how does the migration path look in detail? say for User accessing the user table [21:43:03] that sounds like a case where having distinct DI containers can be useful...? [21:43:04] DanielK_WMDE_, brion: thx, the fog lifts a bit :-) We tell extension developers not to use these global objects and instead call getContext() in outputPage and in hooks. Will that change in this new world? [21:43:07] doing the same with a global is a lot trickier [21:43:23] gwicke: if you have control over the parameters, require a service, not the locator. if you do not have control over the parameters, access the global. [21:43:31] 1. create UserManager which has all the DB access, delegate in User via global service locator access [21:43:48] 2. go through all callers, have them access UserManager directly [21:43:51] spagewmf: i think we'll need/want some clear example code to demonstrate proper usage [21:43:57] 3. recurse for callers of callers [21:44:03] 4. drop UserManager from User [21:44:06] tgr: User is, again, a smart record... hard to migrate, you would need to inject a UserLookup into the constructor [21:44:07] DanielK_WMDE_: sure, I'm just saying that it might be very verbose to pass each service separately down a long call chain [21:44:08] we'd want to use the giant getContext() less [21:44:08] something like that? [21:44:52] gwicke: if you end up doing that, something is wrong with your code. if you need many services, you are probably doing too much, or something evil, like instantiating another service. [21:44:53] Right now, Context is pretty much a global service locator in and of itself, so using getContext() is the equivalent of injecting the service container, which we want to avoid. [21:45:13] yeah, ObjectCache might be a better candicate as it has no problem with "smart" record separation as much, right? [21:45:16] DanielK_WMDE_: so how do you ensure everything that creates User has a UserLookup at hand? also, do you want in the long term for User to have access to UserLookup? [21:45:16] candidate* [21:45:18] gwicke: i was surprised how the problem of passsing around services just vanisches when you follow the approach of "never instantiate a service yourself" [21:45:26] that seems the wrong direction [21:45:35] parent5446: I think there are things we can migrate out of Context once there is somewhere else to put them [21:45:44] DanielK_WMDE_: I'm not talking about instantiating, only about getting access to a service [21:45:44] Another one is Stats (RequestContext::getStats) [21:45:55] And MediaWikiLogger. [21:45:55] it is a tiny bit better than new globals but not the desired end goal [21:46:00] Krinkle: yes, migrating an all-static class is much easier. you just leave the static stuff as a sub. [21:46:02] bd808: Yeah agreed. [21:46:16] in node land, we routinely use a request context object as a service locator [21:46:21] Although I'll admit the one thing that is sometimes missing from a generic service locator is the type hinting [21:46:23] re: smart records vs data access objects -- it may make sense to a) deprecate the old Revision, Title, User, etc ; b) convert them internally to implement via using the global lookup + DAO internally, with the same interface for back-compat; c) some day kill the back-compat interfaces ;) [21:46:26] #action daniel to look into refactoring an all-static class like ObjectCache, Interwiki, or Linker as an example [21:46:50] oh yeah those'll be easier [21:47:17] parent5446: large frameworks typically offer IDE plugins for that [21:47:19] Krinkle: logging and profiling are two of the rare things where injection *might* not be what you want, because you need them everywhere. [21:47:26] brion: Yeah, instead of moving stuff out of Revision and keeping Revision as half-deprecated, deprecate entirely into RevisionRow and RevisionManager or something like that. Easier to spot use by checking for class. [21:47:36] nice [21:47:40] DanielK_WMDE_: For logging that ship already sailed. [21:47:48] I imagine singletons generally will be moved into the service locator [21:47:50] ok it's a big commitment but i'm getting more excited about this idea now [21:47:51] tgr: Ah really? Does PhpStorm have something? Because it'd be really nice to have suggestions again for services rather than having to put a docblock with the type. [21:48:01] definitely feels like it can be done piecemeal [21:48:12] *reads up* [21:48:26] brion: i already have some RFCs up for that, actually :) https://phabricator.wikimedia.org/T114394 specifically, and also part of https://phabricator.wikimedia.org/T107595 [21:48:48] parent5446: not for MediaWiki but eg. for Symfony there is a plugin to read the DIC config files and show proper type hints [21:48:52] Krinkle: i'm working on that for https://phabricator.wikimedia.org/T107595 [21:48:54] so RequestContext::getMain() will become a deprecated wrapper for MediaWikiServices::getInstance()->getContext() [21:49:14] DanielK_WMDE_: in a way, you are putting less faith into interfaces implemented by a factory object, and compensate by passing in services individually [21:49:15] tgr: Ah OK. Thanks for the heads up. I had no idea. Definitely something we'd want to work on for MediaWiki if at all possible. [21:49:29] TimStarling: indeed [21:50:35] but there will be less need to actually get a RequestContext [21:50:36] gwicke: passing factories is useful sometimes, but should be avoided if possible. basically, if all information needed for instantiating the thing is already there when constructing your object, then create the thing and inject it, not the factory [21:50:38] parent5446: also PhpStorm has some sort of feature to customize type hinting by running PHP code provided by the framework for that purpose, never looked at it closely though [21:50:56] gwicke: a factory is a partially applied constructor, basically. you pass it so someone else can fill in the blanks. [21:51:10] it can also just return singletons [21:51:19] which makes it a locator [21:51:32] DanielK_WMDE_: when you get to a point of wanting to build objects from a description, look at ncludes/libs/ObjectFactory.php. It should do most anything that you would need [21:51:34] The key difference is that generally a constructor is not considered to be a part of the class's interface, so by using a factory, you tie the constructor to the factory and provide an explicit interface for generating objects. [21:51:46] gwicke: it can, but then passing it is pointless. [21:51:51] if you define one interface for each service you need, you get the same minimal interfaces as passing in each service instance separately [21:51:59] parent5446: http://confluence.jetbrains.com/display/PhpStorm/PhpStorm+Advanced+Metadata [21:52:14] tgr: Thanks! [21:52:33] gwicke: yes. but you then can't re-use the implementations separately from each other [21:52:36] ok, let's start wrapping up [21:52:41] DanielK_WMDE_: can your RFC mention replacement for getContext()->getFoo in extension code (which in turn replaced direct $wgFoo access)? [21:52:51] DanielK_WMDE_: you still can [21:53:26] I know we have some differing opinions on the details [21:53:34] #action mention replacement for getContext()->getFoo in extension code (which in turn replaced direct $wgFoo access) [21:53:39] Time check! [21:53:43] the question is just whether you request the instance outside & pass it in, or pass in the container implementing the service access interfaces needed & let the code inside call it [21:53:59] #info bd808 does not agree with "Objects that need access to services can only be constructed via factories" [21:54:08] gwicke: sometimes you want to pass factories, yes. you never want to pass *the* locator [21:54:12] ok, wrapup time... [21:54:13] we have some action items for changes to the RFC, so I suppose that means we will consider approving it after those changes are made [21:54:49] If in the mean time i could get some reviews on my proposed changes on gerrit... :) [21:54:58] \o/ [21:55:03] DanielK_WMDE_: yeah, it would be *a* locator, as all that's required are the specific service access interfaces [21:55:12] I think this is one of the class of RfCs where the hard part will really just be finding resources to drive implementation and adoption [21:55:20] gwicke: i'd then call it a registry or factory, to avoid confusion [21:55:28] but then it's just about the name [21:55:46] DanielK_WMDE_: i'll add myself to them and add some comments shortly [21:55:51] well, adding some reviewers might be a good start [21:56:07] bd808: i'm happy if i can follow it when working on core, and can point to it if people don't like how i do things :) [21:56:07] DanielK_WMDE_: it's hard to find terms that aren't very overloaded in this area [21:56:20] TimStarling: heh! [21:56:31] DanielK_WMDE_: OK. I'd like to chat before next wednesday about a more concrete approach for objectcache. It can be orthogonal to this RFC if need be, as a play ground. It is currently being refactored by Aaron and me and I'd like to take your views into account. Perhaps "right" in one go, but if anything a first attempt. [21:57:23] I think there is pretty broad agreement that accessing a global locator / registry / kitchen sink is a transition technology [21:57:24] so we have an implementor group consisting of DanielK_WMDE_ and Krinkle [21:57:31] anyone else volunteering to be part of it? [21:57:38] It's hard, really hard, not to overload a factory container, gwicke. [21:58:21] DanielK_WMDE_: one thing I would like to see improved in the proposal is differentiation between end goal and migration path [21:58:23] TimStarling: I'll wade into it too, at least to make comments and some provisional tweaks [21:58:37] thanks brion [21:58:49] * brion is all excited about objects! [21:58:59] ie what are the rules we should start following as soon as the rfc is approved vs. those we will be able to follow a year from now maybe after a lot of refactpriong [21:59:06] *refactoring* [21:59:18] Krinkle: cool, let's talk about that! at the same time, i will be looking at refactoring Interwiki, as a first step regarding https://phabricator.wikimedia.org/T113034 [21:59:42] so there will be a public EventBus meeting at some time to be determined, probably Friday [21:59:51] that will be on IRC, right? [21:59:59] tgr: bigger changes will come as we migrate the smart record objects to DAO+dumb records, so more an dmore things can use the DI pattern directly [22:00:04] tgr: well, there is a lot of "should" in the rfc. new code should *really* follow the shoulds. old code should be moved in that direction. [22:00:11] tgr: more immediately, we'll probably only start migrating a few things directly [22:00:18] *nod* [22:00:24] then this time next week, we have penciled in https://phabricator.wikimedia.org/T105638 "Streamlining Composer usage" [22:00:26] brion: exactly [22:00:41] sweet :) [22:00:42] TimStarling: I personally wouldn't mind a hangout, actually, but I'll ask around & send out an announcement [22:00:55] DanielK_WMDE_: what I am getting at is, some of those shoulds cannot be followed by new code without refactoring old code [22:01:11] will that become the responsibility of people submitting new code? [22:01:15] #action DanielK_WMDE_ mention existing related implementations (Pimple , includes/libs/ObjectFactory.php , IEG, Wikibase?) in RFC [22:01:24] TimStarling: ottomata booked something on Friday for 11:15am PDT [22:01:33] ok, thanks everyone [22:01:34] tgr: ah that brings to mind -- code reviewers should become familiar with new patterns :D [22:01:38] we'll have to plan [22:01:44] #endmeeting [22:01:44] Meeting ended Wed Oct 28 22:01:44 2015 UTC. Information about MeetBot at http://wiki.debian.org/MeetBot . (v 0.1.4) [22:01:44] Minutes: https://tools.wmflabs.org/meetbot/wikimedia-office/2015/wikimedia-office.2015-10-28-21.00.html [22:01:44] Minutes (text): https://tools.wmflabs.org/meetbot/wikimedia-office/2015/wikimedia-office.2015-10-28-21.00.txt [22:01:44] Minutes (wiki): https://tools.wmflabs.org/meetbot/wikimedia-office/2015/wikimedia-office.2015-10-28-21.00.wiki [22:01:45] Log: https://tools.wmflabs.org/meetbot/wikimedia-office/2015/wikimedia-office.2015-10-28-21.00.log.html [22:01:53] whee [22:02:06] robla: yeah, just saw that as well [22:04:48] robla, ottomata : I gave the EventBus event in GCal a description, tweak away [22:04:56] thanks for runnign the meeting, TimStarling! [22:05:13] DanielK_WMDE_: thanks for writing the RFC! [22:05:46] indeed, thanks for pushing DI forward, it's very much needed [22:05:50] forward to shiny future of injection.... or something [22:06:12] i'm very happy to see so much support for this [22:06:21] i expected a lot more reluctance [22:06:28] so, let's do this :) [22:06:31] DanielK_WMDE_: thanks for making $me->dude->doHeadAsplode() :-) It's another new world for extension writers [22:06:44] hehe... [22:06:58] spagewmf: wait until I let you write extensions in JavaScript. ;-p [22:07:01] random tangent .. whenever i hear 'injection' ... syringes come to mind .. childhood trauma. :) [22:07:21] spagewmf: https://www.youtube.com/watch?v=mrb2Oc6naDI [22:07:45] * gwicke refrains from making bad puns on addiction [22:08:23] we should just call it dependency insertion instead. oh, wait, that's not better... [22:08:34] subbu: it sounds like a future where the authorities inject you with false memories and then introduce you to your kids [22:08:55] :) [22:09:33] we should just call it Lambda The Ultimate [22:09:58] pass all the things, with strong types [22:21:09] gwicke: sounds like Haskell ;) [22:22:11] yeah: Haskell, ML, Rust, Scala, ...