On 22/02/2013, at 3:10 AM, Adam Murdoch <[email protected]> wrote:

> Hi,
> 
> So we're starting to build out a graph of build items, with our source sets 
> and jvm binaries (and publications). At the moment, this is pretty basic, 
> where you can define some source sets and define some jvm binaries and attach 
> the source sets as inputs to the binaries. Or you can attach a component as 
> input to a publication.
> 
> There are a few different types of build items that we need to model:
> 
> 1. Something that already exists and does not need building. These things are 
> only consumed in the current project. You need to be able to define it and 
> configure some stuff about how to use it. For example: here is a java source 
> set and it includes java source from this directory and that directory.
> 
> 2. Something that is produced outside the project. Again, these things are 
> only consumed in the current project. You need to be able to define a 
> dependency on the thing and resolve it into something usable. For example: 
> give me a jvm binary for 'org:gradle:gradle-core:1.5+' so that I can use it 
> in my compile classpath, or give me the source set for project(':other') so I 
> can generate some aggregate javadoc from it.
> 
> 3. Something that is produced by the project. You need to be able to define 
> it and configure some stuff about how to build it. For example, please 
> produce a jvm binary into this classes directory, built from these input 
> source sets and targeting this jvm version.
> 
> 4. Something that is produced and consumed within the project. As above, 
> where the configuration that describes how to build it also implies how to 
> use it.
> 
> 5. Something that is a view over some other things. For example, a composite 
> or a filtered source set. These things are only consumed.
> 
> What's common here is that everything is consumable, but not everything is 
> buildable by the current build. So, we need to come up with some API patterns 
> for representing things that are only consumable and things that are both 
> buildable and consumable.
> 
> One option is to use read-only super types, and mutable subtypes, something 
> like (this is just to demonstrate the idea):
> 
> interface JavaSourceSet {
>      FileCollection getSource();
>      FileCollection getCompileClasspath();
> }
> 
> interface ConfigurableJavaSourceSet extends JavaSourceSet {
>     SourceDirectorySet getSource();
>     ConfigurableFileCollection getCompileClasspath();
> }
> 
> You would define and configure an implementation of 
> ConfigurableJavaSourceSet. ClassesDirectoryBinary would accept any 
> JavaSourceSet as input.
> 
> Another option is to use parallel types, and the mutable type can give you a 
> read-only view of itself:
> 
> interface JavaSourceSet {
>     FileCollection getSource();
>     FileCollection getCompileClasspath();
> }
> 
> interface ConfigurableJavaSourceSet {
>     SourceDirectorySet getSource();
>     ConfigurableFileCollection getCompileClasspath();
> 
>     JavaSourceSet toSourceSet();  // convert to usable view
> }
> 
> ClassesDirectoryBinary would accept any JavaSourceSet or anything that can be 
> converted to a JavaSourceSet.
> 
> Then there's the optional operation approach:
> 
> interface JavaSourceSet {
>     SourceDirectorySet getSource() // may return a read-only instance that 
> throws UnsupportedOperationException when you try to mutate it
>     ConfigurableFileCollection getCompileClasspath() // may return a 
> read-only instance
> }
> 
> 
> Thoughts? Preferences? Other options?

As much as I don't entirely love it, the mutable subtype idea is the most 
appealing to me because I think it's the simplest for a user POV and doesn't 
blow out the number of types. I think it pushes the complexity on the 
implementer of the type rather than the API user which seems appealing.

I don't like the parallel types approach as you end up having to duplicate 
everything and need more contextual awareness when gluing things together. Or, 
you end up with a ton of method overloads to handle either type.

The optional operation approach is fundamentally non user friendly to me. These 
kinds of weak contracts reduce the value of the API documentation.

-- 
Luke Daley
Principal Engineer, Gradleware 
http://gradleware.com


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply via email to