On 10 May 2014, at 11:52 am, Luke Daley <[email protected]> wrote:

> 
> 
> On 10 May 2014 at 7:40:14 am, Adam Murdoch ([email protected]) 
> wrote:
> 
>> 
>> On 9 May 2014, at 3:06 pm, Luke Daley <[email protected]> wrote:
>> 
>>> Hi,
>>> 
>>> I’m trying to bust the new plugin portal code out of core-impl and parts 
>>> out of core. I’m unsure about how to do this and avoid a circular 
>>> dependency.
>>> 
>>> There are 3 parts:
>>> 
>>> 1. core - integrates plugin resolvers into the build lifecycle, provides 
>>> dependency management services needed for plugin resolution
>>> 2. general plugin infrastructure for plugin resolvers to use (e.g. 
>>> interfaces to implement)
>>> 3. specific plugin portal plugin resolver implementation
>>> 
>>> My plan was to create a new ‘plugin-portal’ project for #3, and put the 
>>> interfaces and support (#2) in ‘core’. Thus, circular dependency.
>>> 
>>> The way that core-impl solves this is through some service loader 
>>> indirection. I can see how we could do a similar thing in this case. The 
>>> ‘plugin-portal’ project could advertise a PluginResolver implementation 
>>> that ‘core’ loads at runtime. Therefore, ‘core’ would have no compile 
>>> dependency on ‘plugin-portal’. Is this the way to go?
>>> 
>>> One question then is how to order the plugin resolvers in core. If it just 
>>> loads them arbitrarily off the classpath, what orders them? One option 
>>> would be for the plugin portal resolver to be called out especially (e.g. 
>>> it’s loaded via some kind of marker interface that lives in core).
>>> 
>>> Any ideas?
>> 
>> 
>> The relationship between core and the dependency management stuff is 
>> actually a little different to this. You could think of the dependency 
>> management and plugin resolution capabilities being structured this way:
>> 
>> 1. Public DSL and APIs through which you use the capability - defining 
>> repositories, dependencies, plugins, whatever.
>> 2. These are backed by some internal services that do the work. These 
>> internal services are decoupled from the public types. They use their own 
>> request and response types. The services are injected into the public stuff.
>> 3. The internal services have an implementation that provides some 
>> resolution algorithm.
>> 4. The algorithm is backed by some internal resolver API that represent some 
>> source for the things being resolved.
>> 5. There are a bunch of resolver implementations.
>> 
>> #2 is the contract between the DSL and the implementation, so this needs to 
>> be visible to everything. Ideally, #3 - #5 would not be visible from #1, and 
>> #1 not visible from #3 - #5.
>> 
>> Currently, for dependency management, here’s what we do:
>> 
>> - #1 lives in core, because the dependency management DSL has references to 
>> core (eg via Configuration -> Buildable -> Task -> Project -> 
>> ConfigurationContainer and back).
>> - #2 lives in core, because the internal service API is not entirely 
>> decoupled from the DSL.
>> - #3, #4, and #5 live together in core-impl.
>> 
>> We use discovery to find #3 from #1, but not to find the resolver 
>> implementations - #3 takes care of that.
>> 
>> I would do something similar for the plugins: move the algorithm, the 
>> resolver API and resolver implementations out of core, inject some entry 
>> point service into core, and let the implementation of the entry point 
>> service take care of everything else.
>> 
>> The resolution algorithm and the resolver implementations don’t necessarily 
>> need to be separated from each other. I would keep them together for now.
> 
> So, in concrete terms, …
> 
> 1. Leave the PluginResolver (and dependencies) interface in core
> 
> 2. Create plugin-resolution project that provides a single PluginResolver 
> implementation that core resolves via lookup
> 
>       - depends on core (PluginResolver etc.)
> 
>       - depends on coreImpl (for dependency resolution infrastructure) 
> 
> 
> 

Yeah, I think so. I think you’ll also need to extract an interface out of 
PluginResolverFactory and inject that instead of a PluginResolver.

> If so,
> 
> - How do I get at the dependency management infrastructure in 
> plugin-resolution? service lookup like in core?
> 

Yes.

> - Do I depend on the concrete types in coreImpl instead of core interfaces? 
> (e.g. DefaultDependencyFactory instead of DependencyFactory) in 
> plugin-resolution?
> 
> 

Interfaces, not implementations.

> - Do I create a PluginResolutionServices in core that plugin-resolution 
> provides the impl for (like DependencyManagementServices)? 
> 
> 

I don’t think you need to. Just make the factory available.


--
Adam Murdoch
Gradle Co-founder
http://www.gradle.org
VP of Engineering, Gradleware Inc. - Gradle Training, Support, Consulting
http://www.gradleware.com

Join us for Gradle Summit 2014, June 12th and 13th in Santa Clara, CA: 
http://www.gradlesummit.com

Reply via email to